Skip to content

Commit

Permalink
src: move more to node_process.cc from node.cc
Browse files Browse the repository at this point in the history
PR-URL: #22422
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
  • Loading branch information
jasnell committed Aug 23, 2018
1 parent d320511 commit 264c99f
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 225 deletions.
225 changes: 0 additions & 225 deletions src/node.cc
Expand Up @@ -114,13 +114,6 @@ typedef int mode_t;
#include <dlfcn.h>
#endif

#ifdef __APPLE__
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#elif !defined(_MSC_VER)
extern char **environ;
#endif

// This is used to load built-in modules. Instead of using
// __attribute__((constructor)), we call the _register_<modname>
// function for each built-in modules explicitly in
Expand Down Expand Up @@ -168,9 +161,6 @@ using v8::Undefined;
using v8::V8;
using v8::Value;

static Mutex process_mutex;
static Mutex environ_mutex;

static bool v8_is_profiling = false;
static bool node_is_initialized = false;
static uv_once_t init_modpending_once = UV_ONCE_INIT;
Expand Down Expand Up @@ -1695,221 +1685,6 @@ static void GetLinkedBinding(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(effective_exports);
}

static void ProcessTitleGetter(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {
char buffer[512];
uv_get_process_title(buffer, sizeof(buffer));
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), buffer,
v8::NewStringType::kNormal).ToLocalChecked());
}


static void ProcessTitleSetter(Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<void>& info) {
node::Utf8Value title(info.GetIsolate(), value);
TRACE_EVENT_METADATA1("__metadata", "process_name", "name",
TRACE_STR_COPY(*title));
uv_set_process_title(*title);
}


static void EnvGetter(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
if (property->IsSymbol()) {
return info.GetReturnValue().SetUndefined();
}
Mutex::ScopedLock lock(environ_mutex);
#ifdef __POSIX__
node::Utf8Value key(isolate, property);
const char* val = getenv(*key);
if (val) {
return info.GetReturnValue().Set(String::NewFromUtf8(isolate, val,
v8::NewStringType::kNormal).ToLocalChecked());
}
#else // _WIN32
node::TwoByteValue key(isolate, property);
WCHAR buffer[32767]; // The maximum size allowed for environment variables.
SetLastError(ERROR_SUCCESS);
DWORD result = GetEnvironmentVariableW(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);
Local<String> rc = String::NewFromTwoByte(isolate, two_byte_buffer);
return info.GetReturnValue().Set(rc);
}
#endif
}


static void EnvSetter(Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<Value>& info) {
Environment* env = Environment::GetCurrent(info);
if (env->options()->pending_deprecation && env->EmitProcessEnvWarning() &&
!value->IsString() && !value->IsNumber() && !value->IsBoolean()) {
if (ProcessEmitDeprecationWarning(
env,
"Assigning any value other than a string, number, or boolean to a "
"process.env property is deprecated. Please make sure to convert the "
"value to a string before setting process.env with it.",
"DEP0104").IsNothing())
return;
}

Mutex::ScopedLock lock(environ_mutex);
#ifdef __POSIX__
node::Utf8Value key(info.GetIsolate(), property);
node::Utf8Value val(info.GetIsolate(), value);
setenv(*key, *val, 1);
#else // _WIN32
node::TwoByteValue key(info.GetIsolate(), property);
node::TwoByteValue val(info.GetIsolate(), 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
// Whether it worked or not, always return value.
info.GetReturnValue().Set(value);
}


static void EnvQuery(Local<Name> property,
const PropertyCallbackInfo<Integer>& info) {
Mutex::ScopedLock lock(environ_mutex);
int32_t rc = -1; // Not found unless proven otherwise.
if (property->IsString()) {
#ifdef __POSIX__
node::Utf8Value key(info.GetIsolate(), property);
if (getenv(*key))
rc = 0;
#else // _WIN32
node::TwoByteValue key(info.GetIsolate(), property);
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
SetLastError(ERROR_SUCCESS);
if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
GetLastError() == ERROR_SUCCESS) {
rc = 0;
if (key_ptr[0] == L'=') {
// Environment variables that start with '=' are hidden and read-only.
rc = static_cast<int32_t>(v8::ReadOnly) |
static_cast<int32_t>(v8::DontDelete) |
static_cast<int32_t>(v8::DontEnum);
}
}
#endif
}
if (rc != -1)
info.GetReturnValue().Set(rc);
}


