@@ -34,7 +34,7 @@ using v8::Value;
3434
3535class RealEnvStore final : public KVStore {
3636 public:
37- Local <String> Get (Isolate* isolate, Local<String> key) const override ;
37+ MaybeLocal <String> Get (Isolate* isolate, Local<String> key) const override ;
3838 void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
3939 int32_t Query (Isolate* isolate, Local<String> key) const override ;
4040 void Delete (Isolate* isolate, Local<String> key) override ;
@@ -43,7 +43,7 @@ class RealEnvStore final : public KVStore {
4343
4444class MapKVStore final : public KVStore {
4545 public:
46- Local <String> Get (Isolate* isolate, Local<String> key) const override ;
46+ MaybeLocal <String> Get (Isolate* isolate, Local<String> key) const override ;
4747 void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
4848 int32_t Query (Isolate* isolate, Local<String> key) const override ;
4949 void Delete (Isolate* isolate, Local<String> key) override ;
@@ -64,92 +64,72 @@ Mutex env_var_mutex;
6464std::shared_ptr<KVStore> system_environment = std::make_shared<RealEnvStore>();
6565} // namespace per_process
6666
67- Local <String> RealEnvStore::Get (Isolate* isolate,
68- Local<String> property) const {
67+ MaybeLocal <String> RealEnvStore::Get (Isolate* isolate,
68+ Local<String> property) const {
6969 Mutex::ScopedLock lock (per_process::env_var_mutex);
70- # ifdef __POSIX__
70+
7171 node::Utf8Value key (isolate, property);
72- const char * val = getenv (*key);
73- if (val) {
74- return String::NewFromUtf8 (isolate, val, NewStringType::kNormal )
75- .ToLocalChecked ();
72+ size_t init_sz = 256 ;
73+ MaybeStackBuffer<char , 256 > val;
74+ int ret = uv_os_getenv (*key, *val, &init_sz);
75+
76+ if (ret == UV_ENOBUFS) {
77+ // Buffer is not large enough, reallocate to the updated init_sz
78+ // and fetch env value again.
79+ val.AllocateSufficientStorage (init_sz);
80+ ret = uv_os_getenv (*key, *val, &init_sz);
7681 }
77- #else // _WIN32
78- node::TwoByteValue key (isolate, property);
79- WCHAR buffer[32767 ]; // The maximum size allowed for environment variables.
80- SetLastError (ERROR_SUCCESS);
81- DWORD result = GetEnvironmentVariableW (
82- reinterpret_cast <WCHAR*>(*key), buffer, arraysize (buffer));
83- // If result >= sizeof buffer the buffer was too small. That should never
84- // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
85- // found.
86- if ((result > 0 || GetLastError () == ERROR_SUCCESS) &&
87- result < arraysize (buffer)) {
88- const uint16_t * two_byte_buffer = reinterpret_cast <const uint16_t *>(buffer);
89- v8::MaybeLocal<String> rc = String::NewFromTwoByte (
90- isolate, two_byte_buffer, NewStringType::kNormal );
91- if (rc.IsEmpty ()) {
92- isolate->ThrowException (ERR_STRING_TOO_LONG (isolate));
93- return Local<String>();
94- }
95- return rc.ToLocalChecked ();
82+
83+ if (ret >= 0 ) { // Env key value fetch success.
84+ MaybeLocal<String> value_string =
85+ String::NewFromUtf8 (isolate, *val, NewStringType::kNormal , init_sz);
86+ return value_string;
9687 }
97- # endif
98- return Local <String>();
88+
89+ return MaybeLocal <String>();
9990}
10091
10192void RealEnvStore::Set (Isolate* isolate,
10293 Local<String> property,
10394 Local<String> value) {
10495 Mutex::ScopedLock lock (per_process::env_var_mutex);
105- # ifdef __POSIX__
96+
10697 node::Utf8Value key (isolate, property);
10798 node::Utf8Value val (isolate, value);
108- setenv (*key, *val, 1 );
109- #else // _WIN32
110- node::TwoByteValue key (isolate, property);
111- node::TwoByteValue val (isolate, value);
112- WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
113- // Environment variables that start with '=' are read-only.
114- if (key_ptr[0 ] != L' =' ) {
115- SetEnvironmentVariableW (key_ptr, reinterpret_cast <WCHAR*>(*val));
116- }
99+
100+ #ifdef _WIN32
101+ if (key[0 ] == L' =' ) return ;
117102#endif
103+ uv_os_setenv (*key, *val);
118104}
119105
120106int32_t RealEnvStore::Query (Isolate* isolate, Local<String> property) const {
121107 Mutex::ScopedLock lock (per_process::env_var_mutex);
122- # ifdef __POSIX__
108+
123109 node::Utf8Value key (isolate, property);
124- if (getenv (*key)) return 0 ;
125- #else // _WIN32
126- node::TwoByteValue key (isolate, property);
127- WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
128- SetLastError (ERROR_SUCCESS);
129- if (GetEnvironmentVariableW (key_ptr, nullptr , 0 ) > 0 ||
130- GetLastError () == ERROR_SUCCESS) {
131- if (key_ptr[0 ] == L' =' ) {
132- // Environment variables that start with '=' are hidden and read-only.
133- return static_cast <int32_t >(v8::ReadOnly) |
134- static_cast <int32_t >(v8::DontDelete) |
135- static_cast <int32_t >(v8::DontEnum);
136- }
137- return 0 ;
138- }
110+ #ifdef _WIN32
111+ if (key[0 ] == L' =' )
112+ return static_cast <int32_t >(v8::ReadOnly) |
113+ static_cast <int32_t >(v8::DontDelete) |
114+ static_cast <int32_t >(v8::DontEnum);
139115#endif
140- return -1 ;
116+
117+ char val[2 ];
118+ size_t init_sz = sizeof (val);
119+ int ret = uv_os_getenv (*key, val, &init_sz);
120+
121+ if (ret == UV_ENOENT) {
122+ return -1 ;
123+ }
124+
125+ return 0 ;
141126}
142127
143128void RealEnvStore::Delete (Isolate* isolate, Local<String> property) {
144129 Mutex::ScopedLock lock (per_process::env_var_mutex);
145- # ifdef __POSIX__
130+
146131 node::Utf8Value key (isolate, property);
147- unsetenv (*key);
148- #else
149- node::TwoByteValue key (isolate, property);
150- WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
151- SetEnvironmentVariableW (key_ptr, nullptr );
152- #endif
132+ uv_os_unsetenv (*key);
153133}
154134
155135Local<Array> RealEnvStore::Enumerate (Isolate* isolate) const {
@@ -214,19 +194,20 @@ std::shared_ptr<KVStore> KVStore::Clone(v8::Isolate* isolate) const {
214194 for (uint32_t i = 0 ; i < keys_length; i++) {
215195 Local<Value> key = keys->Get (context, i).ToLocalChecked ();
216196 CHECK (key->IsString ());
217- copy->Set (isolate, key.As <String>(), Get (isolate, key.As <String>()));
197+ copy->Set (isolate,
198+ key.As <String>(),
199+ Get (isolate, key.As <String>()).ToLocalChecked ());
218200 }
219201 return copy;
220202}
221203
222- Local <String> MapKVStore::Get (Isolate* isolate, Local<String> key) const {
204+ MaybeLocal <String> MapKVStore::Get (Isolate* isolate, Local<String> key) const {
223205 Mutex::ScopedLock lock (mutex_);
224206 Utf8Value str (isolate, key);
225207 auto it = map_.find (std::string (*str, str.length ()));
226208 if (it == map_.end ()) return Local<String>();
227209 return String::NewFromUtf8 (isolate, it->second .data (),
228- NewStringType::kNormal , it->second .size ())
229- .ToLocalChecked ();
210+ NewStringType::kNormal , it->second .size ());
230211}
231212
232213void MapKVStore::Set (Isolate* isolate, Local<String> key, Local<String> value) {
@@ -306,8 +287,11 @@ static void EnvGetter(Local<Name> property,
306287 return info.GetReturnValue ().SetUndefined ();
307288 }
308289 CHECK (property->IsString ());
309- info.GetReturnValue ().Set (
310- env->env_vars ()->Get (env->isolate (), property.As <String>()));
290+ MaybeLocal<String> value_string =
291+ env->env_vars ()->Get (env->isolate (), property.As <String>());
292+ if (!value_string.IsEmpty ()) {
293+ info.GetReturnValue ().Set (value_string.ToLocalChecked ());
294+ }
311295}
312296
313297static void EnvSetter (Local<Name> property,
0 commit comments