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:
parent
03eec137a2
commit
b354d12599
@ -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;
|
||||||
|
@ -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));
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user