src: improve error handling in process.env handling
PR-URL: https://github.com/nodejs/node/pull/57707 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
f31c88021b
commit
214e3d4aff
@ -26,7 +26,6 @@ using v8::Maybe;
|
||||
using v8::MaybeLocal;
|
||||
using v8::Name;
|
||||
using v8::NamedPropertyHandlerConfiguration;
|
||||
using v8::NewStringType;
|
||||
using v8::Nothing;
|
||||
using v8::Object;
|
||||
using v8::ObjectTemplate;
|
||||
@ -45,7 +44,7 @@ class RealEnvStore final : public KVStore {
|
||||
int32_t Query(Isolate* isolate, Local<String> key) const override;
|
||||
int32_t Query(const char* key) const override;
|
||||
void Delete(Isolate* isolate, Local<String> key) override;
|
||||
Local<Array> Enumerate(Isolate* isolate) const override;
|
||||
MaybeLocal<Array> Enumerate(Isolate* isolate) const override;
|
||||
};
|
||||
|
||||
class MapKVStore final : public KVStore {
|
||||
@ -56,7 +55,7 @@ class MapKVStore final : public KVStore {
|
||||
int32_t Query(Isolate* isolate, Local<String> key) const override;
|
||||
int32_t Query(const char* key) const override;
|
||||
void Delete(Isolate* isolate, Local<String> key) override;
|
||||
Local<Array> Enumerate(Isolate* isolate) const override;
|
||||
MaybeLocal<Array> Enumerate(Isolate* isolate) const override;
|
||||
|
||||
std::shared_ptr<KVStore> Clone(Isolate* isolate) const override;
|
||||
|
||||
@ -131,8 +130,12 @@ MaybeLocal<String> RealEnvStore::Get(Isolate* isolate,
|
||||
|
||||
if (value.has_value()) {
|
||||
std::string val = value.value();
|
||||
return String::NewFromUtf8(
|
||||
isolate, val.data(), NewStringType::kNormal, val.size());
|
||||
Local<Value> ret;
|
||||
if (!ToV8Value(isolate->GetCurrentContext(), val).ToLocal(&ret)) {
|
||||
return {};
|
||||
}
|
||||
DCHECK(ret->IsString());
|
||||
return ret.As<String>();
|
||||
}
|
||||
|
||||
return MaybeLocal<String>();
|
||||
@ -188,7 +191,7 @@ void RealEnvStore::Delete(Isolate* isolate, Local<String> property) {
|
||||
DateTimeConfigurationChangeNotification(isolate, key);
|
||||
}
|
||||
|
||||
Local<Array> RealEnvStore::Enumerate(Isolate* isolate) const {
|
||||
MaybeLocal<Array> RealEnvStore::Enumerate(Isolate* isolate) const {
|
||||
Mutex::ScopedLock lock(per_process::env_var_mutex);
|
||||
uv_env_item_t* items;
|
||||
int count;
|
||||
@ -203,12 +206,12 @@ Local<Array> RealEnvStore::Enumerate(Isolate* isolate) const {
|
||||
// If the key starts with '=' it is a hidden environment variable.
|
||||
if (items[i].name[0] == '=') continue;
|
||||
#endif
|
||||
MaybeLocal<String> str = String::NewFromUtf8(isolate, items[i].name);
|
||||
if (str.IsEmpty()) {
|
||||
Local<Value> str;
|
||||
if (!String::NewFromUtf8(isolate, items[i].name).ToLocal(&str)) {
|
||||
isolate->ThrowException(ERR_STRING_TOO_LONG(isolate));
|
||||
return Local<Array>();
|
||||
return {};
|
||||
}
|
||||
env_v[env_v_index++] = str.ToLocalChecked();
|
||||
env_v[env_v_index++] = str;
|
||||
}
|
||||
|
||||
return Array::New(isolate, env_v.out(), env_v_index);
|
||||
@ -219,14 +222,22 @@ std::shared_ptr<KVStore> KVStore::Clone(Isolate* isolate) const {
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
|
||||
std::shared_ptr<KVStore> copy = KVStore::CreateMapKVStore();
|
||||
Local<Array> keys = Enumerate(isolate);
|
||||
Local<Array> keys;
|
||||
if (!Enumerate(isolate).ToLocal(&keys)) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t keys_length = keys->Length();
|
||||
for (uint32_t i = 0; i < keys_length; i++) {
|
||||
Local<Value> key = keys->Get(context, i).ToLocalChecked();
|
||||
Local<Value> key;
|
||||
Local<Value> value;
|
||||
if (!keys->Get(context, i).ToLocal(&key)) {
|
||||
return nullptr;
|
||||
}
|
||||
CHECK(key->IsString());
|
||||
copy->Set(isolate,
|
||||
key.As<String>(),
|
||||
Get(isolate, key.As<String>()).ToLocalChecked());
|
||||
if (!Get(isolate, key.As<String>()).ToLocal(&value)) {
|
||||
return nullptr;
|
||||
}
|
||||
copy->Set(isolate, key.As<String>(), value.As<String>());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
@ -242,8 +253,12 @@ MaybeLocal<String> MapKVStore::Get(Isolate* isolate, Local<String> key) const {
|
||||
std::optional<std::string> value = Get(*str);
|
||||
if (!value.has_value()) return MaybeLocal<String>();
|
||||
std::string val = value.value();
|
||||
return String::NewFromUtf8(
|
||||
isolate, val.data(), NewStringType::kNormal, val.size());
|
||||
Local<Value> ret;
|
||||
if (!ToV8Value(isolate->GetCurrentContext(), val).ToLocal(&ret)) {
|
||||
return {};
|
||||
}
|
||||
DCHECK(ret->IsString());
|
||||
return ret.As<String>();
|
||||
}
|
||||
|
||||
void MapKVStore::Set(Isolate* isolate, Local<String> key, Local<String> value) {
|
||||
@ -272,15 +287,16 @@ void MapKVStore::Delete(Isolate* isolate, Local<String> key) {
|
||||
map_.erase(std::string(*str, str.length()));
|
||||
}
|
||||
|
||||
Local<Array> MapKVStore::Enumerate(Isolate* isolate) const {
|
||||
MaybeLocal<Array> MapKVStore::Enumerate(Isolate* isolate) const {
|
||||
Mutex::ScopedLock lock(mutex_);
|
||||
LocalVector<Value> values(isolate);
|
||||
values.reserve(map_.size());
|
||||
for (const auto& pair : map_) {
|
||||
values.emplace_back(
|
||||
String::NewFromUtf8(isolate, pair.first.data(),
|
||||
NewStringType::kNormal, pair.first.size())
|
||||
.ToLocalChecked());
|
||||
Local<Value> val;
|
||||
if (!ToV8Value(isolate->GetCurrentContext(), pair.first).ToLocal(&val)) {
|
||||
return {};
|
||||
}
|
||||
values.emplace_back(val);
|
||||
}
|
||||
return Array::New(isolate, values.data(), values.size());
|
||||
}
|
||||
@ -324,7 +340,10 @@ Maybe<void> KVStore::AssignToObject(v8::Isolate* isolate,
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> object) {
|
||||
HandleScope scope(isolate);
|
||||
Local<Array> keys = Enumerate(isolate);
|
||||
Local<Array> keys;
|
||||
if (!Enumerate(isolate).ToLocal(&keys)) {
|
||||
return Nothing<void>();
|
||||
}
|
||||
uint32_t keys_length = keys->Length();
|
||||
for (uint32_t i = 0; i < keys_length; i++) {
|
||||
Local<Value> key;
|
||||
@ -421,6 +440,7 @@ static Intercepted EnvGetter(Local<Name> property,
|
||||
TraceEnvVar(env, "get", property.As<String>());
|
||||
|
||||
if (has_env) {
|
||||
// ToLocalChecked here is ok since we check IsEmpty above.
|
||||
info.GetReturnValue().Set(value_string.ToLocalChecked());
|
||||
return Intercepted::kYes;
|
||||
}
|
||||
@ -502,8 +522,10 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
|
||||
|
||||
TraceEnvVar(env, "enumerate environment variables");
|
||||
|
||||
info.GetReturnValue().Set(
|
||||
env->env_vars()->Enumerate(env->isolate()));
|
||||
Local<Array> ret;
|
||||
if (env->env_vars()->Enumerate(env->isolate()).ToLocal(&ret)) {
|
||||
info.GetReturnValue().Set(ret);
|
||||
}
|
||||
}
|
||||
|
||||
static Intercepted EnvDefiner(Local<Name> property,
|
||||
|
@ -545,6 +545,10 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
|
||||
env_vars = env->env_vars();
|
||||
}
|
||||
|
||||
if (!env_vars) {
|
||||
THROW_ERR_OPERATION_FAILED(env, "Failed to copy environment variables");
|
||||
}
|
||||
|
||||
if (args[1]->IsObject() || args[2]->IsArray()) {
|
||||
per_isolate_opts.reset(new PerIsolateOptions());
|
||||
|
||||
|
@ -316,7 +316,7 @@ class KVStore {
|
||||
v8::Local<v8::String> key) const = 0;
|
||||
virtual int32_t Query(const char* key) const = 0;
|
||||
virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0;
|
||||
virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;
|
||||
virtual v8::MaybeLocal<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;
|
||||
|
||||
virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const;
|
||||
virtual v8::Maybe<void> AssignFromObject(v8::Local<v8::Context> context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user