From 63a0ebcc9053f6ceb01095db67e03a76cccd925f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 16 Sep 2021 21:48:07 +0200 Subject: [PATCH] js: Add a simple loadJSON(path) built-in to load JSON from a file This is very handy when you want to load data from /proc, for example. --- Userland/Libraries/LibJS/Runtime/JSONObject.h | 3 +- Userland/Utilities/js.cpp | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Runtime/JSONObject.h b/Userland/Libraries/LibJS/Runtime/JSONObject.h index 6c83cce556e..591d9bc8015 100644 --- a/Userland/Libraries/LibJS/Runtime/JSONObject.h +++ b/Userland/Libraries/LibJS/Runtime/JSONObject.h @@ -22,6 +22,8 @@ public: // test-js to communicate between the JS tests and the C++ test runner. static String stringify_impl(GlobalObject&, Value value, Value replacer, Value space); + static Value parse_json_value(GlobalObject&, const JsonValue&); + private: struct StringifyState { FunctionObject* replacer_function { nullptr }; @@ -40,7 +42,6 @@ private: // Parse helpers static Object* parse_json_object(GlobalObject&, const JsonObject&); static Array* parse_json_array(GlobalObject&, const JsonArray&); - static Value parse_json_value(GlobalObject&, const JsonValue&); static Value internalize_json_property(GlobalObject&, Object* holder, PropertyName const& name, FunctionObject& reviver); JS_DECLARE_NATIVE_FUNCTION(stringify); diff --git a/Userland/Utilities/js.cpp b/Userland/Utilities/js.cpp index 75b2d4cb0e5..4d8ad054e72 100644 --- a/Userland/Utilities/js.cpp +++ b/Userland/Utilities/js.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(repl_help); JS_DECLARE_NATIVE_FUNCTION(load_file); JS_DECLARE_NATIVE_FUNCTION(save_to_file); + JS_DECLARE_NATIVE_FUNCTION(load_json); }; class ScriptObject final : public JS::GlobalObject { @@ -91,6 +93,7 @@ public: private: JS_DECLARE_NATIVE_FUNCTION(load_file); + JS_DECLARE_NATIVE_FUNCTION(load_json); }; static bool s_dump_ast = false; @@ -909,6 +912,25 @@ static JS::Value load_file_impl(JS::VM& vm, JS::GlobalObject& global_object) return JS::js_undefined(); } +static JS::Value load_json_impl(JS::VM& vm, JS::GlobalObject& global_object) +{ + auto filename = vm.argument(0).to_string(global_object); + if (vm.exception()) + return {}; + auto file = Core::File::construct(filename); + if (!file->open(Core::OpenMode::ReadOnly)) { + vm.throw_exception(global_object, String::formatted("Failed to open '{}': {}", filename, file->error_string())); + return {}; + } + auto file_contents = file->read_all(); + auto json = JsonValue::from_string(file_contents); + if (!json.has_value()) { + vm.throw_exception(global_object, JS::ErrorType::JsonMalformed); + return {}; + } + return JS::JSONObject::parse_json_value(global_object, json.value()); +} + void ReplObject::initialize_global_object() { Base::initialize_global_object(); @@ -918,6 +940,7 @@ void ReplObject::initialize_global_object() define_native_function("help", repl_help, 0, attr); 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); } JS_DEFINE_NATIVE_FUNCTION(ReplObject::save_to_file) @@ -957,12 +980,18 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::load_file) return load_file_impl(vm, global_object); } +JS_DEFINE_NATIVE_FUNCTION(ReplObject::load_json) +{ + return load_json_impl(vm, global_object); +} + void ScriptObject::initialize_global_object() { Base::initialize_global_object(); define_direct_property("global", this, JS::Attribute::Enumerable); u8 attr = JS::Attribute::Configurable | JS::Attribute::Writable | JS::Attribute::Enumerable; define_native_function("load", load_file, 1, attr); + define_native_function("loadJSON", load_json, 1, attr); } JS_DEFINE_NATIVE_FUNCTION(ScriptObject::load_file) @@ -970,6 +999,11 @@ JS_DEFINE_NATIVE_FUNCTION(ScriptObject::load_file) return load_file_impl(vm, global_object); } +JS_DEFINE_NATIVE_FUNCTION(ScriptObject::load_json) +{ + return load_json_impl(vm, global_object); +} + static void repl(JS::Interpreter& interpreter) { while (!s_fail_repl) {