@@ -61,6 +61,10 @@ class CreatePoolWorker : public Napi::AsyncWorker {
6161
6262Napi::Value CreatePoolWrapper (const Napi::CallbackInfo& info) {
6363 Napi::Env env = info.Env ();
64+ if (info.Length () < 3 ) {
65+ Napi::Error::New (env, " CreatePoolWrapper requires 3 arguments" ).ThrowAsJavaScriptException ();
66+ return env.Null ();
67+ }
6468 std::string ua = info[0 ].As <Napi::String>();
6569 std::string cs = info[1 ].As <Napi::String>();
6670 Napi::Function cb = info[2 ].As <Napi::Function>();
@@ -79,6 +83,10 @@ class ClosePoolWorker : public Napi::AsyncWorker {
7983
8084 void Execute () override {
8185 result_ = ClosePool (poolId_);
86+ // Release the pinner ID of the response message to prevent native leak!
87+ if (result_.r0 > 0 ) {
88+ ::Release (result_.r0);
89+ }
8290 }
8391
8492 void OnOK () override {
@@ -94,6 +102,10 @@ class ClosePoolWorker : public Napi::AsyncWorker {
94102
95103Napi::Value ClosePoolWrapper (const Napi::CallbackInfo& info) {
96104 Napi::Env env = info.Env ();
105+ if (info.Length () < 2 ) {
106+ Napi::Error::New (env, " ClosePoolWrapper requires 2 arguments" ).ThrowAsJavaScriptException ();
107+ return env.Null ();
108+ }
97109 int64_t pid = info[0 ].As <Napi::Number>().Int64Value ();
98110 Napi::Function cb = info[1 ].As <Napi::Function>();
99111 ClosePoolWorker* worker = new ClosePoolWorker (cb, pid);
@@ -135,6 +147,10 @@ class CreateConnectionWorker : public Napi::AsyncWorker {
135147
136148Napi::Value CreateConnectionWrapper (const Napi::CallbackInfo& info) {
137149 Napi::Env env = info.Env ();
150+ if (info.Length () < 2 ) {
151+ Napi::Error::New (env, " CreateConnectionWrapper requires 2 arguments" ).ThrowAsJavaScriptException ();
152+ return env.Null ();
153+ }
138154 int64_t pid = info[0 ].As <Napi::Number>().Int64Value ();
139155 Napi::Function cb = info[1 ].As <Napi::Function>();
140156 CreateConnectionWorker* worker = new CreateConnectionWorker (cb, pid);
@@ -152,6 +168,10 @@ class CloseConnectionWorker : public Napi::AsyncWorker {
152168
153169 void Execute () override {
154170 result_ = CloseConnection (poolId_, connId_);
171+ // Release the pinner ID of the response message to prevent native leak!
172+ if (result_.r0 > 0 ) {
173+ ::Release (result_.r0);
174+ }
155175 }
156176
157177 void OnOK () override {
@@ -167,6 +187,10 @@ class CloseConnectionWorker : public Napi::AsyncWorker {
167187
168188Napi::Value CloseConnectionWrapper (const Napi::CallbackInfo& info) {
169189 Napi::Env env = info.Env ();
190+ if (info.Length () < 3 ) {
191+ Napi::Error::New (env, " CloseConnectionWrapper requires 3 arguments" ).ThrowAsJavaScriptException ();
192+ return env.Null ();
193+ }
170194 int64_t pid = info[0 ].As <Napi::Number>().Int64Value ();
171195 int64_t cid = info[1 ].As <Napi::Number>().Int64Value ();
172196 Napi::Function cb = info[2 ].As <Napi::Function>();
@@ -200,6 +224,10 @@ class ExecuteWorker : public Napi::AsyncWorker {
200224 } else {
201225 obj.Set (" r4" , env.Null ());
202226 }
227+ // Release the pinner ID of the response buffer immediately after copy!
228+ if (result_.r0 > 0 ) {
229+ ::Release (result_.r0);
230+ }
203231 Callback ().Call ({env.Null (), obj});
204232 }
205233private:
@@ -210,6 +238,10 @@ class ExecuteWorker : public Napi::AsyncWorker {
210238
211239Napi::Value ExecuteWrapper (const Napi::CallbackInfo& info) {
212240 Napi::Env env = info.Env ();
241+ if (info.Length () < 4 ) {
242+ Napi::Error::New (env, " ExecuteWrapper requires 4 arguments" ).ThrowAsJavaScriptException ();
243+ return env.Null ();
244+ }
213245 int64_t pid = info[0 ].As <Napi::Number>().Int64Value ();
214246 int64_t cid = info[1 ].As <Napi::Number>().Int64Value ();
215247
@@ -246,6 +278,10 @@ class NextWorker : public Napi::AsyncWorker {
246278 } else {
247279 obj.Set (" r4" , env.Null ());
248280 }
281+ // Release the pinner ID of the response buffer immediately after copy!
282+ if (result_.r0 > 0 ) {
283+ ::Release (result_.r0);
284+ }
249285 Callback ().Call ({env.Null (), obj});
250286 }
251287private:
@@ -292,15 +328,58 @@ class MetadataWorker : public Napi::AsyncWorker {
292328 } else {
293329 obj.Set (" r4" , env.Null ());
294330 }
331+ // Release the pinner ID of the response buffer immediately after copy!
332+ if (result_.r0 > 0 ) {
333+ ::Release (result_.r0);
334+ }
295335 Callback ().Call ({env.Null (), obj});
296336 }
297337private:
298338 int64_t poolId_, connId_, rowsId_;
299339 Metadata_return result_;
300340};
301341
342+ //
343+ // Worker 8: CloseRows asynchronously
344+ //
345+ class CloseRowsWorker : public Napi ::AsyncWorker {
346+ public:
347+ CloseRowsWorker (Napi::Function& callback, int64_t poolId, int64_t connId, int64_t rowsId)
348+ : AsyncWorker(callback), poolId_(poolId), connId_(connId), rowsId_(rowsId), result_({0 , 0 , 0 , 0 , nullptr }) {}
349+
350+ void Execute () override {
351+ result_ = ::CloseRows (poolId_, connId_, rowsId_);
352+ }
353+
354+ void OnOK () override {
355+ Napi::Env env = Env ();
356+ Napi::Object obj = Napi::Object::New (env);
357+ obj.Set (" r0" , Napi::Number::New (env, result_.r0 ));
358+ obj.Set (" r1" , Napi::Number::New (env, result_.r1 ));
359+ obj.Set (" r2" , Napi::Number::New (env, result_.r2 ));
360+ obj.Set (" r3" , Napi::Number::New (env, result_.r3 ));
361+ if (result_.r4 != nullptr && result_.r3 > 0 ) {
362+ obj.Set (" r4" , Napi::Buffer<uint8_t >::Copy (env, (uint8_t *)result_.r4 , result_.r3 ));
363+ } else {
364+ obj.Set (" r4" , env.Null ());
365+ }
366+ // Release the pinner ID of the response message to prevent native leak!
367+ if (result_.r0 > 0 ) {
368+ ::Release (result_.r0);
369+ }
370+ Callback ().Call ({env.Null (), obj});
371+ }
372+ private:
373+ int64_t poolId_, connId_, rowsId_;
374+ CloseRows_return result_;
375+ };
376+
302377Napi::Value MetadataWrapper (const Napi::CallbackInfo& info) {
303378 Napi::Env env = info.Env ();
379+ if (info.Length () < 4 ) {
380+ Napi::Error::New (env, " MetadataWrapper requires 4 arguments" ).ThrowAsJavaScriptException ();
381+ return env.Null ();
382+ }
304383 int64_t pid = info[0 ].As <Napi::Number>().Int64Value ();
305384 int64_t cid = info[1 ].As <Napi::Number>().Int64Value ();
306385 int64_t rid = info[2 ].As <Napi::Number>().Int64Value ();
@@ -323,21 +402,17 @@ Napi::Value NativeRelease(const Napi::CallbackInfo& info) {
323402// CloseRows dummy/missing implementation for POC length if needed, or we just rely on GC.
324403Napi::Value CloseRowsWrapper (const Napi::CallbackInfo& info) {
325404 Napi::Env env = info.Env ();
326- if (info.Length () < 3 ) return env.Null ();
405+ if (info.Length () < 4 ) {
406+ Napi::Error::New (env, " CloseRowsWrapper requires 4 arguments" ).ThrowAsJavaScriptException ();
407+ return env.Null ();
408+ }
327409 int64_t pid = info[0 ].As <Napi::Number>().Int64Value ();
328410 int64_t cid = info[1 ].As <Napi::Number>().Int64Value ();
329411 int64_t rid = info[2 ].As <Napi::Number>().Int64Value ();
412+ Napi::Function cb = info[3 ].As <Napi::Function>();
330413
331- // N-API sync close implementation
332- CloseRows (pid, cid, rid);
333-
334- // invokeAsync appends a callback at the end of properties
335- if (info.Length () >= 4 && info[3 ].IsFunction ()) {
336- Napi::Object obj = Napi::Object::New (env);
337- obj.Set (" r1" , Napi::Number::New (env, 0 ));
338- Napi::Function cb = info[3 ].As <Napi::Function>();
339- cb.Call ({env.Null (), obj}); // Mock empty GoReturnTuple callback
340- }
414+ CloseRowsWorker* worker = new CloseRowsWorker (cb, pid, cid, rid);
415+ worker->Queue ();
341416 return env.Undefined ();
342417}
343418
0 commit comments