Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-03-13 17:32:37 +0300
committerAnna Henningsen <anna@addaleax.net>2019-03-31 00:25:34 +0300
commit1ee37aac09f263b00029561542cf3bea5db5113b (patch)
tree918a05206a11d3c0c29ca53f77411acdc5e4ae6d /src/node_env_var.cc
parentf5b5fe3937ec353e43d30ae976725e0773e14c6f (diff)
src: implement generic backend for process.env
Allow a generic string-based backing store, with no significance to the remainder of the process, as a store for `process.env`. PR-URL: https://github.com/nodejs/node/pull/26544 Fixes: https://github.com/nodejs/node/issues/24947 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'src/node_env_var.cc')
-rw-r--r--src/node_env_var.cc118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/node_env_var.cc b/src/node_env_var.cc
index 6bd799e19f8..2df7275b175 100644
--- a/src/node_env_var.cc
+++ b/src/node_env_var.cc
@@ -14,13 +14,17 @@ using v8::Array;
using v8::Boolean;
using v8::Context;
using v8::EscapableHandleScope;
+using v8::HandleScope;
using v8::Integer;
using v8::Isolate;
+using v8::Just;
using v8::Local;
+using v8::Maybe;
using v8::MaybeLocal;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::NewStringType;
+using v8::Nothing;
using v8::Object;
using v8::ObjectTemplate;
using v8::PropertyCallbackInfo;
@@ -36,6 +40,24 @@ class RealEnvStore final : public KVStore {
Local<Array> Enumerate(Isolate* isolate) const override;
};
+class GenericKVStore final : public KVStore {
+ public:
+ Local<String> Get(Isolate* isolate, Local<String> key) const override;
+ void Set(Isolate* isolate, Local<String> key, Local<String> value) override;
+ int32_t Query(Isolate* isolate, Local<String> key) const override;
+ void Delete(Isolate* isolate, Local<String> key) override;
+ Local<Array> Enumerate(Isolate* isolate) const override;
+
+ std::shared_ptr<KVStore> Clone(Isolate* isolate) const override;
+
+ GenericKVStore() {}
+ GenericKVStore(const GenericKVStore& other) : map_(other.map_) {}
+
+ private:
+ mutable Mutex mutex_;
+ std::unordered_map<std::string, std::string> map_;
+};
+
namespace per_process {
Mutex env_var_mutex;
std::shared_ptr<KVStore> real_environment = std::make_shared<RealEnvStore>();
@@ -181,6 +203,102 @@ Local<Array> RealEnvStore::Enumerate(Isolate* isolate) const {
return Array::New(isolate, env_v.data(), env_v.size());
}
+std::shared_ptr<KVStore> KVStore::Clone(v8::Isolate* isolate) const {
+ HandleScope handle_scope(isolate);
+ Local<Context> context = isolate->GetCurrentContext();
+
+ std::shared_ptr<KVStore> copy = KVStore::CreateGenericKVStore();
+ Local<Array> keys = Enumerate(isolate);
+ uint32_t keys_length = keys->Length();
+ for (uint32_t i = 0; i < keys_length; i++) {
+ Local<Value> key = keys->Get(context, i).ToLocalChecked();
+ CHECK(key->IsString());
+ copy->Set(isolate, key.As<String>(), Get(isolate, key.As<String>()));
+ }
+ return copy;
+}
+
+Local<String> GenericKVStore::Get(Isolate* isolate, Local<String> key) const {
+ Mutex::ScopedLock lock(mutex_);
+ String::Utf8Value str(isolate, key);
+ auto it = map_.find(std::string(*str, str.length()));
+ if (it == map_.end()) return Local<String>();
+ return String::NewFromUtf8(isolate, it->second.data(),
+ NewStringType::kNormal, it->second.size())
+ .ToLocalChecked();
+}
+
+void GenericKVStore::Set(Isolate* isolate, Local<String> key,
+ Local<String> value) {
+ Mutex::ScopedLock lock(mutex_);
+ String::Utf8Value key_str(isolate, key);
+ String::Utf8Value value_str(isolate, value);
+ if (*key_str != nullptr && *value_str != nullptr) {
+ map_[std::string(*key_str, key_str.length())] =
+ std::string(*value_str, value_str.length());
+ }
+}
+
+int32_t GenericKVStore::Query(Isolate* isolate, Local<String> key) const {
+ Mutex::ScopedLock lock(mutex_);
+ String::Utf8Value str(isolate, key);
+ auto it = map_.find(std::string(*str, str.length()));
+ return it == map_.end() ? -1 : 0;
+}
+
+void GenericKVStore::Delete(Isolate* isolate, Local<String> key) {
+ Mutex::ScopedLock lock(mutex_);
+ String::Utf8Value str(isolate, key);
+ map_.erase(std::string(*str, str.length()));
+}
+
+Local<Array> GenericKVStore::Enumerate(Isolate* isolate) const {
+ Mutex::ScopedLock lock(mutex_);
+ std::vector<Local<Value>> values;
+ values.reserve(map_.size());
+ for (const auto& pair : map_) {
+ values.emplace_back(
+ String::NewFromUtf8(isolate, pair.first.data(),
+ NewStringType::kNormal, pair.first.size())
+ .ToLocalChecked());
+ }
+ return Array::New(isolate, values.data(), values.size());
+}
+
+std::shared_ptr<KVStore> GenericKVStore::Clone(Isolate* isolate) const {
+ return std::make_shared<GenericKVStore>(*this);
+}
+
+std::shared_ptr<KVStore> KVStore::CreateGenericKVStore() {
+ return std::make_shared<GenericKVStore>();
+}
+
+Maybe<bool> KVStore::AssignFromObject(Local<Context> context,
+ Local<Object> entries) {
+ Isolate* isolate = context->GetIsolate();
+ HandleScope handle_scope(isolate);
+ Local<Array> keys;
+ if (!entries->GetOwnPropertyNames(context).ToLocal(&keys))
+ return Nothing<bool>();
+ uint32_t keys_length = keys->Length();
+ for (uint32_t i = 0; i < keys_length; i++) {
+ Local<Value> key;
+ if (!keys->Get(context, i).ToLocal(&key))
+ return Nothing<bool>();
+ if (!key->IsString()) continue;
+
+ Local<Value> value;
+ Local<String> value_string;
+ if (!entries->Get(context, key.As<String>()).ToLocal(&value) ||
+ !value->ToString(context).ToLocal(&value_string)) {
+ return Nothing<bool>();
+ }
+
+ Set(isolate, key.As<String>(), value_string);
+ }
+ return Just(true);
+}
+
static void EnvGetter(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {
Environment* env = Environment::GetCurrent(info);