From a35d7428c325f773632f6efd85c8cbb074f43624 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 27 Aug 2024 18:07:37 +0200 Subject: [PATCH 01/34] install napi --- package-lock.json | 35 +++++++++++++++++++++++------------ package.json | 6 +++--- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 060f81852..9e4b42b4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "dependencies": { "@mapbox/node-pre-gyp": "1.0.11", "env-paths": "2.2.0", - "nan": "2.20.0", - "node-gyp": "10.2.0", + "node-addon-api": "^8.1.0", + "node-gyp": "10.1.0", "npmlog": "4.1.2", "rimraf": "^3.0.2", "tslib": "2.0.1" @@ -6629,11 +6629,6 @@ "version": "2.1.2", "license": "MIT" }, - "node_modules/nan": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", - "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==" - }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -6646,6 +6641,14 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.1.0.tgz", + "integrity": "sha512-yBY+qqWSv3dWKGODD6OGE6GnTX7Q2r+4+DfpqxHSHh8x0B4EKP9+wVGLS6U/AM1vxSNNmUEuIV5EGhYwPpfOwQ==", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, "node_modules/node-environment-flags": { "version": "1.0.6", "dev": true, @@ -6682,9 +6685,9 @@ } }, "node_modules/node-gyp": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", - "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", + "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", @@ -6692,9 +6695,9 @@ "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", - "proc-log": "^4.1.0", + "proc-log": "^3.0.0", "semver": "^7.3.5", - "tar": "^6.2.1", + "tar": "^6.1.2", "which": "^4.0.0" }, "bin": { @@ -6778,6 +6781,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/node-gyp/node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/node-gyp/node_modules/semver": { "version": "7.6.2", "license": "ISC", diff --git a/package.json b/package.json index c11bbda1a..09aac5517 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,8 @@ "dependencies": { "@mapbox/node-pre-gyp": "1.0.11", "env-paths": "2.2.0", - "nan": "2.20.0", - "node-gyp": "10.2.0", + "node-addon-api": "^8.1.0", + "node-gyp": "10.1.0", "npmlog": "4.1.2", "rimraf": "^3.0.2", "tslib": "2.0.1" @@ -104,4 +104,4 @@ "engines": { "node": ">= 20.16.0" } -} +} \ No newline at end of file From 19fe3c60704f58e4d0803c9fe06efbfba8b0a717 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 27 Aug 2024 18:11:28 +0200 Subject: [PATCH 02/34] run migration --- binding.gyp | 31 +- examples/19-binary-data-protobuf/package.json | 1 + examples/21-websockets-server/package.json | 1 + examples/package.json | 1 + src/Curl.cc | 94 +- src/Curl.h | 22 +- src/CurlVersionInfo.cc | 60 +- src/CurlVersionInfo.h | 12 +- src/Easy.cc | 1117 +++++++++-------- src/Easy.h | 66 +- src/Http2PushFrameHeaders.cc | 78 +- src/Http2PushFrameHeaders.h | 20 +- src/Multi.cc | 240 ++-- src/Multi.h | 32 +- src/Share.cc | 87 +- src/Share.h | 20 +- src/macros.h | 3 +- src/node_libcurl.cc | 22 +- 18 files changed, 986 insertions(+), 921 deletions(-) diff --git a/binding.gyp b/binding.gyp index 22e0f2bea..4867b6d58 100644 --- a/binding.gyp +++ b/binding.gyp @@ -15,6 +15,15 @@ 'targets': [ { 'target_name': 'sslctx', + '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 }, + }, 'type': 'static_library', 'sources': [ 'src/sslctx.c', @@ -29,6 +38,15 @@ }, { 'target_name': '<(module_name)', + '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 }, + }, 'type': 'loadable_module', 'sources': [ 'src/node_libcurl.cc', @@ -41,7 +59,6 @@ 'src/Http2PushFrameHeaders.cc', ], 'include_dirs' : [ - " curlOptionBlob = { #endif }; -static void ExportConstants(v8::Local obj, +static void ExportConstants(Napi::Object obj, const std::vector& optionGroup, v8::PropertyAttribute attributes) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); for (std::vector::const_iterator it = optionGroup.begin(), end = optionGroup.end(); it != end; ++it) { - Nan::DefineOwnProperty(obj, Nan::New(it->name).ToLocalChecked(), - Nan::New(static_cast(it->value)), attributes); + Napi::DefineOwnProperty(obj, Napi::String::New(env, it->name), + Napi::Number::New(env, static_cast(it->value)), attributes); } } // Add Curl constructor to the module exports -NAN_MODULE_INIT(Initialize) { - Nan::HandleScope scope; +Napi::Object Initialize(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); - v8::Local obj = Nan::New(); + Napi::Object obj = Napi::Object::New(env); v8::PropertyAttribute attributes = static_cast(v8::ReadOnly | v8::DontDelete); @@ -737,7 +737,7 @@ NAN_MODULE_INIT(Initialize) { static_cast(v8::ReadOnly | v8::DontDelete | v8::DontEnum); // export options - v8::Local optionsObj = Nan::New(); + Napi::Object optionsObj = Napi::Object::New(env); ExportConstants(optionsObj, curlOptionNotImplemented, attributesDontEnum); ExportConstants(optionsObj, curlOptionString, attributes); ExportConstants(optionsObj, curlOptionInteger, attributes); @@ -747,7 +747,7 @@ NAN_MODULE_INIT(Initialize) { ExportConstants(optionsObj, curlOptionBlob, attributes); // export infos - v8::Local infosObj = Nan::New(); + Napi::Object infosObj = Napi::Object::New(env); ExportConstants(infosObj, curlInfoNotImplemented, attributesDontEnum); ExportConstants(infosObj, curlInfoString, attributes); ExportConstants(infosObj, curlInfoOffT, attributes); @@ -757,34 +757,34 @@ NAN_MODULE_INIT(Initialize) { ExportConstants(infosObj, curlInfoLinkedList, attributes); // export Curl codes - v8::Local multiObj = Nan::New(); + Napi::Object multiObj = Napi::Object::New(env); ExportConstants(multiObj, curlMultiOptionNotImplemented, attributesDontEnum); ExportConstants(multiObj, curlMultiOptionInteger, attributes); ExportConstants(multiObj, curlMultiOptionStringArray, attributes); ExportConstants(multiObj, curlMultiOptionFunction, attributes); // static members - Nan::DefineOwnProperty(obj, Nan::New("option").ToLocalChecked(), optionsObj, + Napi::DefineOwnProperty(obj, Napi::String::New(env, "option"), optionsObj, attributes); - Nan::DefineOwnProperty(obj, Nan::New("info").ToLocalChecked(), infosObj, attributes); - Nan::DefineOwnProperty(obj, Nan::New("multi").ToLocalChecked(), multiObj, attributes); + Napi::DefineOwnProperty(obj, Napi::String::New(env, "info"), infosObj, attributes); + Napi::DefineOwnProperty(obj, Napi::String::New(env, "multi"), multiObj, attributes); - Nan::SetMethod(obj, "globalInit", GlobalInit); - Nan::SetMethod(obj, "globalCleanup", GlobalCleanup); - Nan::SetMethod(obj, "getVersion", GetVersion); - Nan::SetMethod(obj, "getCount", GetCount); - Nan::SetAccessor(obj, Nan::New("VERSION_NUM").ToLocalChecked(), GetterVersionNum, 0, - v8::Local(), v8::DEFAULT, attributes); + Napi::SetMethod(obj, "globalInit", GlobalInit); + Napi::SetMethod(obj, "globalCleanup", GlobalCleanup); + Napi::SetMethod(obj, "getVersion", GetVersion); + Napi::SetMethod(obj, "getCount", GetCount); + Napi::SetAccessor(obj, Napi::String::New(env, "VERSION_NUM"), GetterVersionNum, 0, + Napi::Value(), v8::DEFAULT, attributes); - Nan::Set(target, Nan::New("Curl").ToLocalChecked(), obj); + (target).Set(Napi::String::New(env, "Curl"), obj); } int32_t IsInsideCurlConstantStruct(const std::vector& curlConstants, - const v8::Local& searchFor) { - Nan::HandleScope scope; + const Napi::Value& searchFor) { + Napi::HandleScope scope(env); - bool isString = searchFor->IsString(); - bool isInt = searchFor->IsInt32(); + bool isString = searchFor.IsString(); + bool isInt = searchFor.IsNumber(); std::string optionName = ""; int32_t optionId = -1; @@ -794,14 +794,14 @@ int32_t IsInsideCurlConstantStruct(const std::vector& curlConstant } if (isString) { - Nan::Utf8String optionNameV8(searchFor); + std::string optionNameV8 = searchFor.As(); optionName = std::string(*optionNameV8); std::transform(optionName.begin(), optionName.end(), optionName.begin(), ::toupper); } else { // int - optionId = Nan::To(searchFor).FromJust(); + optionId = searchFor.As().Int32Value(); } for (std::vector::const_iterator it = curlConstants.begin(), @@ -817,7 +817,7 @@ int32_t IsInsideCurlConstantStruct(const std::vector& curlConstant // based on https://github.com/libxmljs/libxmljs/blob/master/src/libxmljs.cc#L45 void AdjustMemory(ssize_t diff) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); addonAllocatedMemory += diff; @@ -828,25 +828,25 @@ void AdjustMemory(ssize_t diff) { return; } - Nan::AdjustExternalMemory(static_cast(diff)); + Napi::AdjustExternalMemory(static_cast(diff)); } // Return human readable string with the version number of libcurl and some of its important // components (like OpenSSL version). -NAN_METHOD(GetVersion) { - Nan::HandleScope scope; +Napi::Value GetVersion(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); const char* version = curl_version(); - v8::Local versionObj = Nan::New(version).ToLocalChecked(); + Napi::Value versionObj = Napi::String::New(env, version); - info.GetReturnValue().Set(versionObj); + return versionObj; } -NAN_METHOD(GetCount) { - Nan::HandleScope scope; +Napi::Value GetCount(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - info.GetReturnValue().Set(Easy::currentOpenedHandles); + return Easy::currentOpenedHandles; } // The following memory allocation wrappers are mostly the ones at @@ -910,11 +910,11 @@ void* CallocCallback(size_t nmemb, size_t size) { return ptr; } -NAN_METHOD(GlobalInit) { - Nan::HandleScope scope; +Napi::Value GlobalInit(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - long flags = info[0]->IsUndefined() // NOLINT(runtime/int) - ? static_cast(Nan::To(info[0]).FromJust()) // NOLINT(runtime/int) + long flags = info[0].IsUndefined() // NOLINT(runtime/int) + ? static_cast(info[0].As().Int32Value()) // NOLINT(runtime/int) : CURL_GLOBAL_ALL; curl_version_info_data* version = curl_version_info(CURLVERSION_NOW); @@ -932,24 +932,24 @@ NAN_METHOD(GlobalInit) { globalInitRetCode = curl_global_init(flags); } - info.GetReturnValue().Set(globalInitRetCode); + return globalInitRetCode; } -NAN_METHOD(GlobalCleanup) { - Nan::HandleScope scope; +Napi::Value GlobalCleanup(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); curl_global_cleanup(); - info.GetReturnValue().Set(Nan::Undefined()); + return env.Undefined(); } // Return hexdecimal representation of the libcurl version. -NAN_GETTER(GetterVersionNum) { - Nan::HandleScope scope; +Napi::Value GetterVersionNum(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - v8::Local version = Nan::New(LIBCURL_VERSION_NUM); + v8::Local version = Napi::New(env, LIBCURL_VERSION_NUM); - info.GetReturnValue().Set(version); + return version; } } // namespace NodeLibcurl diff --git a/src/Curl.h b/src/Curl.h index 3fa635b39..fc068f339 100644 --- a/src/Curl.h +++ b/src/Curl.h @@ -10,14 +10,16 @@ #include "macros.h" #include -#include -#include +#include +#include +#include +#include #include #include #include -using Nan::ObjectWrap; +using Napi::ObjectWrap; namespace NodeLibcurl { @@ -60,18 +62,18 @@ extern const std::vector curlMultiOptionStringArray; extern const std::vector curlMultiOptionFunction; // export Curl to js -NAN_MODULE_INIT(Initialize); +Napi::Object Initialize(Napi::Env env, Napi::Object exports); // js exported Methods -NAN_METHOD(GlobalInit); -NAN_METHOD(GlobalCleanup); -NAN_METHOD(GetVersion); -NAN_METHOD(GetCount); -NAN_GETTER(GetterVersionNum); +Napi::Value GlobalInit(const Napi::CallbackInfo& info); +Napi::Value GlobalCleanup(const Napi::CallbackInfo& info); +Napi::Value GetVersion(const Napi::CallbackInfo& info); +Napi::Value GetCount(const Napi::CallbackInfo& info); +Napi::Value GetterVersionNum(const Napi::CallbackInfo& info); // helper methods int32_t IsInsideCurlConstantStruct(const std::vector& curlConstants, - const v8::Local& searchFor); + const Napi::Value& searchFor); void ThrowError(const char* message, const char* reason = nullptr); void AdjustMemory(ssize_t size); diff --git a/src/CurlVersionInfo.cc b/src/CurlVersionInfo.cc index 80feb28ed..8fb10795e 100644 --- a/src/CurlVersionInfo.cc +++ b/src/CurlVersionInfo.cc @@ -14,24 +14,24 @@ namespace NodeLibcurl { namespace { template -void SetObjPropertyToNullOrValue(v8::Local obj, std::string key, TValue value) { - Nan::Set(obj, Nan::New(key).ToLocalChecked(), Nan::New(value)); +void SetObjPropertyToNullOrValue(Napi::Object obj, std::string key, TValue value) { + (obj).Set(Napi::New(env, key), Napi::New(env, value)); } template <> -void SetObjPropertyToNullOrValue>(v8::Local obj, +void SetObjPropertyToNullOrValue>(Napi::Object obj, std::string key, v8::Local value) { - Nan::Set(obj, Nan::New(key).ToLocalChecked(), value); + (obj).Set(Napi::New(env, key), value); } template <> -void SetObjPropertyToNullOrValue(v8::Local obj, std::string key, +void SetObjPropertyToNullOrValue(Napi::Object obj, std::string key, const char* value) { if (value == nullptr) { - Nan::Set(obj, Nan::New(key).ToLocalChecked(), Nan::Null()); + (obj).Set(Napi::New(env, key), env.Null()); } else { - Nan::Set(obj, Nan::New(key).ToLocalChecked(), Nan::New(value).ToLocalChecked()); + (obj).Set(Napi::New(env, key), Napi::New(env, value)); } } } // namespace @@ -82,23 +82,23 @@ const std::vector CurlVersionInfo::features = { const curl_version_info_data* CurlVersionInfo::versionInfo = curl_version_info(CURLVERSION_NOW); -NAN_MODULE_INIT(CurlVersionInfo::Initialize) { - Nan::HandleScope scope; +Napi::Object CurlVersionInfo::Initialize(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); if (!versionInfo) { - Nan::ThrowError("Failed to retrieve libcurl information using curl_version_info"); - return; + Napi::Error::New(env, "Failed to retrieve libcurl information using curl_version_info").ThrowAsJavaScriptException(); + return env.Null(); } v8::PropertyAttribute attributes = static_cast(v8::ReadOnly | v8::DontDelete); - v8::Local obj = Nan::New(); + Napi::Object obj = Napi::Object::New(env); - Nan::SetAccessor(obj, Nan::New("protocols").ToLocalChecked(), GetterProtocols, 0, - v8::Local(), v8::DEFAULT, attributes); - Nan::SetAccessor(obj, Nan::New("features").ToLocalChecked(), GetterFeatures, 0, - v8::Local(), v8::DEFAULT, attributes); + Napi::SetAccessor(obj, Napi::String::New(env, "protocols"), GetterProtocols, 0, + Napi::Value(), v8::DEFAULT, attributes); + Napi::SetAccessor(obj, Napi::String::New(env, "features"), GetterFeatures, 0, + Napi::Value(), v8::DEFAULT, attributes); SetObjPropertyToNullOrValue(obj, "rawFeatures", versionInfo->features); SetObjPropertyToNullOrValue(obj, "version", versionInfo->version); @@ -117,14 +117,14 @@ NAN_MODULE_INIT(CurlVersionInfo::Initialize) { SetObjPropertyToNullOrValue(obj, "brotliVersion", versionInfo->brotli_version); #else SetObjPropertyToNullOrValue(obj, "brotliVersionNumber", 0); - SetObjPropertyToNullOrValue(obj, "brotliVersion", Nan::Null()); + SetObjPropertyToNullOrValue(obj, "brotliVersion", env.Null()); #endif - Nan::Set(target, Nan::New("CurlVersionInfo").ToLocalChecked(), obj); + (target).Set(Napi::String::New(env, "CurlVersionInfo"), obj); } -NAN_GETTER(CurlVersionInfo::GetterProtocols) { - Nan::HandleScope scope; +Napi::Value CurlVersionInfo::GetterProtocols(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); // const pointer to const char pointer const char* const* protocols = versionInfo->protocols; @@ -132,30 +132,30 @@ NAN_GETTER(CurlVersionInfo::GetterProtocols) { std::vector vec; - v8::Local protocolsResult = Nan::New(); + Napi::Array protocolsResult = Napi::Array::New(env); for (i = 0; *(protocols + i); i++) { - v8::Local protocol = Nan::New(*(protocols + i)).ToLocalChecked(); - Nan::Set(protocolsResult, i, protocol); + Napi::String protocol = Napi::String::New(env, *(protocols + i)); + (protocolsResult).Set(i, protocol); } - info.GetReturnValue().Set(protocolsResult); + return protocolsResult; } // basically a copy of https://github.com/curl/curl/blob/05a131eb7740e/src/tool_help.c#L579 -NAN_GETTER(CurlVersionInfo::GetterFeatures) { - Nan::HandleScope scope; +Napi::Value CurlVersionInfo::GetterFeatures(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - v8::Local featuresResult = Nan::New(); + Napi::Array featuresResult = Napi::Array::New(env); unsigned int currentFeature = 0; for (auto const& feat : CurlVersionInfo::features) { if (versionInfo->features & feat.bitmask) { - v8::Local featureString = Nan::New(feat.name).ToLocalChecked(); - Nan::Set(featuresResult, currentFeature++, featureString); + Napi::String featureString = Napi::String::New(env, feat.name); + (featuresResult).Set(currentFeature++, featureString); } } - info.GetReturnValue().Set(featuresResult); + return featuresResult; } } // namespace NodeLibcurl diff --git a/src/CurlVersionInfo.h b/src/CurlVersionInfo.h index 20466740e..b92347fc3 100644 --- a/src/CurlVersionInfo.h +++ b/src/CurlVersionInfo.h @@ -10,8 +10,10 @@ #include "Curl.h" #include -#include -#include +#include +#include +#include +#include namespace NodeLibcurl { @@ -33,10 +35,10 @@ class CurlVersionInfo { static const curl_version_info_data* versionInfo; public: - static NAN_MODULE_INIT(Initialize); + static Napi::Object Initialize(Napi::Env env, Napi::Object exports); - static NAN_GETTER(GetterProtocols); - static NAN_GETTER(GetterFeatures); + Napi::Value GetterProtocols(const Napi::CallbackInfo& info); + Napi::Value GetterFeatures(const Napi::CallbackInfo& info); }; } // namespace NodeLibcurl #endif diff --git a/src/Easy.cc b/src/Easy.cc index d823d6024..b2ce4d8e2 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1,5 +1,5 @@ #ifndef NOMINMAX -# define NOMINMAX // To remove conflicts with recent v8 code std::numeric_limits::max() +#define NOMINMAX // To remove conflicts with recent v8 code std::numeric_limits::max() #endif /** * Copyright (c) Jonathan Cardoso Machado. All Rights Reserved. @@ -13,7 +13,8 @@ #include "CurlHttpPost.h" #include "Share.h" #include "make_unique.h" -#include "nan.h" +#include "napi.h" +#include "uv.h" #include #include @@ -47,7 +48,7 @@ class Easy::ToFree { } }; -Nan::Persistent Easy::constructor; +Napi::FunctionReference Easy::constructor; uint32_t Easy::counter = 0; uint32_t Easy::currentOpenedHandles = 0; @@ -168,17 +169,17 @@ Easy::Easy(CURL* easy) { ++Easy::currentOpenedHandles; } -v8::Local Easy::FromCURLHandle(CURL* handle) { - Nan::EscapableHandleScope scope; +Napi::Object Easy::FromCURLHandle(CURL* handle) { + Napi::EscapableHandleScope scope(env); // create a new js object using this one as the argument for the constructor. const int argc = 1; - v8::Local curlEasyHandle = Nan::New(reinterpret_cast(handle)); + Napi::External curlEasyHandle = Napi::External::New(env, reinterpret_cast(handle)); - v8::Local argv[argc] = {curlEasyHandle}; - v8::Local cons = Nan::GetFunction(Nan::New(Easy::constructor)).ToLocalChecked(); + Napi::Value argv[argc] = {curlEasyHandle}; + Napi::Function cons = Napi::GetFunction(Napi::New(env, Easy::constructor)); - v8::Local newInstance = Nan::NewInstance(cons, argc, argv).ToLocalChecked(); + Napi::Object newInstance = Napi::NewInstance(cons, argc, argv); return scope.Escape(newInstance); } @@ -278,8 +279,8 @@ void Easy::MonitorSockets() { int events = 0 | UV_READABLE | UV_WRITABLE; if (this->socketPollHandle) { - Nan::ThrowError("Already monitoring sockets!"); - return; + Napi::Error::New(env, "Already monitoring sockets!").ThrowAsJavaScriptException(); + return env.Null(); } #if NODE_LIBCURL_VER_GE(7, 45, 0) @@ -287,8 +288,9 @@ void Easy::MonitorSockets() { retCurl = curl_easy_getinfo(this->ch, CURLINFO_ACTIVESOCKET, &socket); if (socket == CURL_SOCKET_BAD) { - Nan::ThrowError("Received invalid socket from the current connection!"); - return; + Napi::Error::New(env, "Received invalid socket from the current connection!") + .ThrowAsJavaScriptException(); + return env.Null(); } #else long socket; // NOLINT(runtime/int) @@ -300,8 +302,8 @@ void Easy::MonitorSockets() { errorMsg += std::string("Failed to receive socket. Reason: ") + curl_easy_strerror(retCurl); - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } this->socketPollHandle = new uv_poll_t; @@ -314,8 +316,8 @@ void Easy::MonitorSockets() { errorMsg += std::string("Failed to poll on connection socket. Reason:") + UV_ERROR_STRING(retUv); - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } this->socketPollHandle->data = this; @@ -333,8 +335,8 @@ void Easy::UnmonitorSockets() { errorMsg += std::string("Failed to stop polling on socket. Reason: ") + UV_ERROR_STRING(retUv); - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } uv_close(reinterpret_cast(this->socketPollHandle), Easy::OnSocketClose); @@ -356,19 +358,19 @@ void Easy::CallSocketEvent(int status, int events) { return; } - Nan::HandleScope scope; + Napi::HandleScope scope(env); - v8::Local err = Nan::Null(); + Napi::Value err = env.Null(); if (status < 0) { - err = Nan::Error(UV_ERROR_STRING(status)); + err = Napi::Error::New(env, UV_ERROR_STRING(status)); } const int argc = 2; - v8::Local argv[argc] = {err, Nan::New(events)}; + Napi::Value argv[argc] = {err, Napi::Number::New(env, events)}; // **(this->cbOnSocketEvent.get()) is the same than this->cbOnSocketEvent->GetFunction() - Nan::AsyncResource asyncResource("Easy::CallSocketEvent"); + Napi::AsyncResource asyncResource("Easy::CallSocketEvent"); asyncResource.runInAsyncScope(this->handle(), this->cbOnSocketEvent->GetFunction(), argc, argv); } @@ -400,21 +402,21 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) // Read callback was set, use it instead if (it != obj->callbacks.end()) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); - v8::Local buf = Nan::NewBuffer(static_cast(n)).ToLocalChecked(); - v8::Local sizeArg = Nan::New(static_cast(size)); - v8::Local nmembArg = Nan::New(static_cast(nmemb)); + Napi::Object buf = Napi::Buffer::New(env, static_cast(n)); + v8::Local sizeArg = Napi::Uint32::New(env, static_cast(size)); + v8::Local nmembArg = Napi::Uint32::New(env, static_cast(nmemb)); const int argc = 3; - v8::Local argv[argc] = { + Napi::Value argv[argc] = { buf, sizeArg, nmembArg, }; - Nan::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::ReadFunction"); - Nan::MaybeLocal returnValueCallback = + Napi::TryCatch tryCatch; + Napi::AsyncResource asyncResource("Easy::ReadFunction"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -426,21 +428,22 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the READ callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the READ callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } return returnValue; } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } - char* data = node::Buffer::Data(buf); + char* data = buf.As>().Data(); bool hasData = !!data && returnValue > 0 && returnValue < CURL_READFUNC_ABORT; @@ -491,19 +494,19 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { // Seek callback was set, use it instead if (it != obj->callbacks.end()) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); - v8::Local offsetArg = Nan::New(static_cast(offset)); - v8::Local originArg = Nan::New(static_cast(origin)); + v8::Local offsetArg = Napi::Uint32::New(env, static_cast(offset)); + v8::Local originArg = Napi::Uint32::New(env, static_cast(origin)); const int argc = 2; - v8::Local argv[argc] = { + Napi::Value argv[argc] = { offsetArg, originArg, }; - Nan::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::SeekFunction"); - Nan::MaybeLocal returnValueCallback = + Napi::TryCatch tryCatch; + Napi::AsyncResource asyncResource("Easy::SeekFunction"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -515,17 +518,18 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the SEEK callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the SEEK callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } // otherwise we can't seek directly @@ -543,7 +547,7 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { } size_t Easy::OnData(char* data, size_t size, size_t nmemb) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); size_t dataLength = size * nmemb; @@ -560,16 +564,15 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { int32_t returnValue = -1; const int argc = 3; - v8::Local buf = - Nan::CopyBuffer(data, static_cast(dataLength)).ToLocalChecked(); - v8::Local sizeArg = Nan::New(static_cast(size)); - v8::Local nmembArg = Nan::New(static_cast(nmemb)); + Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); + v8::Local sizeArg = Napi::Uint32::New(env, static_cast(size)); + v8::Local nmembArg = Napi::Uint32::New(env, static_cast(nmemb)); - v8::Local argv[argc] = {buf, sizeArg, nmembArg}; + Napi::Value argv[argc] = {buf, sizeArg, nmembArg}; - Nan::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::OnData"); - Nan::MaybeLocal returnValueCallback = + Napi::TryCatch tryCatch; + Napi::AsyncResource asyncResource("Easy::OnData"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -581,25 +584,26 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the WRITE callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the WRITE callback must be an integer."); if (this->isInsideMultiHandle) { this->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } return returnValue; } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; } size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); size_t dataLength = size * nmemb; @@ -616,16 +620,15 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { int32_t returnValue = -1; const int argc = 3; - v8::Local buf = - Nan::CopyBuffer(data, static_cast(dataLength)).ToLocalChecked(); - v8::Local sizeArg = Nan::New(static_cast(size)); - v8::Local nmembArg = Nan::New(static_cast(nmemb)); + Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); + v8::Local sizeArg = Napi::Uint32::New(env, static_cast(size)); + v8::Local nmembArg = Napi::Uint32::New(env, static_cast(nmemb)); - v8::Local argv[argc] = {buf, sizeArg, nmembArg}; + Napi::Value argv[argc] = {buf, sizeArg, nmembArg}; - Nan::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::OnHeader"); - Nan::MaybeLocal returnValueCallback = + Napi::TryCatch tryCatch; + Napi::AsyncResource asyncResource("Easy::OnHeader"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -637,93 +640,90 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the HEADER callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the HEADER callback must be an integer."); if (this->isInsideMultiHandle) { this->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } return returnValue; } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; } -v8::Local NullValueIfInvalidString(char* str) { - Nan::EscapableHandleScope scope; +Napi::Value NullValueIfInvalidString(char* str) { + Napi::EscapableHandleScope scope(env); - v8::Local ret = Nan::Null(); + Napi::Value ret = env.Null(); if (str != NULL && str[0] != '\0') { - ret = Nan::New(str).ToLocalChecked(); + ret = Napi::New(env, str); } return scope.Escape(ret); } -v8::Local Easy::CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo) { - Nan::EscapableHandleScope scope; +Napi::Object Easy::CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo) { + Napi::EscapableHandleScope scope(env); - v8::Local fileName = Nan::New(fileInfo->filename).ToLocalChecked(); - v8::Local fileType = Nan::New(fileInfo->filetype); - v8::Local time = Nan::Null().As(); + Napi::String fileName = Napi::New(env, fileInfo->filename); + v8::Local fileType = Napi::New(env, fileInfo->filetype); + Napi::Value time = env.Null().As(); if (fileInfo->time != 0) - time = Nan::New(static_cast(fileInfo->time) * 1000) - .ToLocalChecked() - .As(); - - v8::Local perm = Nan::New(fileInfo->perm); - v8::Local uid = Nan::New(fileInfo->uid); - v8::Local gid = Nan::New(fileInfo->gid); - v8::Local size = Nan::New(static_cast(fileInfo->size)); - v8::Local hardLinks = Nan::New(static_cast(fileInfo->hardlinks)); - - v8::Local strings = Nan::New(); - Nan::Set(strings, Nan::New("time").ToLocalChecked(), - NullValueIfInvalidString(fileInfo->strings.time)); - Nan::Set(strings, Nan::New("perm").ToLocalChecked(), - NullValueIfInvalidString(fileInfo->strings.perm)); - Nan::Set(strings, Nan::New("user").ToLocalChecked(), - NullValueIfInvalidString(fileInfo->strings.user)); - Nan::Set(strings, Nan::New("group").ToLocalChecked(), - NullValueIfInvalidString(fileInfo->strings.group)); - Nan::Set(strings, Nan::New("target").ToLocalChecked(), - NullValueIfInvalidString(fileInfo->strings.target)); - - v8::Local obj = Nan::New(); - Nan::Set(obj, Nan::New("fileName").ToLocalChecked(), fileName); - Nan::Set(obj, Nan::New("fileType").ToLocalChecked(), fileType); - Nan::Set(obj, Nan::New("time").ToLocalChecked(), time); - Nan::Set(obj, Nan::New("perm").ToLocalChecked(), perm); - Nan::Set(obj, Nan::New("uid").ToLocalChecked(), uid); - Nan::Set(obj, Nan::New("gid").ToLocalChecked(), gid); - Nan::Set(obj, Nan::New("size").ToLocalChecked(), size); - Nan::Set(obj, Nan::New("hardLinks").ToLocalChecked(), hardLinks); - Nan::Set(obj, Nan::New("strings").ToLocalChecked(), strings); + time = Napi::Date::New(env, static_cast(fileInfo->time) * 1000) + + .As(); + + v8::Local perm = Napi::New(env, fileInfo->perm); + v8::Local uid = Napi::New(env, fileInfo->uid); + v8::Local gid = Napi::New(env, fileInfo->gid); + Napi::Number size = Napi::Number::New(env, static_cast(fileInfo->size)); + v8::Local hardLinks = Napi::New(env, static_cast(fileInfo->hardlinks)); + + Napi::Object strings = Napi::Object::New(env); + (strings).Set(Napi::String::New(env, "time"), NullValueIfInvalidString(fileInfo->strings.time)); + (strings).Set(Napi::String::New(env, "perm"), NullValueIfInvalidString(fileInfo->strings.perm)); + (strings).Set(Napi::String::New(env, "user"), NullValueIfInvalidString(fileInfo->strings.user)); + (strings).Set(Napi::String::New(env, "group"), NullValueIfInvalidString(fileInfo->strings.group)); + (strings).Set(Napi::String::New(env, "target"), + NullValueIfInvalidString(fileInfo->strings.target)); + + Napi::Object obj = Napi::Object::New(env); + (obj).Set(Napi::String::New(env, "fileName"), fileName); + (obj).Set(Napi::String::New(env, "fileType"), fileType); + (obj).Set(Napi::String::New(env, "time"), time); + (obj).Set(Napi::String::New(env, "perm"), perm); + (obj).Set(Napi::String::New(env, "uid"), uid); + (obj).Set(Napi::String::New(env, "gid"), gid); + (obj).Set(Napi::String::New(env, "size"), size); + (obj).Set(Napi::String::New(env, "hardLinks"), hardLinks); + (obj).Set(Napi::String::New(env, "strings"), strings); return scope.Escape(obj); } -v8::Local Easy::CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts) { - Nan::EscapableHandleScope scope; +Napi::Object Easy::CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts) { + Napi::EscapableHandleScope scope(env); auto hasExpire = !!sts->expire[0] && !!strcmp(sts->expire, TIME_IN_THE_FUTURE); - v8::Local host = Nan::New(sts->name).ToLocalChecked(); - v8::Local includeSubDomains = Nan::New(!!sts->includeSubDomains); - v8::Local expire = hasExpire ? Nan::New(sts->expire).ToLocalChecked().As() - : Nan::Null().As(); + Napi::String host = Napi::New(env, sts->name); + Napi::Boolean includeSubDomains = Napi::New(env, !!sts->includeSubDomains); + Napi::Value expire = + hasExpire ? Napi::New(env, sts->expire).As() : env.Null().As(); - v8::Local obj = Nan::New(); - Nan::Set(obj, Nan::New("host").ToLocalChecked(), host); - Nan::Set(obj, Nan::New("includeSubDomains").ToLocalChecked(), includeSubDomains); - Nan::Set(obj, Nan::New("expire").ToLocalChecked(), expire); + Napi::Object obj = Napi::Object::New(env); + (obj).Set(Napi::String::New(env, "host"), host); + (obj).Set(Napi::String::New(env, "includeSubDomains"), includeSubDomains); + (obj).Set(Napi::String::New(env, "expire"), expire); return scope.Escape(obj); } @@ -737,15 +737,15 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // assert(it != obj->callbacks.end() && "CHUNK_BGN callback not set."); const int argc = 2; - v8::Local argv[argc] = {Easy::CreateV8ObjectFromCurlFileInfo(transferInfo), - Nan::New(remains)}; + Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlFileInfo(transferInfo), + Napi::Number::New(env, remains)}; int32_t returnValue = CURL_CHUNK_BGN_FUNC_FAIL; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbChunkBgn"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbChunkBgn"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -757,18 +757,19 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the CHUNK_BGN callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the CHUNK_BGN callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; @@ -784,10 +785,10 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) int32_t returnValue = CURL_CHUNK_END_FUNC_FAIL; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbChunkEnd"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbChunkEnd"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); if (tryCatch.HasCaught()) { @@ -799,24 +800,25 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the CHUNK_END callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the CHUNK_END callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; } int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, void* userptr) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(userptr); @@ -826,18 +828,18 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi assert(it != obj->callbacks.end() && "DEBUG callback not set."); const int argc = 2; - v8::Local buf = Nan::CopyBuffer(data, static_cast(size)).ToLocalChecked(); - v8::Local argv[argc] = { - Nan::New(type), + Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(size)); + Napi::Value argv[argc] = { + Napi::Number::New(env, type), buf, }; int32_t returnValue = 1; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbDebug"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbDebug"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -849,24 +851,25 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the DEBUG callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the DEBUG callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; } int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(ptr); @@ -876,15 +879,14 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { assert(it != obj->callbacks.end() && "FNMATCH callback not set."); const int argc = 2; - v8::Local argv[argc] = {Nan::New(pattern).ToLocalChecked(), - Nan::New(string).ToLocalChecked()}; + Napi::Value argv[argc] = {Napi::New(env, pattern), Napi::New(env, string)}; int32_t returnValue = CURL_FNMATCHFUNC_FAIL; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbFnMatch"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbFnMatch"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -896,17 +898,18 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the FNMATCH callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the FNMATCH callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; @@ -914,7 +917,7 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { #if NODE_LIBCURL_VER_GE(7, 74, 0) - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(userdata); @@ -925,10 +928,10 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { int32_t returnValue = CURLSTS_FAIL; - Nan::TryCatch tryCatch; - v8::Local cacheEntryObject; + Napi::TryCatch tryCatch; + Napi::Value cacheEntryObject; - v8::Local typeError = Nan::TypeError( + Napi::Value typeError = Napi::TypeError( "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" " - Object matching the type CurlHstsEntry\n" " - An array matching the type CurlHstsEntry[]\n" @@ -940,7 +943,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { if (obj->hstsReadCache.size() > 0) { auto persistentValue = obj->hstsReadCache.back(); - cacheEntryObject = Nan::New(obj->hstsReadCache.back()); + cacheEntryObject = Napi::New(env, obj->hstsReadCache.back()); // reset the persistent handler so we do not leak memory persistentValue.Reset(); @@ -953,8 +956,8 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { return CURLSTS_DONE; } - Nan::AsyncResource asyncResource("Easy::CbHstsRead"); - Nan::MaybeLocal returnValueFromHstsReadCallback = + Napi::AsyncResource asyncResource("Easy::CbHstsRead"); + Napi::MaybeLocal returnValueFromHstsReadCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); if (tryCatch.HasCaught()) { @@ -971,7 +974,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { return returnValue; } - cacheEntryObject = returnValueFromHstsReadCallback.ToLocalChecked(); + cacheEntryObject = returnValueFromHstsReadCallback; } if (cacheEntryObject->IsNull()) { @@ -980,7 +983,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { // returning an array from the callback can be used to avoid multiple // context switches between v8 and js if (cacheEntryObject->IsArray()) { - auto cacheArray = cacheEntryObject.As(); + auto cacheArray = cacheEntryObject.As(); auto cacheArrayLength = cacheArray->Length(); if (cacheArrayLength == 0) { @@ -989,78 +992,78 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { // inserting in reverse order as we are processing the hstsReadCache stack from back to front for (int i = cacheArrayLength - 1; i >= 0; i--) { - auto idxValue = Nan::Get(cacheArray, i); + auto idxValue = (cacheArray).Get(i); assert(!idxValue.IsEmpty() && "Value inside array could not be found - Process may be running out of memory"); - auto idxValueChecked = idxValue.ToLocalChecked(); + auto idxValueChecked = idxValue; // we check for an array here too to avoid passing a child array here. // If that happens, the code would get to this condition again when we // process this cache entry in a future iteration - if (!idxValueChecked->IsObject() || idxValueChecked->IsArray()) { + if (!idxValueChecked.IsObject() || idxValueChecked->IsArray()) { THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) return returnValue; } - auto idxValueAsObject = idxValueChecked.As(); - - Nan::CopyablePersistentTraits::CopyablePersistent persistentValue; - - persistentValue.Reset(Nan::GetCurrentContext()->GetIsolate(), idxValueAsObject); + auto idxValueAsObject = idxValueChecked.As(); + + Napi::CopyablePersistentTraits::CopyablePersistent persistentValue; + + persistentValue.Reset(Napi::GetCurrentContext()->GetIsolate(), idxValueAsObject); obj->hstsReadCache.push_back(persistentValue); } auto persistentValue = obj->hstsReadCache.back(); - cacheEntryObject = Nan::New(obj->hstsReadCache.back()); + cacheEntryObject = Napi::New(env, obj->hstsReadCache.back()); persistentValue.Reset(); obj->hstsReadCache.pop_back(); obj->wasHstsReadCacheSet = true; } - if (cacheEntryObject->IsObject()) { + if (cacheEntryObject.IsObject()) { // napi would make this so much cleaner... - auto cacheEntry = cacheEntryObject.As(); + auto cacheEntry = cacheEntryObject.As(); - auto hostPropertyStr = Nan::New("host").ToLocalChecked(); - auto includeSubDomainsPropertyStr = Nan::New("includeSubDomains").ToLocalChecked(); - auto expirePropertyStr = Nan::New("expire").ToLocalChecked(); + auto hostPropertyStr = Napi::String::New(env, "host"); + auto includeSubDomainsPropertyStr = Napi::String::New(env, "includeSubDomains"); + auto expirePropertyStr = Napi::String::New(env, "expire"); - auto hostPropertyValue = Nan::Get(cacheEntry, hostPropertyStr); - auto includeSubDomainsPropertyValue = Nan::Get(cacheEntry, includeSubDomainsPropertyStr); - auto expirePropertyValue = Nan::Get(cacheEntry, expirePropertyStr); + auto hostPropertyValue = (cacheEntry).Get(hostPropertyStr); + auto includeSubDomainsPropertyValue = (cacheEntry).Get(includeSubDomainsPropertyStr); + auto expirePropertyValue = (cacheEntry).Get(expirePropertyStr); if (hostPropertyValue.IsEmpty() || includeSubDomainsPropertyValue.IsEmpty() || expirePropertyValue.IsEmpty()) { assert("Process ran out of memory - fields returned from HSTSREADFUNCTION were empty"); } - auto hostPropertyValueChecked = hostPropertyValue.ToLocalChecked(); - auto includeSubDomainsPropertyValueChecked = includeSubDomainsPropertyValue.ToLocalChecked(); - auto expirePropertyValueChecked = expirePropertyValue.ToLocalChecked(); + auto hostPropertyValueChecked = hostPropertyValue; + auto includeSubDomainsPropertyValueChecked = includeSubDomainsPropertyValue; + auto expirePropertyValueChecked = expirePropertyValue; // the validation here is pretty basic, and we are not really validating // the format of the expire string - libcurl should do that // make sure the provided data is valid - if (!hostPropertyValueChecked->IsString() || + if (!hostPropertyValueChecked.IsString() || (!includeSubDomainsPropertyValueChecked->IsNullOrUndefined() && !includeSubDomainsPropertyValueChecked->IsBoolean()) || (!expirePropertyValueChecked->IsNullOrUndefined() && - !expirePropertyValueChecked->IsString())) { + !expirePropertyValueChecked.IsString())) { THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) return returnValue; } - Nan::Utf8String hostStrValue(hostPropertyValueChecked); + std::string hostStrValue = hostPropertyValueChecked.As(); // make sure str len is inside the given max length - if (static_cast(hostStrValue.length()) > sts->namelen) { - v8::Local typeError = Nan::TypeError( + if (static_cast(hostStrValue.Length()) > sts->namelen) { + Napi::Value typeError = Napi::TypeError( "The host property value returned from the HSTSREADFUNCTION callback function was " "invalid. The host string is too long.\n" "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " @@ -1072,17 +1075,17 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { } sts->name = *hostStrValue; - sts->includeSubDomains = Nan::To(includeSubDomainsPropertyValueChecked).FromJust(); + sts->includeSubDomains = includeSubDomainsPropertyValueChecked.As().Value(); - if (expirePropertyValueChecked->IsString()) { + if (expirePropertyValueChecked.IsString()) { // make sure expire length is one expected by libcurl // YYYYMMDD HH:MM:SS [null-terminated] size_t currentSize = - static_cast(expirePropertyValueChecked.As()->Length()); + static_cast(expirePropertyValueChecked.As()->Length()); size_t expectedSize = sizeof(sts->expire) / sizeof(sts->expire[0]) - 1; if (currentSize != expectedSize) { - v8::Local typeError = Nan::TypeError( + Napi::Value typeError = Napi::TypeError( "The expire property value returned from the HSTSREADFUNCTION callback function was " "invalid. String is either too long, or too short.\n" "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the " @@ -1094,7 +1097,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { return returnValue; } - Nan::Utf8String expireStrValue(expirePropertyValueChecked); + std::string expireStrValue = expirePropertyValueChecked.As(); auto expireCharValue = *expireStrValue; strcpy(sts->expire, expireCharValue); @@ -1119,7 +1122,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_index* count, void* userdata) { #if NODE_LIBCURL_VER_GE(7, 74, 0) - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(userdata); @@ -1130,25 +1133,25 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde int32_t returnValue = CURLSTS_FAIL; - Nan::TryCatch tryCatch; - v8::Local value; + Napi::TryCatch tryCatch; + Napi::Value value; - v8::Local typeError = - Nan::TypeError("Return value from the HSTSWRITEFUNCTION callback must be an integer."); + Napi::Value typeError = Napi::TypeError::New( + env, "Return value from the HSTSWRITEFUNCTION callback must be an integer."); // TODO(jonathan): give the option to receive an array directly? - v8::Local countObj = Nan::New(); - v8::Local index = Nan::New(static_cast(count->index)); - v8::Local total = Nan::New(static_cast(count->total)); - Nan::Set(countObj, Nan::New("index").ToLocalChecked(), index); - Nan::Set(countObj, Nan::New("total").ToLocalChecked(), total); + Napi::Object countObj = Napi::Object::New(env); + Napi::Number index = Napi::New(env, static_cast(count->index)); + Napi::Number total = Napi::New(env, static_cast(count->total)); + (countObj).Set(Napi::String::New(env, "index"), index); + (countObj).Set(Napi::String::New(env, "total"), total); const int argc = 2; - v8::Local argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; + Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; - Nan::AsyncResource asyncResource("Easy::CbHstsWrite"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbHstsWrite"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -1165,14 +1168,14 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde return returnValue; } - value = returnValueCallback.ToLocalChecked(); + value = returnValueCallback; - if (!value->IsNumber()) { + if (!value.IsNumber()) { THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) return returnValue; } - returnValue = Nan::To(value).FromJust(); + returnValue = value.As().Int32Value(); return returnValue; #else @@ -1181,7 +1184,7 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde } int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal, double ulnow) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(clientp); @@ -1201,15 +1204,15 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal assert(it != obj->callbacks.end() && "PROGRESS callback not set."); const int argc = 4; - v8::Local argv[argc] = {Nan::New(static_cast(dltotal)), - Nan::New(static_cast(dlnow)), - Nan::New(static_cast(ultotal)), - Nan::New(static_cast(ulnow))}; + Napi::Value argv[argc] = {Napi::Number::New(env, static_cast(dltotal)), + Napi::Number::New(env, static_cast(dlnow)), + Napi::Number::New(env, static_cast(ultotal)), + Napi::Number::New(env, static_cast(ulnow))}; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbProgress"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbProgress"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -1221,17 +1224,18 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the PROGRESS callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the PROGRESS callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } #if NODE_LIBCURL_VER_GE(7, 68, 0) @@ -1247,7 +1251,7 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { #if NODE_LIBCURL_VER_GE(7, 64, 0) - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(userdata); @@ -1259,10 +1263,10 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { it = obj->callbacks.find(CURLOPT_TRAILERFUNCTION); assert(it != obj->callbacks.end() && "Trailer callback not set."); - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbTrailer"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbTrailer"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); if (tryCatch.HasCaught()) { @@ -1274,48 +1278,50 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { return CURL_TRAILERFUNC_ABORT; } - v8::Local returnValueCbTypeError = Nan::TypeError( + Napi::Value returnValueCbTypeError = Napi::TypeError( "Return value from the Trailer callback must be an array of strings or false."); - bool isInvalid = - returnValueCallback.IsEmpty() || (!returnValueCallback.ToLocalChecked()->IsArray() && - !returnValueCallback.ToLocalChecked()->IsFalse()); + bool isInvalid = returnValueCallback.IsEmpty() || + (!returnValueCallback->IsArray() && !returnValueCallback->IsFalse()); if (isInvalid) { if (obj->isInsideMultiHandle) { obj->callbackError.Reset(returnValueCbTypeError); } else { - Nan::ThrowError(returnValueCbTypeError); + Napi::Error::New(env, returnValueCbTypeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } return CURL_TRAILERFUNC_ABORT; } - v8::Local returnValueCallbackChecked = returnValueCallback.ToLocalChecked(); + Napi::Value returnValueCallbackChecked = returnValueCallback; if (returnValueCallbackChecked->IsFalse()) { return CURL_TRAILERFUNC_ABORT; } - v8::Local rows = v8::Local::Cast(returnValueCallbackChecked); + Napi::Array rows = returnValueCallbackChecked.As(); // [headerStr1, headerStr2] for (uint32_t i = 0, len = rows->Length(); i < len; ++i) { // not an array of objects - v8::Local headerStrValue = Nan::Get(rows, i).ToLocalChecked(); - if (!headerStrValue->IsString()) { + Napi::Value headerStrValue = (rows).Get(i); + if (!headerStrValue.IsString()) { if (obj->isInsideMultiHandle) { obj->callbackError.Reset(returnValueCbTypeError); } else { - Nan::ThrowError(returnValueCbTypeError); + Napi::Error::New(env, returnValueCbTypeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } return CURL_TRAILERFUNC_ABORT; } - *headerList = curl_slist_append(*headerList, *Nan::Utf8String(headerStrValue)); + *headerList = + curl_slist_append(*headerList, headerStrValue->As().Utf8Value().c_str()); } return CURL_TRAILERFUNC_OK; @@ -1326,7 +1332,7 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); Easy* obj = static_cast(clientp); @@ -1351,15 +1357,15 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o assert(it != obj->callbacks.end() && "XFERINFO callback not set."); const int argc = 4; - v8::Local argv[argc] = {Nan::New(static_cast(dltotal)), - Nan::New(static_cast(dlnow)), - Nan::New(static_cast(ultotal)), - Nan::New(static_cast(ulnow))}; + Napi::Value argv[argc] = {Napi::Number::New(env, static_cast(dltotal)), + Napi::Number::New(env, static_cast(dlnow)), + Napi::Number::New(env, static_cast(ultotal)), + Napi::Number::New(env, static_cast(ulnow))}; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Easy::CbXferinfo"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Easy::CbXferinfo"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -1371,17 +1377,18 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { - v8::Local typeError = - Nan::TypeError("Return value from the XFERINFO callback must be an integer."); + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { + Napi::Value typeError = + Napi::TypeError::New(env, "Return value from the XFERINFO callback must be an integer."); if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Nan::ThrowError(typeError); + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + tryCatch.ReThrow(); } } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } #if NODE_LIBCURL_VER_GE(7, 68, 0) @@ -1395,72 +1402,73 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o return returnValue; } -NAN_MODULE_INIT(Easy::Initialize) { - Nan::HandleScope scope; +Napi::Object Easy::Initialize(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); // Easy js "class" function template initialization - v8::Local tmpl = Nan::New(Easy::New); - tmpl->SetClassName(Nan::New("Easy").ToLocalChecked()); - tmpl->InstanceTemplate()->SetInternalFieldCount(1); + Napi::FunctionReference tmpl = Napi::Function::New(env, Easy::New); + tmpl->SetClassName(Napi::String::New(env, "Easy")); + v8::Local proto = tmpl->PrototypeTemplate(); // prototype methods - Nan::SetPrototypeMethod(tmpl, "setOpt", Easy::SetOpt); - Nan::SetPrototypeMethod(tmpl, "getInfo", Easy::GetInfo); - Nan::SetPrototypeMethod(tmpl, "send", Easy::Send); - Nan::SetPrototypeMethod(tmpl, "recv", Easy::Recv); - Nan::SetPrototypeMethod(tmpl, "perform", Easy::Perform); - Nan::SetPrototypeMethod(tmpl, "upkeep", Easy::Upkeep); - Nan::SetPrototypeMethod(tmpl, "pause", Easy::Pause); - Nan::SetPrototypeMethod(tmpl, "reset", Easy::Reset); - Nan::SetPrototypeMethod(tmpl, "dupHandle", Easy::DupHandle); - Nan::SetPrototypeMethod(tmpl, "onSocketEvent", Easy::OnSocketEvent); - Nan::SetPrototypeMethod(tmpl, "monitorSocketEvents", Easy::MonitorSocketEvents); - Nan::SetPrototypeMethod(tmpl, "unmonitorSocketEvents", Easy::UnmonitorSocketEvents); - Nan::SetPrototypeMethod(tmpl, "close", Easy::Close); + Napi::SetPrototypeMethod(tmpl, "setOpt", Easy::SetOpt); + Napi::SetPrototypeMethod(tmpl, "getInfo", Easy::GetInfo); + Napi::SetPrototypeMethod(tmpl, "send", Easy::Send); + Napi::SetPrototypeMethod(tmpl, "recv", Easy::Recv); + Napi::SetPrototypeMethod(tmpl, "perform", Easy::Perform); + Napi::SetPrototypeMethod(tmpl, "upkeep", Easy::Upkeep); + Napi::SetPrototypeMethod(tmpl, "pause", Easy::Pause); + Napi::SetPrototypeMethod(tmpl, "reset", Easy::Reset); + Napi::SetPrototypeMethod(tmpl, "dupHandle", Easy::DupHandle); + Napi::SetPrototypeMethod(tmpl, "onSocketEvent", Easy::OnSocketEvent); + Napi::SetPrototypeMethod(tmpl, "monitorSocketEvents", Easy::MonitorSocketEvents); + Napi::SetPrototypeMethod(tmpl, "unmonitorSocketEvents", Easy::UnmonitorSocketEvents); + Napi::SetPrototypeMethod(tmpl, "close", Easy::Close); // static methods - Nan::SetMethod(tmpl, "strError", Easy::StrError); + Napi::SetMethod(tmpl, "strError", Easy::StrError); // Instance accessors - Nan::SetAccessor(proto, Nan::New("id").ToLocalChecked(), Easy::IdGetter, 0, - v8::Local(), v8::DEFAULT, v8::ReadOnly); - Nan::SetAccessor(proto, Nan::New("isInsideMultiHandle").ToLocalChecked(), - Easy::IsInsideMultiHandleGetter, 0, v8::Local(), v8::DEFAULT, - v8::ReadOnly); - Nan::SetAccessor(proto, Nan::New("isMonitoringSockets").ToLocalChecked(), - Easy::IsMonitoringSocketsGetter, 0, v8::Local(), v8::DEFAULT, - v8::ReadOnly); - Nan::SetAccessor(proto, Nan::New("isOpen").ToLocalChecked(), Easy::IsOpenGetter, 0, - v8::Local(), v8::DEFAULT, v8::ReadOnly); + Napi::SetAccessor(proto, Napi::String::New(env, "id"), Easy::IdGetter, 0, Napi::Value(), + v8::DEFAULT, v8::ReadOnly); + Napi::SetAccessor(proto, Napi::String::New(env, "isInsideMultiHandle"), + Easy::IsInsideMultiHandleGetter, 0, Napi::Value(), v8::DEFAULT, v8::ReadOnly); + Napi::SetAccessor(proto, Napi::String::New(env, "isMonitoringSockets"), + Easy::IsMonitoringSocketsGetter, 0, Napi::Value(), v8::DEFAULT, v8::ReadOnly); + Napi::SetAccessor(proto, Napi::String::New(env, "isOpen"), Easy::IsOpenGetter, 0, Napi::Value(), + v8::DEFAULT, v8::ReadOnly); Easy::constructor.Reset(tmpl); - Nan::Set(target, Nan::New("Easy").ToLocalChecked(), Nan::GetFunction(tmpl).ToLocalChecked()); + (target).Set(Napi::String::New(env, "Easy"), Napi::GetFunction(tmpl)); } -NAN_METHOD(Easy::New) { +Napi::Value Easy::New(const Napi::CallbackInfo& info) { if (!info.IsConstructCall()) { - Nan::ThrowError("You must use \"new\" to instantiate this object."); + Napi::Error::New(env, "You must use \"new\" to instantiate this object.") + .ThrowAsJavaScriptException(); } - v8::Local jsHandle = info[0]; + Napi::Value jsHandle = info[0]; Easy* obj = nullptr; // Copy constructor, used when duplicating handles. if (!jsHandle->IsUndefined()) { if (!jsHandle->IsExternal() && - (!jsHandle->IsObject() || !Nan::New(Easy::constructor)->HasInstance(jsHandle))) { - Nan::ThrowError(Nan::TypeError("Argument must be an instance of an Easy handle.")); - return; + (!jsHandle.IsObject() || !Napi::New(env, Easy::constructor)->HasInstance(jsHandle))) { + Napi::Error::New(env, + Napi::TypeError::New(env, "Argument must be an instance of an Easy handle.")) + .ThrowAsJavaScriptException(); + return env.Null(); } // This is the case when calling with a curl easy handle directly if (jsHandle->IsExternal()) { - CURL* curlEasyHandle = reinterpret_cast(info[0].As()->Value()); + CURL* curlEasyHandle = reinterpret_cast(info[0].As()->Value()); obj = new Easy(curlEasyHandle); } else { - Easy* orig = Nan::ObjectWrap::Unwrap(Nan::To(info[0]).ToLocalChecked()); + Easy* orig = info[0].To().Unwrap(); obj = new Easy(orig); } @@ -1470,46 +1478,46 @@ NAN_METHOD(Easy::New) { if (obj) { obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); + return info.This(); } } -NAN_GETTER(Easy::IdGetter) { - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Easy::IdGetter(const Napi::CallbackInfo& info) { + Easy* obj = this; - info.GetReturnValue().Set(Nan::New(obj->id)); + return Napi::New(env, obj->id); } -NAN_GETTER(Easy::IsInsideMultiHandleGetter) { - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Easy::IsInsideMultiHandleGetter(const Napi::CallbackInfo& info) { + Easy* obj = this; - info.GetReturnValue().Set(Nan::New(obj->isInsideMultiHandle)); + return Napi::New(env, obj->isInsideMultiHandle); } -NAN_GETTER(Easy::IsMonitoringSocketsGetter) { - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Easy::IsMonitoringSocketsGetter(const Napi::CallbackInfo& info) { + Easy* obj = this; - info.GetReturnValue().Set(Nan::New(obj->isMonitoringSockets)); + return Napi::New(env, obj->isMonitoringSockets); } -NAN_GETTER(Easy::IsOpenGetter) { - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); +Napi::Value Easy::IsOpenGetter(const Napi::CallbackInfo& info) { + Easy* obj = this; - info.GetReturnValue().Set(Nan::New(obj->isOpen)); + return Napi::New(env, obj->isOpen); } -NAN_METHOD(Easy::SetOpt) { - Nan::HandleScope scope; +Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local opt = info[0]; - v8::Local value = info[1]; + Napi::Value opt = info[0]; + Napi::Value value = info[1]; CURLcode setOptRetCode = CURLE_UNKNOWN_OPTION; @@ -1519,7 +1527,7 @@ NAN_METHOD(Easy::SetOpt) { // we probably could use these here for newer libcurl versions... if ((optionId = IsInsideCurlConstantStruct(curlOptionNotImplemented, opt))) { - Nan::ThrowError( + Napi::ThrowError( "Unsupported option, probably because it's too complex to implement " "using javascript or unecessary when using javascript (like the _DATA " "options)."); @@ -1530,18 +1538,18 @@ NAN_METHOD(Easy::SetOpt) { if (value->IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); } else { - if (!value->IsObject() || !Nan::New(Share::constructor)->HasInstance(value)) { - Nan::ThrowTypeError( + if (!value.IsObject() || !Napi::New(env, Share::constructor)->HasInstance(value)) { + Napi::ThrowTypeError( "Invalid value for the SHARE option. It must be a Share " "instance."); return; } - Share* share = Nan::ObjectWrap::Unwrap(value.As()); + Share* share = value.As().Unwrap(); if (!share->isOpen) { - Nan::ThrowError("Share handle is already closed."); - return; + Napi::Error::New(env, "Share handle is already closed.").ThrowAsJavaScriptException(); + return env.Null(); } setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, share->sh); @@ -1558,26 +1566,26 @@ NAN_METHOD(Easy::SetOpt) { std::string invalidArrayMsg = "HTTPPOST option value should be an Array of Objects."; if (!value->IsArray()) { - Nan::ThrowTypeError(invalidArrayMsg.c_str()); - return; + Napi::TypeError::New(env, invalidArrayMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local rows = v8::Local::Cast(value); + Napi::Array rows = value.As(); std::unique_ptr httpPost = std::make_unique(); // [{ key : val }] for (uint32_t i = 0, len = rows->Length(); i < len; ++i) { // not an array of objects - v8::Local obj = Nan::Get(rows, i).ToLocalChecked(); - if (!obj->IsObject()) { - Nan::ThrowTypeError(invalidArrayMsg.c_str()); - return; + Napi::Value obj = (rows).Get(i); + if (!obj.IsObject()) { + Napi::TypeError::New(env, invalidArrayMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local postData = v8::Local::Cast(obj); + Napi::Object postData = obj.As(); - const v8::Local props = Nan::GetPropertyNames(postData).ToLocalChecked(); + const Napi::Array props = Napi::GetPropertyNames(postData); const uint32_t postDataLength = props->Length(); bool hasFile = false; @@ -1590,12 +1598,11 @@ NAN_METHOD(Easy::SetOpt) { for (uint32_t j = 0; j < postDataLength; ++j) { int32_t httpPostId = -1; - const v8::Local postDataKey = Nan::Get(props, j).ToLocalChecked(); - const v8::Local postDataValue = - Nan::Get(postData, postDataKey).ToLocalChecked(); + const Napi::Value postDataKey = (props).Get(j); + const Napi::Value postDataValue = (postData).Get(postDataKey); // convert postDataKey to httppost id - Nan::Utf8String fieldName(postDataKey); + std::string fieldName = postDataKey.As(); std::string optionName = std::string(*fieldName); std::transform(optionName.begin(), optionName.end(), optionName.begin(), ::toupper); @@ -1629,71 +1636,67 @@ NAN_METHOD(Easy::SetOpt) { errorMsg += std::string("Invalid property given: \"") + optionName + "\". Valid properties are file, type, contents, name " "and filename."; - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } // check if value is a string. - if (!postDataValue->IsString()) { + if (!postDataValue.IsString()) { std::string errorMsg; errorMsg += std::string("Value for property \"") + optionName + "\" must be a string."; - Nan::ThrowTypeError(errorMsg.c_str()); - return; + Napi::TypeError::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } } if (!hasName) { - Nan::ThrowError("Missing field \"name\"."); - return; + Napi::Error::New(env, "Missing field \"name\".").ThrowAsJavaScriptException(); + return env.Null(); } - Nan::Utf8String fieldName( - Nan::Get(postData, Nan::New("name").ToLocalChecked()).ToLocalChecked()); + std::string fieldName = (postData).Get(Napi::String > ("name".As < Napi::String::New(env))); CURLFORMcode curlFormCode; if (hasFile) { - Nan::Utf8String file( - Nan::Get(postData, Nan::New("file").ToLocalChecked()).ToLocalChecked()); + std::string file = (postData).Get(Napi::String > ("file".As < Napi::String::New(env))); if (hasContentType) { - Nan::Utf8String contentType( - Nan::Get(postData, Nan::New("type").ToLocalChecked()).ToLocalChecked()); + std::string contentType = + (postData).Get(Napi::String > ("type".As < Napi::String::New(env))); if (hasNewFileName) { - Nan::Utf8String fileName( - Nan::Get(postData, Nan::New("filename").ToLocalChecked()) - .ToLocalChecked()); + std::string fileName = + (postData).Get(Napi::String > ("filename".As < Napi::String::New(env))); curlFormCode = - httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType, *fileName); + httpPost->AddFile(*fieldName, fieldName.Length(), *file, *contentType, *fileName); } else { - curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType); + curlFormCode = httpPost->AddFile(*fieldName, fieldName.Length(), *file, *contentType); } } else { - curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file); + curlFormCode = httpPost->AddFile(*fieldName, fieldName.Length(), *file); } } else if (hasContent) { // if file is not set, the contents field MUST // be set. - Nan::Utf8String fieldValue( - Nan::Get(postData, Nan::New("contents").ToLocalChecked()) - .ToLocalChecked()); + std::string fieldValue = + (postData).Get(Napi::String > ("contents".As < Napi::String::New(env))); curlFormCode = - httpPost->AddField(*fieldName, fieldName.length(), *fieldValue, fieldValue.length()); + httpPost->AddField(*fieldName, fieldName.Length(), *fieldValue, fieldValue.Length()); } else { - Nan::ThrowError("Missing field \"contents\"."); - return; + Napi::Error::New(env, "Missing field \"contents\".").ThrowAsJavaScriptException(); + return env.Null(); } if (curlFormCode != CURL_FORMADD_OK) { std::string errorMsg; errorMsg += std::string("Error while adding field \"") + *fieldName + "\" to post data."; - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } } @@ -1705,16 +1708,16 @@ NAN_METHOD(Easy::SetOpt) { } else { if (!value->IsArray()) { - Nan::ThrowTypeError("Option value must be an Array."); - return; + Napi::TypeError::New(env, "Option value must be an Array.").ThrowAsJavaScriptException(); + return env.Null(); } // convert value to curl linked list (curl_slist) curl_slist* slist = NULL; - v8::Local array = v8::Local::Cast(value); + Napi::Array array = value.As(); for (uint32_t i = 0, len = array->Length(); i < len; ++i) { - slist = curl_slist_append(slist, *Nan::Utf8String(Nan::Get(array, i).ToLocalChecked())); + slist = curl_slist_append(slist, (array).Get(i->As().Utf8Value().c_str())); } setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), slist); @@ -1728,14 +1731,14 @@ NAN_METHOD(Easy::SetOpt) { if (value->IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); } else { - if (!value->IsString()) { - Nan::ThrowTypeError("Option value must be a string."); - return; + if (!value.IsString()) { + Napi::TypeError::New(env, "Option value must be a string.").ThrowAsJavaScriptException(); + return env.Null(); } - Nan::Utf8String value(info[1]); + std::string value = info[1].As(); - size_t length = static_cast(value.length()); + size_t length = static_cast(value.Length()); std::string valueStr = std::string(*value, length); @@ -1772,22 +1775,22 @@ NAN_METHOD(Easy::SetOpt) { case CURLOPT_RESUME_FROM_LARGE: setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), - static_cast(Nan::To(value).FromJust())); + static_cast(value.As().DoubleValue())); break; // special case with READDATA, since we need to store the file descriptor // and not overwrite the READDATA already set in the handle. case CURLOPT_READDATA: - obj->readDataFileDescriptor = Nan::To(value).FromJust(); + obj->readDataFileDescriptor = value.As().Int32Value(); setOptRetCode = CURLE_OK; break; case CURLOPT_PATH_AS_IS: - obj->pathAsIs = Nan::To(value).FromJust(); + obj->pathAsIs = value.As().Int32Value(); setOptRetCode = CURLE_OK; break; default: setOptRetCode = curl_easy_setopt( obj->ch, static_cast(optionId), - static_cast(Nan::To(value).FromJust())); // NOLINT(runtime/int) + static_cast(value.As().Int32Value())); // NOLINT(runtime/int) break; } @@ -1796,8 +1799,9 @@ NAN_METHOD(Easy::SetOpt) { bool isNull = value->IsNull(); if (!value->IsFunction() && !isNull) { - Nan::ThrowTypeError("Option value must be a null or a function."); - return; + Napi::TypeError::New(env, "Option value must be a null or a function.") + .ThrowAsJavaScriptException(); + return env.Null(); } switch (optionId) { @@ -1814,7 +1818,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, NULL); } else { obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, Easy::CbChunkBgn); @@ -1835,7 +1839,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, NULL); } else { obj->callbacks[CURLOPT_CHUNK_END_FUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, Easy::CbChunkEnd); @@ -1851,7 +1855,8 @@ NAN_METHOD(Easy::SetOpt) { curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_DEBUGFUNCTION].reset(new Nan::Callback(value.As())); + obj->callbacks[CURLOPT_DEBUGFUNCTION].reset( + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, Easy::CbDebug); @@ -1868,7 +1873,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_FUNCTION, NULL); } else { obj->callbacks[CURLOPT_FNMATCH_FUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_FUNCTION, Easy::CbFnMatch); @@ -1882,7 +1887,8 @@ NAN_METHOD(Easy::SetOpt) { if (isNull) { obj->callbacks.erase(CURLOPT_HEADERFUNCTION); } else { - obj->callbacks[CURLOPT_HEADERFUNCTION].reset(new Nan::Callback(value.As())); + obj->callbacks[CURLOPT_HEADERFUNCTION].reset( + new Napi::FunctionReference(value.As())); } break; @@ -1896,7 +1902,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSREADFUNCTION, NULL); } else { obj->callbacks[CURLOPT_HSTSREADFUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_HSTSREADDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSREADFUNCTION, Easy::CbHstsRead); @@ -1911,7 +1917,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEFUNCTION, NULL); } else { obj->callbacks[CURLOPT_HSTSWRITEFUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEFUNCTION, Easy::CbHstsWrite); @@ -1929,7 +1935,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_PROGRESSFUNCTION, NULL); } else { obj->callbacks[CURLOPT_PROGRESSFUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_PROGRESSDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_PROGRESSFUNCTION, Easy::CbProgress); @@ -1944,7 +1950,8 @@ NAN_METHOD(Easy::SetOpt) { if (isNull) { obj->callbacks.erase(CURLOPT_READFUNCTION); } else { - obj->callbacks[CURLOPT_READFUNCTION].reset(new Nan::Callback(value.As())); + obj->callbacks[CURLOPT_READFUNCTION].reset( + new Napi::FunctionReference(value.As())); } break; @@ -1956,7 +1963,8 @@ NAN_METHOD(Easy::SetOpt) { if (isNull) { obj->callbacks.erase(CURLOPT_SEEKFUNCTION); } else { - obj->callbacks[CURLOPT_SEEKFUNCTION].reset(new Nan::Callback(value.As())); + obj->callbacks[CURLOPT_SEEKFUNCTION].reset( + new Napi::FunctionReference(value.As())); } break; @@ -1971,7 +1979,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_TRAILERFUNCTION, NULL); } else { obj->callbacks[CURLOPT_TRAILERFUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_TRAILERDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_TRAILERFUNCTION, Easy::CbTrailer); @@ -1993,7 +2001,7 @@ NAN_METHOD(Easy::SetOpt) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_XFERINFOFUNCTION, NULL); } else { obj->callbacks[CURLOPT_XFERINFOFUNCTION].reset( - new Nan::Callback(value.As())); + new Napi::FunctionReference(value.As())); curl_easy_setopt(obj->ch, CURLOPT_XFERINFODATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_XFERINFOFUNCTION, Easy::CbXferinfo); @@ -2009,7 +2017,8 @@ NAN_METHOD(Easy::SetOpt) { if (isNull) { obj->callbacks.erase(CURLOPT_WRITEFUNCTION); } else { - obj->callbacks[CURLOPT_WRITEFUNCTION].reset(new Nan::Callback(value.As())); + obj->callbacks[CURLOPT_WRITEFUNCTION].reset( + new Napi::FunctionReference(value.As())); } break; @@ -2020,10 +2029,10 @@ NAN_METHOD(Easy::SetOpt) { #if NODE_LIBCURL_VER_GE(7, 71, 0) if (value->IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); - } else if (value->IsString()) { - Nan::Utf8String utf8StringValue(value); + } else if (value.IsString()) { + std::string utf8StringValue = value.As(); - size_t length = static_cast(utf8StringValue.length()); + size_t length = static_cast(utf8StringValue.Length()); struct curl_blob blob; blob.data = *utf8StringValue; @@ -2031,24 +2040,25 @@ NAN_METHOD(Easy::SetOpt) { blob.flags = CURL_BLOB_COPY; setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), &blob); - } else if (node::Buffer::HasInstance(value)) { + } else if (value.IsBuffer()) { struct curl_blob blob; - blob.data = node::Buffer::Data(value); - blob.len = node::Buffer::Length(value); + blob.data = value.As>().Data(); + blob.len = value.As>().Length(); blob.flags = CURL_BLOB_COPY; setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), &blob); } else { - Nan::ThrowTypeError("Option value must be a string or Buffer."); - return; + Napi::TypeError::New(env, "Option value must be a string or Buffer.") + .ThrowAsJavaScriptException(); + return env.Null(); } #else - Nan::ThrowError("Blob options require curl 7.71 or newer."); - return; + Napi::Error::New(env, "Blob options require curl 7.71 or newer.").ThrowAsJavaScriptException(); + return env.Null(); #endif } - info.GetReturnValue().Set(setOptRetCode); + return setOptRetCode; } // traits class to determine if we need to check for null pointer first @@ -2058,45 +2068,46 @@ template <> struct ResultTypeIsChar : std::true_type {}; template -v8::Local Easy::GetInfoTmpl(const Easy* obj, int infoId) { - Nan::EscapableHandleScope scope; +Napi::Value Easy::GetInfoTmpl(const Easy* obj, int infoId) { + Napi::EscapableHandleScope scope(env); TResultType result; CURLINFO info = static_cast(infoId); CURLcode code = curl_easy_getinfo(obj->ch, info, &result); - v8::Local retVal = Nan::Undefined(); + Napi::Value retVal = env.Undefined(); if (code != CURLE_OK) { std::string str = std::to_string(static_cast(code)); - Nan::ThrowError(str.c_str()); + Napi::Error::New(env, str.c_str()).ThrowAsJavaScriptException(); + } else { // is string if (ResultTypeIsChar::value && !result) { - retVal = Nan::MakeMaybe(Nan::EmptyString()).ToLocalChecked(); + retVal = Napi::MakeMaybe(Napi::EmptyString()); } else { - retVal = Nan::MakeMaybe(Nan::New(result)).ToLocalChecked(); + retVal = Napi::MakeMaybe(Napi::Tv8MappingType::New(env, result)); } } return scope.Escape(retVal); } -NAN_METHOD(Easy::GetInfo) { - Nan::HandleScope scope; +Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local infoVal = info[0]; + Napi::Value infoVal = info[0]; - v8::Local retVal = Nan::Undefined(); + Napi::Value retVal = env.Undefined(); int infoId; @@ -2105,13 +2116,13 @@ NAN_METHOD(Easy::GetInfo) { // Special case for unsupported info if ((infoId = IsInsideCurlConstantStruct(curlInfoNotImplemented, infoVal))) { - Nan::ThrowError( + Napi::ThrowError( "Unsupported info, probably because it's too complex to implement " "using javascript or unecessary when using javascript."); return; } - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; // String if ((infoId = IsInsideCurlConstantStruct(curlInfoString, infoVal))) { @@ -2141,7 +2152,7 @@ NAN_METHOD(Easy::GetInfo) { // casting it to int32_t can be dangerous, only if Microsoft ever decides // to change the underlying architecture behind it. // https://stackoverflow.com/a/26496808/710693 - retVal = Nan::New(static_cast(socket)); + retVal = Napi::Number::New(env, static_cast(socket)); } // Linked list @@ -2155,7 +2166,7 @@ NAN_METHOD(Easy::GetInfo) { code = curl_easy_getinfo(obj->ch, curlInfo, &ci); if (code == CURLE_OK) { - v8::Local arr = Nan::New(); + Napi::Array arr = Napi::Array::New(env); bool isValid = true; for (int i = 0; i < ci->num_of_certs; i++) { @@ -2165,8 +2176,8 @@ NAN_METHOD(Easy::GetInfo) { curr = linkedList; while (curr) { - auto value = arr->Set(arr->GetCreationContext().ToLocalChecked(), arr->Length(), - Nan::New(curr->data).ToLocalChecked()); + auto value = arr.Set(arr->GetCreationContext(), arr->Length(), + Napi::String::New(env, curr->data)); if (value.IsJust()) { curr = curr->next; } else { @@ -2185,22 +2196,24 @@ NAN_METHOD(Easy::GetInfo) { if (isValid) { retVal = arr; } else { - Nan::ThrowError("Something went wrong while trying to retrieve info from curl slist"); + Napi::Error::New(env, + "Something went wrong while trying to retrieve info from curl slist") + .ThrowAsJavaScriptException(); } } } else { code = curl_easy_getinfo(obj->ch, curlInfo, &linkedList); if (code == CURLE_OK) { - v8::Local arr = Nan::New(); + Napi::Array arr = Napi::Array::New(env); bool isValid = true; if (linkedList) { curr = linkedList; while (curr) { - auto value = arr->Set(arr->GetCreationContext().ToLocalChecked(), arr->Length(), - Nan::New(curr->data).ToLocalChecked()); + auto value = arr.Set(arr->GetCreationContext(), arr->Length(), + Napi::String::New(env, curr->data)); if (value.IsJust()) { curr = curr->next; } else { @@ -2215,14 +2228,16 @@ NAN_METHOD(Easy::GetInfo) { if (isValid) { retVal = arr; } else { - Nan::ThrowError("Something went wrong while trying to retrieve info from curl slist"); + Napi::Error::New(env, + "Something went wrong while trying to retrieve info from curl slist") + .ThrowAsJavaScriptException(); } } } } if (tryCatch.HasCaught()) { - Nan::Utf8String msg(tryCatch.Message()->Get()); + std::string msg = tryCatch.Message(.As()->Get()); std::string errCode = std::string(*msg); // based on this interesting answer @@ -2232,165 +2247,165 @@ NAN_METHOD(Easy::GetInfo) { errCode.end()); // 43 is CURLE_BAD_FUNCTION_ARGUMENT - code = static_cast(std::stoi(errCode.length() > 0 ? errCode : "43")); + code = static_cast(std::stoi(errCode.Length() > 0 ? errCode : "43")); } - v8::Local ret = Nan::New(); - Nan::Set(ret, Nan::New("code").ToLocalChecked(), Nan::New(static_cast(code))); - Nan::Set(ret, Nan::New("data").ToLocalChecked(), retVal); + Napi::Object ret = Napi::Object::New(env); + (ret).Set(Napi::String::New(env, "code"), Napi::New(env, static_cast(code))); + (ret).Set(Napi::String::New(env, "data"), retVal); - info.GetReturnValue().Set(ret); + return ret; } -NAN_METHOD(Easy::Send) { - Nan::HandleScope scope; +Napi::Value Easy::Send(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } if (info.Length() == 0) { - Nan::ThrowError("Missing buffer argument."); - return; + Napi::Error::New(env, "Missing buffer argument.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local buf = info[0]; + Napi::Value buf = info[0]; - if (!buf->IsObject() || !node::Buffer::HasInstance(buf)) { - Nan::ThrowError("Invalid Buffer instance given."); - return; + if (!buf.IsObject() || !buf.IsBuffer()) { + Napi::Error::New(env, "Invalid Buffer instance given.").ThrowAsJavaScriptException(); + return env.Null(); } - const char* bufContent = node::Buffer::Data(buf); - size_t bufLength = node::Buffer::Length(buf); + const char* bufContent = buf.As>().Data(); + size_t bufLength = buf.As>().Length(); size_t n = 0; CURLcode curlRet = curl_easy_send(obj->ch, bufContent, bufLength, &n); - v8::Local ret = Nan::New(); - Nan::Set(ret, Nan::New("code").ToLocalChecked(), Nan::New(static_cast(curlRet))); - Nan::Set(ret, Nan::New("bytesSent").ToLocalChecked(), Nan::New(static_cast(n))); + Napi::Object ret = Napi::Object::New(env); + (ret).Set(Napi::String::New(env, "code"), Napi::New(env, static_cast(curlRet))); + (ret).Set(Napi::String::New(env, "bytesSent"), Napi::New(env, static_cast(n))); - info.GetReturnValue().Set(ret); + return ret; } -NAN_METHOD(Easy::Recv) { - Nan::HandleScope scope; +Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } if (info.Length() == 0) { - Nan::ThrowError("Missing buffer argument."); - return; + Napi::Error::New(env, "Missing buffer argument.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local buf = info[0]; + Napi::Value buf = info[0]; - if (!buf->IsObject() || !node::Buffer::HasInstance(buf)) { - Nan::ThrowError("Invalid Buffer instance given."); - return; + if (!buf.IsObject() || !buf.IsBuffer()) { + Napi::Error::New(env, "Invalid Buffer instance given.").ThrowAsJavaScriptException(); + return env.Null(); } - char* bufContent = node::Buffer::Data(buf); - size_t bufLength = node::Buffer::Length(buf); + char* bufContent = buf.As>().Data(); + size_t bufLength = buf.As>().Length(); size_t n = 0; CURLcode curlRet = curl_easy_recv(obj->ch, bufContent, bufLength, &n); - v8::Local ret = Nan::New(); - Nan::Set(ret, Nan::New("code").ToLocalChecked(), Nan::New(static_cast(curlRet))); - Nan::Set(ret, Nan::New("bytesReceived").ToLocalChecked(), Nan::New(static_cast(n))); + Napi::Object ret = Napi::Object::New(env); + (ret).Set(Napi::String::New(env, "code"), Napi::New(env, static_cast(curlRet))); + (ret).Set(Napi::String::New(env, "bytesReceived"), Napi::New(env, static_cast(n))); - info.GetReturnValue().Set(ret); + return ret; } // exec this handle -NAN_METHOD(Easy::Perform) { - Nan::HandleScope scope; +Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } if (!obj->SetUrlOpts()) { - v8::Local ret = Nan::New(static_cast(CURLE_URL_MALFORMAT)); - info.GetReturnValue().Set(ret); + v8::Local ret = Napi::Number::New(env, static_cast(CURLE_URL_MALFORMAT)); + return ret; return; } SETLOCALE_WRAPPER(CURLcode code = curl_easy_perform(obj->ch);); - v8::Local ret = Nan::New(static_cast(code)); + v8::Local ret = Napi::Number::New(env, static_cast(code)); - info.GetReturnValue().Set(ret); + return ret; } -NAN_METHOD(Easy::Upkeep) { - Nan::HandleScope scope; +Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } #if NODE_LIBCURL_VER_GE(7, 62, 0) CURLcode code = curl_easy_upkeep(obj->ch); #else CURLcode code = CURLE_FUNCTION_NOT_FOUND; - Nan::ThrowError( + Napi::ThrowError( "The addon was built against a libcurl version that does not support upkeep. It requires " "libcurl >= 7.62"); return; #endif - v8::Local ret = Nan::New(static_cast(code)); + v8::Local ret = Napi::Number::New(env, static_cast(code)); - info.GetReturnValue().Set(ret); + return ret; } -NAN_METHOD(Easy::Pause) { - Nan::HandleScope scope; +Napi::Value Easy::Pause(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle is closed."); - return; + Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - if (!info[0]->IsUint32()) { - Nan::ThrowTypeError("Bitmask value must be an integer."); - return; + if (!info[0].IsUint32()) { + Napi::TypeError::New(env, "Bitmask value must be an integer.").ThrowAsJavaScriptException(); + return env.Null(); } - uint32_t bitmask = Nan::To(info[0]).FromJust(); + uint32_t bitmask = info[0].As().Uint32Value(); CURLcode code = curl_easy_pause(obj->ch, static_cast(bitmask)); - info.GetReturnValue().Set(static_cast(code)); + return static_cast(code); } -NAN_METHOD(Easy::Reset) { - Nan::HandleScope scope; +Napi::Value Easy::Reset(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle closed."); - return; + Napi::Error::New(env, "Curl handle closed.").ThrowAsJavaScriptException(); + return env.Null(); } curl_easy_reset(obj->ch); @@ -2410,59 +2425,59 @@ NAN_METHOD(Easy::Reset) { obj->readDataFileDescriptor = -1; obj->readDataOffset = -1; - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Easy::DupHandle) { - Nan::HandleScope scope; +Napi::Value Easy::DupHandle(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); // create a new js object using this one as the argument for the constructor. const int argc = 1; - v8::Local argv[argc] = {info.This()}; - v8::Local cons = Nan::GetFunction(Nan::New(Easy::constructor)).ToLocalChecked(); + Napi::Value argv[argc] = {info.This()}; + Napi::Function cons = Napi::GetFunction(Napi::New(env, Easy::constructor)); - v8::Local newInstance = Nan::NewInstance(cons, argc, argv).ToLocalChecked(); + Napi::Object newInstance = Napi::NewInstance(cons, argc, argv); - info.GetReturnValue().Set(newInstance); + return newInstance; } -NAN_METHOD(Easy::OnSocketEvent) { - Nan::HandleScope scope; +Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!info.Length()) { - Nan::ThrowError("You must specify the callback function."); - return; + Napi::Error::New(env, "You must specify the callback function.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local arg = info[0]; + Napi::Value arg = info[0]; if (arg->IsNull()) { obj->cbOnSocketEvent = nullptr; - info.GetReturnValue().Set(info.This()); + return info.This(); return; } if (!arg->IsFunction()) { - Nan::ThrowTypeError("Invalid callback given."); - return; + Napi::TypeError::New(env, "Invalid callback given.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local callback = arg.As(); + Napi::Function callback = arg.As(); - obj->cbOnSocketEvent.reset(new Nan::Callback(callback)); + obj->cbOnSocketEvent.reset(new Napi::FunctionReference(callback)); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Easy::MonitorSocketEvents) { - Nan::HandleScope scope; +Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; obj->MonitorSockets(); @@ -2471,15 +2486,15 @@ NAN_METHOD(Easy::MonitorSocketEvents) { return; } - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Easy::UnmonitorSocketEvents) { - Nan::HandleScope scope; +Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; obj->UnmonitorSockets(); @@ -2488,23 +2503,24 @@ NAN_METHOD(Easy::UnmonitorSocketEvents) { return; } - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Easy::Close) { +Napi::Value Easy::Close(const Napi::CallbackInfo& info) { // check https://github.com/php/php-src/blob/master/ext/curl/interface.c#L3196 - Nan::HandleScope scope; + Napi::HandleScope scope(env); - Easy* obj = Nan::ObjectWrap::Unwrap(info.This()); + Easy* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Curl handle already closed."); - return; + Napi::Error::New(env, "Curl handle already closed.").ThrowAsJavaScriptException(); + return env.Null(); } if (obj->isInsideMultiHandle) { - Nan::ThrowError("Curl handle is inside a Multi instance, you must remove it first."); - return; + Napi::Error::New(env, "Curl handle is inside a Multi instance, you must remove it first.") + .ThrowAsJavaScriptException(); + return env.Null(); } obj->Dispose(); @@ -2512,22 +2528,23 @@ NAN_METHOD(Easy::Close) { return; } -NAN_METHOD(Easy::StrError) { - Nan::HandleScope scope; +Napi::Value Easy::StrError(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - v8::Local errCode = info[0]; + Napi::Value errCode = info[0]; - if (!errCode->IsInt32()) { - Nan::ThrowTypeError("Invalid errCode passed to Easy.strError."); - return; + if (!errCode.IsNumber()) { + Napi::TypeError::New(env, "Invalid errCode passed to Easy.strError.") + .ThrowAsJavaScriptException(); + return env.Null(); } const char* errorMsg = - curl_easy_strerror(static_cast(Nan::To(errCode).FromJust())); + curl_easy_strerror(static_cast(errCode.As().Int32Value())); - v8::Local ret = Nan::New(errorMsg).ToLocalChecked(); + Napi::String ret = Napi::New(env, errorMsg); - info.GetReturnValue().Set(ret); + return ret; } } // namespace NodeLibcurl diff --git a/src/Easy.h b/src/Easy.h index c06ba1ba2..8ebe9da48 100644 --- a/src/Easy.h +++ b/src/Easy.h @@ -11,15 +11,17 @@ #include "libcurl_compat.h" #include -#include -#include +#include +#include +#include +#include #include #include namespace NodeLibcurl { -class Easy : public Nan::ObjectWrap { +class Easy : public Napi::ObjectWrap { class ToFree; Easy(); @@ -45,13 +47,13 @@ class Easy : public Nan::ObjectWrap { static uint32_t counter; // callbacks - typedef std::map> CallbacksMap; + typedef std::map> CallbacksMap; CallbacksMap callbacks = CallbacksMap{}; - std::shared_ptr + std::shared_ptr cbOnSocketEvent; // still required since it's not related to any CURLOption // members - std::vector::CopyablePersistent> hstsReadCache; + std::vector::CopyablePersistent> hstsReadCache; uint32_t wasHstsReadCacheSet = false; uv_poll_t* socketPollHandle = nullptr; std::shared_ptr toFree = nullptr; @@ -70,30 +72,30 @@ class Easy : public Nan::ObjectWrap { // static methods template - static v8::Local GetInfoTmpl(const Easy* obj, int infoId); - static v8::Local CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo); - static v8::Local CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts); + static Napi::Value GetInfoTmpl(const Easy* obj, int infoId); + static Napi::Object CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo); + static Napi::Object CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts); // js available methods - static NAN_METHOD(New); - static NAN_GETTER(IdGetter); - static NAN_GETTER(IsInsideMultiHandleGetter); - static NAN_GETTER(IsMonitoringSocketsGetter); - static NAN_GETTER(IsOpenGetter); - static NAN_METHOD(SetOpt); - static NAN_METHOD(GetInfo); - static NAN_METHOD(Send); - static NAN_METHOD(Recv); - static NAN_METHOD(Perform); - static NAN_METHOD(Upkeep); - static NAN_METHOD(Pause); - static NAN_METHOD(Reset); - static NAN_METHOD(DupHandle); - static NAN_METHOD(OnSocketEvent); - static NAN_METHOD(MonitorSocketEvents); - static NAN_METHOD(UnmonitorSocketEvents); - static NAN_METHOD(Close); - static NAN_METHOD(StrError); + static Napi::Value New(const Napi::CallbackInfo& info); + Napi::Value IdGetter(const Napi::CallbackInfo& info); + Napi::Value IsInsideMultiHandleGetter(const Napi::CallbackInfo& info); + Napi::Value IsMonitoringSocketsGetter(const Napi::CallbackInfo& info); + Napi::Value IsOpenGetter(const Napi::CallbackInfo& info); + static Napi::Value SetOpt(const Napi::CallbackInfo& info); + static Napi::Value GetInfo(const Napi::CallbackInfo& info); + static Napi::Value Send(const Napi::CallbackInfo& info); + static Napi::Value Recv(const Napi::CallbackInfo& info); + static Napi::Value Perform(const Napi::CallbackInfo& info); + static Napi::Value Upkeep(const Napi::CallbackInfo& info); + static Napi::Value Pause(const Napi::CallbackInfo& info); + static Napi::Value Reset(const Napi::CallbackInfo& info); + static Napi::Value DupHandle(const Napi::CallbackInfo& info); + static Napi::Value OnSocketEvent(const Napi::CallbackInfo& info); + static Napi::Value MonitorSocketEvents(const Napi::CallbackInfo& info); + static Napi::Value UnmonitorSocketEvents(const Napi::CallbackInfo& info); + static Napi::Value Close(const Napi::CallbackInfo& info); + static Napi::Value StrError(const Napi::CallbackInfo& info); // cURL callbacks static size_t ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata); @@ -125,10 +127,10 @@ class Easy : public Nan::ObjectWrap { bool operator==(const Easy& easy) const; bool operator!=(const Easy& other) const; - static v8::Local FromCURLHandle(CURL* handle); + static Napi::Object FromCURLHandle(CURL* handle); // js object constructor template - static Nan::Persistent constructor; + static Napi::FunctionReference constructor; // members CURL* ch; @@ -136,13 +138,13 @@ class Easy : public Nan::ObjectWrap { bool isOpen = true; // used to return callback errors when inside Multi interface - Nan::Persistent callbackError; + Napi::Persistent callbackError; // static members static uint32_t currentOpenedHandles; // export Easy to js - static NAN_MODULE_INIT(Initialize); + static Napi::Object Initialize(Napi::Env env, Napi::Object exports); }; } // namespace NodeLibcurl #endif diff --git a/src/Http2PushFrameHeaders.cc b/src/Http2PushFrameHeaders.cc index 86fc6d18e..48c6b789c 100644 --- a/src/Http2PushFrameHeaders.cc +++ b/src/Http2PushFrameHeaders.cc @@ -13,7 +13,7 @@ namespace NodeLibcurl { -Nan::Persistent Http2PushFrameHeaders::objectTemplate; +Napi::Persistent Http2PushFrameHeaders::objectTemplate; Http2PushFrameHeaders::Http2PushFrameHeaders(struct curl_pushheaders* headers, size_t numberOfHeaders) { @@ -21,11 +21,11 @@ Http2PushFrameHeaders::Http2PushFrameHeaders(struct curl_pushheaders* headers, this->numberOfHeaders = numberOfHeaders; } -v8::Local Http2PushFrameHeaders::NewInstance(struct curl_pushheaders* headers, +Napi::Object Http2PushFrameHeaders::NewInstance(struct curl_pushheaders* headers, size_t numberOfHeaders) { - Nan::EscapableHandleScope scope; + Napi::EscapableHandleScope scope(env); - v8::Local jsObj = Nan::NewInstance(Nan::New(objectTemplate)).ToLocalChecked(); + Napi::Object jsObj = Napi::NewInstance(Napi::New(env, objectTemplate)); Http2PushFrameHeaders* cppObj = new Http2PushFrameHeaders(headers, numberOfHeaders); cppObj->Wrap(jsObj); @@ -33,74 +33,74 @@ v8::Local Http2PushFrameHeaders::NewInstance(struct curl_pushheaders return scope.Escape(jsObj); } -NAN_METHOD(Http2PushFrameHeaders::GetByIndex) { - Nan::HandleScope scope; +Napi::Value Http2PushFrameHeaders::GetByIndex(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - v8::Local value = info[0]; + Napi::Value value = info[0]; if (!value->IsUint32()) { - Nan::ThrowTypeError("Index must be a non-negative integer"); - return; + Napi::TypeError::New(env, "Index must be a non-negative integer").ThrowAsJavaScriptException(); + return env.Null(); } - Http2PushFrameHeaders* obj = Nan::ObjectWrap::Unwrap(info.This()); - uint32_t val = Nan::To(value).FromJust(); + Http2PushFrameHeaders* obj = this; + uint32_t val = value.As().Uint32Value(); char* result = curl_pushheader_bynum(obj->headers, static_cast(val)); - v8::Local returnValue = - result == NULL ? Nan::Null().As() - : Nan::New(result).ToLocalChecked().As(); + Napi::Value returnValue = + result == NULL ? env.Null().As() + : Napi::String>(result).As value = info[0]; + Napi::Value value = info[0]; - if (!value->IsString()) { - Nan::ThrowTypeError("Name must be a string"); - return; + if (!value.IsString()) { + Napi::TypeError::New(env, "Name must be a string").ThrowAsJavaScriptException(); + return env.Null(); } - Http2PushFrameHeaders* obj = Nan::ObjectWrap::Unwrap(info.This()); + Http2PushFrameHeaders* obj = this; - Nan::Utf8String utf8String(value); + std::string utf8String = value.As(); char* result = curl_pushheader_byname(obj->headers, *utf8String); - v8::Local returnValue = - result == NULL ? Nan::Null().As() - : Nan::New(result).ToLocalChecked().As(); + Napi::Value returnValue = + result == NULL ? env.Null().As() + : Napi::String>(result).As(info.This()); + Http2PushFrameHeaders* obj = this; - info.GetReturnValue().Set(Nan::New(static_cast(obj->numberOfHeaders))); + return Napi::Uint32::New(env, static_cast(obj->numberOfHeaders)); } -NAN_MODULE_INIT(Http2PushFrameHeaders::Initialize) { - Nan::HandleScope scope; +Napi::Object Http2PushFrameHeaders::Initialize(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + + v8::Local objTmpl = Napi::ObjectTemplate::New(env); - v8::Local objTmpl = Nan::New(); - objTmpl->SetInternalFieldCount(1); v8::PropertyAttribute attributes = static_cast(v8::ReadOnly | v8::DontDelete); - Nan::SetAccessor(objTmpl, Nan::New("numberOfHeaders").ToLocalChecked(), - Http2PushFrameHeaders::GetterNumberOfHeaders, 0, v8::Local(), + Napi::SetAccessor(objTmpl, Napi::String::New(env, "numberOfHeaders"), + Http2PushFrameHeaders::GetterNumberOfHeaders, 0, Napi::Value(), v8::DEFAULT, attributes); - Nan::SetMethod(objTmpl, "getByIndex", Http2PushFrameHeaders::GetByIndex); - Nan::SetMethod(objTmpl, "getByName", Http2PushFrameHeaders::GetByName); + Napi::SetMethod(objTmpl, "getByIndex", Http2PushFrameHeaders::GetByIndex); + Napi::SetMethod(objTmpl, "getByName", Http2PushFrameHeaders::GetByName); Http2PushFrameHeaders::objectTemplate.Reset(objTmpl); diff --git a/src/Http2PushFrameHeaders.h b/src/Http2PushFrameHeaders.h index a39e2b439..c0538a727 100644 --- a/src/Http2PushFrameHeaders.h +++ b/src/Http2PushFrameHeaders.h @@ -8,12 +8,14 @@ #define NODELIBCURL_HTTP_2_PUSH_FRAME_HEADERS_H #include -#include -#include +#include +#include +#include +#include namespace NodeLibcurl { -class Http2PushFrameHeaders : public Nan::ObjectWrap { +class Http2PushFrameHeaders : public Napi::ObjectWrap { // Private as this can only be created using NewInstance Http2PushFrameHeaders(struct curl_pushheaders* headers, size_t numberOfHeaders); // Copy constructors cannot be used. @@ -24,18 +26,18 @@ class Http2PushFrameHeaders : public Nan::ObjectWrap { size_t numberOfHeaders; // js object template - static Nan::Persistent objectTemplate; + static Napi::Persistent objectTemplate; // js available Methods - static NAN_METHOD(GetByIndex); - static NAN_METHOD(GetByName); - static NAN_GETTER(GetterNumberOfHeaders); + static Napi::Value GetByIndex(const Napi::CallbackInfo& info); + static Napi::Value GetByName(const Napi::CallbackInfo& info); + Napi::Value GetterNumberOfHeaders(const Napi::CallbackInfo& info); public: - static v8::Local NewInstance(struct curl_pushheaders* headers, + static Napi::Object NewInstance(struct curl_pushheaders* headers, size_t numberOfHeaders); - static NAN_MODULE_INIT(Initialize); + static Napi::Object Initialize(Napi::Env env, Napi::Object exports); }; } // namespace NodeLibcurl diff --git a/src/Multi.cc b/src/Multi.cc index b70471198..6d6294005 100644 --- a/src/Multi.cc +++ b/src/Multi.cc @@ -20,7 +20,7 @@ namespace NodeLibcurl { -Nan::Persistent Multi::constructor; +Napi::FunctionReference Multi::constructor; Multi::Multi() { // init uv timer to be used with HandleTimeout @@ -174,8 +174,8 @@ void Multi::OnSocket(uv_poll_t* handle, int status, int events) { errorMsg += std::string("curl_multi_socket_action failed. Reason: ") + curl_multi_strerror(code); - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } ctx->multi->ProcessMessages(); @@ -196,8 +196,8 @@ UV_TIMER_CB(Multi::OnTimeout) { errorMsg += std::string("curl_multi_socket_action failed. Reason: ") + curl_multi_strerror(code); - Nan::ThrowError(errorMsg.c_str()); - return; + Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); + return env.Null(); } obj->ProcessMessages(); @@ -255,7 +255,7 @@ void Multi::OnSocketClose(uv_handle_t* handle) { } void Multi::CallOnMessageCallback(CURL* easy, CURLcode statusCode) { - Nan::HandleScope scope; + Napi::HandleScope scope(env); // we don't have an on message callback, just return. if (this->cbOnMessage == nullptr) { @@ -268,8 +268,8 @@ void Multi::CallOnMessageCallback(CURL* easy, CURLcode statusCode) { char* ptr = nullptr; CURLcode code = curl_easy_getinfo(easy, CURLINFO_PRIVATE, &ptr); if (code != CURLE_OK) { - Nan::ThrowError("Error retrieving current handle instance."); - return; + Napi::Error::New(env, "Error retrieving current handle instance.").ThrowAsJavaScriptException(); + return env.Null(); } assert(ptr != nullptr && "Invalid handle returned from CURLINFO_PRIVATE."); @@ -277,20 +277,20 @@ void Multi::CallOnMessageCallback(CURL* easy, CURLcode statusCode) { bool hasError = !obj->callbackError.IsEmpty(); - v8::Local easyArg = obj->handle(); + Napi::Object easyArg = obj->handle(); - v8::Local err = Nan::Null(); - v8::Local errCode = Nan::New(static_cast( + Napi::Value err = env.Null(); + v8::Local errCode = Napi::New(env, static_cast( statusCode == CURLE_OK && hasError ? CURLE_ABORTED_BY_CALLBACK : statusCode)); if (statusCode != CURLE_OK || hasError) { - err = hasError ? Nan::New(obj->callbackError) : Nan::Error(curl_easy_strerror(statusCode)); + err = hasError ? Napi::New(env, obj->callbackError) : Napi::Error::New(env, curl_easy_strerror(statusCode)); } - v8::Local argv[] = {err, easyArg, errCode}; + Napi::Value argv[] = {err, easyArg, errCode}; const int argc = 3; - Nan::AsyncResource asyncResource("Multi::CallOnMessageCallback"); + Napi::AsyncResource asyncResource("Multi::CallOnMessageCallback"); asyncResource.runInAsyncScope(obj->handle(), this->cbOnMessage->GetFunction(), argc, argv); } @@ -305,7 +305,7 @@ int Multi::CbPushFunction(CURL* parent, CURL* child, size_t numberOfHeaders, // // this means that we must not rethrow errors we catch from user land. // doing so would cause the whole library code to fall apart as it would not be safe to // use other v8 objects. - Nan::HandleScope scope; + Napi::HandleScope scope(env); int returnValue = -1; @@ -326,25 +326,25 @@ int Multi::CbPushFunction(CURL* parent, CURL* child, size_t numberOfHeaders, // assert(parentEasyObj->isOpen && "The Easy instance doing the current request was closed prematurely"); - v8::Local parentEasyJsObj = obj->handle(); + Napi::Object parentEasyJsObj = obj->handle(); // create new Easy instance to be used with the easy curl handle passed // as second parameter - v8::Local childEasyJsObj = Easy::FromCURLHandle(child); + Napi::Object childEasyJsObj = Easy::FromCURLHandle(child); auto http2PushFrameJsObj = Http2PushFrameHeaders::NewInstance(headers, numberOfHeaders); const int argc = 3; - v8::Local argv[argc] = { + Napi::Value argv[argc] = { parentEasyJsObj, childEasyJsObj, http2PushFrameJsObj, }; - Nan::TryCatch tryCatch; + Napi::TryCatch tryCatch; - Nan::AsyncResource asyncResource("Multi::CbPushFunction"); - Nan::MaybeLocal returnValueCallback = + Napi::AsyncResource asyncResource("Multi::CbPushFunction"); + Napi::MaybeLocal returnValueCallback = asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); if (tryCatch.HasCaught()) { @@ -353,67 +353,69 @@ int Multi::CbPushFunction(CURL* parent, CURL* child, size_t numberOfHeaders, // return returnValue; } - if (returnValueCallback.IsEmpty() || !returnValueCallback.ToLocalChecked()->IsInt32()) { + if (returnValueCallback.IsEmpty() || !returnValueCallback.IsNumber()) { // Nothing we can do - Let's just ignore it - // v8::Local typeError = - // Nan::TypeError("Return value from the PUSHFUNCTION callback must be an integer."); - // Nan::ThrowError(typeError); + // Napi::Value typeError = + // Napi::TypeError::New(env, "Return value from the PUSHFUNCTION callback must be an integer."); + // Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + } else { - returnValue = Nan::To(returnValueCallback.ToLocalChecked()).FromJust(); + returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); } return returnValue; } // Add Curl constructor to the module exports -NAN_MODULE_INIT(Multi::Initialize) { - Nan::HandleScope scope; +Napi::Object Multi::Initialize(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); // Multi js "class" function template initialization - v8::Local tmpl = Nan::New(Multi::New); - tmpl->SetClassName(Nan::New("Multi").ToLocalChecked()); - tmpl->InstanceTemplate()->SetInternalFieldCount(1); + Napi::FunctionReference tmpl = Napi::Function::New(env, Multi::New); + tmpl->SetClassName(Napi::String::New(env, "Multi")); + // prototype methods - Nan::SetPrototypeMethod(tmpl, "setOpt", Multi::SetOpt); - Nan::SetPrototypeMethod(tmpl, "addHandle", Multi::AddHandle); - Nan::SetPrototypeMethod(tmpl, "onMessage", Multi::OnMessage); - Nan::SetPrototypeMethod(tmpl, "removeHandle", Multi::RemoveHandle); - Nan::SetPrototypeMethod(tmpl, "getCount", Multi::GetCount); - Nan::SetPrototypeMethod(tmpl, "close", Multi::Close); + Napi::SetPrototypeMethod(tmpl, "setOpt", Multi::SetOpt); + Napi::SetPrototypeMethod(tmpl, "addHandle", Multi::AddHandle); + Napi::SetPrototypeMethod(tmpl, "onMessage", Multi::OnMessage); + Napi::SetPrototypeMethod(tmpl, "removeHandle", Multi::RemoveHandle); + Napi::SetPrototypeMethod(tmpl, "getCount", Multi::GetCount); + Napi::SetPrototypeMethod(tmpl, "close", Multi::Close); // static methods - Nan::SetMethod(tmpl, "strError", Multi::StrError); + Napi::SetMethod(tmpl, "strError", Multi::StrError); Multi::constructor.Reset(tmpl); - Nan::Set(target, Nan::New("Multi").ToLocalChecked(), Nan::GetFunction(tmpl).ToLocalChecked()); + (target).Set(Napi::String::New(env, "Multi"), Napi::GetFunction(tmpl)); } -NAN_METHOD(Multi::New) { +Napi::Value Multi::New(const Napi::CallbackInfo& info) { if (!info.IsConstructCall()) { - Nan::ThrowError("You must use \"new\" to instantiate this object."); + Napi::Error::New(env, "You must use \"new\" to instantiate this object.").ThrowAsJavaScriptException(); + } Multi* obj = new Multi(); obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Multi::SetOpt) { - Nan::HandleScope scope; +Napi::Value Multi::SetOpt(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Multi* obj = Nan::ObjectWrap::Unwrap(info.This()); + Multi* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Multi handle is closed."); - return; + Napi::Error::New(env, "Multi handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local opt = info[0]; - v8::Local value = info[1]; + Napi::Value opt = info[0]; + Napi::Value value = info[1]; CURLMcode setOptRetCode = CURLM_UNKNOWN_OPTION; @@ -421,7 +423,7 @@ NAN_METHOD(Multi::SetOpt) { // array of strings option if ((optionId = IsInsideCurlConstantStruct(curlMultiOptionNotImplemented, opt))) { - Nan::ThrowError( + Napi::ThrowError( "Unsupported option, probably because it's too complex to implement " "using javascript or unecessary when using javascript."); return; @@ -431,16 +433,16 @@ NAN_METHOD(Multi::SetOpt) { } else { if (!value->IsArray()) { - Nan::ThrowTypeError("Option value must be an Array."); - return; + Napi::TypeError::New(env, "Option value must be an Array.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local array = v8::Local::Cast(value); + Napi::Array array = value.As(); uint32_t arrayLength = array->Length(); std::vector strings; for (uint32_t i = 0; i < arrayLength; ++i) { - strings.push_back(*Nan::Utf8String(Nan::Get(array, i).ToLocalChecked())); + strings.push_back((array).Get(i->As().Utf8Value().c_str())); } strings.push_back(NULL); @@ -451,20 +453,20 @@ NAN_METHOD(Multi::SetOpt) { // check if option is integer, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlMultiOptionInteger, opt))) { // If not an integer, throw error - if (!value->IsInt32()) { - Nan::ThrowTypeError("Option value must be an integer."); - return; + if (!value.IsNumber()) { + Napi::TypeError::New(env, "Option value must be an integer.").ThrowAsJavaScriptException(); + return env.Null(); } - int32_t val = Nan::To(value).FromJust(); + int32_t val = value.As().Int32Value(); setOptRetCode = curl_multi_setopt(obj->mh, static_cast(optionId), val); } else if ((optionId = IsInsideCurlConstantStruct(curlMultiOptionFunction, opt))) { bool isNull = value->IsNull(); if (!value->IsFunction() && !isNull) { - Nan::ThrowTypeError("Option value must be null or a function."); - return; + Napi::TypeError::New(env, "Option value must be null or a function.").ThrowAsJavaScriptException(); + return env.Null(); } switch (optionId) { @@ -477,7 +479,7 @@ NAN_METHOD(Multi::SetOpt) { curl_multi_setopt(obj->mh, CURLMOPT_PUSHDATA, NULL); setOptRetCode = curl_multi_setopt(obj->mh, CURLMOPT_PUSHFUNCTION, NULL); } else { - obj->callbacks[CURLMOPT_PUSHFUNCTION].reset(new Nan::Callback(value.As())); + obj->callbacks[CURLMOPT_PUSHFUNCTION].reset(new Napi::FunctionReference(value.As())); curl_multi_setopt(obj->mh, CURLMOPT_PUSHDATA, obj); setOptRetCode = curl_multi_setopt(obj->mh, CURLMOPT_PUSHFUNCTION, Multi::CbPushFunction); @@ -488,27 +490,27 @@ NAN_METHOD(Multi::SetOpt) { } } - info.GetReturnValue().Set(setOptRetCode); + return setOptRetCode; } -NAN_METHOD(Multi::OnMessage) { - Nan::HandleScope scope; +Napi::Value Multi::OnMessage(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Multi* obj = Nan::ObjectWrap::Unwrap(info.This()); + Multi* obj = this; if (!info.Length()) { - Nan::ThrowError( + Napi::ThrowError( "You must specify the callback function. If you want to remove the " "current one you can pass null."); return; } - v8::Local arg = info[0]; + Napi::Value arg = info[0]; bool isNull = arg->IsNull(); if (!arg->IsFunction() && !isNull) { - Nan::ThrowTypeError( + Napi::ThrowTypeError( "Argument must be a Function. If you want to remove the current one " "you can pass null."); return; @@ -517,33 +519,33 @@ NAN_METHOD(Multi::OnMessage) { if (isNull) { obj->cbOnMessage = nullptr; } else { - obj->cbOnMessage.reset(new Nan::Callback(arg.As())); + obj->cbOnMessage.reset(new Napi::FunctionReference(arg.As())); } - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Multi::AddHandle) { - Nan::HandleScope scope; +Napi::Value Multi::AddHandle(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Multi* obj = Nan::ObjectWrap::Unwrap(info.This()); + Multi* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Multi handle is closed."); - return; + Napi::Error::New(env, "Multi handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local handle = info[0]; + Napi::Value handle = info[0]; - if (!handle->IsObject() || !Nan::New(Easy::constructor)->HasInstance(handle)) { - Nan::ThrowError(Nan::TypeError("Argument must be an instance of an Easy handle.")); - return; + if (!handle.IsObject() || !Napi::New(env, Easy::constructor)->HasInstance(handle)) { + Napi::Error::New(env, Napi::TypeError::New(env, "Argument must be an instance of an Easy handle.")).ThrowAsJavaScriptException(); + return env.Null(); } else { - Easy* easy = Nan::ObjectWrap::Unwrap(handle.As()); + Easy* easy = handle.As().Unwrap(); if (!easy->isOpen) { - Nan::ThrowError("Cannot add an Easy handle that is closed."); - return; + Napi::Error::New(env, "Cannot add an Easy handle that is closed.").ThrowAsJavaScriptException(); + return env.Null(); } easy->SetUrlOpts(); @@ -556,91 +558,91 @@ NAN_METHOD(Multi::AddHandle) { curl_multi_add_handle(obj->mh, easy->ch);); // NOLINT(whitespace/newline) if (code != CURLM_OK) { - Nan::ThrowError(Nan::TypeError("Could not add easy handle to the multi handle.")); - return; + Napi::Error::New(env, Napi::TypeError::New(env, "Could not add easy handle to the multi handle.")).ThrowAsJavaScriptException(); + return env.Null(); } ++obj->amountOfHandles; easy->isInsideMultiHandle = true; - v8::Local ret = Nan::New(static_cast(code)); + v8::Local ret = Napi::New(env, static_cast(code)); - info.GetReturnValue().Set(ret); + return ret; } } -NAN_METHOD(Multi::RemoveHandle) { - Nan::HandleScope scope; +Napi::Value Multi::RemoveHandle(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Multi* obj = Nan::ObjectWrap::Unwrap(info.This()); + Multi* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Multi handle is closed."); - return; + Napi::Error::New(env, "Multi handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local handle = info[0]; + Napi::Value handle = info[0]; - if (!handle->IsObject() || !Nan::New(Easy::constructor)->HasInstance(handle)) { - Nan::ThrowError(Nan::TypeError("Argument must be an instance of an Easy handle.")); - return; + if (!handle.IsObject() || !Napi::New(env, Easy::constructor)->HasInstance(handle)) { + Napi::Error::New(env, Napi::TypeError::New(env, "Argument must be an instance of an Easy handle.")).ThrowAsJavaScriptException(); + return env.Null(); } else { - Easy* easy = Nan::ObjectWrap::Unwrap(handle.As()); + Easy* easy = handle.As().Unwrap(); CURLMcode code = curl_multi_remove_handle(obj->mh, easy->ch); if (code != CURLM_OK) { - Nan::ThrowError(Nan::TypeError("Could not remove easy handle from multi handle.")); - return; + Napi::Error::New(env, Napi::TypeError::New(env, "Could not remove easy handle from multi handle.")).ThrowAsJavaScriptException(); + return env.Null(); } --obj->amountOfHandles; easy->isInsideMultiHandle = false; - v8::Local ret = Nan::New(static_cast(code)); + v8::Local ret = Napi::New(env, static_cast(code)); - info.GetReturnValue().Set(ret); + return ret; } } -NAN_METHOD(Multi::GetCount) { - Nan::HandleScope scope; +Napi::Value Multi::GetCount(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Multi* obj = Nan::ObjectWrap::Unwrap(info.This()); + Multi* obj = this; - v8::Local ret = Nan::New(static_cast(obj->amountOfHandles)); + v8::Local ret = Napi::New(env, static_cast(obj->amountOfHandles)); - info.GetReturnValue().Set(ret); + return ret; } -NAN_METHOD(Multi::Close) { - Nan::HandleScope scope; +Napi::Value Multi::Close(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Multi* obj = Nan::ObjectWrap::Unwrap(info.This()); + Multi* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Multi handle already closed."); - return; + Napi::Error::New(env, "Multi handle already closed.").ThrowAsJavaScriptException(); + return env.Null(); } obj->Dispose(); } -NAN_METHOD(Multi::StrError) { - Nan::HandleScope scope; +Napi::Value Multi::StrError(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - v8::Local errCode = info[0]; + Napi::Value errCode = info[0]; - if (!errCode->IsInt32()) { - Nan::ThrowTypeError("Invalid errCode passed to Multi.strError."); - return; + if (!errCode.IsNumber()) { + Napi::TypeError::New(env, "Invalid errCode passed to Multi.strError.").ThrowAsJavaScriptException(); + return env.Null(); } const char* errorMsg = - curl_multi_strerror(static_cast(Nan::To(errCode).FromJust())); + curl_multi_strerror(static_cast(errCode.As().Int32Value())); - v8::Local ret = Nan::New(errorMsg).ToLocalChecked(); + Napi::String ret = Napi::New(env, errorMsg); - info.GetReturnValue().Set(ret); + return ret; } } // namespace NodeLibcurl diff --git a/src/Multi.h b/src/Multi.h index 30a0ee09f..63c739ecf 100644 --- a/src/Multi.h +++ b/src/Multi.h @@ -12,14 +12,16 @@ #include "make_unique.h" #include -#include -#include +#include +#include +#include +#include #include namespace NodeLibcurl { -class Multi : public Nan::ObjectWrap { +class Multi : public Napi::ObjectWrap { // instance methods Multi(); ~Multi(); @@ -47,10 +49,10 @@ class Multi : public Nan::ObjectWrap { int runningHandles = 0; // callbacks - typedef std::map> CallbacksMap; + typedef std::map> CallbacksMap; CallbacksMap callbacks = CallbacksMap{}; // required as it's not specific to a single message - std::shared_ptr cbOnMessage; + std::shared_ptr cbOnMessage; deleted_unique_ptr timeout; @@ -58,17 +60,17 @@ class Multi : public Nan::ObjectWrap { static CurlSocketContext* CreateCurlSocketContext(curl_socket_t sockfd, Multi* multi); static void DestroyCurlSocketContext(CurlSocketContext* ctx); // js object constructor template - static Nan::Persistent constructor; + static Napi::FunctionReference constructor; // js available Methods - static NAN_METHOD(New); - static NAN_METHOD(SetOpt); - static NAN_METHOD(AddHandle); - static NAN_METHOD(OnMessage); - static NAN_METHOD(RemoveHandle); - static NAN_METHOD(GetCount); - static NAN_METHOD(Close); - static NAN_METHOD(StrError); + static Napi::Value New(const Napi::CallbackInfo& info); + static Napi::Value SetOpt(const Napi::CallbackInfo& info); + static Napi::Value AddHandle(const Napi::CallbackInfo& info); + static Napi::Value OnMessage(const Napi::CallbackInfo& info); + static Napi::Value RemoveHandle(const Napi::CallbackInfo& info); + static Napi::Value GetCount(const Napi::CallbackInfo& info); + static Napi::Value Close(const Napi::CallbackInfo& info); + static Napi::Value StrError(const Napi::CallbackInfo& info); // libcurl multi_setopt callbacks static int HandleSocket(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp); @@ -85,7 +87,7 @@ class Multi : public Nan::ObjectWrap { public: // export Multi to js - static NAN_MODULE_INIT(Initialize); + static Napi::Object Initialize(Napi::Env env, Napi::Object exports); }; } // namespace NodeLibcurl diff --git a/src/Share.cc b/src/Share.cc index dcef8e45d..991d8809c 100644 --- a/src/Share.cc +++ b/src/Share.cc @@ -18,7 +18,7 @@ namespace NodeLibcurl { -Nan::Persistent Share::constructor; +Napi::FunctionReference Share::constructor; Share::Share() : isOpen(true) { this->sh = curl_share_init(); @@ -42,62 +42,63 @@ void Share::Dispose() { this->isOpen = false; } -NAN_MODULE_INIT(Share::Initialize) { - Nan::HandleScope scope; +Napi::Object Share::Initialize(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); // Easy js "class" function template initialization - v8::Local tmpl = Nan::New(Share::New); - tmpl->SetClassName(Nan::New("Share").ToLocalChecked()); - tmpl->InstanceTemplate()->SetInternalFieldCount(1); + Napi::FunctionReference tmpl = Napi::Function::New(env, Share::New); + tmpl->SetClassName(Napi::String::New(env, "Share")); + // prototype methods - Nan::SetPrototypeMethod(tmpl, "setOpt", Share::SetOpt); - Nan::SetPrototypeMethod(tmpl, "close", Share::Close); + Napi::SetPrototypeMethod(tmpl, "setOpt", Share::SetOpt); + Napi::SetPrototypeMethod(tmpl, "close", Share::Close); // static methods - Nan::SetMethod(tmpl, "strError", Share::StrError); + Napi::SetMethod(tmpl, "strError", Share::StrError); Share::constructor.Reset(tmpl); - Nan::Set(target, Nan::New("Share").ToLocalChecked(), Nan::GetFunction(tmpl).ToLocalChecked()); + (target).Set(Napi::String::New(env, "Share"), Napi::GetFunction(tmpl)); } -NAN_METHOD(Share::New) { +Napi::Value Share::New(const Napi::CallbackInfo& info) { if (!info.IsConstructCall()) { - Nan::ThrowError("You must use \"new\" to instantiate this object."); + Napi::Error::New(env, "You must use \"new\" to instantiate this object.").ThrowAsJavaScriptException(); + } Share* obj = new Share(); obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(Share::SetOpt) { - Nan::HandleScope scope; +Napi::Value Share::SetOpt(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Share* obj = Nan::ObjectWrap::Unwrap(info.This()); + Share* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Share handle is closed."); - return; + Napi::Error::New(env, "Share handle is closed.").ThrowAsJavaScriptException(); + return env.Null(); } - v8::Local opt = info[0]; - v8::Local value = info[1]; + Napi::Value opt = info[0]; + Napi::Value value = info[1]; CURLSHcode setOptRetCode = CURLSHE_BAD_OPTION; int32_t optionId = -1; - if (!value->IsInt32()) { - Nan::ThrowError("Option value must be an integer."); - return; + if (!value.IsNumber()) { + Napi::Error::New(env, "Option value must be an integer.").ThrowAsJavaScriptException(); + return env.Null(); } - if (opt->IsInt32()) { - optionId = Nan::To(opt).FromJust(); - } else if (opt->IsString()) { - Nan::Utf8String option(opt); + if (opt.IsNumber()) { + optionId = opt.As().Int32Value(); + } else if (opt.IsString()) { + std::string option = opt.As(); std::string optionString(*option); @@ -109,19 +110,19 @@ NAN_METHOD(Share::SetOpt) { } setOptRetCode = curl_share_setopt(obj->sh, static_cast(optionId), - Nan::To(value).FromJust()); + value.As().Int32Value()); - info.GetReturnValue().Set(setOptRetCode); + return setOptRetCode; } -NAN_METHOD(Share::Close) { - Nan::HandleScope scope; +Napi::Value Share::Close(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - Share* obj = Nan::ObjectWrap::Unwrap(info.This()); + Share* obj = this; if (!obj->isOpen) { - Nan::ThrowError("Share handle already closed."); - return; + Napi::Error::New(env, "Share handle already closed.").ThrowAsJavaScriptException(); + return env.Null(); } obj->Dispose(); @@ -129,22 +130,22 @@ NAN_METHOD(Share::Close) { return; } -NAN_METHOD(Share::StrError) { - Nan::HandleScope scope; +Napi::Value Share::StrError(const Napi::CallbackInfo& info) { + Napi::HandleScope scope(env); - v8::Local errCode = info[0]; + Napi::Value errCode = info[0]; - if (!errCode->IsInt32()) { - Nan::ThrowTypeError("Invalid errCode passed to Share.strError."); - return; + if (!errCode.IsNumber()) { + Napi::TypeError::New(env, "Invalid errCode passed to Share.strError.").ThrowAsJavaScriptException(); + return env.Null(); } const char* errorMsg = - curl_share_strerror(static_cast(Nan::To(errCode).FromJust())); + curl_share_strerror(static_cast(errCode.As().Int32Value())); - v8::Local ret = Nan::New(errorMsg).ToLocalChecked(); + Napi::String ret = Napi::New(env, errorMsg); - info.GetReturnValue().Set(ret); + return ret; } } // namespace NodeLibcurl diff --git a/src/Share.h b/src/Share.h index 3c04943f7..1f0ae826d 100644 --- a/src/Share.h +++ b/src/Share.h @@ -9,12 +9,14 @@ #define NODELIBCURL_SHARE_H #include -#include -#include +#include +#include +#include +#include namespace NodeLibcurl { -class Share : public Nan::ObjectWrap { +class Share : public Napi::ObjectWrap { Share(); Share(const Share& that); @@ -27,20 +29,20 @@ class Share : public Nan::ObjectWrap { public: // js object constructor template - static Nan::Persistent constructor; + static Napi::FunctionReference constructor; // members CURLSH* sh; bool isOpen; // export Easy to js - static NAN_MODULE_INIT(Initialize); + static Napi::Object Initialize(Napi::Env env, Napi::Object exports); // js available methods - static NAN_METHOD(New); - static NAN_METHOD(SetOpt); - static NAN_METHOD(Close); - static NAN_METHOD(StrError); + static Napi::Value New(const Napi::CallbackInfo& info); + static Napi::Value SetOpt(const Napi::CallbackInfo& info); + static Napi::Value Close(const Napi::CallbackInfo& info); + static Napi::Value StrError(const Napi::CallbackInfo& info); }; } // namespace NodeLibcurl #endif diff --git a/src/macros.h b/src/macros.h index 0c12ae23f..5c69a0ecc 100644 --- a/src/macros.h +++ b/src/macros.h @@ -57,7 +57,8 @@ if (obj->isInsideMultiHandle) { \ obj->callbackError.Reset(typeError); \ } else { \ - Nan::ThrowError(typeError); \ + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); + \ tryCatch.ReThrow(); \ } #endif diff --git a/src/node_libcurl.cc b/src/node_libcurl.cc index 3447fff75..73c1d16c0 100644 --- a/src/node_libcurl.cc +++ b/src/node_libcurl.cc @@ -15,8 +15,10 @@ #include "Share.h" #include -#include -#include +#include +#include +#include +#include #include @@ -28,7 +30,7 @@ static void AtExitCallback(void* arg) { curl_global_cleanup(); } -NAN_MODULE_INIT(Init) { +Napi::Object Init(Napi::Env env, Napi::Object exports) { // Some background story on this commented code and other usages of setlocale // elsewhere on the addon: Libcurl, when built with libidn2, calls function // `idn2_lookup_ul` to retrieve a punycode representation @@ -51,14 +53,14 @@ NAN_MODULE_INIT(Init) { // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=vs-2019 // setlocale(AC_ALL, "") Initialize(target); - Easy::Initialize(target); - Multi::Initialize(target); - Share::Initialize(target); - CurlVersionInfo::Initialize(target); - Http2PushFrameHeaders::Initialize(target); + Easy::Initialize(env, target, module); + Multi::Initialize(env, target, module); + Share::Initialize(env, target, module); + CurlVersionInfo::Initialize(env, target, module); + Http2PushFrameHeaders::Initialize(env, target, module); #if NODE_VERSION_AT_LEAST(11, 0, 0) - auto context = Nan::GetCurrentContext(); + auto context = Napi::GetCurrentContext(); node::AtExit(node::GetCurrentEnvironment(context), AtExitCallback, NULL); #else // this will stay until Node.js v10 support is dropped @@ -68,5 +70,5 @@ NAN_MODULE_INIT(Init) { #endif } -NODE_MODULE(node_libcurl, Init); +NODE_API_MODULE(node_libcurl, Init); } // namespace NodeLibcurl From 57b725d46aa91a24747996af51acdc0073a0812c Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 27 Aug 2024 18:26:26 +0200 Subject: [PATCH 03/34] fix include_dirs --- binding.gyp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding.gyp b/binding.gyp index 4867b6d58..ff2efa59f 100644 --- a/binding.gyp +++ b/binding.gyp @@ -58,7 +58,7 @@ 'src/CurlVersionInfo.cc', 'src/Http2PushFrameHeaders.cc', ], - 'include_dirs' : [ + 'include_dirs' : [ " Date: Thu, 29 Aug 2024 11:46:22 +0100 Subject: [PATCH 04/34] fixing some of the compile errors --- src/Easy.cc | 2 +- src/Easy.h | 6 ++++-- src/Http2PushFrameHeaders.cc | 2 +- src/Http2PushFrameHeaders.h | 2 +- src/node_libcurl.cc | 6 +++--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index b2ce4d8e2..1bcb3fbde 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1009,7 +1009,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { auto idxValueAsObject = idxValueChecked.As(); - Napi::CopyablePersistentTraits::CopyablePersistent persistentValue; + v8::NonCopyablePersistentTraits::CopyablePersistent persistentValue; persistentValue.Reset(Napi::GetCurrentContext()->GetIsolate(), idxValueAsObject); diff --git a/src/Easy.h b/src/Easy.h index 8ebe9da48..bddc0deb7 100644 --- a/src/Easy.h +++ b/src/Easy.h @@ -15,10 +15,12 @@ #include #include #include +#include #include #include + namespace NodeLibcurl { class Easy : public Napi::ObjectWrap { @@ -53,7 +55,7 @@ class Easy : public Napi::ObjectWrap { cbOnSocketEvent; // still required since it's not related to any CURLOption // members - std::vector::CopyablePersistent> hstsReadCache; + std::vector> hstsReadCache; uint32_t wasHstsReadCacheSet = false; uv_poll_t* socketPollHandle = nullptr; std::shared_ptr toFree = nullptr; @@ -138,7 +140,7 @@ class Easy : public Napi::ObjectWrap { bool isOpen = true; // used to return callback errors when inside Multi interface - Napi::Persistent callbackError; + v8::Persistent callbackError; // static members static uint32_t currentOpenedHandles; diff --git a/src/Http2PushFrameHeaders.cc b/src/Http2PushFrameHeaders.cc index 48c6b789c..9d257ea73 100644 --- a/src/Http2PushFrameHeaders.cc +++ b/src/Http2PushFrameHeaders.cc @@ -13,7 +13,7 @@ namespace NodeLibcurl { -Napi::Persistent Http2PushFrameHeaders::objectTemplate; +v8::Persistent Http2PushFrameHeaders::objectTemplate; Http2PushFrameHeaders::Http2PushFrameHeaders(struct curl_pushheaders* headers, size_t numberOfHeaders) { diff --git a/src/Http2PushFrameHeaders.h b/src/Http2PushFrameHeaders.h index c0538a727..55005bdc1 100644 --- a/src/Http2PushFrameHeaders.h +++ b/src/Http2PushFrameHeaders.h @@ -26,7 +26,7 @@ class Http2PushFrameHeaders : public Napi::ObjectWrap { size_t numberOfHeaders; // js object template - static Napi::Persistent objectTemplate; + static v8::Persistent objectTemplate; // js available Methods static Napi::Value GetByIndex(const Napi::CallbackInfo& info); diff --git a/src/node_libcurl.cc b/src/node_libcurl.cc index 73c1d16c0..fb1d76e7a 100644 --- a/src/node_libcurl.cc +++ b/src/node_libcurl.cc @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include #include @@ -60,7 +60,7 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) { Http2PushFrameHeaders::Initialize(env, target, module); #if NODE_VERSION_AT_LEAST(11, 0, 0) - auto context = Napi::GetCurrentContext(); + auto context = v8::Isolate::GetCurrent()->GetCurrentContext(); node::AtExit(node::GetCurrentEnvironment(context), AtExitCallback, NULL); #else // this will stay until Node.js v10 support is dropped From 3c8451e24c967d08f10698071724c54892e57be1 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Thu, 29 Aug 2024 12:06:53 +0100 Subject: [PATCH 05/34] fix the initialize calls on node_libcurl.cc --- src/macros.h | 4 +--- src/node_libcurl.cc | 35 +++++++---------------------------- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/src/macros.h b/src/macros.h index 5c69a0ecc..d56958fef 100644 --- a/src/macros.h +++ b/src/macros.h @@ -57,8 +57,6 @@ if (obj->isInsideMultiHandle) { \ obj->callbackError.Reset(typeError); \ } else { \ - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - \ - tryCatch.ReThrow(); \ + Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); \ } #endif diff --git a/src/node_libcurl.cc b/src/node_libcurl.cc index fb1d76e7a..f6e3fd9a9 100644 --- a/src/node_libcurl.cc +++ b/src/node_libcurl.cc @@ -19,7 +19,7 @@ #include #include #include - +#include #include namespace NodeLibcurl { @@ -31,33 +31,12 @@ static void AtExitCallback(void* arg) { } Napi::Object Init(Napi::Env env, Napi::Object exports) { - // Some background story on this commented code and other usages of setlocale - // elsewhere on the addon: Libcurl, when built with libidn2, calls function - // `idn2_lookup_ul` to retrieve a punycode representation - // of a domain. This function internally uses libunistring - // `u8_strconv_from_encoding`, which expects an existing locale being set: - // https://github.com/libidn/libidn2/blob/02a3127d21f8a99042a8ae82f1513b3ffc0170f2/lib/lookup.c#L536 - // Node.js (correctly) does not set any locale by default, and so when this - // function gets called - // an error is returned, and libcurl bails out with MALFORMED URL error. - // We could just call setlocale here, like the commented code, and it would - // work, however this would - // impact addon users that, in some way, use locale. - // (I've opened this issue to make sure - // https://github.com/nodejs/help/issues/1878) Instead of doing that, we are - // instead calling setlocale on some specific parts of the code, to be - // more specific, on Easy#SetPerform, Multi#AddHandle and Multi#OnSocket - // That code is behind a DEFINE guard, which the user can disable by passing - // `node_libcurl_no_setlocale` option when building, this will define - // NODE_LIBCURL_NO_SETLOCALE. - // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=vs-2019 - // setlocale(AC_ALL, "") - Initialize(target); - Easy::Initialize(env, target, module); - Multi::Initialize(env, target, module); - Share::Initialize(env, target, module); - CurlVersionInfo::Initialize(env, target, module); - Http2PushFrameHeaders::Initialize(env, target, module); + // Initialize(target); + Easy::Initialize(env, exports); + Multi::Initialize(env, exports); + Share::Initialize(env, exports); + CurlVersionInfo::Initialize(env, exports); + Http2PushFrameHeaders::Initialize(env, exports); #if NODE_VERSION_AT_LEAST(11, 0, 0) auto context = v8::Isolate::GetCurrent()->GetCurrentContext(); From b5e71290b76d0e1a102c9d21c9d7b3bb35a9a876 Mon Sep 17 00:00:00 2001 From: jackkav Date: Fri, 6 Sep 2024 22:41:55 +0200 Subject: [PATCH 06/34] add dx --- .gitignore | 1 - .vscode/tasks.json | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 .vscode/tasks.json diff --git a/.gitignore b/.gitignore index ea9f54ea4..06b7be266 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ debug/ Debug/ release/ Release/ -.vscode/ test/curl/upload.png # coverage diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..aa63923ea --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,39 @@ +{ + "version": "2.0.0", + "command": "make", + "tasks": [ + { + "label": "Build with Make", + "type": "shell", + "command": "make", + "options": { + "cwd": "${workspaceFolder}/build" + }, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, + // arg passing example: in this case is executed make QUIET=0 + "args": ["QUIET=0"], + // Use the standard less compilation problem matcher. + "problemMatcher": { + "owner": "cpp", + "fileLocation": ["relative","${workspaceFolder}/build"], + "pattern": { + "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } + } + ] + } \ No newline at end of file From 8a1f8c604b0984c85f669e571efb267c7c0e31a6 Mon Sep 17 00:00:00 2001 From: jackkav Date: Fri, 6 Sep 2024 22:49:15 +0200 Subject: [PATCH 07/34] 485 --- src/Easy.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 1bcb3fbde..3062cfa1c 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -405,8 +405,8 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) Napi::HandleScope scope(env); Napi::Object buf = Napi::Buffer::New(env, static_cast(n)); - v8::Local sizeArg = Napi::Uint32::New(env, static_cast(size)); - v8::Local nmembArg = Napi::Uint32::New(env, static_cast(nmemb)); + v8::Local sizeArg = Napi::Number::New(env, static_cast(size)); + v8::Local nmembArg = Napi::Number::New(env, static_cast(nmemb)); const int argc = 3; Napi::Value argv[argc] = { buf, @@ -496,8 +496,8 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { if (it != obj->callbacks.end()) { Napi::HandleScope scope(env); - v8::Local offsetArg = Napi::Uint32::New(env, static_cast(offset)); - v8::Local originArg = Napi::Uint32::New(env, static_cast(origin)); + v8::Local offsetArg = Napi::Number::New(env, static_cast(offset)); + v8::Local originArg = Napi::Number::New(env, static_cast(origin)); const int argc = 2; Napi::Value argv[argc] = { offsetArg, @@ -565,8 +565,8 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { const int argc = 3; Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); - v8::Local sizeArg = Napi::Uint32::New(env, static_cast(size)); - v8::Local nmembArg = Napi::Uint32::New(env, static_cast(nmemb)); + v8::Local sizeArg = Napi::Number::New(env, static_cast(size)); + v8::Local nmembArg = Napi::Number::New(env, static_cast(nmemb)); Napi::Value argv[argc] = {buf, sizeArg, nmembArg}; @@ -621,8 +621,8 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { const int argc = 3; Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); - v8::Local sizeArg = Napi::Uint32::New(env, static_cast(size)); - v8::Local nmembArg = Napi::Uint32::New(env, static_cast(nmemb)); + v8::Local sizeArg = Napi::Number::New(env, static_cast(size)); + v8::Local nmembArg = Napi::Number::New(env, static_cast(nmemb)); Napi::Value argv[argc] = {buf, sizeArg, nmembArg}; From deeffe356e66ce88a7f5fd864f2593ad83b6a0a6 Mon Sep 17 00:00:00 2001 From: jackkav Date: Fri, 6 Sep 2024 23:44:20 +0200 Subject: [PATCH 08/34] 481 --- src/Easy.cc | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 3062cfa1c..6d4859e95 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1527,11 +1527,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // we probably could use these here for newer libcurl versions... if ((optionId = IsInsideCurlConstantStruct(curlOptionNotImplemented, opt))) { - Napi::ThrowError( - "Unsupported option, probably because it's too complex to implement " - "using javascript or unecessary when using javascript (like the _DATA " - "options)."); - return; + throw Napi::Error::New(env, "Unsupported option, probably because it's too complex to implement using javascript or unecessary when using javascript (like the _DATA options)."); } else if ((optionId = IsInsideCurlConstantStruct(curlOptionSpecific, opt))) { switch (optionId) { case CURLOPT_SHARE: @@ -1539,10 +1535,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); } else { if (!value.IsObject() || !Napi::New(env, Share::constructor)->HasInstance(value)) { - Napi::ThrowTypeError( - "Invalid value for the SHARE option. It must be a Share " - "instance."); - return; + throw Napi::Error::New(env, ( + "Invalid value for the SHARE option. It must be a Share instance."); } Share* share = value.As().Unwrap(); @@ -2116,10 +2110,8 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { // Special case for unsupported info if ((infoId = IsInsideCurlConstantStruct(curlInfoNotImplemented, infoVal))) { - Napi::ThrowError( - "Unsupported info, probably because it's too complex to implement " - "using javascript or unecessary when using javascript."); - return; + throw Napi::Error::New(env, ( + "Unsupported info, probably because it's too complex to implement using javascript or unecessary when using javascript."); } Napi::TryCatch tryCatch; @@ -2365,10 +2357,8 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { CURLcode code = curl_easy_upkeep(obj->ch); #else CURLcode code = CURLE_FUNCTION_NOT_FOUND; - Napi::ThrowError( - "The addon was built against a libcurl version that does not support upkeep. It requires " - "libcurl >= 7.62"); - return; + throw Napi::Error::New(env, ( + "The addon was built against a libcurl version that does not support upkeep. It requires libcurl >= 7.62"); #endif v8::Local ret = Napi::Number::New(env, static_cast(code)); From 5a4827b0c6360fcd7546832abeef3f221dc4b8d3 Mon Sep 17 00:00:00 2001 From: jackkav Date: Fri, 6 Sep 2024 23:51:59 +0200 Subject: [PATCH 09/34] 469 --- src/Easy.cc | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 6d4859e95..823b7d8a8 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1445,6 +1445,7 @@ Napi::Object Easy::Initialize(Napi::Env env, Napi::Object exports) { } Napi::Value Easy::New(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); if (!info.IsConstructCall()) { Napi::Error::New(env, "You must use \"new\" to instantiate this object.") .ThrowAsJavaScriptException(); @@ -1454,17 +1455,14 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { Easy* obj = nullptr; // Copy constructor, used when duplicating handles. - if (!jsHandle->IsUndefined()) { - if (!jsHandle->IsExternal() && + if (!jsHandle.IsUndefined()) { + if (!jsHandle.IsExternal() && (!jsHandle.IsObject() || !Napi::New(env, Easy::constructor)->HasInstance(jsHandle))) { - Napi::Error::New(env, - Napi::TypeError::New(env, "Argument must be an instance of an Easy handle.")) - .ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Argument must be an instance of an Easy handle."); } // This is the case when calling with a curl easy handle directly - if (jsHandle->IsExternal()) { + if (jsHandle.IsExternal()) { CURL* curlEasyHandle = reinterpret_cast(info[0].As()->Value()); obj = new Easy(curlEasyHandle); } else { @@ -1531,7 +1529,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else if ((optionId = IsInsideCurlConstantStruct(curlOptionSpecific, opt))) { switch (optionId) { case CURLOPT_SHARE: - if (value->IsNull()) { + if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); } else { if (!value.IsObject() || !Napi::New(env, Share::constructor)->HasInstance(value)) { @@ -1552,14 +1550,14 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } // linked list options } else if ((optionId = IsInsideCurlConstantStruct(curlOptionLinkedList, opt))) { - if (value->IsNull()) { + if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); // HTTPPOST is a special case, since it's an array of objects. } else if (optionId == CURLOPT_HTTPPOST) { std::string invalidArrayMsg = "HTTPPOST option value should be an Array of Objects."; - if (!value->IsArray()) { + if (!value.IsArray()) { Napi::TypeError::New(env, invalidArrayMsg.c_str()).ThrowAsJavaScriptException(); return env.Null(); } @@ -1701,7 +1699,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } } else { - if (!value->IsArray()) { + if (!value.IsArray()) { Napi::TypeError::New(env, "Option value must be an Array.").ThrowAsJavaScriptException(); return env.Null(); } @@ -1722,7 +1720,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } // check if option is string, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlOptionString, opt))) { - if (value->IsNull()) { + if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); } else { if (!value.IsString()) { @@ -1790,9 +1788,9 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // check if option is a function, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlOptionFunction, opt))) { - bool isNull = value->IsNull(); + bool isNull = value.IsNull(); - if (!value->IsFunction() && !isNull) { + if (!value.IsFunction() && !isNull) { Napi::TypeError::New(env, "Option value must be a null or a function.") .ThrowAsJavaScriptException(); return env.Null(); @@ -2021,7 +2019,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // check if option is a blob, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlOptionBlob, opt))) { #if NODE_LIBCURL_VER_GE(7, 71, 0) - if (value->IsNull()) { + if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); } else if (value.IsString()) { std::string utf8StringValue = value.As(); From 3c9e3f8754c6ca9df743be68e37a368530116c61 Mon Sep 17 00:00:00 2001 From: jackkav Date: Sat, 7 Sep 2024 00:12:22 +0200 Subject: [PATCH 10/34] 453 --- src/Easy.cc | 114 ++++++++++++++++++++++------------------------------ 1 file changed, 48 insertions(+), 66 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 823b7d8a8..5ffe5f102 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -279,8 +279,7 @@ void Easy::MonitorSockets() { int events = 0 | UV_READABLE | UV_WRITABLE; if (this->socketPollHandle) { - Napi::Error::New(env, "Already monitoring sockets!").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Already monitoring sockets!"); } #if NODE_LIBCURL_VER_GE(7, 45, 0) @@ -288,9 +287,7 @@ void Easy::MonitorSockets() { retCurl = curl_easy_getinfo(this->ch, CURLINFO_ACTIVESOCKET, &socket); if (socket == CURL_SOCKET_BAD) { - Napi::Error::New(env, "Received invalid socket from the current connection!") - .ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Received invalid socket from the current connection!"); } #else long socket; // NOLINT(runtime/int) @@ -302,8 +299,7 @@ void Easy::MonitorSockets() { errorMsg += std::string("Failed to receive socket. Reason: ") + curl_easy_strerror(retCurl); - Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, errorMsg.c_str()); } this->socketPollHandle = new uv_poll_t; @@ -316,8 +312,7 @@ void Easy::MonitorSockets() { errorMsg += std::string("Failed to poll on connection socket. Reason:") + UV_ERROR_STRING(retUv); - Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, errorMsg.c_str()); } this->socketPollHandle->data = this; @@ -335,8 +330,7 @@ void Easy::UnmonitorSockets() { errorMsg += std::string("Failed to stop polling on socket. Reason: ") + UV_ERROR_STRING(retUv); - Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, errorMsg.c_str()); } uv_close(reinterpret_cast(this->socketPollHandle), Easy::OnSocketClose); @@ -434,9 +428,7 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } return returnValue; } else { @@ -524,9 +516,7 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -590,9 +580,7 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { if (this->isInsideMultiHandle) { this->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } return returnValue; } else { @@ -646,9 +634,7 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { if (this->isInsideMultiHandle) { this->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } return returnValue; } else { @@ -664,7 +650,7 @@ Napi::Value NullValueIfInvalidString(char* str) { Napi::Value ret = env.Null(); if (str != NULL && str[0] != '\0') { - ret = Napi::New(env, str); + ret = Napi::String::New(env, str); } return scope.Escape(ret); @@ -682,11 +668,11 @@ Napi::Object Easy::CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo) { .As(); - v8::Local perm = Napi::New(env, fileInfo->perm); - v8::Local uid = Napi::New(env, fileInfo->uid); - v8::Local gid = Napi::New(env, fileInfo->gid); + v8::Local perm = Napi::Number::New(env, fileInfo->perm); + v8::Local uid = Napi::Number::New(env, fileInfo->uid); + v8::Local gid = Napi::Number::New(env, fileInfo->gid); Napi::Number size = Napi::Number::New(env, static_cast(fileInfo->size)); - v8::Local hardLinks = Napi::New(env, static_cast(fileInfo->hardlinks)); + v8::Local hardLinks = Napi::Number::New(env, static_cast(fileInfo->hardlinks)); Napi::Object strings = Napi::Object::New(env); (strings).Set(Napi::String::New(env, "time"), NullValueIfInvalidString(fileInfo->strings.time)); @@ -715,7 +701,7 @@ Napi::Object Easy::CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts) { auto hasExpire = !!sts->expire[0] && !!strcmp(sts->expire, TIME_IN_THE_FUTURE); - Napi::String host = Napi::New(env, sts->name); + Napi::String host = Napi::Number::New(env, sts->name); Napi::Boolean includeSubDomains = Napi::New(env, !!sts->includeSubDomains); Napi::Value expire = hasExpire ? Napi::New(env, sts->expire).As() : env.Null().As(); @@ -764,9 +750,7 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -806,9 +790,7 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -904,9 +886,7 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -977,7 +957,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { cacheEntryObject = returnValueFromHstsReadCallback; } - if (cacheEntryObject->IsNull()) { + if (cacheEntryObject.IsNull()) { return CURLSTS_DONE; } else { // returning an array from the callback can be used to avoid multiple @@ -1505,6 +1485,7 @@ Napi::Value Easy::IsOpenGetter(const Napi::CallbackInfo& info) { } Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; @@ -2088,6 +2069,7 @@ Napi::Value Easy::GetInfoTmpl(const Easy* obj, int infoId) { } Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; @@ -2248,6 +2230,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { } Napi::Value Easy::Send(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; @@ -2283,6 +2266,7 @@ Napi::Value Easy::Send(const Napi::CallbackInfo& info) { } Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; @@ -2319,19 +2303,18 @@ Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { // exec this handle Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); } if (!obj->SetUrlOpts()) { v8::Local ret = Napi::Number::New(env, static_cast(CURLE_URL_MALFORMAT)); return ret; - return; } SETLOCALE_WRAPPER(CURLcode code = curl_easy_perform(obj->ch);); @@ -2342,13 +2325,13 @@ Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { } Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); } #if NODE_LIBCURL_VER_GE(7, 62, 0) @@ -2365,18 +2348,17 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { } Napi::Value Easy::Pause(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed.") } - if (!info[0].IsUint32()) { - Napi::TypeError::New(env, "Bitmask value must be an integer.").ThrowAsJavaScriptException(); - return env.Null(); + if (!info[0].IsNumber()) { + throw Napi::TypeError::New(env, "Bitmask value must be an integer.") } uint32_t bitmask = info[0].As().Uint32Value(); @@ -2387,13 +2369,13 @@ Napi::Value Easy::Pause(const Napi::CallbackInfo& info) { } Napi::Value Easy::Reset(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle closed.") } curl_easy_reset(obj->ch); @@ -2417,6 +2399,7 @@ Napi::Value Easy::Reset(const Napi::CallbackInfo& info) { } Napi::Value Easy::DupHandle(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); // create a new js object using this one as the argument for the constructor. @@ -2430,26 +2413,25 @@ Napi::Value Easy::DupHandle(const Napi::CallbackInfo& info) { } Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; if (!info.Length()) { - Napi::Error::New(env, "You must specify the callback function.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "You must specify the callback function.") } Napi::Value arg = info[0]; - if (arg->IsNull()) { + if (arg.IsNull()) { obj->cbOnSocketEvent = nullptr; return info.This(); - return; } - if (!arg->IsFunction()) { - Napi::TypeError::New(env, "Invalid callback given.").ThrowAsJavaScriptException(); + if (!arg.IsFunction()) { + Napi::TypeError::New(env, "Invalid callback given.") return env.Null(); } @@ -2461,6 +2443,7 @@ Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { } Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; @@ -2478,6 +2461,7 @@ Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { } Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; @@ -2496,19 +2480,18 @@ Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { Napi::Value Easy::Close(const Napi::CallbackInfo& info) { // check https://github.com/php/php-src/blob/master/ext/curl/interface.c#L3196 + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Easy* obj = this; if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle already closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle already closed.") } if (obj->isInsideMultiHandle) { - Napi::Error::New(env, "Curl handle is inside a Multi instance, you must remove it first.") - .ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is inside a Multi instance, you must remove it first.") + } obj->Dispose(); @@ -2517,20 +2500,19 @@ Napi::Value Easy::Close(const Napi::CallbackInfo& info) { } Napi::Value Easy::StrError(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); Napi::HandleScope scope(env); Napi::Value errCode = info[0]; if (!errCode.IsNumber()) { - Napi::TypeError::New(env, "Invalid errCode passed to Easy.strError.") - .ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, "Invalid errCode passed to Easy.strError.") } const char* errorMsg = curl_easy_strerror(static_cast(errCode.As().Int32Value())); - Napi::String ret = Napi::New(env, errorMsg); + Napi::String ret = Napi::String::New(env, errorMsg); return ret; } From 9b8295de951d67c9f3e24adba37a0a2ab3dc0065 Mon Sep 17 00:00:00 2001 From: jackkav Date: Sat, 7 Sep 2024 00:29:36 +0200 Subject: [PATCH 11/34] 422 --- src/Easy.cc | 98 +++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 5ffe5f102..1bf9a52d2 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -962,9 +962,9 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { } else { // returning an array from the callback can be used to avoid multiple // context switches between v8 and js - if (cacheEntryObject->IsArray()) { + if (cacheEntryObject.IsArray()) { auto cacheArray = cacheEntryObject.As(); - auto cacheArrayLength = cacheArray->Length(); + auto cacheArrayLength = cacheArray.Length(); if (cacheArrayLength == 0) { return CURLSTS_DONE; @@ -982,7 +982,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { // we check for an array here too to avoid passing a child array here. // If that happens, the code would get to this condition again when we // process this cache entry in a future iteration - if (!idxValueChecked.IsObject() || idxValueChecked->IsArray()) { + if (!idxValueChecked.IsObject() || idxValueChecked.IsArray()) { THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) return returnValue; } @@ -1042,7 +1042,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { std::string hostStrValue = hostPropertyValueChecked.As(); // make sure str len is inside the given max length - if (static_cast(hostStrValue.Length()) > sts->namelen) { + if (static_cast(hostStrValue.length()) > sts->namelen) { Napi::Value typeError = Napi::TypeError( "The host property value returned from the HSTSREADFUNCTION callback function was " "invalid. The host string is too long.\n" @@ -1061,7 +1061,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { // make sure expire length is one expected by libcurl // YYYYMMDD HH:MM:SS [null-terminated] size_t currentSize = - static_cast(expirePropertyValueChecked.As()->Length()); + static_cast(expirePropertyValueChecked.As().Length()); size_t expectedSize = sizeof(sts->expire) / sizeof(sts->expire[0]) - 1; if (currentSize != expectedSize) { @@ -1122,8 +1122,8 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde // TODO(jonathan): give the option to receive an array directly? Napi::Object countObj = Napi::Object::New(env); - Napi::Number index = Napi::New(env, static_cast(count->index)); - Napi::Number total = Napi::New(env, static_cast(count->total)); + Napi::Number index = Napi::Number::New(env, static_cast(count->index)); + Napi::Number total = Napi::Number::New(env, static_cast(count->total)); (countObj).Set(Napi::String::New(env, "index"), index); (countObj).Set(Napi::String::New(env, "total"), total); @@ -1210,9 +1210,7 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -1268,9 +1266,7 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { if (obj->isInsideMultiHandle) { obj->callbackError.Reset(returnValueCbTypeError); } else { - Napi::Error::New(env, returnValueCbTypeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, returnValueCbTypeError); } return CURL_TRAILERFUNC_ABORT; @@ -1278,23 +1274,21 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { Napi::Value returnValueCallbackChecked = returnValueCallback; - if (returnValueCallbackChecked->IsFalse()) { + if (returnValueCallbackChecked.IsFalse()) { return CURL_TRAILERFUNC_ABORT; } Napi::Array rows = returnValueCallbackChecked.As(); // [headerStr1, headerStr2] - for (uint32_t i = 0, len = rows->Length(); i < len; ++i) { + for (uint32_t i = 0, len = rows.Length(); i < len; ++i) { // not an array of objects Napi::Value headerStrValue = (rows).Get(i); if (!headerStrValue.IsString()) { if (obj->isInsideMultiHandle) { obj->callbackError.Reset(returnValueCbTypeError); } else { - Napi::Error::New(env, returnValueCbTypeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, returnValueCbTypeError); } return CURL_TRAILERFUNC_ABORT; @@ -1363,9 +1357,7 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError); } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -1461,34 +1453,38 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { } Napi::Value Easy::IdGetter(const Napi::CallbackInfo& info) { - Easy* obj = this; + Napi::Env env = info.Env(); + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - return Napi::New(env, obj->id); + return Napi::Number::New(env, obj->id); } Napi::Value Easy::IsInsideMultiHandleGetter(const Napi::CallbackInfo& info) { - Easy* obj = this; + Napi::Env env = info.Env(); + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - return Napi::New(env, obj->isInsideMultiHandle); + return Napi::Boolean::New(env, obj->isInsideMultiHandle); } Napi::Value Easy::IsMonitoringSocketsGetter(const Napi::CallbackInfo& info) { - Easy* obj = this; + Napi::Env env = info.Env(); + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - return Napi::New(env, obj->isMonitoringSockets); + return Napi::Boolean::New(env, obj->isMonitoringSockets); } Napi::Value Easy::IsOpenGetter(const Napi::CallbackInfo& info) { - Easy* obj = this; + Napi::Env env = info.Env(); + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - return Napi::New(env, obj->isOpen); + return Napi::Boolean::New(env, obj->isOpen); } Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); @@ -1548,7 +1544,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { std::unique_ptr httpPost = std::make_unique(); // [{ key : val }] - for (uint32_t i = 0, len = rows->Length(); i < len; ++i) { + for (uint32_t i = 0, len = rows.Length(); i < len; ++i) { // not an array of objects Napi::Value obj = (rows).Get(i); if (!obj.IsObject()) { @@ -1559,7 +1555,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { Napi::Object postData = obj.As(); const Napi::Array props = Napi::GetPropertyNames(postData); - const uint32_t postDataLength = props->Length(); + const uint32_t postDataLength = props.Length(); bool hasFile = false; bool hasContentType = false; @@ -1628,19 +1624,19 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { return env.Null(); } - std::string fieldName = (postData).Get(Napi::String > ("name".As < Napi::String::New(env))); + std::string fieldName = (postData).Get(("name".As ("file".As < Napi::String::New(env))); + std::string file = (postData).Get(("file".As ("type".As < Napi::String::New(env))); + (postData).Get(("type".As ("filename".As < Napi::String::New(env))); + (postData).Get(("filename".As AddFile(*fieldName, fieldName.Length(), *file, *contentType, *fileName); } else { @@ -1654,7 +1650,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // be set. std::string fieldValue = - (postData).Get(Napi::String > ("contents".As < Napi::String::New(env))); + (postData).Get(("contents".As AddField(*fieldName, fieldName.Length(), *fieldValue, fieldValue.Length()); @@ -1689,7 +1685,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_slist* slist = NULL; Napi::Array array = value.As(); - for (uint32_t i = 0, len = array->Length(); i < len; ++i) { + for (uint32_t i = 0, len = array.Length(); i < len; ++i) { slist = curl_slist_append(slist, (array).Get(i->As().Utf8Value().c_str())); } @@ -2072,7 +2068,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); @@ -2148,7 +2144,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { curr = linkedList; while (curr) { - auto value = arr.Set(arr->GetCreationContext(), arr->Length(), + auto value = arr.Set(arr->GetCreationContext(), arr.Length(), Napi::String::New(env, curr->data)); if (value.IsJust()) { curr = curr->next; @@ -2184,7 +2180,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { curr = linkedList; while (curr) { - auto value = arr.Set(arr->GetCreationContext(), arr->Length(), + auto value = arr.Set(arr->GetCreationContext(), arr.Length(), Napi::String::New(env, curr->data)); if (value.IsJust()) { curr = curr->next; @@ -2233,7 +2229,7 @@ Napi::Value Easy::Send(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); @@ -2269,7 +2265,7 @@ Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); @@ -2306,7 +2302,7 @@ Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { throw Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); @@ -2328,7 +2324,7 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { throw Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); @@ -2351,7 +2347,7 @@ Napi::Value Easy::Pause(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { throw Napi::Error::New(env, "Curl handle is closed.") @@ -2372,7 +2368,7 @@ Napi::Value Easy::Reset(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { throw Napi::Error::New(env, "Curl handle closed.") @@ -2416,7 +2412,7 @@ Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!info.Length()) { throw Napi::Error::New(env, "You must specify the callback function.") @@ -2446,7 +2442,7 @@ Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); Napi::TryCatch tryCatch; @@ -2464,7 +2460,7 @@ Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); Napi::TryCatch tryCatch; @@ -2483,7 +2479,7 @@ Napi::Value Easy::Close(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Easy* obj = this; + Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { throw Napi::Error::New(env, "Curl handle already closed.") From 2dd3e1fbe15be238a712c0c9ef1b86565dfbea03 Mon Sep 17 00:00:00 2001 From: jackkav Date: Sat, 7 Sep 2024 10:56:04 +0200 Subject: [PATCH 12/34] 407 --- src/Easy.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 1bf9a52d2..e71730fea 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -48,6 +48,12 @@ class Easy::ToFree { } }; +void assert(bool condition, const std::string& message = "Assertion failed!") { + if (!condition) { + throw std::runtime_error(message); + } +} + Napi::FunctionReference Easy::constructor; uint32_t Easy::counter = 0; @@ -1509,16 +1515,14 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); } else { - if (!value.IsObject() || !Napi::New(env, Share::constructor)->HasInstance(value)) { - throw Napi::Error::New(env, ( - "Invalid value for the SHARE option. It must be a Share instance."); + if (!value.IsObject() || !Share::constructor.Value().HasInstance(value)) { + throw Napi::Error::New(env, "Invalid value for the SHARE option. It must be a Share instance."); } - Share* share = value.As().Unwrap(); + Share* share = Napi::ObjectWrap::Unwrap(value.As()); if (!share->isOpen) { - Napi::Error::New(env, "Share handle is already closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Share handle is already closed."); } setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, share->sh); @@ -1535,8 +1539,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { std::string invalidArrayMsg = "HTTPPOST option value should be an Array of Objects."; if (!value.IsArray()) { - Napi::TypeError::New(env, invalidArrayMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, invalidArrayMsg.c_str()); } Napi::Array rows = value.As(); @@ -1548,9 +1551,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // not an array of objects Napi::Value obj = (rows).Get(i); if (!obj.IsObject()) { - Napi::TypeError::New(env, invalidArrayMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); - } + throw Napi::TypeError::New(env, invalidArrayMsg.c_str()); Napi::Object postData = obj.As(); @@ -1614,8 +1615,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { std::string errorMsg; errorMsg += std::string("Value for property \"") + optionName + "\" must be a string."; - Napi::TypeError::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, errorMsg.c_str()); } } From b12f618c90c6b8648c5ceb92cc8b2a4b5d7a7a5a Mon Sep 17 00:00:00 2001 From: jackkav Date: Sat, 7 Sep 2024 11:08:25 +0200 Subject: [PATCH 13/34] 354 --- src/Easy.cc | 99 ++++++++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 65 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index e71730fea..18df27727 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -845,9 +845,7 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi if (obj->isInsideMultiHandle) { obj->callbackError.Reset(typeError); } else { - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); - - tryCatch.ReThrow(); + throw Napi::Error::New(env, typeError) } } else { returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); @@ -1425,8 +1423,7 @@ Napi::Object Easy::Initialize(Napi::Env env, Napi::Object exports) { Napi::Value Easy::New(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (!info.IsConstructCall()) { - Napi::Error::New(env, "You must use \"new\" to instantiate this object.") - .ThrowAsJavaScriptException(); + throw Napi::Error::New(env, "You must use \"new\" to instantiate this object."); } Napi::Value jsHandle = info[0]; @@ -1493,8 +1490,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed."); } Napi::Value opt = info[0]; @@ -1606,8 +1602,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { errorMsg += std::string("Invalid property given: \"") + optionName + "\". Valid properties are file, type, contents, name " "and filename."; - Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, errorMsg.c_str()); } // check if value is a string. @@ -1620,8 +1615,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } if (!hasName) { - Napi::Error::New(env, "Missing field \"name\".").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Missing field \"name\"."); } std::string fieldName = (postData).Get(("name".As AddField(*fieldName, fieldName.Length(), *fieldValue, fieldValue.Length()); } else { - Napi::Error::New(env, "Missing field \"contents\".").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Missing field \"contents\"."); } if (curlFormCode != CURL_FORMADD_OK) { std::string errorMsg; errorMsg += std::string("Error while adding field \"") + *fieldName + "\" to post data."; - Napi::Error::New(env, errorMsg.c_str()).ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, errorMsg.c_str()); } } @@ -1677,8 +1669,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else { if (!value.IsArray()) { - Napi::TypeError::New(env, "Option value must be an Array.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, "Option value must be an Array."); } // convert value to curl linked list (curl_slist) @@ -1701,8 +1692,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); } else { if (!value.IsString()) { - Napi::TypeError::New(env, "Option value must be a string.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, "Option value must be a string."); } std::string value = info[1].As(); @@ -1768,9 +1758,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { bool isNull = value.IsNull(); if (!value.IsFunction() && !isNull) { - Napi::TypeError::New(env, "Option value must be a null or a function.") - .ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, "Option value must be a null or a function."); } switch (optionId) { @@ -2017,13 +2005,10 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), &blob); } else { - Napi::TypeError::New(env, "Option value must be a string or Buffer.") - .ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::TypeError::New(env, "Option value must be a string or Buffer."); } #else - Napi::Error::New(env, "Blob options require curl 7.71 or newer.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Blob options require curl 7.71 or newer."); #endif } @@ -2050,7 +2035,7 @@ Napi::Value Easy::GetInfoTmpl(const Easy* obj, int infoId) { if (code != CURLE_OK) { std::string str = std::to_string(static_cast(code)); - Napi::Error::New(env, str.c_str()).ThrowAsJavaScriptException(); + throw Napi::Error::New(env, str.c_str()) } else { // is string @@ -2071,8 +2056,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed."); } Napi::Value infoVal = info[0]; @@ -2164,9 +2148,8 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { if (isValid) { retVal = arr; } else { - Napi::Error::New(env, - "Something went wrong while trying to retrieve info from curl slist") - .ThrowAsJavaScriptException(); + throw Napi::Error::New(env, + "Something went wrong while trying to retrieve info from curl slist"); } } } else { @@ -2196,10 +2179,8 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { if (isValid) { retVal = arr; } else { - Napi::Error::New(env, - "Something went wrong while trying to retrieve info from curl slist") - .ThrowAsJavaScriptException(); - } + throw Napi::Error::New(env, + "Something went wrong while trying to retrieve info from curl slist"); } } } @@ -2232,20 +2213,17 @@ Napi::Value Easy::Send(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed."); } if (info.Length() == 0) { - Napi::Error::New(env, "Missing buffer argument.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Missing buffer argument."); } Napi::Value buf = info[0]; if (!buf.IsObject() || !buf.IsBuffer()) { - Napi::Error::New(env, "Invalid Buffer instance given.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Invalid Buffer instance given."); } const char* bufContent = buf.As>().Data(); @@ -2268,20 +2246,17 @@ Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Curl handle is closed."); } if (info.Length() == 0) { - Napi::Error::New(env, "Missing buffer argument.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Missing buffer argument."); } Napi::Value buf = info[0]; if (!buf.IsObject() || !buf.IsBuffer()) { - Napi::Error::New(env, "Invalid Buffer instance given.").ThrowAsJavaScriptException(); - return env.Null(); + throw Napi::Error::New(env, "Invalid Buffer instance given."); } char* bufContent = buf.As>().Data(); @@ -2305,7 +2280,7 @@ Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + throw Napi::Error::New(env, "Curl handle is closed.") } if (!obj->SetUrlOpts()) { @@ -2327,7 +2302,7 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle is closed.").ThrowAsJavaScriptException(); + throw Napi::Error::New(env, "Curl handle is closed.") } #if NODE_LIBCURL_VER_GE(7, 62, 0) @@ -2444,13 +2419,10 @@ Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - Napi::TryCatch tryCatch; - - obj->MonitorSockets(); - - if (tryCatch.HasCaught()) { - tryCatch.ReThrow(); - return; + try{ + obj->MonitorSockets(); + } catch (const std::exception& e) { + throw Napi::Error::New(env, e.what()); } return info.This(); @@ -2462,13 +2434,10 @@ Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - Napi::TryCatch tryCatch; - - obj->UnmonitorSockets(); - - if (tryCatch.HasCaught()) { - tryCatch.ReThrow(); - return; + try{ + obj->UnmonitorSockets(); + } catch (const std::exception& e) { + throw Napi::Error::New(env, e.what()); } return info.This(); From ef4fe08a8266a8c7685ca2fe18d8747b8b31d118 Mon Sep 17 00:00:00 2001 From: jackkav Date: Sat, 7 Sep 2024 12:19:14 +0200 Subject: [PATCH 14/34] 307 --- src/Easy.cc | 101 +++++++++++++++++++++++---------------------------- src/Easy.h | 6 +-- src/macros.h | 2 +- 3 files changed, 50 insertions(+), 59 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 18df27727..48e5baf5d 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -259,7 +259,7 @@ CURLcode Easy::SslCtxFunction(CURL* curl, void* sslctx, void* userdata) { } // Dispose persistent objects and references stored during the life of this obj. -void Easy::Dispose() { +void Easy::Dispose(Napi::Env env) { // this call should only be done when the handle is still open assert(this->isOpen && "This handle was already closed."); assert(this->ch && "The curl handle ran away."); @@ -269,7 +269,7 @@ void Easy::Dispose() { NODE_LIBCURL_ADJUST_MEM(-MEMORY_PER_HANDLE); if (this->isMonitoringSockets) { - this->UnmonitorSockets(); + this->UnmonitorSockets(env); } this->isOpen = false; @@ -279,7 +279,7 @@ void Easy::Dispose() { --Easy::currentOpenedHandles; } -void Easy::MonitorSockets() { +void Easy::MonitorSockets(Napi::Env env) { int retUv; CURLcode retCurl; int events = 0 | UV_READABLE | UV_WRITABLE; @@ -327,7 +327,7 @@ void Easy::MonitorSockets() { this->isMonitoringSockets = true; } -void Easy::UnmonitorSockets() { +void Easy::UnmonitorSockets(Napi::Env env) { int retUv; retUv = uv_poll_stop(this->socketPollHandle); @@ -1364,7 +1364,7 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.ToLocalChecked().As().Int32Value(); } #if NODE_LIBCURL_VER_GE(7, 68, 0) @@ -1381,43 +1381,35 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o Napi::Object Easy::Initialize(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); - // Easy js "class" function template initialization - Napi::FunctionReference tmpl = Napi::Function::New(env, Easy::New); - tmpl->SetClassName(Napi::String::New(env, "Easy")); - - v8::Local proto = tmpl->PrototypeTemplate(); - - // prototype methods - Napi::SetPrototypeMethod(tmpl, "setOpt", Easy::SetOpt); - Napi::SetPrototypeMethod(tmpl, "getInfo", Easy::GetInfo); - Napi::SetPrototypeMethod(tmpl, "send", Easy::Send); - Napi::SetPrototypeMethod(tmpl, "recv", Easy::Recv); - Napi::SetPrototypeMethod(tmpl, "perform", Easy::Perform); - Napi::SetPrototypeMethod(tmpl, "upkeep", Easy::Upkeep); - Napi::SetPrototypeMethod(tmpl, "pause", Easy::Pause); - Napi::SetPrototypeMethod(tmpl, "reset", Easy::Reset); - Napi::SetPrototypeMethod(tmpl, "dupHandle", Easy::DupHandle); - Napi::SetPrototypeMethod(tmpl, "onSocketEvent", Easy::OnSocketEvent); - Napi::SetPrototypeMethod(tmpl, "monitorSocketEvents", Easy::MonitorSocketEvents); - Napi::SetPrototypeMethod(tmpl, "unmonitorSocketEvents", Easy::UnmonitorSocketEvents); - Napi::SetPrototypeMethod(tmpl, "close", Easy::Close); - - // static methods - Napi::SetMethod(tmpl, "strError", Easy::StrError); - - // Instance accessors - Napi::SetAccessor(proto, Napi::String::New(env, "id"), Easy::IdGetter, 0, Napi::Value(), - v8::DEFAULT, v8::ReadOnly); - Napi::SetAccessor(proto, Napi::String::New(env, "isInsideMultiHandle"), - Easy::IsInsideMultiHandleGetter, 0, Napi::Value(), v8::DEFAULT, v8::ReadOnly); - Napi::SetAccessor(proto, Napi::String::New(env, "isMonitoringSockets"), - Easy::IsMonitoringSocketsGetter, 0, Napi::Value(), v8::DEFAULT, v8::ReadOnly); - Napi::SetAccessor(proto, Napi::String::New(env, "isOpen"), Easy::IsOpenGetter, 0, Napi::Value(), - v8::DEFAULT, v8::ReadOnly); - - Easy::constructor.Reset(tmpl); - - (target).Set(Napi::String::New(env, "Easy"), Napi::GetFunction(tmpl)); + Napi::Function tmpl = DefineClass(env, "Easy", + InstanceMethod("setOpt", &Easy::SetOpt), + InstanceMethod("getInfo", &Easy::GetInfo), + InstanceMethod("send", &Easy::Send), + InstanceMethod("recv", &Easy::Recv), + InstanceMethod("perform", &Easy::Perform), + InstanceMethod("upkeep", &Easy::Upkeep), + InstanceMethod("pause", &Easy::Pause), + InstanceMethod("reset", &Easy::Reset), + InstanceMethod("dupHandle", &Easy::DupHandle), + InstanceMethod("onSocketEvent", &Easy::OnSocketEvent), + InstanceMethod("monitorSocketEvents", &Easy::MonitorSocketEvents), + InstanceMethod("unmonitorSocketEvents", &Easy::UnmonitorSocketEvents), + InstanceMethod("close", &Easy::Close), + + StaticMethod("strError", &Easy::StrError), + + InstanceAccessor("id", &Easy::IdGetter, nullptr), + InstanceAccessor("isInsideMultiHandle", &Easy::IsInsideMultiHandleGetter, nullptr), + InstanceAccessor("isMonitoringSockets", &Easy::IsMonitoringSocketsGetter, nullptr), + InstanceAccessor("isOpen", &Easy::IsOpenGetter, nullptr) + ); + + // Store the class constructor in the persistent reference + Easy::constructor = Napi::Persistent(tmpl); + Easy::constructor.SuppressDestruct(); + + // Set the class on the exports object + exports.Set("Easy", tmpl); } Napi::Value Easy::New(const Napi::CallbackInfo& info) { @@ -1551,7 +1543,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { Napi::Object postData = obj.As(); - const Napi::Array props = Napi::GetPropertyNames(postData); + const Napi::Array props = postData.GetPropertyNames(); const uint32_t postDataLength = props.Length(); bool hasFile = false; @@ -1618,19 +1610,17 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { throw Napi::Error::New(env, "Missing field \"name\"."); } - std::string fieldName = (postData).Get(("name".As (); CURLFORMcode curlFormCode; if (hasFile) { - std::string file = (postData).Get(("file".As (); if (hasContentType) { - std::string contentType = - (postData).Get(("type".As (); if (hasNewFileName) { - std::string fileName = - (postData).Get(("filename".As (); curlFormCode = httpPost->AddFile(*fieldName, fieldName.Length(), *file, *contentType, *fileName); } else { @@ -1643,8 +1633,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else if (hasContent) { // if file is not set, the contents field MUST // be set. - std::string fieldValue = - (postData).Get(("contents".As (); curlFormCode = httpPost->AddField(*fieldName, fieldName.Length(), *fieldValue, fieldValue.Length()); @@ -1677,7 +1666,9 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { Napi::Array array = value.As(); for (uint32_t i = 0, len = array.Length(); i < len; ++i) { - slist = curl_slist_append(slist, (array).Get(i->As().Utf8Value().c_str())); + Napi::String item = array.Get(i).As(); + std::string utf8String = item.Utf8Value(); + slist = curl_slist_append(slist, utf8String.c_str()); } setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), slist); @@ -2420,7 +2411,7 @@ Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); try{ - obj->MonitorSockets(); + obj->MonitorSockets(env); } catch (const std::exception& e) { throw Napi::Error::New(env, e.what()); } @@ -2435,7 +2426,7 @@ Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); try{ - obj->UnmonitorSockets(); + obj->UnmonitorSockets(env); } catch (const std::exception& e) { throw Napi::Error::New(env, e.what()); } @@ -2459,7 +2450,7 @@ Napi::Value Easy::Close(const Napi::CallbackInfo& info) { } - obj->Dispose(); + obj->Dispose(env); return; } diff --git a/src/Easy.h b/src/Easy.h index bddc0deb7..7e2706f60 100644 --- a/src/Easy.h +++ b/src/Easy.h @@ -36,11 +36,11 @@ class Easy : public Napi::ObjectWrap { ~Easy(); // instance methods - void Dispose(); + void Dispose(Napi::Env env); void ResetRequiredHandleOptions(); void CallSocketEvent(int status, int events); - void MonitorSockets(); - void UnmonitorSockets(); + void MonitorSockets(Napi::Env env); + void UnmonitorSockets(Napi::Env env); size_t OnData(char* data, size_t size, size_t nmemb); size_t OnHeader(char* data, size_t size, size_t nmemb); diff --git a/src/macros.h b/src/macros.h index d56958fef..3fd9d8aea 100644 --- a/src/macros.h +++ b/src/macros.h @@ -57,6 +57,6 @@ if (obj->isInsideMultiHandle) { \ obj->callbackError.Reset(typeError); \ } else { \ - Napi::Error::New(env, typeError).ThrowAsJavaScriptException(); \ + throw Napi::Error::New(env, typeError) \ } #endif From 724bcb7e24a702b887771f17fcf2573461aa4d5f Mon Sep 17 00:00:00 2001 From: jackkav Date: Sat, 7 Sep 2024 16:46:15 +0200 Subject: [PATCH 15/34] risky 307 --- src/Easy.cc | 55 ++++++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 48e5baf5d..dcbefcc88 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -197,7 +197,7 @@ bool Easy::operator!=(const Easy& other) const { return !(*this == other); } Easy::~Easy(void) { if (this->isOpen) { - this->Dispose(); + this->Dispose(env); } if (this->url) { @@ -1622,12 +1622,12 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (hasNewFileName) { std::string fileName = postData.Get("filename").As(); curlFormCode = - httpPost->AddFile(*fieldName, fieldName.Length(), *file, *contentType, *fileName); + httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType, *fileName); } else { - curlFormCode = httpPost->AddFile(*fieldName, fieldName.Length(), *file, *contentType); + curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType); } } else { - curlFormCode = httpPost->AddFile(*fieldName, fieldName.Length(), *file); + curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file); } } else if (hasContent) { // if file is not set, the contents field MUST @@ -1636,7 +1636,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { std::string fieldValue = postData.Get("contents").As(); curlFormCode = - httpPost->AddField(*fieldName, fieldName.Length(), *fieldValue, fieldValue.Length()); + httpPost->AddField(*fieldName, fieldName.length(), *fieldValue, fieldValue.length()); } else { throw Napi::Error::New(env, "Missing field \"contents\"."); @@ -1688,9 +1688,9 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { std::string value = info[1].As(); - size_t length = static_cast(value.Length()); + size_t length = static_cast(value.length()); - std::string valueStr = std::string(*value, length); + std::string valueStr = std::string(value, length); // libcurl makes a copy of the strings after version 7.17, CURLOPT_POSTFIELD // is the only exception @@ -1765,8 +1765,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, NULL); } else { - obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, Easy::CbChunkBgn); @@ -1786,8 +1785,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, NULL); } else { - obj->callbacks[CURLOPT_CHUNK_END_FUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_CHUNK_END_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, Easy::CbChunkEnd); @@ -1803,8 +1801,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_DEBUGFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_DEBUGFUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, Easy::CbDebug); @@ -1820,8 +1817,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_DATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_FUNCTION, NULL); } else { - obj->callbacks[CURLOPT_FNMATCH_FUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_FNMATCH_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_FUNCTION, Easy::CbFnMatch); @@ -1835,8 +1831,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_HEADERFUNCTION); } else { - obj->callbacks[CURLOPT_HEADERFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_HEADERFUNCTION] = std::make_unique(Napi::Persistent(value.As())); } break; @@ -1849,8 +1844,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_HSTSREADDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSREADFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_HSTSREADFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_HSTSREADFUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_HSTSREADDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSREADFUNCTION, Easy::CbHstsRead); @@ -1864,8 +1858,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_HSTSWRITEFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_HSTSWRITEFUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEFUNCTION, Easy::CbHstsWrite); @@ -1882,8 +1875,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_PROGRESSDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_PROGRESSFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_PROGRESSFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_PROGRESSFUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_PROGRESSDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_PROGRESSFUNCTION, Easy::CbProgress); @@ -1898,8 +1890,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_READFUNCTION); } else { - obj->callbacks[CURLOPT_READFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_READFUNCTION] = std::make_unique(Napi::Persistent(value.As())); } break; @@ -1911,8 +1902,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_SEEKFUNCTION); } else { - obj->callbacks[CURLOPT_SEEKFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_SEEKFUNCTION] = std::make_unique(Napi::Persistent(value.As())); } break; @@ -1926,8 +1916,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_TRAILERDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_TRAILERFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_TRAILERFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_TRAILERFUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_TRAILERDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_TRAILERFUNCTION, Easy::CbTrailer); @@ -1948,8 +1937,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_XFERINFODATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_XFERINFOFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_XFERINFOFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_XFERINFOFUNCTION] = std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_XFERINFODATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_XFERINFOFUNCTION, Easy::CbXferinfo); @@ -1965,8 +1953,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_WRITEFUNCTION); } else { - obj->callbacks[CURLOPT_WRITEFUNCTION].reset( - new Napi::FunctionReference(value.As())); + obj->callbacks[CURLOPT_WRITEFUNCTION] = std::make_unique(Napi::Persistent(value.As())); } break; @@ -1980,7 +1967,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else if (value.IsString()) { std::string utf8StringValue = value.As(); - size_t length = static_cast(utf8StringValue.Length()); + size_t length = static_cast(utf8StringValue.length()); struct curl_blob blob; blob.data = *utf8StringValue; From 2f286e539db479fcc8dbef5ef1a431ec7c37ca49 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 00:18:13 +0200 Subject: [PATCH 16/34] 320 --- src/Easy.cc | 77 +++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index dcbefcc88..25e5128e3 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -357,7 +357,7 @@ void Easy::CallSocketEvent(int status, int events) { if (this->cbOnSocketEvent == nullptr) { return; } - + Napi::HandleScope scope(env); Napi::Value err = env.Null(); @@ -438,7 +438,7 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) } return returnValue; } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As(); } char* data = buf.As>().Data(); @@ -525,7 +525,7 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } // otherwise we can't seek directly @@ -590,7 +590,7 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { } return returnValue; } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } return returnValue; @@ -644,7 +644,7 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { } return returnValue; } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } return returnValue; @@ -666,7 +666,7 @@ Napi::Object Easy::CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo) { Napi::EscapableHandleScope scope(env); Napi::String fileName = Napi::New(env, fileInfo->filename); - v8::Local fileType = Napi::New(env, fileInfo->filetype); + v8::Local fileType = Napi::Number::New(env, fileInfo->filetype); Napi::Value time = env.Null().As(); if (fileInfo->time != 0) @@ -708,9 +708,9 @@ Napi::Object Easy::CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts) { auto hasExpire = !!sts->expire[0] && !!strcmp(sts->expire, TIME_IN_THE_FUTURE); Napi::String host = Napi::Number::New(env, sts->name); - Napi::Boolean includeSubDomains = Napi::New(env, !!sts->includeSubDomains); + Napi::Boolean includeSubDomains = Napi::Boolean::New(env, !!sts->includeSubDomains); Napi::Value expire = - hasExpire ? Napi::New(env, sts->expire).As() : env.Null().As(); + hasExpire ? Napi::Boolean::New(env, sts->expire).As() : env.Null().As(); Napi::Object obj = Napi::Object::New(env); (obj).Set(Napi::String::New(env, "host"), host); @@ -759,7 +759,7 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } return returnValue; @@ -799,7 +799,7 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } return returnValue; @@ -848,7 +848,7 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi throw Napi::Error::New(env, typeError) } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } return returnValue; @@ -865,7 +865,7 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { assert(it != obj->callbacks.end() && "FNMATCH callback not set."); const int argc = 2; - Napi::Value argv[argc] = {Napi::New(env, pattern), Napi::New(env, string)}; + Napi::Value argv[argc] = {Napi::String::New(env, pattern), Napi::String::New(env, string)}; int32_t returnValue = CURL_FNMATCHFUNC_FAIL; @@ -893,7 +893,7 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } return returnValue; @@ -1217,7 +1217,7 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked(.As().Int32Value()); + returnValue = returnValueCallback.As().Int32Value(); } #if NODE_LIBCURL_VER_GE(7, 68, 0) @@ -1381,28 +1381,27 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o Napi::Object Easy::Initialize(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); - Napi::Function tmpl = DefineClass(env, "Easy", - InstanceMethod("setOpt", &Easy::SetOpt), - InstanceMethod("getInfo", &Easy::GetInfo), - InstanceMethod("send", &Easy::Send), - InstanceMethod("recv", &Easy::Recv), - InstanceMethod("perform", &Easy::Perform), - InstanceMethod("upkeep", &Easy::Upkeep), - InstanceMethod("pause", &Easy::Pause), - InstanceMethod("reset", &Easy::Reset), - InstanceMethod("dupHandle", &Easy::DupHandle), - InstanceMethod("onSocketEvent", &Easy::OnSocketEvent), - InstanceMethod("monitorSocketEvents", &Easy::MonitorSocketEvents), - InstanceMethod("unmonitorSocketEvents", &Easy::UnmonitorSocketEvents), - InstanceMethod("close", &Easy::Close), - + Napi::Function tmpl = DefineClass(env, "Easy", { + InstanceMethod<&Easy::SetOpt>("setOpt"), + InstanceMethod<&Easy::GetInfo>("getInfo"), + InstanceMethod<&Easy::Send>("send"), + InstanceMethod<&Easy::Recv>("recv"), + InstanceMethod<&Easy::Perform>("perform"), + InstanceMethod<&Easy::Upkeep>("upkeep"), + InstanceMethod<&Easy::Pause>("pause"), + InstanceMethod<&Easy::Reset>("reset"), + InstanceMethod<&Easy::DupHandle>("dupHandle"), + InstanceMethod<&Easy::OnSocketEvent>("onSocketEvent"), + InstanceMethod<&Easy::MonitorSocketEvents>("monitorSocketEvents"), + InstanceMethod<&Easy::UnmonitorSocketEvents>("unmonitorSocketEvents"), + InstanceMethod<&Easy::Close>("close"), StaticMethod("strError", &Easy::StrError), InstanceAccessor("id", &Easy::IdGetter, nullptr), InstanceAccessor("isInsideMultiHandle", &Easy::IsInsideMultiHandleGetter, nullptr), InstanceAccessor("isMonitoringSockets", &Easy::IsMonitoringSocketsGetter, nullptr), InstanceAccessor("isOpen", &Easy::IsOpenGetter, nullptr) - ); +}); // Store the class constructor in the persistent reference Easy::constructor = Napi::Persistent(tmpl); @@ -1990,7 +1989,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { #endif } - return setOptRetCode; + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } // traits class to determine if we need to check for null pointer first @@ -2048,8 +2047,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { // Special case for unsupported info if ((infoId = IsInsideCurlConstantStruct(curlInfoNotImplemented, infoVal))) { - throw Napi::Error::New(env, ( - "Unsupported info, probably because it's too complex to implement using javascript or unecessary when using javascript."); + throw Napi::Error::New(env, "Unsupported info, probably because it's too complex to implement using javascript or unecessary when using javascript."); } Napi::TryCatch tryCatch; @@ -2178,7 +2176,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { } Napi::Object ret = Napi::Object::New(env); - (ret).Set(Napi::String::New(env, "code"), Napi::New(env, static_cast(code))); + (ret).Set(Napi::String::New(env, "code"), Napi::Number::New(env, static_cast(code))); (ret).Set(Napi::String::New(env, "data"), retVal); return ret; @@ -2211,8 +2209,8 @@ Napi::Value Easy::Send(const Napi::CallbackInfo& info) { CURLcode curlRet = curl_easy_send(obj->ch, bufContent, bufLength, &n); Napi::Object ret = Napi::Object::New(env); - (ret).Set(Napi::String::New(env, "code"), Napi::New(env, static_cast(curlRet))); - (ret).Set(Napi::String::New(env, "bytesSent"), Napi::New(env, static_cast(n))); + (ret).Set(Napi::String::New(env, "code"), Napi::Number::New(env, static_cast(curlRet))); + (ret).Set(Napi::String::New(env, "bytesSent"), Napi::Number::New(env, static_cast(n))); return ret; } @@ -2244,8 +2242,8 @@ Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { CURLcode curlRet = curl_easy_recv(obj->ch, bufContent, bufLength, &n); Napi::Object ret = Napi::Object::New(env); - (ret).Set(Napi::String::New(env, "code"), Napi::New(env, static_cast(curlRet))); - (ret).Set(Napi::String::New(env, "bytesReceived"), Napi::New(env, static_cast(n))); + (ret).Set(Napi::String::New(env, "code"), Napi::Number::New(env, static_cast(curlRet))); + (ret).Set(Napi::String::New(env, "bytesReceived"), Napi::Number::New(env, static_cast(n))); return ret; } @@ -2287,8 +2285,7 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { CURLcode code = curl_easy_upkeep(obj->ch); #else CURLcode code = CURLE_FUNCTION_NOT_FOUND; - throw Napi::Error::New(env, ( - "The addon was built against a libcurl version that does not support upkeep. It requires libcurl >= 7.62"); + throw Napi::Error::New(env, "The addon was built against a libcurl version that does not support upkeep. It requires libcurl >= 7.62"); #endif v8::Local ret = Napi::Number::New(env, static_cast(code)); From 053ab72970c52a7bfcfe0374e4d72ae892848b80 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 00:44:41 +0200 Subject: [PATCH 17/34] 300 --- src/Easy.cc | 53 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 25e5128e3..7fd89be29 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -560,11 +560,11 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { int32_t returnValue = -1; const int argc = 3; - Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); - v8::Local sizeArg = Napi::Number::New(env, static_cast(size)); - v8::Local nmembArg = Napi::Number::New(env, static_cast(nmemb)); + Napi::Buffer buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); + Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); + Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); - Napi::Value argv[argc] = {buf, sizeArg, nmembArg}; + std::vector argv = { buf, sizeArg, nmembArg }; Napi::TryCatch tryCatch; Napi::AsyncResource asyncResource("Easy::OnData"); @@ -614,11 +614,12 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { int32_t returnValue = -1; const int argc = 3; - Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); - v8::Local sizeArg = Napi::Number::New(env, static_cast(size)); - v8::Local nmembArg = Napi::Number::New(env, static_cast(nmemb)); + Napi::Buffer buf = Napi::Buffer::Copy(env, data, static_cast(dataLength)); + Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); + Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); + + std::vector argv = { buf, sizeArg, nmembArg }; - Napi::Value argv[argc] = {buf, sizeArg, nmembArg}; Napi::TryCatch tryCatch; Napi::AsyncResource asyncResource("Easy::OnHeader"); @@ -663,22 +664,21 @@ Napi::Value NullValueIfInvalidString(char* str) { } Napi::Object Easy::CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo) { + Napi::Env env = Napi::Env(); Napi::EscapableHandleScope scope(env); - Napi::String fileName = Napi::New(env, fileInfo->filename); - v8::Local fileType = Napi::Number::New(env, fileInfo->filetype); - Napi::Value time = env.Null().As(); + Napi::String fileName = Napi::String:::New(env, fileInfo->filename); + Napi::Number fileType = Napi::Number::New(env, fileInfo->filetype); + Napi::Value time = env.Null(); if (fileInfo->time != 0) - time = Napi::Date::New(env, static_cast(fileInfo->time) * 1000) - - .As(); + time = Napi::Date::New(env, static_cast(fileInfo->time) * 1000).As(); - v8::Local perm = Napi::Number::New(env, fileInfo->perm); - v8::Local uid = Napi::Number::New(env, fileInfo->uid); - v8::Local gid = Napi::Number::New(env, fileInfo->gid); + Napi::Number perm = Napi::Number::New(env, fileInfo->perm); + Napi::Number uid = Napi::Number::New(env, fileInfo->uid); + Napi::Number gid = Napi::Number::New(env, fileInfo->gid); Napi::Number size = Napi::Number::New(env, static_cast(fileInfo->size)); - v8::Local hardLinks = Napi::Number::New(env, static_cast(fileInfo->hardlinks)); + Napi::Number hardLinks = Napi::Number::New(env, static_cast(fileInfo->hardlinks)); Napi::Object strings = Napi::Object::New(env); (strings).Set(Napi::String::New(env, "time"), NullValueIfInvalidString(fileInfo->strings.time)); @@ -709,8 +709,8 @@ Napi::Object Easy::CreateV8ObjectFromCurlHstsEntry(struct curl_hstsentry* sts) { Napi::String host = Napi::Number::New(env, sts->name); Napi::Boolean includeSubDomains = Napi::Boolean::New(env, !!sts->includeSubDomains); - Napi::Value expire = - hasExpire ? Napi::Boolean::New(env, sts->expire).As() : env.Null().As(); + Napi::String expire = + hasExpire ? Napi::String::New(env, sts->expire) : Napi::String::New(env.Null()); Napi::Object obj = Napi::Object::New(env); (obj).Set(Napi::String::New(env, "host"), host); @@ -816,9 +816,9 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi assert(it != obj->callbacks.end() && "DEBUG callback not set."); const int argc = 2; - Napi::Object buf = Napi::Buffer::Copy(env, data, static_cast(size)); + Napi::Buffer buf = Napi::Buffer::Copy(env, data, static_cast(size)); Napi::Value argv[argc] = { - Napi::Number::New(env, type), + Napi::Number::New(env, type), // Assuming 'type' is a number buf, }; @@ -927,7 +927,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { if (obj->hstsReadCache.size() > 0) { auto persistentValue = obj->hstsReadCache.back(); - cacheEntryObject = Napi::New(env, obj->hstsReadCache.back()); + cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); // reset the persistent handler so we do not leak memory persistentValue.Reset(); @@ -1001,7 +1001,7 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { } auto persistentValue = obj->hstsReadCache.back(); - cacheEntryObject = Napi::New(env, obj->hstsReadCache.back()); + cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); persistentValue.Reset(); obj->hstsReadCache.pop_back(); @@ -1423,7 +1423,7 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { // Copy constructor, used when duplicating handles. if (!jsHandle.IsUndefined()) { if (!jsHandle.IsExternal() && - (!jsHandle.IsObject() || !Napi::New(env, Easy::constructor)->HasInstance(jsHandle))) { + (!jsHandle.IsObject() || !Napi::Function::New(env, Easy::constructor)->HasInstance(jsHandle))) { throw Napi::Error::New(env, "Argument must be an instance of an Easy handle."); } @@ -1432,7 +1432,7 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { CURL* curlEasyHandle = reinterpret_cast(info[0].As()->Value()); obj = new Easy(curlEasyHandle); } else { - Easy* orig = info[0].To().Unwrap(); + Easy* orig = info[0].As().Unwrap(); obj = new Easy(orig); } @@ -1441,7 +1441,6 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { } if (obj) { - obj->Wrap(info.This()); return info.This(); } } From 60c4e7685719bc963033a5c7678077a98b856c30 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 00:56:54 +0200 Subject: [PATCH 18/34] 290 --- src/Easy.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 7fd89be29..85c1c3a84 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -404,15 +404,15 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) if (it != obj->callbacks.end()) { Napi::HandleScope scope(env); - Napi::Object buf = Napi::Buffer::New(env, static_cast(n)); - v8::Local sizeArg = Napi::Number::New(env, static_cast(size)); - v8::Local nmembArg = Napi::Number::New(env, static_cast(nmemb)); - const int argc = 3; - Napi::Value argv[argc] = { - buf, - sizeArg, - nmembArg, - }; + Napi::Buffer buf = Napi::Buffer::New(env, static_cast(n)); + Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); + Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); + const int argc = 3; + Napi::Value argv[argc] = { + buf, + sizeArg, + nmembArg, + }; Napi::TryCatch tryCatch; Napi::AsyncResource asyncResource("Easy::ReadFunction"); @@ -494,8 +494,8 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { if (it != obj->callbacks.end()) { Napi::HandleScope scope(env); - v8::Local offsetArg = Napi::Number::New(env, static_cast(offset)); - v8::Local originArg = Napi::Number::New(env, static_cast(origin)); + Napi::Number offsetArg = Napi::Number::New(env, static_cast(offset)); + Napi::Number originArg = Napi::Number::New(env, static_cast(origin)); const int argc = 2; Napi::Value argv[argc] = { offsetArg, @@ -1299,7 +1299,7 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { } *headerList = - curl_slist_append(*headerList, headerStrValue->As().Utf8Value().c_str()); + curl_slist_append(*headerList, headerStrValue.As().Utf8Value().c_str()); } return CURL_TRAILERFUNC_OK; @@ -1364,7 +1364,7 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.ToLocalChecked().As().Int32Value(); + returnValue = returnValueCallback.Int32Value().As(); } #if NODE_LIBCURL_VER_GE(7, 68, 0) @@ -1432,7 +1432,7 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { CURL* curlEasyHandle = reinterpret_cast(info[0].As()->Value()); obj = new Easy(curlEasyHandle); } else { - Easy* orig = info[0].As().Unwrap(); + Easy* orig = Napi::ObjectWrap::Unwrap(info.This().As()); obj = new Easy(orig); } From 3582a3b35172935640be75fa8f4aff6a527b67c2 Mon Sep 17 00:00:00 2001 From: Filipe Freire Date: Tue, 10 Sep 2024 11:01:30 +0100 Subject: [PATCH 19/34] 279? --- src/Easy.cc | 43 ++++--------------------------------------- 1 file changed, 4 insertions(+), 39 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 85c1c3a84..100bf049b 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -2094,8 +2094,6 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { if (code == CURLE_OK) { Napi::Array arr = Napi::Array::New(env); - bool isValid = true; - for (int i = 0; i < ci->num_of_certs; i++) { linkedList = ci->certinfo[i]; @@ -2103,60 +2101,27 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { curr = linkedList; while (curr) { - auto value = arr.Set(arr->GetCreationContext(), arr.Length(), - Napi::String::New(env, curr->data)); - if (value.IsJust()) { - curr = curr->next; - } else { - curr = NULL; - isValid = false; - } - } - - // stop the loop if we found an invalid value - if (!isValid) { - break; + arr.Set(arr.Length(), Napi::String::New(env, curr->data)); + curr = curr->next; } } } - - if (isValid) { - retVal = arr; - } else { - throw Napi::Error::New(env, - "Something went wrong while trying to retrieve info from curl slist"); - } } } else { code = curl_easy_getinfo(obj->ch, curlInfo, &linkedList); if (code == CURLE_OK) { Napi::Array arr = Napi::Array::New(env); - bool isValid = true; - if (linkedList) { curr = linkedList; while (curr) { - auto value = arr.Set(arr->GetCreationContext(), arr.Length(), - Napi::String::New(env, curr->data)); - if (value.IsJust()) { - curr = curr->next; - } else { - curr = NULL; - isValid = false; - } + arr.Set(arr.Length(), Napi::String::New(env, curr->data)); + curr = curr->next; } curl_slist_free_all(linkedList); } - - if (isValid) { - retVal = arr; - } else { - throw Napi::Error::New(env, - "Something went wrong while trying to retrieve info from curl slist"); - } } } From 4aaa796e48a60f7be9db2c79e090b8cd5dc6753e Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 13:44:15 +0200 Subject: [PATCH 20/34] remove some quirk macros --- src/Easy.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 100bf049b..c71d7b057 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1220,11 +1220,7 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal returnValue = returnValueCallback.As().Int32Value(); } -#if NODE_LIBCURL_VER_GE(7, 68, 0) if (returnValue && returnValue != CURL_PROGRESSFUNC_CONTINUE) { -#else - if (returnValue) { -#endif obj->isCbProgressAlreadyAborted = true; } @@ -1367,11 +1363,7 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o returnValue = returnValueCallback.Int32Value().As(); } -#if NODE_LIBCURL_VER_GE(7, 68, 0) if (returnValue && returnValue != CURL_PROGRESSFUNC_CONTINUE) { -#else - if (returnValue) { -#endif obj->isCbProgressAlreadyAborted = true; } From 56c40465afc828ff5d5c326684a27403004f23f8 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 13:45:09 +0200 Subject: [PATCH 21/34] and another --- src/Easy.cc | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index c71d7b057..c56e60ac3 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1488,8 +1488,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if ((optionId = IsInsideCurlConstantStruct(curlOptionNotImplemented, opt))) { throw Napi::Error::New(env, "Unsupported option, probably because it's too complex to implement using javascript or unecessary when using javascript (like the _DATA options)."); } else if ((optionId = IsInsideCurlConstantStruct(curlOptionSpecific, opt))) { - switch (optionId) { - case CURLOPT_SHARE: + if (optionId == CURLOPT_SHARE) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); } else { @@ -1505,7 +1504,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, share->sh); } - break; } // linked list options } else if ((optionId = IsInsideCurlConstantStruct(curlOptionLinkedList, opt))) { @@ -1826,7 +1824,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { break; -#if NODE_LIBCURL_VER_GE(7, 74, 0) case CURLOPT_HSTSREADFUNCTION: if (isNull) { obj->callbacks.erase(CURLOPT_HSTSREADFUNCTION); @@ -1855,7 +1852,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } break; -#endif case CURLOPT_PROGRESSFUNCTION: @@ -1897,7 +1893,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { break; -#if NODE_LIBCURL_VER_GE(7, 64, 0) case CURLOPT_TRAILERFUNCTION: if (isNull) { @@ -1913,9 +1908,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } break; -#endif -#if NODE_LIBCURL_VER_GE(7, 32, 0) /* xferinfo was introduced in 7.32.0. New libcurls will prefer the new callback and instead use that one even if both callbacks are set. */ @@ -1934,7 +1927,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } break; -#endif case CURLOPT_WRITEFUNCTION: @@ -1951,7 +1943,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // check if option is a blob, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlOptionBlob, opt))) { -#if NODE_LIBCURL_VER_GE(7, 71, 0) if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); } else if (value.IsString()) { @@ -1975,9 +1966,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else { throw Napi::TypeError::New(env, "Option value must be a string or Buffer."); } -#else - throw Napi::Error::New(env, "Blob options require curl 7.71 or newer."); -#endif + } return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); @@ -2057,13 +2046,8 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { retVal = Easy::GetInfoTmpl(obj, infoId); // NOLINT(runtime/int) // ACTIVESOCKET and alike } else if ((infoId = IsInsideCurlConstantStruct(curlInfoSocket, infoVal))) { -#if NODE_LIBCURL_VER_GE(7, 45, 0) curl_socket_t socket; -#else - // this should never really used tho, as it's only possible to have - // an curlInfoSocket value with libcurl >= 7.45.0 - long socket; // NOLINT(runtime/int) -#endif + code = curl_easy_getinfo(obj->ch, static_cast(infoId), &socket); if (code == CURLE_OK) { From 2be3f1324225423e197af5f5a1ea8ffeac7f291c Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 13:57:41 +0200 Subject: [PATCH 22/34] fix missing bracket --- src/Easy.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index c56e60ac3..70df9a154 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -2098,6 +2098,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { curl_slist_free_all(linkedList); } + } } } @@ -2221,12 +2222,7 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { throw Napi::Error::New(env, "Curl handle is closed.") } -#if NODE_LIBCURL_VER_GE(7, 62, 0) CURLcode code = curl_easy_upkeep(obj->ch); -#else - CURLcode code = CURLE_FUNCTION_NOT_FOUND; - throw Napi::Error::New(env, "The addon was built against a libcurl version that does not support upkeep. It requires libcurl >= 7.62"); -#endif v8::Local ret = Napi::Number::New(env, static_cast(code)); From 22c38854773e082d56d8e80f87a67dc322c61795 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 14:00:13 +0200 Subject: [PATCH 23/34] 285 --- src/Easy.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 70df9a154..4ee40c707 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -2197,7 +2197,7 @@ Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle is closed.") + throw Napi::Error::New(env, "Curl handle is closed."); } if (!obj->SetUrlOpts()) { @@ -2219,7 +2219,7 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle is closed.") + throw Napi::Error::New(env, "Curl handle is closed."); } CURLcode code = curl_easy_upkeep(obj->ch); @@ -2236,11 +2236,11 @@ Napi::Value Easy::Pause(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle is closed.") + throw Napi::Error::New(env, "Curl handle is closed."); } if (!info[0].IsNumber()) { - throw Napi::TypeError::New(env, "Bitmask value must be an integer.") + throw Napi::TypeError::New(env, "Bitmask value must be an integer."); } uint32_t bitmask = info[0].As().Uint32Value(); @@ -2257,7 +2257,7 @@ Napi::Value Easy::Reset(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle closed.") + throw Napi::Error::New(env, "Curl handle closed."); } curl_easy_reset(obj->ch); @@ -2301,7 +2301,7 @@ Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!info.Length()) { - throw Napi::Error::New(env, "You must specify the callback function.") + throw Napi::Error::New(env, "You must specify the callback function."); } Napi::Value arg = info[0]; @@ -2313,7 +2313,7 @@ Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { } if (!arg.IsFunction()) { - Napi::TypeError::New(env, "Invalid callback given.") + Napi::TypeError::New(env, "Invalid callback given."); return env.Null(); } @@ -2362,17 +2362,17 @@ Napi::Value Easy::Close(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); if (!obj->isOpen) { - throw Napi::Error::New(env, "Curl handle already closed.") + throw Napi::Error::New(env, "Curl handle already closed."); } if (obj->isInsideMultiHandle) { - throw Napi::Error::New(env, "Curl handle is inside a Multi instance, you must remove it first.") + throw Napi::Error::New(env, "Curl handle is inside a Multi instance, you must remove it first."); } obj->Dispose(env); - return; + return env.Undefined(); } Napi::Value Easy::StrError(const Napi::CallbackInfo& info) { @@ -2382,7 +2382,7 @@ Napi::Value Easy::StrError(const Napi::CallbackInfo& info) { Napi::Value errCode = info[0]; if (!errCode.IsNumber()) { - throw Napi::TypeError::New(env, "Invalid errCode passed to Easy.strError.") + throw Napi::TypeError::New(env, "Invalid errCode passed to Easy.strError."); } const char* errorMsg = From 016c94889a5e0887dbb1e91cd09968c9b0836ebc Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 14:08:19 +0200 Subject: [PATCH 24/34] 276 --- src/Easy.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 4ee40c707..906654d7d 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -2103,7 +2103,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { } if (tryCatch.HasCaught()) { - std::string msg = tryCatch.Message(.As()->Get()); + std::string msg = tryCatch.Message().As()->Get()); std::string errCode = std::string(*msg); // based on this interesting answer @@ -2201,13 +2201,13 @@ Napi::Value Easy::Perform(const Napi::CallbackInfo& info) { } if (!obj->SetUrlOpts()) { - v8::Local ret = Napi::Number::New(env, static_cast(CURLE_URL_MALFORMAT)); - return ret; + Napi::Number ret = Napi::Number::New(env, static_cast(CURLE_URL_MALFORMAT)); + return Napi::Number::New(env, static_cast(CURLE_URL_MALFORMAT)); } SETLOCALE_WRAPPER(CURLcode code = curl_easy_perform(obj->ch);); - v8::Local ret = Napi::Number::New(env, static_cast(code)); + Napi::Number ret = Napi::Number::New(env, static_cast(code)); return ret; } @@ -2224,7 +2224,7 @@ Napi::Value Easy::Upkeep(const Napi::CallbackInfo& info) { CURLcode code = curl_easy_upkeep(obj->ch); - v8::Local ret = Napi::Number::New(env, static_cast(code)); + Napi::Number ret = Napi::Number::New(env, static_cast(code)); return ret; } @@ -2247,7 +2247,7 @@ Napi::Value Easy::Pause(const Napi::CallbackInfo& info) { CURLcode code = curl_easy_pause(obj->ch, static_cast(bitmask)); - return static_cast(code); + return Napi::Number::New(env, static_cast(code)); } Napi::Value Easy::Reset(const Napi::CallbackInfo& info) { @@ -2318,8 +2318,7 @@ Napi::Value Easy::OnSocketEvent(const Napi::CallbackInfo& info) { } Napi::Function callback = arg.As(); - - obj->cbOnSocketEvent.reset(new Napi::FunctionReference(callback)); + obj->cbOnSocketEvent = std::make_unique(Napi::Persistent(callback)); return info.This(); } From ba29199e99eb9e2f498dec43c6eefec50fdbd420 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 14:16:10 +0200 Subject: [PATCH 25/34] 269 --- src/Easy.cc | 121 ++++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 906654d7d..d344edd78 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1487,7 +1487,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if ((optionId = IsInsideCurlConstantStruct(curlOptionNotImplemented, opt))) { throw Napi::Error::New(env, "Unsupported option, probably because it's too complex to implement using javascript or unecessary when using javascript (like the _DATA options)."); - } else if ((optionId = IsInsideCurlConstantStruct(curlOptionSpecific, opt))) { + } + if ((optionId = IsInsideCurlConstantStruct(curlOptionSpecific, opt))) { if (optionId == CURLOPT_SHARE) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); @@ -2030,49 +2031,64 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { throw Napi::Error::New(env, "Unsupported info, probably because it's too complex to implement using javascript or unecessary when using javascript."); } - Napi::TryCatch tryCatch; + try{ - // String - if ((infoId = IsInsideCurlConstantStruct(curlInfoString, infoVal))) { - retVal = Easy::GetInfoTmpl(obj, infoId); - // curl_off_t - } else if ((infoId = IsInsideCurlConstantStruct(curlInfoOffT, infoVal))) { - retVal = Easy::GetInfoTmpl(obj, infoId); - // Double - } else if ((infoId = IsInsideCurlConstantStruct(curlInfoDouble, infoVal))) { - retVal = Easy::GetInfoTmpl(obj, infoId); - // Integer - } else if ((infoId = IsInsideCurlConstantStruct(curlInfoInteger, infoVal))) { - retVal = Easy::GetInfoTmpl(obj, infoId); // NOLINT(runtime/int) - // ACTIVESOCKET and alike - } else if ((infoId = IsInsideCurlConstantStruct(curlInfoSocket, infoVal))) { - curl_socket_t socket; - - code = curl_easy_getinfo(obj->ch, static_cast(infoId), &socket); - - if (code == CURLE_OK) { - // curl_socket_t is of type SOCKET on Windows, - // casting it to int32_t can be dangerous, only if Microsoft ever decides - // to change the underlying architecture behind it. - // https://stackoverflow.com/a/26496808/710693 - retVal = Napi::Number::New(env, static_cast(socket)); - } + // String + if ((infoId = IsInsideCurlConstantStruct(curlInfoString, infoVal))) { + retVal = Easy::GetInfoTmpl(obj, infoId); + // curl_off_t + } else if ((infoId = IsInsideCurlConstantStruct(curlInfoOffT, infoVal))) { + retVal = Easy::GetInfoTmpl(obj, infoId); + // Double + } else if ((infoId = IsInsideCurlConstantStruct(curlInfoDouble, infoVal))) { + retVal = Easy::GetInfoTmpl(obj, infoId); + // Integer + } else if ((infoId = IsInsideCurlConstantStruct(curlInfoInteger, infoVal))) { + retVal = Easy::GetInfoTmpl(obj, infoId); // NOLINT(runtime/int) + // ACTIVESOCKET and alike + } else if ((infoId = IsInsideCurlConstantStruct(curlInfoSocket, infoVal))) { + curl_socket_t socket; + + code = curl_easy_getinfo(obj->ch, static_cast(infoId), &socket); - // Linked list - } else if ((infoId = IsInsideCurlConstantStruct(curlInfoLinkedList, infoVal))) { - curl_slist* linkedList; - curl_slist* curr; + if (code == CURLE_OK) { + // curl_socket_t is of type SOCKET on Windows, + // casting it to int32_t can be dangerous, only if Microsoft ever decides + // to change the underlying architecture behind it. + // https://stackoverflow.com/a/26496808/710693 + retVal = Napi::Number::New(env, static_cast(socket)); + } - curlInfo = static_cast(infoId); - if (curlInfo == CURLINFO_CERTINFO) { - curl_certinfo* ci = NULL; - code = curl_easy_getinfo(obj->ch, curlInfo, &ci); + // Linked list + } else if ((infoId = IsInsideCurlConstantStruct(curlInfoLinkedList, infoVal))) { + curl_slist* linkedList; + curl_slist* curr; - if (code == CURLE_OK) { - Napi::Array arr = Napi::Array::New(env); - for (int i = 0; i < ci->num_of_certs; i++) { - linkedList = ci->certinfo[i]; + curlInfo = static_cast(infoId); + if (curlInfo == CURLINFO_CERTINFO) { + curl_certinfo* ci = NULL; + code = curl_easy_getinfo(obj->ch, curlInfo, &ci); + + if (code == CURLE_OK) { + Napi::Array arr = Napi::Array::New(env); + for (int i = 0; i < ci->num_of_certs; i++) { + linkedList = ci->certinfo[i]; + + if (linkedList) { + curr = linkedList; + + while (curr) { + arr.Set(arr.Length(), Napi::String::New(env, curr->data)); + curr = curr->next; + } + } + } + } + } else { + code = curl_easy_getinfo(obj->ch, curlInfo, &linkedList); + if (code == CURLE_OK) { + Napi::Array arr = Napi::Array::New(env); if (linkedList) { curr = linkedList; @@ -2080,30 +2096,15 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { arr.Set(arr.Length(), Napi::String::New(env, curr->data)); curr = curr->next; } - } - } - } - } else { - code = curl_easy_getinfo(obj->ch, curlInfo, &linkedList); - - if (code == CURLE_OK) { - Napi::Array arr = Napi::Array::New(env); - if (linkedList) { - curr = linkedList; - while (curr) { - arr.Set(arr.Length(), Napi::String::New(env, curr->data)); - curr = curr->next; + curl_slist_free_all(linkedList); } - - curl_slist_free_all(linkedList); } } } - } - if (tryCatch.HasCaught()) { - std::string msg = tryCatch.Message().As()->Get()); + } catch (const std::exception& e) { + std::string msg = e.what(); std::string errCode = std::string(*msg); // based on this interesting answer @@ -2113,7 +2114,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { errCode.end()); // 43 is CURLE_BAD_FUNCTION_ARGUMENT - code = static_cast(std::stoi(errCode.Length() > 0 ? errCode : "43")); + code = static_cast(std::stoi(errCode.length() > 0 ? errCode : "43")); } Napi::Object ret = Napi::Object::New(env); @@ -2287,9 +2288,9 @@ Napi::Value Easy::DupHandle(const Napi::CallbackInfo& info) { // create a new js object using this one as the argument for the constructor. const int argc = 1; Napi::Value argv[argc] = {info.This()}; - Napi::Function cons = Napi::GetFunction(Napi::New(env, Easy::constructor)); + Napi::Function cons = Easy::constructor.Value(); - Napi::Object newInstance = Napi::NewInstance(cons, argc, argv); + Napi::Object newInstance = cons.New(argc, argv); return newInstance; } From b45642c6d0814eff82edfee40b5c8960b3ece6d1 Mon Sep 17 00:00:00 2001 From: jackkav Date: Tue, 10 Sep 2024 14:37:49 +0200 Subject: [PATCH 26/34] early returns --- src/Easy.cc | 99 +++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index d344edd78..8ffa62005 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1492,7 +1492,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (optionId == CURLOPT_SHARE) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); - } else { + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); + } if (!value.IsObject() || !Share::constructor.Value().HasInstance(value)) { throw Napi::Error::New(env, "Invalid value for the SHARE option. It must be a Share instance."); } @@ -1504,15 +1505,17 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, share->sh); - } + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } // linked list options - } else if ((optionId = IsInsideCurlConstantStruct(curlOptionLinkedList, opt))) { + } + if ((optionId = IsInsideCurlConstantStruct(curlOptionLinkedList, opt))) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); - + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); // HTTPPOST is a special case, since it's an array of objects. - } else if (optionId == CURLOPT_HTTPPOST) { + } + if (optionId == CURLOPT_HTTPPOST) { std::string invalidArrayMsg = "HTTPPOST option value should be an Array of Objects."; if (!value.IsArray()) { @@ -1670,38 +1673,39 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else if ((optionId = IsInsideCurlConstantStruct(curlOptionString, opt))) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); - } else { - if (!value.IsString()) { - throw Napi::TypeError::New(env, "Option value must be a string."); - } - - std::string value = info[1].As(); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); + } + if (!value.IsString()) { + throw Napi::TypeError::New(env, "Option value must be a string."); + } - size_t length = static_cast(value.length()); + std::string value = info[1].As(); - std::string valueStr = std::string(value, length); + size_t length = static_cast(value.length()); - // libcurl makes a copy of the strings after version 7.17, CURLOPT_POSTFIELD - // is the only exception - if (static_cast(optionId) == CURLOPT_POSTFIELDS) { - std::vector valueChar = std::vector(valueStr.begin(), valueStr.end()); - valueChar.push_back(0); + std::string valueStr = std::string(value, length); - setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), &valueChar[0]); + // libcurl makes a copy of the strings after version 7.17, CURLOPT_POSTFIELD + // is the only exception + if (static_cast(optionId) == CURLOPT_POSTFIELDS) { + std::vector valueChar = std::vector(valueStr.begin(), valueStr.end()); + valueChar.push_back(0); - if (setOptRetCode == CURLE_OK) { - obj->toFree->str.push_back(std::move(valueChar)); - } + setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), &valueChar[0]); - } else if (static_cast(optionId) == CURLOPT_URL) { - obj->urlData = std::vector(valueStr.begin(), valueStr.end()); - obj->urlData.push_back(0); - setOptRetCode = CURLE_OK; - } else { - setOptRetCode = - curl_easy_setopt(obj->ch, static_cast(optionId), valueStr.c_str()); + if (setOptRetCode == CURLE_OK) { + obj->toFree->str.push_back(std::move(valueChar)); } + + } else if (static_cast(optionId) == CURLOPT_URL) { + obj->urlData = std::vector(valueStr.begin(), valueStr.end()); + obj->urlData.push_back(0); + setOptRetCode = CURLE_OK; + } else { + setOptRetCode = + curl_easy_setopt(obj->ch, static_cast(optionId), valueStr.c_str()); } + // check if option is an integer, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlOptionInteger, opt))) { @@ -1753,12 +1757,13 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { obj->callbacks.erase(CURLOPT_CHUNK_BGN_FUNCTION); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, NULL); - } else { - obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); - - curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); - setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, Easy::CbChunkBgn); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } + obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); + + curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); + setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, Easy::CbChunkBgn); + break; @@ -1773,12 +1778,13 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { obj->callbacks.erase(CURLOPT_CHUNK_END_FUNCTION); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, NULL); - } else { - obj->callbacks[CURLOPT_CHUNK_END_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); - - curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); - setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, Easy::CbChunkEnd); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } + obj->callbacks[CURLOPT_CHUNK_END_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); + + curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); + setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, Easy::CbChunkEnd); + break; @@ -1789,12 +1795,13 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, NULL); - } else { - obj->callbacks[CURLOPT_DEBUGFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); + } + obj->callbacks[CURLOPT_DEBUGFUNCTION] = std::make_unique(Napi::Persistent(value.As())); - curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, obj); - setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, Easy::CbDebug); - } + curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, obj); + setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, Easy::CbDebug); + break; @@ -1946,7 +1953,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else if ((optionId = IsInsideCurlConstantStruct(curlOptionBlob, opt))) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); - } else if (value.IsString()) { + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); + }else if (value.IsString()) { std::string utf8StringValue = value.As(); size_t length = static_cast(utf8StringValue.length()); @@ -1957,6 +1965,7 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { blob.flags = CURL_BLOB_COPY; setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), &blob); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } else if (value.IsBuffer()) { struct curl_blob blob; blob.data = value.As>().Data(); From e53f4d84c3c7bec0dbe4dcd0a323c6f4b0ab7e73 Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 16:46:21 +0200 Subject: [PATCH 27/34] early return --- src/Easy.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Easy.cc b/src/Easy.cc index 8ffa62005..eabce9290 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -1954,7 +1954,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (value.IsNull()) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), NULL); return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); - }else if (value.IsString()) { + } + if (value.IsString()) { std::string utf8StringValue = value.As(); size_t length = static_cast(utf8StringValue.length()); From 5809fa248d5d1bd5f3f264c4dc425962e75c644b Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 16:56:37 +0200 Subject: [PATCH 28/34] 268 --- src/Easy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Easy.cc b/src/Easy.cc index eabce9290..1be3838ef 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -667,7 +667,7 @@ Napi::Object Easy::CreateV8ObjectFromCurlFileInfo(curl_fileinfo* fileInfo) { Napi::Env env = Napi::Env(); Napi::EscapableHandleScope scope(env); - Napi::String fileName = Napi::String:::New(env, fileInfo->filename); + Napi::String fileName = Napi::String::New(env, fileInfo->filename); Napi::Number fileType = Napi::Number::New(env, fileInfo->filetype); Napi::Value time = env.Null(); From 1ccd37e9b854cc07b02da0671d892e8b9962b770 Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 17:01:58 +0200 Subject: [PATCH 29/34] format and fix } --- .vscode/settings.json | 3 + src/Easy.cc | 352 ++++++++++++++++++++++-------------------- 2 files changed, 185 insertions(+), 170 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..1020fdf91 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "clang_format_executable": "/nix/store/kn213m6rd11nlbl1hvgla5zkqawr4jyj-clang-tools-17.0.6/bin/clang-format" +} \ No newline at end of file diff --git a/src/Easy.cc b/src/Easy.cc index 1be3838ef..e4cb3b900 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -49,9 +49,9 @@ class Easy::ToFree { }; void assert(bool condition, const std::string& message = "Assertion failed!") { - if (!condition) { - throw std::runtime_error(message); - } + if (!condition) { + throw std::runtime_error(message); + } } Napi::FunctionReference Easy::constructor; @@ -357,7 +357,7 @@ void Easy::CallSocketEvent(int status, int events) { if (this->cbOnSocketEvent == nullptr) { return; } - + Napi::HandleScope scope(env); Napi::Value err = env.Null(); @@ -404,15 +404,15 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) if (it != obj->callbacks.end()) { Napi::HandleScope scope(env); - Napi::Buffer buf = Napi::Buffer::New(env, static_cast(n)); - Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); - Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); - const int argc = 3; - Napi::Value argv[argc] = { - buf, - sizeArg, - nmembArg, - }; + Napi::Buffer buf = Napi::Buffer::New(env, static_cast(n)); + Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); + Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); + const int argc = 3; + Napi::Value argv[argc] = { + buf, + sizeArg, + nmembArg, + }; Napi::TryCatch tryCatch; Napi::AsyncResource asyncResource("Easy::ReadFunction"); @@ -564,7 +564,7 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); - std::vector argv = { buf, sizeArg, nmembArg }; + std::vector argv = {buf, sizeArg, nmembArg}; Napi::TryCatch tryCatch; Napi::AsyncResource asyncResource("Easy::OnData"); @@ -618,8 +618,7 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { Napi::Number sizeArg = Napi::Number::New(env, static_cast(size)); Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); - std::vector argv = { buf, sizeArg, nmembArg }; - + std::vector argv = {buf, sizeArg, nmembArg}; Napi::TryCatch tryCatch; Napi::AsyncResource asyncResource("Easy::OnHeader"); @@ -1373,29 +1372,24 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o Napi::Object Easy::Initialize(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); - Napi::Function tmpl = DefineClass(env, "Easy", { - InstanceMethod<&Easy::SetOpt>("setOpt"), - InstanceMethod<&Easy::GetInfo>("getInfo"), - InstanceMethod<&Easy::Send>("send"), - InstanceMethod<&Easy::Recv>("recv"), - InstanceMethod<&Easy::Perform>("perform"), - InstanceMethod<&Easy::Upkeep>("upkeep"), - InstanceMethod<&Easy::Pause>("pause"), - InstanceMethod<&Easy::Reset>("reset"), - InstanceMethod<&Easy::DupHandle>("dupHandle"), - InstanceMethod<&Easy::OnSocketEvent>("onSocketEvent"), - InstanceMethod<&Easy::MonitorSocketEvents>("monitorSocketEvents"), - InstanceMethod<&Easy::UnmonitorSocketEvents>("unmonitorSocketEvents"), - InstanceMethod<&Easy::Close>("close"), - StaticMethod("strError", &Easy::StrError), - - InstanceAccessor("id", &Easy::IdGetter, nullptr), - InstanceAccessor("isInsideMultiHandle", &Easy::IsInsideMultiHandleGetter, nullptr), - InstanceAccessor("isMonitoringSockets", &Easy::IsMonitoringSocketsGetter, nullptr), - InstanceAccessor("isOpen", &Easy::IsOpenGetter, nullptr) -}); - - // Store the class constructor in the persistent reference + Napi::Function tmpl = DefineClass( + env, "Easy", + {InstanceMethod<&Easy::SetOpt>("setOpt"), InstanceMethod<&Easy::GetInfo>("getInfo"), + InstanceMethod<&Easy::Send>("send"), InstanceMethod<&Easy::Recv>("recv"), + InstanceMethod<&Easy::Perform>("perform"), InstanceMethod<&Easy::Upkeep>("upkeep"), + InstanceMethod<&Easy::Pause>("pause"), InstanceMethod<&Easy::Reset>("reset"), + InstanceMethod<&Easy::DupHandle>("dupHandle"), + InstanceMethod<&Easy::OnSocketEvent>("onSocketEvent"), + InstanceMethod<&Easy::MonitorSocketEvents>("monitorSocketEvents"), + InstanceMethod<&Easy::UnmonitorSocketEvents>("unmonitorSocketEvents"), + InstanceMethod<&Easy::Close>("close"), StaticMethod("strError", &Easy::StrError), + + InstanceAccessor("id", &Easy::IdGetter, nullptr), + InstanceAccessor("isInsideMultiHandle", &Easy::IsInsideMultiHandleGetter, nullptr), + InstanceAccessor("isMonitoringSockets", &Easy::IsMonitoringSocketsGetter, nullptr), + InstanceAccessor("isOpen", &Easy::IsOpenGetter, nullptr)}); + + // Store the class constructor in the persistent reference Easy::constructor = Napi::Persistent(tmpl); Easy::constructor.SuppressDestruct(); @@ -1415,7 +1409,8 @@ Napi::Value Easy::New(const Napi::CallbackInfo& info) { // Copy constructor, used when duplicating handles. if (!jsHandle.IsUndefined()) { if (!jsHandle.IsExternal() && - (!jsHandle.IsObject() || !Napi::Function::New(env, Easy::constructor)->HasInstance(jsHandle))) { + (!jsHandle.IsObject() || + !Napi::Function::New(env, Easy::constructor)->HasInstance(jsHandle))) { throw Napi::Error::New(env, "Argument must be an instance of an Easy handle."); } @@ -1486,26 +1481,30 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { // we probably could use these here for newer libcurl versions... if ((optionId = IsInsideCurlConstantStruct(curlOptionNotImplemented, opt))) { - throw Napi::Error::New(env, "Unsupported option, probably because it's too complex to implement using javascript or unecessary when using javascript (like the _DATA options)."); + throw Napi::Error::New( + env, + "Unsupported option, probably because it's too complex to implement using javascript or " + "unecessary when using javascript (like the _DATA options)."); } if ((optionId = IsInsideCurlConstantStruct(curlOptionSpecific, opt))) { if (optionId == CURLOPT_SHARE) { - if (value.IsNull()) { - setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); - return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); - } - if (!value.IsObject() || !Share::constructor.Value().HasInstance(value)) { - throw Napi::Error::New(env, "Invalid value for the SHARE option. It must be a Share instance."); - } + if (value.IsNull()) { + setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, NULL); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); + } + if (!value.IsObject() || !Share::constructor.Value().HasInstance(value)) { + throw Napi::Error::New(env, + "Invalid value for the SHARE option. It must be a Share instance."); + } - Share* share = Napi::ObjectWrap::Unwrap(value.As()); + Share* share = Napi::ObjectWrap::Unwrap(value.As()); - if (!share->isOpen) { - throw Napi::Error::New(env, "Share handle is already closed."); - } + if (!share->isOpen) { + throw Napi::Error::New(env, "Share handle is already closed."); + } - setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, share->sh); - return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); + setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_SHARE, share->sh); + return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } // linked list options } @@ -1533,121 +1532,124 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (!obj.IsObject()) { throw Napi::TypeError::New(env, invalidArrayMsg.c_str()); - Napi::Object postData = obj.As(); + Napi::Object postData = obj.As(); - const Napi::Array props = postData.GetPropertyNames(); - const uint32_t postDataLength = props.Length(); + const Napi::Array props = postData.GetPropertyNames(); + const uint32_t postDataLength = props.Length(); - bool hasFile = false; - bool hasContentType = false; - bool hasContent = false; - bool hasName = false; - bool hasNewFileName = false; + bool hasFile = false; + bool hasContentType = false; + bool hasContent = false; + bool hasName = false; + bool hasNewFileName = false; - // loop through the properties names, making sure they are valid. - for (uint32_t j = 0; j < postDataLength; ++j) { - int32_t httpPostId = -1; + // loop through the properties names, making sure they are valid. + for (uint32_t j = 0; j < postDataLength; ++j) { + int32_t httpPostId = -1; - const Napi::Value postDataKey = (props).Get(j); - const Napi::Value postDataValue = (postData).Get(postDataKey); + const Napi::Value postDataKey = (props).Get(j); + const Napi::Value postDataValue = (postData).Get(postDataKey); - // convert postDataKey to httppost id - std::string fieldName = postDataKey.As(); - std::string optionName = std::string(*fieldName); - std::transform(optionName.begin(), optionName.end(), optionName.begin(), ::toupper); + // convert postDataKey to httppost id + std::string fieldName = postDataKey.As(); + std::string optionName = std::string(*fieldName); + std::transform(optionName.begin(), optionName.end(), optionName.begin(), ::toupper); - for (std::vector::const_iterator it = curlOptionHttpPost.begin(), - end = curlOptionHttpPost.end(); - it != end; ++it) { - if (it->name == optionName) { - httpPostId = static_cast(it->value); + for (std::vector::const_iterator it = curlOptionHttpPost.begin(), + end = curlOptionHttpPost.end(); + it != end; ++it) { + if (it->name == optionName) { + httpPostId = static_cast(it->value); + } } - } - switch (httpPostId) { - case CurlHttpPost::FILE: - hasFile = true; - break; - case CurlHttpPost::TYPE: - hasContentType = true; - break; - case CurlHttpPost::CONTENTS: - hasContent = true; - break; - case CurlHttpPost::NAME: - hasName = true; - break; - case CurlHttpPost::FILENAME: - hasNewFileName = true; - break; - case -1: // property not found + switch (httpPostId) { + case CurlHttpPost::FILE: + hasFile = true; + break; + case CurlHttpPost::TYPE: + hasContentType = true; + break; + case CurlHttpPost::CONTENTS: + hasContent = true; + break; + case CurlHttpPost::NAME: + hasName = true; + break; + case CurlHttpPost::FILENAME: + hasNewFileName = true; + break; + case -1: // property not found + std::string errorMsg; + + errorMsg += std::string("Invalid property given: \"") + optionName + + "\". Valid properties are file, type, contents, name " + "and filename."; + throw Napi::Error::New(env, errorMsg.c_str()); + } + + // check if value is a string. + if (!postDataValue.IsString()) { std::string errorMsg; - errorMsg += std::string("Invalid property given: \"") + optionName + - "\". Valid properties are file, type, contents, name " - "and filename."; - throw Napi::Error::New(env, errorMsg.c_str()); + errorMsg += + std::string("Value for property \"") + optionName + "\" must be a string."; + throw Napi::TypeError::New(env, errorMsg.c_str()); + } } - // check if value is a string. - if (!postDataValue.IsString()) { - std::string errorMsg; - - errorMsg += std::string("Value for property \"") + optionName + "\" must be a string."; - throw Napi::TypeError::New(env, errorMsg.c_str()); + if (!hasName) { + throw Napi::Error::New(env, "Missing field \"name\"."); } - } - if (!hasName) { - throw Napi::Error::New(env, "Missing field \"name\"."); - } - - std::string fieldName = postData.Get("name").As(); - CURLFORMcode curlFormCode; + std::string fieldName = postData.Get("name").As(); + CURLFORMcode curlFormCode; - if (hasFile) { - std::string file = postData.Get("file").As(); + if (hasFile) { + std::string file = postData.Get("file").As(); - if (hasContentType) { - std::string contentType = postData.Get("type").As(); + if (hasContentType) { + std::string contentType = postData.Get("type").As(); - if (hasNewFileName) { - std::string fileName = postData.Get("filename").As(); - curlFormCode = - httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType, *fileName); + if (hasNewFileName) { + std::string fileName = postData.Get("filename").As(); + curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file, + *contentType, *fileName); + } else { + curlFormCode = + httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType); + } } else { - curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file, *contentType); + curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file); } - } else { - curlFormCode = httpPost->AddFile(*fieldName, fieldName.length(), *file); - } - } else if (hasContent) { // if file is not set, the contents field MUST - // be set. + } else if (hasContent) { // if file is not set, the contents field MUST + // be set. - std::string fieldValue = postData.Get("contents").As(); + std::string fieldValue = postData.Get("contents").As(); - curlFormCode = - httpPost->AddField(*fieldName, fieldName.length(), *fieldValue, fieldValue.length()); + curlFormCode = httpPost->AddField(*fieldName, fieldName.length(), *fieldValue, + fieldValue.length()); - } else { - throw Napi::Error::New(env, "Missing field \"contents\"."); - } + } else { + throw Napi::Error::New(env, "Missing field \"contents\"."); + } - if (curlFormCode != CURL_FORMADD_OK) { - std::string errorMsg; + if (curlFormCode != CURL_FORMADD_OK) { + std::string errorMsg; - errorMsg += std::string("Error while adding field \"") + *fieldName + "\" to post data."; - throw Napi::Error::New(env, errorMsg.c_str()); + errorMsg += + std::string("Error while adding field \"") + *fieldName + "\" to post data."; + throw Napi::Error::New(env, errorMsg.c_str()); + } } - } - setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HTTPPOST, httpPost->first); + setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HTTPPOST, httpPost->first); - if (setOptRetCode == CURLE_OK) { - obj->toFree->post.push_back(std::move(httpPost)); + if (setOptRetCode == CURLE_OK) { + obj->toFree->post.push_back(std::move(httpPost)); + } } - } else { if (!value.IsArray()) { throw Napi::TypeError::New(env, "Option value must be an Array."); @@ -1658,9 +1660,9 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { Napi::Array array = value.As(); for (uint32_t i = 0, len = array.Length(); i < len; ++i) { - Napi::String item = array.Get(i).As(); - std::string utf8String = item.Utf8Value(); - slist = curl_slist_append(slist, utf8String.c_str()); + Napi::String item = array.Get(i).As(); + std::string utf8String = item.Utf8Value(); + slist = curl_slist_append(slist, utf8String.c_str()); } setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), slist); @@ -1705,7 +1707,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, static_cast(optionId), valueStr.c_str()); } - // check if option is an integer, and the value is correct } else if ((optionId = IsInsideCurlConstantStruct(curlOptionInteger, opt))) { @@ -1759,11 +1760,11 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, NULL); return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } - obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_CHUNK_BGN_FUNCTION] = + std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_BGN_FUNCTION, Easy::CbChunkBgn); - break; @@ -1780,11 +1781,11 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, NULL); return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); } - obj->callbacks[CURLOPT_CHUNK_END_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_CHUNK_END_FUNCTION] = + std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_CHUNK_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_CHUNK_END_FUNCTION, Easy::CbChunkEnd); - break; @@ -1796,12 +1797,12 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, NULL); return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); - } - obj->callbacks[CURLOPT_DEBUGFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + } + obj->callbacks[CURLOPT_DEBUGFUNCTION] = + std::make_unique(Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_DEBUGDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_DEBUGFUNCTION, Easy::CbDebug); - break; @@ -1813,7 +1814,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_DATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_FUNCTION, NULL); } else { - obj->callbacks[CURLOPT_FNMATCH_FUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_FNMATCH_FUNCTION] = std::make_unique( + Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_DATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_FNMATCH_FUNCTION, Easy::CbFnMatch); @@ -1827,7 +1829,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_HEADERFUNCTION); } else { - obj->callbacks[CURLOPT_HEADERFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_HEADERFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); } break; @@ -1839,7 +1842,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_HSTSREADDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSREADFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_HSTSREADFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_HSTSREADFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_HSTSREADDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSREADFUNCTION, Easy::CbHstsRead); @@ -1853,7 +1857,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_HSTSWRITEFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_HSTSWRITEFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_HSTSWRITEFUNCTION, Easy::CbHstsWrite); @@ -1869,7 +1874,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_PROGRESSDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_PROGRESSFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_PROGRESSFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_PROGRESSFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_PROGRESSDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_PROGRESSFUNCTION, Easy::CbProgress); @@ -1884,7 +1890,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_READFUNCTION); } else { - obj->callbacks[CURLOPT_READFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_READFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); } break; @@ -1896,7 +1903,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_SEEKFUNCTION); } else { - obj->callbacks[CURLOPT_SEEKFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_SEEKFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); } break; @@ -1909,7 +1917,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_TRAILERDATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_TRAILERFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_TRAILERFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_TRAILERFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_TRAILERDATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_TRAILERFUNCTION, Easy::CbTrailer); @@ -1928,7 +1937,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { curl_easy_setopt(obj->ch, CURLOPT_XFERINFODATA, NULL); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_XFERINFOFUNCTION, NULL); } else { - obj->callbacks[CURLOPT_XFERINFOFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_XFERINFOFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); curl_easy_setopt(obj->ch, CURLOPT_XFERINFODATA, obj); setOptRetCode = curl_easy_setopt(obj->ch, CURLOPT_XFERINFOFUNCTION, Easy::CbXferinfo); @@ -1943,7 +1953,8 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { if (isNull) { obj->callbacks.erase(CURLOPT_WRITEFUNCTION); } else { - obj->callbacks[CURLOPT_WRITEFUNCTION] = std::make_unique(Napi::Persistent(value.As())); + obj->callbacks[CURLOPT_WRITEFUNCTION] = std::make_unique( + Napi::Persistent(value.As())); } break; @@ -1977,7 +1988,6 @@ Napi::Value Easy::SetOpt(const Napi::CallbackInfo& info) { } else { throw Napi::TypeError::New(env, "Option value must be a string or Buffer."); } - } return Napi::Number::New(info.Env(), static_cast(setOptRetCode)); @@ -2038,11 +2048,12 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { // Special case for unsupported info if ((infoId = IsInsideCurlConstantStruct(curlInfoNotImplemented, infoVal))) { - throw Napi::Error::New(env, "Unsupported info, probably because it's too complex to implement using javascript or unecessary when using javascript."); + throw Napi::Error::New(env, + "Unsupported info, probably because it's too complex to implement " + "using javascript or unecessary when using javascript."); } - try{ - + try { // String if ((infoId = IsInsideCurlConstantStruct(curlInfoString, infoVal))) { retVal = Easy::GetInfoTmpl(obj, infoId); @@ -2195,7 +2206,8 @@ Napi::Value Easy::Recv(const Napi::CallbackInfo& info) { Napi::Object ret = Napi::Object::New(env); (ret).Set(Napi::String::New(env, "code"), Napi::Number::New(env, static_cast(curlRet))); - (ret).Set(Napi::String::New(env, "bytesReceived"), Napi::Number::New(env, static_cast(n))); + (ret).Set(Napi::String::New(env, "bytesReceived"), + Napi::Number::New(env, static_cast(n))); return ret; } @@ -2340,7 +2352,7 @@ Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - try{ + try { obj->MonitorSockets(env); } catch (const std::exception& e) { throw Napi::Error::New(env, e.what()); @@ -2355,7 +2367,7 @@ Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { Easy* obj = Napi::ObjectWrap::Unwrap(info.This().As()); - try{ + try { obj->UnmonitorSockets(env); } catch (const std::exception& e) { throw Napi::Error::New(env, e.what()); @@ -2376,8 +2388,8 @@ Napi::Value Easy::Close(const Napi::CallbackInfo& info) { } if (obj->isInsideMultiHandle) { - throw Napi::Error::New(env, "Curl handle is inside a Multi instance, you must remove it first."); - + throw Napi::Error::New(env, + "Curl handle is inside a Multi instance, you must remove it first."); } obj->Dispose(env); From 8b963e1af7639006b70f90cd1a5c89648880db09 Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 17:14:05 +0200 Subject: [PATCH 30/34] try catches --- src/Easy.cc | 273 +++++++++++++++++++++++++--------------------------- 1 file changed, 133 insertions(+), 140 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index e4cb3b900..49f0bc6d7 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -414,16 +414,16 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) nmembArg, }; - Napi::TryCatch tryCatch; - Napi::AsyncResource asyncResource("Easy::ReadFunction"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::ReadFunction"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -502,16 +502,16 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { originArg, }; - Napi::TryCatch tryCatch; - Napi::AsyncResource asyncResource("Easy::SeekFunction"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::SeekFunction"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -566,16 +566,16 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { std::vector argv = {buf, sizeArg, nmembArg}; - Napi::TryCatch tryCatch; - Napi::AsyncResource asyncResource("Easy::OnData"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::OnData"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (this->isInsideMultiHandle) { - this->callbackError.Reset(tryCatch.Exception()); + this->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -620,16 +620,16 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { std::vector argv = {buf, sizeArg, nmembArg}; - Napi::TryCatch tryCatch; - Napi::AsyncResource asyncResource("Easy::OnHeader"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::OnHeader"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (this->isInsideMultiHandle) { - this->callbackError.Reset(tryCatch.Exception()); + this->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -733,17 +733,16 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // int32_t returnValue = CURL_CHUNK_BGN_FUNC_FAIL; - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbChunkBgn"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::CbChunkBgn"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -774,17 +773,16 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) int32_t returnValue = CURL_CHUNK_END_FUNC_FAIL; - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbChunkEnd"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + try { + Napi::AsyncResource asyncResource("Easy::CbChunkEnd"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -823,17 +821,16 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi int32_t returnValue = 1; - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbDebug"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::CbDebug"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -868,17 +865,16 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { int32_t returnValue = CURL_FNMATCHFUNC_FAIL; - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbFnMatch"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::CbFnMatch"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -911,43 +907,43 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { int32_t returnValue = CURLSTS_FAIL; - Napi::TryCatch tryCatch; - Napi::Value cacheEntryObject; - - Napi::Value typeError = Napi::TypeError( - "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" - " - Object matching the type CurlHstsEntry\n" - " - An array matching the type CurlHstsEntry[]\n" - " - null\n" - "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " - "callback, thus you may be receiving an error while the request did in fact work. Please " - "fix " - "the HSTS callback to return the correct data to avoid this."); - - if (obj->hstsReadCache.size() > 0) { - auto persistentValue = obj->hstsReadCache.back(); - cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); - - // reset the persistent handler so we do not leak memory - persistentValue.Reset(); - // remove it from the stack - obj->hstsReadCache.pop_back(); - } else { - // if this is true, this means we got all the entries in the cache provided by the user - if (obj->wasHstsReadCacheSet) { - obj->wasHstsReadCacheSet = false; - return CURLSTS_DONE; - } + try { + Napi::Value cacheEntryObject; + + Napi::Value typeError = Napi::TypeError( + "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" + " - Object matching the type CurlHstsEntry\n" + " - An array matching the type CurlHstsEntry[]\n" + " - null\n" + "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " + "callback, thus you may be receiving an error while the request did in fact work. Please " + "fix " + "the HSTS callback to return the correct data to avoid this."); + + if (obj->hstsReadCache.size() > 0) { + auto persistentValue = obj->hstsReadCache.back(); + cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); - Napi::AsyncResource asyncResource("Easy::CbHstsRead"); - Napi::MaybeLocal returnValueFromHstsReadCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + // reset the persistent handler so we do not leak memory + persistentValue.Reset(); + // remove it from the stack + obj->hstsReadCache.pop_back(); + } else { + // if this is true, this means we got all the entries in the cache provided by the user + if (obj->wasHstsReadCacheSet) { + obj->wasHstsReadCacheSet = false; + return CURLSTS_DONE; + } - if (tryCatch.HasCaught()) { + Napi::AsyncResource asyncResource("Easy::CbHstsRead"); + Napi::MaybeLocal returnValueFromHstsReadCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + } + catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -1116,32 +1112,32 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde int32_t returnValue = CURLSTS_FAIL; - Napi::TryCatch tryCatch; - Napi::Value value; + try { + Napi::Value value; - Napi::Value typeError = Napi::TypeError::New( - env, "Return value from the HSTSWRITEFUNCTION callback must be an integer."); + Napi::Value typeError = Napi::TypeError::New( + env, "Return value from the HSTSWRITEFUNCTION callback must be an integer."); - // TODO(jonathan): give the option to receive an array directly? + // TODO(jonathan): give the option to receive an array directly? - Napi::Object countObj = Napi::Object::New(env); - Napi::Number index = Napi::Number::New(env, static_cast(count->index)); - Napi::Number total = Napi::Number::New(env, static_cast(count->total)); - (countObj).Set(Napi::String::New(env, "index"), index); - (countObj).Set(Napi::String::New(env, "total"), total); + Napi::Object countObj = Napi::Object::New(env); + Napi::Number index = Napi::Number::New(env, static_cast(count->index)); + Napi::Number total = Napi::Number::New(env, static_cast(count->total)); + (countObj).Set(Napi::String::New(env, "index"), index); + (countObj).Set(Napi::String::New(env, "total"), total); - const int argc = 2; - Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; + const int argc = 2; + Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; - Napi::AsyncResource asyncResource("Easy::CbHstsWrite"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncResource asyncResource("Easy::CbHstsWrite"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -1192,17 +1188,16 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal Napi::Number::New(env, static_cast(ultotal)), Napi::Number::New(env, static_cast(ulnow))}; - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbProgress"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::CbProgress"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -1240,17 +1235,16 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { it = obj->callbacks.find(CURLOPT_TRAILERFUNCTION); assert(it != obj->callbacks.end() && "Trailer callback not set."); - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbTrailer"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + try { + Napi::AsyncResource asyncResource("Easy::CbTrailer"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return CURL_TRAILERFUNC_ABORT; } @@ -1335,17 +1329,16 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o Napi::Number::New(env, static_cast(ultotal)), Napi::Number::New(env, static_cast(ulnow))}; - Napi::TryCatch tryCatch; - - Napi::AsyncResource asyncResource("Easy::CbXferinfo"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + try { + Napi::AsyncResource asyncResource("Easy::CbXferinfo"); + Napi::MaybeLocal returnValueCallback = + asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); - if (tryCatch.HasCaught()) { + } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(tryCatch.Exception()); + obj->callbackError.Reset(e.Message()); } else { - tryCatch.ReThrow(); + throw e; } return returnValue; } @@ -2018,9 +2011,9 @@ Napi::Value Easy::GetInfoTmpl(const Easy* obj, int infoId) { } else { // is string if (ResultTypeIsChar::value && !result) { - retVal = Napi::MakeMaybe(Napi::EmptyString()); + retVal = Napi::String::New(env, ""); } else { - retVal = Napi::MakeMaybe(Napi::Tv8MappingType::New(env, result)); + retVal = Napi::Value::From(env, result); } } @@ -2124,7 +2117,7 @@ Napi::Value Easy::GetInfo(const Napi::CallbackInfo& info) { } } - } catch (const std::exception& e) { + } catch (const Napi::Error& e) { std::string msg = e.what(); std::string errCode = std::string(*msg); @@ -2354,7 +2347,7 @@ Napi::Value Easy::MonitorSocketEvents(const Napi::CallbackInfo& info) { try { obj->MonitorSockets(env); - } catch (const std::exception& e) { + } catch (const Napi::Error& e) { throw Napi::Error::New(env, e.what()); } @@ -2369,7 +2362,7 @@ Napi::Value Easy::UnmonitorSocketEvents(const Napi::CallbackInfo& info) { try { obj->UnmonitorSockets(env); - } catch (const std::exception& e) { + } catch (const Napi::Error& e) { throw Napi::Error::New(env, e.what()); } From 2e7baa62cad3f84d832ee013efb34e4949072f59 Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 17:36:32 +0200 Subject: [PATCH 31/34] 216 --- src/Easy.cc | 333 +++++++++++++++++++++++++--------------------------- src/Easy.h | 11 +- 2 files changed, 167 insertions(+), 177 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 49f0bc6d7..1d3039705 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -370,8 +370,8 @@ void Easy::CallSocketEvent(int status, int events) { Napi::Value argv[argc] = {err, Napi::Number::New(env, events)}; // **(this->cbOnSocketEvent.get()) is the same than this->cbOnSocketEvent->GetFunction() - Napi::AsyncResource asyncResource("Easy::CallSocketEvent"); - asyncResource.runInAsyncScope(this->handle(), this->cbOnSocketEvent->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CallSocketEvent"); + asyncContext.runInAsyncScope(this->handle(), this->cbOnSocketEvent->GetFunction(), argc, argv); } // Called by libcurl when some chunk of data (from body) is available @@ -415,13 +415,13 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) }; try { - Napi::AsyncResource asyncResource("Easy::ReadFunction"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext(env, "Easy::ReadFunction"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -503,13 +503,13 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { }; try { - Napi::AsyncResource asyncResource("Easy::SeekFunction"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::SeekFunction"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -567,9 +567,9 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { std::vector argv = {buf, sizeArg, nmembArg}; try { - Napi::AsyncResource asyncResource("Easy::OnData"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::OnData"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (this->isInsideMultiHandle) { @@ -621,9 +621,9 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { std::vector argv = {buf, sizeArg, nmembArg}; try { - Napi::AsyncResource asyncResource("Easy::OnHeader"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::OnHeader"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (this->isInsideMultiHandle) { @@ -734,13 +734,13 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // int32_t returnValue = CURL_CHUNK_BGN_FUNC_FAIL; try { - Napi::AsyncResource asyncResource("Easy::CbChunkBgn"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CbChunkBgn"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -772,15 +772,15 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) assert(it != obj->callbacks.end() && "CHUNK_END callback not set."); int32_t returnValue = CURL_CHUNK_END_FUNC_FAIL; - + Napi::Value returnValueCallback; try { - Napi::AsyncResource asyncResource("Easy::CbChunkEnd"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + Napi::AsyncContext asyncContext("Easy::CbChunkEnd"); + returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -822,13 +822,13 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi int32_t returnValue = 1; try { - Napi::AsyncResource asyncResource("Easy::CbDebug"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CbDebug"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -866,13 +866,13 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { int32_t returnValue = CURL_FNMATCHFUNC_FAIL; try { - Napi::AsyncResource asyncResource("Easy::CbFnMatch"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CbFnMatch"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -895,7 +895,6 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { } int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { -#if NODE_LIBCURL_VER_GE(7, 74, 0) Napi::HandleScope scope(env); Easy* obj = static_cast(userdata); @@ -906,10 +905,9 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { assert(it != obj->callbacks.end() && "HSTSREADFUNCTION callback not set."); int32_t returnValue = CURLSTS_FAIL; + Napi::Value cacheEntryObject; try { - Napi::Value cacheEntryObject; - Napi::Value typeError = Napi::TypeError( "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" " - Object matching the type CurlHstsEntry\n" @@ -935,117 +933,139 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { return CURLSTS_DONE; } - Napi::AsyncResource asyncResource("Easy::CbHstsRead"); - Napi::MaybeLocal returnValueFromHstsReadCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); - } - catch (const Napi::Error& e) { - if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); - } else { - throw e; + Napi::AsyncContext asyncContext("Easy::CbHstsRead"); + Napi::Value returnValueFromHstsReadCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + if (returnValueFromHstsReadCallback.IsEmpty()) { + THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) + return returnValue; } - return returnValue; - } - if (returnValueFromHstsReadCallback.IsEmpty()) { - THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) - return returnValue; + cacheEntryObject = returnValueFromHstsReadCallback; } - cacheEntryObject = returnValueFromHstsReadCallback; + } catch (const Napi::Error& e) { + if (obj->isInsideMultiHandle) { + obj->callbackError.Reset(Napi::String::New(env, e.Message())); + } else { + throw e; + } + return returnValue; } if (cacheEntryObject.IsNull()) { return CURLSTS_DONE; - } else { - // returning an array from the callback can be used to avoid multiple - // context switches between v8 and js - if (cacheEntryObject.IsArray()) { - auto cacheArray = cacheEntryObject.As(); - auto cacheArrayLength = cacheArray.Length(); + } + // returning an array from the callback can be used to avoid multiple + // context switches between v8 and js + if (cacheEntryObject.IsArray()) { + auto cacheArray = cacheEntryObject.As(); + auto cacheArrayLength = cacheArray.Length(); - if (cacheArrayLength == 0) { - return CURLSTS_DONE; + if (cacheArrayLength == 0) { + return CURLSTS_DONE; + } + + // inserting in reverse order as we are processing the hstsReadCache stack from back to front + for (int i = cacheArrayLength - 1; i >= 0; i--) { + auto idxValue = (cacheArray).Get(i); + + assert(!idxValue.IsEmpty() && + "Value inside array could not be found - Process may be running out of memory"); + + auto idxValueChecked = idxValue; + + // we check for an array here too to avoid passing a child array here. + // If that happens, the code would get to this condition again when we + // process this cache entry in a future iteration + if (!idxValueChecked.IsObject() || idxValueChecked.IsArray()) { + THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) + return returnValue; } - // inserting in reverse order as we are processing the hstsReadCache stack from back to front - for (int i = cacheArrayLength - 1; i >= 0; i--) { - auto idxValue = (cacheArray).Get(i); + auto idxValueAsObject = idxValueChecked.As(); - assert(!idxValue.IsEmpty() && - "Value inside array could not be found - Process may be running out of memory"); + v8::NonCopyablePersistentTraits::CopyablePersistent persistentValue; - auto idxValueChecked = idxValue; + persistentValue.Reset(Napi::GetCurrentContext()->GetIsolate(), idxValueAsObject); - // we check for an array here too to avoid passing a child array here. - // If that happens, the code would get to this condition again when we - // process this cache entry in a future iteration - if (!idxValueChecked.IsObject() || idxValueChecked.IsArray()) { - THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) - return returnValue; - } + obj->hstsReadCache.push_back(persistentValue); + } - auto idxValueAsObject = idxValueChecked.As(); + auto persistentValue = obj->hstsReadCache.back(); + cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); - v8::NonCopyablePersistentTraits::CopyablePersistent persistentValue; + persistentValue.Reset(); + obj->hstsReadCache.pop_back(); + obj->wasHstsReadCacheSet = true; + } - persistentValue.Reset(Napi::GetCurrentContext()->GetIsolate(), idxValueAsObject); + if (cacheEntryObject.IsObject()) { + // napi would make this so much cleaner... - obj->hstsReadCache.push_back(persistentValue); - } + auto cacheEntry = cacheEntryObject.As(); - auto persistentValue = obj->hstsReadCache.back(); - cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); + auto hostPropertyStr = Napi::String::New(env, "host"); + auto includeSubDomainsPropertyStr = Napi::String::New(env, "includeSubDomains"); + auto expirePropertyStr = Napi::String::New(env, "expire"); - persistentValue.Reset(); - obj->hstsReadCache.pop_back(); - obj->wasHstsReadCacheSet = true; - } + auto hostPropertyValue = (cacheEntry).Get(hostPropertyStr); + auto includeSubDomainsPropertyValue = (cacheEntry).Get(includeSubDomainsPropertyStr); + auto expirePropertyValue = (cacheEntry).Get(expirePropertyStr); - if (cacheEntryObject.IsObject()) { - // napi would make this so much cleaner... + if (hostPropertyValue.IsEmpty() || includeSubDomainsPropertyValue.IsEmpty() || + expirePropertyValue.IsEmpty()) { + assert("Process ran out of memory - fields returned from HSTSREADFUNCTION were empty"); + } - auto cacheEntry = cacheEntryObject.As(); + auto hostPropertyValueChecked = hostPropertyValue; + auto includeSubDomainsPropertyValueChecked = includeSubDomainsPropertyValue; + auto expirePropertyValueChecked = expirePropertyValue; - auto hostPropertyStr = Napi::String::New(env, "host"); - auto includeSubDomainsPropertyStr = Napi::String::New(env, "includeSubDomains"); - auto expirePropertyStr = Napi::String::New(env, "expire"); + // the validation here is pretty basic, and we are not really validating + // the format of the expire string - libcurl should do that - auto hostPropertyValue = (cacheEntry).Get(hostPropertyStr); - auto includeSubDomainsPropertyValue = (cacheEntry).Get(includeSubDomainsPropertyStr); - auto expirePropertyValue = (cacheEntry).Get(expirePropertyStr); + // make sure the provided data is valid + if (!hostPropertyValueChecked.IsString() || + (!includeSubDomainsPropertyValueChecked->IsNullOrUndefined() && + !includeSubDomainsPropertyValueChecked->IsBoolean()) || + (!expirePropertyValueChecked->IsNullOrUndefined() && + !expirePropertyValueChecked.IsString())) { + THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) + return returnValue; + } - if (hostPropertyValue.IsEmpty() || includeSubDomainsPropertyValue.IsEmpty() || - expirePropertyValue.IsEmpty()) { - assert("Process ran out of memory - fields returned from HSTSREADFUNCTION were empty"); - } + std::string hostStrValue = hostPropertyValueChecked.As(); - auto hostPropertyValueChecked = hostPropertyValue; - auto includeSubDomainsPropertyValueChecked = includeSubDomainsPropertyValue; - auto expirePropertyValueChecked = expirePropertyValue; + // make sure str len is inside the given max length + if (static_cast(hostStrValue.length()) > sts->namelen) { + Napi::Value typeError = Napi::TypeError( + "The host property value returned from the HSTSREADFUNCTION callback function was " + "invalid. The host string is too long.\n" + "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " + "callback, thus you may be receiving an error while the request did in fact work. " + "Please fix the HSTS callback to return the correct data to avoid this."); + THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) - // the validation here is pretty basic, and we are not really validating - // the format of the expire string - libcurl should do that + return returnValue; + } - // make sure the provided data is valid - if (!hostPropertyValueChecked.IsString() || - (!includeSubDomainsPropertyValueChecked->IsNullOrUndefined() && - !includeSubDomainsPropertyValueChecked->IsBoolean()) || - (!expirePropertyValueChecked->IsNullOrUndefined() && - !expirePropertyValueChecked.IsString())) { - THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) - return returnValue; - } + sts->name = *hostStrValue; + sts->includeSubDomains = includeSubDomainsPropertyValueChecked.As().Value(); - std::string hostStrValue = hostPropertyValueChecked.As(); + if (expirePropertyValueChecked.IsString()) { + // make sure expire length is one expected by libcurl + // YYYYMMDD HH:MM:SS [null-terminated] + size_t currentSize = + static_cast(expirePropertyValueChecked.As().Length()); + size_t expectedSize = sizeof(sts->expire) / sizeof(sts->expire[0]) - 1; - // make sure str len is inside the given max length - if (static_cast(hostStrValue.length()) > sts->namelen) { + if (currentSize != expectedSize) { Napi::Value typeError = Napi::TypeError( - "The host property value returned from the HSTSREADFUNCTION callback function was " - "invalid. The host string is too long.\n" - "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " + "The expire property value returned from the HSTSREADFUNCTION callback function was " + "invalid. String is either too long, or too short.\n" + "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the " + "HSTS " "callback, thus you may be receiving an error while the request did in fact work. " "Please fix the HSTS callback to return the correct data to avoid this."); THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) @@ -1053,49 +1073,22 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { return returnValue; } - sts->name = *hostStrValue; - sts->includeSubDomains = includeSubDomainsPropertyValueChecked.As().Value(); - - if (expirePropertyValueChecked.IsString()) { - // make sure expire length is one expected by libcurl - // YYYYMMDD HH:MM:SS [null-terminated] - size_t currentSize = - static_cast(expirePropertyValueChecked.As().Length()); - size_t expectedSize = sizeof(sts->expire) / sizeof(sts->expire[0]) - 1; - - if (currentSize != expectedSize) { - Napi::Value typeError = Napi::TypeError( - "The expire property value returned from the HSTSREADFUNCTION callback function was " - "invalid. String is either too long, or too short.\n" - "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the " - "HSTS " - "callback, thus you may be receiving an error while the request did in fact work. " - "Please fix the HSTS callback to return the correct data to avoid this."); - THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) - - return returnValue; - } - - std::string expireStrValue = expirePropertyValueChecked.As(); - auto expireCharValue = *expireStrValue; + std::string expireStrValue = expirePropertyValueChecked.As(); + auto expireCharValue = *expireStrValue; - strcpy(sts->expire, expireCharValue); - } else { - // TODO(jonathan): libcurl <= 7.79 has a bug when expire is not set, see: - // https://github.com/curl/curl/issues/7720 - to avoid this bug we are setting it manually - // to a future date here - strcpy(sts->expire, TIME_IN_THE_FUTURE); - } - returnValue = CURLSTS_OK; + strcpy(sts->expire, expireCharValue); } else { - THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) + // TODO(jonathan): libcurl <= 7.79 has a bug when expire is not set, see: + // https://github.com/curl/curl/issues/7720 - to avoid this bug we are setting it manually + // to a future date here + strcpy(sts->expire, TIME_IN_THE_FUTURE); } + returnValue = CURLSTS_OK; + } else { + THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) } return returnValue; -#else - return 0; -#endif } int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_index* count, @@ -1129,13 +1122,13 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde const int argc = 2; Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; - Napi::AsyncResource asyncResource("Easy::CbHstsWrite"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CbHstsWrite"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -1189,13 +1182,13 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal Napi::Number::New(env, static_cast(ulnow))}; try { - Napi::AsyncResource asyncResource("Easy::CbProgress"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CbProgress"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -1236,13 +1229,13 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { assert(it != obj->callbacks.end() && "Trailer callback not set."); try { - Napi::AsyncResource asyncResource("Easy::CbTrailer"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); + Napi::AsyncContext asyncContext("Easy::CbTrailer"); + Napi::Value returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -1328,15 +1321,15 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o Napi::Number::New(env, static_cast(dlnow)), Napi::Number::New(env, static_cast(ultotal)), Napi::Number::New(env, static_cast(ulnow))}; - + Napi::Value returnValueCallback; try { - Napi::AsyncResource asyncResource("Easy::CbXferinfo"); - Napi::MaybeLocal returnValueCallback = - asyncResource.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); + Napi::AsyncContext asyncContext("Easy::CbXferinfo"); + returnValueCallback = + asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { if (obj->isInsideMultiHandle) { - obj->callbackError.Reset(e.Message()); + obj->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } diff --git a/src/Easy.h b/src/Easy.h index 7e2706f60..071c61794 100644 --- a/src/Easy.h +++ b/src/Easy.h @@ -11,15 +11,12 @@ #include "libcurl_compat.h" #include -#include -#include -#include -#include -#include #include #include - +#include +#include +#include namespace NodeLibcurl { @@ -140,7 +137,7 @@ class Easy : public Napi::ObjectWrap { bool isOpen = true; // used to return callback errors when inside Multi interface - v8::Persistent callbackError; + Napi::Reference callbackError; // static members static uint32_t currentOpenedHandles; From f7be0447d78b7e296de8feef8369716fd49c0a4d Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 17:42:46 +0200 Subject: [PATCH 32/34] 180 --- src/Easy.cc | 54 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index 1d3039705..ffb683521 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -413,10 +413,10 @@ size_t Easy::ReadFunction(char* ptr, size_t size, size_t nmemb, void* userdata) sizeArg, nmembArg, }; - + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext(env, "Easy::ReadFunction"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -501,10 +501,11 @@ size_t Easy::SeekFunction(void* userdata, curl_off_t offset, int origin) { offsetArg, originArg, }; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::SeekFunction"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -565,10 +566,11 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); std::vector argv = {buf, sizeArg, nmembArg}; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::OnData"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -619,10 +621,11 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { Napi::Number nmembArg = Napi::Number::New(env, static_cast(nmemb)); std::vector argv = {buf, sizeArg, nmembArg}; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::OnHeader"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(this->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -732,10 +735,11 @@ long Easy::CbChunkBgn(curl_fileinfo* transferInfo, void* ptr, int remains) { // Napi::Number::New(env, remains)}; int32_t returnValue = CURL_CHUNK_BGN_FUNC_FAIL; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::CbChunkBgn"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -773,6 +777,7 @@ long Easy::CbChunkEnd(void* ptr) { // NOLINT(runtime/int) int32_t returnValue = CURL_CHUNK_END_FUNC_FAIL; Napi::Value returnValueCallback; + try { Napi::AsyncContext asyncContext("Easy::CbChunkEnd"); returnValueCallback = @@ -820,10 +825,11 @@ int Easy::CbDebug(CURL* handle, curl_infotype type, char* data, size_t size, voi }; int32_t returnValue = 1; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::CbDebug"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -864,10 +870,11 @@ int Easy::CbFnMatch(void* ptr, const char* pattern, const char* string) { Napi::Value argv[argc] = {Napi::String::New(env, pattern), Napi::String::New(env, string)}; int32_t returnValue = CURL_FNMATCHFUNC_FAIL; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::CbFnMatch"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -906,18 +913,17 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { int32_t returnValue = CURLSTS_FAIL; Napi::Value cacheEntryObject; + Napi::Value typeError = Napi::TypeError( + "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" + " - Object matching the type CurlHstsEntry\n" + " - An array matching the type CurlHstsEntry[]\n" + " - null\n" + "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " + "callback, thus you may be receiving an error while the request did in fact work. Please " + "fix " + "the HSTS callback to return the correct data to avoid this."); try { - Napi::Value typeError = Napi::TypeError( - "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" - " - Object matching the type CurlHstsEntry\n" - " - An array matching the type CurlHstsEntry[]\n" - " - null\n" - "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " - "callback, thus you may be receiving an error while the request did in fact work. Please " - "fix " - "the HSTS callback to return the correct data to avoid this."); - if (obj->hstsReadCache.size() > 0) { auto persistentValue = obj->hstsReadCache.back(); cacheEntryObject = Napi::Object::New(env, obj->hstsReadCache.back()); @@ -1104,6 +1110,7 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde assert(it != obj->callbacks.end() && "HSTSWRITEFUNCTION callback not set."); int32_t returnValue = CURLSTS_FAIL; + Napi::Value returnValueCallback; try { Napi::Value value; @@ -1123,7 +1130,7 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; Napi::AsyncContext asyncContext("Easy::CbHstsWrite"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -1180,10 +1187,11 @@ int Easy::CbProgress(void* clientp, double dltotal, double dlnow, double ultotal Napi::Number::New(env, static_cast(dlnow)), Napi::Number::New(env, static_cast(ultotal)), Napi::Number::New(env, static_cast(ulnow))}; + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::CbProgress"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), argc, argv); } catch (const Napi::Error& e) { @@ -1227,10 +1235,11 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { // make sure the callback was set it = obj->callbacks.find(CURLOPT_TRAILERFUNCTION); assert(it != obj->callbacks.end() && "Trailer callback not set."); + Napi::Value returnValueCallback; try { Napi::AsyncContext asyncContext("Easy::CbTrailer"); - Napi::Value returnValueCallback = + returnValueCallback = asyncContext.runInAsyncScope(obj->handle(), it->second->GetFunction(), 0, NULL); } catch (const Napi::Error& e) { @@ -1258,7 +1267,7 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { return CURL_TRAILERFUNC_ABORT; } - Napi::Value returnValueCallbackChecked = returnValueCallback; + returnValueCallbackChecked = returnValueCallback; if (returnValueCallbackChecked.IsFalse()) { return CURL_TRAILERFUNC_ABORT; @@ -1322,6 +1331,7 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o Napi::Number::New(env, static_cast(ultotal)), Napi::Number::New(env, static_cast(ulnow))}; Napi::Value returnValueCallback; + try { Napi::AsyncContext asyncContext("Easy::CbXferinfo"); returnValueCallback = From 5e8e877c407d102a2f2c65e64212f5dcb3667582 Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 17:59:04 +0200 Subject: [PATCH 33/34] 167 --- src/Easy.cc | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index ffb683521..fcd481a85 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -575,7 +575,7 @@ size_t Easy::OnData(char* data, size_t size, size_t nmemb) { } catch (const Napi::Error& e) { if (this->isInsideMultiHandle) { - this->callbackError.Reset(e.Message()); + this->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -630,7 +630,7 @@ size_t Easy::OnHeader(char* data, size_t size, size_t nmemb) { } catch (const Napi::Error& e) { if (this->isInsideMultiHandle) { - this->callbackError.Reset(e.Message()); + this->callbackError.Reset(Napi::String::New(env, e.Message())); } else { throw e; } @@ -1111,21 +1111,19 @@ int Easy::CbHstsWrite(CURL* handle, struct curl_hstsentry* sts, struct curl_inde int32_t returnValue = CURLSTS_FAIL; Napi::Value returnValueCallback; + Napi::Value value; - try { - Napi::Value value; - - Napi::Value typeError = Napi::TypeError::New( - env, "Return value from the HSTSWRITEFUNCTION callback must be an integer."); + Napi::Value typeError = Napi::TypeError::New( + env, "Return value from the HSTSWRITEFUNCTION callback must be an integer."); - // TODO(jonathan): give the option to receive an array directly? - - Napi::Object countObj = Napi::Object::New(env); - Napi::Number index = Napi::Number::New(env, static_cast(count->index)); - Napi::Number total = Napi::Number::New(env, static_cast(count->total)); - (countObj).Set(Napi::String::New(env, "index"), index); - (countObj).Set(Napi::String::New(env, "total"), total); + // TODO(jonathan): give the option to receive an array directly? + Napi::Object countObj = Napi::Object::New(env); + Napi::Number index = Napi::Number::New(env, static_cast(count->index)); + Napi::Number total = Napi::Number::New(env, static_cast(count->total)); + (countObj).Set(Napi::String::New(env, "index"), index); + (countObj).Set(Napi::String::New(env, "total"), total); + try { const int argc = 2; Napi::Value argv[argc] = {Easy::CreateV8ObjectFromCurlHstsEntry(sts), countObj}; @@ -1254,8 +1252,9 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { Napi::Value returnValueCbTypeError = Napi::TypeError( "Return value from the Trailer callback must be an array of strings or false."); - bool isInvalid = returnValueCallback.IsEmpty() || - (!returnValueCallback->IsArray() && !returnValueCallback->IsFalse()); + bool isInvalid = + returnValueCallback.IsEmpty() || + (!returnValueCallback.IsArray() && !Napi::Boolean(env, returnValueCallback).Value()); if (isInvalid) { if (obj->isInsideMultiHandle) { @@ -1267,9 +1266,9 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { return CURL_TRAILERFUNC_ABORT; } - returnValueCallbackChecked = returnValueCallback; + Napi::Boolean returnValueCallbackChecked = Napi::Boolean(env, returnValueCallback); - if (returnValueCallbackChecked.IsFalse()) { + if (returnValueCallbackChecked.Value()) { return CURL_TRAILERFUNC_ABORT; } From 03628a727f8d2842af4e31e1431c8c0d12cc40be Mon Sep 17 00:00:00 2001 From: jackkav Date: Wed, 11 Sep 2024 18:17:39 +0200 Subject: [PATCH 34/34] 150 --- src/Easy.cc | 46 ++++++++++++++++++++++++---------------------- src/Easy.h | 3 ++- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/Easy.cc b/src/Easy.cc index fcd481a85..12ad0875e 100644 --- a/src/Easy.cc +++ b/src/Easy.cc @@ -913,7 +913,8 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { int32_t returnValue = CURLSTS_FAIL; Napi::Value cacheEntryObject; - Napi::Value typeError = Napi::TypeError( + Napi::Value typeError = Napi::Error::New( + env, "Return value from the HSTSREADFUNCTION callback must be one of the following:\n" " - Object matching the type CurlHstsEntry\n" " - An array matching the type CurlHstsEntry[]\n" @@ -991,9 +992,9 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { auto idxValueAsObject = idxValueChecked.As(); - v8::NonCopyablePersistentTraits::CopyablePersistent persistentValue; + Napi::ObjectReference persistentValue; - persistentValue.Reset(Napi::GetCurrentContext()->GetIsolate(), idxValueAsObject); + persistentValue.Reset(idxValueAsObject); obj->hstsReadCache.push_back(persistentValue); } @@ -1015,37 +1016,37 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { auto includeSubDomainsPropertyStr = Napi::String::New(env, "includeSubDomains"); auto expirePropertyStr = Napi::String::New(env, "expire"); - auto hostPropertyValue = (cacheEntry).Get(hostPropertyStr); - auto includeSubDomainsPropertyValue = (cacheEntry).Get(includeSubDomainsPropertyStr); - auto expirePropertyValue = (cacheEntry).Get(expirePropertyStr); + Napi::Value hostPropertyValue = cacheEntry.Get(hostPropertyStr); + Napi::Value includeSubDomainsPropertyValue = cacheEntry.Get(includeSubDomainsPropertyStr); + Napi::Value expirePropertyValue = cacheEntry.Get(expirePropertyStr); if (hostPropertyValue.IsEmpty() || includeSubDomainsPropertyValue.IsEmpty() || expirePropertyValue.IsEmpty()) { assert("Process ran out of memory - fields returned from HSTSREADFUNCTION were empty"); } - auto hostPropertyValueChecked = hostPropertyValue; - auto includeSubDomainsPropertyValueChecked = includeSubDomainsPropertyValue; - auto expirePropertyValueChecked = expirePropertyValue; + Napi::Value hostPropertyValueChecked = hostPropertyValue; + Napi::Value includeSubDomainsPropertyValueChecked = includeSubDomainsPropertyValue; + Napi::Value expirePropertyValueChecked = expirePropertyValue; // the validation here is pretty basic, and we are not really validating // the format of the expire string - libcurl should do that // make sure the provided data is valid if (!hostPropertyValueChecked.IsString() || - (!includeSubDomainsPropertyValueChecked->IsNullOrUndefined() && - !includeSubDomainsPropertyValueChecked->IsBoolean()) || - (!expirePropertyValueChecked->IsNullOrUndefined() && - !expirePropertyValueChecked.IsString())) { + (!includeSubDomainsPropertyValueChecked.IsNull() && + !includeSubDomainsPropertyValueChecked.IsBoolean()) || + (!expirePropertyValueChecked.IsNull() && !expirePropertyValueChecked.IsString())) { THROW_ERROR_OR_SET_MULTI_CALLBACK_ERROR_IF_INSIDE_MULTI(typeError) return returnValue; } - std::string hostStrValue = hostPropertyValueChecked.As(); + std::string hostStrValue = hostPropertyValue.As().Utf8Value(); // make sure str len is inside the given max length if (static_cast(hostStrValue.length()) > sts->namelen) { - Napi::Value typeError = Napi::TypeError( + Napi::Value typeError = Napi::Error::New( + env, "The host property value returned from the HSTSREADFUNCTION callback function was " "invalid. The host string is too long.\n" "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the HSTS " @@ -1056,18 +1057,19 @@ int Easy::CbHstsRead(CURL* handle, struct curl_hstsentry* sts, void* userdata) { return returnValue; } - sts->name = *hostStrValue; + sts->name = strdup(hostStrValue.c_str()); sts->includeSubDomains = includeSubDomainsPropertyValueChecked.As().Value(); if (expirePropertyValueChecked.IsString()) { // make sure expire length is one expected by libcurl // YYYYMMDD HH:MM:SS [null-terminated] - size_t currentSize = - static_cast(expirePropertyValueChecked.As().Length()); + std::string expireStrValue = expirePropertyValue.As().Utf8Value(); + size_t currentSize = expireStrValue.size(); size_t expectedSize = sizeof(sts->expire) / sizeof(sts->expire[0]) - 1; if (currentSize != expectedSize) { - Napi::Value typeError = Napi::TypeError( + Napi::Value typeError = Napi::Error::New( + env, "The expire property value returned from the HSTSREADFUNCTION callback function was " "invalid. String is either too long, or too short.\n" "Libcurl <= 7.79.0 does not stop requests from firing if there are errors in the " @@ -1249,8 +1251,8 @@ int Easy::CbTrailer(struct curl_slist** headerList, void* userdata) { return CURL_TRAILERFUNC_ABORT; } - Napi::Value returnValueCbTypeError = Napi::TypeError( - "Return value from the Trailer callback must be an array of strings or false."); + Napi::Value returnValueCbTypeError = Napi::Error::New( + env, "Return value from the Trailer callback must be an array of strings or false."); bool isInvalid = returnValueCallback.IsEmpty() || @@ -1354,7 +1356,7 @@ int Easy::CbXferinfo(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_o throw Napi::Error::New(env, typeError); } } else { - returnValue = returnValueCallback.Int32Value().As(); + returnValue = returnValueCallback.As().Int32Value(); } if (returnValue && returnValue != CURL_PROGRESSFUNC_CONTINUE) { diff --git a/src/Easy.h b/src/Easy.h index 071c61794..694e1796a 100644 --- a/src/Easy.h +++ b/src/Easy.h @@ -52,7 +52,8 @@ class Easy : public Napi::ObjectWrap { cbOnSocketEvent; // still required since it's not related to any CURLOption // members - std::vector> hstsReadCache; + std::vector hstsReadCache; + uint32_t wasHstsReadCacheSet = false; uv_poll_t* socketPollHandle = nullptr; std::shared_ptr toFree = nullptr;