diff options
author | Andreas Kling <kling@serenityos.org> | 2020-03-26 12:26:11 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-26 12:26:11 +0100 |
commit | 6e6495fdf9534f160216603ed2112fe1cbed9926 (patch) | |
tree | 45b6cf3dcbdff0b200c805ec04990d6573ff9d85 /Userland | |
parent | 68dec2801d09f7b9ed6a53fa45ab012e835c4c79 (diff) | |
download | serenity-6e6495fdf9534f160216603ed2112fe1cbed9926.zip |
js: Implement some modest pretty-printing of values
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/js.cpp | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/Userland/js.cpp b/Userland/js.cpp index f13cb9204b..ee96818639 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -32,6 +32,7 @@ #include <LibJS/AST.h> #include <LibJS/Interpreter.h> #include <LibJS/Parser.h> +#include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Object.h> #include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/Value.h> @@ -92,6 +93,74 @@ String read_next_piece() return piece.to_string(); } +static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects); + +static void print_array(const JS::Array* array, HashTable<JS::Object*>& seen_objects) +{ + fputs("[ ", stdout); + for (size_t i = 0; i < array->elements().size(); ++i) { + print_value(array->elements()[i], seen_objects); + if (i != array->elements().size() - 1) + fputs(", ", stdout); + } + fputs(" ]", stdout); +} + +static void print_object(const JS::Object* object, HashTable<JS::Object*>& seen_objects) +{ + fputs("{ ", stdout); + size_t index = 0; + for (auto& it : object->own_properties()) { + printf("\"\033[33;1m%s\033[0m\": ", it.key.characters()); + print_value(it.value, seen_objects); + if (index != object->own_properties().size() - 1) + fputs(", ", stdout); + ++index; + } + fputs(" }", stdout); +} + +void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects) +{ + if (value.is_object()) { + if (seen_objects.contains(value.as_object())) { + // FIXME: Maybe we should only do this for circular references, + // not for all reoccurring objects. + printf("<already printed Object %p>", value.as_object()); + return; + } + seen_objects.set(value.as_object()); + } + + if (value.is_array()) + return print_array(static_cast<const JS::Array*>(value.as_object()), seen_objects); + + if (value.is_object()) + return print_object(value.as_object(), seen_objects); + + if (value.is_string()) + printf("\033[31;1m"); + else if (value.is_number()) + printf("\033[35;1m"); + else if (value.is_boolean()) + printf("\033[32;1m"); + else if (value.is_null() || value.is_undefined()) + printf("\033[34;1m"); + if (value.is_string()) + putchar('"'); + printf("%s", value.to_string().characters()); + if (value.is_string()) + putchar('"'); + printf("\033[0m"); +} + +static void print(JS::Value value) +{ + HashTable<JS::Object*> seen_objects; + print_value(value, seen_objects); + putchar('\n'); +} + void repl(JS::Interpreter& interpreter) { while (true) { @@ -104,7 +173,7 @@ void repl(JS::Interpreter& interpreter) program->dump(0); auto result = interpreter.run(*program); - printf("%s\n", result.to_string().characters()); + print(result); } } |