From 718308d656de8d558cde8c8884db8b4fa0eaa67e Mon Sep 17 00:00:00 2001 From: Dennis Ameling Date: Thu, 8 Apr 2021 22:47:01 +0200 Subject: [PATCH 1/2] First work on N-API migration --- binding.gyp | 11 +++++- package-lock.json | 10 +++--- package.json | 2 +- src/main.cc | 86 +++++++++++++++++++++++------------------------ 4 files changed, 59 insertions(+), 50 deletions(-) diff --git a/binding.gyp b/binding.gyp index e6de9be..875b197 100644 --- a/binding.gyp +++ b/binding.gyp @@ -13,11 +13,20 @@ 'targets': [ { 'target_name': 'fs_admin', + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions' ], + 'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', + 'CLANG_CXX_LIBRARY': 'libc++', + 'MACOSX_DEPLOYMENT_TARGET': '10.7', + }, + 'msvs_settings': { + 'VCCLCompilerTool': { 'ExceptionHandling': 1 }, + }, 'sources': [ 'src/main.cc', ], 'include_dirs': [ - ' argv[] = {Nan::New(exit_code)}; + void OnOK() { + Napi::Value argv[] = {Napi::Number::New(env, exit_code)}; callback->Call(1, argv, async_resource); } }; -void GetAuthorizationForm(const Nan::FunctionCallbackInfo& info) { +void GetAuthorizationForm(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); auto auth_form = CreateAuthorizationForm(); - auto buffer = Nan::CopyBuffer(auth_form.c_str(), auth_form.size()); - info.GetReturnValue().Set(buffer.ToLocalChecked()); + auto buffer = Napi::Buffer::Copy(env, auth_form.c_str(), auth_form.size()); + return buffer; } -void ClearAuthorizationCache(const Nan::FunctionCallbackInfo& info) { +void ClearAuthorizationCache(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); ClearAuthorizationCache(); } -void SpawnAsAdmin(const Nan::FunctionCallbackInfo& info) { - if (!info[0]->IsString()) { - Nan::ThrowTypeError("Command must be a string"); - return; +void SpawnAsAdmin(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + if (!info[0].IsString()) { + Napi::TypeError::New(env, "Command must be a string").ThrowAsJavaScriptException(); + return env.Null(); } - Nan::Utf8String commandNan(info[0]); - std::string command(*commandNan, commandNan.length()); + std::string commandNan = info[0].As(); + std::string command(*commandNan, commandNan.Length()); - if (!info[1]->IsArray()) { - Nan::ThrowTypeError("Arguments must be an array"); - return; + if (!info[1].IsArray()) { + Napi::TypeError::New(env, "Arguments must be an array").ThrowAsJavaScriptException(); + return env.Null(); } - Local js_args = Local::Cast(info[1]); + Napi::Array js_args = info[1].As(); std::vector args; args.reserve(js_args->Length()); for (uint32_t i = 0; i < js_args->Length(); ++i) { - Local context = Nan::GetCurrentContext(); - Local js_arg = js_args->Get(context, i).ToLocalChecked(); - if (!js_arg->IsString()) { - Nan::ThrowTypeError("Arguments must be an array of strings"); - return; + Local context = Napi::GetCurrentContext(); + Napi::Value js_arg = js_args->Get(context, i); + if (!js_arg.IsString()) { + Napi::TypeError::New(env, "Arguments must be an array of strings").ThrowAsJavaScriptException(); + return env.Null(); } - args.push_back(*Nan::Utf8String(js_arg)); + args.push_back(js_arg->As().Utf8Value().c_str()); } bool test_mode = false; - if (info[2]->IsTrue()) test_mode = true; + if (info[2].IsTrue()) test_mode = true; - if (!info[3]->IsFunction()) { - Nan::ThrowTypeError("Callback must be a function"); - return; + if (!info[3].IsFunction()) { + Napi::TypeError::New(env, "Callback must be a function").ThrowAsJavaScriptException(); + return env.Null(); } void *child_process = StartChildProcess(command, args, test_mode); if (!child_process) { - info.GetReturnValue().Set(Nan::False()); + return env.False(); } else { - Nan::AsyncQueueWorker(new Worker(new Nan::Callback(info[3].As()), child_process, test_mode)); - info.GetReturnValue().Set(Nan::True()); + new Worker(new Napi::FunctionReference(info[3].As()), child_process, test_mode).Queue(); + return env.True(); } } -NAN_MODULE_INIT(Init) { - Nan::SetMethod(target, "getAuthorizationForm", GetAuthorizationForm); - Nan::SetMethod(target, "clearAuthorizationCache", ClearAuthorizationCache); - Nan::SetMethod(target, "spawnAsAdmin", SpawnAsAdmin); +Napi::Object Init(Napi::Env env, Napi::Object exports) { + exports.Set(Napi::String::New(env, "getAuthorizationForm"), Napi::Function::New(env, GetAuthorizationForm)); + exports.Set(Napi::String::New(env, "clearAuthorizationCache"), Napi::Function::New(env, ClearAuthorizationCache)); + exports.Set(Napi::String::New(env, "spawnAsAdmin"), Napi::Function::New(env, SpawnAsAdmin)); } -#if NODE_MAJOR_VERSION >= 10 -NAN_MODULE_WORKER_ENABLED(fs_admin, Init) -#else -NODE_MODULE(fs_admin, Init) -#endif +NODE_API_MODULE(fs_admin, Init) } // namespace spawn_as_admin From 14946c3259a234daded04856de4bec3c8a676415 Mon Sep 17 00:00:00 2001 From: Sergio Padrino Date: Thu, 15 Apr 2021 22:58:43 +0200 Subject: [PATCH 2/2] Migrate main.cc to N-API --- src/fs-admin-darwin.cc | 2 +- src/fs-admin-linux.cc | 2 +- src/fs-admin-win.cc | 2 +- src/fs-admin.h | 2 +- src/main.cc | 52 +++++++++++++++++++++--------------------- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/fs-admin-darwin.cc b/src/fs-admin-darwin.cc index 8171191..c6b2725 100644 --- a/src/fs-admin-darwin.cc +++ b/src/fs-admin-darwin.cc @@ -33,7 +33,7 @@ AuthorizationRef GetAuthorizationRef() { return authorization_ref; } -void ClearAuthorizationCache() { +void ClearAuthorizationCacheImpl() { if (authorization_ref) { AuthorizationFree(authorization_ref, kAuthorizationFlagDefaults); authorization_ref = nullptr; diff --git a/src/fs-admin-linux.cc b/src/fs-admin-linux.cc index ee05aaf..23c3768 100644 --- a/src/fs-admin-linux.cc +++ b/src/fs-admin-linux.cc @@ -14,6 +14,6 @@ int WaitForChildProcessToExit(void *child_process, bool test_mode) { } string CreateAuthorizationForm() { return ""; } -void ClearAuthorizationCache() {} +void ClearAuthorizationCacheImpl() {} } // namespace fs_admin diff --git a/src/fs-admin-win.cc b/src/fs-admin-win.cc index 4606006..05bc27c 100644 --- a/src/fs-admin-win.cc +++ b/src/fs-admin-win.cc @@ -86,6 +86,6 @@ int WaitForChildProcessToExit(void *child_process, bool test_mode) { } std::string CreateAuthorizationForm() { return ""; } -void ClearAuthorizationCache() {} +void ClearAuthorizationCacheImpl() {} } // namespace fs_admin diff --git a/src/fs-admin.h b/src/fs-admin.h index 06714bb..24f6516 100644 --- a/src/fs-admin.h +++ b/src/fs-admin.h @@ -8,7 +8,7 @@ namespace fs_admin { std::string CreateAuthorizationForm(); -void ClearAuthorizationCache(); +void ClearAuthorizationCacheImpl(); void *StartChildProcess(const std::string &command, const std::vector &args, bool test_mode); diff --git a/src/main.cc b/src/main.cc index 107b7bd..d77c1e0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -12,8 +12,8 @@ class Worker : public Napi::AsyncWorker { bool test_mode; public: - Worker(const Napi::Env &env, void *child_process, bool test_mode) : - Napi::AsyncWorker(env), + Worker(const Function& callback, void *child_process, bool test_mode) : + Napi::AsyncWorker(callback), child_process(child_process), exit_code(-1), test_mode(test_mode) {} @@ -23,66 +23,65 @@ class Worker : public Napi::AsyncWorker { } void OnOK() { - Napi::Value argv[] = {Napi::Number::New(env, exit_code)}; - callback->Call(1, argv, async_resource); + const std::vector argv{Napi::Number::New(Env(), exit_code)}; + Callback().Call(argv); } }; -void GetAuthorizationForm(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); +Napi::Value GetAuthorizationForm(const Napi::CallbackInfo& info) { + const Napi::Env& env = info.Env(); auto auth_form = CreateAuthorizationForm(); - auto buffer = Napi::Buffer::Copy(env, auth_form.c_str(), auth_form.size()); + auto buffer = Napi::Buffer::Copy(env, auth_form.c_str(), auth_form.size()); return buffer; } -void ClearAuthorizationCache(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - ClearAuthorizationCache(); +Napi::Value ClearAuthorizationCache(const Napi::CallbackInfo& info) { + ClearAuthorizationCacheImpl(); + return info.Env().Undefined(); } -void SpawnAsAdmin(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); +Napi::Value SpawnAsAdmin(const Napi::CallbackInfo& info) { + const Napi::Env& env = info.Env(); if (!info[0].IsString()) { Napi::TypeError::New(env, "Command must be a string").ThrowAsJavaScriptException(); return env.Null(); } - std::string commandNan = info[0].As(); - std::string command(*commandNan, commandNan.Length()); + std::string command = info[0].As(); if (!info[1].IsArray()) { Napi::TypeError::New(env, "Arguments must be an array").ThrowAsJavaScriptException(); - return env.Null(); + return env.Undefined(); } Napi::Array js_args = info[1].As(); std::vector args; - args.reserve(js_args->Length()); - for (uint32_t i = 0; i < js_args->Length(); ++i) { - Local context = Napi::GetCurrentContext(); - Napi::Value js_arg = js_args->Get(context, i); + args.reserve(js_args.Length()); + for (uint32_t i = 0; i < js_args.Length(); ++i) { + Napi::Value js_arg = js_args.Get(i); if (!js_arg.IsString()) { Napi::TypeError::New(env, "Arguments must be an array of strings").ThrowAsJavaScriptException(); - return env.Null(); + return env.Undefined(); } - args.push_back(js_arg->As().Utf8Value().c_str()); + args.push_back(js_arg.As()); } bool test_mode = false; - if (info[2].IsTrue()) test_mode = true; + if (info[2].ToBoolean().Value()) test_mode = true; if (!info[3].IsFunction()) { Napi::TypeError::New(env, "Callback must be a function").ThrowAsJavaScriptException(); - return env.Null(); + return env.Undefined(); } void *child_process = StartChildProcess(command, args, test_mode); if (!child_process) { - return env.False(); + return Napi::Number::New(env, false); } else { - new Worker(new Napi::FunctionReference(info[3].As()), child_process, test_mode).Queue(); - return env.True(); + auto worker = new Worker(info[3].As(), child_process, test_mode); + worker->Queue(); + return Napi::Number::New(env, true); } } @@ -90,6 +89,7 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "getAuthorizationForm"), Napi::Function::New(env, GetAuthorizationForm)); exports.Set(Napi::String::New(env, "clearAuthorizationCache"), Napi::Function::New(env, ClearAuthorizationCache)); exports.Set(Napi::String::New(env, "spawnAsAdmin"), Napi::Function::New(env, SpawnAsAdmin)); + return exports; } NODE_API_MODULE(fs_admin, Init)