@@ -36,7 +36,7 @@ using v8::Value;
3636
3737class RealEnvStore final : public KVStore {
3838 public:
39- Local <String> Get (Isolate* isolate, Local<String> key) const override ;
39+ MaybeLocal <String> Get (Isolate* isolate, Local<String> key) const override ;
4040 void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
4141 int32_t Query (Isolate* isolate, Local<String> key) const override ;
4242 void Delete (Isolate* isolate, Local<String> key) override ;
@@ -45,7 +45,7 @@ class RealEnvStore final : public KVStore {
4545
4646class MapKVStore final : public KVStore {
4747 public:
48- Local <String> Get (Isolate* isolate, Local<String> key) const override ;
48+ MaybeLocal <String> Get (Isolate* isolate, Local<String> key) const override ;
4949 void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
5050 int32_t Query (Isolate* isolate, Local<String> key) const override ;
5151 void Delete (Isolate* isolate, Local<String> key) override ;
@@ -79,93 +79,73 @@ void DateTimeConfigurationChangeNotification(Isolate* isolate, const T& key) {
7979 }
8080}
8181
82- Local <String> RealEnvStore::Get (Isolate* isolate,
83- Local<String> property) const {
82+ MaybeLocal <String> RealEnvStore::Get (Isolate* isolate,
83+ Local<String> property) const {
8484 Mutex::ScopedLock lock (per_process::env_var_mutex);
85- # ifdef __POSIX__
85+
8686 node::Utf8Value key (isolate, property);
87- const char * val = getenv (*key);
88- if (val) {
89- return String::NewFromUtf8 (isolate, val, NewStringType::kNormal )
90- .ToLocalChecked ();
87+ size_t init_sz = 256 ;
88+ MaybeStackBuffer<char , 256 > val;
89+ int ret = uv_os_getenv (*key, *val, &init_sz);
90+
91+ if (ret == UV_ENOBUFS) {
92+ // Buffer is not large enough, reallocate to the updated init_sz
93+ // and fetch env value again.
94+ val.AllocateSufficientStorage (init_sz);
95+ ret = uv_os_getenv (*key, *val, &init_sz);
9196 }
92- #else // _WIN32
93- node::TwoByteValue key (isolate, property);
94- WCHAR buffer[32767 ]; // The maximum size allowed for environment variables.
95- SetLastError (ERROR_SUCCESS);
96- DWORD result = GetEnvironmentVariableW (
97- reinterpret_cast <WCHAR*>(*key), buffer, arraysize (buffer));
98- // If result >= sizeof buffer the buffer was too small. That should never
99- // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
100- // found.
101- if ((result > 0 || GetLastError () == ERROR_SUCCESS) &&
102- result < arraysize (buffer)) {
103- const uint16_t * two_byte_buffer = reinterpret_cast <const uint16_t *>(buffer);
104- v8::MaybeLocal<String> rc = String::NewFromTwoByte (
105- isolate, two_byte_buffer, NewStringType::kNormal );
106- if (rc.IsEmpty ()) {
107- isolate->ThrowException (ERR_STRING_TOO_LONG (isolate));
108- return Local<String>();
109- }
110- return rc.ToLocalChecked ();
97+
98+ if (ret >= 0 ) { // Env key value fetch success.
99+ MaybeLocal<String> value_string =
100+ String::NewFromUtf8 (isolate, *val, NewStringType::kNormal , init_sz);
101+ return value_string;
111102 }
112- # endif
113- return Local <String>();
103+
104+ return MaybeLocal <String>();
114105}
115106
116107void RealEnvStore::Set (Isolate* isolate,
117108 Local<String> property,
118109 Local<String> value) {
119110 Mutex::ScopedLock lock (per_process::env_var_mutex);
120- # ifdef __POSIX__
111+
121112 node::Utf8Value key (isolate, property);
122113 node::Utf8Value val (isolate, value);
123- setenv (*key, *val, 1 );
124- #else // _WIN32
125- node::TwoByteValue key (isolate, property);
126- node::TwoByteValue val (isolate, value);
127- WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
128- // Environment variables that start with '=' are read-only.
129- if (key_ptr[0 ] != L' =' ) {
130- SetEnvironmentVariableW (key_ptr, reinterpret_cast <WCHAR*>(*val));
131- }
114+
115+ #ifdef _WIN32
116+ if (key[0 ] == L' =' ) return ;
132117#endif
118+ uv_os_setenv (*key, *val);
133119 DateTimeConfigurationChangeNotification (isolate, key);
134120}
135121
136122int32_t RealEnvStore::Query (Isolate* isolate, Local<String> property) const {
137123 Mutex::ScopedLock lock (per_process::env_var_mutex);
138- # ifdef __POSIX__
124+
139125 node::Utf8Value key (isolate, property);
140- if (getenv (*key)) return 0 ;
141- #else // _WIN32
142- node::TwoByteValue key (isolate, property);
143- WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
144- SetLastError (ERROR_SUCCESS);
145- if (GetEnvironmentVariableW (key_ptr, nullptr , 0 ) > 0 ||
146- GetLastError () == ERROR_SUCCESS) {
147- if (key_ptr[0 ] == L' =' ) {
148- // Environment variables that start with '=' are hidden and read-only.
149- return static_cast <int32_t >(v8::ReadOnly) |
150- static_cast <int32_t >(v8::DontDelete) |
151- static_cast <int32_t >(v8::DontEnum);
152- }
153- return 0 ;
154- }
126+ #ifdef _WIN32
127+ if (key[0 ] == L' =' )
128+ return static_cast <int32_t >(v8::ReadOnly) |
129+ static_cast <int32_t >(v8::DontDelete) |
130+ static_cast <int32_t >(v8::DontEnum);
155131#endif
156- return -1 ;
132+
133+ char val[2 ];
134+ size_t init_sz = sizeof (val);
135+ int ret = uv_os_getenv (*key, val, &init_sz);
136+
137+ if (ret == UV_ENOENT) {
138+ return -1 ;
139+ }
140+
141+ return 0 ;
157142}
158143
159144void RealEnvStore::Delete (Isolate* isolate, Local<String> property) {
160145 Mutex::ScopedLock lock (per_process::env_var_mutex);
161- # ifdef __POSIX__
146+
162147 node::Utf8Value key (isolate, property);
163- unsetenv (*key);
164- #else
165- node::TwoByteValue key (isolate, property);
166- WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
167- SetEnvironmentVariableW (key_ptr, nullptr );
168- #endif
148+ uv_os_unsetenv (*key);
169149 DateTimeConfigurationChangeNotification (isolate, key);
170150}
171151
@@ -231,19 +211,20 @@ std::shared_ptr<KVStore> KVStore::Clone(v8::Isolate* isolate) const {
231211 for (uint32_t i = 0 ; i < keys_length; i++) {
232212 Local<Value> key = keys->Get (context, i).ToLocalChecked ();
233213 CHECK (key->IsString ());
234- copy->Set (isolate, key.As <String>(), Get (isolate, key.As <String>()));
214+ copy->Set (isolate,
215+ key.As <String>(),
216+ Get (isolate, key.As <String>()).ToLocalChecked ());
235217 }
236218 return copy;
237219}
238220
239- Local <String> MapKVStore::Get (Isolate* isolate, Local<String> key) const {
221+ MaybeLocal <String> MapKVStore::Get (Isolate* isolate, Local<String> key) const {
240222 Mutex::ScopedLock lock (mutex_);
241223 Utf8Value str (isolate, key);
242224 auto it = map_.find (std::string (*str, str.length ()));
243225 if (it == map_.end ()) return Local<String>();
244226 return String::NewFromUtf8 (isolate, it->second .data (),
245- NewStringType::kNormal , it->second .size ())
246- .ToLocalChecked ();
227+ NewStringType::kNormal , it->second .size ());
247228}
248229
249230void MapKVStore::Set (Isolate* isolate, Local<String> key, Local<String> value) {
@@ -323,8 +304,11 @@ static void EnvGetter(Local<Name> property,
323304 return info.GetReturnValue ().SetUndefined ();
324305 }
325306 CHECK (property->IsString ());
326- info.GetReturnValue ().Set (
327- env->env_vars ()->Get (env->isolate (), property.As <String>()));
307+ MaybeLocal<String> value_string =
308+ env->env_vars ()->Get (env->isolate (), property.As <String>());
309+ if (!value_string.IsEmpty ()) {
310+ info.GetReturnValue ().Set (value_string.ToLocalChecked ());
311+ }
328312}
329313
330314static void EnvSetter (Local<Name> property,
0 commit comments