Skip to content

Commit 3da380b

Browse files
committed
src: make OnWorkComplete and OnExecute override-able
No breaking changes on existing code were expected. All existing tests shall pass without any touch. Changes on declaration: - Added `Napi::AsyncWorker::OnWorkComplete`. - Added `Napi::AsyncWorker::OnExecute`.
1 parent 9e0e0f3 commit 3da380b

File tree

3 files changed

+88
-51
lines changed

3 files changed

+88
-51
lines changed

doc/async_worker.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,30 @@ class was created, passing in the error as the first parameter.
136136
virtual void Napi::AsyncWorker::OnError(const Napi::Error& e);
137137
```
138138

139+
### OnWorkComplete
140+
141+
This method is invoked after the work has completed on the JavaScript thread.
142+
The default implementation of this method checks the status of the work and
143+
tries to dispatch the result to `Napi::AsyncWorker::OnOk` or `Napi::AsyncWorker::Error`
144+
if the work has committed an error. If the work was cancelled, neither
145+
`Napi::AsyncWorker::OnOk` nor `Napi::AsyncWorker::Error` will be invoked.
146+
After the result is dispatched, the default implementation will call into
147+
`Napi::AsyncWorker::Destroy` if `SuppressDestruct()` was not called.
148+
149+
```cpp
150+
virtual void OnWorkComplete(Napi::Env env, napi_status status);
151+
```
152+
153+
### OnExecute
154+
155+
This method is invoked immediately on the work thread when scheduled.
156+
The default implementation of this method just calls the `Napi::AsyncWorker::Execute` method
157+
and handles exceptions if cpp exceptions were enabled.
158+
159+
```cpp
160+
virtual void OnExecute(Napi::Env env);
161+
```
162+
139163
### Destroy
140164

141165
This method is invoked when the instance must be deallocated. If

napi-inl.h

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4085,8 +4085,8 @@ inline AsyncWorker::AsyncWorker(const Object& receiver,
40854085
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
40864086
NAPI_THROW_IF_FAILED_VOID(_env, status);
40874087

4088-
status = napi_create_async_work(_env, resource, resource_id, OnExecute,
4089-
OnWorkComplete, this, &_work);
4088+
status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
4089+
OnAsyncWorkComplete, this, &_work);
40904090
NAPI_THROW_IF_FAILED_VOID(_env, status);
40914091
}
40924092

@@ -4111,8 +4111,8 @@ inline AsyncWorker::AsyncWorker(Napi::Env env,
41114111
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
41124112
NAPI_THROW_IF_FAILED_VOID(_env, status);
41134113

4114-
status = napi_create_async_work(_env, resource, resource_id, OnExecute,
4115-
OnWorkComplete, this, &_work);
4114+
status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
4115+
OnAsyncWorkComplete, this, &_work);
41164116
NAPI_THROW_IF_FAILED_VOID(_env, status);
41174117
}
41184118

@@ -4199,40 +4199,51 @@ inline void AsyncWorker::SetError(const std::string& error) {
41994199
inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
42004200
return {};
42014201
}
4202+
// The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT
4203+
// use it within this method, as it does not run on the main thread and must
4204+
// not run any method that would cause JavaScript to run. In practice, this
4205+
// means that almost any use of napi_env will be incorrect.
4206+
inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) {
4207+
AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
4208+
self->OnExecute(env);
4209+
}
42024210
// The OnExecute method receives an napi_env argument. However, do NOT
42034211
// use it within this method, as it does not run on the main thread and must
42044212
// not run any method that would cause JavaScript to run. In practice, this
42054213
// means that almost any use of napi_env will be incorrect.
4206-
inline void AsyncWorker::OnExecute(napi_env /*DO_NOT_USE*/, void* this_pointer) {
4207-
AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
4214+
inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) {
42084215
#ifdef NAPI_CPP_EXCEPTIONS
42094216
try {
4210-
self->Execute();
4217+
this->Execute();
42114218
} catch (const std::exception& e) {
4212-
self->SetError(e.what());
4219+
this->SetError(e.what());
42134220
}
42144221
#else // NAPI_CPP_EXCEPTIONS
4215-
self->Execute();
4222+
this->Execute();
42164223
#endif // NAPI_CPP_EXCEPTIONS
42174224
}
42184225

4219-
inline void AsyncWorker::OnWorkComplete(
4220-
napi_env /*env*/, napi_status status, void* this_pointer) {
4221-
AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
4226+
inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
4227+
napi_status status,
4228+
void* asyncworker) {
4229+
AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
4230+
self->OnWorkComplete(env, status);
4231+
}
4232+
inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
42224233
if (status != napi_cancelled) {
4223-
HandleScope scope(self->_env);
4234+
HandleScope scope(this->_env);
42244235
details::WrapCallback([&] {
4225-
if (self->_error.size() == 0) {
4226-
self->OnOK();
4236+
if (this->_error.size() == 0) {
4237+
this->OnOK();
42274238
}
42284239
else {
4229-
self->OnError(Error::New(self->_env, self->_error));
4240+
this->OnError(Error::New(this->_env, this->_error));
42304241
}
42314242
return nullptr;
42324243
});
42334244
}
4234-
if (!self->_suppress_destruct) {
4235-
self->Destroy();
4245+
if (!this->_suppress_destruct) {
4246+
this->Destroy();
42364247
}
42374248
}
42384249

@@ -4597,14 +4608,14 @@ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
45974608

45984609
template<class T>
45994610
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
4600-
const Function& callback)
4611+
const Function& callback)
46014612
: AsyncProgressWorker(receiver, callback, "generic") {
46024613
}
46034614

46044615
template<class T>
46054616
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
4606-
const Function& callback,
4607-
const char* resource_name)
4617+
const Function& callback,
4618+
const char* resource_name)
46084619
: AsyncProgressWorker(receiver,
46094620
callback,
46104621
resource_name,
@@ -4630,14 +4641,14 @@ inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
46304641

46314642
template<class T>
46324643
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
4633-
const char* resource_name)
4644+
const char* resource_name)
46344645
: AsyncProgressWorker(env, resource_name, Object::New(env)) {
46354646
}
46364647

46374648
template<class T>
46384649
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
4639-
const char* resource_name,
4640-
const Object& resource)
4650+
const char* resource_name,
4651+
const Object& resource)
46414652
: AsyncWorker(env, resource_name, resource),
46424653
_asyncdata(nullptr),
46434654
_asyncsize(0) {
@@ -4716,7 +4727,6 @@ template<class T>
47164727
inline void AsyncProgressWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
47174728
_worker->SendProgress_(data, count);
47184729
}
4719-
47204730
#endif
47214731

47224732
////////////////////////////////////////////////////////////////////////////////

napi.h

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,10 @@ namespace Napi {
19831983
ObjectReference& Receiver();
19841984
FunctionReference& Callback();
19851985

1986+
virtual void OnExecute(Napi::Env env);
1987+
virtual void OnWorkComplete(Napi::Env env,
1988+
napi_status status);
1989+
19861990
protected:
19871991
explicit AsyncWorker(const Function& callback);
19881992
explicit AsyncWorker(const Function& callback,
@@ -2016,10 +2020,10 @@ namespace Napi {
20162020
void SetError(const std::string& error);
20172021

20182022
private:
2019-
static void OnExecute(napi_env env, void* this_pointer);
2020-
static void OnWorkComplete(napi_env env,
2021-
napi_status status,
2022-
void* this_pointer);
2023+
static inline void OnAsyncWorkExecute(napi_env env, void* asyncworker);
2024+
static inline void OnAsyncWorkComplete(napi_env env,
2025+
napi_status status,
2026+
void* asyncworker);
20232027

20242028
napi_env _env;
20252029
napi_async_work _work;
@@ -2251,33 +2255,32 @@ namespace Napi {
22512255
};
22522256

22532257
protected:
2254-
explicit AsyncProgressWorker(const Function& callback);
2255-
explicit AsyncProgressWorker(const Function& callback,
2256-
const char* resource_name);
2257-
explicit AsyncProgressWorker(const Function& callback,
2258-
const char* resource_name,
2259-
const Object& resource);
2260-
explicit AsyncProgressWorker(const Object& receiver,
2261-
const Function& callback);
2262-
explicit AsyncProgressWorker(const Object& receiver,
2263-
const Function& callback,
2264-
const char* resource_name);
2265-
explicit AsyncProgressWorker(const Object& receiver,
2266-
const Function& callback,
2267-
const char* resource_name,
2268-
const Object& resource);
2258+
explicit AsyncProgressWorker(const Function& callback);
2259+
explicit AsyncProgressWorker(const Function& callback,
2260+
const char* resource_name);
2261+
explicit AsyncProgressWorker(const Function& callback,
2262+
const char* resource_name,
2263+
const Object& resource);
2264+
explicit AsyncProgressWorker(const Object& receiver,
2265+
const Function& callback);
2266+
explicit AsyncProgressWorker(const Object& receiver,
2267+
const Function& callback,
2268+
const char* resource_name);
2269+
explicit AsyncProgressWorker(const Object& receiver,
2270+
const Function& callback,
2271+
const char* resource_name,
2272+
const Object& resource);
22692273

22702274
// Optional callback of Napi::ThreadSafeFunction only available after NAPI_VERSION 4.
22712275
// Refs: https://github.com/nodejs/node/pull/27791
22722276
#if NAPI_VERSION > 4
2273-
explicit AsyncProgressWorker(Napi::Env env);
2274-
explicit AsyncProgressWorker(Napi::Env env,
2275-
const char* resource_name);
2276-
explicit AsyncProgressWorker(Napi::Env env,
2277-
const char* resource_name,
2278-
const Object& resource);
2277+
explicit AsyncProgressWorker(Napi::Env env);
2278+
explicit AsyncProgressWorker(Napi::Env env,
2279+
const char* resource_name);
2280+
explicit AsyncProgressWorker(Napi::Env env,
2281+
const char* resource_name,
2282+
const Object& resource);
22792283
#endif
2280-
22812284
virtual void Execute(const ExecutionProgress& progress) = 0;
22822285
virtual void OnProgress(const T* data, size_t count) = 0;
22832286

0 commit comments

Comments
 (0)