diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index fb506677945..6d7e50029d9 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -156,9 +156,6 @@ public: const StackInfo& stack_info() const { return m_stack_info; }; - bool underscore_is_last_value() const { return m_underscore_is_last_value; } - void set_underscore_is_last_value(bool b) { m_underscore_is_last_value = b; } - u32 execution_generation() const { return m_execution_generation; } void finish_execution_generation() { ++m_execution_generation; } @@ -279,8 +276,6 @@ private: JS_ENUMERATE_WELL_KNOWN_SYMBOLS #undef __JS_ENUMERATE - bool m_underscore_is_last_value { false }; - u32 m_execution_generation { 0 }; OwnPtr m_custom_data; diff --git a/Userland/Utilities/js.cpp b/Userland/Utilities/js.cpp index be9b825450f..cf376d8eda8 100644 --- a/Userland/Utilities/js.cpp +++ b/Userland/Utilities/js.cpp @@ -71,6 +71,7 @@ RefPtr vm; Vector repl_statements; +JS::Handle last_value = JS::make_handle(JS::js_undefined()); class ReplObject final : public JS::GlobalObject { JS_OBJECT(ReplObject, JS::GlobalObject); @@ -86,6 +87,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(load_file); JS_DECLARE_NATIVE_FUNCTION(save_to_file); JS_DECLARE_NATIVE_FUNCTION(load_json); + JS_DECLARE_NATIVE_FUNCTION(last_value_getter); }; class ScriptObject final : public JS::GlobalObject { @@ -986,6 +988,9 @@ static bool parse_and_run(JS::Interpreter& interpreter, StringView source, Strin } }; + if (!result.is_error()) + last_value = JS::make_handle(result.value()); + if (result.is_error()) { handle_exception(); return false; @@ -1041,6 +1046,24 @@ void ReplObject::initialize_global_object() define_native_function("load", load_file, 1, attr); define_native_function("save", save_to_file, 1, attr); define_native_function("loadJSON", load_json, 1, attr); + + define_native_accessor( + "_", + [](JS::VM&, JS::GlobalObject&) { + return last_value.value(); + }, + [](JS::VM& vm, JS::GlobalObject& global_object) -> JS::ThrowCompletionOr { + VERIFY(is(global_object)); + outln("Disable writing last value to '_'"); + + // We must delete first otherwise this setter gets called recursively. + TRY(global_object.internal_delete(JS::PropertyKey { "_" })); + + auto value = vm.argument(0); + TRY(global_object.internal_set(JS::PropertyKey { "_" }, value, &global_object)); + return value; + }, + attr); } JS_DEFINE_NATIVE_FUNCTION(ReplObject::save_to_file) @@ -1263,7 +1286,6 @@ ErrorOr serenity_main(Main::Arguments arguments) #ifdef JS_TRACK_ZOMBIE_CELLS interpreter->heap().set_zombify_dead_cells(zombify_dead_cells); #endif - interpreter->vm().set_underscore_is_last_value(true); auto& global_environment = interpreter->realm().global_environment();