src: modified RealEnvStore methods to use libuv functions

Modified RealEnvStore::Get, Set, Query and Delete methods
to use libuv methods environment variables operations instead
of using os specific logic and switches.

Fixes: https://github.com/nodejs/node/issues/27211
Refs: http://docs.libuv.org/en/v1.x/misc.html

PR-URL: https://github.com/nodejs/node/pull/27310
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
Devendra Satram 2019-04-19 18:03:18 +05:30 committed by Anna Henningsen
parent 03eec137a2
commit b354d12599
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9
3 changed files with 58 additions and 73 deletions

View File

@ -610,8 +610,8 @@ class KVStore {
KVStore(KVStore&&) = delete; KVStore(KVStore&&) = delete;
KVStore& operator=(KVStore&&) = delete; KVStore& operator=(KVStore&&) = delete;
virtual v8::Local<v8::String> Get(v8::Isolate* isolate, virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate,
v8::Local<v8::String> key) const = 0; v8::Local<v8::String> key) const = 0;
virtual void Set(v8::Isolate* isolate, virtual void Set(v8::Isolate* isolate,
v8::Local<v8::String> key, v8::Local<v8::String> key,
v8::Local<v8::String> value) = 0; v8::Local<v8::String> value) = 0;

View File

@ -340,7 +340,8 @@ std::string GetCwd(Environment* env) {
void StartProfilers(Environment* env) { void StartProfilers(Environment* env) {
Isolate* isolate = env->isolate(); Isolate* isolate = env->isolate();
Local<String> coverage_str = env->env_vars()->Get( Local<String> coverage_str = env->env_vars()->Get(
isolate, FIXED_ONE_BYTE_STRING(isolate, "NODE_V8_COVERAGE")); isolate, FIXED_ONE_BYTE_STRING(isolate, "NODE_V8_COVERAGE"))
.FromMaybe(Local<String>());
if (!coverage_str.IsEmpty() && coverage_str->Length() > 0) { if (!coverage_str.IsEmpty() && coverage_str->Length() > 0) {
CHECK_NULL(env->coverage_connection()); CHECK_NULL(env->coverage_connection());
env->set_coverage_connection(std::make_unique<V8CoverageConnection>(env)); env->set_coverage_connection(std::make_unique<V8CoverageConnection>(env));

View File

@ -36,7 +36,7 @@ using v8::Value;
class RealEnvStore final : public KVStore { class RealEnvStore final : public KVStore {
public: public:
Local<String> Get(Isolate* isolate, Local<String> key) const override; MaybeLocal<String> Get(Isolate* isolate, Local<String> key) const override;
void Set(Isolate* isolate, Local<String> key, Local<String> value) override; void Set(Isolate* isolate, Local<String> key, Local<String> value) override;
int32_t Query(Isolate* isolate, Local<String> key) const override; int32_t Query(Isolate* isolate, Local<String> key) const override;
void Delete(Isolate* isolate, Local<String> key) override; void Delete(Isolate* isolate, Local<String> key) override;
@ -45,7 +45,7 @@ class RealEnvStore final : public KVStore {
class MapKVStore final : public KVStore { class MapKVStore final : public KVStore {
public: public:
Local<String> Get(Isolate* isolate, Local<String> key) const override; MaybeLocal<String> Get(Isolate* isolate, Local<String> key) const override;
void Set(Isolate* isolate, Local<String> key, Local<String> value) override; void Set(Isolate* isolate, Local<String> key, Local<String> value) override;
int32_t Query(Isolate* isolate, Local<String> key) const override; int32_t Query(Isolate* isolate, Local<String> key) const override;
void Delete(Isolate* isolate, Local<String> key) override; void Delete(Isolate* isolate, Local<String> key) override;
@ -79,93 +79,73 @@ void DateTimeConfigurationChangeNotification(Isolate* isolate, const T& key) {
} }
} }
Local<String> RealEnvStore::Get(Isolate* isolate, MaybeLocal<String> RealEnvStore::Get(Isolate* isolate,
Local<String> property) const { Local<String> property) const {
Mutex::ScopedLock lock(per_process::env_var_mutex); Mutex::ScopedLock lock(per_process::env_var_mutex);
#ifdef __POSIX__
node::Utf8Value key(isolate, property); node::Utf8Value key(isolate, property);
const char* val = getenv(*key); size_t init_sz = 256;
if (val) { MaybeStackBuffer<char, 256> val;
return String::NewFromUtf8(isolate, val, NewStringType::kNormal) int ret = uv_os_getenv(*key, *val, &init_sz);
.ToLocalChecked();
if (ret == UV_ENOBUFS) {
// Buffer is not large enough, reallocate to the updated init_sz
// and fetch env value again.
val.AllocateSufficientStorage(init_sz);
ret = uv_os_getenv(*key, *val, &init_sz);
} }
#else // _WIN32
node::TwoByteValue key(isolate, property); if (ret >= 0) { // Env key value fetch success.
WCHAR buffer[32767]; // The maximum size allowed for environment variables. MaybeLocal<String> value_string =
SetLastError(ERROR_SUCCESS); String::NewFromUtf8(isolate, *val, NewStringType::kNormal, init_sz);
DWORD result = GetEnvironmentVariableW( return value_string;
reinterpret_cast<WCHAR*>(*key), buffer, arraysize(buffer));
// If result >= sizeof buffer the buffer was too small. That should never
// happen. If result == 0 and result != ERROR_SUCCESS the variable was not
// found.
if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
result < arraysize(buffer)) {
const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
v8::MaybeLocal<String> rc = String::NewFromTwoByte(
isolate, two_byte_buffer, NewStringType::kNormal);
if (rc.IsEmpty()) {
isolate->ThrowException(ERR_STRING_TOO_LONG(isolate));
return Local<String>();
}
return rc.ToLocalChecked();
} }
#endif
return Local<String>(); return MaybeLocal<String>();
} }
void RealEnvStore::Set(Isolate* isolate, void RealEnvStore::Set(Isolate* isolate,
Local<String> property, Local<String> property,
Local<String> value) { Local<String> value) {
Mutex::ScopedLock lock(per_process::env_var_mutex); Mutex::ScopedLock lock(per_process::env_var_mutex);
#ifdef __POSIX__
node::Utf8Value key(isolate, property); node::Utf8Value key(isolate, property);
node::Utf8Value val(isolate, value); node::Utf8Value val(isolate, value);
setenv(*key, *val, 1);
#else // _WIN32 #ifdef _WIN32
node::TwoByteValue key(isolate, property); if (key[0] == L'=') return;
node::TwoByteValue val(isolate, value);
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
// Environment variables that start with '=' are read-only.
if (key_ptr[0] != L'=') {
SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
}
#endif #endif
uv_os_setenv(*key, *val);
DateTimeConfigurationChangeNotification(isolate, key); DateTimeConfigurationChangeNotification(isolate, key);
} }
int32_t RealEnvStore::Query(Isolate* isolate, Local<String> property) const { int32_t RealEnvStore::Query(Isolate* isolate, Local<String> property) const {
Mutex::ScopedLock lock(per_process::env_var_mutex); Mutex::ScopedLock lock(per_process::env_var_mutex);
#ifdef __POSIX__
node::Utf8Value key(isolate, property); node::Utf8Value key(isolate, property);
if (getenv(*key)) return 0; #ifdef _WIN32
#else // _WIN32 if (key[0] == L'=')
node::TwoByteValue key(isolate, property); return static_cast<int32_t>(v8::ReadOnly) |
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key); static_cast<int32_t>(v8::DontDelete) |
SetLastError(ERROR_SUCCESS); static_cast<int32_t>(v8::DontEnum);
if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
GetLastError() == ERROR_SUCCESS) {
if (key_ptr[0] == L'=') {
// Environment variables that start with '=' are hidden and read-only.
return static_cast<int32_t>(v8::ReadOnly) |
static_cast<int32_t>(v8::DontDelete) |
static_cast<int32_t>(v8::DontEnum);
}
return 0;
}
#endif #endif
return -1;
char val[2];
size_t init_sz = sizeof(val);
int ret = uv_os_getenv(*key, val, &init_sz);
if (ret == UV_ENOENT) {
return -1;
}
return 0;
} }
void RealEnvStore::Delete(Isolate* isolate, Local<String> property) { void RealEnvStore::Delete(Isolate* isolate, Local<String> property) {
Mutex::ScopedLock lock(per_process::env_var_mutex); Mutex::ScopedLock lock(per_process::env_var_mutex);
#ifdef __POSIX__
node::Utf8Value key(isolate, property); node::Utf8Value key(isolate, property);
unsetenv(*key); uv_os_unsetenv(*key);
#else
node::TwoByteValue key(isolate, property);
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
SetEnvironmentVariableW(key_ptr, nullptr);
#endif
DateTimeConfigurationChangeNotification(isolate, key); DateTimeConfigurationChangeNotification(isolate, key);
} }
@ -231,19 +211,20 @@ std::shared_ptr<KVStore> KVStore::Clone(v8::Isolate* isolate) const {
for (uint32_t i = 0; i < keys_length; i++) { for (uint32_t i = 0; i < keys_length; i++) {
Local<Value> key = keys->Get(context, i).ToLocalChecked(); Local<Value> key = keys->Get(context, i).ToLocalChecked();
CHECK(key->IsString()); CHECK(key->IsString());
copy->Set(isolate, key.As<String>(), Get(isolate, key.As<String>())); copy->Set(isolate,
key.As<String>(),
Get(isolate, key.As<String>()).ToLocalChecked());
} }
return copy; return copy;
} }
Local<String> MapKVStore::Get(Isolate* isolate, Local<String> key) const { MaybeLocal<String> MapKVStore::Get(Isolate* isolate, Local<String> key) const {
Mutex::ScopedLock lock(mutex_); Mutex::ScopedLock lock(mutex_);
Utf8Value str(isolate, key); Utf8Value str(isolate, key);
auto it = map_.find(std::string(*str, str.length())); auto it = map_.find(std::string(*str, str.length()));
if (it == map_.end()) return Local<String>(); if (it == map_.end()) return Local<String>();
return String::NewFromUtf8(isolate, it->second.data(), return String::NewFromUtf8(isolate, it->second.data(),
NewStringType::kNormal, it->second.size()) NewStringType::kNormal, it->second.size());
.ToLocalChecked();
} }
void MapKVStore::Set(Isolate* isolate, Local<String> key, Local<String> value) { void MapKVStore::Set(Isolate* isolate, Local<String> key, Local<String> value) {
@ -323,8 +304,11 @@ static void EnvGetter(Local<Name> property,
return info.GetReturnValue().SetUndefined(); return info.GetReturnValue().SetUndefined();
} }
CHECK(property->IsString()); CHECK(property->IsString());
info.GetReturnValue().Set( MaybeLocal<String> value_string =
env->env_vars()->Get(env->isolate(), property.As<String>())); env->env_vars()->Get(env->isolate(), property.As<String>());
if (!value_string.IsEmpty()) {
info.GetReturnValue().Set(value_string.ToLocalChecked());
}
} }
static void EnvSetter(Local<Name> property, static void EnvSetter(Local<Name> property,