mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
js: Use new string formatting functions
This commit is contained in:
parent
626c17d284
commit
518481086b
Notes:
sideshowbarker
2024-07-19 01:28:05 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/518481086b0 Pull-request: https://github.com/SerenityOS/serenity/pull/4009
1 changed files with 53 additions and 60 deletions
113
Userland/js.cpp
113
Userland/js.cpp
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue