@homaiohq/napi-quickfix 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +135 -0
- package/LICENSE +21 -0
- package/README.md +638 -2
- package/THIRD_PARTY_LICENSES +48 -0
- package/cpp/acceptor_wrap.cpp +468 -0
- package/cpp/acceptor_wrap.h +116 -0
- package/cpp/addon.cpp +87 -0
- package/cpp/application_bridge.cpp +466 -0
- package/cpp/application_bridge.h +204 -0
- package/cpp/data_dictionary_wrap.cpp +165 -0
- package/cpp/data_dictionary_wrap.h +59 -0
- package/cpp/engine_common.cpp +5 -0
- package/cpp/engine_common.h +127 -0
- package/cpp/engine_workers.h +167 -0
- package/cpp/errors.h +142 -0
- package/cpp/field_map_ops.h +492 -0
- package/cpp/group_wrap.cpp +221 -0
- package/cpp/group_wrap.h +76 -0
- package/cpp/initiator_wrap.cpp +492 -0
- package/cpp/initiator_wrap.h +104 -0
- package/cpp/message_wrap.cpp +288 -0
- package/cpp/message_wrap.h +95 -0
- package/cpp/session_id_wrap.cpp +91 -0
- package/cpp/session_id_wrap.h +46 -0
- package/cpp/session_op_gate.h +201 -0
- package/cpp/session_settings_wrap.cpp +98 -0
- package/cpp/session_settings_wrap.h +40 -0
- package/cpp/session_static.cpp +220 -0
- package/cpp/session_wrap.cpp +438 -0
- package/cpp/session_wrap.h +144 -0
- package/dist/cjs/acceptor.d.ts +29 -0
- package/dist/cjs/acceptor.js +38 -0
- package/dist/cjs/application.d.ts +115 -0
- package/dist/cjs/application.js +62 -0
- package/dist/cjs/data-dictionary.d.ts +67 -0
- package/dist/cjs/data-dictionary.js +105 -0
- package/dist/cjs/engine.d.ts +152 -0
- package/dist/cjs/engine.js +183 -0
- package/dist/cjs/enums.d.ts +56 -0
- package/dist/cjs/enums.js +44 -0
- package/dist/cjs/field-value.d.ts +12 -0
- package/dist/cjs/field-value.js +40 -0
- package/dist/cjs/generated/fields.d.ts +6122 -0
- package/dist/cjs/generated/fields.js +6127 -0
- package/dist/cjs/generated/values.d.ts +8548 -0
- package/dist/cjs/generated/values.js +8580 -0
- package/dist/cjs/group.d.ts +126 -0
- package/dist/cjs/group.js +185 -0
- package/dist/cjs/index.d.ts +68 -0
- package/dist/cjs/index.js +73 -0
- package/dist/cjs/initiator.d.ts +29 -0
- package/dist/cjs/initiator.js +38 -0
- package/dist/cjs/load-native.cjs +5 -0
- package/dist/cjs/message.d.ts +238 -0
- package/dist/cjs/message.js +299 -0
- package/dist/cjs/native.d.ts +325 -0
- package/dist/cjs/native.js +22 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/session-id.d.ts +51 -0
- package/dist/cjs/session-id.js +87 -0
- package/dist/cjs/session-settings.d.ts +46 -0
- package/dist/cjs/session-settings.js +75 -0
- package/dist/cjs/session.d.ts +213 -0
- package/dist/cjs/session.js +337 -0
- package/dist/esm/acceptor.d.ts +29 -0
- package/dist/esm/acceptor.js +34 -0
- package/dist/esm/application.d.ts +115 -0
- package/dist/esm/application.js +57 -0
- package/dist/esm/data-dictionary.d.ts +67 -0
- package/dist/esm/data-dictionary.js +101 -0
- package/dist/esm/engine.d.ts +152 -0
- package/dist/esm/engine.js +179 -0
- package/dist/esm/enums.d.ts +56 -0
- package/dist/esm/enums.js +35 -0
- package/dist/esm/field-value.d.ts +12 -0
- package/dist/esm/field-value.js +37 -0
- package/dist/esm/generated/fields.d.ts +6122 -0
- package/dist/esm/generated/fields.js +6124 -0
- package/dist/esm/generated/values.d.ts +8548 -0
- package/dist/esm/generated/values.js +8564 -0
- package/dist/esm/group.d.ts +126 -0
- package/dist/esm/group.js +181 -0
- package/dist/esm/index.d.ts +68 -0
- package/dist/esm/index.js +43 -0
- package/dist/esm/initiator.d.ts +29 -0
- package/dist/esm/initiator.js +34 -0
- package/dist/esm/load-native.cjs +5 -0
- package/dist/esm/message.d.ts +238 -0
- package/dist/esm/message.js +293 -0
- package/dist/esm/native.d.ts +325 -0
- package/dist/esm/native.js +16 -0
- package/dist/esm/session-id.d.ts +51 -0
- package/dist/esm/session-id.js +82 -0
- package/dist/esm/session-settings.d.ts +46 -0
- package/dist/esm/session-settings.js +71 -0
- package/dist/esm/session.d.ts +213 -0
- package/dist/esm/session.js +329 -0
- package/package.json +95 -4
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/darwin-x64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/load-native.cjs +5 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#ifndef NAPI_QUICKFIX_ENGINE_WORKERS_H
|
|
2
|
+
#define NAPI_QUICKFIX_ENGINE_WORKERS_H
|
|
3
|
+
|
|
4
|
+
#include <napi.h>
|
|
5
|
+
|
|
6
|
+
#include <condition_variable>
|
|
7
|
+
#include <functional>
|
|
8
|
+
#include <memory>
|
|
9
|
+
#include <mutex>
|
|
10
|
+
#include <utility>
|
|
11
|
+
|
|
12
|
+
#include "errors.h"
|
|
13
|
+
|
|
14
|
+
namespace napi_quickfix {
|
|
15
|
+
|
|
16
|
+
// One-shot completion signal from a libuv worker to the JS thread. The stop
|
|
17
|
+
// worker signals it once its operation (FIX stop() + gate freeze) has
|
|
18
|
+
// returned, success or not; the wrap's Teardown() waits on it rather than
|
|
19
|
+
// destroying the engine under an operation that may still be running it.
|
|
20
|
+
class StopCompletion {
|
|
21
|
+
public:
|
|
22
|
+
void Signal() {
|
|
23
|
+
{
|
|
24
|
+
std::lock_guard<std::mutex> lock(mtx_);
|
|
25
|
+
done_ = true;
|
|
26
|
+
}
|
|
27
|
+
cv_.notify_all();
|
|
28
|
+
}
|
|
29
|
+
void Wait() {
|
|
30
|
+
std::unique_lock<std::mutex> lock(mtx_);
|
|
31
|
+
cv_.wait(lock, [this] { return done_; });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private:
|
|
35
|
+
std::mutex mtx_;
|
|
36
|
+
std::condition_variable cv_;
|
|
37
|
+
bool done_ = false;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// A generic AsyncWorker that runs a blocking QuickFIX engine operation
|
|
41
|
+
// (start/stop) on a libuv worker thread and resolves/rejects a JS Promise.
|
|
42
|
+
// (The per-message SendToTargetWorker lives in session_static.cpp.)
|
|
43
|
+
//
|
|
44
|
+
// Why off-thread: start()/stop() synchronously invoke FIX::Application callbacks
|
|
45
|
+
// (toAdmin/toApp during send-on-logon, onLogout during stop) which the
|
|
46
|
+
// ApplicationBridge dispatches back to the JS thread via a TSFN BlockingCall +
|
|
47
|
+
// future. If the operation ran ON the JS thread, the event loop couldn't service
|
|
48
|
+
// the TSFN trampoline and we'd deadlock. Running it on a worker thread keeps the
|
|
49
|
+
// main event loop free to run CallJs.
|
|
50
|
+
//
|
|
51
|
+
// Lifetime: the worker holds a Napi::ObjectReference to the owning wrap object so
|
|
52
|
+
// it (and its bridge / engine / factories) can't be GC'd while the op is in
|
|
53
|
+
// flight. The reference is released when the promise is settled -- through
|
|
54
|
+
// the Settlement handed to onSettled, which the wrap may settle later than
|
|
55
|
+
// OnOK (on the JS thread) when the promise has to wait for deferred work,
|
|
56
|
+
// e.g. an engine destruction queued behind the bridge's pending callbacks.
|
|
57
|
+
class EngineOpWorker : public Napi::AsyncWorker {
|
|
58
|
+
public:
|
|
59
|
+
// The promise plus the owner reference, moved out of the worker (which
|
|
60
|
+
// deletes itself once OnOK/OnError returns) so settling can outlive it.
|
|
61
|
+
class Settlement {
|
|
62
|
+
public:
|
|
63
|
+
Settlement(Napi::Promise::Deferred deferred, Napi::ObjectReference ownerRef,
|
|
64
|
+
CapturedError err)
|
|
65
|
+
: deferred_(std::move(deferred)),
|
|
66
|
+
ownerRef_(std::move(ownerRef)),
|
|
67
|
+
err_(std::move(err)) {}
|
|
68
|
+
|
|
69
|
+
// Resolve, or reject with the error the op threw, and release the owner
|
|
70
|
+
// reference. JS thread only; idempotent.
|
|
71
|
+
void Settle() {
|
|
72
|
+
if (done_) return;
|
|
73
|
+
done_ = true;
|
|
74
|
+
Napi::Env env = deferred_.Env();
|
|
75
|
+
Napi::HandleScope scope(env);
|
|
76
|
+
if (err_.has) {
|
|
77
|
+
deferred_.Reject(err_.ToError(env).Value());
|
|
78
|
+
} else {
|
|
79
|
+
deferred_.Resolve(env.Undefined());
|
|
80
|
+
}
|
|
81
|
+
ownerRef_.Reset();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The environment is going away before the promise could be settled:
|
|
85
|
+
// leave the promise pending and the reference to the environment's own
|
|
86
|
+
// cleanup, touching nothing that may already be torn down.
|
|
87
|
+
void Abandon() {
|
|
88
|
+
if (done_) return;
|
|
89
|
+
done_ = true;
|
|
90
|
+
ownerRef_.SuppressDestruct();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private:
|
|
94
|
+
Napi::Promise::Deferred deferred_;
|
|
95
|
+
Napi::ObjectReference ownerRef_;
|
|
96
|
+
CapturedError err_;
|
|
97
|
+
bool done_ = false;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// onSettled(ok, settlement) runs on the JS thread once op() has returned
|
|
101
|
+
// (ok) or thrown (!ok). It must eventually Settle() (or Abandon()) the
|
|
102
|
+
// settlement -- right away, or later on the JS thread.
|
|
103
|
+
using OnSettled =
|
|
104
|
+
std::function<void(bool, const std::shared_ptr<Settlement>&)>;
|
|
105
|
+
|
|
106
|
+
EngineOpWorker(Napi::Env env, Napi::Object owner, std::function<void()> op,
|
|
107
|
+
OnSettled onSettled)
|
|
108
|
+
: Napi::AsyncWorker(env),
|
|
109
|
+
deferred_(Napi::Promise::Deferred::New(env)),
|
|
110
|
+
op_(std::move(op)),
|
|
111
|
+
onSettled_(std::move(onSettled)) {
|
|
112
|
+
ownerRef_ = Napi::Persistent(owner);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
Napi::Promise Promise() { return deferred_.Promise(); }
|
|
116
|
+
|
|
117
|
+
// Runs on a libuv worker thread. NO Napi/JS access allowed here.
|
|
118
|
+
void Execute() override {
|
|
119
|
+
try {
|
|
120
|
+
op_();
|
|
121
|
+
} catch (const std::exception& e) {
|
|
122
|
+
err_.Capture(e);
|
|
123
|
+
} catch (...) {
|
|
124
|
+
err_.has = true;
|
|
125
|
+
err_.message = "unknown native error";
|
|
126
|
+
err_.fixErrorName = "Error";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Runs on the JS thread.
|
|
131
|
+
void OnOK() override {
|
|
132
|
+
Napi::HandleScope scope(Env());
|
|
133
|
+
Dispatch();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Runs on the JS thread (only if AsyncWorker::SetError was used; we don't, so
|
|
137
|
+
// errors flow through OnOK — but provide OnError for completeness/safety).
|
|
138
|
+
void OnError(const Napi::Error& e) override {
|
|
139
|
+
Napi::HandleScope scope(Env());
|
|
140
|
+
err_.has = true;
|
|
141
|
+
err_.message = e.Message();
|
|
142
|
+
err_.fixErrorName = "Error";
|
|
143
|
+
Dispatch();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private:
|
|
147
|
+
void Dispatch() {
|
|
148
|
+
const bool ok = !err_.has;
|
|
149
|
+
auto settlement = std::make_shared<Settlement>(
|
|
150
|
+
std::move(deferred_), std::move(ownerRef_), std::move(err_));
|
|
151
|
+
if (onSettled_) {
|
|
152
|
+
onSettled_(ok, settlement);
|
|
153
|
+
} else {
|
|
154
|
+
settlement->Settle();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
Napi::Promise::Deferred deferred_;
|
|
159
|
+
Napi::ObjectReference ownerRef_;
|
|
160
|
+
std::function<void()> op_;
|
|
161
|
+
OnSettled onSettled_;
|
|
162
|
+
CapturedError err_;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
} // namespace napi_quickfix
|
|
166
|
+
|
|
167
|
+
#endif // NAPI_QUICKFIX_ENGINE_WORKERS_H
|
package/cpp/errors.h
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// C++ -> Napi::Error translation for the QuickFIX wrapper.
|
|
2
|
+
//
|
|
3
|
+
// Every wrapper method funnels caught exceptions through here so that JS sees a
|
|
4
|
+
// consistent Error shape:
|
|
5
|
+
// - name: "QuickFixError"
|
|
6
|
+
// - message: the exception's what()
|
|
7
|
+
// - fixError: a discriminator string. For FIX::Exception this is its `.type`
|
|
8
|
+
// (e.g. "Field not found: 35", "Configuration failed", ...) which
|
|
9
|
+
// is stable per concrete type; we ALSO set fixErrorName to the C++
|
|
10
|
+
// class name (e.g. "FieldNotFound") which is the value TS keys on.
|
|
11
|
+
// - detail: the exception's `.detail` when available.
|
|
12
|
+
//
|
|
13
|
+
// NAPI_CPP_EXCEPTIONS is enabled, so throwing a Napi::Error unwinds into a JS
|
|
14
|
+
// throw at the call boundary.
|
|
15
|
+
#ifndef NAPI_QUICKFIX_ERRORS_H
|
|
16
|
+
#define NAPI_QUICKFIX_ERRORS_H
|
|
17
|
+
|
|
18
|
+
#include <napi.h>
|
|
19
|
+
|
|
20
|
+
#include <exception>
|
|
21
|
+
#include <string>
|
|
22
|
+
|
|
23
|
+
#include "quickfix/Exceptions.h"
|
|
24
|
+
|
|
25
|
+
namespace napi_quickfix {
|
|
26
|
+
|
|
27
|
+
// Map a concrete FIX::Exception to a stable class-name discriminator. QuickFIX
|
|
28
|
+
// exceptions don't carry RTTI-friendly names, so we dynamic_cast the well-known
|
|
29
|
+
// concrete types (order: most-specific first is not required since they don't
|
|
30
|
+
// inherit from each other beyond Exception).
|
|
31
|
+
inline const char* FixErrorName(const FIX::Exception& e) {
|
|
32
|
+
if (dynamic_cast<const FIX::ConfigError*>(&e)) return "ConfigError";
|
|
33
|
+
if (dynamic_cast<const FIX::RuntimeError*>(&e)) return "RuntimeError";
|
|
34
|
+
if (dynamic_cast<const FIX::FieldNotFound*>(&e)) return "FieldNotFound";
|
|
35
|
+
if (dynamic_cast<const FIX::FieldConvertError*>(&e)) return "FieldConvertError";
|
|
36
|
+
if (dynamic_cast<const FIX::MessageParseError*>(&e)) return "MessageParseError";
|
|
37
|
+
if (dynamic_cast<const FIX::InvalidMessage*>(&e)) return "InvalidMessage";
|
|
38
|
+
if (dynamic_cast<const FIX::IncorrectDataFormat*>(&e)) return "IncorrectDataFormat";
|
|
39
|
+
if (dynamic_cast<const FIX::IncorrectTagValue*>(&e)) return "IncorrectTagValue";
|
|
40
|
+
if (dynamic_cast<const FIX::IncorrectMessageStructure*>(&e)) return "IncorrectMessageStructure";
|
|
41
|
+
if (dynamic_cast<const FIX::InvalidTagNumber*>(&e)) return "InvalidTagNumber";
|
|
42
|
+
if (dynamic_cast<const FIX::RequiredTagMissing*>(&e)) return "RequiredTagMissing";
|
|
43
|
+
if (dynamic_cast<const FIX::TagNotDefinedForMessage*>(&e)) return "TagNotDefinedForMessage";
|
|
44
|
+
if (dynamic_cast<const FIX::NoTagValue*>(&e)) return "NoTagValue";
|
|
45
|
+
if (dynamic_cast<const FIX::DuplicateFieldNumber*>(&e)) return "DuplicateFieldNumber";
|
|
46
|
+
if (dynamic_cast<const FIX::InvalidMessageType*>(&e)) return "InvalidMessageType";
|
|
47
|
+
if (dynamic_cast<const FIX::UnsupportedMessageType*>(&e)) return "UnsupportedMessageType";
|
|
48
|
+
if (dynamic_cast<const FIX::UnsupportedVersion*>(&e)) return "UnsupportedVersion";
|
|
49
|
+
if (dynamic_cast<const FIX::TagOutOfOrder*>(&e)) return "TagOutOfOrder";
|
|
50
|
+
if (dynamic_cast<const FIX::RepeatedTag*>(&e)) return "RepeatedTag";
|
|
51
|
+
if (dynamic_cast<const FIX::RepeatingGroupCountMismatch*>(&e)) return "RepeatingGroupCountMismatch";
|
|
52
|
+
if (dynamic_cast<const FIX::DoNotSend*>(&e)) return "DoNotSend";
|
|
53
|
+
if (dynamic_cast<const FIX::RejectLogon*>(&e)) return "RejectLogon";
|
|
54
|
+
if (dynamic_cast<const FIX::SessionNotFound*>(&e)) return "SessionNotFound";
|
|
55
|
+
if (dynamic_cast<const FIX::DataDictionaryNotFound*>(&e)) return "DataDictionaryNotFound";
|
|
56
|
+
if (dynamic_cast<const FIX::IOException*>(&e)) return "IOException";
|
|
57
|
+
if (dynamic_cast<const FIX::SocketException*>(&e)) return "SocketException";
|
|
58
|
+
return "FixException";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Build (but do not throw) a Napi::Error from a FIX::Exception.
|
|
62
|
+
inline Napi::Error MakeFixError(Napi::Env env, const FIX::Exception& e) {
|
|
63
|
+
Napi::Error err = Napi::Error::New(env, e.what());
|
|
64
|
+
err.Set("name", Napi::String::New(env, "QuickFixError"));
|
|
65
|
+
err.Set("fixError", Napi::String::New(env, e.type));
|
|
66
|
+
err.Set("fixErrorName", Napi::String::New(env, FixErrorName(e)));
|
|
67
|
+
err.Set("detail", Napi::String::New(env, e.detail));
|
|
68
|
+
return err;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Build (but do not throw) a Napi::Error from a generic std::exception.
|
|
72
|
+
inline Napi::Error MakeStdError(Napi::Env env, const std::exception& e) {
|
|
73
|
+
Napi::Error err = Napi::Error::New(env, e.what());
|
|
74
|
+
err.Set("name", Napi::String::New(env, "QuickFixError"));
|
|
75
|
+
err.Set("fixErrorName", Napi::String::New(env, "Error"));
|
|
76
|
+
return err;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// A plain-data capture of an exception's mapped fields, safe to carry across
|
|
80
|
+
// threads (an AsyncWorker's Execute() runs off the JS thread and MUST NOT touch
|
|
81
|
+
// Napi/JS). Populate it in a catch block on the worker thread, then rebuild a
|
|
82
|
+
// Napi::Error from it in OnError/OnOK (which run on the JS thread).
|
|
83
|
+
struct CapturedError {
|
|
84
|
+
bool has = false;
|
|
85
|
+
bool isFix = false;
|
|
86
|
+
std::string message; // what()
|
|
87
|
+
std::string fixError; // FIX::Exception::type (for FIX exceptions)
|
|
88
|
+
std::string fixErrorName; // stable class-name discriminator
|
|
89
|
+
std::string detail; // FIX::Exception::detail
|
|
90
|
+
|
|
91
|
+
void Capture(const std::exception& e) {
|
|
92
|
+
has = true;
|
|
93
|
+
message = e.what();
|
|
94
|
+
if (const auto* fe = dynamic_cast<const FIX::Exception*>(&e)) {
|
|
95
|
+
isFix = true;
|
|
96
|
+
fixError = fe->type;
|
|
97
|
+
fixErrorName = FixErrorName(*fe);
|
|
98
|
+
detail = fe->detail;
|
|
99
|
+
} else {
|
|
100
|
+
isFix = false;
|
|
101
|
+
fixErrorName = "Error";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Build (do not throw) a Napi::Error from the captured fields.
|
|
106
|
+
Napi::Error ToError(Napi::Env env) const {
|
|
107
|
+
Napi::Error err = Napi::Error::New(env, message);
|
|
108
|
+
err.Set("name", Napi::String::New(env, "QuickFixError"));
|
|
109
|
+
if (isFix) {
|
|
110
|
+
err.Set("fixError", Napi::String::New(env, fixError));
|
|
111
|
+
err.Set("fixErrorName", Napi::String::New(env, fixErrorName));
|
|
112
|
+
err.Set("detail", Napi::String::New(env, detail));
|
|
113
|
+
} else {
|
|
114
|
+
err.Set("fixErrorName", Napi::String::New(env, fixErrorName));
|
|
115
|
+
}
|
|
116
|
+
return err;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Translate a caught exception and throw the corresponding Napi::Error. Callers
|
|
121
|
+
// use this inside a catch block, e.g.:
|
|
122
|
+
// try { ... } catch (const std::exception& e) { TranslateAndThrow(env, e); }
|
|
123
|
+
[[noreturn]] inline void TranslateAndThrow(Napi::Env env, const std::exception& e) {
|
|
124
|
+
if (const auto* fe = dynamic_cast<const FIX::Exception*>(&e)) {
|
|
125
|
+
throw MakeFixError(env, *fe);
|
|
126
|
+
}
|
|
127
|
+
throw MakeStdError(env, e);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
} // namespace napi_quickfix
|
|
131
|
+
|
|
132
|
+
// Wrap a QuickFIX-calling body so any std::exception is converted to a JS throw.
|
|
133
|
+
// Usage:
|
|
134
|
+
// NQ_TRY(env) { ...quickfix calls that may throw... } NQ_CATCH(env)
|
|
135
|
+
// The body may `return` a Napi::Value normally.
|
|
136
|
+
#define NQ_TRY(env) try
|
|
137
|
+
#define NQ_CATCH(env) \
|
|
138
|
+
catch (const std::exception& _nq_e) { \
|
|
139
|
+
::napi_quickfix::TranslateAndThrow((env), _nq_e); \
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#endif // NAPI_QUICKFIX_ERRORS_H
|