diff --git a/Userland/js.cpp b/Userland/js.cpp index 9170c7526e..849ebf0580 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -161,10 +162,10 @@ static void print_value(JS::Value value, HashTable& seen_objects); static void print_array(JS::Array& array, HashTable& seen_objects) { bool first = true; - fputs("[ ", stdout); + out("[ "); for (auto it = array.indexed_properties().begin(false); it != array.indexed_properties().end(); ++it) { if (!first) - fputs(", ", stdout); + out(", "); first = false; auto value = it.value_and_attributes(&array).value; // The V8 repl doesn't throw an exception here, and instead just @@ -174,18 +175,18 @@ static void print_array(JS::Array& array, HashTable& seen_objects) return; print_value(value, seen_objects); } - fputs(" ]", stdout); + out(" ]"); } static void print_object(JS::Object& object, HashTable& seen_objects) { - fputs("{ ", stdout); + out("{{ "); bool first = true; for (auto& entry : object.indexed_properties()) { if (!first) - fputs(", ", stdout); + out(", "); 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; // The V8 repl doesn't throw an exception here, and instead just // prints 'undefined'. We may choose to replicate that behavior in @@ -196,51 +197,51 @@ static void print_object(JS::Object& object, HashTable& seen_object } if (!object.indexed_properties().is_empty() && object.shape().property_count()) - fputs(", ", stdout); + out(", "); size_t index = 0; for (auto& it : object.shape().property_table_ordered()) { 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 { - 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); if (index != object.shape().property_count() - 1) - fputs(", ", stdout); + out(", "); ++index; } - fputs(" }", stdout); + out(" }}"); } static void print_function(const JS::Object& function, HashTable&) { - 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&) { - printf("\033[34;1mDate %s\033[0m", static_cast(date).string().characters()); + out("\033[34;1mDate {}\033[0m", static_cast(date).string()); } static void print_error(const JS::Object& object, HashTable&) { auto& error = static_cast(object); - printf("\033[34;1m[%s]\033[0m", error.name().characters()); + out("\033[34;1m[{}]\033[0m", error.name()); if (!error.message().is_empty()) - printf(": %s", error.message().characters()); + out(": {}", error.message()); } static void print_regexp(const JS::Object& object, HashTable&) { auto& regexp = static_cast(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& seen_objects) { if (value.is_empty()) { - printf("\033[34;1m\033[0m"); + out("\033[34;1m\033[0m"); return; } @@ -248,7 +249,7 @@ static void print_value(JS::Value value, HashTable& seen_objects) if (seen_objects.contains(&value.as_object())) { // FIXME: Maybe we should only do this for circular references, // not for all reoccurring objects. - printf("", &value.as_object()); + out("", &value.as_object()); return; } seen_objects.set(&value.as_object()); @@ -271,30 +272,30 @@ static void print_value(JS::Value value, HashTable& seen_objects) } if (value.is_string()) - printf("\033[32;1m"); + out("\033[32;1m"); else if (value.is_number() || value.is_bigint()) - printf("\033[35;1m"); + out("\033[35;1m"); else if (value.is_boolean()) - printf("\033[33;1m"); + out("\033[33;1m"); else if (value.is_null()) - printf("\033[33;1m"); + out("\033[33;1m"); else if (value.is_undefined()) - printf("\033[34;1m"); + out("\033[34;1m"); if (value.is_string()) - putchar('"'); + out("\""); else if (value.is_negative_zero()) - putchar('-'); - printf("%s", value.to_string_without_side_effects().characters()); + out("-"); + out("{}", value.to_string_without_side_effects()); if (value.is_string()) - putchar('"'); - printf("\033[0m"); + out("\""); + out("\033[0m"); } static void print(JS::Value value) { HashTable seen_objects; print_value(value, seen_objects); - putchar('\n'); + outln(); } 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 hint = error.source_location_hint(source); if (!hint.is_empty()) - printf("%s\n", hint.characters()); + outln("{}", hint); vm->throw_exception(interpreter.global_object(), error.to_string()); } else { interpreter.run(interpreter.global_object(), *program); } if (vm->exception()) { - printf("Uncaught exception: "); + out("Uncaught exception: "); print(vm->exception()->value()); auto trace = vm->exception()->trace(); if (trace.size() > 1) { @@ -433,11 +434,11 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::exit_interpreter) JS_DEFINE_NATIVE_FUNCTION(ReplObject::repl_help) { - printf("REPL commands:\n"); - printf(" exit(code): exit the REPL with specified code. Defaults to 0.\n"); - printf(" help(): display this menu\n"); - 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"); - printf(" save(file): accepts a file name, writes REPL input history to a file. For example: save(\"foo.txt\")\n"); + outln("REPL commands:"); + outln(" exit(code): exit the REPL with specified code. Defaults to 0."); + outln(" help(): display this menu"); + 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\")"); + outln(" save(file): accepts a file name, writes REPL input history to a file. For example: save(\"foo.txt\")"); return JS::js_undefined(); } @@ -450,7 +451,8 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::load_file) String file_name = file.as_string().string(); auto js_file = Core::File::construct(file_name); 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(); @@ -491,49 +493,43 @@ public: virtual JS::Value log() override { - puts(vm().join_arguments().characters()); + outln("{}", vm().join_arguments()); return JS::js_undefined(); } virtual JS::Value info() override { - printf("(i) %s\n", vm().join_arguments().characters()); + outln("(i) {}", vm().join_arguments()); return JS::js_undefined(); } virtual JS::Value debug() override { - printf("\033[36;1m"); - puts(vm().join_arguments().characters()); - printf("\033[0m"); + outln("\033[36;1m{}\033[0m", vm().join_arguments()); return JS::js_undefined(); } virtual JS::Value warn() override { - printf("\033[33;1m"); - puts(vm().join_arguments().characters()); - printf("\033[0m"); + outln("\033[33;1m{}\033[0m", vm().join_arguments()); return JS::js_undefined(); } virtual JS::Value error() override { - printf("\033[31;1m"); - puts(vm().join_arguments().characters()); - printf("\033[0m"); + outln("\033[31;1m{}\033[0m", vm().join_arguments()); return JS::js_undefined(); } virtual JS::Value clear() override { - printf("\033[3J\033[H\033[2J"); + out("\033[3J\033[H\033[2J"); fflush(stdout); return JS::js_undefined(); } virtual JS::Value trace() override { - puts(vm().join_arguments().characters()); + outln("{}", vm().join_arguments()); auto trace = get_trace(); for (auto& function_name : trace) { if (function_name.is_empty()) function_name = ""; - printf(" -> %s\n", function_name.characters()); + outln(" -> {}", function_name); } return JS::js_undefined(); } @@ -541,19 +537,16 @@ public: { auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default"; auto counter_value = m_console.counter_increment(label); - printf("%s: %u\n", label.characters(), counter_value); + 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"; - if (m_console.counter_reset(label)) { - printf("%s: 0\n", label.characters()); - } else { - printf("\033[33;1m"); - printf("\"%s\" doesn't have a count\n", label.characters()); - printf("\033[0m"); - } + if (m_console.counter_reset(label)) + outln("{}: 0", label); + else + outln("\033[33;1m\"{}\" doesn't have a count\033[0m", label); return JS::js_undefined(); } }; @@ -797,7 +790,7 @@ int main(int argc, char** argv) auto file = Core::File::construct(script_path); 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; } auto file_contents = file->read_all();