@@ -260,6 +260,7 @@ static napi_status CallFunction (napi_env env,
260260 *
261261 * - DoExecute (abstract, worker pool thread): main work
262262 * - HandleOKCallback (main thread): call JS callback on success
263+ * - HandleErrorCallback (main thread): call JS callback on error
263264 * - DoFinally (main thread): do cleanup regardless of success
264265 */
265266struct BaseWorker {
@@ -310,48 +311,52 @@ struct BaseWorker {
310311 }
311312
312313 virtual void DoExecute () = 0;
313- virtual void DoFinally (napi_env env) {};
314314
315315 static void Complete (napi_env env, napi_status status, void * data) {
316316 BaseWorker* self = (BaseWorker*)data;
317317
318318 self->DoComplete (env);
319319 self->DoFinally (env);
320-
321- napi_delete_reference (env, self->callbackRef_ );
322- napi_delete_async_work (env, self->asyncWork_ );
323-
324- delete self;
325320 }
326321
327322 void DoComplete (napi_env env) {
328- if (status_.ok ()) {
329- return HandleOKCallback (env);
330- }
331-
332- napi_value argv = CreateError (env, errMsg_);
333323 napi_value callback;
334324 napi_get_reference_value (env, callbackRef_, &callback);
335- CallFunction (env, callback, 1 , &argv);
325+
326+ if (status_.ok ()) {
327+ HandleOKCallback (env, callback);
328+ } else {
329+ HandleErrorCallback (env, callback);
330+ }
336331 }
337332
338- virtual void HandleOKCallback (napi_env env) {
333+ virtual void HandleOKCallback (napi_env env, napi_value callback ) {
339334 napi_value argv;
340335 napi_get_null (env, &argv);
341- napi_value callback;
342- napi_get_reference_value (env, callbackRef_, &callback);
343336 CallFunction (env, callback, 1 , &argv);
344337 }
345338
339+ virtual void HandleErrorCallback (napi_env env, napi_value callback) {
340+ napi_value argv = CreateError (env, errMsg_);
341+ CallFunction (env, callback, 1 , &argv);
342+ }
343+
344+ virtual void DoFinally (napi_env env) {
345+ napi_delete_reference (env, callbackRef_);
346+ napi_delete_async_work (env, asyncWork_);
347+
348+ delete this ;
349+ }
350+
346351 void Queue (napi_env env) {
347352 napi_queue_async_work (env, asyncWork_);
348353 }
349354
350- napi_ref callbackRef_;
351- napi_async_work asyncWork_;
352355 Database* database_;
353356
354357private:
358+ napi_ref callbackRef_;
359+ napi_async_work asyncWork_;
355360 leveldb::Status status_;
356361 char *errMsg_;
357362};
@@ -491,6 +496,7 @@ struct PriorityWorker : public BaseWorker {
491496
492497 void DoFinally (napi_env env) override {
493498 database_->DecrementPriorityWork (env);
499+ BaseWorker::DoFinally (env);
494500 }
495501};
496502
@@ -507,7 +513,6 @@ struct BaseIterator {
507513 int limit,
508514 bool fillCache)
509515 : database_(database),
510- isEnding_ (false ),
511516 hasEnded_ (false ),
512517 didSeek_(false ),
513518 reverse_(reverse),
@@ -669,7 +674,6 @@ struct BaseIterator {
669674 }
670675
671676 Database* database_;
672- bool isEnding_;
673677 bool hasEnded_;
674678
675679private:
@@ -713,6 +717,7 @@ struct Iterator final : public BaseIterator {
713717 highWaterMark_(highWaterMark),
714718 landed_(false ),
715719 nexting_(false ),
720+ isEnding_(false ),
716721 endWorker_(NULL ),
717722 ref_(NULL ) {
718723 }
@@ -729,15 +734,6 @@ struct Iterator final : public BaseIterator {
729734 if (ref_ != NULL ) napi_delete_reference (env, ref_);
730735 }
731736
732- void CheckEndCallback (napi_env env) {
733- nexting_ = false ;
734-
735- if (endWorker_ != NULL ) {
736- endWorker_->Queue (env);
737- endWorker_ = NULL ;
738- }
739- }
740-
741737 bool ReadMany (uint32_t size, std::vector<std::pair<std::string, std::string>>& result) {
742738 size_t bytesRead = 0 ;
743739
@@ -780,6 +776,7 @@ struct Iterator final : public BaseIterator {
780776 uint32_t highWaterMark_;
781777 bool landed_;
782778 bool nexting_;
779+ bool isEnding_;
783780 BaseWorker* endWorker_;
784781
785782private:
@@ -1043,7 +1040,7 @@ struct GetWorker final : public PriorityWorker {
10431040 SetStatus (database_->Get (options_, key_, value_));
10441041 }
10451042
1046- void HandleOKCallback (napi_env env) override {
1043+ void HandleOKCallback (napi_env env, napi_value callback ) override {
10471044 napi_value argv[2 ];
10481045 napi_get_null (env, &argv[0 ]);
10491046
@@ -1053,8 +1050,6 @@ struct GetWorker final : public PriorityWorker {
10531050 napi_create_string_utf8 (env, value_.data (), value_.size (), &argv[1 ]);
10541051 }
10551052
1056- napi_value callback;
1057- napi_get_reference_value (env, callbackRef_, &callback);
10581053 CallFunction (env, callback, 2 , argv);
10591054 }
10601055
@@ -1233,12 +1228,10 @@ struct ApproximateSizeWorker final : public PriorityWorker {
12331228 size_ = database_->ApproximateSize (&range);
12341229 }
12351230
1236- void HandleOKCallback (napi_env env) override {
1231+ void HandleOKCallback (napi_env env, napi_value callback ) override {
12371232 napi_value argv[2 ];
12381233 napi_get_null (env, &argv[0 ]);
12391234 napi_create_int64 (env, (uint64_t )size_, &argv[1 ]);
1240- napi_value callback;
1241- napi_get_reference_value (env, callbackRef_, &callback);
12421235 CallFunction (env, callback, 2 , argv);
12431236 }
12441237
@@ -1486,10 +1479,9 @@ struct EndWorker final : public BaseWorker {
14861479 iterator_->End ();
14871480 }
14881481
1489- void HandleOKCallback (napi_env env) override {
1490- // TODO: would this be safe(r) to do in DoFinally() i.e. after we call the callback?
1482+ void DoFinally (napi_env env) override {
14911483 iterator_->Detach (env);
1492- BaseWorker::HandleOKCallback (env);
1484+ BaseWorker::DoFinally (env);
14931485 }
14941486
14951487 Iterator* iterator_;
@@ -1551,7 +1543,7 @@ struct NextWorker final : public BaseWorker {
15511543 }
15521544 }
15531545
1554- void HandleOKCallback (napi_env env) override {
1546+ void HandleOKCallback (napi_env env, napi_value callback ) override {
15551547 size_t arraySize = result_.size () * 2 ;
15561548 napi_value jsArray;
15571549 napi_create_array_with_length (env, arraySize, &jsArray);
@@ -1580,19 +1572,25 @@ struct NextWorker final : public BaseWorker {
15801572 napi_set_element (env, jsArray, static_cast <int >(arraySize - idx * 2 - 2 ), returnValue);
15811573 }
15821574
1583- // clean up & handle the next/end state
1584- // TODO: always do this, even on error
1585- iterator_->CheckEndCallback (env);
1586-
15871575 napi_value argv[3 ];
15881576 napi_get_null (env, &argv[0 ]);
15891577 argv[1 ] = jsArray;
15901578 napi_get_boolean (env, !ok_, &argv[2 ]);
1591- napi_value callback;
1592- napi_get_reference_value (env, callbackRef_, &callback);
15931579 CallFunction (env, callback, 3 , argv);
15941580 }
15951581
1582+ void DoFinally (napi_env env) override {
1583+ // clean up & handle the next/end state
1584+ iterator_->nexting_ = false ;
1585+
1586+ if (iterator_->endWorker_ != NULL ) {
1587+ iterator_->endWorker_ ->Queue (env);
1588+ iterator_->endWorker_ = NULL ;
1589+ }
1590+
1591+ BaseWorker::DoFinally (env);
1592+ }
1593+
15961594 Iterator* iterator_;
15971595 std::vector<std::pair<std::string, std::string> > result_;
15981596 bool ok_;
0 commit comments