js: Use new string formatting functions

This commit is contained in:
Linus Groh 2020-11-09 19:10:59 +00:00 committed by Andreas Kling
parent 626c17d284
commit 518481086b
Notes: sideshowbarker 2024-07-19 01:28:05 +09:00

View file

@ -25,6 +25,7 @@
*/ */
#include <AK/ByteBuffer.h> #include <AK/ByteBuffer.h>
#include <AK/Format.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <LibCore/ArgsParser.h> #include <LibCore/ArgsParser.h>
@ -161,10 +162,10 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects);
static void print_array(JS::Array& array, HashTable<JS::Object*>& seen_objects) static void print_array(JS::Array& array, HashTable<JS::Object*>& seen_objects)
{ {
bool first = true; bool first = true;
fputs("[ ", stdout); out("[ ");
for (auto it = array.indexed_properties().begin(false); it != array.indexed_properties().end(); ++it) { for (auto it = array.indexed_properties().begin(false); it != array.indexed_properties().end(); ++it) {
if (!first) if (!first)
fputs(", ", stdout); out(", ");
first = false; first = false;
auto value = it.value_and_attributes(&array).value; auto value = it.value_and_attributes(&array).value;
// The V8 repl doesn't throw an exception here, and instead just // The V8 repl doesn't throw an exception here, and instead just
@ -174,18 +175,18 @@ static void print_array(JS::Array& array, HashTable<JS::Object*>& seen_objects)
return; return;
print_value(value, seen_objects); print_value(value, seen_objects);
} }
fputs(" ]", stdout); out(" ]");
} }
static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_objects) static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_objects)
{ {
fputs("{ ", stdout); out("{{ ");
bool first = true; bool first = true;
for (auto& entry : object.indexed_properties()) { for (auto& entry : object.indexed_properties()) {
if (!first) if (!first)
fputs(", ", stdout); out(", ");
first = false; first = false;
printf("\"\033[33;1m%d\033[0m\": ", entry.index()); out("\"\033[33;1m{}\033[0m\": ", entry.index());
auto value = entry.value_and_attributes(&object).value; auto value = entry.value_and_attributes(&object).value;
// The V8 repl doesn't throw an exception here, and instead just // The V8 repl doesn't throw an exception here, and instead just
// prints 'undefined'. We may choose to replicate that behavior in // prints 'undefined'. We may choose to replicate that behavior in
@ -196,51 +197,51 @@ static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_object
} }
if (!object.indexed_properties().is_empty() && object.shape().property_count()) if (!object.indexed_properties().is_empty() && object.shape().property_count())
fputs(", ", stdout); out(", ");
size_t index = 0; size_t index = 0;
for (auto& it : object.shape().property_table_ordered()) { for (auto& it : object.shape().property_table_ordered()) {
if (it.key.is_string()) { if (it.key.is_string()) {
printf("\"\033[33;1m%s\033[0m\": ", it.key.to_display_string().characters()); out("\"\033[33;1m{}\033[0m\": ", it.key.to_display_string());
} else { } else {
printf("\033[33;1m%s\033[0m: ", it.key.to_display_string().characters()); out("\033[33;1m{}\033[0m: ", it.key.to_display_string());
} }
print_value(object.get_direct(it.value.offset), seen_objects); print_value(object.get_direct(it.value.offset), seen_objects);
if (index != object.shape().property_count() - 1) if (index != object.shape().property_count() - 1)
fputs(", ", stdout); out(", ");
++index; ++index;
} }
fputs(" }", stdout); out(" }}");
} }
static void print_function(const JS::Object& function, HashTable<JS::Object*>&) static void print_function(const JS::Object& function, HashTable<JS::Object*>&)
{ {
printf("\033[34;1m[%s]\033[0m", function.class_name()); out("\033[34;1m[{}]\033[0m", function.class_name());
} }
static void print_date(const JS::Object& date, HashTable<JS::Object*>&) static void print_date(const JS::Object& date, HashTable<JS::Object*>&)
{ {
printf("\033[34;1mDate %s\033[0m", static_cast<const JS::Date&>(date).string().characters()); out("\033[34;1mDate {}\033[0m", static_cast<const JS::Date&>(date).string());
} }
static void print_error(const JS::Object& object, HashTable<JS::Object*>&) static void print_error(const JS::Object& object, HashTable<JS::Object*>&)
{ {
auto& error = static_cast<const JS::Error&>(object); auto& error = static_cast<const JS::Error&>(object);
printf("\033[34;1m[%s]\033[0m", error.name().characters()); out("\033[34;1m[{}]\033[0m", error.name());
if (!error.message().is_empty()) if (!error.message().is_empty())
printf(": %s", error.message().characters()); out(": {}", error.message());
} }
static void print_regexp(const JS::Object& object, HashTable<JS::Object*>&) static void print_regexp(const JS::Object& object, HashTable<JS::Object*>&)
{ {
auto& regexp = static_cast<const JS::RegExpObject&>(object); auto& regexp = static_cast<const JS::RegExpObject&>(object);
printf("\033[34;1m/%s/%s\033[0m", regexp.content().characters(), regexp.flags().characters()); out("\033[34;1m/{}/{}\033[0m", regexp.content(), regexp.flags());
} }
static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects) static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
{ {
if (value.is_empty()) { if (value.is_empty()) {
printf("\033[34;1m<empty>\033[0m"); out("\033[34;1m<empty>\033[0m");
return; return;
} }
@ -248,7 +249,7 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
if (seen_objects.contains(&value.as_object())) { if (seen_objects.contains(&value.as_object())) {
// FIXME: Maybe we should only do this for circular references, // FIXME: Maybe we should only do this for circular references,
// not for all reoccurring objects. // not for all reoccurring objects.
printf("<already printed Object %p>", &value.as_object()); out("<already printed Object {}>", &value.as_object());
return; return;
} }
seen_objects.set(&value.as_object()); seen_objects.set(&value.as_object());
@ -271,30 +272,30 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
} }
if (value.is_string()) if (value.is_string())
printf("\033[32;1m"); out("\033[32;1m");
else if (value.is_number() || value.is_bigint()) else if (value.is_number() || value.is_bigint())
printf("\033[35;1m"); out("\033[35;1m");
else if (value.is_boolean()) else if (value.is_boolean())
printf("\033[33;1m"); out("\033[33;1m");
else if (value.is_null()) else if (value.is_null())
printf("\033[33;1m"); out("\033[33;1m");
else if (value.is_undefined()) else if (value.is_undefined())
printf("\033[34;1m"); out("\033[34;1m");
if (value.is_string()) if (value.is_string())
putchar('"'); out("\"");
else if (value.is_negative_zero()) else if (value.is_negative_zero())
putchar('-'); out("-");
printf("%s", value.to_string_without_side_effects().characters()); out("{}", value.to_string_without_side_effects());
if (value.is_string()) if (value.is_string())
putchar('"'); out("\"");
printf("\033[0m"); out("\033[0m");
} }
static void print(JS::Value value) static void print(JS::Value value)
{ {
HashTable<JS::Object*> seen_objects; HashTable<JS::Object*> seen_objects;
print_value(value, seen_objects); print_value(value, seen_objects);
putchar('\n'); outln();
} }
static bool file_has_shebang(AK::ByteBuffer file_contents) static bool file_has_shebang(AK::ByteBuffer file_contents)
@ -352,14 +353,14 @@ static bool parse_and_run(JS::Interpreter& interpreter, const StringView& source
auto error = parser.errors()[0]; auto error = parser.errors()[0];
auto hint = error.source_location_hint(source); auto hint = error.source_location_hint(source);
if (!hint.is_empty()) if (!hint.is_empty())
printf("%s\n", hint.characters()); outln("{}", hint);
vm->throw_exception<JS::SyntaxError>(interpreter.global_object(), error.to_string()); vm->throw_exception<JS::SyntaxError>(interpreter.global_object(), error.to_string());
} else { } else {
interpreter.run(interpreter.global_object(), *program); interpreter.run(interpreter.global_object(), *program);
} }
if (vm->exception()) { if (vm->exception()) {
printf("Uncaught exception: "); out("Uncaught exception: ");
print(vm->exception()->value()); print(vm->exception()->value());
auto trace = vm->exception()->trace(); auto trace = vm->exception()->trace();
if (trace.size() > 1) { if (trace.size() > 1) {
@ -433,11 +434,11 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::exit_interpreter)
JS_DEFINE_NATIVE_FUNCTION(ReplObject::repl_help) JS_DEFINE_NATIVE_FUNCTION(ReplObject::repl_help)
{ {
printf("REPL commands:\n"); outln("REPL commands:");
printf(" exit(code): exit the REPL with specified code. Defaults to 0.\n"); outln(" exit(code): exit the REPL with specified code. Defaults to 0.");
printf(" help(): display this menu\n"); outln(" help(): display this menu");
printf(" load(files): accepts file names as params to load into running session. For example load(\"js/1.js\", \"js/2.js\", \"js/3.js\")\n"); outln(" load(files): accepts file names as params to load into running session. For example load(\"js/1.js\", \"js/2.js\", \"js/3.js\")");
printf(" save(file): accepts a file name, writes REPL input history to a file. For example: save(\"foo.txt\")\n"); outln(" save(file): accepts a file name, writes REPL input history to a file. For example: save(\"foo.txt\")");
return JS::js_undefined(); return JS::js_undefined();
} }
@ -450,7 +451,8 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::load_file)
String file_name = file.as_string().string(); String file_name = file.as_string().string();
auto js_file = Core::File::construct(file_name); auto js_file = Core::File::construct(file_name);
if (!js_file->open(Core::IODevice::ReadOnly)) { if (!js_file->open(Core::IODevice::ReadOnly)) {
fprintf(stderr, "Failed to open %s: %s\n", file_name.characters(), js_file->error_string()); warnln("Failed to open {}: {}", file_name, js_file->error_string());
continue;
} }
auto file_contents = js_file->read_all(); auto file_contents = js_file->read_all();
@ -491,49 +493,43 @@ public:
virtual JS::Value log() override virtual JS::Value log() override
{ {
puts(vm().join_arguments().characters()); outln("{}", vm().join_arguments());
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value info() override virtual JS::Value info() override
{ {
printf("(i) %s\n", vm().join_arguments().characters()); outln("(i) {}", vm().join_arguments());
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value debug() override virtual JS::Value debug() override
{ {
printf("\033[36;1m"); outln("\033[36;1m{}\033[0m", vm().join_arguments());
puts(vm().join_arguments().characters());
printf("\033[0m");
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value warn() override virtual JS::Value warn() override
{ {
printf("\033[33;1m"); outln("\033[33;1m{}\033[0m", vm().join_arguments());
puts(vm().join_arguments().characters());
printf("\033[0m");
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value error() override virtual JS::Value error() override
{ {
printf("\033[31;1m"); outln("\033[31;1m{}\033[0m", vm().join_arguments());
puts(vm().join_arguments().characters());
printf("\033[0m");
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value clear() override virtual JS::Value clear() override
{ {
printf("\033[3J\033[H\033[2J"); out("\033[3J\033[H\033[2J");
fflush(stdout); fflush(stdout);
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value trace() override virtual JS::Value trace() override
{ {
puts(vm().join_arguments().characters()); outln("{}", vm().join_arguments());
auto trace = get_trace(); auto trace = get_trace();
for (auto& function_name : trace) { for (auto& function_name : trace) {
if (function_name.is_empty()) if (function_name.is_empty())
function_name = "<anonymous>"; function_name = "<anonymous>";
printf(" -> %s\n", function_name.characters()); outln(" -> {}", function_name);
} }
return JS::js_undefined(); return JS::js_undefined();
} }
@ -541,19 +537,16 @@ public:
{ {
auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default"; auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default";
auto counter_value = m_console.counter_increment(label); auto counter_value = m_console.counter_increment(label);
printf("%s: %u\n", label.characters(), counter_value); outln("{}: {}", label, counter_value);
return JS::js_undefined(); return JS::js_undefined();
} }
virtual JS::Value count_reset() override virtual JS::Value count_reset() override
{ {
auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default"; auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default";
if (m_console.counter_reset(label)) { if (m_console.counter_reset(label))
printf("%s: 0\n", label.characters()); outln("{}: 0", label);
} else { else
printf("\033[33;1m"); outln("\033[33;1m\"{}\" doesn't have a count\033[0m", label);
printf("\"%s\" doesn't have a count\n", label.characters());
printf("\033[0m");
}
return JS::js_undefined(); return JS::js_undefined();
} }
}; };
@ -797,7 +790,7 @@ int main(int argc, char** argv)
auto file = Core::File::construct(script_path); auto file = Core::File::construct(script_path);
if (!file->open(Core::IODevice::ReadOnly)) { if (!file->open(Core::IODevice::ReadOnly)) {
fprintf(stderr, "Failed to open %s: %s\n", script_path, file->error_string()); warnln("Failed to open {}: {}", script_path, file->error_string());
return 1; return 1;
} }
auto file_contents = file->read_all(); auto file_contents = file->read_all();