@@ -14,13 +14,17 @@ using v8::Array;
14
14
using v8::Boolean ;
15
15
using v8::Context;
16
16
using v8::EscapableHandleScope;
17
+ using v8::HandleScope;
17
18
using v8::Integer;
18
19
using v8::Isolate;
20
+ using v8::Just;
19
21
using v8::Local;
22
+ using v8::Maybe;
20
23
using v8::MaybeLocal;
21
24
using v8::Name;
22
25
using v8::NamedPropertyHandlerConfiguration;
23
26
using v8::NewStringType;
27
+ using v8::Nothing;
24
28
using v8::Object;
25
29
using v8::ObjectTemplate;
26
30
using v8::PropertyCallbackInfo;
@@ -36,6 +40,24 @@ class RealEnvStore final : public KVStore {
36
40
Local<Array> Enumerate (Isolate* isolate) const override ;
37
41
};
38
42
43
+ class GenericKVStore final : public KVStore {
44
+ public:
45
+ Local<String> Get (Isolate* isolate, Local<String> key) const override ;
46
+ void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
47
+ int32_t Query (Isolate* isolate, Local<String> key) const override ;
48
+ void Delete (Isolate* isolate, Local<String> key) override ;
49
+ Local<Array> Enumerate (Isolate* isolate) const override ;
50
+
51
+ std::shared_ptr<KVStore> Clone (Isolate* isolate) const override ;
52
+
53
+ GenericKVStore () {}
54
+ GenericKVStore (const GenericKVStore& other) : map_(other.map_) {}
55
+
56
+ private:
57
+ mutable Mutex mutex_;
58
+ std::unordered_map<std::string, std::string> map_;
59
+ };
60
+
39
61
namespace per_process {
40
62
Mutex env_var_mutex;
41
63
std::shared_ptr<KVStore> real_environment = std::make_shared<RealEnvStore>();
@@ -181,6 +203,102 @@ Local<Array> RealEnvStore::Enumerate(Isolate* isolate) const {
181
203
return Array::New (isolate, env_v.data (), env_v.size ());
182
204
}
183
205
206
+ std::shared_ptr<KVStore> KVStore::Clone (v8::Isolate* isolate) const {
207
+ HandleScope handle_scope (isolate);
208
+ Local<Context> context = isolate->GetCurrentContext ();
209
+
210
+ std::shared_ptr<KVStore> copy = KVStore::CreateGenericKVStore ();
211
+ Local<Array> keys = Enumerate (isolate);
212
+ uint32_t keys_length = keys->Length ();
213
+ for (uint32_t i = 0 ; i < keys_length; i++) {
214
+ Local<Value> key = keys->Get (context, i).ToLocalChecked ();
215
+ CHECK (key->IsString ());
216
+ copy->Set (isolate, key.As <String>(), Get (isolate, key.As <String>()));
217
+ }
218
+ return copy;
219
+ }
220
+
221
+ Local<String> GenericKVStore::Get (Isolate* isolate, Local<String> key) const {
222
+ Mutex::ScopedLock lock (mutex_);
223
+ String::Utf8Value str (isolate, key);
224
+ auto it = map_.find (std::string (*str, str.length ()));
225
+ if (it == map_.end ()) return Local<String>();
226
+ return String::NewFromUtf8 (isolate, it->second .data (),
227
+ NewStringType::kNormal , it->second .size ())
228
+ .ToLocalChecked ();
229
+ }
230
+
231
+ void GenericKVStore::Set (Isolate* isolate, Local<String> key,
232
+ Local<String> value) {
233
+ Mutex::ScopedLock lock (mutex_);
234
+ String::Utf8Value key_str (isolate, key);
235
+ String::Utf8Value value_str (isolate, value);
236
+ if (*key_str != nullptr && *value_str != nullptr ) {
237
+ map_[std::string (*key_str, key_str.length ())] =
238
+ std::string (*value_str, value_str.length ());
239
+ }
240
+ }
241
+
242
+ int32_t GenericKVStore::Query (Isolate* isolate, Local<String> key) const {
243
+ Mutex::ScopedLock lock (mutex_);
244
+ String::Utf8Value str (isolate, key);
245
+ auto it = map_.find (std::string (*str, str.length ()));
246
+ return it == map_.end () ? -1 : 0 ;
247
+ }
248
+
249
+ void GenericKVStore::Delete (Isolate* isolate, Local<String> key) {
250
+ Mutex::ScopedLock lock (mutex_);
251
+ String::Utf8Value str (isolate, key);
252
+ map_.erase (std::string (*str, str.length ()));
253
+ }
254
+
255
+ Local<Array> GenericKVStore::Enumerate (Isolate* isolate) const {
256
+ Mutex::ScopedLock lock (mutex_);
257
+ std::vector<Local<Value>> values;
258
+ values.reserve (map_.size ());
259
+ for (const auto & pair : map_) {
260
+ values.emplace_back (
261
+ String::NewFromUtf8 (isolate, pair.first .data (),
262
+ NewStringType::kNormal , pair.first .size ())
263
+ .ToLocalChecked ());
264
+ }
265
+ return Array::New (isolate, values.data (), values.size ());
266
+ }
267
+
268
+ std::shared_ptr<KVStore> GenericKVStore::Clone (Isolate* isolate) const {
269
+ return std::make_shared<GenericKVStore>(*this );
270
+ }
271
+
272
+ std::shared_ptr<KVStore> KVStore::CreateGenericKVStore () {
273
+ return std::make_shared<GenericKVStore>();
274
+ }
275
+
276
+ Maybe<bool > KVStore::AssignFromObject (Local<Context> context,
277
+ Local<Object> entries) {
278
+ Isolate* isolate = context->GetIsolate ();
279
+ HandleScope handle_scope (isolate);
280
+ Local<Array> keys;
281
+ if (!entries->GetOwnPropertyNames (context).ToLocal (&keys))
282
+ return Nothing<bool >();
283
+ uint32_t keys_length = keys->Length ();
284
+ for (uint32_t i = 0 ; i < keys_length; i++) {
285
+ Local<Value> key;
286
+ if (!keys->Get (context, i).ToLocal (&key))
287
+ return Nothing<bool >();
288
+ if (!key->IsString ()) continue ;
289
+
290
+ Local<Value> value;
291
+ Local<String> value_string;
292
+ if (!entries->Get (context, key.As <String>()).ToLocal (&value) ||
293
+ !value->ToString (context).ToLocal (&value_string)) {
294
+ return Nothing<bool >();
295
+ }
296
+
297
+ Set (isolate, key.As <String>(), value_string);
298
+ }
299
+ return Just (true );
300
+ }
301
+
184
302
static void EnvGetter (Local<Name> property,
185
303
const PropertyCallbackInfo<Value>& info) {
186
304
Environment* env = Environment::GetCurrent (info);
0 commit comments