mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
js: Add command line flag for disabling ANSI colors
This commit is contained in:
parent
c7d2df45b9
commit
11d1950e74
Notes:
sideshowbarker
2024-07-18 00:43:30 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/11d1950e742 Pull-request: https://github.com/SerenityOS/serenity/pull/11049 Reviewed-by: https://github.com/linusg ✅
2 changed files with 193 additions and 150 deletions
|
@ -28,6 +28,7 @@ Run `help()` in REPL mode to see its available built-in functions.
|
|||
* `-m`, `--as-module`: Treat as module
|
||||
* `-l`, `--print-last-result`: Print the result of the last statement executed.
|
||||
* `-g`, `--gc-on-every-allocation`: Run garbage collection on every allocation.
|
||||
* `-c`, `--disable-ansi-colors`: Disable ANSI colors
|
||||
* `-s`, `--no-syntax-highlight`: Disable live syntax highlighting in the REPL
|
||||
|
||||
## Examples
|
||||
|
|
|
@ -104,6 +104,7 @@ static bool s_run_bytecode = false;
|
|||
static bool s_opt_bytecode = false;
|
||||
static bool s_as_module = false;
|
||||
static bool s_print_last_result = false;
|
||||
static bool s_strip_ansi = false;
|
||||
static RefPtr<Line::Editor> s_editor;
|
||||
static String s_history_path = String::formatted("{}/.js-history", Core::StandardPaths::home_directory());
|
||||
static int s_repl_line_level = 0;
|
||||
|
@ -193,22 +194,62 @@ static String read_next_piece()
|
|||
return piece.to_string();
|
||||
}
|
||||
|
||||
static String strip_ansi(StringView format_string)
|
||||
{
|
||||
if (format_string.is_empty())
|
||||
return String::empty();
|
||||
|
||||
StringBuilder builder;
|
||||
size_t i;
|
||||
for (i = 0; i < format_string.length() - 1; ++i) {
|
||||
if (format_string[i] == '\033' && format_string[i + 1] == '[') {
|
||||
while (i < format_string.length() && format_string[i] != 'm')
|
||||
++i;
|
||||
} else {
|
||||
builder.append(format_string[i]);
|
||||
}
|
||||
}
|
||||
if (i < format_string.length())
|
||||
builder.append(format_string[i]);
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
template<typename... Parameters>
|
||||
static void js_out(CheckedFormatString<Parameters...>&& fmtstr, const Parameters&... parameters)
|
||||
{
|
||||
if (!s_strip_ansi)
|
||||
return out(move(fmtstr), parameters...);
|
||||
auto stripped_fmtstr = strip_ansi(fmtstr.view());
|
||||
out(stripped_fmtstr, parameters...);
|
||||
}
|
||||
|
||||
template<typename... Parameters>
|
||||
static void js_outln(CheckedFormatString<Parameters...>&& fmtstr, const Parameters&... parameters)
|
||||
{
|
||||
if (!s_strip_ansi)
|
||||
return outln(move(fmtstr), parameters...);
|
||||
auto stripped_fmtstr = strip_ansi(fmtstr.view());
|
||||
outln(stripped_fmtstr, parameters...);
|
||||
}
|
||||
|
||||
inline void js_outln() { outln(); }
|
||||
|
||||
static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects);
|
||||
|
||||
static void print_type(FlyString const& name)
|
||||
{
|
||||
out("[\033[36;1m{}\033[0m]", name);
|
||||
js_out("[\033[36;1m{}\033[0m]", name);
|
||||
}
|
||||
|
||||
static void print_separator(bool& first)
|
||||
{
|
||||
out(first ? " " : ", ");
|
||||
js_out(first ? " " : ", ");
|
||||
first = false;
|
||||
}
|
||||
|
||||
static void print_array(JS::Array& array, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
out("[");
|
||||
js_out("[");
|
||||
bool first = true;
|
||||
for (auto it = array.indexed_properties().begin(false); it != array.indexed_properties().end(); ++it) {
|
||||
print_separator(first);
|
||||
|
@ -222,17 +263,17 @@ static void print_array(JS::Array& array, HashTable<JS::Object*>& seen_objects)
|
|||
print_value(value, seen_objects);
|
||||
}
|
||||
if (!first)
|
||||
out(" ");
|
||||
out("]");
|
||||
js_out(" ");
|
||||
js_out("]");
|
||||
}
|
||||
|
||||
static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
out("{{");
|
||||
js_out("{{");
|
||||
bool first = true;
|
||||
for (auto& entry : object.indexed_properties()) {
|
||||
print_separator(first);
|
||||
out("\"\033[33;1m{}\033[0m\": ", entry.index());
|
||||
js_out("\"\033[33;1m{}\033[0m\": ", entry.index());
|
||||
auto value_or_error = object.get(entry.index());
|
||||
// The V8 repl doesn't throw an exception here, and instead just
|
||||
// prints 'undefined'. We may choose to replicate that behavior in
|
||||
|
@ -245,30 +286,30 @@ static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_object
|
|||
for (auto& it : object.shape().property_table_ordered()) {
|
||||
print_separator(first);
|
||||
if (it.key.is_string()) {
|
||||
out("\"\033[33;1m{}\033[0m\": ", it.key.to_display_string());
|
||||
js_out("\"\033[33;1m{}\033[0m\": ", it.key.to_display_string());
|
||||
} else {
|
||||
out("[\033[33;1m{}\033[0m]: ", it.key.to_display_string());
|
||||
js_out("[\033[33;1m{}\033[0m]: ", it.key.to_display_string());
|
||||
}
|
||||
print_value(object.get_direct(it.value.offset), seen_objects);
|
||||
}
|
||||
if (!first)
|
||||
out(" ");
|
||||
out("}}");
|
||||
js_out(" ");
|
||||
js_out("}}");
|
||||
}
|
||||
|
||||
static void print_function(JS::Object const& object, HashTable<JS::Object*>&)
|
||||
{
|
||||
print_type(object.class_name());
|
||||
if (is<JS::ECMAScriptFunctionObject>(object))
|
||||
out(" {}", static_cast<JS::ECMAScriptFunctionObject const&>(object).name());
|
||||
js_out(" {}", static_cast<JS::ECMAScriptFunctionObject const&>(object).name());
|
||||
else if (is<JS::NativeFunction>(object))
|
||||
out(" {}", static_cast<JS::NativeFunction const&>(object).name());
|
||||
js_out(" {}", static_cast<JS::NativeFunction const&>(object).name());
|
||||
}
|
||||
|
||||
static void print_date(JS::Object const& object, HashTable<JS::Object*>&)
|
||||
{
|
||||
print_type("Date");
|
||||
out(" \033[34;1m{}\033[0m", static_cast<JS::Date const&>(object).string());
|
||||
js_out(" \033[34;1m{}\033[0m", static_cast<JS::Date const&>(object).string());
|
||||
}
|
||||
|
||||
static void print_error(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
|
@ -282,7 +323,7 @@ static void print_error(JS::Object const& object, HashTable<JS::Object*>& seen_o
|
|||
auto message_string = message.to_string_without_side_effects();
|
||||
print_type(name_string);
|
||||
if (!message_string.is_empty())
|
||||
out(" \033[31;1m{}\033[0m", message_string);
|
||||
js_out(" \033[31;1m{}\033[0m", message_string);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,16 +331,16 @@ static void print_regexp_object(JS::Object const& object, HashTable<JS::Object*>
|
|||
{
|
||||
auto& regexp_object = static_cast<JS::RegExpObject const&>(object);
|
||||
print_type("RegExp");
|
||||
out(" \033[34;1m/{}/{}\033[0m", regexp_object.escape_regexp_pattern(), regexp_object.flags());
|
||||
js_out(" \033[34;1m/{}/{}\033[0m", regexp_object.escape_regexp_pattern(), regexp_object.flags());
|
||||
}
|
||||
|
||||
static void print_proxy_object(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
auto& proxy_object = static_cast<JS::ProxyObject const&>(object);
|
||||
print_type("Proxy");
|
||||
out("\n target: ");
|
||||
js_out("\n target: ");
|
||||
print_value(&proxy_object.target(), seen_objects);
|
||||
out("\n handler: ");
|
||||
js_out("\n handler: ");
|
||||
print_value(&proxy_object.handler(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -308,17 +349,17 @@ static void print_map(JS::Object const& object, HashTable<JS::Object*>& seen_obj
|
|||
auto& map = static_cast<JS::Map const&>(object);
|
||||
auto& entries = map.entries();
|
||||
print_type("Map");
|
||||
out(" {{");
|
||||
js_out(" {{");
|
||||
bool first = true;
|
||||
for (auto& entry : entries) {
|
||||
print_separator(first);
|
||||
print_value(entry.key, seen_objects);
|
||||
out(" => ");
|
||||
js_out(" => ");
|
||||
print_value(entry.value, seen_objects);
|
||||
}
|
||||
if (!first)
|
||||
out(" ");
|
||||
out("}}");
|
||||
js_out(" ");
|
||||
js_out("}}");
|
||||
}
|
||||
|
||||
static void print_set(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
|
@ -326,15 +367,15 @@ static void print_set(JS::Object const& object, HashTable<JS::Object*>& seen_obj
|
|||
auto& set = static_cast<JS::Set const&>(object);
|
||||
auto& values = set.values();
|
||||
print_type("Set");
|
||||
out(" {{");
|
||||
js_out(" {{");
|
||||
bool first = true;
|
||||
for (auto& value : values) {
|
||||
print_separator(first);
|
||||
print_value(value, seen_objects);
|
||||
}
|
||||
if (!first)
|
||||
out(" ");
|
||||
out("}}");
|
||||
js_out(" ");
|
||||
js_out("}}");
|
||||
}
|
||||
|
||||
static void print_promise(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
|
@ -343,19 +384,19 @@ static void print_promise(JS::Object const& object, HashTable<JS::Object*>& seen
|
|||
print_type("Promise");
|
||||
switch (promise.state()) {
|
||||
case JS::Promise::State::Pending:
|
||||
out("\n state: ");
|
||||
out("\033[36;1mPending\033[0m");
|
||||
js_out("\n state: ");
|
||||
js_out("\033[36;1mPending\033[0m");
|
||||
break;
|
||||
case JS::Promise::State::Fulfilled:
|
||||
out("\n state: ");
|
||||
out("\033[32;1mFulfilled\033[0m");
|
||||
out("\n result: ");
|
||||
js_out("\n state: ");
|
||||
js_out("\033[32;1mFulfilled\033[0m");
|
||||
js_out("\n result: ");
|
||||
print_value(promise.result(), seen_objects);
|
||||
break;
|
||||
case JS::Promise::State::Rejected:
|
||||
out("\n state: ");
|
||||
out("\033[31;1mRejected\033[0m");
|
||||
out("\n result: ");
|
||||
js_out("\n state: ");
|
||||
js_out("\033[31;1mRejected\033[0m");
|
||||
js_out("\n result: ");
|
||||
print_value(promise.result(), seen_objects);
|
||||
break;
|
||||
default:
|
||||
|
@ -369,20 +410,20 @@ static void print_array_buffer(JS::Object const& object, HashTable<JS::Object*>&
|
|||
auto& buffer = array_buffer.buffer();
|
||||
auto byte_length = array_buffer.byte_length();
|
||||
print_type("ArrayBuffer");
|
||||
out("\n byteLength: ");
|
||||
js_out("\n byteLength: ");
|
||||
print_value(JS::Value((double)byte_length), seen_objects);
|
||||
if (!byte_length)
|
||||
return;
|
||||
outln();
|
||||
js_outln();
|
||||
for (size_t i = 0; i < byte_length; ++i) {
|
||||
out("{:02x}", buffer[i]);
|
||||
js_out("{:02x}", buffer[i]);
|
||||
if (i + 1 < byte_length) {
|
||||
if ((i + 1) % 32 == 0)
|
||||
outln();
|
||||
js_outln();
|
||||
else if ((i + 1) % 16 == 0)
|
||||
out(" ");
|
||||
js_out(" ");
|
||||
else
|
||||
out(" ");
|
||||
js_out(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,9 +437,9 @@ static void print_shadow_realm(JS::Object const&, HashTable<JS::Object*>&)
|
|||
template<typename T>
|
||||
static void print_number(T number) requires IsArithmetic<T>
|
||||
{
|
||||
out("\033[35;1m");
|
||||
out("{}", number);
|
||||
out("\033[0m");
|
||||
js_out("\033[35;1m");
|
||||
js_out("{}", number);
|
||||
js_out("\033[0m");
|
||||
}
|
||||
|
||||
static void print_typed_array(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
|
@ -407,30 +448,30 @@ static void print_typed_array(JS::Object const& object, HashTable<JS::Object*>&
|
|||
auto& array_buffer = *typed_array_base.viewed_array_buffer();
|
||||
auto length = typed_array_base.array_length();
|
||||
print_type(object.class_name());
|
||||
out("\n length: ");
|
||||
js_out("\n length: ");
|
||||
print_value(JS::Value(length), seen_objects);
|
||||
out("\n byteLength: ");
|
||||
js_out("\n byteLength: ");
|
||||
print_value(JS::Value(typed_array_base.byte_length()), seen_objects);
|
||||
out("\n buffer: ");
|
||||
js_out("\n buffer: ");
|
||||
print_type("ArrayBuffer");
|
||||
if (array_buffer.is_detached())
|
||||
out(" (detached)");
|
||||
out(" @ {:p}", &array_buffer);
|
||||
js_out(" (detached)");
|
||||
js_out(" @ {:p}", &array_buffer);
|
||||
if (!length || array_buffer.is_detached())
|
||||
return;
|
||||
outln();
|
||||
js_outln();
|
||||
// FIXME: This kinda sucks.
|
||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||
if (is<JS::ClassName>(object)) { \
|
||||
out("[ "); \
|
||||
js_out("[ "); \
|
||||
auto& typed_array = static_cast<JS::ClassName const&>(typed_array_base); \
|
||||
auto data = typed_array.data(); \
|
||||
for (size_t i = 0; i < length; ++i) { \
|
||||
if (i > 0) \
|
||||
out(", "); \
|
||||
js_out(", "); \
|
||||
print_number(data[i]); \
|
||||
} \
|
||||
out(" ]"); \
|
||||
js_out(" ]"); \
|
||||
return; \
|
||||
}
|
||||
JS_ENUMERATE_TYPED_ARRAYS
|
||||
|
@ -442,20 +483,20 @@ static void print_data_view(JS::Object const& object, HashTable<JS::Object*>& se
|
|||
{
|
||||
auto& data_view = static_cast<JS::DataView const&>(object);
|
||||
print_type("DataView");
|
||||
out("\n byteLength: ");
|
||||
js_out("\n byteLength: ");
|
||||
print_value(JS::Value(data_view.byte_length()), seen_objects);
|
||||
out("\n byteOffset: ");
|
||||
js_out("\n byteOffset: ");
|
||||
print_value(JS::Value(data_view.byte_offset()), seen_objects);
|
||||
out("\n buffer: ");
|
||||
js_out("\n buffer: ");
|
||||
print_type("ArrayBuffer");
|
||||
out(" @ {:p}", data_view.viewed_array_buffer());
|
||||
js_out(" @ {:p}", data_view.viewed_array_buffer());
|
||||
}
|
||||
|
||||
static void print_temporal_calendar(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
auto& calendar = static_cast<JS::Temporal::Calendar const&>(object);
|
||||
print_type("Temporal.Calendar");
|
||||
out(" ");
|
||||
js_out(" ");
|
||||
print_value(JS::js_string(object.vm(), calendar.identifier()), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -463,14 +504,14 @@ static void print_temporal_duration(JS::Object const& object, HashTable<JS::Obje
|
|||
{
|
||||
auto& duration = static_cast<JS::Temporal::Duration const&>(object);
|
||||
print_type("Temporal.Duration");
|
||||
out(" \033[34;1m{} y, {} M, {} w, {} d, {} h, {} m, {} s, {} ms, {} us, {} ns\033[0m", duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds());
|
||||
js_out(" \033[34;1m{} y, {} M, {} w, {} d, {} h, {} m, {} s, {} ms, {} us, {} ns\033[0m", duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds());
|
||||
}
|
||||
|
||||
static void print_temporal_instant(JS::Object const& object, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
auto& instant = static_cast<JS::Temporal::Instant const&>(object);
|
||||
print_type("Temporal.Instant");
|
||||
out(" ");
|
||||
js_out(" ");
|
||||
// FIXME: Print human readable date and time, like in print_date() - ideally handling arbitrarily large values since we get a bigint.
|
||||
print_value(&instant.nanoseconds(), seen_objects);
|
||||
}
|
||||
|
@ -479,8 +520,8 @@ static void print_temporal_plain_date(JS::Object const& object, HashTable<JS::Ob
|
|||
{
|
||||
auto& plain_date = static_cast<JS::Temporal::PlainDate const&>(object);
|
||||
print_type("Temporal.PlainDate");
|
||||
out(" \033[34;1m{:04}-{:02}-{:02}\033[0m", plain_date.iso_year(), plain_date.iso_month(), plain_date.iso_day());
|
||||
out("\n calendar: ");
|
||||
js_out(" \033[34;1m{:04}-{:02}-{:02}\033[0m", plain_date.iso_year(), plain_date.iso_month(), plain_date.iso_day());
|
||||
js_out("\n calendar: ");
|
||||
print_value(&plain_date.calendar(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -488,8 +529,8 @@ static void print_temporal_plain_date_time(JS::Object const& object, HashTable<J
|
|||
{
|
||||
auto& plain_date_time = static_cast<JS::Temporal::PlainDateTime const&>(object);
|
||||
print_type("Temporal.PlainDateTime");
|
||||
out(" \033[34;1m{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_date_time.iso_year(), plain_date_time.iso_month(), plain_date_time.iso_day(), plain_date_time.iso_hour(), plain_date_time.iso_minute(), plain_date_time.iso_second(), plain_date_time.iso_millisecond(), plain_date_time.iso_microsecond(), plain_date_time.iso_nanosecond());
|
||||
out("\n calendar: ");
|
||||
js_out(" \033[34;1m{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_date_time.iso_year(), plain_date_time.iso_month(), plain_date_time.iso_day(), plain_date_time.iso_hour(), plain_date_time.iso_minute(), plain_date_time.iso_second(), plain_date_time.iso_millisecond(), plain_date_time.iso_microsecond(), plain_date_time.iso_nanosecond());
|
||||
js_out("\n calendar: ");
|
||||
print_value(&plain_date_time.calendar(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -498,8 +539,8 @@ static void print_temporal_plain_month_day(JS::Object const& object, HashTable<J
|
|||
auto& plain_month_day = static_cast<JS::Temporal::PlainMonthDay const&>(object);
|
||||
print_type("Temporal.PlainMonthDay");
|
||||
// Also has an [[ISOYear]] internal slot, but showing that here seems rather unexpected.
|
||||
out(" \033[34;1m{:02}-{:02}\033[0m", plain_month_day.iso_month(), plain_month_day.iso_day());
|
||||
out("\n calendar: ");
|
||||
js_out(" \033[34;1m{:02}-{:02}\033[0m", plain_month_day.iso_month(), plain_month_day.iso_day());
|
||||
js_out("\n calendar: ");
|
||||
print_value(&plain_month_day.calendar(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -507,8 +548,8 @@ static void print_temporal_plain_time(JS::Object const& object, HashTable<JS::Ob
|
|||
{
|
||||
auto& plain_time = static_cast<JS::Temporal::PlainTime const&>(object);
|
||||
print_type("Temporal.PlainTime");
|
||||
out(" \033[34;1m{:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_time.iso_hour(), plain_time.iso_minute(), plain_time.iso_second(), plain_time.iso_millisecond(), plain_time.iso_microsecond(), plain_time.iso_nanosecond());
|
||||
out("\n calendar: ");
|
||||
js_out(" \033[34;1m{:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_time.iso_hour(), plain_time.iso_minute(), plain_time.iso_second(), plain_time.iso_millisecond(), plain_time.iso_microsecond(), plain_time.iso_nanosecond());
|
||||
js_out("\n calendar: ");
|
||||
print_value(&plain_time.calendar(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -517,8 +558,8 @@ static void print_temporal_plain_year_month(JS::Object const& object, HashTable<
|
|||
auto& plain_year_month = static_cast<JS::Temporal::PlainYearMonth const&>(object);
|
||||
print_type("Temporal.PlainYearMonth");
|
||||
// Also has an [[ISODay]] internal slot, but showing that here seems rather unexpected.
|
||||
out(" \033[34;1m{:04}-{:02}\033[0m", plain_year_month.iso_year(), plain_year_month.iso_month());
|
||||
out("\n calendar: ");
|
||||
js_out(" \033[34;1m{:04}-{:02}\033[0m", plain_year_month.iso_year(), plain_year_month.iso_month());
|
||||
js_out("\n calendar: ");
|
||||
print_value(&plain_year_month.calendar(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -526,10 +567,10 @@ static void print_temporal_time_zone(JS::Object const& object, HashTable<JS::Obj
|
|||
{
|
||||
auto& time_zone = static_cast<JS::Temporal::TimeZone const&>(object);
|
||||
print_type("Temporal.TimeZone");
|
||||
out(" ");
|
||||
js_out(" ");
|
||||
print_value(JS::js_string(object.vm(), time_zone.identifier()), seen_objects);
|
||||
if (time_zone.offset_nanoseconds().has_value()) {
|
||||
out("\n offset (ns): ");
|
||||
js_out("\n offset (ns): ");
|
||||
print_value(JS::Value(*time_zone.offset_nanoseconds()), seen_objects);
|
||||
}
|
||||
}
|
||||
|
@ -538,11 +579,11 @@ static void print_temporal_zoned_date_time(JS::Object const& object, HashTable<J
|
|||
{
|
||||
auto& zoned_date_time = static_cast<JS::Temporal::ZonedDateTime const&>(object);
|
||||
print_type("Temporal.ZonedDateTime");
|
||||
out("\n epochNanoseconds: ");
|
||||
js_out("\n epochNanoseconds: ");
|
||||
print_value(&zoned_date_time.nanoseconds(), seen_objects);
|
||||
out("\n timeZone: ");
|
||||
js_out("\n timeZone: ");
|
||||
print_value(&zoned_date_time.time_zone(), seen_objects);
|
||||
out("\n calendar: ");
|
||||
js_out("\n calendar: ");
|
||||
print_value(&zoned_date_time.calendar(), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -550,13 +591,13 @@ static void print_intl_display_names(JS::Object const& object, HashTable<JS::Obj
|
|||
{
|
||||
auto& display_names = static_cast<JS::Intl::DisplayNames const&>(object);
|
||||
print_type("Intl.DisplayNames");
|
||||
out("\n locale: ");
|
||||
js_out("\n locale: ");
|
||||
print_value(js_string(object.vm(), display_names.locale()), seen_objects);
|
||||
out("\n type: ");
|
||||
js_out("\n type: ");
|
||||
print_value(js_string(object.vm(), display_names.type_string()), seen_objects);
|
||||
out("\n style: ");
|
||||
js_out("\n style: ");
|
||||
print_value(js_string(object.vm(), display_names.style_string()), seen_objects);
|
||||
out("\n fallback: ");
|
||||
js_out("\n fallback: ");
|
||||
print_value(js_string(object.vm(), display_names.fallback_string()), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -564,29 +605,29 @@ static void print_intl_locale(JS::Object const& object, HashTable<JS::Object*>&
|
|||
{
|
||||
auto& locale = static_cast<JS::Intl::Locale const&>(object);
|
||||
print_type("Intl.Locale");
|
||||
out("\n locale: ");
|
||||
js_out("\n locale: ");
|
||||
print_value(js_string(object.vm(), locale.locale()), seen_objects);
|
||||
if (locale.has_calendar()) {
|
||||
out("\n calendar: ");
|
||||
js_out("\n calendar: ");
|
||||
print_value(js_string(object.vm(), locale.calendar()), seen_objects);
|
||||
}
|
||||
if (locale.has_case_first()) {
|
||||
out("\n caseFirst: ");
|
||||
js_out("\n caseFirst: ");
|
||||
print_value(js_string(object.vm(), locale.case_first()), seen_objects);
|
||||
}
|
||||
if (locale.has_collation()) {
|
||||
out("\n collation: ");
|
||||
js_out("\n collation: ");
|
||||
print_value(js_string(object.vm(), locale.collation()), seen_objects);
|
||||
}
|
||||
if (locale.has_hour_cycle()) {
|
||||
out("\n hourCycle: ");
|
||||
js_out("\n hourCycle: ");
|
||||
print_value(js_string(object.vm(), locale.hour_cycle()), seen_objects);
|
||||
}
|
||||
if (locale.has_numbering_system()) {
|
||||
out("\n numberingSystem: ");
|
||||
js_out("\n numberingSystem: ");
|
||||
print_value(js_string(object.vm(), locale.numbering_system()), seen_objects);
|
||||
}
|
||||
out("\n numeric: ");
|
||||
js_out("\n numeric: ");
|
||||
print_value(JS::Value(locale.numeric()), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -594,11 +635,11 @@ static void print_intl_list_format(JS::Object const& object, HashTable<JS::Objec
|
|||
{
|
||||
auto& list_format = static_cast<JS::Intl::ListFormat const&>(object);
|
||||
print_type("Intl.ListFormat");
|
||||
out("\n locale: ");
|
||||
js_out("\n locale: ");
|
||||
print_value(js_string(object.vm(), list_format.locale()), seen_objects);
|
||||
out("\n type: ");
|
||||
js_out("\n type: ");
|
||||
print_value(js_string(object.vm(), list_format.type_string()), seen_objects);
|
||||
out("\n style: ");
|
||||
js_out("\n style: ");
|
||||
print_value(js_string(object.vm(), list_format.style_string()), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -606,63 +647,63 @@ static void print_intl_number_format(JS::Object const& object, HashTable<JS::Obj
|
|||
{
|
||||
auto& number_format = static_cast<JS::Intl::NumberFormat const&>(object);
|
||||
print_type("Intl.NumberFormat");
|
||||
out("\n locale: ");
|
||||
js_out("\n locale: ");
|
||||
print_value(js_string(object.vm(), number_format.locale()), seen_objects);
|
||||
out("\n dataLocale: ");
|
||||
js_out("\n dataLocale: ");
|
||||
print_value(js_string(object.vm(), number_format.data_locale()), seen_objects);
|
||||
out("\n numberingSystem: ");
|
||||
js_out("\n numberingSystem: ");
|
||||
print_value(js_string(object.vm(), number_format.numbering_system()), seen_objects);
|
||||
out("\n style: ");
|
||||
js_out("\n style: ");
|
||||
print_value(js_string(object.vm(), number_format.style_string()), seen_objects);
|
||||
if (number_format.has_currency()) {
|
||||
out("\n currency: ");
|
||||
js_out("\n currency: ");
|
||||
print_value(js_string(object.vm(), number_format.currency()), seen_objects);
|
||||
}
|
||||
if (number_format.has_currency_display()) {
|
||||
out("\n currencyDisplay: ");
|
||||
js_out("\n currencyDisplay: ");
|
||||
print_value(js_string(object.vm(), number_format.currency_display_string()), seen_objects);
|
||||
}
|
||||
if (number_format.has_currency_sign()) {
|
||||
out("\n currencySign: ");
|
||||
js_out("\n currencySign: ");
|
||||
print_value(js_string(object.vm(), number_format.currency_sign_string()), seen_objects);
|
||||
}
|
||||
if (number_format.has_unit()) {
|
||||
out("\n unit: ");
|
||||
js_out("\n unit: ");
|
||||
print_value(js_string(object.vm(), number_format.unit()), seen_objects);
|
||||
}
|
||||
if (number_format.has_unit_display()) {
|
||||
out("\n unitDisplay: ");
|
||||
js_out("\n unitDisplay: ");
|
||||
print_value(js_string(object.vm(), number_format.unit_display_string()), seen_objects);
|
||||
}
|
||||
out("\n minimumIntegerDigits: ");
|
||||
js_out("\n minimumIntegerDigits: ");
|
||||
print_value(JS::Value(number_format.min_integer_digits()), seen_objects);
|
||||
if (number_format.has_min_fraction_digits()) {
|
||||
out("\n minimumFractionDigits: ");
|
||||
js_out("\n minimumFractionDigits: ");
|
||||
print_value(JS::Value(number_format.min_fraction_digits()), seen_objects);
|
||||
}
|
||||
if (number_format.has_max_fraction_digits()) {
|
||||
out("\n maximumFractionDigits: ");
|
||||
js_out("\n maximumFractionDigits: ");
|
||||
print_value(JS::Value(number_format.max_fraction_digits()), seen_objects);
|
||||
}
|
||||
if (number_format.has_min_significant_digits()) {
|
||||
out("\n minimumSignificantDigits: ");
|
||||
js_out("\n minimumSignificantDigits: ");
|
||||
print_value(JS::Value(number_format.min_significant_digits()), seen_objects);
|
||||
}
|
||||
if (number_format.has_max_significant_digits()) {
|
||||
out("\n maximumSignificantDigits: ");
|
||||
js_out("\n maximumSignificantDigits: ");
|
||||
print_value(JS::Value(number_format.max_significant_digits()), seen_objects);
|
||||
}
|
||||
out("\n useGrouping: ");
|
||||
js_out("\n useGrouping: ");
|
||||
print_value(JS::Value(number_format.use_grouping()), seen_objects);
|
||||
out("\n roundingType: ");
|
||||
js_out("\n roundingType: ");
|
||||
print_value(js_string(object.vm(), number_format.rounding_type_string()), seen_objects);
|
||||
out("\n notation: ");
|
||||
js_out("\n notation: ");
|
||||
print_value(js_string(object.vm(), number_format.notation_string()), seen_objects);
|
||||
if (number_format.has_compact_display()) {
|
||||
out("\n compactDisplay: ");
|
||||
js_out("\n compactDisplay: ");
|
||||
print_value(js_string(object.vm(), number_format.compact_display_string()), seen_objects);
|
||||
}
|
||||
out("\n signDisplay: ");
|
||||
js_out("\n signDisplay: ");
|
||||
print_value(js_string(object.vm(), number_format.sign_display_string()), seen_objects);
|
||||
}
|
||||
|
||||
|
@ -670,14 +711,14 @@ static void print_primitive_wrapper_object(FlyString const& name, JS::Object con
|
|||
{
|
||||
// BooleanObject, NumberObject, StringObject
|
||||
print_type(name);
|
||||
out(" ");
|
||||
js_out(" ");
|
||||
print_value(object.value_of(), seen_objects);
|
||||
}
|
||||
|
||||
static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
|
||||
{
|
||||
if (value.is_empty()) {
|
||||
out("\033[34;1m<empty>\033[0m");
|
||||
js_out("\033[34;1m<empty>\033[0m");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -685,7 +726,7 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
|
|||
if (seen_objects.contains(&value.as_object())) {
|
||||
// FIXME: Maybe we should only do this for circular references,
|
||||
// not for all reoccurring objects.
|
||||
out("<already printed Object {}>", &value.as_object());
|
||||
js_out("<already printed Object {}>", &value.as_object());
|
||||
return;
|
||||
}
|
||||
seen_objects.set(&value.as_object());
|
||||
|
@ -757,30 +798,30 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
|
|||
}
|
||||
|
||||
if (value.is_string())
|
||||
out("\033[32;1m");
|
||||
js_out("\033[32;1m");
|
||||
else if (value.is_number() || value.is_bigint())
|
||||
out("\033[35;1m");
|
||||
js_out("\033[35;1m");
|
||||
else if (value.is_boolean())
|
||||
out("\033[33;1m");
|
||||
js_out("\033[33;1m");
|
||||
else if (value.is_null())
|
||||
out("\033[33;1m");
|
||||
js_out("\033[33;1m");
|
||||
else if (value.is_undefined())
|
||||
out("\033[34;1m");
|
||||
js_out("\033[34;1m");
|
||||
if (value.is_string())
|
||||
out("\"");
|
||||
js_out("\"");
|
||||
else if (value.is_negative_zero())
|
||||
out("-");
|
||||
out("{}", value.to_string_without_side_effects());
|
||||
js_out("-");
|
||||
js_out("{}", value.to_string_without_side_effects());
|
||||
if (value.is_string())
|
||||
out("\"");
|
||||
out("\033[0m");
|
||||
js_out("\"");
|
||||
js_out("\033[0m");
|
||||
}
|
||||
|
||||
static void print(JS::Value value)
|
||||
{
|
||||
HashTable<JS::Object*> seen_objects;
|
||||
print_value(value, seen_objects);
|
||||
outln();
|
||||
js_outln();
|
||||
}
|
||||
|
||||
static bool write_to_file(String const& path)
|
||||
|
@ -822,7 +863,7 @@ static bool parse_and_run(JS::Interpreter& interpreter, StringView source, Strin
|
|||
auto error = parser.errors()[0];
|
||||
auto hint = error.source_location_hint(source);
|
||||
if (!hint.is_empty())
|
||||
outln("{}", hint);
|
||||
js_outln("{}", hint);
|
||||
vm->throw_exception<JS::SyntaxError>(interpreter.global_object(), error.to_string());
|
||||
} else {
|
||||
if (JS::Bytecode::g_dump_bytecode || s_run_bytecode) {
|
||||
|
@ -854,7 +895,7 @@ static bool parse_and_run(JS::Interpreter& interpreter, StringView source, Strin
|
|||
auto handle_exception = [&] {
|
||||
auto* exception = vm->exception();
|
||||
vm->clear_exception();
|
||||
out("Uncaught exception: ");
|
||||
js_out("Uncaught exception: ");
|
||||
print(exception->value());
|
||||
auto& traceback = exception->traceback();
|
||||
if (traceback.size() > 1) {
|
||||
|
@ -872,11 +913,11 @@ static bool parse_and_run(JS::Interpreter& interpreter, StringView source, Strin
|
|||
// If more than 5 (1 + >4) consecutive function calls with the same name, print
|
||||
// the name only once and show the number of repetitions instead. This prevents
|
||||
// printing ridiculously large call stacks of recursive functions.
|
||||
outln(" -> {}", traceback_frame.function_name);
|
||||
outln(" {} more calls", repetitions);
|
||||
js_outln(" -> {}", traceback_frame.function_name);
|
||||
js_outln(" {} more calls", repetitions);
|
||||
} else {
|
||||
for (size_t j = 0; j < repetitions + 1; ++j)
|
||||
outln(" -> {}", traceback_frame.function_name);
|
||||
js_outln(" -> {}", traceback_frame.function_name);
|
||||
}
|
||||
repetitions = 0;
|
||||
}
|
||||
|
@ -961,11 +1002,11 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::exit_interpreter)
|
|||
|
||||
JS_DEFINE_NATIVE_FUNCTION(ReplObject::repl_help)
|
||||
{
|
||||
outln("REPL commands:");
|
||||
outln(" exit(code): exit the REPL with specified code. Defaults to 0.");
|
||||
outln(" help(): display this menu");
|
||||
outln(" load(file): load given JS file into running session. For example: load(\"foo.js\")");
|
||||
outln(" save(file): write REPL input history to the given file. For example: save(\"foo.txt\")");
|
||||
js_outln("REPL commands:");
|
||||
js_outln(" exit(code): exit the REPL with specified code. Defaults to 0.");
|
||||
js_outln(" help(): display this menu");
|
||||
js_outln(" load(file): load given JS file into running session. For example: load(\"foo.js\")");
|
||||
js_outln(" save(file): write REPL input history to the given file. For example: save(\"foo.txt\")");
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
|
@ -1024,49 +1065,49 @@ public:
|
|||
|
||||
virtual JS::Value log() override
|
||||
{
|
||||
outln("{}", vm().join_arguments());
|
||||
js_outln("{}", vm().join_arguments());
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
virtual JS::Value info() override
|
||||
{
|
||||
outln("(i) {}", vm().join_arguments());
|
||||
js_outln("(i) {}", vm().join_arguments());
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
virtual JS::Value debug() override
|
||||
{
|
||||
outln("\033[36;1m{}\033[0m", vm().join_arguments());
|
||||
js_outln("\033[36;1m{}\033[0m", vm().join_arguments());
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
virtual JS::Value warn() override
|
||||
{
|
||||
outln("\033[33;1m{}\033[0m", vm().join_arguments());
|
||||
js_outln("\033[33;1m{}\033[0m", vm().join_arguments());
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
virtual JS::Value error() override
|
||||
{
|
||||
outln("\033[31;1m{}\033[0m", vm().join_arguments());
|
||||
js_outln("\033[31;1m{}\033[0m", vm().join_arguments());
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
virtual JS::Value clear() override
|
||||
{
|
||||
out("\033[3J\033[H\033[2J");
|
||||
js_out("\033[3J\033[H\033[2J");
|
||||
fflush(stdout);
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
virtual JS::Value trace() override
|
||||
{
|
||||
outln("{}", vm().join_arguments());
|
||||
js_outln("{}", vm().join_arguments());
|
||||
auto trace = get_trace();
|
||||
for (auto& function_name : trace) {
|
||||
if (function_name.is_empty())
|
||||
function_name = "<anonymous>";
|
||||
outln(" -> {}", function_name);
|
||||
js_outln(" -> {}", function_name);
|
||||
}
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
@ -1075,7 +1116,7 @@ public:
|
|||
{
|
||||
auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default";
|
||||
auto counter_value = m_console.counter_increment(label);
|
||||
outln("{}: {}", label, counter_value);
|
||||
js_outln("{}: {}", label, counter_value);
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
|
@ -1083,9 +1124,9 @@ public:
|
|||
{
|
||||
auto label = vm().argument_count() ? vm().argument(0).to_string_without_side_effects() : "default";
|
||||
if (m_console.counter_reset(label))
|
||||
outln("{}: 0", label);
|
||||
js_outln("{}: 0", label);
|
||||
else
|
||||
outln("\033[33;1m\"{}\" doesn't have a count\033[0m", label);
|
||||
js_outln("\033[33;1m\"{}\" doesn't have a count\033[0m", label);
|
||||
return JS::js_undefined();
|
||||
}
|
||||
|
||||
|
@ -1094,10 +1135,10 @@ public:
|
|||
auto& vm = this->vm();
|
||||
if (!vm.argument(0).to_boolean()) {
|
||||
if (vm.argument_count() > 1) {
|
||||
out("\033[31;1mAssertion failed:\033[0m");
|
||||
outln(" {}", vm.join_arguments(1));
|
||||
js_out("\033[31;1mAssertion failed:\033[0m");
|
||||
js_outln(" {}", vm.join_arguments(1));
|
||||
} else {
|
||||
outln("\033[31;1mAssertion failed\033[0m");
|
||||
js_outln("\033[31;1mAssertion failed\033[0m");
|
||||
}
|
||||
}
|
||||
return JS::js_undefined();
|
||||
|
@ -1122,6 +1163,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
args_parser.add_option(s_opt_bytecode, "Optimize the bytecode", "optimize-bytecode", 'p');
|
||||
args_parser.add_option(s_as_module, "Treat as module", "as-module", 'm');
|
||||
args_parser.add_option(s_print_last_result, "Print last result", "print-last-result", 'l');
|
||||
args_parser.add_option(s_strip_ansi, "Disable ANSI colors", "disable-ansi-colors", 'c');
|
||||
args_parser.add_option(gc_on_every_allocation, "GC on every allocation", "gc-on-every-allocation", 'g');
|
||||
#ifdef JS_TRACK_ZOMBIE_CELLS
|
||||
bool zombify_dead_cells = false;
|
||||
|
@ -1140,19 +1182,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
// might want to revisit at a later point and disable warnings for promises created this way.
|
||||
vm->on_promise_unhandled_rejection = [](auto& promise) {
|
||||
// FIXME: Optionally make print_value() to print to stderr
|
||||
out("WARNING: A promise was rejected without any handlers");
|
||||
out(" (result: ");
|
||||
js_out("WARNING: A promise was rejected without any handlers");
|
||||
js_out(" (result: ");
|
||||
HashTable<JS::Object*> seen_objects;
|
||||
print_value(promise.result(), seen_objects);
|
||||
outln(")");
|
||||
js_outln(")");
|
||||
};
|
||||
vm->on_promise_rejection_handled = [](auto& promise) {
|
||||
// FIXME: Optionally make print_value() to print to stderr
|
||||
out("WARNING: A handler was added to an already rejected promise");
|
||||
out(" (result: ");
|
||||
js_out("WARNING: A handler was added to an already rejected promise");
|
||||
js_out(" (result: ");
|
||||
HashTable<JS::Object*> seen_objects;
|
||||
print_value(promise.result(), seen_objects);
|
||||
outln(")");
|
||||
js_outln(")");
|
||||
};
|
||||
OwnPtr<JS::Interpreter> interpreter;
|
||||
|
||||
|
|
Loading…
Reference in a new issue