mdbxmou 0.2.4 → 0.2.6
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/README.md +8 -2
- package/build.js +4 -3
- package/lib/async.d.cts +69 -0
- package/lib/async.d.mts +65 -0
- package/lib/index.d.mts +7 -0
- package/lib/nativemou.d.cts +4 -0
- package/lib/nativemou.d.mts +5 -0
- package/lib/types.d.ts +260 -0
- package/package.json +33 -6
- package/src/async/envmou_async.cpp +450 -0
- package/src/async/envmou_async.hpp +116 -0
- package/src/dbimou.hpp +3 -0
- package/src/envmou.cpp +1 -1
- package/src/txnmou.cpp +26 -124
- package/src/txnmou.hpp +18 -75
- package/src/typemou.hpp +85 -9
- package/src/valuemou.hpp +3 -2
package/src/txnmou.cpp
CHANGED
|
@@ -12,11 +12,6 @@ void txnmou::init(const char *class_name, Napi::Env env) {
|
|
|
12
12
|
InstanceMethod("openMap", &txnmou::open_map),
|
|
13
13
|
InstanceMethod("createMap", &txnmou::create_map),
|
|
14
14
|
InstanceMethod("isActive", &txnmou::is_active),
|
|
15
|
-
InstanceMethod("isTopLevel", &txnmou::is_top_level),
|
|
16
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
17
|
-
InstanceMethod("startTransaction", &txnmou::start_transaction),
|
|
18
|
-
InstanceMethod("getChildrenCount", &txnmou::get_children_count),
|
|
19
|
-
#endif
|
|
20
15
|
});
|
|
21
16
|
|
|
22
17
|
ctor = Napi::Persistent(func);
|
|
@@ -28,22 +23,14 @@ Napi::Value txnmou::commit(const Napi::CallbackInfo& info) {
|
|
|
28
23
|
|
|
29
24
|
try {
|
|
30
25
|
check();
|
|
31
|
-
|
|
32
|
-
// Проверяем активные дочерние транзакции
|
|
33
|
-
cleanup_children();
|
|
34
|
-
|
|
35
|
-
if (has_active_children()) {
|
|
36
|
-
throw std::runtime_error("txn: active child exist");
|
|
37
|
-
}
|
|
38
|
-
#endif // MDBX_TXN_HAS_CHILD
|
|
26
|
+
|
|
39
27
|
auto rc = mdbx_txn_commit(*this);
|
|
40
28
|
if (rc != MDBX_SUCCESS) {
|
|
41
29
|
throw Napi::Error::New(env, std::string("txn: ") + mdbx_strerror(rc));
|
|
42
30
|
}
|
|
43
31
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
txn_.reset();
|
|
32
|
+
dec_counter();
|
|
33
|
+
txn_.release();
|
|
47
34
|
} catch (const std::exception& e) {
|
|
48
35
|
throw Napi::Error::New(env, e.what());
|
|
49
36
|
}
|
|
@@ -56,27 +43,14 @@ Napi::Value txnmou::abort(const Napi::CallbackInfo& info) {
|
|
|
56
43
|
|
|
57
44
|
try {
|
|
58
45
|
check();
|
|
59
|
-
|
|
60
|
-
// Сначала отменяем все дочерние транзакции
|
|
61
|
-
cleanup_children();
|
|
62
|
-
|
|
63
|
-
for (const auto& child : children_) {
|
|
64
|
-
if (child && child->txn_ && !child->is_committed_ && !child->is_aborted_) {
|
|
65
|
-
try {
|
|
66
|
-
child->abort(info);
|
|
67
|
-
} catch (...) {
|
|
68
|
-
// Игнорируем ошибки при abort дочерних
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
#endif // MDBX_TXN_HAS_CHILD
|
|
46
|
+
|
|
73
47
|
auto rc = mdbx_txn_abort(*this);
|
|
74
48
|
if (rc != MDBX_SUCCESS) {
|
|
75
49
|
throw Napi::Error::New(env, std::string("txn: ") + mdbx_strerror(rc));
|
|
76
50
|
}
|
|
77
51
|
|
|
78
|
-
|
|
79
|
-
txn_.
|
|
52
|
+
dec_counter();
|
|
53
|
+
txn_.release();
|
|
80
54
|
} catch (const std::exception& e) {
|
|
81
55
|
throw Napi::Error::New(env, e.what());
|
|
82
56
|
}
|
|
@@ -84,6 +58,14 @@ Napi::Value txnmou::abort(const Napi::CallbackInfo& info) {
|
|
|
84
58
|
return env.Undefined();
|
|
85
59
|
}
|
|
86
60
|
|
|
61
|
+
// Уменьшает счетчик транзакций
|
|
62
|
+
void txnmou::dec_counter() noexcept
|
|
63
|
+
{
|
|
64
|
+
if (env_) {
|
|
65
|
+
--(*env_);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
87
69
|
Napi::Value txnmou::get_dbi(const Napi::CallbackInfo& info, db_mode db_mode)
|
|
88
70
|
{
|
|
89
71
|
Napi::Env env = info.Env();
|
|
@@ -115,7 +97,7 @@ Napi::Value txnmou::get_dbi(const Napi::CallbackInfo& info, db_mode db_mode)
|
|
|
115
97
|
if (arg0.IsString()) {
|
|
116
98
|
db_name = arg0.As<Napi::String>().Utf8Value();
|
|
117
99
|
key_mode = parse_key_mode(env, arg1, key_flag);
|
|
118
|
-
} else if (arg0.IsNumber()) {
|
|
100
|
+
} else if (arg0.IsNumber() || arg0.IsBigInt()) {
|
|
119
101
|
key_mode = parse_key_mode(env, arg0, key_flag);
|
|
120
102
|
value_mode = value_mode::parse(arg1);
|
|
121
103
|
} else {
|
|
@@ -126,25 +108,25 @@ Napi::Value txnmou::get_dbi(const Napi::CallbackInfo& info, db_mode db_mode)
|
|
|
126
108
|
auto arg0 = info[0];
|
|
127
109
|
if (arg0.IsString()) {
|
|
128
110
|
db_name = arg0.As<Napi::String>().Utf8Value();
|
|
129
|
-
} else {
|
|
111
|
+
} else if (arg0.IsNumber() || arg0.IsBigInt()) {
|
|
130
112
|
key_mode = parse_key_mode(env, arg0, key_flag);
|
|
113
|
+
} else {
|
|
114
|
+
throw Napi::Error::New(env, "Invalid argument type: expected string (db_name) or number (key_mode)");
|
|
131
115
|
}
|
|
132
|
-
} else {
|
|
133
|
-
throw Napi::Error::New(env, "Invalid number of arguments for get_dbi");
|
|
134
116
|
}
|
|
117
|
+
// arg_count == 0: используем значения по умолчанию (строковый ключ, default db)
|
|
135
118
|
|
|
136
119
|
check();
|
|
137
120
|
|
|
138
|
-
// создаем новый объект dbi
|
|
139
|
-
auto obj = dbimou::ctor.New({});
|
|
140
|
-
auto ptr = dbimou::Unwrap(obj);
|
|
141
|
-
|
|
142
121
|
MDBX_dbi dbi{};
|
|
143
122
|
auto flags = static_cast<MDBX_db_flags_t>(db_mode.val|key_mode.val|value_mode.val);
|
|
144
123
|
auto rc = mdbx_dbi_open(*this, db_name.empty() ? nullptr : db_name.c_str(), flags, &dbi);
|
|
145
124
|
if (rc != MDBX_SUCCESS) {
|
|
146
125
|
throw std::runtime_error(std::string("mdbx_dbi_open ") + mdbx_strerror(rc));
|
|
147
126
|
}
|
|
127
|
+
// создаем новый объект dbi
|
|
128
|
+
auto obj = dbimou::ctor.New({});
|
|
129
|
+
auto ptr = dbimou::Unwrap(obj);
|
|
148
130
|
ptr->attach(dbi, db_mode, key_mode,
|
|
149
131
|
value_mode, key_flag, value_flag);
|
|
150
132
|
return obj;
|
|
@@ -159,96 +141,16 @@ Napi::Value txnmou::get_dbi(const Napi::CallbackInfo& info, db_mode db_mode)
|
|
|
159
141
|
|
|
160
142
|
Napi::Value txnmou::is_active(const Napi::CallbackInfo& info) {
|
|
161
143
|
Napi::Env env = info.Env();
|
|
162
|
-
|
|
163
|
-
return Napi::Boolean::New(env, active);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
Napi::Value txnmou::is_top_level(const Napi::CallbackInfo& info) {
|
|
167
|
-
Napi::Env env = info.Env();
|
|
168
|
-
return Napi::Boolean::New(env, parent_ == nullptr);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
172
|
-
|
|
173
|
-
Napi::Value txnmou::start_transaction(const Napi::CallbackInfo& info) {
|
|
174
|
-
Napi::Env env = info.Env();
|
|
175
|
-
|
|
176
|
-
// Создаем новый объект txnmou для дочерней транзакции
|
|
177
|
-
auto child_obj = ctor.New({});
|
|
178
|
-
auto child_wrapper = txnmou::Unwrap(child_obj);
|
|
179
|
-
|
|
180
|
-
int rc{MDBX_SUCCESS};
|
|
181
|
-
try {
|
|
182
|
-
check();
|
|
183
|
-
|
|
184
|
-
MDBX_txn* child_txn;
|
|
185
|
-
auto rc = mdbx_txn_begin(*env_, txn_.get(), flags_, &child_txn);
|
|
186
|
-
if (rc != MDBX_SUCCESS) {
|
|
187
|
-
std::string flag_name = (flags_ == MDBX_TXN_RDONLY) ? "read" : "write";
|
|
188
|
-
throw Napi::Error::New(env, std::string("txn ") + flag_name + ": " + mdbx_strerror(rc));
|
|
189
|
-
}
|
|
190
|
-
child_wrapper->attach(*env_, child_txn, flags_, this);
|
|
191
|
-
} catch (const std::exception& e) {
|
|
192
|
-
throw Napi::Error::New(env, e.what());
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return child_obj;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
Napi::Value txnmou::get_children_count(const Napi::CallbackInfo& info) {
|
|
199
|
-
Napi::Env env = info.Env();
|
|
200
|
-
cleanup_children();
|
|
201
|
-
|
|
202
|
-
size_t active_count = 0;
|
|
203
|
-
for (const auto& child : children_) {
|
|
204
|
-
if (child && child->txn_ && !child->is_committed_ && !child->is_aborted_) {
|
|
205
|
-
active_count++;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return Napi::Number::New(env, static_cast<double>(active_count));
|
|
144
|
+
return Napi::Boolean::New(env, txn_ != nullptr);
|
|
210
145
|
}
|
|
211
146
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
void txnmou::attach(envmou& env, MDBX_txn* txn,
|
|
215
|
-
txn_mode mode, txnmou* parent)
|
|
147
|
+
void txnmou::attach(envmou& env, MDBX_txn* txn, txn_mode mode)
|
|
216
148
|
{
|
|
217
|
-
// увеличиваем счетчик транзакций в env
|
|
218
149
|
env_ = &env;
|
|
219
|
-
|
|
220
|
-
if (parent == nullptr) {
|
|
221
|
-
// Если родительская транзакция не указана, увеличиваем счетчик
|
|
222
|
-
++(*env_);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
parent_ = parent;
|
|
226
150
|
mode_ = mode;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
231
|
-
if (parent) {
|
|
232
|
-
parent->push_back(this);
|
|
233
|
-
}
|
|
234
|
-
#endif
|
|
151
|
+
|
|
152
|
+
++(*env_);
|
|
235
153
|
txn_.reset(txn);
|
|
236
154
|
}
|
|
237
155
|
|
|
238
|
-
void txnmou::free_txn::operator()(MDBX_txn* txn) const noexcept {
|
|
239
|
-
if (!that.is_committed_ && !that.is_aborted_) {
|
|
240
|
-
// Автоматический abort при деструкции
|
|
241
|
-
auto rc = mdbx_txn_abort(that);
|
|
242
|
-
if (rc != MDBX_SUCCESS) {
|
|
243
|
-
fprintf(stderr, "mdbx_txn_abort code: %d, msg: %s\n", rc, mdbx_strerror(rc));
|
|
244
|
-
}
|
|
245
|
-
that.is_aborted_ = true;
|
|
246
|
-
}
|
|
247
|
-
// уменьшаем счетчик транзакций (только родительских)
|
|
248
|
-
if (that.parent_ == nullptr) {
|
|
249
|
-
//fprintf(stderr, "free_txn: --env\n");
|
|
250
|
-
--(*that.env_);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
156
|
} // namespace mdbxmou
|
package/src/txnmou.hpp
CHANGED
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
#include "dbimou.hpp"
|
|
4
4
|
|
|
5
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
6
|
-
#include <vector>
|
|
7
|
-
#endif
|
|
8
|
-
|
|
9
5
|
namespace mdbxmou {
|
|
10
6
|
|
|
11
7
|
class envmou;
|
|
@@ -14,74 +10,21 @@ class txnmou final
|
|
|
14
10
|
: public Napi::ObjectWrap<txnmou>
|
|
15
11
|
{
|
|
16
12
|
private:
|
|
17
|
-
envmou* env_{nullptr};
|
|
18
|
-
// транзакция
|
|
19
|
-
struct free_txn {
|
|
20
|
-
txnmou& that;
|
|
21
|
-
void operator()(MDBX_txn* txn) const noexcept;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
free_txn erase_{*this};
|
|
25
|
-
std::unique_ptr<MDBX_txn, free_txn> txn_{nullptr, erase_};
|
|
26
|
-
|
|
27
|
-
// Иерархия транзакций
|
|
28
|
-
txnmou* parent_{nullptr};
|
|
29
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
30
|
-
std::vector<txnmou*> children_{};
|
|
31
|
-
#endif
|
|
32
|
-
|
|
33
|
-
// Флаг для отслеживания состояния
|
|
34
|
-
bool is_committed_{};
|
|
35
|
-
bool is_aborted_{};
|
|
36
|
-
|
|
37
|
-
// Сохраняем тип транзакции для создания дочерних того же типа
|
|
38
|
-
txn_mode mode_{};
|
|
13
|
+
envmou* env_{nullptr};
|
|
39
14
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
throw std::runtime_error("txn: already committed");
|
|
44
|
-
if (is_aborted_)
|
|
45
|
-
throw std::runtime_error("txn: already aborted");
|
|
46
|
-
}
|
|
15
|
+
std::unique_ptr<MDBX_txn,
|
|
16
|
+
txnmou_managed::free_txn> txn_{};
|
|
17
|
+
txn_mode mode_{};
|
|
47
18
|
|
|
48
|
-
void check() const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (!txn_)
|
|
53
|
-
throw std::runtime_error("txn: not initialized");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
57
|
-
// Проверка активных дочерних транзакций
|
|
58
|
-
bool has_active_children() const {
|
|
59
|
-
for (const auto& child : children_) {
|
|
60
|
-
if (child && child->txn_ && !child->is_committed_ && !child->is_aborted_) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
19
|
+
void check() const {
|
|
20
|
+
if (!txn_) {
|
|
21
|
+
throw std::runtime_error("txn: inactive");
|
|
63
22
|
}
|
|
64
|
-
return false;
|
|
65
23
|
}
|
|
66
24
|
|
|
67
|
-
//
|
|
68
|
-
void
|
|
69
|
-
children_.erase(
|
|
70
|
-
std::remove_if(children_.begin(), children_.end(),
|
|
71
|
-
[](const txnmou* child) {
|
|
72
|
-
return !child || child->is_committed_ || child->is_aborted_;
|
|
73
|
-
}),
|
|
74
|
-
children_.end()
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Общий метод для создания дочерних транзакций
|
|
79
|
-
Napi::Value start_transaction(const Napi::CallbackInfo& info, MDBX_txn_flags_t flags);
|
|
25
|
+
// Уменьшает счетчик транзакций
|
|
26
|
+
void dec_counter() noexcept;
|
|
80
27
|
|
|
81
|
-
void push_back(txnmou* child) {
|
|
82
|
-
children_.push_back(child);
|
|
83
|
-
}
|
|
84
|
-
#endif
|
|
85
28
|
Napi::Value get_dbi(const Napi::CallbackInfo&, db_mode);
|
|
86
29
|
|
|
87
30
|
public:
|
|
@@ -91,9 +34,16 @@ public:
|
|
|
91
34
|
: Napi::ObjectWrap<txnmou>(info)
|
|
92
35
|
{ }
|
|
93
36
|
|
|
37
|
+
~txnmou() {
|
|
38
|
+
if (txn_) {
|
|
39
|
+
dec_counter();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//void Finalize(Napi::Env env) { fprintf(stderr, "txnmou::Finalize %p\n", this); }
|
|
44
|
+
|
|
94
45
|
static void init(const char *class_name, Napi::Env env);
|
|
95
46
|
|
|
96
|
-
// Основные операции (только синхронные)
|
|
97
47
|
Napi::Value commit(const Napi::CallbackInfo&);
|
|
98
48
|
Napi::Value abort(const Napi::CallbackInfo&);
|
|
99
49
|
Napi::Value open_map(const Napi::CallbackInfo& info) {
|
|
@@ -107,16 +57,9 @@ public:
|
|
|
107
57
|
return txn_.get();
|
|
108
58
|
}
|
|
109
59
|
|
|
110
|
-
#ifdef MDBX_TXN_HAS_CHILD
|
|
111
|
-
// Работа с вложенными транзакциями
|
|
112
|
-
Napi::Value start_transaction(const Napi::CallbackInfo&);
|
|
113
|
-
Napi::Value get_children_count(const Napi::CallbackInfo&);
|
|
114
|
-
#endif
|
|
115
60
|
Napi::Value is_active(const Napi::CallbackInfo&);
|
|
116
|
-
Napi::Value is_top_level(const Napi::CallbackInfo&);
|
|
117
61
|
|
|
118
|
-
void attach(envmou& env, MDBX_txn* txn,
|
|
119
|
-
txn_mode mode, txnmou* parent = nullptr);
|
|
62
|
+
void attach(envmou& env, MDBX_txn* txn, txn_mode mode);
|
|
120
63
|
};
|
|
121
64
|
|
|
122
65
|
} // namespace mdbxmou
|
package/src/typemou.hpp
CHANGED
|
@@ -10,21 +10,97 @@ namespace mdbxmou {
|
|
|
10
10
|
using buffer_type = std::vector<char>;
|
|
11
11
|
|
|
12
12
|
struct txnmou_managed final
|
|
13
|
-
: mdbx::
|
|
13
|
+
: mdbx::txn
|
|
14
14
|
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
// свободу txn
|
|
16
|
+
struct free_txn
|
|
17
|
+
{
|
|
18
|
+
void operator()(MDBX_txn *txn) const noexcept {
|
|
19
|
+
mdbx_txn_abort(txn);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
std::unique_ptr<MDBX_txn, free_txn> guard_;
|
|
24
|
+
|
|
25
|
+
txnmou_managed(MDBX_txn* txn) noexcept
|
|
26
|
+
: mdbx::txn(txn)
|
|
27
|
+
, guard_(txn)
|
|
28
|
+
{ }
|
|
29
|
+
|
|
30
|
+
// Move конструктор
|
|
31
|
+
txnmou_managed(txnmou_managed&& other) noexcept
|
|
32
|
+
: mdbx::txn(other.txn::handle_)
|
|
33
|
+
, guard_(std::move(other.guard_))
|
|
34
|
+
{
|
|
35
|
+
other.txn::handle_ = nullptr;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Запрет копирования
|
|
39
|
+
txnmou_managed(const txnmou_managed&) = delete;
|
|
40
|
+
txnmou_managed& operator=(const txnmou_managed&) = delete;
|
|
41
|
+
|
|
42
|
+
~txnmou_managed() noexcept {
|
|
43
|
+
// guard_ автоматически откатит транзакцию
|
|
44
|
+
txn::handle_ = nullptr;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Commit транзакции
|
|
48
|
+
void commit() {
|
|
49
|
+
if (guard_) {
|
|
50
|
+
auto rc = ::mdbx_txn_commit(guard_.release());
|
|
51
|
+
txn::handle_ = nullptr;
|
|
52
|
+
if (rc != MDBX_SUCCESS) {
|
|
53
|
+
throw std::runtime_error(::mdbx_strerror(rc));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Abort транзакции
|
|
59
|
+
void abort() {
|
|
60
|
+
if (guard_) {
|
|
61
|
+
auto rc = ::mdbx_txn_abort(guard_.release());
|
|
62
|
+
txn::handle_ = nullptr;
|
|
63
|
+
if (rc != MDBX_SUCCESS) {
|
|
64
|
+
throw std::runtime_error(::mdbx_strerror(rc));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
18
67
|
}
|
|
19
68
|
};
|
|
20
69
|
|
|
21
70
|
struct cursormou_managed final
|
|
22
|
-
: mdbx::
|
|
71
|
+
: mdbx::cursor
|
|
23
72
|
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
73
|
+
// свободу курсору
|
|
74
|
+
struct free_cursor
|
|
75
|
+
{
|
|
76
|
+
void operator()(MDBX_cursor* c) const noexcept {
|
|
77
|
+
if (c) ::mdbx_cursor_close(c);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
std::unique_ptr<MDBX_cursor, free_cursor> guard_;
|
|
82
|
+
|
|
83
|
+
explicit cursormou_managed(MDBX_cursor* cursor) noexcept
|
|
84
|
+
: mdbx::cursor(cursor)
|
|
85
|
+
, guard_(cursor)
|
|
86
|
+
{ }
|
|
87
|
+
|
|
88
|
+
// Move конструктор
|
|
89
|
+
cursormou_managed(cursormou_managed&& other) noexcept
|
|
90
|
+
: mdbx::cursor(other.cursor::handle_)
|
|
91
|
+
, guard_(std::move(other.guard_))
|
|
92
|
+
{
|
|
93
|
+
other.cursor::handle_ = nullptr;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Запрет копирования
|
|
97
|
+
cursormou_managed(const cursormou_managed&) = delete;
|
|
98
|
+
cursormou_managed& operator=(const cursormou_managed&) = delete;
|
|
99
|
+
|
|
100
|
+
~cursormou_managed() noexcept {
|
|
101
|
+
// guard_ автоматически закроет курсор
|
|
102
|
+
cursor::handle_ = nullptr;
|
|
103
|
+
}
|
|
28
104
|
};
|
|
29
105
|
|
|
30
106
|
struct env_flag {
|
package/src/valuemou.hpp
CHANGED
|
@@ -38,9 +38,8 @@ public:
|
|
|
38
38
|
if (status != napi_ok) {
|
|
39
39
|
throw Napi::Error::New(env, "napi_get_value_string_utf8 length");
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
mem.reserve(length + 1);
|
|
43
|
-
mem.resize(length);
|
|
44
43
|
|
|
45
44
|
status = napi_get_value_string_utf8(
|
|
46
45
|
env, arg0, mem.data(), mem.capacity(), nullptr);
|
|
@@ -48,6 +47,8 @@ public:
|
|
|
48
47
|
throw Napi::Error::New(env, "napi_get_value_string_utf8 copyout");
|
|
49
48
|
}
|
|
50
49
|
|
|
50
|
+
mem.resize(length);
|
|
51
|
+
|
|
51
52
|
assign(mem.data(), mem.size());
|
|
52
53
|
}
|
|
53
54
|
|