@@ -34,7 +34,7 @@ using v8::Value;
34
34
35
35
class RealEnvStore final : public KVStore {
36
36
public:
37
- Local <String> Get (Isolate* isolate, Local<String> key) const override ;
37
+ MaybeLocal <String> Get (Isolate* isolate, Local<String> key) const override ;
38
38
void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
39
39
int32_t Query (Isolate* isolate, Local<String> key) const override ;
40
40
void Delete (Isolate* isolate, Local<String> key) override ;
@@ -43,7 +43,7 @@ class RealEnvStore final : public KVStore {
43
43
44
44
class MapKVStore final : public KVStore {
45
45
public:
46
- Local <String> Get (Isolate* isolate, Local<String> key) const override ;
46
+ MaybeLocal <String> Get (Isolate* isolate, Local<String> key) const override ;
47
47
void Set (Isolate* isolate, Local<String> key, Local<String> value) override ;
48
48
int32_t Query (Isolate* isolate, Local<String> key) const override ;
49
49
void Delete (Isolate* isolate, Local<String> key) override ;
@@ -64,92 +64,72 @@ Mutex env_var_mutex;
64
64
std::shared_ptr<KVStore> system_environment = std::make_shared<RealEnvStore>();
65
65
} // namespace per_process
66
66
67
- Local <String> RealEnvStore::Get (Isolate* isolate,
68
- Local<String> property) const {
67
+ MaybeLocal <String> RealEnvStore::Get (Isolate* isolate,
68
+ Local<String> property) const {
69
69
Mutex::ScopedLock lock (per_process::env_var_mutex);
70
- # ifdef __POSIX__
70
+
71
71
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);
76
81
}
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;
96
87
}
97
- # endif
98
- return Local <String>();
88
+
89
+ return MaybeLocal <String>();
99
90
}
100
91
101
92
void RealEnvStore::Set (Isolate* isolate,
102
93
Local<String> property,
103
94
Local<String> value) {
104
95
Mutex::ScopedLock lock (per_process::env_var_mutex);
105
- # ifdef __POSIX__
96
+
106
97
node::Utf8Value key (isolate, property);
107
98
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 ;
117
102
#endif
103
+ uv_os_setenv (*key, *val);
118
104
}
119
105
120
106
int32_t RealEnvStore::Query (Isolate* isolate, Local<String> property) const {
121
107
Mutex::ScopedLock lock (per_process::env_var_mutex);
122
- # ifdef __POSIX__
108
+
123
109
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);
139
115
#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 ;
141
126
}
142
127
143
128
void RealEnvStore::Delete (Isolate* isolate, Local<String> property) {
144
129
Mutex::ScopedLock lock (per_process::env_var_mutex);
145
- # ifdef __POSIX__
130
+
146
131
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);
153
133
}
154
134
155
135
Local<Array> RealEnvStore::Enumerate (Isolate* isolate) const {
@@ -214,19 +194,20 @@ std::shared_ptr<KVStore> KVStore::Clone(v8::Isolate* isolate) const {
214
194
for (uint32_t i = 0 ; i < keys_length; i++) {
215
195
Local<Value> key = keys->Get (context, i).ToLocalChecked ();
216
196
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 ());
218
200
}
219
201
return copy;
220
202
}
221
203
222
- Local <String> MapKVStore::Get (Isolate* isolate, Local<String> key) const {
204
+ MaybeLocal <String> MapKVStore::Get (Isolate* isolate, Local<String> key) const {
223
205
Mutex::ScopedLock lock (mutex_);
224
206
Utf8Value str (isolate, key);
225
207
auto it = map_.find (std::string (*str, str.length ()));
226
208
if (it == map_.end ()) return Local<String>();
227
209
return String::NewFromUtf8 (isolate, it->second .data (),
228
- NewStringType::kNormal , it->second .size ())
229
- .ToLocalChecked ();
210
+ NewStringType::kNormal , it->second .size ());
230
211
}
231
212
232
213
void MapKVStore::Set (Isolate* isolate, Local<String> key, Local<String> value) {
@@ -306,8 +287,11 @@ static void EnvGetter(Local<Name> property,
306
287
return info.GetReturnValue ().SetUndefined ();
307
288
}
308
289
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
+ }
311
295
}
312
296
313
297
static void EnvSetter (Local<Name> property,
0 commit comments