static void EnvDeleter(Local<Name> property,
const PropertyCallbackInfo<Boolean>& info) {
Mutex::ScopedLock lock(environ_mutex);
if (property->IsString()) {
#ifdef __POSIX__
node::Utf8Value key(info.GetIsolate(), property);
unsetenv(*key);
#else
node::TwoByteValue key(info.GetIsolate(), property);
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
SetEnvironmentVariableW(key_ptr, nullptr);
#endif
}

// process.env never has non-configurable properties, so always
// return true like the tc39 delete operator.
info.GetReturnValue().Set(true);
}


static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
Environment* env = Environment::GetCurrent(info);
Isolate* isolate = env->isolate();
Local<Context> ctx = env->context();
Local<Function> fn = env->push_values_to_array_function();
Local<Value> argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
size_t idx = 0;

Mutex::ScopedLock lock(environ_mutex);
#ifdef __POSIX__
int size = 0;
while (environ[size])
size++;

Local<Array> envarr = Array::New(isolate);

for (int i = 0; i < size; ++i) {
const char* var = environ[i];
const char* s = strchr(var, '=');
const int length = s ? s - var : strlen(var);
argv[idx] = String::NewFromUtf8(isolate,
var,
v8::NewStringType::kNormal,
length).ToLocalChecked();
if (++idx >= arraysize(argv)) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
idx = 0;
}
}
if (idx > 0) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
}
#else // _WIN32
WCHAR* environment = GetEnvironmentStringsW();
if (environment == nullptr)
return; // This should not happen.
Local<Array> envarr = Array::New(isolate);
WCHAR* p = environment;
while (*p) {
WCHAR* s;
if (*p == L'=') {
// If the key starts with '=' it is a hidden environment variable.
p += wcslen(p) + 1;
continue;
} else {
s = wcschr(p, L'=');
}
if (!s) {
s = p + wcslen(p);
}
const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
const size_t two_byte_buffer_len = s - p;
argv[idx] = String::NewFromTwoByte(isolate,
two_byte_buffer,
String::kNormalString,
two_byte_buffer_len);
if (++idx >= arraysize(argv)) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
idx = 0;
}
p = s + wcslen(s) + 1;
}
if (idx > 0) {
fn->Call(ctx, envarr, idx, argv).ToLocalChecked();
}
FreeEnvironmentStringsW(environment);
#endif

info.GetReturnValue().Set(envarr);
}


static void GetParentProcessId(Local<Name> property,
const PropertyCallbackInfo<Value>& info) {
info.GetReturnValue().Set(Integer::New(info.GetIsolate(), uv_os_getppid()));
}


static Local<Object> GetFeatures(Environment* env) {
EscapableHandleScope scope(env->isolate());

Expand Down
23 changes: 23 additions & 0 deletions src/node_internals.h
Expand Up @@ -170,6 +170,9 @@ struct sockaddr;

namespace node {

extern Mutex process_mutex;
extern Mutex environ_mutex;

// Tells whether it is safe to call v8::Isolate::GetCurrent().
extern bool v8_initialized;

Expand Down Expand Up @@ -888,6 +891,26 @@ void StopProfilerIdleNotifier(const v8::FunctionCallbackInfo<v8::Value>& args);
void Umask(const v8::FunctionCallbackInfo<v8::Value>& args);
void Uptime(const v8::FunctionCallbackInfo<v8::Value>& args);

void EnvDeleter(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Boolean>& info);
void EnvGetter(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& info);
void EnvSetter(v8::Local<v8::Name> property,
v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<v8::Value>& info);
void EnvQuery(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Integer>& info);
void EnvEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info);

void GetParentProcessId(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& info);

void ProcessTitleGetter(v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& info);
void ProcessTitleSetter(v8::Local<v8::Name> property,
v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<void>& info);

#if defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__)
void SetGid(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetEGid(const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down

0 comments on commit 264c99f

Please sign in to comment.