From 95a106c7870b590453589f3ad8d8d7dc67d312f8 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 28 Jun 2023 18:48:00 +0200 Subject: [PATCH 01/42] refactor(): wip --- src/cli/cli.cc | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 4bedb45d7..6cf83e3de 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2107,6 +2107,8 @@ int main (const int argc, const char* argv[]) { } else { targetPlatform = platform.os; } + + argvForward += " --platform=" + targetPlatform; auto platformFriendlyName = targetPlatform == "win32" ? "windows" : targetPlatform; platformFriendlyName = platformFriendlyName == "android-emulator" ? "android" : platformFriendlyName; @@ -2927,6 +2929,7 @@ int main (const int argc, const char* argv[]) { if (key.find("compiler_debug_flags") != String::npos) continue; if (key.find("linker_flags") != String::npos) continue; if (key.find("linker_debug_flags") != String::npos) continue; + if (key.find("configure_script") != String::npos) continue; if (key.starts_with("build_extensions_mac_")) continue; if (key.starts_with("build_extensions_linux_")) continue; if (key.starts_with("build_extensions_win_")) continue; @@ -2971,12 +2974,33 @@ int main (const int argc, const char* argv[]) { settings["build_extensions_" + extension + "_android_linker_debug_flags"] + " " ); + auto configure = settings["build_extensions_" + extension + "_configure_script"]; auto sources = StringStream(); auto make = StringStream(); auto cwd = targetPath; std::unordered_set cflags; std::unordered_set cppflags; + if (configure.size() > 0) { + auto output = replace(exec(configure + argvForward).output, "\n", " "); + if (output.size() > 0) { + for (const auto& source : parseStringList(output, ' ')) { + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("configure: " + source); + } + + auto destination= ( + Path(source).parent_path() / + Path(source).filename().string() + ).string(); + + fs::create_directories(jni / Path(destination).parent_path()); + fs::copy(cwd / source, jni / destination, fs::copy_options::overwrite_existing); + sources << source << " "; + } + } + } + for (auto source : parseStringList(tuple.second, ' ')) { auto destination= ( Path(source).parent_path() / @@ -3304,6 +3328,7 @@ int main (const int argc, const char* argv[]) { if (key.find("compiler_debug_flags") != String::npos) continue; if (key.find("linker_flags") != String::npos) continue; if (key.find("linker_debug_flags") != String::npos) continue; + if (key.find("configure_script") != String::npos) continue; if (key.starts_with("build_extensions_mac_")) continue; if (key.starts_with("build_extensions_linux_")) continue; if (key.starts_with("build_extensions_win_")) continue; @@ -3316,6 +3341,8 @@ int main (const int argc, const char* argv[]) { extension = replace(key, "build_extensions_", ""); } + auto configure = settings["build_extensions_" + extension + "_configure_script"]; + auto sources = parseStringList(tuple.second, ' '); auto objects = StringStream(); auto libdir = platform.arch == "arm64" ? prefixFile(String("lib/arm64-") + (flagBuildForSimulator ? "iPhoneSimulator" : "iPhoneOS")) @@ -3326,7 +3353,20 @@ int main (const int argc, const char* argv[]) { extensions.push_back(extension); } - for (const auto& source : parseStringList(tuple.second, ' ')) { + if (configure.size() > 0) { + auto output = replace(exec(configure + argvForward).output, "\n", " "); + if (output.size() > 0) { + for (const auto& source : parseStringList(output, ' ')) { + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("configure: " + source); + } + + sources.push_back(source); + } + } + } + + for (const auto& source : sources) { String compiler; auto compilerFlags = ( @@ -3360,11 +3400,15 @@ int main (const int argc, const char* argv[]) { } else if (source.ends_with(".cc") || source.ends_with(".cpp") || source.ends_with(".c++") || source.ends_with(".mm")) { compiler = "clang++"; compilerFlags += " -std=c++2a -ObjC++ -v "; + } else if (source.ends_with(".o") || source.ends_with(".a")) { + objects << source << " "; + continue; } else { compiler = "clang"; compilerFlags += " -ObjC -v "; } + auto filename = Path(replace(replace(source, "\\.cc", ".o"), "\\.c", ".o")).filename(); auto object = ( paths.pathResourcesRelativeToUserBuild / @@ -4066,6 +4110,7 @@ int main (const int argc, const char* argv[]) { if (key.find("compiler_debug_flags") != String::npos) continue; if (key.find("linker_flags") != String::npos) continue; if (key.find("linker_debug_flags") != String::npos) continue; + if (key.find("configure_script") != String::npos) continue; if (key.starts_with("build_extensions_ios_")) continue; if (key.starts_with("build_extensions_android_")) continue; @@ -4074,17 +4119,31 @@ int main (const int argc, const char* argv[]) { if (!platform.linux && key.starts_with("build_extensions_linux_")) continue; String extension; - auto os = replace(platform.os, "win32", "win"); + auto os = replace(replace(platform.os, "win32", "win"), "macos", "mac");; if (key.starts_with("build_extensions_" + os)) { extension = replace(key, "build_extensions_" + os + "_", ""); } else { extension = replace(key, "build_extensions_", ""); } + auto configure = settings["build_extensions_" + extension + "_configure_script"]; auto sources = parseStringList(tuple.second, ' '); auto objects = StringStream(); auto lib = (paths.pathResourcesRelativeToUserBuild / "socket" / "extensions" / extension / (extension + SHARED_OBJ_EXT)); + if (configure.size() > 0) { + auto output = replace(exec(configure + argvForward).output, "\n", " "); + if (output.size() > 0) { + for (const auto& source : parseStringList(output, ' ')) { + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("configure: " + source); + } + + sources.push_back(source); + } + } + } + if (sources.size() == 0) { continue; } @@ -4144,6 +4203,9 @@ int main (const int argc, const char* argv[]) { } else if (platform.win) { compilerFlags += " -stdlib=libstdc++"; } + } else if (source.ends_with(".o") || source.ends_with(".a")) { + objects << source << " "; + continue; } else { if (CC.size() > 0) { compiler = CC; From 7e3b81df72e0a5ea2c398cd1c6e12699f6f67243 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Fri, 7 Jul 2023 08:55:54 +0200 Subject: [PATCH 02/42] refactor(): support external extension sources --- include/socket/extension.h | 32 +++++- src/cli/cli.cc | 208 ++++++++++++++++++++++++++++++++----- src/extension/context.cc | 12 ++- src/extension/ipc.cc | 21 +++- 4 files changed, 241 insertions(+), 32 deletions(-) diff --git a/include/socket/extension.h b/include/socket/extension.h index 365355be2..7c33afd16 100644 --- a/include/socket/extension.h +++ b/include/socket/extension.h @@ -193,6 +193,26 @@ extern "C" { const sapi_context_t* context ); + /** + * Get user data from context. + * @param context - An extension context + * @return An opaque pointer to user data + */ + SOCKET_RUNTIME_EXTENSION_EXPORT + const void * sapi_context_get_data ( + const sapi_context_t* context + ); + + /** + * Get parent context for this context + * @param context - An extension context + * @return A pointer to the parent context. This value may be `NULL`. + */ + SOCKET_RUNTIME_EXTENSION_EXPORT + const sapi_context_t* sapi_context_get_parent ( + const sapi_context_t* context + ); + /** * Set a context error code. * @param context - An extension context @@ -665,7 +685,7 @@ extern "C" { */ #define sapi_printf(ctx, format, ...) ({ \ char _buffer[BUFSIZ] = {0}; \ - int _size = snprintf(nullptr, 0, format, ##__VA_ARGS__) + 1; \ + int _size = snprintf(NULL, 0, format, ##__VA_ARGS__) + 1; \ snprintf(_buffer, _size, format, ##__VA_ARGS__); \ sapi_log(ctx, _buffer); \ }) @@ -824,6 +844,16 @@ extern "C" { const sapi_ipc_result_t* result ); + /** + * Get context from IPC result. + * @param result - An IPC request result + * @return An extension context + */ + SOCKET_RUNTIME_EXTENSION_EXPORT + sapi_context_t* sapi_ipc_result_get_context ( + const sapi_ipc_result_t* result + ); + /** * Set the IPC result message * @param result - An IPC request result diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 6cf83e3de..70151d134 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2942,6 +2942,44 @@ int main (const int argc, const char* argv[]) { extension = replace(key, "build_extensions_", ""); } + extension = split(extension, '_')[0]; + + auto source = settings["build_extensions_" + extension + "_source"]; + + if (source.size() > 0) { + Path target; + if (fs::exists(source)) { + target = source; + } else if (source.ends_with(".git")) { + auto path = Path { source }; + target = paths.platformSpecificOutputPath / "extensions" / replace(path.filename().string(), ".git", ""); + + if (!fs::exists(target)) { + auto exitCode = std::system(("git clone " + source + " " + target.string()).c_str()); + + if (exitCode) { + exit(exitCode); + } + } + } + + if (fs::exists(target)) { + auto configFile = target / "socket.ini"; + auto config = parseINI(fs::exists(configFile) ? readFile(configFile) : ""); + settings["build_extensions_" + extension + "_path"] = target; + + for (const auto& entry : config) { + if (entry.first.starts_with("extension_sources")) { + settings["build_extensions_" + extension] += entry.second; + } else if (entry.first.starts_with("extension_")) { + auto key = replace(entry.first, "extension_", extension + "_"); + auto value = entry.second; + settings["build_extensions_" + key] = value; + } + } + } + } + auto compilerFlags = replace( settings["build_extensions_compiler_flags"] + " " + settings["build_extensions_android_compiler_flags"] + " " + @@ -2975,20 +3013,32 @@ int main (const int argc, const char* argv[]) { ); auto configure = settings["build_extensions_" + extension + "_configure_script"]; + auto build = settings["build_extensions_" + extension + "_build_script"]; + auto path = settings["build_extensions_" + extension + "_path"]; + auto sources = StringStream(); auto make = StringStream(); auto cwd = targetPath; std::unordered_set cflags; std::unordered_set cppflags; + if (path.size() > 0) { + fs::current_path(path); + } else { + fs::current_path(targetPath); + } + + if (build.size() > 0) { + auto exitCode = std::system((build + argvForward).c_str()); + if (exitCode) { + exit(exitCode); + } + } + if (configure.size() > 0) { auto output = replace(exec(configure + argvForward).output, "\n", " "); if (output.size() > 0) { for (const auto& source : parseStringList(output, ' ')) { - if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { - log("configure: " + source); - } - auto destination= ( Path(source).parent_path() / Path(source).filename().string() @@ -3007,6 +3057,10 @@ int main (const int argc, const char* argv[]) { Path(source).filename().string() ).string(); + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("source: " + source); + } + fs::create_directories(jni / Path(destination).parent_path()); fs::copy(cwd / source, jni / destination, fs::copy_options::overwrite_existing); @@ -3341,7 +3395,47 @@ int main (const int argc, const char* argv[]) { extension = replace(key, "build_extensions_", ""); } + auto source = settings["build_extensions_" + extension + "_source"]; + + if (source.size() > 0) { + Path target; + if (fs::exists(source)) { + target = source; + } else if (source.ends_with(".git")) { + auto path = Path { source }; + target = paths.platformSpecificOutputPath / "extensions" / replace(path.filename().string(), ".git", ""); + + if (!fs::exists(target)) { + auto exitCode = std::system(("git clone " + source + " " + target.string()).c_str()); + + if (exitCode) { + exit(exitCode); + } + } + } + + if (fs::exists(target)) { + auto configFile = target / "socket.ini"; + auto config = parseINI(fs::exists(configFile) ? readFile(configFile) : ""); + settings["build_extensions_" + extension + "_path"] = target; + + for (const auto& entry : config) { + if (entry.first.starts_with("extension_sources")) { + settings["build_extensions_" + extension] += entry.second; + } else if (entry.first.starts_with("extension_")) { + auto key = replace(entry.first, "extension_", extension + "_"); + auto value = entry.second; + settings["build_extensions_" + key] = value; + } + } + } + } + + auto configure = settings["build_extensions_" + extension + "_configure_script"]; + auto build = settings["build_extensions_" + extension + "_build_script"]; + auto path = settings["build_extensions_" + extension + "_path"]; + auto sources = parseStringList(tuple.second, ' '); auto objects = StringStream(); auto libdir = platform.arch == "arm64" @@ -3353,6 +3447,13 @@ int main (const int argc, const char* argv[]) { extensions.push_back(extension); } + if (build.size() > 0) { + auto exitCode = std::system((build + argvForward).c_str()); + if (exitCode) { + exit(exitCode); + } + } + if (configure.size() > 0) { auto output = replace(exec(configure + argvForward).output, "\n", " "); if (output.size() > 0) { @@ -4126,19 +4227,75 @@ int main (const int argc, const char* argv[]) { extension = replace(key, "build_extensions_", ""); } + extension = split(extension, '_')[0]; + + auto source = settings["build_extensions_" + extension + "_source"]; + + if (source.size() > 0) { + Path target; + if (fs::exists(source)) { + target = source; + } else if (source.ends_with(".git")) { + auto path = Path { source }; + target = paths.platformSpecificOutputPath / "extensions" / replace(path.filename().string(), ".git", ""); + + if (!fs::exists(target)) { + auto exitCode = std::system(("git clone " + source + " " + target.string()).c_str()); + + if (exitCode) { + exit(exitCode); + } + } + } + + if (fs::exists(target)) { + auto configFile = target / "socket.ini"; + auto config = parseINI(fs::exists(configFile) ? readFile(configFile) : ""); + settings["build_extensions_" + extension + "_path"] = target; + + for (const auto& entry : config) { + if (entry.first.starts_with("extension_sources")) { + settings["build_extensions_" + extension] += entry.second; + } else if (entry.first.starts_with("extension_")) { + auto key = replace(entry.first, "extension_", extension + "_"); + auto value = entry.second; + settings["build_extensions_" + key] = value; + } + } + } + } + auto configure = settings["build_extensions_" + extension + "_configure_script"]; - auto sources = parseStringList(tuple.second, ' '); + auto build = settings["build_extensions_" + extension + "_build_script"]; + auto path = settings["build_extensions_" + extension + "_path"]; + + auto sources = parseStringList( + trim(settings["build_extensions_" + extension] + " " + settings["build_extensions_" + extension + "_" + os]), + ' ' + ); + auto objects = StringStream(); auto lib = (paths.pathResourcesRelativeToUserBuild / "socket" / "extensions" / extension / (extension + SHARED_OBJ_EXT)); + fs::create_directories(lib.parent_path()); + + if (path.size() > 0) { + fs::current_path(path); + } else { + fs::current_path(targetPath); + } + + if (build.size() > 0) { + auto exitCode = std::system((build + argvForward).c_str()); + if (exitCode) { + exit(exitCode); + } + } + if (configure.size() > 0) { auto output = replace(exec(configure + argvForward).output, "\n", " "); if (output.size() > 0) { for (const auto& source : parseStringList(output, ' ')) { - if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { - log("configure: " + source); - } - sources.push_back(source); } } @@ -4158,8 +4315,6 @@ int main (const int argc, const char* argv[]) { ); for (auto source : sources) { - source = fs::absolute(Path(targetPath) / source).string(); - auto compilerFlags = ( settings["build_extensions_compiler_flags"] + " " + settings["build_extensions_" + os + "_compiler_flags"] + " " + @@ -4203,13 +4358,8 @@ int main (const int argc, const char* argv[]) { } else if (platform.win) { compilerFlags += " -stdlib=libstdc++"; } - } else if (source.ends_with(".o") || source.ends_with(".a")) { - objects << source << " "; - continue; - } else { - if (CC.size() > 0) { - compiler = CC; - } else if (CXX.ends_with("clang++")) { + + if (CXX.ends_with("clang++")) { compiler = CXX.substr(0, CXX.size() - 2); } else if (CXX.ends_with("clang++.exe")) { compiler = CXX.substr(0, CXX.size() - 6) + ".exe"; @@ -4218,22 +4368,26 @@ int main (const int argc, const char* argv[]) { } else if (CXX.ends_with("g++.exe")) { compiler = CXX.substr(0, CXX.size() - 6) + "cc.exe"; } + } else if (source.ends_with(".o") || source.ends_with(".a")) { + objects << source << " "; + continue; + } else if (source.ends_with(".c") ){ + if (CC.size() > 0) { + compiler = CC; + } if (platform.mac) { compilerFlags += " -ObjC -v"; } + } else { + continue; } - auto filename = Path(replace(replace(source, "\\.cc", ".o"), "\\.c", ".o")).filename(); - auto object = ( - paths.pathResourcesRelativeToUserBuild / - "socket" / - "extensions" / - extension / - filename - ); + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("source: " + source); + } - fs::create_directories(object.parent_path()); + auto object = Path(replace(replace(source, "\\.cc", ".o"), "\\.c", ".o")); objects << (quote + object.string() + quote) << " "; auto compileExtensionObjectCommand = StringStream(); diff --git a/src/extension/context.cc b/src/extension/context.cc index 380dbea7f..79120e304 100644 --- a/src/extension/context.cc +++ b/src/extension/context.cc @@ -45,9 +45,7 @@ bool sapi_context_dispatch ( } return ctx->router->dispatch([=]() { - ctx->router->bridge->core->dispatchEventLoop([ctx, data, callback] () { - callback(ctx, data); - }); + callback(ctx, data); }); } @@ -99,6 +97,14 @@ const sapi_ipc_router_t* sapi_context_get_router (const sapi_context_t* ctx) { return reinterpret_cast(ctx->router); } +const void * sapi_context_get_data (const sapi_context_t* context) { + return context != nullptr ? context->data : nullptr; +} + +const sapi_context_t* sapi_context_get_parent (const sapi_context_t* context) { + return context != nullptr ? reinterpret_cast(context->context) : nullptr; +} + void sapi_context_error_reset (sapi_context_t* context) { if (context == nullptr) return; context->error.code = 0; diff --git a/src/extension/ipc.cc b/src/extension/ipc.cc index 77fe76b39..ab15dbe22 100644 --- a/src/extension/ipc.cc +++ b/src/extension/ipc.cc @@ -20,12 +20,15 @@ void sapi_ipc_router_map ( } sapi_context_t context(ctx); + auto router = ctx->router; ctx->router->map(name, [data, callback, context]( auto& message, auto router, auto reply ) { - auto ctx = new sapi_context_t(context); + router->dispatch([=]() mutable { + auto ctx = sapi_context_create(&context, true); + ctx->data = data; auto msg = SSC::IPC::Message( message.uri, true, // decode parameter values AOT in `message.uri` @@ -38,6 +41,7 @@ void sapi_ipc_router_map ( (sapi_ipc_message_t*) &msg, reinterpret_cast(&router) ); + }); }); } @@ -315,6 +319,12 @@ const sapi_ipc_message_t* sapi_ipc_result_get_message ( : nullptr; } +sapi_context_t* sapi_ipc_result_get_context ( + const sapi_ipc_result_t* result +) { + return result ? result->context : nullptr; +} + void sapi_ipc_result_set_json ( sapi_ipc_result_t* result, const sapi_json_any_t* json @@ -338,6 +348,9 @@ void sapi_ipc_result_set_json ( } else if (json->isNumber()) { auto number = reinterpret_cast(json); result->value = SSC::JSON::Number(number->data); + } else if (json->isRaw()) { + auto raw = reinterpret_cast(json); + result->value = SSC::JSON::Raw(raw->data); } } } @@ -373,6 +386,9 @@ void sapi_ipc_result_set_json_data ( } else if (json->isNumber()) { auto number = reinterpret_cast(json); result->data = SSC::JSON::Number(number->data); + } else if (json->isRaw()) { + auto raw = reinterpret_cast(json); + result->data = SSC::JSON::Raw(raw->data); } } } @@ -408,6 +424,9 @@ void sapi_ipc_result_set_json_error ( } else if (json->isNumber()) { auto number = reinterpret_cast(json); result->err = SSC::JSON::Number(number->data); + } else if (json->isRaw()) { + auto raw = reinterpret_cast(json); + result->err = SSC::JSON::Raw(raw->data); } } } From b2a0c45a73a9dc849026f4ad4921660e985687fd Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sat, 8 Jul 2023 13:33:21 +0200 Subject: [PATCH 03/42] fix(include/socket/extension.h): fix 'sapi_process_spawn_kill' name --- include/socket/extension.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/socket/extension.h b/include/socket/extension.h index 7c33afd16..2bb29a2b8 100644 --- a/include/socket/extension.h +++ b/include/socket/extension.h @@ -1244,7 +1244,7 @@ extern "C" { * @return TODO */ SOCKET_RUNTIME_EXTENSION_EXPORT - const bool sapi_process_kill ( + const bool sapi_process_spawn_kill ( sapi_process_spawn_t* process, const int code ); From fc18af4dc28e0121827d427cacd3b3c560bd6668 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sat, 8 Jul 2023 13:33:36 +0200 Subject: [PATCH 04/42] refactor(src/extension/process.cc): guard ios/ fix 'sapi_process_spawn_lkill' name --- src/extension/process.cc | 51 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/extension/process.cc b/src/extension/process.cc index 30032bfab..c83e6aeba 100644 --- a/src/extension/process.cc +++ b/src/extension/process.cc @@ -4,11 +4,17 @@ const sapi_process_exec_t* sapi_process_exec ( sapi_context_t* ctx, const char* command ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_exec is not supported on this platform"); + return nullptr; +#endif + if (ctx == nullptr) return nullptr; if (!ctx->isAllowed("process_exec")) { sapi_debug(ctx, "'process_exec' is not allowed."); return nullptr; } + auto process = SSC::exec(command); process.output = SSC::trim(process.output); return ctx->memory.alloc(ctx, process); @@ -17,12 +23,22 @@ const sapi_process_exec_t* sapi_process_exec ( const int sapi_process_exec_get_exit_code ( const sapi_process_exec_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_exec_get_exit_code is not supported on this platform"); + return -1 +#endif + return process != nullptr ? process->exitCode : -1; } const char* sapi_process_exec_get_output ( const sapi_process_exec_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_exec_get_output is not supported on this platform"); + return nullptr; +#endif + return process != nullptr ? process->output.c_str() : nullptr; } @@ -35,6 +51,11 @@ sapi_process_spawn_t* sapi_process_spawn ( sapi_process_spawn_stderr_callback_t onstderr, sapi_process_spawn_exit_callback_t onexit ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn is not supported on this platform"); + return nullptr; +#endif + auto process = ctx->memory.alloc( ctx, command, @@ -51,24 +72,40 @@ sapi_process_spawn_t* sapi_process_spawn ( const int sapi_process_spawn_get_exit_code ( const sapi_process_spawn_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_get_exit_code is not supported on this platform"); + return -1; +#endif return process != nullptr ? process->status.load() : -1; } const unsigned long sapi_process_spawn_get_pid ( const sapi_process_spawn_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_get_pid is not supported on this platform"); + return 0; +#endif return process != nullptr ? process->id : 0; } sapi_context_t* sapi_process_spawn_get_context ( const sapi_process_spawn_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_get_context is not supported on this platform"); + return nullptr; +#endif return process != nullptr ? process->context : nullptr; } const int sapi_process_spawn_wait ( sapi_process_spawn_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_wait is not supported on this platform"); + return -1; +#endif return process != nullptr ? process->wait() : -1; } @@ -77,6 +114,10 @@ const bool sapi_process_spawn_write ( const char* data, const size_t size ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_write is not supported on this platform"); + return false; +#endif if (!process || process->closed) return false; process->write(data, size); return true; @@ -85,15 +126,23 @@ const bool sapi_process_spawn_write ( const bool sapi_process_spawn_close_stdin ( sapi_process_spawn_t* process ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_close_stdin is not supported on this platform"); + return false; +#endif if (!process || process->closed) return false; process->close_stdin(); return true; } -const bool sapi_process_kill ( +const bool sapi_process_spawn_kill ( sapi_process_spawn_t* process, const int code ) { +#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + debug("sapi_process_spawn_kill is not supported on this platform"); + return false; +#endif if (!process || process->closed) return false; process->kill(code); return true; From 9cc70d90dde3d88c449eba9f7f331d62921839a6 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sat, 8 Jul 2023 13:33:54 +0200 Subject: [PATCH 05/42] chore(.github/workflows/ci.yml): set 'VERBOSE=1' env var --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62542279f..bfe613466 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,6 +59,7 @@ jobs: npm install && npm test env: CI: true + VERBOSE: 1 NODE_AUTH_TOKEN: ${{ secrets.PACKAGE_PAT }} mac: @@ -94,6 +95,7 @@ jobs: npm install && npm test env: CI: true + VERBOSE: 1 NODE_AUTH_TOKEN: ${{ secrets.PACKAGE_PAT }} windows: @@ -143,6 +145,7 @@ jobs: npm install && npm test env: CI: true + VERBOSE: 1 NODE_AUTH_TOKEN: ${{ secrets.PACKAGE_PAT }} ios: @@ -178,6 +181,7 @@ jobs: npm install && npm run test:ios-simulator env: CI: true + VERBOSE: 1 NODE_AUTH_TOKEN: ${{ secrets.PACKAGE_PAT }} android_macos: @@ -289,6 +293,7 @@ jobs: ./bin/ci_version_check.sh env: CI: true + VERBOSE: 1 SSC_ANDROID_CI: true NODE_AUTH_TOKEN: ${{ secrets.PACKAGE_PAT }} From 11a83dd5899e5f996f4ef774f6282f02615d7755 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sat, 8 Jul 2023 13:34:11 +0200 Subject: [PATCH 06/42] fix(src/cli/cli.cc): convert path to string --- src/cli/cli.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 70151d134..b770a5b42 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2966,7 +2966,7 @@ int main (const int argc, const char* argv[]) { if (fs::exists(target)) { auto configFile = target / "socket.ini"; auto config = parseINI(fs::exists(configFile) ? readFile(configFile) : ""); - settings["build_extensions_" + extension + "_path"] = target; + settings["build_extensions_" + extension + "_path"] = target.string(); for (const auto& entry : config) { if (entry.first.starts_with("extension_sources")) { @@ -3417,7 +3417,7 @@ int main (const int argc, const char* argv[]) { if (fs::exists(target)) { auto configFile = target / "socket.ini"; auto config = parseINI(fs::exists(configFile) ? readFile(configFile) : ""); - settings["build_extensions_" + extension + "_path"] = target; + settings["build_extensions_" + extension + "_path"] = target.string(); for (const auto& entry : config) { if (entry.first.starts_with("extension_sources")) { @@ -4251,7 +4251,7 @@ int main (const int argc, const char* argv[]) { if (fs::exists(target)) { auto configFile = target / "socket.ini"; auto config = parseINI(fs::exists(configFile) ? readFile(configFile) : ""); - settings["build_extensions_" + extension + "_path"] = target; + settings["build_extensions_" + extension + "_path"] = target.string(); for (const auto& entry : config) { if (entry.first.starts_with("extension_sources")) { From 7e6ee76a1476c992e4a3a1460c51dd12c7ce3158 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sat, 8 Jul 2023 13:34:27 +0200 Subject: [PATCH 07/42] fix(bin/build-runtime-library.sh): include 'process/unix.cc' for android --- bin/build-runtime-library.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/build-runtime-library.sh b/bin/build-runtime-library.sh index bad04dd45..72ac3970f 100755 --- a/bin/build-runtime-library.sh +++ b/bin/build-runtime-library.sh @@ -118,6 +118,7 @@ if [[ "$platform" = "android" ]]; then clang="$(android_clang "$ANDROID_HOME" "$NDK_VERSION" "$host" "$host_arch" "++")" clang_target="$(android_clang_target "$arch")" + sources+=("$root/src/process/unix.cc") elif [[ "$host" = "Darwin" ]]; then sources+=("$root/src/window/apple.mm") if (( TARGET_OS_IPHONE)) || (( TARGET_IPHONE_SIMULATOR )); then From e979a85448b57a47ab6bbbc1655859061e47b440 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Sat, 8 Jul 2023 13:40:27 +0200 Subject: [PATCH 08/42] fix(src/cli/cli.cc): fix default 'CC' compiler --- src/cli/cli.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index b770a5b42..28be9f260 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -3504,12 +3504,13 @@ int main (const int argc, const char* argv[]) { } else if (source.ends_with(".o") || source.ends_with(".a")) { objects << source << " "; continue; - } else { + } else if (source.ends_with(".c")) { compiler = "clang"; compilerFlags += " -ObjC -v "; + } else { + continue; } - auto filename = Path(replace(replace(source, "\\.cc", ".o"), "\\.c", ".o")).filename(); auto object = ( paths.pathResourcesRelativeToUserBuild / @@ -4371,11 +4372,8 @@ int main (const int argc, const char* argv[]) { } else if (source.ends_with(".o") || source.ends_with(".a")) { objects << source << " "; continue; - } else if (source.ends_with(".c") ){ - if (CC.size() > 0) { - compiler = CC; - } - + } else if (source.ends_with(".c")) { + compiler = CC.size() > 0 ? CC : "clang"; if (platform.mac) { compilerFlags += " -ObjC -v"; } From ba51b32f80e9bba59ddc18eb6e68448124cec8cf Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:20:13 +0200 Subject: [PATCH 09/42] chore(.gitignore): ignore '*.o' files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index eb1da71bd..3a4f31726 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ build/ # Provisioning profile *.mobileprovision dist/ +*.o From 9fcbcde3c7f53c8b9a2dcfa5f3a8fb8ac6991107 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:20:26 +0200 Subject: [PATCH 10/42] refactor(bin/cflags.sh): default visibility is hidden --- bin/cflags.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/cflags.sh b/bin/cflags.sh index 29fd88680..0f0f7356e 100755 --- a/bin/cflags.sh +++ b/bin/cflags.sh @@ -50,6 +50,7 @@ cflags+=( $CFLAG $CXXFLAGS -std=c++2a + -fvisibility=hidden -I"$root/include" -I"$root/build/uv/include" -I"$root/build/include" From 3b423039fe06826f4ac78150b37cc734bb27ba33 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:20:43 +0200 Subject: [PATCH 11/42] refactor(bin/install.sh): omit feature check in debug mode --- bin/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install.sh b/bin/install.sh index 7a74386e9..bc55e2498 100755 --- a/bin/install.sh +++ b/bin/install.sh @@ -853,7 +853,7 @@ function _compile_libuv { } function _check_compiler_features { - if [[ -z "$DEBUG" ]]; then + if [[ -n "$DEBUG" ]]; then return fi From 650eaf646ec9be11220ae68f338149f28ae8124b Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:20:58 +0200 Subject: [PATCH 12/42] refactor(include/socket/extension.h): remove 'const' for scalar types --- include/socket/extension.h | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/include/socket/extension.h b/include/socket/extension.h index 2bb29a2b8..81287c970 100644 --- a/include/socket/extension.h +++ b/include/socket/extension.h @@ -64,7 +64,7 @@ }; \ \ SOCKET_RUNTIME_EXTENSION_EXPORT \ - const unsigned int __sapi_extension_abi () { \ + unsigned int __sapi_extension_abi () { \ return __sapi_extension__.abi; \ } \ \ @@ -127,7 +127,7 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT sapi_context_t* sapi_context_create ( sapi_context_t* parent, - const bool retained + bool retained ); /** @@ -221,7 +221,7 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT void sapi_context_error_set_code ( sapi_context_t* context, - const int code + int code ); /** @@ -230,7 +230,7 @@ extern "C" { * @return The code of the error */ SOCKET_RUNTIME_EXTENSION_EXPORT - const int sapi_context_error_get_code (const sapi_context_t* context); + int sapi_context_error_get_code (const sapi_context_t* context); /** * Set a context error name. @@ -488,7 +488,7 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT sapi_json_boolean_t* sapi_json_boolean_create ( sapi_context_t* context, - const bool boolean + bool boolean ); /** @@ -549,7 +549,7 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT void sapi_json_array_set ( sapi_json_array_t* array, - const unsigned int index, + unsigned int index, sapi_json_any_t* value ); @@ -562,7 +562,7 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT sapi_json_any_t* sapi_json_array_get ( const sapi_json_array_t* array, - const unsigned int index + unsigned int index ); /** @@ -756,7 +756,7 @@ extern "C" { * @return The window index the IPC message was initiated from or intended for */ SOCKET_RUNTIME_EXTENSION_EXPORT - const int sapi_ipc_message_get_index ( + int sapi_ipc_message_get_index ( const sapi_ipc_message_t* message ); @@ -947,8 +947,8 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT void sapi_ipc_result_set_bytes ( sapi_ipc_result_t* result, - const unsigned int size, - const unsigned char* bytes + unsigned int size, + unsigned char* bytes ); /** @@ -957,7 +957,7 @@ extern "C" { * @return THe IPC result bytes */ SOCKET_RUNTIME_EXTENSION_EXPORT - const unsigned char* sapi_ipc_result_get_bytes ( + unsigned char* sapi_ipc_result_get_bytes ( const sapi_ipc_result_t* result ); @@ -967,7 +967,7 @@ extern "C" { * @return The size of the IPC result bytes */ SOCKET_RUNTIME_EXTENSION_EXPORT - const unsigned int sapi_ipc_result_get_bytes_size ( + unsigned int sapi_ipc_result_get_bytes_size ( const sapi_ipc_result_t* result ); @@ -1042,8 +1042,8 @@ extern "C" { bool sapi_ipc_send_bytes ( sapi_context_t* context, const char* seq, - const unsigned int size, - const unsigned char* bytes, + unsigned int size, + unsigned char* bytes, const char* headers ); @@ -1057,7 +1057,7 @@ extern "C" { * @param data - User data propagated to `callback` */ SOCKET_RUNTIME_EXTENSION_EXPORT - void sapi_ipc_router_map ( + bool sapi_ipc_router_map ( sapi_context_t* context, const char* route, sapi_ipc_router_message_callback_t callback, @@ -1071,7 +1071,7 @@ extern "C" { * @param route - The route name to map */ SOCKET_RUNTIME_EXTENSION_EXPORT - void sapi_ipc_router_unmap ( + bool sapi_ipc_router_unmap ( sapi_context_t* context, const char* route ); @@ -1133,7 +1133,7 @@ extern "C" { typedef void (*sapi_process_spawn_stdout_callback_t)( const sapi_process_spawn_t* process, const char* output, - const unsigned int size + unsigned int size ); /** @@ -1142,7 +1142,7 @@ extern "C" { typedef void (*sapi_process_spawn_stderr_callback_t)( const sapi_process_spawn_t* process, const char* output, - const unsigned int size + unsigned int size ); /** @@ -1150,7 +1150,7 @@ extern "C" { */ typedef void (*sapi_process_spawn_exit_callback_t)( const sapi_process_spawn_t* process, - const int exit_code + int exit_code ); /** @@ -1172,7 +1172,7 @@ extern "C" { * @return The exit code of the process */ SOCKET_RUNTIME_EXTENSION_EXPORT - const int sapi_process_exec_get_exit_code ( + int sapi_process_exec_get_exit_code ( const sapi_process_exec_t* process ); @@ -1207,12 +1207,12 @@ extern "C" { * @return The exit code of the process */ SOCKET_RUNTIME_EXTENSION_EXPORT - const int sapi_process_spawn_get_exit_code ( + int sapi_process_spawn_get_exit_code ( const sapi_process_spawn_t* process ); SOCKET_RUNTIME_EXTENSION_EXPORT - const unsigned long sapi_process_spawn_get_pid ( + unsigned long sapi_process_spawn_get_pid ( const sapi_process_spawn_t* process ); @@ -1222,19 +1222,19 @@ extern "C" { ); SOCKET_RUNTIME_EXTENSION_EXPORT - const int sapi_process_spawn_wait ( + int sapi_process_spawn_wait ( const sapi_process_spawn_t* process ); SOCKET_RUNTIME_EXTENSION_EXPORT - const bool sapi_process_spawn_write ( + bool sapi_process_spawn_write ( const sapi_process_spawn_t* process, const char* bytes, - const unsigned long size + unsigned long size ); SOCKET_RUNTIME_EXTENSION_EXPORT - const bool sapi_process_spawn_close_stdin ( + bool sapi_process_spawn_close_stdin ( const sapi_process_spawn_t* process ); @@ -1244,9 +1244,9 @@ extern "C" { * @return TODO */ SOCKET_RUNTIME_EXTENSION_EXPORT - const bool sapi_process_spawn_kill ( + bool sapi_process_spawn_kill ( sapi_process_spawn_t* process, - const int code + int code ); /** From 0a4a065ff765ddb739b95b3de153a7fe464e45fe Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:21:15 +0200 Subject: [PATCH 13/42] chore(src/desktop/main.cc): clean up --- src/desktop/main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/desktop/main.cc b/src/desktop/main.cc index d8f2ba52a..03319a0f8 100644 --- a/src/desktop/main.cc +++ b/src/desktop/main.cc @@ -431,13 +431,13 @@ MAIN { createProcess(force); process->open(); } -#ifdef _WIN32 + #ifdef _WIN32 size_t last_pos = 0; while ((last_pos = process->path.find('\\', last_pos)) != std::string::npos) { process->path.replace(last_pos, 1, "\\\\\\\\"); last_pos += 4; } -#endif + #endif const JSON::Object json = JSON::Object::Entries { { "cmd", cmd }, { "argv", process->argv }, From 6d35ec589b1c8390dec3fe1331c665b35da09a70 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:21:40 +0200 Subject: [PATCH 14/42] chore(src/extension/context.cc): remove 'const' for scalar types --- src/extension/context.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extension/context.cc b/src/extension/context.cc index 79120e304..713394ae0 100644 --- a/src/extension/context.cc +++ b/src/extension/context.cc @@ -2,7 +2,7 @@ sapi_context_t* sapi_context_create ( sapi_context_t* parent, - const bool retained + bool retained ) { if (parent && !parent->isAllowed("context_create")) { sapi_debug(parent, "'context_create' is not allowed."); @@ -115,14 +115,14 @@ void sapi_context_error_reset (sapi_context_t* context) { void sapi_context_error_set_code ( sapi_context_t* context, - const int code + int code ) { if (context == nullptr) return; context->error.code = code; context->state = SSC::Extension::Context::State::Error; } -const int sapi_context_error_get_code (const sapi_context_t* context) { +int sapi_context_error_get_code (const sapi_context_t* context) { if (context == nullptr) return -1; return context->error.code; } From 76b1250de83913a8d34752bf8f0fd4f7504f197e Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:22:01 +0200 Subject: [PATCH 15/42] chore(src/extension/extension.cc): remove 'const' for scalar types --- src/extension/extension.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/extension.cc b/src/extension/extension.cc index a844c2e51..0c0c41051 100644 --- a/src/extension/extension.cc +++ b/src/extension/extension.cc @@ -73,7 +73,7 @@ namespace SSC { template sapi_json_boolean_t* SSC::Extension::Context::Memory::alloc ( sapi_context_t*, - const bool + bool ); template sapi_json_number_t* From c4a48640fb1e52c3d6156654a8a1889e4706577a Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:22:23 +0200 Subject: [PATCH 16/42] refactor(src/extension/ipc.cc): 'nullptr' check, return 'false' on failure --- src/extension/ipc.cc | 54 ++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/extension/ipc.cc b/src/extension/ipc.cc index ab15dbe22..3329f7b63 100644 --- a/src/extension/ipc.cc +++ b/src/extension/ipc.cc @@ -1,6 +1,6 @@ #include "extension.hh" -void sapi_ipc_router_map ( +bool sapi_ipc_router_map ( sapi_context_t* ctx, const char* name, sapi_ipc_router_message_callback_t callback, @@ -11,51 +11,57 @@ void sapi_ipc_router_map ( ctx->router == nullptr || ctx->state > SSC::Extension::Context::State::Init ) { - return; + return false; } if (!ctx->isAllowed("ipc_router_map")) { sapi_debug(ctx, "'ipc_router_map' is not allowed."); - return; + return false; } - sapi_context_t context(ctx); auto router = ctx->router; - ctx->router->map(name, [data, callback, context]( - auto& message, + auto context = sapi_context_create(ctx, true); + + if (context == nullptr) { + return false; + } + + ctx->data = data; + ctx->router->map(name, [context, data, callback]( + auto message, auto router, auto reply - ) { - router->dispatch([=]() mutable { - auto ctx = sapi_context_create(&context, true); - ctx->data = data; + ) mutable { auto msg = SSC::IPC::Message( message.uri, true, // decode parameter values AOT in `message.uri` message.buffer.bytes, message.buffer.size ); - ctx->internal = ctx->memory.alloc(reply); + context->internal = context->memory.alloc(reply); callback( - ctx, + context, (sapi_ipc_message_t*) &msg, reinterpret_cast(&router) ); - }); }); + + return true; } -void sapi_ipc_router_unmap (sapi_context_t* ctx, const char* name) { +bool sapi_ipc_router_unmap (sapi_context_t* ctx, const char* name) { if (ctx == nullptr || ctx->router == nullptr) { - return; + return false; } if (!ctx->isAllowed("ipc_router_unmap")) { sapi_debug(ctx, "'ipc_router_unmap' is not allowed."); - return; + return false; } ctx->router->unmap(name); + + return true; } uint64_t sapi_ipc_router_listen ( @@ -139,8 +145,8 @@ bool sapi_ipc_reply (const sapi_ipc_result_t* result) { bool sapi_ipc_send_bytes ( sapi_context_t* ctx, const char* seq, - const unsigned int size, - const unsigned char* bytes, + unsigned int size, + unsigned char* bytes, const char* headers ) { if (ctx == nullptr || ctx->router == nullptr || bytes == nullptr || size == 0) { @@ -258,7 +264,7 @@ sapi_ipc_result_t* sapi_ipc_result_create ( return result; } -const int sapi_ipc_message_get_index (const sapi_ipc_message_t* message) { +int sapi_ipc_message_get_index (const sapi_ipc_message_t* message) { return message ? message->index : -1; } @@ -441,8 +447,8 @@ const sapi_json_any_t* sapi_ipc_result_get_json_error ( void sapi_ipc_result_set_bytes ( sapi_ipc_result_t* result, - const unsigned int size, - const unsigned char* bytes + unsigned int size, + unsigned char* bytes ) { if (result && size && bytes) { auto pointer = const_cast(reinterpret_cast(bytes)); @@ -451,15 +457,15 @@ void sapi_ipc_result_set_bytes ( } } -const unsigned char* sapi_ipc_result_get_bytes ( +unsigned char* sapi_ipc_result_get_bytes ( const sapi_ipc_result_t* result ) { return result - ? reinterpret_cast(result->post.body) + ? reinterpret_cast(result->post.body) : nullptr; } -const unsigned int sapi_ipc_result_get_bytes_size ( +unsigned int sapi_ipc_result_get_bytes_size ( const sapi_ipc_result_t* result ) { return result ? result->post.length : 0; From 796f95db41edd2de9cf2f7a2bc2f794f73ddcef0 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:22:53 +0200 Subject: [PATCH 17/42] refactor(src/extension): remove 'const' for scalar types --- src/extension/extension.hh | 4 ++-- src/extension/json.cc | 6 +++--- src/extension/process.cc | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/extension/extension.hh b/src/extension/extension.hh index e3099e486..1a0507e4a 100644 --- a/src/extension/extension.hh +++ b/src/extension/extension.hh @@ -227,10 +227,10 @@ extern "C" { struct sapi_json_boolean : public SSC::JSON::Boolean { sapi_context_t* context = nullptr; sapi_json_boolean () = default; - sapi_json_boolean (const bool boolean) + sapi_json_boolean (bool boolean) : SSC::JSON::Boolean(boolean) {} - sapi_json_boolean (sapi_context_t* ctx, const bool boolean) + sapi_json_boolean (sapi_context_t* ctx, bool boolean) : context(ctx), SSC::JSON::Boolean(boolean) {} }; diff --git a/src/extension/json.cc b/src/extension/json.cc index 84302fc6e..418e4e150 100644 --- a/src/extension/json.cc +++ b/src/extension/json.cc @@ -29,7 +29,7 @@ sapi_json_string_t* sapi_json_string_create ( sapi_json_boolean_t* sapi_json_boolean_create ( sapi_context_t* ctx, - const bool boolean + bool boolean ) { return ctx->memory.alloc(ctx, boolean); } @@ -142,7 +142,7 @@ sapi_json_any_t* sapi_json_object_get ( void sapi_json_array_set ( sapi_json_array_t* json, - const unsigned int index, + unsigned int index, sapi_json_any_t* any ) { if (json == nullptr || any == nullptr) return; @@ -205,7 +205,7 @@ void sapi_json_array_push ( sapi_json_any_t* sapi_json_array_get ( const sapi_json_array_t* json, - const unsigned int index + unsigned int index ) { if (json->has(index)) { auto pointer = json->data.at(index).pointer.get(); diff --git a/src/extension/process.cc b/src/extension/process.cc index c83e6aeba..e3d01e262 100644 --- a/src/extension/process.cc +++ b/src/extension/process.cc @@ -20,12 +20,12 @@ const sapi_process_exec_t* sapi_process_exec ( return ctx->memory.alloc(ctx, process); } -const int sapi_process_exec_get_exit_code ( +int sapi_process_exec_get_exit_code ( const sapi_process_exec_t* process ) { #if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) debug("sapi_process_exec_get_exit_code is not supported on this platform"); - return -1 + return -1; #endif return process != nullptr ? process->exitCode : -1; @@ -69,7 +69,7 @@ sapi_process_spawn_t* sapi_process_spawn ( return process; } -const int sapi_process_spawn_get_exit_code ( +int sapi_process_spawn_get_exit_code ( const sapi_process_spawn_t* process ) { #if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) @@ -79,7 +79,7 @@ const int sapi_process_spawn_get_exit_code ( return process != nullptr ? process->status.load() : -1; } -const unsigned long sapi_process_spawn_get_pid ( +unsigned long sapi_process_spawn_get_pid ( const sapi_process_spawn_t* process ) { #if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) @@ -99,7 +99,7 @@ sapi_context_t* sapi_process_spawn_get_context ( return process != nullptr ? process->context : nullptr; } -const int sapi_process_spawn_wait ( +int sapi_process_spawn_wait ( sapi_process_spawn_t* process ) { #if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) @@ -109,7 +109,7 @@ const int sapi_process_spawn_wait ( return process != nullptr ? process->wait() : -1; } -const bool sapi_process_spawn_write ( +bool sapi_process_spawn_write ( sapi_process_spawn_t* process, const char* data, const size_t size @@ -123,7 +123,7 @@ const bool sapi_process_spawn_write ( return true; } -const bool sapi_process_spawn_close_stdin ( +bool sapi_process_spawn_close_stdin ( sapi_process_spawn_t* process ) { #if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) @@ -135,9 +135,9 @@ const bool sapi_process_spawn_close_stdin ( return true; } -const bool sapi_process_spawn_kill ( +bool sapi_process_spawn_kill ( sapi_process_spawn_t* process, - const int code + int code ) { #if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) debug("sapi_process_spawn_kill is not supported on this platform"); From 35c7feace3f576b60793345076f08f83d501823d Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:23:11 +0200 Subject: [PATCH 18/42] refactor(test/src/application.js): handle '#' comments --- test/src/application.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/src/application.js b/test/src/application.js index 5c569fc20..398a907fd 100644 --- a/test/src/application.js +++ b/test/src/application.js @@ -52,12 +52,17 @@ if (!['android', 'ios'].includes(process.platform)) { const config = [] for (let line of lines) { line = line.trim() - if (line.length === 0 || line.startsWith(';')) continue + let [key, value] = line.split('=') + + if (line.length === 0 || line.startsWith(';') || line.startsWith('#')) { + continue + } + if (line.startsWith('[') && line.endsWith(']')) { prefix = line.slice(1, -1) continue } - let [key, value] = line.split('=') + key = key.trim() value = value.trim().replace(/^"/, '').replace(/"$/, '').replace('.') config.push([prefix.length === 0 ? key : prefix + '_' + key, value]) From c704dac5c71fb145e511575121a587522e5017ac Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 14:23:40 +0200 Subject: [PATCH 19/42] test(test/extension): use 'socket.ini' for extension --- test/socket.ini | 26 +-------------------- test/src/extensions/feature-policies.js | 2 +- test/src/extensions/simple/ipc-ping.cc | 4 ++-- test/src/extensions/sqlite3/socket.ini | 30 +++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 28 deletions(-) create mode 100644 test/src/extensions/sqlite3/socket.ini diff --git a/test/socket.ini b/test/socket.ini index 16aa46497..de011af7e 100644 --- a/test/socket.ini +++ b/test/socket.ini @@ -20,31 +20,7 @@ env[] = SOCKET_MODULE_PATH_PREFIX [build.extensions] simple-ipc-ping = src/extensions/simple/ipc-ping.cc -sqlite3[] = src/extensions/sqlite3/extension.cc -sqlite3[] = build/sqlite3/sqlite3.h -sqlite3[] = build/sqlite3/sqlite3.c - -[build.extensions.sqlite3.compiler] -flags[] = -DSQLITE_ENABLE_COLUMN_METADATA -flags[] = -DDSQLITE_ENABLE_SESSION -flags[] = -DSQLITE_ENABLE_RTREE -flags[] = -DSQLITE_ENABLE_FTS4 -flags[] = -DSQLITE_DQS=0 -flags[] = -lpthread -lm -ldl -flags[] = -Ibuild/sqlite3 -flags[] = -Os - -[build.extensions.sqlite3.win.compiler] -flags[] = -DWIN64 -flags[] = -DNDEBUG -flags[] = -D_WINDOWS -flags[] = -D_USRDLL -flags[] = -DNO_TCL -flags[] = -D_CRT_SECURE_NO_DEPRECATE -flags[] = -DTHREADSAFE=1 -flags[] = -DTEMP_STORE=1 -flags[] = -DSQLITE_MAX_EXPR_DEPTH=0 -flags[] = -m64 +sqlite3 = src/extensions/sqlite3 ; Injected environment variables [env] diff --git a/test/src/extensions/feature-policies.js b/test/src/extensions/feature-policies.js index aa765cd43..f1bec2c95 100644 --- a/test/src/extensions/feature-policies.js +++ b/test/src/extensions/feature-policies.js @@ -30,7 +30,7 @@ test('extension.load(name) - feature policies', async (t) => { await simple.unload() try { - simple = await extension.load('simple-ipc-ping', { allow: ['ipc'] }) + simple = await extension.load('simple-ipc-ping', { allow: ['context', 'ipc'] }) } catch (err) { return t.ifError(err) } diff --git a/test/src/extensions/simple/ipc-ping.cc b/test/src/extensions/simple/ipc-ping.cc index 2ac78dfbb..0b02baa76 100644 --- a/test/src/extensions/simple/ipc-ping.cc +++ b/test/src/extensions/simple/ipc-ping.cc @@ -15,14 +15,14 @@ void onping ( } bool initialize (sapi_context_t* context, const void *data) { - if (sapi_extension_is_allowed(context, "ipc,ipc_router,ipc_router_map")) { + if (sapi_extension_is_allowed(context, "ipc_router_map")) { sapi_ipc_router_map(context, "simple.ping", onping, data); } return true; } bool deinitialize (sapi_context_t* context, const void *data) { - if (sapi_extension_is_allowed(context, "ipc,ipc_router,ipc_router_unmap")) { + if (sapi_extension_is_allowed(context, "ipc_router_unmap")) { sapi_ipc_router_unmap(context, "simple.ping"); } return true; diff --git a/test/src/extensions/sqlite3/socket.ini b/test/src/extensions/sqlite3/socket.ini new file mode 100644 index 000000000..cd85a9dc0 --- /dev/null +++ b/test/src/extensions/sqlite3/socket.ini @@ -0,0 +1,30 @@ +[meta] +name = "sqlite3" +type = "extension" + +[extension] +sources[] = ./extension.cc +sources[] = ../../../build/sqlite3/sqlite3.h +sources[] = ../../../build/sqlite3/sqlite3.c + +[.compiler] +flags[] = -DSQLITE_ENABLE_COLUMN_METADATA +flags[] = -DDSQLITE_ENABLE_SESSION +flags[] = -DSQLITE_ENABLE_RTREE +flags[] = -DSQLITE_ENABLE_FTS4 +flags[] = -DSQLITE_DQS=0 +flags[] = -lpthread -lm -ldl +flags[] = -I../../../build/sqlite3 +flags[] = -Os + +[.win.compiler] +flags[] = -DWIN64 +flags[] = -DNDEBUG +flags[] = -D_WINDOWS +flags[] = -D_USRDLL +flags[] = -DNO_TCL +flags[] = -D_CRT_SECURE_NO_DEPRECATE +flags[] = -DTHREADSAFE=1 +flags[] = -DTEMP_STORE=1 +flags[] = -DSQLITE_MAX_EXPR_DEPTH=0 +flags[] = -m64 From 38b589045f8340ad9e4564cbb9a5fc1bd6e5bc8f Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Mon, 10 Jul 2023 15:47:20 +0200 Subject: [PATCH 20/42] refactor(src/cli): fix extension source for android --- src/cli/cli.cc | 74 ++++++++++++++++++++++++++++++++++++++++++-------- src/common.hh | 4 ++- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 28be9f260..0ca252bb0 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2934,6 +2934,7 @@ int main (const int argc, const char* argv[]) { if (key.starts_with("build_extensions_linux_")) continue; if (key.starts_with("build_extensions_win_")) continue; if (key.starts_with("build_extensions_ios_")) continue; + if (key.ends_with("_path")) continue; String extension; if (key.starts_with("build_extensions_android")) { @@ -2945,6 +2946,13 @@ int main (const int argc, const char* argv[]) { extension = split(extension, '_')[0]; auto source = settings["build_extensions_" + extension + "_source"]; + auto oldCwd = fs::current_path(); + fs::current_path(targetPath); + + if (source.size() == 0 && fs::is_directory(settings["build_extensions_" + extension])) { + source = settings["build_extensions_" + extension]; + settings["build_extensions_" + extension] = ""; + } if (source.size() > 0) { Path target; @@ -3023,6 +3031,7 @@ int main (const int argc, const char* argv[]) { std::unordered_set cppflags; if (path.size() > 0) { + fs::current_path(targetPath); fs::current_path(path); } else { fs::current_path(targetPath); @@ -3051,18 +3060,27 @@ int main (const int argc, const char* argv[]) { } } - for (auto source : parseStringList(tuple.second, ' ')) { + for ( + auto source : parseStringList( + trim(settings["build_extensions_" + extension] + " " + settings["build_extensions_" + extension + "_android"]), + ' ' + ) + ) { + if (!fs::is_regular_file(source)) { + continue; + } + auto destination= ( Path(source).parent_path() / Path(source).filename().string() ).string(); if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { - log("source: " + source); + log("extension source: " + source); } fs::create_directories(jni / Path(destination).parent_path()); - fs::copy(cwd / source, jni / destination, fs::copy_options::overwrite_existing); + fs::copy(source, jni / destination, fs::copy_options::overwrite_existing); if (destination.ends_with(".hh") || destination.ends_with(".h")) { continue; @@ -3076,6 +3094,8 @@ int main (const int argc, const char* argv[]) { sources << destination << " "; } + fs::current_path(oldCwd); + make << "## socket/extensions/" << extension << SHARED_OBJ_EXT << std::endl; make << "include $(CLEAR_VARS)" << std::endl; make << "LOCAL_MODULE := extension-" << extension << std::endl; @@ -3387,6 +3407,7 @@ int main (const int argc, const char* argv[]) { if (key.starts_with("build_extensions_linux_")) continue; if (key.starts_with("build_extensions_win_")) continue; if (key.starts_with("build_extensions_android_")) continue; + if (key.ends_with("_path")) continue; String extension; if (key.starts_with("build_extensions_ios")) { @@ -3397,6 +3418,11 @@ int main (const int argc, const char* argv[]) { auto source = settings["build_extensions_" + extension + "_source"]; + if (source.size() == 0 && fs::is_directory(settings["build_extensions_" + extension])) { + source = settings["build_extensions_" + extension]; + settings["build_extensions_" + extension] = ""; + } + if (source.size() > 0) { Path target; if (fs::exists(source)) { @@ -3431,12 +3457,15 @@ int main (const int argc, const char* argv[]) { } } - auto configure = settings["build_extensions_" + extension + "_configure_script"]; auto build = settings["build_extensions_" + extension + "_build_script"]; auto path = settings["build_extensions_" + extension + "_path"]; - auto sources = parseStringList(tuple.second, ' '); + auto sources = parseStringList( + trim(settings["build_extensions_" + extension] + " " + settings["build_extensions_" + extension + "_ios"]), + ' ' + ); + auto objects = StringStream(); auto libdir = platform.arch == "arm64" ? prefixFile(String("lib/arm64-") + (flagBuildForSimulator ? "iPhoneSimulator" : "iPhoneOS")) @@ -3447,6 +3476,13 @@ int main (const int argc, const char* argv[]) { extensions.push_back(extension); } + if (path.size() > 0) { + fs::current_path(targetPath); + fs::current_path(path); + } else { + fs::current_path(targetPath); + } + if (build.size() > 0) { auto exitCode = std::system((build + argvForward).c_str()); if (exitCode) { @@ -3468,6 +3504,10 @@ int main (const int argc, const char* argv[]) { } for (const auto& source : sources) { + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("extension source: " + source); + } + String compiler; auto compilerFlags = ( @@ -3577,6 +3617,8 @@ int main (const int argc, const char* argv[]) { linkerFlags += " -arch arm64 "; } + auto lib = (paths.pathResourcesRelativeToUserBuild / "socket" / "extensions" / extension / (extension + SHARED_OBJ_EXT)); + fs::create_directories(lib.parent_path()); auto compileExtensionLibraryCommand = StringStream(); compileExtensionLibraryCommand << "xcrun -sdk " << (flagBuildForSimulator ? "iphonesimulator" : "iphoneos") @@ -3605,7 +3647,7 @@ int main (const int argc, const char* argv[]) { << " -shared" << " -v" << " " << trim(linkerFlags + " " + (flagDebugMode ? linkerDebugFlags : "")) - << " -o " << (paths.pathResourcesRelativeToUserBuild / "socket" / "extensions" / extension / (extension + SHARED_OBJ_EXT)) + << " -o " << lib ; if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { @@ -3629,7 +3671,6 @@ int main (const int argc, const char* argv[]) { } } - auto lib = (paths.pathResourcesRelativeToUserBuild / "socket" / "extensions" / extension / (extension + SHARED_OBJ_EXT)); // mostly random build IDs and refs auto id = String("17D835592A262D7900") + std::to_string(rand64()).substr(0, 6); auto ref = String("17D835592A262D7900") + std::to_string(rand64()).substr(0, 6); @@ -4215,6 +4256,7 @@ int main (const int argc, const char* argv[]) { if (key.find("configure_script") != String::npos) continue; if (key.starts_with("build_extensions_ios_")) continue; if (key.starts_with("build_extensions_android_")) continue; + if (key.ends_with("_path")) continue; if (!platform.win && key.starts_with("build_extensions_win_")) continue; if (!platform.mac && key.starts_with("build_extensions_mac_")) continue; @@ -4232,6 +4274,11 @@ int main (const int argc, const char* argv[]) { auto source = settings["build_extensions_" + extension + "_source"]; + if (source.size() == 0 && fs::is_directory(settings["build_extensions_" + extension])) { + source = settings["build_extensions_" + extension]; + settings["build_extensions_" + extension] = ""; + } + if (source.size() > 0) { Path target; if (fs::exists(source)) { @@ -4281,6 +4328,7 @@ int main (const int argc, const char* argv[]) { fs::create_directories(lib.parent_path()); if (path.size() > 0) { + fs::current_path(targetPath); fs::current_path(path); } else { fs::current_path(targetPath); @@ -4307,7 +4355,7 @@ int main (const int argc, const char* argv[]) { } if (std::find(extensions.begin(), extensions.end(), extension) == extensions.end()) { - log("Building extension: " + extension + " ((" + platform.os + ") desktop-" + platform.arch + ")"); + log("Building extension: " + extension + " (" + platform.os + "-" + platform.arch + ")"); extensions.push_back(extension); } @@ -4316,6 +4364,10 @@ int main (const int argc, const char* argv[]) { ); for (auto source : sources) { + if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { + log("extension source: " + source); + } + auto compilerFlags = ( settings["build_extensions_compiler_flags"] + " " + settings["build_extensions_" + os + "_compiler_flags"] + " " + @@ -4382,7 +4434,7 @@ int main (const int argc, const char* argv[]) { } if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { - log("source: " + source); + log("extension source: " + source); } auto object = Path(replace(replace(source, "\\.cc", ".o"), "\\.c", ".o")); @@ -4507,7 +4559,6 @@ int main (const int argc, const char* argv[]) { #endif auto compileExtensionLibraryCommand = StringStream(); - compileExtensionLibraryCommand << quote // win32 - quote the entire command << quote // win32 - quote the binary path @@ -4527,8 +4578,6 @@ int main (const int argc, const char* argv[]) { #else << " " << flags << " " << extraFlags - << " -lsocket-runtime" - << " -luv" << " -fvisibility=hidden" << (" -L" + quote + trim(prefixFile("lib/" + platform.arch + "-desktop")) + quote) #endif @@ -4556,6 +4605,7 @@ int main (const int argc, const char* argv[]) { log(compileExtensionLibraryCommand.str()); } + fs::create_directories(lib.parent_path()); do { auto r = exec(compileExtensionLibraryCommand.str()); diff --git a/src/common.hh b/src/common.hh index debd3292c..81f4a043a 100644 --- a/src/common.hh +++ b/src/common.hh @@ -998,7 +998,9 @@ namespace SSC { auto list = Vector(); for (const auto& separator : separators) { for (const auto& part: split(string, separator)) { - list.push_back(part); + if (std::find(list.begin(), list.end(), part) == list.end()) { + list.push_back(part); + } } } From f018d2f134cc1f1a523d53736eb28ccc3a7ca81a Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:25:36 +0200 Subject: [PATCH 21/42] fix(src/extension/ipc.cc): fix context data --- src/extension/ipc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extension/ipc.cc b/src/extension/ipc.cc index 3329f7b63..f418f5991 100644 --- a/src/extension/ipc.cc +++ b/src/extension/ipc.cc @@ -26,9 +26,9 @@ bool sapi_ipc_router_map ( return false; } - ctx->data = data; + context->data = data; ctx->router->map(name, [context, data, callback]( - auto message, + auto& message, auto router, auto reply ) mutable { From 5c653b1fba02e86027a42e754ec218c73d1563a5 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:25:50 +0200 Subject: [PATCH 22/42] feat(src/common.hh): support default value in 'getEnv' --- src/common.hh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common.hh b/src/common.hh index 81f4a043a..375b952cd 100644 --- a/src/common.hh +++ b/src/common.hh @@ -608,6 +608,15 @@ namespace SSC { return getEnv(variableName.c_str()); } + inline String getEnv (const String& variableName, const String& defaultValue) { + const auto value = getEnv(variableName); + if (value.size() == 0) { + return defaultValue; + } + + return value; + } + inline auto setEnv (const String& k, const String& v) { #if _WIN32 return _putenv((k + "=" + v).c_str()); From 837caf93af8196724cad6d032835e0f8c9baebc4 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:26:12 +0200 Subject: [PATCH 23/42] refactor(bin/android-functions.sh): remove ABIs not worth supporting --- bin/android-functions.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/bin/android-functions.sh b/bin/android-functions.sh index f9474a683..0c4977bf8 100755 --- a/bin/android-functions.sh +++ b/bin/android-functions.sh @@ -479,8 +479,6 @@ function android_supported_abis() { else local abis=( "arm64-v8a" - "armeabi-v7a" - "x86" "x86_64" ) From 8c319d4bf0089f6ac7213ed19ba4d11a4f556a37 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:26:30 +0200 Subject: [PATCH 24/42] refactor(src/cli/templates.hh): remove useless src addition --- src/cli/templates.hh | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cli/templates.hh b/src/cli/templates.hh index 0150423c5..06a326cf3 100644 --- a/src/cli/templates.hh +++ b/src/cli/templates.hh @@ -1186,8 +1186,6 @@ LOCAL_SRC_FILES = \ android/window.cc \ init.cc -LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/src/*.cc) - LOCAL_STATIC_LIBRARIES := \ libuv \ libsocket-runtime-static From 624dfbc87f364daa779f111007212fec81b07e43 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:27:45 +0200 Subject: [PATCH 25/42] fix(src/cli/cli.cc): improve building android extensions --- src/cli/cli.cc | 205 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 161 insertions(+), 44 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 0ca252bb0..abbaa0e79 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -1712,7 +1712,7 @@ int main (const int argc, const char* argv[]) { } // only validate if config exists and we didn't exit early above - if (configExists) { + if (configExists && !equal(subcommand, "init") && !equal(subcommand, "env")) { // Check if build_name is set if (settings.count("build_name") == 0) { log("ERROR: 'name' value is required in socket.ini in the [build] section"); @@ -2408,7 +2408,7 @@ int main (const int argc, const char* argv[]) { if ( targetPlatform.starts_with("android") && - settings.count("build_ios_copy_map") != 0 + settings.count("build_android_copy_map") != 0 ) { auto copyMapFile = Path{settings["build_android_copy_map"]}.make_preferred(); @@ -2419,10 +2419,7 @@ int main (const int argc, const char* argv[]) { copyMapFiles.push_back(copyMapFile); } - if ( - settings.count("build_" + platform.os + "_copy_map") != 0 && - settings.count("build_ios_copy_map") != 0 - ) { + if (settings.count("build_" + platform.os + "_copy_map") != 0) { auto copyMapFile = Path{settings["build_" + platform.os + "_copy_map"]}.make_preferred(); if (copyMapFile.is_relative()) { @@ -2902,13 +2899,13 @@ int main (const int argc, const char* argv[]) { if (settings["android_native_abis"].size() > 0) { makefileContext["android_native_abis"] = settings["android_native_abis"]; } else { - makefileContext["android_native_abis"] = "all"; + makefileContext["android_native_abis"] = "arm64-v8a x86_64"; } // custom native sources for ( auto const &file : - parseStringList(settings["android_native_sources"]) + parseStringList(settings["android_native_sources"], ' ') ) { auto filename = Path(file).filename(); writeFile( @@ -2982,7 +2979,12 @@ int main (const int argc, const char* argv[]) { } else if (entry.first.starts_with("extension_")) { auto key = replace(entry.first, "extension_", extension + "_"); auto value = entry.second; - settings["build_extensions_" + key] = value; + auto index = "build_extensions_" + key; + if (settings[index].size() > 0) { + settings[index] += " " + value; + } else { + settings[index] = value; + } } } } @@ -3006,22 +3008,27 @@ int main (const int argc, const char* argv[]) { "-I$(LOCAL_PATH)/" ); - auto linkerFlags = ( + auto linkerFlags = replace( settings["build_extensions_linker_flags"] + " " + settings["build_extensions_android_linker_flags"] + " " + settings["build_extensions_" + extension + "_linker_flags"] + " " + - settings["build_extensions_" + extension + "_android_linker_flags"] + " " + settings["build_extensions_" + extension + "_android_linker_flags"] + " ", + "-I", + "-I$(LOCAL_PATH)/" ); - auto linkerDebugFlags = ( + auto linkerDebugFlags = replace( settings["build_extensions_linker_debug_flags"] + " " + settings["build_extensions_android_linker_debug_flags"] + " " + settings["build_extensions_" + extension + "_linker_debug_flags"] + " " + - settings["build_extensions_" + extension + "_android_linker_debug_flags"] + " " + settings["build_extensions_" + extension + "_android_linker_debug_flags"] + " ", + "-I", + "-I$(LOCAL_PATH)/" ); auto configure = settings["build_extensions_" + extension + "_configure_script"]; auto build = settings["build_extensions_" + extension + "_build_script"]; + auto copy = settings["build_extensions_" + extension + "_build_copy"]; auto path = settings["build_extensions_" + extension + "_path"]; auto sources = StringStream(); @@ -3048,29 +3055,47 @@ int main (const int argc, const char* argv[]) { auto output = replace(exec(configure + argvForward).output, "\n", " "); if (output.size() > 0) { for (const auto& source : parseStringList(output, ' ')) { - auto destination= ( - Path(source).parent_path() / - Path(source).filename().string() - ).string(); - - fs::create_directories(jni / Path(destination).parent_path()); - fs::copy(cwd / source, jni / destination, fs::copy_options::overwrite_existing); - sources << source << " "; + auto destination = fs::absolute(targetPath / source); + sources << destination.string() << " "; } } } + if (copy.size() > 0) { + auto pathResources = paths.pathResourcesRelativeToUserBuild; + for (const auto& file : parseStringList(copy, ' ')) { + auto parts = split(file, ':'); + auto target = parts[0]; + auto destination = parts.size() == 2 ? pathResources / parts[1] : pathResources; + fs::create_directories(destination.parent_path()); + fs::copy( + target, + destination, + fs::copy_options::update_existing | fs::copy_options::recursive + ); + } + } + for ( auto source : parseStringList( trim(settings["build_extensions_" + extension] + " " + settings["build_extensions_" + extension + "_android"]), ' ' ) ) { - if (!fs::is_regular_file(source)) { + if (fs::is_directory(source)) { + auto target = Path(source).filename(); + fs::create_directories(jni / target); + fs::copy( + source, + jni / target, + fs::copy_options::update_existing | fs::copy_options::recursive + ); + continue; + } else if (!fs::is_regular_file(source)) { continue; } - auto destination= ( + auto destination = ( Path(source).parent_path() / Path(source).filename().string() ).string(); @@ -3096,6 +3121,34 @@ int main (const int argc, const char* argv[]) { fs::current_path(oldCwd); + Vector libs; + auto archs = settings["android_native_abis"]; + + if (archs.size() == 0) { + archs = "arm64-v8a x86_64"; + } + + for (const auto& source : parseStringList(sources.str(), ' ')) { + if (source.ends_with(".a")) { + auto name = replace(Path(source).filename().string(), ".a", ""); + for (const auto& arch : parseStringList(archs, ' ')) { + if (source.find(arch) != -1) { + fs::create_directories(jni / ".." / "libs" / arch); + fs::copy(source, jni / ".." / "libs" / arch / Path(source).filename(), fs::copy_options::overwrite_existing); + } + } + + if (std::find(libs.begin(), libs.end(), name) == libs.end()) { + libs.push_back(name); + make << "## " << Path(source).filename().string() << std::endl; + make << "include $(CLEAR_VARS)" << std::endl; + make << "LOCAL_MODULE := " << name << std::endl; + make << "LOCAL_SRC_FILES = ../libs/$(TARGET_ARCH_ABI)/" << Path(source).filename().string() << std::endl; + make << "include $(PREBUILT_STATIC_LIBRARY)" << std::endl; + } + } + } + make << "## socket/extensions/" << extension << SHARED_OBJ_EXT << std::endl; make << "include $(CLEAR_VARS)" << std::endl; make << "LOCAL_MODULE := extension-" << extension << std::endl; @@ -3159,9 +3212,24 @@ int main (const int argc, const char* argv[]) { } make << std::endl; - make << "LOCAL_LDLIBS := -landroid -llog" << std::endl; - make << "LOCAL_WHOLE_STATIC_LIBRARIES := libuv libsocket-runtime-static" << std::endl; - make << "LOCAL_SRC_FILES = init.cc " << sources.str() << std::endl; + make << "LOCAL_LDLIBS += -landroid -llog" << std::endl; + + for (const auto& lib : libs) { + make << "LOCAL_STATIC_LIBRARIES += " << lib << std::endl; + } + make << std::endl; + + make << "LOCAL_STATIC_LIBRARIES += libuv libsocket-runtime-static" << std::endl; + make << "LOCAL_SRC_FILES = init.cc" << std::endl; + + for (const auto& source : parseStringList(sources.str(), ' ')) { + if (source.ends_with(".c") || source.ends_with(".cc") || source.ends_with(".mm") || source.ends_with(".m")) { + make << "LOCAL_SRC_FILES += " << source << std::endl; + } + } + + make << std::endl; + make << "include $(BUILD_SHARED_LIBRARY)" << std::endl; make << std::endl; @@ -3416,6 +3484,8 @@ int main (const int argc, const char* argv[]) { extension = replace(key, "build_extensions_", ""); } + extension = split(extension, '_')[0]; + auto source = settings["build_extensions_" + extension + "_source"]; if (source.size() == 0 && fs::is_directory(settings["build_extensions_" + extension])) { @@ -3451,7 +3521,12 @@ int main (const int argc, const char* argv[]) { } else if (entry.first.starts_with("extension_")) { auto key = replace(entry.first, "extension_", extension + "_"); auto value = entry.second; - settings["build_extensions_" + key] = value; + auto index = "build_extensions_" + key; + if (settings[index].size() > 0) { + settings[index] += " " + value; + } else { + settings[index] = value; + } } } } @@ -3459,6 +3534,7 @@ int main (const int argc, const char* argv[]) { auto configure = settings["build_extensions_" + extension + "_configure_script"]; auto build = settings["build_extensions_" + extension + "_build_script"]; + auto copy = settings["build_extensions_" + extension + "_build_copy"]; auto path = settings["build_extensions_" + extension + "_path"]; auto sources = parseStringList( @@ -3494,15 +3570,25 @@ int main (const int argc, const char* argv[]) { auto output = replace(exec(configure + argvForward).output, "\n", " "); if (output.size() > 0) { for (const auto& source : parseStringList(output, ' ')) { - if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { - log("configure: " + source); - } - sources.push_back(source); } } } + if (copy.size() > 0) { + auto pathResources = paths.platformSpecificOutputPath / "ui"; + for (const auto& file : parseStringList(copy, ' ')) { + auto parts = split(file, ':'); + auto target = parts[0]; + auto destination = parts.size() == 2 ? pathResources / parts[1] : pathResources; + fs::copy( + target, + destination, + fs::copy_options::update_existing | fs::copy_options::recursive + ); + } + } + for (const auto& source : sources) { if (getEnv("DEBUG") == "1" || getEnv("VERBOSE") == "1") { log("extension source: " + source); @@ -3577,8 +3663,11 @@ int main (const int argc, const char* argv[]) { << " -DPORT=" << devPort << " -DSSC_VERSION=" << SSC::VERSION_STRING << " -DSSC_VERSION_HASH=" << SSC::VERSION_HASH_STRING + << " -target " << (flagBuildForSimulator ? platform.arch + "-apple-ios-simulator": "arm64-apple-ios") + << " -fembed-bitcode" << " -fPIC" << " " << trim(compilerFlags + " " + (flagDebugMode ? compilerDebugFlags : "")) + << " " << (flagBuildForSimulator ? "-mios-simulator-version-min=" : "-miphoneos-version-min=") + getEnv("IPHONEOS_VERSION_MIN", "14.0") << " -c " << source << " -o " << object.string() ; @@ -3642,10 +3731,13 @@ int main (const int argc, const char* argv[]) { << " -framework UserNotifications" << " -framework WebKit" << " -framework UIKit" + << " -fembed-bitcode" << " -std=c++2a" << " -ObjC++" << " -shared" << " -v" + << " -target " << (flagBuildForSimulator ? platform.arch + "-apple-ios-simulator": "arm64-apple-ios") + << " " << (flagBuildForSimulator ? "-mios-simulator-version-min=" : "-miphoneos-version-min=") + getEnv("IPHONEOS_VERSION_MIN", "14.0") << " " << trim(linkerFlags + " " + (flagDebugMode ? linkerDebugFlags : "")) << " -o " << lib ; @@ -4054,10 +4146,15 @@ int main (const int argc, const char* argv[]) { sdkmanager << packages.str(); - if (debugEnv || verboseEnv) log(sdkmanager.str()); - if (std::system(sdkmanager.str().c_str()) != 0) { - log("ERROR: failed to initialize Android SDK (sdkmanager)"); - exit(1); + if (getEnv("SSC_SKIP_ANDROID_SDK_MANAGER").size() == 0) { + if (debugEnv || verboseEnv) { + log(sdkmanager.str()); + } + + if (std::system(sdkmanager.str().c_str()) != 0) { + log("ERROR: failed to initialize Android SDK (sdkmanager)"); + exit(1); + } } if (!androidEnableStandardNdkBuild) { @@ -4307,7 +4404,12 @@ int main (const int argc, const char* argv[]) { } else if (entry.first.starts_with("extension_")) { auto key = replace(entry.first, "extension_", extension + "_"); auto value = entry.second; - settings["build_extensions_" + key] = value; + auto index = "build_extensions_" + key; + if (settings[index].size() > 0) { + settings[index] += " " + value; + } else { + settings[index] = value; + } } } } @@ -4315,6 +4417,7 @@ int main (const int argc, const char* argv[]) { auto configure = settings["build_extensions_" + extension + "_configure_script"]; auto build = settings["build_extensions_" + extension + "_build_script"]; + auto copy = settings["build_extensions_" + extension + "_build_copy"]; auto path = settings["build_extensions_" + extension + "_path"]; auto sources = parseStringList( @@ -4350,6 +4453,20 @@ int main (const int argc, const char* argv[]) { } } + if (copy.size() > 0) { + auto pathResources = paths.pathResourcesRelativeToUserBuild; + for (const auto& file : parseStringList(copy, ' ')) { + auto parts = split(file, ':'); + auto target = parts[0]; + auto destination = parts.size() == 2 ? pathResources / parts[1] : pathResources; + fs::copy( + target, + destination, + fs::copy_options::update_existing | fs::copy_options::recursive + ); + } + } + if (sources.size() == 0) { continue; } @@ -4517,17 +4634,17 @@ int main (const int argc, const char* argv[]) { } auto linkerFlags = ( - settings["build_extensions_linker_flags"] + - settings["build_extensions_" + os + "_linker_flags"] + - settings["build_extensions_" + extension + "_linker_flags"] + - settings["build_extensions_" + extension + "_" + os + "_linker_flags"] + settings["build_extensions_linker_flags"] + " " + + settings["build_extensions_" + os + "_linker_flags"] + " " + + settings["build_extensions_" + extension + "_linker_flags"] + " " + + settings["build_extensions_" + extension + "_" + os + "_linker_flags"] + " " ); auto linkerDebugFlags = ( - settings["build_extensions_linker_debug_flags"] + - settings["build_extensions_" + platform.os + "_linker_debug_flags"] + - settings["build_extensions_" + extension + "_linker_debug_flags"] + - settings["build_extensions_" + extension + "_" + os + "_linker_debug_flags"] + settings["build_extensions_linker_debug_flags"] + " " + + settings["build_extensions_" + platform.os + "_linker_debug_flags"] + " " + + settings["build_extensions_" + extension + "_linker_debug_flags"] + " " + + settings["build_extensions_" + extension + "_" + os + "_linker_debug_flags"] + " " ); if (platform.win && debugBuild) { From 35538f27fe82dd18fc46e9338e98ef5a18e4336b Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:28:04 +0200 Subject: [PATCH 26/42] fix(bin/cflags.sh): fix android errors for ndk path --- bin/cflags.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/cflags.sh b/bin/cflags.sh index 0f0f7356e..21d474af6 100755 --- a/bin/cflags.sh +++ b/bin/cflags.sh @@ -40,6 +40,7 @@ if (( !TARGET_OS_ANDROID && !TARGET_ANDROID_EMULATOR )); then fi else source "$root/bin/android-functions.sh" + android_fte > /dev/null cflags+=("-stdlib=libstdc++") cflags+=("-DANDROID -pthreads -fexceptions -fPIC -frtti -fsigned-char -D_FILE_OFFSET_BITS=64 -Wno-invalid-command-line-argument -Wno-unused-command-line-argument") cflags+=("-I$(dirname $NDK_BUILD)/sources/cxx-stl/llvm-libc++/include") From d3c4a6a85627d650ec0a3a2477c018c511d37b59 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Tue, 11 Jul 2023 23:28:45 +0200 Subject: [PATCH 27/42] fix(api/ipc.js): fix promise methods in proxy, handle nested data in results --- api/ipc.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/api/ipc.js b/api/ipc.js index 89ef000f4..f35d11d82 100644 --- a/api/ipc.js +++ b/api/ipc.js @@ -850,8 +850,8 @@ export class Result { const err = maybeMakeError(result?.err || maybeError || null, Result.from) const data = !err && result?.data !== null && result?.data !== undefined - ? result.data - : (!err ? result : null) + ? result.data?.data ?? result.data + : (!err ? result?.err ?? result : null) const source = result?.source || maybeSource || null const headers = result?.headers || maybeHeaders || null @@ -1399,7 +1399,16 @@ export function createBinding (domain, ctx) { get (target, key, ...args) { const value = Reflect.get(target, key, ...args) if (value !== undefined) return value - if (key === 'inspect' || key === '__proto__' || key === 'constructor' || key in Function.prototype) return + if ( + key === 'inspect' || + key === '__proto__' || + key === 'constructor' || + key in Promise.prototype || + key in Function.prototype + ) { + return + } + ctx.chain.add(key) return new Proxy(ctx, this) } From d6936c8cb33133ad410c5a4768de61906bd34a63 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:44:04 +0200 Subject: [PATCH 28/42] refactor(api/ipc.js): include 'id' in 'Result' --- api/ipc.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/api/ipc.js b/api/ipc.js index f35d11d82..a753e26d7 100644 --- a/api/ipc.js +++ b/api/ipc.js @@ -47,6 +47,7 @@ import { import * as errors from './errors.js' import { Buffer } from './buffer.js' +import { rand64 } from './crypto.js' import console from './console.js' let nextSeq = 1 @@ -789,28 +790,36 @@ export class Message extends URL { */ export class Result { /** + * The unique ID for this result. + * @type {string} + */ + id = String(rand64()) + + /** + * An optional error in the result. * @type {Error?} - * @ignore */ - err + err = null /** - * @type {string|object|Uint8Array} + * Result data if given. + * @type {string|object|Uint8Array?} * @ignore */ - data + data = null /** + * The source of this result. * @type {string?} * @ignore */ - source + source = null /** + * Result headers, if given. * @type {Headers?} - * @ignore */ - headers + headers = new Headers() /** * Creates a `Result` instance from input that may be an object @@ -848,6 +857,7 @@ export class Result { maybeError = null } + const id = result?.id || null const err = maybeMakeError(result?.err || maybeError || null, Result.from) const data = !err && result?.data !== null && result?.data !== undefined ? result.data?.data ?? result.data @@ -856,24 +866,26 @@ export class Result { const source = result?.source || maybeSource || null const headers = result?.headers || maybeHeaders || null - return new this(err, data, source, headers) + return new this(id, err, data, source, headers) } /** * `Result` class constructor. * @private + * @param {string?} [id = null] * @param {Error?} [err = null] * @param {object?} [data = null] * @param {string?} [source = null] * @param {object|string|Headers?} [headers = null] * @ignore */ - constructor (err, data, source, headers) { - this.err = typeof err !== 'undefined' ? err : null - this.data = typeof data !== 'undefined' ? data : null + constructor (id, err, data, source, headers) { + this.id = typeof id !== 'undefined' ? id : this.id + this.err = typeof err !== 'undefined' ? err : this.err + this.data = typeof data !== 'undefined' ? data : this.data this.source = typeof source === 'string' && source.length > 0 ? source - : null + : this.source this.headers = headers ? Headers.from(headers) : null From c836a894a7d1468c0841287e5fe1b7597dc1c891 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:44:26 +0200 Subject: [PATCH 29/42] refactor(include/socket/extension.h): require 'message' for 'send_bytes/send_json' --- include/socket/extension.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/socket/extension.h b/include/socket/extension.h index 81287c970..25b9d2e57 100644 --- a/include/socket/extension.h +++ b/include/socket/extension.h @@ -1019,21 +1019,21 @@ extern "C" { /** * Send JSON to the bridge to propagate to the WebView. * @param context - An extension context - * @param seq - An IPC sequence value + * @param message - The IPC message this send request sources from * @param json - The result JSON * @return `true` if successful, otherwise `false` */ SOCKET_RUNTIME_EXTENSION_EXPORT bool sapi_ipc_send_json ( sapi_context_t* context, - const char* seq, + sapi_ipc_message_t* message, sapi_json_any_t* json ); /** * Send bytes to the bridge to propagate to the WebView. * @param context - An extension context - * @param seq - An IPC sequence value + * @param message - The IPC message this send request sources from * @param size - The size of the bytes * @param bytes - The bytes * @return `true` if successful, otherwise `false` @@ -1041,7 +1041,7 @@ extern "C" { SOCKET_RUNTIME_EXTENSION_EXPORT bool sapi_ipc_send_bytes ( sapi_context_t* context, - const char* seq, + sapi_ipc_message_t* message, unsigned int size, unsigned char* bytes, const char* headers From aeaa7d8d1b9ccef3c31c1896869342d4aec28424 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:45:04 +0200 Subject: [PATCH 30/42] refactor(src/common.hh): mark 'init.cc' impls as extern/ fix '_WIN32' check --- src/common.hh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/common.hh b/src/common.hh index 375b952cd..551ff53ff 100644 --- a/src/common.hh +++ b/src/common.hh @@ -224,12 +224,11 @@ namespace SSC { inline const auto DEFAULT_SSC_RC_FILENAME = String(".sscrc"); inline const auto DEFAULT_SSC_ENV_FILENAME = String(".ssc.env"); - const Map getUserConfig (); - - bool isDebugEnabled (); - - const char* getDevHost (); - int getDevPort (); + // from init.cc + extern const Map getUserConfig (); + extern bool isDebugEnabled (); + extern const char* getDevHost (); + extern int getDevPort (); inline String encodeURIComponent (const String& sSrc); inline String decodeURIComponent (const String& sSrc); @@ -254,7 +253,7 @@ namespace SSC { inline String WStringToString (const String& s) { return s; } - + #if defined(_WIN32) SSC::String FormatError(DWORD error, SSC::String source); #endif @@ -581,7 +580,7 @@ namespace SSC { return appData[String("env_") + variableName]; } - #if _WIN32 + #if defined(_WIN32) char* variableValue = nullptr; std::size_t valueSize = 0; auto query = _dupenv_s(&variableValue, &valueSize, variableName); @@ -618,7 +617,7 @@ namespace SSC { } inline auto setEnv (const String& k, const String& v) { - #if _WIN32 + #if defined(_WIN32) return _putenv((k + "=" + v).c_str()); #else setenv(k.c_str(), v.c_str(), 1); @@ -626,7 +625,7 @@ namespace SSC { } inline auto setEnv (const char* s) { - #if _WIN32 + #if defined(_WIN32) return _putenv(s); #else auto parts = split(String(s), '='); From 42f82021604b2643640c72c061937f4dd44bdb0e Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:45:42 +0200 Subject: [PATCH 31/42] refactor(src/core/bluetooth.cc): use 'Result' for bluetooth JSON --- src/core/bluetooth.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/bluetooth.cc b/src/core/bluetooth.cc index 450db472d..28f2b144f 100644 --- a/src/core/bluetooth.cc +++ b/src/core/bluetooth.cc @@ -120,7 +120,8 @@ using namespace SSC; }} }; - self.bluetooth->emit("bluetooth", json); + auto result = SSC::IPC::Result(json); + self.bluetooth->emit("bluetooth", result.json()); } - (void) peripheralManagerDidStartAdvertising: (CBPeripheralManager*) peripheral @@ -138,7 +139,8 @@ using namespace SSC; }} }; - self.bluetooth->emit("bluetooth", json); + auto result = SSC::IPC::Result(json); + self.bluetooth->emit("bluetooth", result.json()); return; } @@ -269,7 +271,8 @@ using namespace SSC; }} }; - self.bluetooth->emit("bluetooth", json); + auto result = SSC::IPC::Result(json); + self.bluetooth->emit("bluetooth", result.json()); [peripheral discoverServices: uuids]; } @@ -321,7 +324,8 @@ using namespace SSC; }} }; - self.bluetooth->emit("bluetooth", json); + auto result = SSC::IPC::Result(json); + self.bluetooth->emit("bluetooth", result.json()); } - (void) peripheral: (CBPeripheral*) peripheral @@ -380,7 +384,8 @@ using namespace SSC; }} }; - self.bluetooth->send("-1", JSON::Object(json).str(), post); + auto result = SSC::IPC::Result(json); + self.bluetooth->send(result.seq, result.json(), post); } - (void) peripheral: (CBPeripheral*) peripheral From 21bb2ee646ba4a7134fd39095391998445c7d012 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:46:03 +0200 Subject: [PATCH 32/42] refactor(src/desktop/main.cc): use 'Result' for window message results --- src/desktop/main.cc | 144 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 29 deletions(-) diff --git a/src/desktop/main.cc b/src/desktop/main.cc index 03319a0f8..40f81685e 100644 --- a/src/desktop/main.cc +++ b/src/desktop/main.cc @@ -354,7 +354,8 @@ MAIN { if (message.name == "heartbeat") { if (seq.size() > 0) { - window->resolvePromise(seq, OK_STATE, "\"heartbeat\""); + auto result = SSC::IPC::Result(message.seq, message, "heartbeat"); + window->resolvePromise(seq, OK_STATE, result.str()); } return; @@ -375,7 +376,7 @@ MAIN { for (auto w : windowManager.windows) { if (w != nullptr) { auto window = windowManager.getWindow(w->opts.index); - window->eval(getEmitToRenderProcessJavaScript("process.exit", value)); + window->resolvePromise(message.seq, OK_STATE, value); } } return; @@ -443,10 +444,10 @@ MAIN { { "argv", process->argv }, { "path", process->path } }; - window->resolvePromise(seq, OK_STATE, encodeURIComponent(json.str())); + window->resolvePromise(seq, OK_STATE, json); return; } - window->resolvePromise(seq, ERROR_STATE, "null"); + window->resolvePromise(seq, ERROR_STATE, SSC::JSON::null); return; } @@ -457,7 +458,7 @@ MAIN { killProcess(process); } - window->resolvePromise(seq, OK_STATE, "null"); + window->resolvePromise(seq, OK_STATE, SSC::JSON::null); return; } @@ -466,7 +467,7 @@ MAIN { if (cmd.size() > 0 && process != nullptr) { process->write(out); } - window->resolvePromise(seq, OK_STATE, "null"); + window->resolvePromise(seq, OK_STATE, SSC::JSON::null); return; } @@ -480,7 +481,7 @@ MAIN { targetWindow->eval(getEmitToRenderProcessJavaScript(event, value)); } const auto seq = message.get("seq"); - currentWindow->resolvePromise(seq, OK_STATE, "null"); + currentWindow->resolvePromise(seq, OK_STATE, SSC::JSON::null); return; } @@ -510,7 +511,7 @@ MAIN { { "width", screenSize.width }, { "height", screenSize.height } }; - window->resolvePromise(seq, OK_STATE, json.str()); + window->resolvePromise(seq, OK_STATE, json); } return; } @@ -546,7 +547,7 @@ MAIN { const JSON::Object json = JSON::Object::Entries { { "err", "Window with index " + std::to_string(targetWindowIndex) + " already exists" } }; - currentWindow->resolvePromise(seq, ERROR_STATE, json.str()); + currentWindow->resolvePromise(seq, ERROR_STATE, json); return; } @@ -557,7 +558,7 @@ MAIN { {"message", error} }} }; - currentWindow->resolvePromise(seq, ERROR_STATE, json.str()); + currentWindow->resolvePromise(seq, ERROR_STATE, json); return; } @@ -599,7 +600,12 @@ MAIN { { "data", targetWindow->json() }, }; - currentWindow->resolvePromise(seq, OK_STATE, json.str()); + auto result = SSC::IPC::Result(message.seq, message, json); + currentWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); return; } @@ -614,7 +620,13 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "data", targetWindow->json()}, }; - window->resolvePromise(message.seq, OK_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + window->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); } return; } @@ -631,7 +643,13 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "err", targetWindowStatus } }; - resolveWindow->resolvePromise(message.get("seq"), ERROR_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + resolveWindow->resolvePromise( + message.seq, + ERROR_STATE, + result.json() + ); return; } @@ -640,7 +658,13 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "data", targetWindow->json() } }; - resolveWindow->resolvePromise(message.get("seq"), OK_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + resolveWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); return; } @@ -656,7 +680,13 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "err", targetWindowStatus } }; - resolveWindow->resolvePromise(message.get("seq"), ERROR_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + resolveWindow->resolvePromise( + message.seq, + ERROR_STATE, + result.json() + ); return; } @@ -665,7 +695,14 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "data", targetWindow->json() } }; - resolveWindow->resolvePromise(message.get("seq"), OK_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + resolveWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); + return; } @@ -681,7 +718,14 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "data", targetWindow->json() }, }; - currentWindow->resolvePromise(seq, OK_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + currentWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); + return; } @@ -698,7 +742,13 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "err", error } }; - currentWindow->resolvePromise(seq, ERROR_STATE, json.str()); + + currentWindow->resolvePromise( + message.seq, + ERROR_STATE, + json.str() + ); + return; } @@ -708,7 +758,13 @@ MAIN { { "data", targetWindow->json() }, }; - currentWindow->resolvePromise(seq, OK_STATE, json.str()); + auto result = SSC::IPC::Result(message.seq, message, json); + currentWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); + return; } @@ -718,14 +774,20 @@ MAIN { const auto currentWindow = windowManager.getWindow(currentIndex); const auto targetWindowIndex = message.get("targetWindowIndex").size() > 0 ? std::stoi(message.get("targetWindowIndex")) : currentIndex; const auto targetWindow = windowManager.getWindow(targetWindowIndex); - + targetWindow->showInspector(); JSON::Object json = JSON::Object::Entries { { "data", true }, }; - - currentWindow->resolvePromise(seq, OK_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + currentWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); + return; } @@ -754,7 +816,13 @@ MAIN { JSON::Object json = JSON::Object::Entries { { "data", targetWindow->json() }, }; - currentWindow->resolvePromise(seq, OK_STATE, json.str()); + + auto result = SSC::IPC::Result(message.seq, message, json); + currentWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); return; } @@ -776,7 +844,12 @@ MAIN { { "data", targetWindow->json() }, }; - currentWindow->resolvePromise(seq, OK_STATE, json.str()); + auto result = SSC::IPC::Result(message.seq, message, json); + currentWindow->resolvePromise( + message.seq, + OK_STATE, + result.json() + ); return; } @@ -796,12 +869,20 @@ MAIN { indexMain = std::stoi(message.get("indexMain")); indexSub = std::stoi(message.get("indexSub")); } catch (...) { - window->resolvePromise(seq, OK_STATE, "null"); + window->resolvePromise( + message.seq, + OK_STATE, + SSC::JSON::null + ); return; } window->setSystemMenuItemEnabled(enabled, indexMain, indexSub); - window->resolvePromise(seq, OK_STATE, "null"); + window->resolvePromise( + message.seq, + OK_STATE, + SSC::JSON::null + ); return; } @@ -821,7 +902,11 @@ MAIN { if (message.name == "window.setContextMenu") { auto seq = message.get("seq"); window->setContextMenu(seq, decodeURIComponent(value)); - window->resolvePromise(seq, OK_STATE, "null"); + window->resolvePromise( + message.seq, + OK_STATE, + SSC::JSON::null + ); return; } @@ -842,10 +927,11 @@ MAIN { }} }; + auto result = SSC::IPC::Result(message.seq, message, err); window->resolvePromise( - message.get("seq"), + message.seq, ERROR_STATE, - encodeURIComponent(JSON::Object(err).str()) + result.json() ); }; From 187b6af7a14f68a310a702b7f8b8e50dd0d373aa Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:46:29 +0200 Subject: [PATCH 33/42] refactor(src/extension/ipc.cc): use 'message' to construct 'Result' --- src/extension/ipc.cc | 56 +++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/extension/ipc.cc b/src/extension/ipc.cc index f418f5991..197276a29 100644 --- a/src/extension/ipc.cc +++ b/src/extension/ipc.cc @@ -144,31 +144,48 @@ bool sapi_ipc_reply (const sapi_ipc_result_t* result) { bool sapi_ipc_send_bytes ( sapi_context_t* ctx, - const char* seq, + sapi_ipc_message_t* message, unsigned int size, unsigned char* bytes, const char* headers ) { - if (ctx == nullptr || ctx->router == nullptr || bytes == nullptr || size == 0) { + if (!ctx || !ctx->router || !bytes || !size) { return false; } - auto body = new char[size]{0}; - memcpy(body, bytes, size); - return ctx->router->send( - seq == nullptr || SSC::String(seq) == "" ? "-1" : seq, - "", - SSC::Post { 0, 0, body, size, headers ? headers : "" } - ); + + auto post = SSC::Post { + .id = 0, + .ttl = 0, + .body = new char[size]{0}, + .length = size, + .headers =headers ? headers : "" + }; + + memcpy(post.body, bytes, size); + + if (message) { + auto result = SSC::IPC::Result( + message->seq, + *message, + SSC::JSON::null, + post + ); + + return ctx->router->send(result.seq, result.str(), result.post); + } + + auto result = SSC::IPC::Result(SSC::JSON::null); + return ctx->router->send(result.seq, result.str(), post); } bool sapi_ipc_send_json ( sapi_context_t* ctx, - const char* seq, + sapi_ipc_message_t* message, sapi_json_any_t* json ) { SSC::JSON::Any value = nullptr; - if (ctx == nullptr || ctx->router == nullptr || json == nullptr) { + if (!ctx || !ctx->router || !json) { return false; } @@ -196,11 +213,18 @@ bool sapi_ipc_send_json ( } } - return ctx->router->send( - seq == nullptr || SSC::String(seq) == "" ? "-1" : seq, - value.str(), - SSC::Post {} - ); + if (message) { + auto result = SSC::IPC::Result( + message->seq, + *message, + value + ); + + return ctx->router->send(result.seq, result.str(), result.post); + } + + auto result = SSC::IPC::Result(value); + return ctx->router->send(result.seq, result.str(), result.post); } bool sapi_ipc_emit ( From e5f9952e0c6ce0f3e50bd5fe41a0e2fa0d15d859 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:46:49 +0200 Subject: [PATCH 34/42] refactor(src/window/window.hh): support 'JSON' in 'resolvePromise' --- src/window/window.hh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/window/window.hh b/src/window/window.hh index 8657f0f85..b87e6dbc1 100644 --- a/src/window/window.hh +++ b/src/window/window.hh @@ -139,6 +139,15 @@ namespace SSC { this->onMessage(IPC::getResolveToMainProcessMessage(seq, state, value)); } + void resolvePromise ( + const String& seq, + const String& state, + const JSON::Any& json + ) { + auto result = SSC::IPC::Result(json); + return resolvePromise(seq, state, result.str()); + } + static float getSizeInPixels (String sizeInPercent, int screenSize) { if (sizeInPercent.size() > 0) { if (sizeInPercent.back() == '%') { From a3b236149a1102ea31e1673d6547c8e196e26618 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Wed, 12 Jul 2023 16:49:18 +0200 Subject: [PATCH 35/42] fix(src/ipc): include 'id' in result JSON --- src/ipc/bridge.cc | 15 +++++++++++++++ src/ipc/ipc.cc | 26 +++++++++++++++++++++++--- src/ipc/ipc.hh | 3 ++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ipc/bridge.cc b/src/ipc/bridge.cc index 67cc07a43..1cb74623e 100644 --- a/src/ipc/bridge.cc +++ b/src/ipc/bridge.cc @@ -1754,6 +1754,21 @@ namespace SSC::IPC { this->core = core; this->router.core = core; this->router.bridge = this; + + this->bluetooth.sendFunction = [this]( + const String& seq, + const JSON::Any value, + const SSC::Post post + ) { + this->router.send(seq, value.str(), post); + }; + + this->bluetooth.emitFunction = [this]( + const String& seq, + const JSON::Any value + ) { + this->router.emit(seq, value.str()); + }; } bool Router::hasMappedBuffer (int index, const Message::Seq seq) { diff --git a/src/ipc/ipc.cc b/src/ipc/ipc.cc index 143ef2e6a..aa183ccd1 100644 --- a/src/ipc/ipc.cc +++ b/src/ipc/ipc.cc @@ -147,6 +147,11 @@ namespace SSC::IPC { } } + Result::Result (const JSON::Any value) { + this->id = rand64(); + this->value = value; + } + Result::Result (const Err error): Result(error.message.seq, error.message) { this->err = error.value; this->source = error.message.name; @@ -161,7 +166,12 @@ namespace SSC::IPC { if (!this->value.isNull()) { if (this->value.isObject()) { auto object = this->value.as(); - object["source"] = this->source; + + if (object.has("data") || object.has("err")) { + object["source"] = this->source; + object["id"] = std::to_string(this->id); + } + return object; } @@ -170,13 +180,23 @@ namespace SSC::IPC { auto entries = JSON::Object::Entries { {"source", this->source}, - {"result_id", std::to_string(this->id)} + {"id", std::to_string(this->id)} }; if (!this->err.isNull()) { entries["err"] = this->err; - } else { + if (this->err.isObject()) { + if (this->err.as().has("id")) { + entries["id"] = this->err.as().get("id"); + } + } + } else if (!this->data.isNull()) { entries["data"] = this->data; + if (this->data.isObject()) { + if (this->data.as().has("id")) { + entries["id"] = this->data.as().get("id"); + } + } } return JSON::Object(entries); diff --git a/src/ipc/ipc.hh b/src/ipc/ipc.hh index 68e14c94f..b72d78dfc 100644 --- a/src/ipc/ipc.hh +++ b/src/ipc/ipc.hh @@ -122,7 +122,7 @@ namespace SSC::IPC { }; Message message; - Message::Seq seq; + Message::Seq seq = "-1"; uint64_t id = 0; String source = ""; JSON::Any value = nullptr; @@ -132,6 +132,7 @@ namespace SSC::IPC { Post post; Result () = default; + Result (const JSON::Any); Result (const Err error); Result (const Data data); Result (const Message::Seq&, const Message&); From 1796cec35c6bc522362625b633aa13f79e0a2e95 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Thu, 13 Jul 2023 16:46:09 +0200 Subject: [PATCH 36/42] refactor(src/cli): support '--root' in 'print-build-dir' command --- src/cli/cli.cc | 19 +++++++++++++++++-- src/cli/templates.hh | 6 +++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index abbaa0e79..0bf38bee3 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2000,10 +2000,25 @@ int main (const int argc, const char* argv[]) { }); Options printBuildDirOptions = { - { { "--platform" }, true }, - { { "--prod" }, true } + { { "--platform" }, true }, { { "--root" }, true} }; createSubcommand("print-build-dir", printBuildDirOptions, true, [&](Map optionsWithValue, std::unordered_set optionsWithoutValue) -> void { + bool flagRoot = optionsWithoutValue.find("--root") != optionsWithoutValue.end(); + + if (flagRoot) { + auto targetPlatform = optionsWithValue["--platform"]; + + if (targetPlatform.size() > 0) { + Path path = getPaths(targetPlatform).platformSpecificOutputPath; + std::cout << path.string() << std::endl; + } else { + Path path = getPaths(platform.os).platformSpecificOutputPath; + std::cout << path.string() << std::endl; + } + + exit(0); + } + // if --platform is specified, use the build path for the specified platform auto targetPlatform = optionsWithValue["--platform"]; if (targetPlatform.size() > 0) { diff --git a/src/cli/templates.hh b/src/cli/templates.hh index 06a326cf3..77cea8b59 100644 --- a/src/cli/templates.hh +++ b/src/cli/templates.hh @@ -103,8 +103,8 @@ usage: ssc print-build-dir [--platform=] [--prod] [] options: - --platform ios; if not specified, runs on the current platform - --prod use a production build directory + --platform android|android-emulator|ios|ios-simulator; if not specified, runs on the current platform + --root print root build directory )TEXT"; constexpr auto gHelpTextRun = R"TEXT( @@ -114,7 +114,7 @@ usage: ssc run [options] [] options: - --platform ios-simulator; if not specified, runs on the current platform + --platform android|ios|ios-simulator; if not specified, runs on the current platform --prod run production build --test=path indicate test mode )TEXT"; From 2429a9da10087be1cf376ea362bdb92666bf5f2d Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Thu, 13 Jul 2023 16:48:30 +0200 Subject: [PATCH 37/42] chore(api): generate docs and ts typings --- api/README.md | 16 +- api/index.d.ts | 3762 ++++++++++++++++++++++++------------------------ 2 files changed, 1899 insertions(+), 1879 deletions(-) diff --git a/api/README.md b/api/README.md index 9b83fbe53..401704137 100644 --- a/api/README.md +++ b/api/README.md @@ -1191,7 +1191,19 @@ External docs: https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fspromisesw import { send } from 'socket:ipc' ``` -## [`emit(name, value, target , options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1031) +### [undefined](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L796) + +The unique ID for this result. + +### [undefined](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L802) + +An optional error in the result. + +### [undefined](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L822) + +Result headers, if given. + +## [`emit(name, value, target , options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1043) Emit event to be dispatched on `window` object. @@ -1203,7 +1215,7 @@ Emit event to be dispatched on `window` object. | options | Object | | true | | -## [`send(command, value, options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1090) +## [`send(command, value, options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1102) Sends an async IPC command request with parameters. diff --git a/api/index.d.ts b/api/index.d.ts index 4d1cb5f1a..cf970430b 100644 --- a/api/index.d.ts +++ b/api/index.d.ts @@ -519,1583 +519,440 @@ declare module "socket:console" { const _default: Console; export default _default; } -declare module "socket:ipc" { - /** - * Parses `seq` as integer value - * @param {string|number} seq - * @param {object=} [options] - * @param {boolean} [options.bigint = false] - * @ignore - */ - export function parseSeq(seq: string | number, options?: object | undefined): number | bigint; - /** - * If `debug.enabled === true`, then debug output will be printed to console. - * @param {(boolean)} [enable] - * @return {boolean} - * @ignore - */ - export function debug(enable?: (boolean)): boolean; - export namespace debug { - function log(): any; - let enabled: any; +declare module "socket:events" { + export const Event: { + new (type: string, eventInitDict?: EventInit): Event; + prototype: Event; + readonly NONE: 0; + readonly CAPTURING_PHASE: 1; + readonly AT_TARGET: 2; + readonly BUBBLING_PHASE: 3; + } | { + new (): {}; + }; + export const CustomEvent: { + new (type: string, eventInitDict?: CustomEventInit): CustomEvent; + prototype: CustomEvent; + } | { + new (type: any, options: any): { + "__#1@#detail": any; + readonly detail: any; + }; + }; + export const MessageEvent: { + new (type: string, eventInitDict?: MessageEventInit): MessageEvent; + prototype: MessageEvent; + } | { + new (type: any, options: any): { + "__#2@#detail": any; + "__#2@#data": any; + readonly detail: any; + readonly data: any; + }; + }; + export const ErrorEvent: { + new (type: string, eventInitDict?: ErrorEventInit): ErrorEvent; + prototype: ErrorEvent; + } | { + new (type: any, options: any): { + "__#3@#detail": any; + "__#3@#error": any; + readonly detail: any; + readonly error: any; + }; + }; + export default exports; + export function EventEmitter(): void; + export class EventEmitter { + _events: any; + _eventsCount: number; + _maxListeners: number; + setMaxListeners(n: any): this; + getMaxListeners(): any; + emit(type: any, ...args: any[]): boolean; + addListener(type: any, listener: any): any; + on: any; + prependListener(type: any, listener: any): any; + once(type: any, listener: any): this; + prependOnceListener(type: any, listener: any): this; + removeListener(type: any, listener: any): this; + off: any; + removeAllListeners(type: any, ...args: any[]): this; + listeners(type: any): any[]; + rawListeners(type: any): any[]; + listenerCount: typeof listenerCount; + eventNames(): any; } + export namespace EventEmitter { + export { EventEmitter }; + export let defaultMaxListeners: number; + export function init(): void; + export function listenerCount(emitter: any, type: any): any; + export { once }; + } + export function once(emitter: any, name: any): Promise; + import * as exports from "socket:events"; + function listenerCount(type: any): any; + +} +declare module "socket:os" { + export function arch(): any; + export function cpus(): any; + export function networkInterfaces(): any; + export function platform(): any; + export function type(): string; + export function isWindows(): boolean; + export function tmpdir(): string; + export function rusage(): any; + export function uptime(): any; + export function uname(): string; + export function hrtime(): any; + export function availableMemory(): any; + export const EOL: "\n" | "\r\n"; + export default exports; + import * as exports from "socket:os"; + +} +declare module "socket:process" { + export function nextTick(callback: any): void; /** - * @ignore - */ - export function postMessage(message: any, ...args: any[]): Promise; - /** - * Waits for the native IPC layer to be ready and exposed on the - * global window object. - * @ignore - */ - export function ready(): Promise; - /** - * Sends a synchronous IPC command over XHR returning a `Result` - * upon success or error. - * @param {string} command - * @param {object|string?} [params] - * @param {object?} [options] - * @return {Result} - * @ignore - */ - export function sendSync(command: string, params?: object | (string | null), options?: object | null): Result; - /** - * Emit event to be dispatched on `window` object. - * @param {string} name - * @param {any} value - * @param {EventTarget=} [target = window] - * @param {Object=} options - */ - export function emit(name: string, value: any, target?: EventTarget | undefined, options?: any | undefined): Promise; - /** - * Resolves a request by `seq` with possible value. - * @param {string} seq - * @param {any} value - * @ignore - */ - export function resolve(seq: string, value: any): Promise; - /** - * Sends an async IPC command request with parameters. - * @param {string} command - * @param {any=} value - * @param {object=} [options] - * @param {boolean=} [options.cache=false] - * @param {boolean=} [options.bytes=false] - * @return {Promise} - */ - export function send(command: string, value?: any | undefined, options?: object | undefined): Promise; - /** - * Sends an async IPC command request with parameters and buffered bytes. - * @param {string} command - * @param {object=} params - * @param {(Buffer|Uint8Array|ArrayBuffer|string|Array)=} buffer - * @param {object=} options - * @ignore - */ - export function write(command: string, params?: object | undefined, buffer?: (Buffer | Uint8Array | ArrayBuffer | string | any[]) | undefined, options?: object | undefined): Promise; - /** - * Sends an async IPC command request with parameters requesting a response - * with buffered bytes. - * @param {string} command - * @param {object=} params - * @param {object=} options - * @ignore - */ - export function request(command: string, params?: object | undefined, options?: object | undefined): Promise; - /** - * Factory for creating a proxy based IPC API. - * @param {string} domain - * @param {(function|object)=} ctx - * @param {string=} [ctx.default] - * @return {Proxy} - * @ignore - */ - export function createBinding(domain: string, ctx?: (Function | object) | undefined): ProxyConstructor; - /** - * Represents an OK IPC status. - * @ignore + * @returns {string} The home directory of the current user. */ - export const OK: 0; + export function homedir(): string; /** - * Represents an ERROR IPC status. - * @ignore + * Computed high resolution time as a `BigInt`. + * @param {Array?} [time] + * @return {bigint} */ - export const ERROR: 1; + export function hrtime(time?: Array | null): bigint; + export namespace hrtime { + function bigint(): any; + } /** - * Timeout in milliseconds for IPC requests. - * @ignore + * @param {number=} [code=0] - The exit code. Default: 0. */ - export const TIMEOUT: number; + export function exit(code?: number | undefined): Promise; + export function memoryUsage(): { + rss: any; + }; + export namespace memoryUsage { + function rss(): any; + } + export default process; + const process: any; +} +declare module "socket:path/path" { /** - * Symbol for the `ipc.debug.enabled` property - * @ignore + * @typedef {(string|Path|URL|{ pathname: string }|{ url: string)} PathComponent */ - export const kDebugEnabled: unique symbol; /** - * @ignore + * A container for a parsed Path. */ - export class Headers extends globalThis.Headers { + export class Path extends URL { /** - * @ignore + * Computes current working directory for a path + * @param {object=} [opts] + * @param {boolean=} [opts.posix] Set to `true` to force POSIX style path + * @return {string} */ - static from(input: any): any; + static cwd(opts?: object | undefined): string; /** - * @ignore + * Resolves path components to an absolute path. + * @param {object} options + * @param {...PathComponent} components + * @return {string} */ - get length(): number; + static resolve(options: object, ...components: PathComponent[]): string; /** - * @ignore + * Computes the relative path from `from` to `to`. + * @param {object} options + * @param {PathComponent} from + * @param {PathComponent} to + * @return {string} */ - toJSON(): { - [k: string]: any; - }; - } - /** - * A container for a IPC message based on a `ipc://` URI scheme. - * @ignore - */ - export class Message extends URL { + static relative(options: object, from: PathComponent, to: PathComponent): string; /** - * The expected protocol for an IPC message. - * @ignore - */ - static get PROTOCOL(): string; - /** - * Creates a `Message` instance from a variety of input. - * @param {string|URL|Message|Buffer|object} input - * @param {(object|string|URLSearchParams)=} [params] - * @param {(ArrayBuffer|Uint8Array|string)?} [bytes] - * @return {Message} - * @ignore - */ - static from(input: string | URL | Message | Buffer | object, params?: (object | string | URLSearchParams) | undefined, bytes?: (ArrayBuffer | Uint8Array | string) | null): Message; - /** - * Predicate to determine if `input` is valid for constructing - * a new `Message` instance. - * @param {string|URL|Message|Buffer|object} input - * @return {boolean} - * @ignore - */ - static isValidInput(input: string | URL | Message | Buffer | object): boolean; - /** - * `Message` class constructor. - * @protected - * @param {string|URL} input - * @param {object|Uint8Array?} [bytes] - * @ignore - */ - protected constructor(); - /** - * @type {Uint8Array?} - * @ignore - */ - bytes: Uint8Array | null; - /** - * Computed IPC message name. - * @ignore - */ - get command(): string; - /** - * Computed IPC message name. - * @ignore - */ - get name(): string; - /** - * Computed `id` value for the command. - * @ignore + * Joins path components. This function may not return an absolute path. + * @param {object} options + * @param {...PathComponent} components + * @return {string} */ - get id(): string; + static join(options: object, ...components: PathComponent[]): string; /** - * Computed `seq` (sequence) value for the command. - * @ignore + * Computes directory name of path. + * @param {object} options + * @param {...PathComponent} components + * @return {string} */ - get seq(): any; + static dirname(options: object, path: any): string; /** - * Computed message value potentially given in message parameters. - * This value is automatically decoded, but not treated as JSON. - * @ignore + * Computes base name of path. + * @param {object} options + * @param {...PathComponent} components + * @return {string} */ - get value(): any; + static basename(options: object, path: any): string; /** - * Computed `index` value for the command potentially referring to - * the window index the command is scoped to or originating from. If not - * specified in the message parameters, then this value defaults to `-1`. - * @ignore + * Computes extension name of path. + * @param {object} options + * @param {PathComponent} path + * @return {string} */ - get index(): number; + static extname(options: object, path: PathComponent): string; /** - * Computed value parsed as JSON. This value is `null` if the value is not present - * or it is invalid JSON. - * @ignore + * Computes normalized path + * @param {object} options + * @param {PathComponent} path + * @return {string} */ - get json(): any; + static normalize(options: object, path: PathComponent): string; /** - * Computed readonly object of message parameters. - * @ignore + * Formats `Path` object into a string. + * @param {object} options + * @param {object|Path} path + * @return {string} */ - get params(): any; + static format(options: object, path: object | Path): string; /** - * Gets unparsed message parameters. - * @ignore + * Parses input `path` into a `Path` instance. + * @param {PathComponent} path + * @return {object} */ - get rawParams(): { - [k: string]: any; - }; + static parse(path: PathComponent): object; /** - * Returns computed parameters as entries - * @return {Array>} - * @ignore + * Creates a `Path` instance from `input` and optional `cwd`. + * @param {PathComponent} input + * @param {string} [cwd] */ - entries(): Array>; + static from(input: PathComponent, cwd?: string): any; /** - * Set a parameter `value` by `key`. - * @param {string} key - * @param {any} value - * @ignore + * `Path` class constructor. + * @protected + * @param {string} pathname + * @param {string} [cwd = Path.cwd()] */ - set(key: string, value: any): void; + protected constructor(); /** - * Get a parameter value by `key`. - * @param {string} key - * @param {any} defaultValue - * @return {any} - * @ignore + * `true` if the path is relative, otherwise `false. + * @type {boolean} */ - get(key: string, defaultValue: any): any; + get isRelative(): boolean; /** - * Delete a parameter by `key`. - * @param {string} key - * @return {boolean} - * @ignore + * The working value of this path. */ - delete(key: string): boolean; + get value(): string; /** - * Computed parameter keys. - * @return {Array} - * @ignore + * The original source, unresolved. + * @type {string} */ - keys(): Array; + get source(): string; /** - * Computed parameter values. - * @return {Array} - * @ignore + * Computed parent path. + * @type {string} */ - values(): Array; + get parent(): string; /** - * Predicate to determine if parameter `key` is present in parameters. - * @param {string} key - * @return {boolean} - * @ignore + * Computed root in path. + * @type {string} */ - has(key: string): boolean; - } - /** - * A result type used internally for handling - * IPC result values from the native layer that are in the form - * of `{ err?, data? }`. The `data` and `err` properties on this - * type of object are in tuple form and be accessed at `[data?,err?]` - * @ignore - */ - export class Result { + get root(): string; /** - * Creates a `Result` instance from input that may be an object - * like `{ err?, data? }`, an `Error` instance, or just `data`. - * @param {object|Error|any?} result - * @param {Error|object} [maybeError] - * @param {string} [maybeSource] - * @param {object|string|Headers} [maybeHeaders] - * @return {Result} - * @ignore + * Computed directory name in path. + * @type {string} */ - static from(result: object | Error | (any | null), maybeError?: Error | object, maybeSource?: string, maybeHeaders?: object | string | Headers): Result; + get dir(): string; /** - * `Result` class constructor. - * @private - * @param {Error?} [err = null] - * @param {object?} [data = null] - * @param {string?} [source = null] - * @param {object|string|Headers?} [headers = null] - * @ignore + * Computed base name in path. + * @type {string} */ - private constructor(); + get base(): string; /** - * @type {Error?} - * @ignore + * Computed base name in path without path extension. + * @type {string} */ - err: Error | null; + get name(): string; /** - * @type {string|object|Uint8Array} - * @ignore + * Computed extension name in path. + * @type {string} */ - data: string | object | Uint8Array; + get ext(): string; /** + * The computed drive, if given in the path. * @type {string?} - * @ignore - */ - source: string | null; - /** - * @type {Headers?} - * @ignore */ - headers: Headers | null; + get drive(): string; /** - * Computed result length. - * @ignore + * @return {URL} */ - get length(): any; + toURL(): URL; /** * @ignore */ - toJSON(): { - headers: Headers; - source: string; - data: any; - err: { - name: string; - message: string; - stack?: string; - cause?: unknown; - type: any; - code: any; - }; + inspect(): { + root: string; + dir: string; + base: string; + ext: string; + name: string; }; /** - * Generator for an `Iterable` interface over this instance. * @ignore */ - [Symbol.iterator](): Generator; + [Symbol.toStringTag](): string; + #private; } + export default Path; + export type PathComponent = (string | Path | URL | { + pathname: string; + } | { + url: string; + }); +} +declare module "socket:path/win32" { /** - * @ignore + * Computes current working directory for a path + * @param {string} */ - export const primordials: any; - export default exports; - import { Buffer } from "socket:buffer"; - import * as exports from "socket:ipc"; - -} -declare module "socket:polyfills" { - export function applyPolyfills(): void; - export default exports; - import * as exports from "socket:polyfills"; - -} -declare module "socket:window/constants" { - export const WINDOW_ERROR: -1; - export const WINDOW_NONE: 0; - export const WINDOW_CREATING: 10; - export const WINDOW_CREATED: 11; - export const WINDOW_HIDING: 20; - export const WINDOW_HIDDEN: 21; - export const WINDOW_SHOWING: 30; - export const WINDOW_SHOWN: 31; - export const WINDOW_CLOSING: 40; - export const WINDOW_CLOSED: 41; - export const WINDOW_EXITING: 50; - export const WINDOW_EXITED: 51; - export const WINDOW_KILLING: 60; - export const WINDOW_KILLED: 61; - export * as _default from "socket:window/constants"; - -} -declare module "socket:events" { - export const Event: { - new (type: string, eventInitDict?: EventInit): Event; - prototype: Event; - readonly NONE: 0; - readonly CAPTURING_PHASE: 1; - readonly AT_TARGET: 2; - readonly BUBBLING_PHASE: 3; - } | { - new (): {}; - }; - export const CustomEvent: { - new (type: string, eventInitDict?: CustomEventInit): CustomEvent; - prototype: CustomEvent; - } | { - new (type: any, options: any): { - "__#1@#detail": any; - readonly detail: any; - }; - }; - export const MessageEvent: { - new (type: string, eventInitDict?: MessageEventInit): MessageEvent; - prototype: MessageEvent; - } | { - new (type: any, options: any): { - "__#2@#detail": any; - "__#2@#data": any; - readonly detail: any; - readonly data: any; - }; - }; - export const ErrorEvent: { - new (type: string, eventInitDict?: ErrorEventInit): ErrorEvent; - prototype: ErrorEvent; - } | { - new (type: any, options: any): { - "__#3@#detail": any; - "__#3@#error": any; - readonly detail: any; - readonly error: any; - }; - }; - export default exports; - export function EventEmitter(): void; - export class EventEmitter { - _events: any; - _eventsCount: number; - _maxListeners: number; - setMaxListeners(n: any): this; - getMaxListeners(): any; - emit(type: any, ...args: any[]): boolean; - addListener(type: any, listener: any): any; - on: any; - prependListener(type: any, listener: any): any; - once(type: any, listener: any): this; - prependOnceListener(type: any, listener: any): this; - removeListener(type: any, listener: any): this; - off: any; - removeAllListeners(type: any, ...args: any[]): this; - listeners(type: any): any[]; - rawListeners(type: any): any[]; - listenerCount: typeof listenerCount; - eventNames(): any; - } - export namespace EventEmitter { - export { EventEmitter }; - export let defaultMaxListeners: number; - export function init(): void; - export function listenerCount(emitter: any, type: any): any; - export { once }; - } - export function once(emitter: any, name: any): Promise; - import * as exports from "socket:events"; - function listenerCount(type: any): any; - -} -declare module "socket:os" { - export function arch(): any; - export function cpus(): any; - export function networkInterfaces(): any; - export function platform(): any; - export function type(): string; - export function isWindows(): boolean; - export function tmpdir(): string; - export function rusage(): any; - export function uptime(): any; - export function uname(): string; - export function hrtime(): any; - export function availableMemory(): any; - export const EOL: "\n" | "\r\n"; - export default exports; - import * as exports from "socket:os"; + export function cwd(): string; + /** + * Resolves path components to an absolute path. + * @param {...PathComponent} components + * @return {string} + */ + export function resolve(...components: PathComponent[]): string; + /** + * Joins path components. This function may not return an absolute path. + * @param {...PathComponent} components + * @return {string} + */ + export function join(...components: PathComponent[]): string; + /** + * Computes directory name of path. + * @param {PathComponent} path + * @return {string} + */ + export function dirname(path: PathComponent): string; + /** + * Computes base name of path. + * @param {PathComponent} path + * @param {string} suffix + * @return {string} + */ + export function basename(path: PathComponent, suffix: string): string; + /** + * Computes extension name of path. + * @param {PathComponent} path + * @return {string} + */ + export function extname(path: PathComponent): string; + /** + * Predicate helper to determine if path is absolute. + * @param {PathComponent} path + * @return {boolean} + */ + export function isAbsolute(path: PathComponent): boolean; + /** + * Parses input `path` into a `Path` instance. + * @param {PathComponent} path + * @return {Path} + */ + export function parse(path: PathComponent): Path; + /** + * Formats `Path` object into a string. + * @param {object|Path} path + * @return {string} + */ + export function format(path: object | Path): string; + /** + * Normalizes `path` resolving `..` and `.\` preserving trailing + * slashes. + * @param {string} path + */ + export function normalize(path: string): string; + /** + * Computes the relative path from `from` to `to`. + * @param {string} from + * @param {string} to + * @return {string} + */ + export function relative(from: string, to: string): string; + export * as _default from "socket:path/win32"; + export * as win32 from "socket:path/win32"; + export const sep: "\\"; + export const delimiter: ";"; + export type PathComponent = import("socket:path/path").PathComponent; + import posix from "socket:path/posix"; + import { Path } from "socket:path/path"; + export { posix, Path }; } -declare module "socket:process" { - export function nextTick(callback: any): void; +declare module "socket:path/posix" { /** - * @returns {string} The home directory of the current user. + * Computes current working directory for a path + * @param {string} + * @return {string} */ - export function homedir(): string; + export function cwd(): string; /** - * Computed high resolution time as a `BigInt`. - * @param {Array?} [time] - * @return {bigint} + * Resolves path components to an absolute path. + * @param {...PathComponent} components + * @return {string} */ - export function hrtime(time?: Array | null): bigint; - export namespace hrtime { - function bigint(): any; - } + export function resolve(...components: PathComponent[]): string; /** - * @param {number=} [code=0] - The exit code. Default: 0. + * Joins path components. This function may not return an absolute path. + * @param {...PathComponent} components + * @return {string} */ - export function exit(code?: number | undefined): Promise; - export function memoryUsage(): { - rss: any; - }; - export namespace memoryUsage { - function rss(): any; - } - export default process; - const process: any; -} -declare module "socket:window" { + export function join(...components: PathComponent[]): string; /** - * @param {string} url + * Computes directory name of path. + * @param {PathComponent} path * @return {string} - * @ignore */ - export function formatFileUrl(url: string): string; + export function dirname(path: PathComponent): string; /** - * @class ApplicationWindow - * Represents a window in the application + * Computes base name of path. + * @param {PathComponent} path + * @param {string} suffix + * @return {string} */ - export class ApplicationWindow { - static constants: typeof statuses; - constructor({ index, ...options }: { - [x: string]: any; - index: any; - }); - /** - * Get the index of the window - * @return {number} - the index of the window - */ - get index(): number; - /** - * Get the size of the window - * @return {{ width: number, height: number }} - the size of the window - */ - getSize(): { - width: number; - height: number; - }; - /** - * Get the title of the window - * @return {string} - the title of the window - */ - getTitle(): string; - /** - * Get the status of the window - * @return {string} - the status of the window - */ - getStatus(): string; - /** - * Close the window - * @return {Promise} - the options of the window - */ - close(): Promise; - /** - * Shows the window - * @return {Promise} - */ - show(): Promise; - /** - * Hides the window - * @return {Promise} - */ - hide(): Promise; - /** - * Sets the title of the window - * @param {string} title - the title of the window - * @return {Promise} - */ - setTitle(title: string): Promise; - /** - * Sets the size of the window - * @param {object} opts - an options object - * @param {(number|string)=} opts.width - the width of the window - * @param {(number|string)=} opts.height - the height of the window - * @return {Promise} - * @throws {Error} - if the width or height is invalid - */ - setSize(opts: { - width?: (number | string) | undefined; - height?: (number | string) | undefined; - }): Promise; - /** - * Navigate the window to a given path - * @param {object} path - file path - * @return {Promise} - */ - navigate(path: object): Promise; - /** - * Opens the Web Inspector for the window - * @return {Promise} - */ - showInspector(): Promise; - /** - * Sets the background color of the window - * @param {object} opts - an options object - * @param {number} opts.red - the red value - * @param {number} opts.green - the green value - * @param {number} opts.blue - the blue value - * @param {number} opts.alpha - the alpha value - * @return {Promise} - */ - setBackgroundColor(opts: { - red: number; - green: number; - blue: number; - alpha: number; - }): Promise; - /** - * Opens a native context menu. - * @param {object} options - an options object - * @return {Promise} - */ - setContextMenu(options: object): Promise; - /** - * Shows a native open file dialog. - * @param {object} options - an options object - * @return {Promise} - an array of file paths - */ - showOpenFilePicker(options: object): Promise; - /** - * Shows a native save file dialog. - * @param {object} options - an options object - * @return {Promise} - an array of file paths - */ - showSaveFilePicker(options: object): Promise; - /** - * Shows a native directory dialog. - * @param {object} options - an options object - * @return {Promise} - an array of file paths - */ - showDirectoryFilePicker(options: object): Promise; - /** - * Sends an IPC message to the window or to qthe backend. - * @param {object} options - an options object - * @param {number=} options.window - the window to send the message to - * @param {boolean=} [options.backend = false] - whether to send the message to the backend - * @param {string} options.event - the event to send - * @param {(string|object)=} options.value - the value to send - * @returns - */ - send(options: { - window?: number | undefined; - backend?: boolean | undefined; - event: string; - value?: (string | object) | undefined; - }): Promise; - /** - * Opens an URL in the default browser. - * @param {object} options - * @returns {Promise} - */ - openExternal(options: object): Promise; - /** - * Adds a listener to the window. - * @param {string} event - the event to listen to - * @param {function(*): void} cb - the callback to call - * @returns {void} - */ - addListener(event: string, cb: (arg0: any) => void): void; - /** - * Adds a listener to the window. An alias for `addListener`. - * @param {string} event - the event to listen to - * @param {function(*): void} cb - the callback to call - * @returns {void} - * @see addListener - */ - on(event: string, cb: (arg0: any) => void): void; - /** - * Adds a listener to the window. The listener is removed after the first call. - * @param {string} event - the event to listen to - * @param {function(*): void} cb - the callback to call - * @returns {void} - */ - once(event: string, cb: (arg0: any) => void): void; - /** - * Removes a listener from the window. - * @param {string} event - the event to remove the listener from - * @param {function(*): void} cb - the callback to remove - * @returns {void} - */ - removeListener(event: string, cb: (arg0: any) => void): void; - /** - * Removes all listeners from the window. - * @param {string} event - the event to remove the listeners from - * @returns {void} - */ - removeAllListeners(event: string): void; - /** - * Removes a listener from the window. An alias for `removeListener`. - * @param {string} event - the event to remove the listener from - * @param {function(*): void} cb - the callback to remove - * @returns {void} - * @see removeListener - */ - off(event: string, cb: (arg0: any) => void): void; - #private; - } - export default ApplicationWindow; - export const constants: typeof statuses; - import ipc from "socket:ipc"; - import * as statuses from "socket:window/constants"; -} -declare module "socket:application" { + export function basename(path: PathComponent, suffix: string): string; /** - * Creates a new window and returns an instance of ApplicationWindow. - * @param {object} opts - an options object - * @param {number} opts.index - the index of the window - * @param {string} opts.path - the path to the HTML file to load into the window - * @param {string=} opts.title - the title of the window - * @param {(number|string)=} opts.width - the width of the window. If undefined, the window will have the main window width. - * @param {(number|string)=} opts.height - the height of the window. If undefined, the window will have the main window height. - * @param {(number|string)=} [opts.minWidth = 0] - the minimum width of the window - * @param {(number|string)=} [opts.minHeight = 0] - the minimum height of the window - * @param {(number|string)=} [opts.maxWidth = '100%'] - the maximum width of the window - * @param {(number|string)=} [opts.maxHeight = '100%'] - the maximum height of the window - * @param {boolean=} [opts.resizable=true] - whether the window is resizable - * @param {boolean=} [opts.frameless=false] - whether the window is frameless - * @param {boolean=} [opts.utility=false] - whether the window is utility (macOS only) - * @param {boolean=} [opts.canExit=false] - whether the window can exit the app - * @return {Promise} + * Computes extension name of path. + * @param {PathComponent} path + * @return {string} */ - export function createWindow(opts: { - index: number; - path: string; - title?: string | undefined; - width?: (number | string) | undefined; - height?: (number | string) | undefined; - minWidth?: (number | string) | undefined; - minHeight?: (number | string) | undefined; - maxWidth?: (number | string) | undefined; - maxHeight?: (number | string) | undefined; - resizable?: boolean | undefined; - frameless?: boolean | undefined; - utility?: boolean | undefined; - canExit?: boolean | undefined; - }): Promise; + export function extname(path: PathComponent): string; /** - * Returns the current screen size. - * @returns {Promise} + * Predicate helper to determine if path is absolute. + * @param {PathComponent} path + * @return {boolean} */ - export function getScreenSize(): Promise; + export function isAbsolute(path: PathComponent): boolean; /** - * Returns the ApplicationWindow instances for the given indices or all windows if no indices are provided. - * @param {number[]|undefined} indices - the indices of the windows - * @return {Promise>} - * @throws {Error} - if indices is not an array of integer numbers + * Parses input `path` into a `Path` instance. + * @param {PathComponent} path + * @return {Path} */ - export function getWindows(indices: number[] | undefined): Promise<{ - [x: number]: ApplicationWindow; - }>; + export function parse(path: PathComponent): Path; /** - * Returns the ApplicationWindow instance for the given index - * @param {number} index - the index of the window - * @throws {Error} - if index is not a valid integer number - * @returns {Promise} - the ApplicationWindow instance or null if the window does not exist + * Formats `Path` object into a string. + * @param {object|Path} path + * @return {string} */ - export function getWindow(index: number): Promise; + export function format(path: object | Path): string; /** - * Returns the ApplicationWindow instance for the current window. - * @return {Promise} + * Normalizes `path` resolving `..` and `./` preserving trailing + * slashes. + * @param {string} path */ - export function getCurrentWindow(): Promise; + export function normalize(path: string): string; /** - * Quits the backend process and then quits the render process, the exit code used is the final exit code to the OS. - * @param {object} code - an exit code - * @return {Promise} - */ - export function exit(code: object): Promise; - /** - * Set the native menu for the app. - * - * @param {object} options - an options object - * @param {string} options.value - the menu layout - * @param {number} options.index - the window to target (if applicable) - * @return {Promise} - * - * Socket Runtime provides a minimalist DSL that makes it easy to create - * cross platform native system and context menus. - * - * Menus are created at run time. They can be created from either the Main or - * Render process. The can be recreated instantly by calling the `setSystemMenu` method. - * - * The method takes a string. Here's an example of a menu. The semi colon is - * significant indicates the end of the menu. Use an underscore when there is no - * accelerator key. Modifiers are optional. And well known OS menu options like - * the edit menu will automatically get accelerators you dont need to specify them. - * - * - * ```js - * socket.application.setSystemMenu({ index: 0, value: ` - * App: - * Foo: f; - * - * Edit: - * Cut: x - * Copy: c - * Paste: v - * Delete: _ - * Select All: a; - * - * Other: - * Apple: _ - * Another Test: T - * !Im Disabled: I - * Some Thing: S + Meta - * --- - * Bazz: s + Meta, Control, Alt; - * `) - * ``` - * - * Separators - * - * To create a separator, use three dashes `---`. - * - * - * Accelerator Modifiers - * - * Accelerator modifiers are used as visual indicators but don't have a - * material impact as the actual key binding is done in the event listener. - * - * A capital letter implies that the accelerator is modified by the `Shift` key. - * - * Additional accelerators are `Meta`, `Control`, `Option`, each separated - * by commas. If one is not applicable for a platform, it will just be ignored. - * - * On MacOS `Meta` is the same as `Command`. - * - * - * Disabled Items - * - * If you want to disable a menu item just prefix the item with the `!` character. - * This will cause the item to appear disabled when the system menu renders. - * - * - * Submenus - * - * We feel like nested menus are an anti-pattern. We don't use them. If you have a - * strong argument for them and a very simple pull request that makes them work we - * may consider them. - * - * - * Event Handling - * - * When a menu item is activated, it raises the `menuItemSelected` event in - * the front end code, you can then communicate with your backend code if you - * want from there. - * - * For example, if the `Apple` item is selected from the `Other` menu... - * - * ```js - * window.addEventListener('menuItemSelected', event => { - * assert(event.detail.parent === 'Other') - * assert(event.detail.title === 'Apple') - * }) - * ``` - * - */ - export function setSystemMenu(o: any): Promise; - /** - * Set the enabled state of the system menu. - * @param {object} value - an options object - * @return {Promise} - */ - export function setSystemMenuItemEnabled(value: object): Promise; - /** - * Socket Runtime version. - * @type {object} - an object containing the version information - */ - export const runtimeVersion: object; - /** - * Runtime debug flag. - * @type {boolean} - */ - export const debug: boolean; - /** - * Application configuration. - * @type {object} - */ - export const config: object; - export namespace backend { - /** - * @param {object} opts - an options object - * @param {boolean} [opts.force = false] - whether to force the existing process to close - * @return {Promise} - */ - function open(opts?: { - force?: boolean; - }): Promise; - /** - * @return {Promise} - */ - function close(): Promise; - } - export default exports; - import ApplicationWindow from "socket:window"; - import ipc from "socket:ipc"; - import * as exports from "socket:application"; - -} -declare module "socket:diagnostics/channels" { - /** - * Normalizes a channel name to lower case replacing white space, - * hyphens (-), underscores (_), with dots (.). - * @ignore - */ - export function normalizeName(group: any, name: any): string; - /** - * Used to preallocate a minimum sized array of subscribers for - * a channel. - * @ignore - */ - export const MIN_CHANNEL_SUBSCRIBER_SIZE: 64; - /** - * A general interface for diagnostic channels that can be subscribed to. - */ - export class Channel { - constructor(name: any); - subscribers: any[]; - name: any; - group: any; - /** - * Accessor for determining if channel has subscribers. This - * is always `false` for `Channel instances and `true` for `ActiveChannel` - * instances. - */ - get hasSubscribers(): boolean; - /** - * Computed number of subscribers for this channel. - */ - get length(): number; - /** - * Resets channel state. - * @param {(boolean)} [shouldOrphan = false] - */ - reset(shouldOrphan?: (boolean)): void; - channel(name: any): Channel; - /** - * Adds an `onMessage` subscription callback to the channel. - * @return {boolean} - */ - subscribe(onMessage: any): boolean; - /** - * Removes an `onMessage` subscription callback from the channel. - * @param {function} onMessage - * @return {boolean} - */ - unsubscribe(onMessage: Function): boolean; - /** - * A no-op for `Channel` instances. This function always returns `false`. - * @param {string} name - * @param {object} message - * @return Promise - */ - publish(name: string, message: object): Promise; - /** - * Returns a string representation of the `ChannelRegistry`. - * @ignore - */ - toString(): string; - /** - * Iterator interface - * @ignore - */ - get [Symbol.iterator](): any[]; - /** - * The `Channel` string tag. - * @ignore - */ - [Symbol.toStringTag](): string; - #private; - } - /** - * An `ActiveChannel` is a prototype implementation for a `Channel` - * that provides an interface what is considered an "active" channel. The - * `hasSubscribers` accessor always returns `true` for this class. - */ - export class ActiveChannel extends Channel { - unsubscribe(onMessage: any): boolean; - /** - * @param {object|any} message - * @return Promise - */ - publish(message: object | any): Promise; - } - /** - * A container for a grouping of channels that are named and owned - * by this group. A `ChannelGroup` can also be a regular channel. - */ - export class ChannelGroup extends Channel { - /** - * @param {Array} channels - * @param {string} name - */ - constructor(name: string, channels: Array); - channels: Channel[]; - /** - * Computed subscribers for all channels in this group. - */ - get subscribers(): any[]; - /** - * Subscribe to a channel or selection of channels in this group. - * @param {string} name - * @return {boolean} - */ - subscribe(name: string, onMessage: any): boolean; - /** - * Unsubscribe from a channel or selection of channels in this group. - * @param {string} name - * @return {boolean} - */ - unsubscribe(name: string, onMessage: any): boolean; - /** - * Gets or creates a channel for this group. - * @param {string} name - * @return {Channel} - */ - channel(name: string): Channel; - /** - * Select a test of channels from this group. - * The following syntax is supported: - * - One Channel: `group.channel` - * - All Channels: `*` - * - Many Channel: `group.*` - * - Collections: `['group.a', 'group.b', 'group.c'] or `group.a,group.b,group.c` - * @param {string|Array} keys - * @param {(boolean)} [hasSubscribers = false] - Enforce subscribers in selection - * @return {Array<{name: string, channel: Channel}>} - */ - select(keys: string | Array, hasSubscribers?: (boolean)): Array<{ - name: string; - channel: Channel; - }>; - /** - * Iterator iterface. - * @ignore - */ - get [Symbol.iterator](): Channel[]; - } - /** - * An object mapping of named channels to `WeakRef` instances. - */ - export const registry: { - /** - * Subscribes callback `onMessage` to channel of `name`. - * @param {string} name - * @param {function} onMessage - * @return {boolean} - */ - subscribe(name: string, onMessage: Function): boolean; - /** - * Unsubscribes callback `onMessage` from channel of `name`. - * @param {string} name - * @param {function} onMessage - * @return {boolean} - */ - unsubscribe(name: string, onMessage: Function): boolean; - /** - * Predicate to determine if a named channel has subscribers. - * @param {string} name - */ - hasSubscribers(name: string): boolean; - /** - * Get or set a channel by `name`. - * @param {string} name - * @return {Channel} - */ - channel(name: string): Channel; - /** - * Creates a `ChannelGroup` for a set of channels - * @param {string} name - * @param {Array} [channels] - * @return {ChannelGroup} - */ - group(name: string, channels?: Array): ChannelGroup; - /** - * Get a channel by name. The name is normalized. - * @param {string} name - * @return {Channel?} - */ - get(name: string): Channel | null; - /** - * Checks if a channel is known by name. The name is normalized. - * @param {string} name - * @return {boolean} - */ - has(name: string): boolean; - /** - * Set a channel by name. The name is normalized. - * @param {string} name - * @param {Channel} channel - * @return {Channel?} - */ - set(name: string, channel: Channel): Channel | null; - /** - * Removes a channel by `name` - * @return {boolean} - */ - remove(name: any): boolean; - /** - * Returns a string representation of the `ChannelRegistry`. - * @ignore - */ - toString(): string; - /** - * Returns a JSON representation of the `ChannelRegistry`. - * @return {object} - */ - toJSON(): object; - /** - * The `ChannelRegistry` string tag. - * @ignore - */ - [Symbol.toStringTag](): string; - }; - export default registry; -} -declare module "socket:worker" { - /** - * @type {import('dom').Worker} - */ - export const Worker: any; - export default Worker; -} -declare module "socket:diagnostics/metric" { - export class Metric { - init(): void; - update(): void; - destroy(): void; - toJSON(): {}; - toString(): string; - [Symbol.iterator](): any; - [Symbol.toStringTag](): string; - } - export default Metric; -} -declare module "socket:diagnostics/window" { - export class RequestAnimationFrameMetric extends Metric { - constructor(options: any); - originalRequestAnimationFrame: typeof requestAnimationFrame; - requestAnimationFrame(callback: any): any; - sampleSize: any; - sampleTick: number; - channel: import("socket:diagnostics/channels").Channel; - value: { - rate: number; - samples: number; - }; - now: number; - samples: Uint8Array; - update(value: any): void; - toJSON(): { - sampleSize: any; - sampleTick: number; - samples: number[]; - rate: number; - now: number; - }; - } - export class FetchMetric extends Metric { - constructor(options: any); - originalFetch: typeof fetch; - channel: import("socket:diagnostics/channels").Channel; - fetch(resource: any, options: any, extra: any): Promise; - } - export class XMLHttpRequestMetric extends Metric { - constructor(options: any); - channel: import("socket:diagnostics/channels").Channel; - patched: { - open: { - (method: string, url: string | URL): void; - (method: string, url: string | URL, async: boolean, username?: string, password?: string): void; - }; - send: (body?: Document | XMLHttpRequestBodyInit) => void; - }; - } - export class WorkerMetric extends Metric { - /** - * @type {Worker} - */ - static GlobalWorker: Worker; - constructor(options: any); - channel: import("socket:diagnostics/channels").Channel; - Worker: { - new (url: any, options: any, ...args: any[]): {}; - }; - } - export const metrics: { - requestAnimationFrame: RequestAnimationFrameMetric; - XMLHttpRequest: XMLHttpRequestMetric; - Worker: WorkerMetric; - fetch: FetchMetric; - channel: import("socket:diagnostics/channels").ChannelGroup; - subscribe(...args: any[]): boolean; - unsubscribe(...args: any[]): boolean; - start(which: any): void; - stop(which: any): void; - }; - namespace _default { - export { metrics }; - } - export default _default; - import { Metric } from "socket:diagnostics/metric"; - import { Worker } from "socket:worker"; -} -declare module "socket:diagnostics/index" { - /** - * @param {string} name - * @return {import('./channels.js').Channel} - */ - export function channel(name: string): import("socket:diagnostics/channels").Channel; - export default exports; - import * as exports from "socket:diagnostics/index"; - import channels from "socket:diagnostics/channels"; - import window from "socket:diagnostics/window"; - - export { channels, window }; -} -declare module "socket:diagnostics" { - export * from "socket:diagnostics/index"; - export default exports; - import * as exports from "socket:diagnostics/index"; -} -declare module "socket:bluetooth" { - export default exports; - /** - * Create an instance of a Bluetooth service. - */ - export class Bluetooth extends EventEmitter { - static isInitalized: boolean; - /** - * constructor is an example property that is set to `true` - * Creates a new service with key-value pairs - * @param {string} serviceId - Given a default value to determine the type - */ - constructor(serviceId?: string); - serviceId: string; - /** - * Start the Bluetooth service. - * @return {Promise} - * - */ - start(): Promise; - /** - * Start scanning for published values that correspond to a well-known UUID. - * Once subscribed to a UUID, events that correspond to that UUID will be - * emitted. To receive these events you can add an event listener, for example... - * - * ```js - * const ble = new Bluetooth(id) - * ble.subscribe(uuid) - * ble.on(uuid, (data, details) => { - * // ...do something interesting - * }) - * ``` - * - * @param {string} [id = ''] - A well-known UUID - * @return {Promise} - */ - subscribe(id?: string): Promise; - /** - * Start advertising a new value for a well-known UUID - * @param {string} [id=''] - A well-known UUID - * @param {string} [value=''] - * @return {Promise} - */ - publish(id?: string, value?: string): Promise; - } - import * as exports from "socket:bluetooth"; - import { EventEmitter } from "socket:events"; - import ipc from "socket:ipc"; - -} -declare module "socket:path/path" { - /** - * @typedef {(string|Path|URL|{ pathname: string }|{ url: string)} PathComponent - */ - /** - * A container for a parsed Path. - */ - export class Path extends URL { - /** - * Computes current working directory for a path - * @param {object=} [opts] - * @param {boolean=} [opts.posix] Set to `true` to force POSIX style path - * @return {string} - */ - static cwd(opts?: object | undefined): string; - /** - * Resolves path components to an absolute path. - * @param {object} options - * @param {...PathComponent} components - * @return {string} - */ - static resolve(options: object, ...components: PathComponent[]): string; - /** - * Computes the relative path from `from` to `to`. - * @param {object} options - * @param {PathComponent} from - * @param {PathComponent} to - * @return {string} - */ - static relative(options: object, from: PathComponent, to: PathComponent): string; - /** - * Joins path components. This function may not return an absolute path. - * @param {object} options - * @param {...PathComponent} components - * @return {string} - */ - static join(options: object, ...components: PathComponent[]): string; - /** - * Computes directory name of path. - * @param {object} options - * @param {...PathComponent} components - * @return {string} - */ - static dirname(options: object, path: any): string; - /** - * Computes base name of path. - * @param {object} options - * @param {...PathComponent} components - * @return {string} - */ - static basename(options: object, path: any): string; - /** - * Computes extension name of path. - * @param {object} options - * @param {PathComponent} path - * @return {string} - */ - static extname(options: object, path: PathComponent): string; - /** - * Computes normalized path - * @param {object} options - * @param {PathComponent} path - * @return {string} - */ - static normalize(options: object, path: PathComponent): string; - /** - * Formats `Path` object into a string. - * @param {object} options - * @param {object|Path} path - * @return {string} - */ - static format(options: object, path: object | Path): string; - /** - * Parses input `path` into a `Path` instance. - * @param {PathComponent} path - * @return {object} - */ - static parse(path: PathComponent): object; - /** - * Creates a `Path` instance from `input` and optional `cwd`. - * @param {PathComponent} input - * @param {string} [cwd] - */ - static from(input: PathComponent, cwd?: string): any; - /** - * `Path` class constructor. - * @protected - * @param {string} pathname - * @param {string} [cwd = Path.cwd()] - */ - protected constructor(); - /** - * `true` if the path is relative, otherwise `false. - * @type {boolean} - */ - get isRelative(): boolean; - /** - * The working value of this path. - */ - get value(): string; - /** - * The original source, unresolved. - * @type {string} - */ - get source(): string; - /** - * Computed parent path. - * @type {string} - */ - get parent(): string; - /** - * Computed root in path. - * @type {string} - */ - get root(): string; - /** - * Computed directory name in path. - * @type {string} - */ - get dir(): string; - /** - * Computed base name in path. - * @type {string} - */ - get base(): string; - /** - * Computed base name in path without path extension. - * @type {string} - */ - get name(): string; - /** - * Computed extension name in path. - * @type {string} - */ - get ext(): string; - /** - * The computed drive, if given in the path. - * @type {string?} - */ - get drive(): string; - /** - * @return {URL} - */ - toURL(): URL; - /** - * @ignore - */ - inspect(): { - root: string; - dir: string; - base: string; - ext: string; - name: string; - }; - /** - * @ignore - */ - [Symbol.toStringTag](): string; - #private; - } - export default Path; - export type PathComponent = (string | Path | URL | { - pathname: string; - } | { - url: string; - }); -} -declare module "socket:path/win32" { - /** - * Computes current working directory for a path - * @param {string} - */ - export function cwd(): string; - /** - * Resolves path components to an absolute path. - * @param {...PathComponent} components - * @return {string} - */ - export function resolve(...components: PathComponent[]): string; - /** - * Joins path components. This function may not return an absolute path. - * @param {...PathComponent} components - * @return {string} - */ - export function join(...components: PathComponent[]): string; - /** - * Computes directory name of path. - * @param {PathComponent} path - * @return {string} - */ - export function dirname(path: PathComponent): string; - /** - * Computes base name of path. - * @param {PathComponent} path - * @param {string} suffix - * @return {string} - */ - export function basename(path: PathComponent, suffix: string): string; - /** - * Computes extension name of path. - * @param {PathComponent} path - * @return {string} - */ - export function extname(path: PathComponent): string; - /** - * Predicate helper to determine if path is absolute. - * @param {PathComponent} path - * @return {boolean} - */ - export function isAbsolute(path: PathComponent): boolean; - /** - * Parses input `path` into a `Path` instance. - * @param {PathComponent} path - * @return {Path} - */ - export function parse(path: PathComponent): Path; - /** - * Formats `Path` object into a string. - * @param {object|Path} path - * @return {string} - */ - export function format(path: object | Path): string; - /** - * Normalizes `path` resolving `..` and `.\` preserving trailing - * slashes. - * @param {string} path - */ - export function normalize(path: string): string; - /** - * Computes the relative path from `from` to `to`. - * @param {string} from - * @param {string} to - * @return {string} - */ - export function relative(from: string, to: string): string; - export * as _default from "socket:path/win32"; - export * as win32 from "socket:path/win32"; - export const sep: "\\"; - export const delimiter: ";"; - export type PathComponent = import("socket:path/path").PathComponent; - import posix from "socket:path/posix"; - import { Path } from "socket:path/path"; - - export { posix, Path }; -} -declare module "socket:path/posix" { - /** - * Computes current working directory for a path - * @param {string} - * @return {string} - */ - export function cwd(): string; - /** - * Resolves path components to an absolute path. - * @param {...PathComponent} components - * @return {string} - */ - export function resolve(...components: PathComponent[]): string; - /** - * Joins path components. This function may not return an absolute path. - * @param {...PathComponent} components - * @return {string} - */ - export function join(...components: PathComponent[]): string; - /** - * Computes directory name of path. - * @param {PathComponent} path - * @return {string} - */ - export function dirname(path: PathComponent): string; - /** - * Computes base name of path. - * @param {PathComponent} path - * @param {string} suffix - * @return {string} - */ - export function basename(path: PathComponent, suffix: string): string; - /** - * Computes extension name of path. - * @param {PathComponent} path - * @return {string} - */ - export function extname(path: PathComponent): string; - /** - * Predicate helper to determine if path is absolute. - * @param {PathComponent} path - * @return {boolean} - */ - export function isAbsolute(path: PathComponent): boolean; - /** - * Parses input `path` into a `Path` instance. - * @param {PathComponent} path - * @return {Path} - */ - export function parse(path: PathComponent): Path; - /** - * Formats `Path` object into a string. - * @param {object|Path} path - * @return {string} - */ - export function format(path: object | Path): string; - /** - * Normalizes `path` resolving `..` and `./` preserving trailing - * slashes. - * @param {string} path - */ - export function normalize(path: string): string; - /** - * Computes the relative path from `from` to `to`. - * @param {string} from - * @param {string} to - * @return {string} + * Computes the relative path from `from` to `to`. + * @param {string} from + * @param {string} to + * @return {string} */ export function relative(from: string, to: string): string; export * as _default from "socket:path/posix"; @@ -2137,69 +994,6 @@ declare module "socket:path" { import { win32 } from "socket:path/index"; export { Path, posix, win32 }; } -declare module "socket:fs" { - export * from "socket:fs/index"; - export default exports; - import * as exports from "socket:fs/index"; -} -declare module "socket:external/libsodium/index" { - export {}; -} -declare module "socket:crypto/sodium" { - const _default: any; - export default _default; -} -declare module "socket:crypto" { - /** - * Generate cryptographically strong random values into the `buffer` - * @param {TypedArray} buffer - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues} - * @return {TypedArray} - */ - export function getRandomValues(buffer: TypedArray, ...args: any[]): TypedArray; - export function rand64(): bigint; - /** - * Generate `size` random bytes. - * @param {number} size - The number of bytes to generate. The size must not be larger than 2**31 - 1. - * @returns {Buffer} - A promise that resolves with an instance of socket.Buffer with random bytes. - */ - export function randomBytes(size: number): Buffer; - /** - * @param {string} algorithm - `SHA-1` | `SHA-256` | `SHA-384` | `SHA-512` - * @param {Buffer | TypedArray | DataView} message - An instance of socket.Buffer, TypedArray or Dataview. - * @returns {Promise} - A promise that resolves with an instance of socket.Buffer with the hash. - */ - export function createDigest(algorithm: string, buf: any): Promise; - /** - * WebCrypto API - * @see {https://developer.mozilla.org/en-US/docs/Web/API/Crypto} - */ - export let webcrypto: any; - /** - * A promise that resolves when all internals to be loaded/ready. - * @type {Promise} - */ - export const ready: Promise; - /** - * Maximum total size of random bytes per page - */ - export const RANDOM_BYTES_QUOTA: number; - /** - * Maximum total size for random bytes. - */ - export const MAX_RANDOM_BYTES: 281474976710655; - /** - * Maximum total amount of allocated per page of bytes (max/quota) - */ - export const MAX_RANDOM_BYTES_PAGES: number; - export default exports; - import { Buffer } from "socket:buffer"; - export namespace sodium { - let ready: Promise; - } - import * as exports from "socket:crypto"; - -} declare module "socket:stream" { export function pipelinePromise(...streams: any[]): Promise; export function pipeline(stream: any, ...streams: any[]): any; @@ -2351,172 +1145,495 @@ declare module "socket:stream" { _transform(data: any, cb: any): void; _flush(cb: any): void; } - export class PassThrough extends exports.Transform { + export class PassThrough extends exports.Transform { + } + import * as exports from "socket:stream"; + import { EventEmitter } from "socket:events"; + +} +declare module "socket:fs/stream" { + export const DEFAULT_STREAM_HIGH_WATER_MARK: number; + /** + * @typedef {import('./handle.js').FileHandle} FileHandle + */ + /** + * A `Readable` stream for a `FileHandle`. + */ + export class ReadStream extends Readable { + end: any; + start: any; + handle: any; + buffer: ArrayBuffer; + signal: any; + timeout: any; + bytesRead: number; + shouldEmitClose: boolean; + /** + * Sets file handle for the ReadStream. + * @param {FileHandle} handle + */ + setHandle(handle: FileHandle): void; + /** + * The max buffer size for the ReadStream. + */ + get highWaterMark(): number; + /** + * Relative or absolute path of the underlying `FileHandle`. + */ + get path(): any; + /** + * `true` if the stream is in a pending state. + */ + get pending(): boolean; + _open(callback: any): Promise; + _read(callback: any): Promise; + } + export namespace ReadStream { + export { DEFAULT_STREAM_HIGH_WATER_MARK as highWaterMark }; + } + /** + * A `Writable` stream for a `FileHandle`. + */ + export class WriteStream extends Writable { + start: any; + handle: any; + signal: any; + timeout: any; + bytesWritten: number; + shouldEmitClose: boolean; + /** + * Sets file handle for the WriteStream. + * @param {FileHandle} handle + */ + setHandle(handle: FileHandle): void; + /** + * The max buffer size for the Writetream. + */ + get highWaterMark(): number; + /** + * Relative or absolute path of the underlying `FileHandle`. + */ + get path(): any; + /** + * `true` if the stream is in a pending state. + */ + get pending(): boolean; + _open(callback: any): Promise; + _write(buffer: any, callback: any): any; + } + export namespace WriteStream { + export { DEFAULT_STREAM_HIGH_WATER_MARK as highWaterMark }; } - import * as exports from "socket:stream"; - import { EventEmitter } from "socket:events"; + export const FileReadStream: typeof exports.ReadStream; + export const FileWriteStream: typeof exports.WriteStream; + export default exports; + export type FileHandle = import("socket:fs/handle").FileHandle; + import { Readable } from "socket:stream"; + import * as exports from "socket:fs/stream"; + import { Writable } from "socket:stream"; } -declare module "socket:fs/stream" { - export const DEFAULT_STREAM_HIGH_WATER_MARK: number; +declare module "socket:fs/constants" { /** - * @typedef {import('./handle.js').FileHandle} FileHandle + * This flag can be used with uv_fs_copyfile() to return an error if the + * destination already exists. */ + export const COPYFILE_EXCL: 1; /** - * A `Readable` stream for a `FileHandle`. + * This flag can be used with uv_fs_copyfile() to attempt to create a reflink. + * If copy-on-write is not supported, a fallback copy mechanism is used. */ - export class ReadStream extends Readable { - end: any; - start: any; - handle: any; - buffer: ArrayBuffer; - signal: any; - timeout: any; - bytesRead: number; - shouldEmitClose: boolean; + export const COPYFILE_FICLONE: 2; + /** + * This flag can be used with uv_fs_copyfile() to attempt to create a reflink. + * If copy-on-write is not supported, an error is returned. + */ + export const COPYFILE_FICLONE_FORCE: 4; + export const UV_DIRENT_UNKNOWN: any; + export const UV_DIRENT_FILE: any; + export const UV_DIRENT_DIR: any; + export const UV_DIRENT_LINK: any; + export const UV_DIRENT_FIFO: any; + export const UV_DIRENT_SOCKET: any; + export const UV_DIRENT_CHAR: any; + export const UV_DIRENT_BLOCK: any; + export const O_RDONLY: any; + export const O_WRONLY: any; + export const O_RDWR: any; + export const O_APPEND: any; + export const O_ASYNC: any; + export const O_CLOEXEC: any; + export const O_CREAT: any; + export const O_DIRECT: any; + export const O_DIRECTORY: any; + export const O_DSYNC: any; + export const O_EXCL: any; + export const O_LARGEFILE: any; + export const O_NOATIME: any; + export const O_NOCTTY: any; + export const O_NOFOLLOW: any; + export const O_NONBLOCK: any; + export const O_NDELAY: any; + export const O_PATH: any; + export const O_SYNC: any; + export const O_TMPFILE: any; + export const O_TRUNC: any; + export const S_IFMT: any; + export const S_IFREG: any; + export const S_IFDIR: any; + export const S_IFCHR: any; + export const S_IFBLK: any; + export const S_IFIFO: any; + export const S_IFLNK: any; + export const S_IFSOCK: any; + export const S_IRWXU: any; + export const S_IRUSR: any; + export const S_IWUSR: any; + export const S_IXUSR: any; + export const S_IRWXG: any; + export const S_IRGRP: any; + export const S_IWGRP: any; + export const S_IXGRP: any; + export const S_IRWXO: any; + export const S_IROTH: any; + export const S_IWOTH: any; + export const S_IXOTH: any; + export const F_OK: any; + export const R_OK: any; + export const W_OK: any; + export const X_OK: any; + export default exports; + import * as exports from "socket:fs/constants"; + +} +declare module "socket:fs/flags" { + export function normalizeFlags(flags: any): any; + export default exports; + import * as exports from "socket:fs/flags"; + +} +declare module "socket:diagnostics/channels" { + /** + * Normalizes a channel name to lower case replacing white space, + * hyphens (-), underscores (_), with dots (.). + * @ignore + */ + export function normalizeName(group: any, name: any): string; + /** + * Used to preallocate a minimum sized array of subscribers for + * a channel. + * @ignore + */ + export const MIN_CHANNEL_SUBSCRIBER_SIZE: 64; + /** + * A general interface for diagnostic channels that can be subscribed to. + */ + export class Channel { + constructor(name: any); + subscribers: any[]; + name: any; + group: any; + /** + * Accessor for determining if channel has subscribers. This + * is always `false` for `Channel instances and `true` for `ActiveChannel` + * instances. + */ + get hasSubscribers(): boolean; + /** + * Computed number of subscribers for this channel. + */ + get length(): number; + /** + * Resets channel state. + * @param {(boolean)} [shouldOrphan = false] + */ + reset(shouldOrphan?: (boolean)): void; + channel(name: any): Channel; + /** + * Adds an `onMessage` subscription callback to the channel. + * @return {boolean} + */ + subscribe(onMessage: any): boolean; + /** + * Removes an `onMessage` subscription callback from the channel. + * @param {function} onMessage + * @return {boolean} + */ + unsubscribe(onMessage: Function): boolean; + /** + * A no-op for `Channel` instances. This function always returns `false`. + * @param {string} name + * @param {object} message + * @return Promise + */ + publish(name: string, message: object): Promise; + /** + * Returns a string representation of the `ChannelRegistry`. + * @ignore + */ + toString(): string; + /** + * Iterator interface + * @ignore + */ + get [Symbol.iterator](): any[]; + /** + * The `Channel` string tag. + * @ignore + */ + [Symbol.toStringTag](): string; + #private; + } + /** + * An `ActiveChannel` is a prototype implementation for a `Channel` + * that provides an interface what is considered an "active" channel. The + * `hasSubscribers` accessor always returns `true` for this class. + */ + export class ActiveChannel extends Channel { + unsubscribe(onMessage: any): boolean; + /** + * @param {object|any} message + * @return Promise + */ + publish(message: object | any): Promise; + } + /** + * A container for a grouping of channels that are named and owned + * by this group. A `ChannelGroup` can also be a regular channel. + */ + export class ChannelGroup extends Channel { + /** + * @param {Array} channels + * @param {string} name + */ + constructor(name: string, channels: Array); + channels: Channel[]; + /** + * Computed subscribers for all channels in this group. + */ + get subscribers(): any[]; + /** + * Subscribe to a channel or selection of channels in this group. + * @param {string} name + * @return {boolean} + */ + subscribe(name: string, onMessage: any): boolean; + /** + * Unsubscribe from a channel or selection of channels in this group. + * @param {string} name + * @return {boolean} + */ + unsubscribe(name: string, onMessage: any): boolean; + /** + * Gets or creates a channel for this group. + * @param {string} name + * @return {Channel} + */ + channel(name: string): Channel; + /** + * Select a test of channels from this group. + * The following syntax is supported: + * - One Channel: `group.channel` + * - All Channels: `*` + * - Many Channel: `group.*` + * - Collections: `['group.a', 'group.b', 'group.c'] or `group.a,group.b,group.c` + * @param {string|Array} keys + * @param {(boolean)} [hasSubscribers = false] - Enforce subscribers in selection + * @return {Array<{name: string, channel: Channel}>} + */ + select(keys: string | Array, hasSubscribers?: (boolean)): Array<{ + name: string; + channel: Channel; + }>; + /** + * Iterator iterface. + * @ignore + */ + get [Symbol.iterator](): Channel[]; + } + /** + * An object mapping of named channels to `WeakRef` instances. + */ + export const registry: { + /** + * Subscribes callback `onMessage` to channel of `name`. + * @param {string} name + * @param {function} onMessage + * @return {boolean} + */ + subscribe(name: string, onMessage: Function): boolean; + /** + * Unsubscribes callback `onMessage` from channel of `name`. + * @param {string} name + * @param {function} onMessage + * @return {boolean} + */ + unsubscribe(name: string, onMessage: Function): boolean; /** - * Sets file handle for the ReadStream. - * @param {FileHandle} handle + * Predicate to determine if a named channel has subscribers. + * @param {string} name */ - setHandle(handle: FileHandle): void; + hasSubscribers(name: string): boolean; /** - * The max buffer size for the ReadStream. + * Get or set a channel by `name`. + * @param {string} name + * @return {Channel} */ - get highWaterMark(): number; + channel(name: string): Channel; /** - * Relative or absolute path of the underlying `FileHandle`. + * Creates a `ChannelGroup` for a set of channels + * @param {string} name + * @param {Array} [channels] + * @return {ChannelGroup} */ - get path(): any; + group(name: string, channels?: Array): ChannelGroup; /** - * `true` if the stream is in a pending state. + * Get a channel by name. The name is normalized. + * @param {string} name + * @return {Channel?} */ - get pending(): boolean; - _open(callback: any): Promise; - _read(callback: any): Promise; - } - export namespace ReadStream { - export { DEFAULT_STREAM_HIGH_WATER_MARK as highWaterMark }; - } - /** - * A `Writable` stream for a `FileHandle`. - */ - export class WriteStream extends Writable { - start: any; - handle: any; - signal: any; - timeout: any; - bytesWritten: number; - shouldEmitClose: boolean; + get(name: string): Channel | null; /** - * Sets file handle for the WriteStream. - * @param {FileHandle} handle + * Checks if a channel is known by name. The name is normalized. + * @param {string} name + * @return {boolean} */ - setHandle(handle: FileHandle): void; + has(name: string): boolean; /** - * The max buffer size for the Writetream. + * Set a channel by name. The name is normalized. + * @param {string} name + * @param {Channel} channel + * @return {Channel?} */ - get highWaterMark(): number; + set(name: string, channel: Channel): Channel | null; /** - * Relative or absolute path of the underlying `FileHandle`. + * Removes a channel by `name` + * @return {boolean} */ - get path(): any; + remove(name: any): boolean; /** - * `true` if the stream is in a pending state. + * Returns a string representation of the `ChannelRegistry`. + * @ignore */ - get pending(): boolean; - _open(callback: any): Promise; - _write(buffer: any, callback: any): any; - } - export namespace WriteStream { - export { DEFAULT_STREAM_HIGH_WATER_MARK as highWaterMark }; - } - export const FileReadStream: typeof exports.ReadStream; - export const FileWriteStream: typeof exports.WriteStream; - export default exports; - export type FileHandle = import("socket:fs/handle").FileHandle; - import { Readable } from "socket:stream"; - import * as exports from "socket:fs/stream"; - import { Writable } from "socket:stream"; - + toString(): string; + /** + * Returns a JSON representation of the `ChannelRegistry`. + * @return {object} + */ + toJSON(): object; + /** + * The `ChannelRegistry` string tag. + * @ignore + */ + [Symbol.toStringTag](): string; + }; + export default registry; } -declare module "socket:fs/constants" { - /** - * This flag can be used with uv_fs_copyfile() to return an error if the - * destination already exists. - */ - export const COPYFILE_EXCL: 1; +declare module "socket:worker" { /** - * This flag can be used with uv_fs_copyfile() to attempt to create a reflink. - * If copy-on-write is not supported, a fallback copy mechanism is used. + * @type {import('dom').Worker} */ - export const COPYFILE_FICLONE: 2; + export const Worker: any; + export default Worker; +} +declare module "socket:diagnostics/metric" { + export class Metric { + init(): void; + update(): void; + destroy(): void; + toJSON(): {}; + toString(): string; + [Symbol.iterator](): any; + [Symbol.toStringTag](): string; + } + export default Metric; +} +declare module "socket:diagnostics/window" { + export class RequestAnimationFrameMetric extends Metric { + constructor(options: any); + originalRequestAnimationFrame: typeof requestAnimationFrame; + requestAnimationFrame(callback: any): any; + sampleSize: any; + sampleTick: number; + channel: import("socket:diagnostics/channels").Channel; + value: { + rate: number; + samples: number; + }; + now: number; + samples: Uint8Array; + update(value: any): void; + toJSON(): { + sampleSize: any; + sampleTick: number; + samples: number[]; + rate: number; + now: number; + }; + } + export class FetchMetric extends Metric { + constructor(options: any); + originalFetch: typeof fetch; + channel: import("socket:diagnostics/channels").Channel; + fetch(resource: any, options: any, extra: any): Promise; + } + export class XMLHttpRequestMetric extends Metric { + constructor(options: any); + channel: import("socket:diagnostics/channels").Channel; + patched: { + open: { + (method: string, url: string | URL): void; + (method: string, url: string | URL, async: boolean, username?: string, password?: string): void; + }; + send: (body?: Document | XMLHttpRequestBodyInit) => void; + }; + } + export class WorkerMetric extends Metric { + /** + * @type {Worker} + */ + static GlobalWorker: Worker; + constructor(options: any); + channel: import("socket:diagnostics/channels").Channel; + Worker: { + new (url: any, options: any, ...args: any[]): {}; + }; + } + export const metrics: { + requestAnimationFrame: RequestAnimationFrameMetric; + XMLHttpRequest: XMLHttpRequestMetric; + Worker: WorkerMetric; + fetch: FetchMetric; + channel: import("socket:diagnostics/channels").ChannelGroup; + subscribe(...args: any[]): boolean; + unsubscribe(...args: any[]): boolean; + start(which: any): void; + stop(which: any): void; + }; + namespace _default { + export { metrics }; + } + export default _default; + import { Metric } from "socket:diagnostics/metric"; + import { Worker } from "socket:worker"; +} +declare module "socket:diagnostics/index" { /** - * This flag can be used with uv_fs_copyfile() to attempt to create a reflink. - * If copy-on-write is not supported, an error is returned. + * @param {string} name + * @return {import('./channels.js').Channel} */ - export const COPYFILE_FICLONE_FORCE: 4; - export const UV_DIRENT_UNKNOWN: any; - export const UV_DIRENT_FILE: any; - export const UV_DIRENT_DIR: any; - export const UV_DIRENT_LINK: any; - export const UV_DIRENT_FIFO: any; - export const UV_DIRENT_SOCKET: any; - export const UV_DIRENT_CHAR: any; - export const UV_DIRENT_BLOCK: any; - export const O_RDONLY: any; - export const O_WRONLY: any; - export const O_RDWR: any; - export const O_APPEND: any; - export const O_ASYNC: any; - export const O_CLOEXEC: any; - export const O_CREAT: any; - export const O_DIRECT: any; - export const O_DIRECTORY: any; - export const O_DSYNC: any; - export const O_EXCL: any; - export const O_LARGEFILE: any; - export const O_NOATIME: any; - export const O_NOCTTY: any; - export const O_NOFOLLOW: any; - export const O_NONBLOCK: any; - export const O_NDELAY: any; - export const O_PATH: any; - export const O_SYNC: any; - export const O_TMPFILE: any; - export const O_TRUNC: any; - export const S_IFMT: any; - export const S_IFREG: any; - export const S_IFDIR: any; - export const S_IFCHR: any; - export const S_IFBLK: any; - export const S_IFIFO: any; - export const S_IFLNK: any; - export const S_IFSOCK: any; - export const S_IRWXU: any; - export const S_IRUSR: any; - export const S_IWUSR: any; - export const S_IXUSR: any; - export const S_IRWXG: any; - export const S_IRGRP: any; - export const S_IWGRP: any; - export const S_IXGRP: any; - export const S_IRWXO: any; - export const S_IROTH: any; - export const S_IWOTH: any; - export const S_IXOTH: any; - export const F_OK: any; - export const R_OK: any; - export const W_OK: any; - export const X_OK: any; + export function channel(name: string): import("socket:diagnostics/channels").Channel; export default exports; - import * as exports from "socket:fs/constants"; + import * as exports from "socket:diagnostics/index"; + import channels from "socket:diagnostics/channels"; + import window from "socket:diagnostics/window"; + export { channels, window }; } -declare module "socket:fs/flags" { - export function normalizeFlags(flags: any): any; +declare module "socket:diagnostics" { + export * from "socket:diagnostics/index"; export default exports; - import * as exports from "socket:fs/flags"; - + import * as exports from "socket:diagnostics/index"; } declare module "socket:fs/stats" { /** @@ -3140,306 +2257,1197 @@ declare module "socket:fs/promises" { * @param {AbortSignal=} [options.signal] * @return {Promise} */ - export function readFile(path: string, options?: object | undefined): Promise; + export function readFile(path: string, options?: object | undefined): Promise; + /** + * @TODO + * @ignore + */ + export function readlink(path: any, options: any): Promise; + /** + * @TODO + * @ignore + */ + export function realpath(path: any, options: any): Promise; + /** + * @TODO + * @ignore + */ + export function rename(oldPath: any, newPath: any): Promise; + /** + * @TODO + * @ignore + */ + export function rmdir(path: any, options: any): Promise; + /** + * @TODO + * @ignore + */ + export function rm(path: any, options: any): Promise; + /** + * @see {@link https://nodejs.org/api/fs.html#fspromisesstatpath-options} + * @param {string | Buffer | URL} path + * @param {object=} [options] + * @param {boolean=} [options.bigint = false] + * @return {Promise} + */ + export function stat(path: string | Buffer | URL, options?: object | undefined): Promise; + /** + * @TODO + * @ignore + */ + export function symlink(target: any, path: any, type: any): Promise; + /** + * @TODO + * @ignore + */ + export function truncate(path: any, length: any): Promise; + /** + * @TODO + * @ignore + */ + export function unlink(path: any): Promise; + /** + * @TODO + * @ignore + */ + export function utimes(path: any, atime: any, mtime: any): Promise; + /** + * @TODO + * @ignore + */ + export function watch(path: any, options: any): Promise; + /** + * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fspromiseswritefilefile-data-options} + * @param {string | Buffer | URL | FileHandle} path - filename or FileHandle + * @param {string|Buffer|Array|DataView|TypedArray|Stream} data + * @param {object=} [options] + * @param {string|null} [options.encoding = 'utf8'] + * @param {number} [options.mode = 0o666] + * @param {string} [options.flag = 'w'] + * @param {AbortSignal=} [options.signal] + * @return {Promise} + */ + export function writeFile(path: string | Buffer | URL | FileHandle, data: string | Buffer | any[] | DataView | TypedArray | Stream, options?: object | undefined): Promise; + export * as constants from "socket:fs/constants"; + export default exports; + import { FileHandle } from "socket:fs/handle"; + import { Dir } from "socket:fs/dir"; + import * as exports from "socket:fs/promises"; + +} +declare module "socket:fs/binding" { + const _default: ProxyConstructor; + export default _default; +} +declare module "socket:fs/index" { + /** + * Asynchronously check access a file for a given mode calling `callback` + * upon success or error. + * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsopenpath-flags-mode-callback} + * @param {string | Buffer | URL} path + * @param {string=} [mode = F_OK(0)] + * @param {function(err, fd)} callback + */ + export function access(path: string | Buffer | URL, mode?: string | undefined, callback: (arg0: err, arg1: fd) => any): void; + /** + * @ignore + */ + export function appendFile(path: any, data: any, options: any, callback: any): void; + /** + * + * Asynchronously changes the permissions of a file. + * No arguments other than a possible exception are given to the completion callback + * + * @see {@link https://nodejs.org/api/fs.html#fschmodpath-mode-callback} + * + * @param {string | Buffer | URL} path + * @param {number} mode + * @param {function(err)} callback + */ + export function chmod(path: string | Buffer | URL, mode: number, callback: (arg0: err) => any): void; + /** + * @ignore + */ + export function chown(path: any, uid: any, gid: any, callback: any): void; + /** + * Asynchronously close a file descriptor calling `callback` upon success or error. + * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsclosefd-callback} + * @param {number} fd + * @param {function(err)=} callback + */ + export function close(fd: number, callback?: ((arg0: err) => any) | undefined): void; + export function copyFile(src: any, dst: any, mode: any, callback: any): void; + /** + * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fscreatewritestreampath-options} + * @param {string | Buffer | URL} path + * @param {object=} options + * @returns {fs.ReadStream} + */ + export function createReadStream(path: string | Buffer | URL, options?: object | undefined): fs.ReadStream; + /** + * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fscreatewritestreampath-options} + * @param {string | Buffer | URL} path + * @param {object=} options + * @returns {fs.WriteStream} + */ + export function createWriteStream(path: string | Buffer | URL, options?: object | undefined): fs.WriteStream; + /** + * Invokes the callback with the for the file descriptor. See + * the POSIX fstat(2) documentation for more detail. + * + * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsfstatfd-options-callback} + * + * @param {number} fd - A file descriptor. + * @param {Object=} options - An options object. + * @param {function} callback - The function to call after completion. + */ + export function fstat(fd: number, options?: any | undefined, callback: Function): void; + /** + * @ignore + */ + export function lchmod(path: any, mode: any, callback: any): void; + /** + * @ignore + */ + export function lchown(path: any, uid: any, gid: any, callback: any): void; + /** + * @ignore + */ + export function lutimes(path: any, atime: any, mtime: any, callback: any): void; + /** + * @ignore + */ + export function link(existingPath: any, newPath: any, callback: any): void; + /** + * @ignore + */ + export function lstat(path: any, options: any, callback: any): void; + /** + * @ignore + */ + export function mkdir(path: any, options: any, callback: any): void; + /** + * Asynchronously open a file calling `callback` upon success or error. + * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsopenpath-flags-mode-callback} + * @param {string | Buffer | URL} path + * @param {string=} [flags = 'r'] + * @param {string=} [mode = 0o666] + * @param {function(err, fd)} callback + */ + export function open(path: string | Buffer | URL, flags?: string | undefined, mode?: string | undefined, options: any, callback: (arg0: err, arg1: fd) => any): void; + /** + * Asynchronously open a directory calling `callback` upon success or error. + * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsreaddirpath-options-callback} + * @param {string | Buffer | URL} path + * @param {Object=} options + * @param {string=} [options.encoding = 'utf8'] + * @param {boolean=} [options.withFileTypes = false] + * @param {function(err, fd)} callback + */ + export function opendir(path: string | Buffer | URL, options?: any | undefined, callback: (arg0: err, arg1: fd) => any): void; + /** + * Asynchronously read from an open file descriptor. + * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsreadfd-buffer-offset-length-position-callback} + * @param {number} fd + * @param {object | Buffer | TypedArray} buffer - The buffer that the data will be written to. + * @param {number} offset - The position in buffer to write the data to. + * @param {number} length - The number of bytes to read. + * @param {number | BigInt | null} position - Specifies where to begin reading from in the file. If position is null or -1 , data will be read from the current file position, and the file position will be updated. If position is an integer, the file position will be unchanged. + * @param {function(err, bytesRead, buffer)} callback + */ + export function read(fd: number, buffer: object | Buffer | TypedArray, offset: number, length: number, position: number | BigInt | null, options: any, callback: (arg0: err, arg1: bytesRead, arg2: any) => any): void; + /** + * Asynchronously read all entries in a directory. + * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsreaddirpath-options-callback} + * @param {string | Buffer | URL } path + * @param {object=} [options] + * @param {string=} [options.encoding = 'utf8'] + * @param {boolean=} [options.withFileTypes = false] + * @param {function(err, buffer)} callback + */ + export function readdir(path: string | Buffer | URL, options?: object | undefined, callback: (arg0: err, arg1: buffer) => any): void; + /** + * @param {string | Buffer | URL | number } path + * @param {object=} [options] + * @param {string=} [options.encoding = 'utf8'] + * @param {string=} [options.flag = 'r'] + * @param {AbortSignal=} [options.signal] + * @param {function(err, buffer)} callback + */ + export function readFile(path: string | Buffer | URL | number, options?: object | undefined, callback: (arg0: err, arg1: buffer) => any): void; + /** + * @ignore + */ + export function readlink(path: any, options: any, callback: any): void; + /** + * @ignore + */ + export function realpath(path: any, options: any, callback: any): void; + /** + * @ignore + */ + export function rename(oldPath: any, newPath: any, callback: any): void; + /** + * @ignore + */ + export function rmdir(path: any, options: any, callback: any): void; + /** + * @ignore + */ + export function rm(path: any, options: any, callback: any): void; + /** + * + * @param {string | Buffer | URL | number } path - filename or file descriptor + * @param {object=} options + * @param {string=} [options.encoding = 'utf8'] + * @param {string=} [options.flag = 'r'] + * @param {AbortSignal=} [options.signal] + * @param {function(err, data)} callback + */ + export function stat(path: string | Buffer | URL | number, options?: object | undefined, callback: (arg0: err, arg1: data) => any): void; + /** + * @ignore + */ + export function symlink(target: any, path: any, type: any, callback: any): void; /** - * @TODO * @ignore */ - export function readlink(path: any, options: any): Promise; + export function truncate(path: any, length: any, callback: any): void; /** - * @TODO * @ignore */ - export function realpath(path: any, options: any): Promise; + export function unlink(path: any, callback: any): void; /** - * @TODO * @ignore */ - export function rename(oldPath: any, newPath: any): Promise; + export function utimes(path: any, atime: any, mtime: any, callback: any): void; /** - * @TODO * @ignore */ - export function rmdir(path: any, options: any): Promise; + export function watch(path: any, options: any, callback: any): void; /** - * @TODO * @ignore */ - export function rm(path: any, options: any): Promise; + export function write(fd: any, buffer: any, offset: any, length: any, position: any, callback: any): void; /** - * @see {@link https://nodejs.org/api/fs.html#fspromisesstatpath-options} - * @param {string | Buffer | URL} path - * @param {object=} [options] - * @param {boolean=} [options.bigint = false] - * @return {Promise} + * @see {@url https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fswritefilefile-data-options-callback} + * @param {string | Buffer | URL | number } path - filename or file descriptor + * @param {string | Buffer | TypedArray | DataView | object } data + * @param {object=} options + * @param {string=} [options.encoding = 'utf8'] + * @param {string=} [options.mode = 0o666] + * @param {string=} [options.flag = 'w'] + * @param {AbortSignal=} [options.signal] + * @param {function(err)} callback */ - export function stat(path: string | Buffer | URL, options?: object | undefined): Promise; + export function writeFile(path: string | Buffer | URL | number, data: string | Buffer | TypedArray | DataView | object, options?: object | undefined, callback: (arg0: err) => any): void; + export function writev(fd: any, buffers: any, position: any, callback: any): void; + export { default as binding } from "socket:./binding.js"; + export default exports; + import * as constants from "socket:fs/constants"; + import { Dir } from "socket:fs/dir"; + import { DirectoryHandle } from "socket:fs/handle"; + import { Dirent } from "socket:fs/dir"; + import fds from "socket:fs/fds"; + import { FileHandle } from "socket:fs/handle"; + import * as promises from "socket:fs/promises"; + import { ReadStream } from "socket:fs/stream"; + import { Stats } from "socket:fs/stats"; + import { WriteStream } from "socket:fs/stream"; + import * as exports from "socket:fs/index"; + + export { constants, Dir, DirectoryHandle, Dirent, fds, FileHandle, promises, ReadStream, Stats, WriteStream }; +} +declare module "socket:fs" { + export * from "socket:fs/index"; + export default exports; + import * as exports from "socket:fs/index"; +} +declare module "socket:external/libsodium/index" { + export {}; +} +declare module "socket:crypto/sodium" { + const _default: any; + export default _default; +} +declare module "socket:crypto" { /** - * @TODO - * @ignore + * Generate cryptographically strong random values into the `buffer` + * @param {TypedArray} buffer + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues} + * @return {TypedArray} */ - export function symlink(target: any, path: any, type: any): Promise; + export function getRandomValues(buffer: TypedArray, ...args: any[]): TypedArray; + export function rand64(): bigint; /** - * @TODO - * @ignore + * Generate `size` random bytes. + * @param {number} size - The number of bytes to generate. The size must not be larger than 2**31 - 1. + * @returns {Buffer} - A promise that resolves with an instance of socket.Buffer with random bytes. */ - export function truncate(path: any, length: any): Promise; + export function randomBytes(size: number): Buffer; /** - * @TODO - * @ignore + * @param {string} algorithm - `SHA-1` | `SHA-256` | `SHA-384` | `SHA-512` + * @param {Buffer | TypedArray | DataView} message - An instance of socket.Buffer, TypedArray or Dataview. + * @returns {Promise} - A promise that resolves with an instance of socket.Buffer with the hash. */ - export function unlink(path: any): Promise; + export function createDigest(algorithm: string, buf: any): Promise; /** - * @TODO - * @ignore + * WebCrypto API + * @see {https://developer.mozilla.org/en-US/docs/Web/API/Crypto} */ - export function utimes(path: any, atime: any, mtime: any): Promise; + export let webcrypto: any; /** - * @TODO - * @ignore + * A promise that resolves when all internals to be loaded/ready. + * @type {Promise} */ - export function watch(path: any, options: any): Promise; + export const ready: Promise; /** - * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fspromiseswritefilefile-data-options} - * @param {string | Buffer | URL | FileHandle} path - filename or FileHandle - * @param {string|Buffer|Array|DataView|TypedArray|Stream} data - * @param {object=} [options] - * @param {string|null} [options.encoding = 'utf8'] - * @param {number} [options.mode = 0o666] - * @param {string} [options.flag = 'w'] - * @param {AbortSignal=} [options.signal] - * @return {Promise} + * Maximum total size of random bytes per page */ - export function writeFile(path: string | Buffer | URL | FileHandle, data: string | Buffer | any[] | DataView | TypedArray | Stream, options?: object | undefined): Promise; - export * as constants from "socket:fs/constants"; + export const RANDOM_BYTES_QUOTA: number; + /** + * Maximum total size for random bytes. + */ + export const MAX_RANDOM_BYTES: 281474976710655; + /** + * Maximum total amount of allocated per page of bytes (max/quota) + */ + export const MAX_RANDOM_BYTES_PAGES: number; export default exports; - import { FileHandle } from "socket:fs/handle"; - import { Dir } from "socket:fs/dir"; - import * as exports from "socket:fs/promises"; + import { Buffer } from "socket:buffer"; + export namespace sodium { + let ready: Promise; + } + import * as exports from "socket:crypto"; } -declare module "socket:fs/binding" { - const _default: ProxyConstructor; - export default _default; -} -declare module "socket:fs/index" { +declare module "socket:ipc" { /** - * Asynchronously check access a file for a given mode calling `callback` - * upon success or error. - * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsopenpath-flags-mode-callback} - * @param {string | Buffer | URL} path - * @param {string=} [mode = F_OK(0)] - * @param {function(err, fd)} callback + * Parses `seq` as integer value + * @param {string|number} seq + * @param {object=} [options] + * @param {boolean} [options.bigint = false] + * @ignore */ - export function access(path: string | Buffer | URL, mode?: string | undefined, callback: (arg0: err, arg1: fd) => any): void; + export function parseSeq(seq: string | number, options?: object | undefined): number | bigint; /** + * If `debug.enabled === true`, then debug output will be printed to console. + * @param {(boolean)} [enable] + * @return {boolean} * @ignore */ - export function appendFile(path: any, data: any, options: any, callback: any): void; + export function debug(enable?: (boolean)): boolean; + export namespace debug { + function log(): any; + let enabled: any; + } /** - * - * Asynchronously changes the permissions of a file. - * No arguments other than a possible exception are given to the completion callback - * - * @see {@link https://nodejs.org/api/fs.html#fschmodpath-mode-callback} - * - * @param {string | Buffer | URL} path - * @param {number} mode - * @param {function(err)} callback + * @ignore */ - export function chmod(path: string | Buffer | URL, mode: number, callback: (arg0: err) => any): void; + export function postMessage(message: any, ...args: any[]): Promise; /** + * Waits for the native IPC layer to be ready and exposed on the + * global window object. * @ignore */ - export function chown(path: any, uid: any, gid: any, callback: any): void; + export function ready(): Promise; /** - * Asynchronously close a file descriptor calling `callback` upon success or error. - * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsclosefd-callback} - * @param {number} fd - * @param {function(err)=} callback + * Sends a synchronous IPC command over XHR returning a `Result` + * upon success or error. + * @param {string} command + * @param {object|string?} [params] + * @param {object?} [options] + * @return {Result} + * @ignore */ - export function close(fd: number, callback?: ((arg0: err) => any) | undefined): void; - export function copyFile(src: any, dst: any, mode: any, callback: any): void; + export function sendSync(command: string, params?: object | (string | null), options?: object | null): Result; /** - * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fscreatewritestreampath-options} - * @param {string | Buffer | URL} path - * @param {object=} options - * @returns {fs.ReadStream} + * Emit event to be dispatched on `window` object. + * @param {string} name + * @param {any} value + * @param {EventTarget=} [target = window] + * @param {Object=} options */ - export function createReadStream(path: string | Buffer | URL, options?: object | undefined): fs.ReadStream; + export function emit(name: string, value: any, target?: EventTarget | undefined, options?: any | undefined): Promise; /** - * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fscreatewritestreampath-options} - * @param {string | Buffer | URL} path - * @param {object=} options - * @returns {fs.WriteStream} + * Resolves a request by `seq` with possible value. + * @param {string} seq + * @param {any} value + * @ignore */ - export function createWriteStream(path: string | Buffer | URL, options?: object | undefined): fs.WriteStream; + export function resolve(seq: string, value: any): Promise; /** - * Invokes the callback with the for the file descriptor. See - * the POSIX fstat(2) documentation for more detail. - * - * @see {@link https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsfstatfd-options-callback} - * - * @param {number} fd - A file descriptor. - * @param {Object=} options - An options object. - * @param {function} callback - The function to call after completion. + * Sends an async IPC command request with parameters. + * @param {string} command + * @param {any=} value + * @param {object=} [options] + * @param {boolean=} [options.cache=false] + * @param {boolean=} [options.bytes=false] + * @return {Promise} */ - export function fstat(fd: number, options?: any | undefined, callback: Function): void; + export function send(command: string, value?: any | undefined, options?: object | undefined): Promise; /** + * Sends an async IPC command request with parameters and buffered bytes. + * @param {string} command + * @param {object=} params + * @param {(Buffer|Uint8Array|ArrayBuffer|string|Array)=} buffer + * @param {object=} options * @ignore */ - export function lchmod(path: any, mode: any, callback: any): void; + export function write(command: string, params?: object | undefined, buffer?: (Buffer | Uint8Array | ArrayBuffer | string | any[]) | undefined, options?: object | undefined): Promise; /** + * Sends an async IPC command request with parameters requesting a response + * with buffered bytes. + * @param {string} command + * @param {object=} params + * @param {object=} options * @ignore */ - export function lchown(path: any, uid: any, gid: any, callback: any): void; + export function request(command: string, params?: object | undefined, options?: object | undefined): Promise; + /** + * Factory for creating a proxy based IPC API. + * @param {string} domain + * @param {(function|object)=} ctx + * @param {string=} [ctx.default] + * @return {Proxy} + * @ignore + */ + export function createBinding(domain: string, ctx?: (Function | object) | undefined): ProxyConstructor; /** + * Represents an OK IPC status. * @ignore */ - export function lutimes(path: any, atime: any, mtime: any, callback: any): void; + export const OK: 0; /** + * Represents an ERROR IPC status. * @ignore */ - export function link(existingPath: any, newPath: any, callback: any): void; + export const ERROR: 1; /** + * Timeout in milliseconds for IPC requests. * @ignore */ - export function lstat(path: any, options: any, callback: any): void; + export const TIMEOUT: number; /** + * Symbol for the `ipc.debug.enabled` property * @ignore */ - export function mkdir(path: any, options: any, callback: any): void; + export const kDebugEnabled: unique symbol; /** - * Asynchronously open a file calling `callback` upon success or error. - * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsopenpath-flags-mode-callback} - * @param {string | Buffer | URL} path - * @param {string=} [flags = 'r'] - * @param {string=} [mode = 0o666] - * @param {function(err, fd)} callback + * @ignore */ - export function open(path: string | Buffer | URL, flags?: string | undefined, mode?: string | undefined, options: any, callback: (arg0: err, arg1: fd) => any): void; + export class Headers extends globalThis.Headers { + /** + * @ignore + */ + static from(input: any): any; + /** + * @ignore + */ + get length(): number; + /** + * @ignore + */ + toJSON(): { + [k: string]: any; + }; + } /** - * Asynchronously open a directory calling `callback` upon success or error. - * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsreaddirpath-options-callback} - * @param {string | Buffer | URL} path - * @param {Object=} options - * @param {string=} [options.encoding = 'utf8'] - * @param {boolean=} [options.withFileTypes = false] - * @param {function(err, fd)} callback + * A container for a IPC message based on a `ipc://` URI scheme. + * @ignore */ - export function opendir(path: string | Buffer | URL, options?: any | undefined, callback: (arg0: err, arg1: fd) => any): void; + export class Message extends URL { + /** + * The expected protocol for an IPC message. + * @ignore + */ + static get PROTOCOL(): string; + /** + * Creates a `Message` instance from a variety of input. + * @param {string|URL|Message|Buffer|object} input + * @param {(object|string|URLSearchParams)=} [params] + * @param {(ArrayBuffer|Uint8Array|string)?} [bytes] + * @return {Message} + * @ignore + */ + static from(input: string | URL | Message | Buffer | object, params?: (object | string | URLSearchParams) | undefined, bytes?: (ArrayBuffer | Uint8Array | string) | null): Message; + /** + * Predicate to determine if `input` is valid for constructing + * a new `Message` instance. + * @param {string|URL|Message|Buffer|object} input + * @return {boolean} + * @ignore + */ + static isValidInput(input: string | URL | Message | Buffer | object): boolean; + /** + * `Message` class constructor. + * @protected + * @param {string|URL} input + * @param {object|Uint8Array?} [bytes] + * @ignore + */ + protected constructor(); + /** + * @type {Uint8Array?} + * @ignore + */ + bytes: Uint8Array | null; + /** + * Computed IPC message name. + * @ignore + */ + get command(): string; + /** + * Computed IPC message name. + * @ignore + */ + get name(): string; + /** + * Computed `id` value for the command. + * @ignore + */ + get id(): string; + /** + * Computed `seq` (sequence) value for the command. + * @ignore + */ + get seq(): any; + /** + * Computed message value potentially given in message parameters. + * This value is automatically decoded, but not treated as JSON. + * @ignore + */ + get value(): any; + /** + * Computed `index` value for the command potentially referring to + * the window index the command is scoped to or originating from. If not + * specified in the message parameters, then this value defaults to `-1`. + * @ignore + */ + get index(): number; + /** + * Computed value parsed as JSON. This value is `null` if the value is not present + * or it is invalid JSON. + * @ignore + */ + get json(): any; + /** + * Computed readonly object of message parameters. + * @ignore + */ + get params(): any; + /** + * Gets unparsed message parameters. + * @ignore + */ + get rawParams(): { + [k: string]: any; + }; + /** + * Returns computed parameters as entries + * @return {Array>} + * @ignore + */ + entries(): Array>; + /** + * Set a parameter `value` by `key`. + * @param {string} key + * @param {any} value + * @ignore + */ + set(key: string, value: any): void; + /** + * Get a parameter value by `key`. + * @param {string} key + * @param {any} defaultValue + * @return {any} + * @ignore + */ + get(key: string, defaultValue: any): any; + /** + * Delete a parameter by `key`. + * @param {string} key + * @return {boolean} + * @ignore + */ + delete(key: string): boolean; + /** + * Computed parameter keys. + * @return {Array} + * @ignore + */ + keys(): Array; + /** + * Computed parameter values. + * @return {Array} + * @ignore + */ + values(): Array; + /** + * Predicate to determine if parameter `key` is present in parameters. + * @param {string} key + * @return {boolean} + * @ignore + */ + has(key: string): boolean; + } /** - * Asynchronously read from an open file descriptor. - * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsreadfd-buffer-offset-length-position-callback} - * @param {number} fd - * @param {object | Buffer | TypedArray} buffer - The buffer that the data will be written to. - * @param {number} offset - The position in buffer to write the data to. - * @param {number} length - The number of bytes to read. - * @param {number | BigInt | null} position - Specifies where to begin reading from in the file. If position is null or -1 , data will be read from the current file position, and the file position will be updated. If position is an integer, the file position will be unchanged. - * @param {function(err, bytesRead, buffer)} callback + * A result type used internally for handling + * IPC result values from the native layer that are in the form + * of `{ err?, data? }`. The `data` and `err` properties on this + * type of object are in tuple form and be accessed at `[data?,err?]` + * @ignore */ - export function read(fd: number, buffer: object | Buffer | TypedArray, offset: number, length: number, position: number | BigInt | null, options: any, callback: (arg0: err, arg1: bytesRead, arg2: any) => any): void; + export class Result { + /** + * Creates a `Result` instance from input that may be an object + * like `{ err?, data? }`, an `Error` instance, or just `data`. + * @param {object|Error|any?} result + * @param {Error|object} [maybeError] + * @param {string} [maybeSource] + * @param {object|string|Headers} [maybeHeaders] + * @return {Result} + * @ignore + */ + static from(result: object | Error | (any | null), maybeError?: Error | object, maybeSource?: string, maybeHeaders?: object | string | Headers): Result; + /** + * `Result` class constructor. + * @private + * @param {string?} [id = null] + * @param {Error?} [err = null] + * @param {object?} [data = null] + * @param {string?} [source = null] + * @param {object|string|Headers?} [headers = null] + * @ignore + */ + private constructor(); + /** + * The unique ID for this result. + * @type {string} + */ + id: string; + /** + * An optional error in the result. + * @type {Error?} + */ + err: Error | null; + /** + * Result data if given. + * @type {string|object|Uint8Array?} + * @ignore + */ + data: string | object | (Uint8Array | null); + /** + * The source of this result. + * @type {string?} + * @ignore + */ + source: string | null; + /** + * Result headers, if given. + * @type {Headers?} + */ + headers: Headers | null; + /** + * Computed result length. + * @ignore + */ + get length(): any; + /** + * @ignore + */ + toJSON(): { + headers: Headers; + source: string; + data: any; + err: { + name: string; + message: string; + stack?: string; + cause?: unknown; + type: any; + code: any; + }; + }; + /** + * Generator for an `Iterable` interface over this instance. + * @ignore + */ + [Symbol.iterator](): Generator; + } /** - * Asynchronously read all entries in a directory. - * @see {https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fsreaddirpath-options-callback} - * @param {string | Buffer | URL } path - * @param {object=} [options] - * @param {string=} [options.encoding = 'utf8'] - * @param {boolean=} [options.withFileTypes = false] - * @param {function(err, buffer)} callback + * @ignore */ - export function readdir(path: string | Buffer | URL, options?: object | undefined, callback: (arg0: err, arg1: buffer) => any): void; + export const primordials: any; + export default exports; + import { Buffer } from "socket:buffer"; + import * as exports from "socket:ipc"; + +} +declare module "socket:polyfills" { + export function applyPolyfills(): void; + export default exports; + import * as exports from "socket:polyfills"; + +} +declare module "socket:window/constants" { + export const WINDOW_ERROR: -1; + export const WINDOW_NONE: 0; + export const WINDOW_CREATING: 10; + export const WINDOW_CREATED: 11; + export const WINDOW_HIDING: 20; + export const WINDOW_HIDDEN: 21; + export const WINDOW_SHOWING: 30; + export const WINDOW_SHOWN: 31; + export const WINDOW_CLOSING: 40; + export const WINDOW_CLOSED: 41; + export const WINDOW_EXITING: 50; + export const WINDOW_EXITED: 51; + export const WINDOW_KILLING: 60; + export const WINDOW_KILLED: 61; + export * as _default from "socket:window/constants"; + +} +declare module "socket:window" { /** - * @param {string | Buffer | URL | number } path - * @param {object=} [options] - * @param {string=} [options.encoding = 'utf8'] - * @param {string=} [options.flag = 'r'] - * @param {AbortSignal=} [options.signal] - * @param {function(err, buffer)} callback + * @param {string} url + * @return {string} + * @ignore */ - export function readFile(path: string | Buffer | URL | number, options?: object | undefined, callback: (arg0: err, arg1: buffer) => any): void; + export function formatFileUrl(url: string): string; /** - * @ignore + * @class ApplicationWindow + * Represents a window in the application */ - export function readlink(path: any, options: any, callback: any): void; + export class ApplicationWindow { + static constants: typeof statuses; + constructor({ index, ...options }: { + [x: string]: any; + index: any; + }); + /** + * Get the index of the window + * @return {number} - the index of the window + */ + get index(): number; + /** + * Get the size of the window + * @return {{ width: number, height: number }} - the size of the window + */ + getSize(): { + width: number; + height: number; + }; + /** + * Get the title of the window + * @return {string} - the title of the window + */ + getTitle(): string; + /** + * Get the status of the window + * @return {string} - the status of the window + */ + getStatus(): string; + /** + * Close the window + * @return {Promise} - the options of the window + */ + close(): Promise; + /** + * Shows the window + * @return {Promise} + */ + show(): Promise; + /** + * Hides the window + * @return {Promise} + */ + hide(): Promise; + /** + * Sets the title of the window + * @param {string} title - the title of the window + * @return {Promise} + */ + setTitle(title: string): Promise; + /** + * Sets the size of the window + * @param {object} opts - an options object + * @param {(number|string)=} opts.width - the width of the window + * @param {(number|string)=} opts.height - the height of the window + * @return {Promise} + * @throws {Error} - if the width or height is invalid + */ + setSize(opts: { + width?: (number | string) | undefined; + height?: (number | string) | undefined; + }): Promise; + /** + * Navigate the window to a given path + * @param {object} path - file path + * @return {Promise} + */ + navigate(path: object): Promise; + /** + * Opens the Web Inspector for the window + * @return {Promise} + */ + showInspector(): Promise; + /** + * Sets the background color of the window + * @param {object} opts - an options object + * @param {number} opts.red - the red value + * @param {number} opts.green - the green value + * @param {number} opts.blue - the blue value + * @param {number} opts.alpha - the alpha value + * @return {Promise} + */ + setBackgroundColor(opts: { + red: number; + green: number; + blue: number; + alpha: number; + }): Promise; + /** + * Opens a native context menu. + * @param {object} options - an options object + * @return {Promise} + */ + setContextMenu(options: object): Promise; + /** + * Shows a native open file dialog. + * @param {object} options - an options object + * @return {Promise} - an array of file paths + */ + showOpenFilePicker(options: object): Promise; + /** + * Shows a native save file dialog. + * @param {object} options - an options object + * @return {Promise} - an array of file paths + */ + showSaveFilePicker(options: object): Promise; + /** + * Shows a native directory dialog. + * @param {object} options - an options object + * @return {Promise} - an array of file paths + */ + showDirectoryFilePicker(options: object): Promise; + /** + * Sends an IPC message to the window or to qthe backend. + * @param {object} options - an options object + * @param {number=} options.window - the window to send the message to + * @param {boolean=} [options.backend = false] - whether to send the message to the backend + * @param {string} options.event - the event to send + * @param {(string|object)=} options.value - the value to send + * @returns + */ + send(options: { + window?: number | undefined; + backend?: boolean | undefined; + event: string; + value?: (string | object) | undefined; + }): Promise; + /** + * Opens an URL in the default browser. + * @param {object} options + * @returns {Promise} + */ + openExternal(options: object): Promise; + /** + * Adds a listener to the window. + * @param {string} event - the event to listen to + * @param {function(*): void} cb - the callback to call + * @returns {void} + */ + addListener(event: string, cb: (arg0: any) => void): void; + /** + * Adds a listener to the window. An alias for `addListener`. + * @param {string} event - the event to listen to + * @param {function(*): void} cb - the callback to call + * @returns {void} + * @see addListener + */ + on(event: string, cb: (arg0: any) => void): void; + /** + * Adds a listener to the window. The listener is removed after the first call. + * @param {string} event - the event to listen to + * @param {function(*): void} cb - the callback to call + * @returns {void} + */ + once(event: string, cb: (arg0: any) => void): void; + /** + * Removes a listener from the window. + * @param {string} event - the event to remove the listener from + * @param {function(*): void} cb - the callback to remove + * @returns {void} + */ + removeListener(event: string, cb: (arg0: any) => void): void; + /** + * Removes all listeners from the window. + * @param {string} event - the event to remove the listeners from + * @returns {void} + */ + removeAllListeners(event: string): void; + /** + * Removes a listener from the window. An alias for `removeListener`. + * @param {string} event - the event to remove the listener from + * @param {function(*): void} cb - the callback to remove + * @returns {void} + * @see removeListener + */ + off(event: string, cb: (arg0: any) => void): void; + #private; + } + export default ApplicationWindow; + export const constants: typeof statuses; + import ipc from "socket:ipc"; + import * as statuses from "socket:window/constants"; +} +declare module "socket:application" { /** - * @ignore + * Creates a new window and returns an instance of ApplicationWindow. + * @param {object} opts - an options object + * @param {number} opts.index - the index of the window + * @param {string} opts.path - the path to the HTML file to load into the window + * @param {string=} opts.title - the title of the window + * @param {(number|string)=} opts.width - the width of the window. If undefined, the window will have the main window width. + * @param {(number|string)=} opts.height - the height of the window. If undefined, the window will have the main window height. + * @param {(number|string)=} [opts.minWidth = 0] - the minimum width of the window + * @param {(number|string)=} [opts.minHeight = 0] - the minimum height of the window + * @param {(number|string)=} [opts.maxWidth = '100%'] - the maximum width of the window + * @param {(number|string)=} [opts.maxHeight = '100%'] - the maximum height of the window + * @param {boolean=} [opts.resizable=true] - whether the window is resizable + * @param {boolean=} [opts.frameless=false] - whether the window is frameless + * @param {boolean=} [opts.utility=false] - whether the window is utility (macOS only) + * @param {boolean=} [opts.canExit=false] - whether the window can exit the app + * @return {Promise} */ - export function realpath(path: any, options: any, callback: any): void; + export function createWindow(opts: { + index: number; + path: string; + title?: string | undefined; + width?: (number | string) | undefined; + height?: (number | string) | undefined; + minWidth?: (number | string) | undefined; + minHeight?: (number | string) | undefined; + maxWidth?: (number | string) | undefined; + maxHeight?: (number | string) | undefined; + resizable?: boolean | undefined; + frameless?: boolean | undefined; + utility?: boolean | undefined; + canExit?: boolean | undefined; + }): Promise; /** - * @ignore + * Returns the current screen size. + * @returns {Promise} */ - export function rename(oldPath: any, newPath: any, callback: any): void; + export function getScreenSize(): Promise; /** - * @ignore + * Returns the ApplicationWindow instances for the given indices or all windows if no indices are provided. + * @param {number[]|undefined} indices - the indices of the windows + * @return {Promise>} + * @throws {Error} - if indices is not an array of integer numbers */ - export function rmdir(path: any, options: any, callback: any): void; + export function getWindows(indices: number[] | undefined): Promise<{ + [x: number]: ApplicationWindow; + }>; /** - * @ignore + * Returns the ApplicationWindow instance for the given index + * @param {number} index - the index of the window + * @throws {Error} - if index is not a valid integer number + * @returns {Promise} - the ApplicationWindow instance or null if the window does not exist */ - export function rm(path: any, options: any, callback: any): void; + export function getWindow(index: number): Promise; /** - * - * @param {string | Buffer | URL | number } path - filename or file descriptor - * @param {object=} options - * @param {string=} [options.encoding = 'utf8'] - * @param {string=} [options.flag = 'r'] - * @param {AbortSignal=} [options.signal] - * @param {function(err, data)} callback + * Returns the ApplicationWindow instance for the current window. + * @return {Promise} */ - export function stat(path: string | Buffer | URL | number, options?: object | undefined, callback: (arg0: err, arg1: data) => any): void; + export function getCurrentWindow(): Promise; /** - * @ignore + * Quits the backend process and then quits the render process, the exit code used is the final exit code to the OS. + * @param {object} code - an exit code + * @return {Promise} */ - export function symlink(target: any, path: any, type: any, callback: any): void; + export function exit(code: object): Promise; /** - * @ignore + * Set the native menu for the app. + * + * @param {object} options - an options object + * @param {string} options.value - the menu layout + * @param {number} options.index - the window to target (if applicable) + * @return {Promise} + * + * Socket Runtime provides a minimalist DSL that makes it easy to create + * cross platform native system and context menus. + * + * Menus are created at run time. They can be created from either the Main or + * Render process. The can be recreated instantly by calling the `setSystemMenu` method. + * + * The method takes a string. Here's an example of a menu. The semi colon is + * significant indicates the end of the menu. Use an underscore when there is no + * accelerator key. Modifiers are optional. And well known OS menu options like + * the edit menu will automatically get accelerators you dont need to specify them. + * + * + * ```js + * socket.application.setSystemMenu({ index: 0, value: ` + * App: + * Foo: f; + * + * Edit: + * Cut: x + * Copy: c + * Paste: v + * Delete: _ + * Select All: a; + * + * Other: + * Apple: _ + * Another Test: T + * !Im Disabled: I + * Some Thing: S + Meta + * --- + * Bazz: s + Meta, Control, Alt; + * `) + * ``` + * + * Separators + * + * To create a separator, use three dashes `---`. + * + * + * Accelerator Modifiers + * + * Accelerator modifiers are used as visual indicators but don't have a + * material impact as the actual key binding is done in the event listener. + * + * A capital letter implies that the accelerator is modified by the `Shift` key. + * + * Additional accelerators are `Meta`, `Control`, `Option`, each separated + * by commas. If one is not applicable for a platform, it will just be ignored. + * + * On MacOS `Meta` is the same as `Command`. + * + * + * Disabled Items + * + * If you want to disable a menu item just prefix the item with the `!` character. + * This will cause the item to appear disabled when the system menu renders. + * + * + * Submenus + * + * We feel like nested menus are an anti-pattern. We don't use them. If you have a + * strong argument for them and a very simple pull request that makes them work we + * may consider them. + * + * + * Event Handling + * + * When a menu item is activated, it raises the `menuItemSelected` event in + * the front end code, you can then communicate with your backend code if you + * want from there. + * + * For example, if the `Apple` item is selected from the `Other` menu... + * + * ```js + * window.addEventListener('menuItemSelected', event => { + * assert(event.detail.parent === 'Other') + * assert(event.detail.title === 'Apple') + * }) + * ``` + * */ - export function truncate(path: any, length: any, callback: any): void; + export function setSystemMenu(o: any): Promise; /** - * @ignore + * Set the enabled state of the system menu. + * @param {object} value - an options object + * @return {Promise} */ - export function unlink(path: any, callback: any): void; + export function setSystemMenuItemEnabled(value: object): Promise; /** - * @ignore + * Socket Runtime version. + * @type {object} - an object containing the version information */ - export function utimes(path: any, atime: any, mtime: any, callback: any): void; + export const runtimeVersion: object; /** - * @ignore + * Runtime debug flag. + * @type {boolean} */ - export function watch(path: any, options: any, callback: any): void; + export const debug: boolean; /** - * @ignore + * Application configuration. + * @type {object} */ - export function write(fd: any, buffer: any, offset: any, length: any, position: any, callback: any): void; + export const config: object; + export namespace backend { + /** + * @param {object} opts - an options object + * @param {boolean} [opts.force = false] - whether to force the existing process to close + * @return {Promise} + */ + function open(opts?: { + force?: boolean; + }): Promise; + /** + * @return {Promise} + */ + function close(): Promise; + } + export default exports; + import ApplicationWindow from "socket:window"; + import ipc from "socket:ipc"; + import * as exports from "socket:application"; + +} +declare module "socket:bluetooth" { + export default exports; /** - * @see {@url https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fswritefilefile-data-options-callback} - * @param {string | Buffer | URL | number } path - filename or file descriptor - * @param {string | Buffer | TypedArray | DataView | object } data - * @param {object=} options - * @param {string=} [options.encoding = 'utf8'] - * @param {string=} [options.mode = 0o666] - * @param {string=} [options.flag = 'w'] - * @param {AbortSignal=} [options.signal] - * @param {function(err)} callback + * Create an instance of a Bluetooth service. */ - export function writeFile(path: string | Buffer | URL | number, data: string | Buffer | TypedArray | DataView | object, options?: object | undefined, callback: (arg0: err) => any): void; - export function writev(fd: any, buffers: any, position: any, callback: any): void; - export { default as binding } from "socket:./binding.js"; - export default exports; - import * as constants from "socket:fs/constants"; - import { Dir } from "socket:fs/dir"; - import { DirectoryHandle } from "socket:fs/handle"; - import { Dirent } from "socket:fs/dir"; - import fds from "socket:fs/fds"; - import { FileHandle } from "socket:fs/handle"; - import * as promises from "socket:fs/promises"; - import { ReadStream } from "socket:fs/stream"; - import { Stats } from "socket:fs/stats"; - import { WriteStream } from "socket:fs/stream"; - import * as exports from "socket:fs/index"; + export class Bluetooth extends EventEmitter { + static isInitalized: boolean; + /** + * constructor is an example property that is set to `true` + * Creates a new service with key-value pairs + * @param {string} serviceId - Given a default value to determine the type + */ + constructor(serviceId?: string); + serviceId: string; + /** + * Start the Bluetooth service. + * @return {Promise} + * + */ + start(): Promise; + /** + * Start scanning for published values that correspond to a well-known UUID. + * Once subscribed to a UUID, events that correspond to that UUID will be + * emitted. To receive these events you can add an event listener, for example... + * + * ```js + * const ble = new Bluetooth(id) + * ble.subscribe(uuid) + * ble.on(uuid, (data, details) => { + * // ...do something interesting + * }) + * ``` + * + * @param {string} [id = ''] - A well-known UUID + * @return {Promise} + */ + subscribe(id?: string): Promise; + /** + * Start advertising a new value for a well-known UUID + * @param {string} [id=''] - A well-known UUID + * @param {string} [value=''] + * @return {Promise} + */ + publish(id?: string, value?: string): Promise; + } + import * as exports from "socket:bluetooth"; + import { EventEmitter } from "socket:events"; + import ipc from "socket:ipc"; - export { constants, Dir, DirectoryHandle, Dirent, fds, FileHandle, promises, ReadStream, Stats, WriteStream }; } declare module "socket:bootstrap" { /** From f5d277b81c620caea14d0a3b38483f1c700f3c53 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Fri, 14 Jul 2023 09:48:00 +0200 Subject: [PATCH 38/42] chore(api): ignore 'ipc.Result' fields --- api/README.md | 16 ++-------------- api/index.d.ts | 3 +++ api/ipc.js | 3 +++ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/api/README.md b/api/README.md index 401704137..fe27ac7c6 100644 --- a/api/README.md +++ b/api/README.md @@ -1191,19 +1191,7 @@ External docs: https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fspromisesw import { send } from 'socket:ipc' ``` -### [undefined](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L796) - -The unique ID for this result. - -### [undefined](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L802) - -An optional error in the result. - -### [undefined](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L822) - -Result headers, if given. - -## [`emit(name, value, target , options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1043) +## [`emit(name, value, target , options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1046) Emit event to be dispatched on `window` object. @@ -1215,7 +1203,7 @@ Emit event to be dispatched on `window` object. | options | Object | | true | | -## [`send(command, value, options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1102) +## [`send(command, value, options)`](https://github.com/socketsupply/socket/blob/master/api/ipc.js#L1105) Sends an async IPC command request with parameters. diff --git a/api/index.d.ts b/api/index.d.ts index cf970430b..42e19a49b 100644 --- a/api/index.d.ts +++ b/api/index.d.ts @@ -2924,11 +2924,13 @@ declare module "socket:ipc" { /** * The unique ID for this result. * @type {string} + * @ignore */ id: string; /** * An optional error in the result. * @type {Error?} + * @ignore */ err: Error | null; /** @@ -2946,6 +2948,7 @@ declare module "socket:ipc" { /** * Result headers, if given. * @type {Headers?} + * @ignore */ headers: Headers | null; /** diff --git a/api/ipc.js b/api/ipc.js index a753e26d7..a5d1de2a7 100644 --- a/api/ipc.js +++ b/api/ipc.js @@ -792,12 +792,14 @@ export class Result { /** * The unique ID for this result. * @type {string} + * @ignore */ id = String(rand64()) /** * An optional error in the result. * @type {Error?} + * @ignore */ err = null @@ -818,6 +820,7 @@ export class Result { /** * Result headers, if given. * @type {Headers?} + * @ignore */ headers = new Headers() From a318a27ca3ef1a73b4b90e9a7772486e98ceb452 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Fri, 14 Jul 2023 09:54:13 +0200 Subject: [PATCH 39/42] refactor(src/cli/cli.cc): clean up --- src/cli/cli.cc | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 0bf38bee3..40e65d44f 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2002,32 +2002,19 @@ int main (const int argc, const char* argv[]) { Options printBuildDirOptions = { { { "--platform" }, true }, { { "--root" }, true} }; + createSubcommand("print-build-dir", printBuildDirOptions, true, [&](Map optionsWithValue, std::unordered_set optionsWithoutValue) -> void { bool flagRoot = optionsWithoutValue.find("--root") != optionsWithoutValue.end(); + // if --platform is specified, use the build path for the specified platform + auto targetPlatform = optionsWithValue["--platform"]; + Paths paths = getPaths(targetPlatform.size() > 0 ? targetPlatform : platform.os); if (flagRoot) { - auto targetPlatform = optionsWithValue["--platform"]; - - if (targetPlatform.size() > 0) { - Path path = getPaths(targetPlatform).platformSpecificOutputPath; - std::cout << path.string() << std::endl; - } else { - Path path = getPaths(platform.os).platformSpecificOutputPath; - std::cout << path.string() << std::endl; - } - + std::cout << paths.platformSpecificOutputPath.string() << std::endl; exit(0); } - // if --platform is specified, use the build path for the specified platform - auto targetPlatform = optionsWithValue["--platform"]; - if (targetPlatform.size() > 0) { - Path path = getPaths(targetPlatform).pathResourcesRelativeToUserBuild; - std::cout << path.string() << std::endl; - exit(0); - } - // if no --platform option is provided, print the current platform build path - std::cout << getPaths(platform.os).pathResourcesRelativeToUserBuild.string() << std::endl; + std::cout << paths.pathResourcesRelativeToUserBuild.string() << std::endl; exit(0); }); From 4953d1fd557694ea380de6970e1b9bab6ff523e5 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Fri, 14 Jul 2023 09:57:11 +0200 Subject: [PATCH 40/42] fix(src/window/linux.cc): fix 'resolvePromise' --- src/window/linux.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window/linux.cc b/src/window/linux.cc index eae4211bd..f1e600936 100644 --- a/src/window/linux.cc +++ b/src/window/linux.cc @@ -1168,7 +1168,7 @@ namespace SSC { guint response = gtk_dialog_run(GTK_DIALOG(dialog)); if (response != GTK_RESPONSE_ACCEPT && response != SELECT_RESPONSE) { - this->resolvePromise(seq, "0", "null"); + this->resolvePromise(seq, "0", SSC::JSON::null); gtk_widget_destroy(dialog); return; } From 98fb2381c5c3a5c37a021b50bbfef0ab0f052f71 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Fri, 14 Jul 2023 10:22:44 +0200 Subject: [PATCH 41/42] fic(src/cli/cli.cc): add missing link flags --- src/cli/cli.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 40e65d44f..974204250 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -4697,6 +4697,8 @@ int main (const int argc, const char* argv[]) { #else << " " << flags << " " << extraFlags + << " -lsocket-runtime" + << " -luv" << " -fvisibility=hidden" << (" -L" + quote + trim(prefixFile("lib/" + platform.arch + "-desktop")) + quote) #endif From 279db49db774bc6de800e6a572b6a603ee50d269 Mon Sep 17 00:00:00 2001 From: Joseph Werle Date: Fri, 14 Jul 2023 11:27:11 +0200 Subject: [PATCH 42/42] refactor(:src/cli/cli.cc): suggested changes from @chicoxyzzy Co-authored-by: Sergey Rubanov --- src/cli/cli.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/cli.cc b/src/cli/cli.cc index 974204250..07a727e90 100644 --- a/src/cli/cli.cc +++ b/src/cli/cli.cc @@ -2000,7 +2000,7 @@ int main (const int argc, const char* argv[]) { }); Options printBuildDirOptions = { - { { "--platform" }, true }, { { "--root" }, true} + { { "--platform" }, true, true }, { { "--root" }, true, false} }; createSubcommand("print-build-dir", printBuildDirOptions, true, [&](Map optionsWithValue, std::unordered_set optionsWithoutValue) -> void {