You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1118 lines
36 KiB

#include "node.h"
#if (SCRIPT_ENGINE_TYPE == SCRIPT_ENGINE_V8) && SE_ENABLE_INSPECTOR
#include "env.h"
#include "http_parser.h"
#include "util.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __POSIX__
#include <unistd.h>
#endif
#define NODE_VERSION "JSB2.0" //cjh added
static inline const char *errno_string(int errorno) {
#define ERRNO_CASE(e) \
case e: return #e;
switch (errorno) {
#ifdef EACCES
ERRNO_CASE(EACCES);
#endif
#ifdef EADDRINUSE
ERRNO_CASE(EADDRINUSE);
#endif
#ifdef EADDRNOTAVAIL
ERRNO_CASE(EADDRNOTAVAIL);
#endif
#ifdef EAFNOSUPPORT
ERRNO_CASE(EAFNOSUPPORT);
#endif
#ifdef EAGAIN
ERRNO_CASE(EAGAIN);
#endif
#ifdef EWOULDBLOCK
#if EAGAIN != EWOULDBLOCK
ERRNO_CASE(EWOULDBLOCK);
#endif
#endif
#ifdef EALREADY
ERRNO_CASE(EALREADY);
#endif
#ifdef EBADF
ERRNO_CASE(EBADF);
#endif
#ifdef EBADMSG
ERRNO_CASE(EBADMSG);
#endif
#ifdef EBUSY
ERRNO_CASE(EBUSY);
#endif
#ifdef ECANCELED
ERRNO_CASE(ECANCELED);
#endif
#ifdef ECHILD
ERRNO_CASE(ECHILD);
#endif
#ifdef ECONNABORTED
ERRNO_CASE(ECONNABORTED);
#endif
#ifdef ECONNREFUSED
ERRNO_CASE(ECONNREFUSED);
#endif
#ifdef ECONNRESET
ERRNO_CASE(ECONNRESET);
#endif
#ifdef EDEADLK
ERRNO_CASE(EDEADLK);
#endif
#ifdef EDESTADDRREQ
ERRNO_CASE(EDESTADDRREQ);
#endif
#ifdef EDOM
ERRNO_CASE(EDOM);
#endif
#ifdef EDQUOT
ERRNO_CASE(EDQUOT);
#endif
#ifdef EEXIST
ERRNO_CASE(EEXIST);
#endif
#ifdef EFAULT
ERRNO_CASE(EFAULT);
#endif
#ifdef EFBIG
ERRNO_CASE(EFBIG);
#endif
#ifdef EHOSTUNREACH
ERRNO_CASE(EHOSTUNREACH);
#endif
#ifdef EIDRM
ERRNO_CASE(EIDRM);
#endif
#ifdef EILSEQ
ERRNO_CASE(EILSEQ);
#endif
#ifdef EINPROGRESS
ERRNO_CASE(EINPROGRESS);
#endif
#ifdef EINTR
ERRNO_CASE(EINTR);
#endif
#ifdef EINVAL
ERRNO_CASE(EINVAL);
#endif
#ifdef EIO
ERRNO_CASE(EIO);
#endif
#ifdef EISCONN
ERRNO_CASE(EISCONN);
#endif
#ifdef EISDIR
ERRNO_CASE(EISDIR);
#endif
#ifdef ELOOP
ERRNO_CASE(ELOOP);
#endif
#ifdef EMFILE
ERRNO_CASE(EMFILE);
#endif
#ifdef EMLINK
ERRNO_CASE(EMLINK);
#endif
#ifdef EMSGSIZE
ERRNO_CASE(EMSGSIZE);
#endif
#ifdef EMULTIHOP
ERRNO_CASE(EMULTIHOP);
#endif
#ifdef ENAMETOOLONG
ERRNO_CASE(ENAMETOOLONG);
#endif
#ifdef ENETDOWN
ERRNO_CASE(ENETDOWN);
#endif
#ifdef ENETRESET
ERRNO_CASE(ENETRESET);
#endif
#ifdef ENETUNREACH
ERRNO_CASE(ENETUNREACH);
#endif
#ifdef ENFILE
ERRNO_CASE(ENFILE);
#endif
#ifdef ENOBUFS
ERRNO_CASE(ENOBUFS);
#endif
#ifdef ENODATA
ERRNO_CASE(ENODATA);
#endif
#ifdef ENODEV
ERRNO_CASE(ENODEV);
#endif
#ifdef ENOENT
ERRNO_CASE(ENOENT);
#endif
#ifdef ENOEXEC
ERRNO_CASE(ENOEXEC);
#endif
#ifdef ENOLINK
ERRNO_CASE(ENOLINK);
#endif
#ifdef ENOLCK
#if ENOLINK != ENOLCK
ERRNO_CASE(ENOLCK);
#endif
#endif
#ifdef ENOMEM
ERRNO_CASE(ENOMEM);
#endif
#ifdef ENOMSG
ERRNO_CASE(ENOMSG);
#endif
#ifdef ENOPROTOOPT
ERRNO_CASE(ENOPROTOOPT);
#endif
#ifdef ENOSPC
ERRNO_CASE(ENOSPC);
#endif
#ifdef ENOSR
ERRNO_CASE(ENOSR);
#endif
#ifdef ENOSTR
ERRNO_CASE(ENOSTR);
#endif
#ifdef ENOSYS
ERRNO_CASE(ENOSYS);
#endif
#ifdef ENOTCONN
ERRNO_CASE(ENOTCONN);
#endif
#ifdef ENOTDIR
ERRNO_CASE(ENOTDIR);
#endif
#ifdef ENOTEMPTY
#if ENOTEMPTY != EEXIST
ERRNO_CASE(ENOTEMPTY);
#endif
#endif
#ifdef ENOTSOCK
ERRNO_CASE(ENOTSOCK);
#endif
#ifdef ENOTSUP
ERRNO_CASE(ENOTSUP);
#else
#ifdef EOPNOTSUPP
ERRNO_CASE(EOPNOTSUPP);
#endif
#endif
#ifdef ENOTTY
ERRNO_CASE(ENOTTY);
#endif
#ifdef ENXIO
ERRNO_CASE(ENXIO);
#endif
#ifdef EOVERFLOW
ERRNO_CASE(EOVERFLOW);
#endif
#ifdef EPERM
ERRNO_CASE(EPERM);
#endif
#ifdef EPIPE
ERRNO_CASE(EPIPE);
#endif
#ifdef EPROTO
ERRNO_CASE(EPROTO);
#endif
#ifdef EPROTONOSUPPORT
ERRNO_CASE(EPROTONOSUPPORT);
#endif
#ifdef EPROTOTYPE
ERRNO_CASE(EPROTOTYPE);
#endif
#ifdef ERANGE
ERRNO_CASE(ERANGE);
#endif
#ifdef EROFS
ERRNO_CASE(EROFS);
#endif
#ifdef ESPIPE
ERRNO_CASE(ESPIPE);
#endif
#ifdef ESRCH
ERRNO_CASE(ESRCH);
#endif
#ifdef ESTALE
ERRNO_CASE(ESTALE);
#endif
#ifdef ETIME
ERRNO_CASE(ETIME);
#endif
#ifdef ETIMEDOUT
ERRNO_CASE(ETIMEDOUT);
#endif
#ifdef ETXTBSY
ERRNO_CASE(ETXTBSY);
#endif
#ifdef EXDEV
ERRNO_CASE(EXDEV);
#endif
default: return "";
}
}
#ifdef __POSIX__
void RegisterSignalHandler(int signal,
void (*handler)(int signal),
bool reset_handler) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
#ifndef __FreeBSD__
// FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
// in turn set for a libthr wrapper. This leads to a crash.
// Work around the issue by manually setting SIG_DFL in the signal handler
sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
#endif
sigfillset(&sa.sa_mask);
CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
}
#endif // __POSIX__
using namespace v8;
namespace node {
static bool v8_is_profiling = false;
Local<Value> ErrnoException(Isolate *isolate,
int errorno,
const char *syscall,
const char *msg,
const char *path) {
Environment *env = Environment::GetCurrent(isolate);
Local<Value> e;
Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
if (msg == nullptr || msg[0] == '\0') {
msg = strerror(errorno);
}
Local<String> message = OneByteString(env->isolate(), msg);
Local<String> cons =
String::Concat(env->isolate(), estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
cons = String::Concat(env->isolate(), cons, message);
Local<String> path_string;
if (path != nullptr) {
// IDEA(bnoordhuis) It's questionable to interpret the file path as UTF-8.
path_string = String::NewFromUtf8(env->isolate(), path, v8::NewStringType::kNormal).ToLocalChecked();
}
if (path_string.IsEmpty() == false) {
cons = String::Concat(env->isolate(), cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '"));
cons = String::Concat(env->isolate(), cons, path_string);
cons = String::Concat(env->isolate(), cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'"));
}
e = Exception::Error(cons);
Local<Object> obj = e->ToObject(env->context()).ToLocalChecked();
obj->Set(env->context(), env->errno_string(), Integer::New(env->isolate(), errorno)).Check();
obj->Set(env->context(), env->code_string(), estring).Check();
if (path_string.IsEmpty() == false) {
obj->Set(env->context(), env->path_string(), path_string).Check();
}
if (syscall != nullptr) {
obj->Set(env->context(), env->syscall_string(), OneByteString(env->isolate(), syscall)).Check();
}
return e;
}
static Local<String> StringFromPath(Isolate *isolate, const char *path) {
#ifdef _WIN32
if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
return String::Concat(isolate, FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
String::NewFromUtf8(isolate, path + 8).ToLocalChecked());
} else if (strncmp(path, "\\\\?\\", 4) == 0) {
return String::NewFromUtf8(isolate, path + 4).ToLocalChecked();
}
#endif
return String::NewFromUtf8(isolate, path, v8::NewStringType::kNormal).ToLocalChecked();
}
Local<Value> UVException(Isolate *isolate,
int errorno,
const char *syscall,
const char *msg,
const char *path) {
return UVException(isolate, errorno, syscall, msg, path, nullptr);
}
Local<Value> UVException(Isolate *isolate,
int errorno,
const char *syscall,
const char *msg,
const char *path,
const char *dest) {
Environment *env = Environment::GetCurrent(isolate);
if (!msg || !msg[0])
msg = uv_strerror(errorno);
Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
Local<String> js_syscall = OneByteString(isolate, syscall);
Local<String> js_path;
Local<String> js_dest;
Local<String> js_msg = js_code;
js_msg = String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
js_msg = String::Concat(isolate, js_msg, OneByteString(isolate, msg));
js_msg = String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
js_msg = String::Concat(isolate, js_msg, js_syscall);
if (path != nullptr) {
js_path = StringFromPath(isolate, path);
js_msg = String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
js_msg = String::Concat(isolate, js_msg, js_path);
js_msg = String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
}
if (dest != nullptr) {
js_dest = StringFromPath(isolate, dest);
js_msg = String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
js_msg = String::Concat(isolate, js_msg, js_dest);
js_msg = String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
}
Local<Object> e = Exception::Error(js_msg)->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
e->Set(isolate->GetCurrentContext(), env->errno_string(), Integer::New(isolate, errorno)).Check();
e->Set(isolate->GetCurrentContext(), env->code_string(), js_code).Check();
e->Set(isolate->GetCurrentContext(), env->syscall_string(), js_syscall).Check();
if (!js_path.IsEmpty())
e->Set(isolate->GetCurrentContext(), env->path_string(), js_path).Check();
if (!js_dest.IsEmpty())
e->Set(isolate->GetCurrentContext(), env->dest_string(), js_dest).Check();
return e;
}
MaybeLocal<Value> MakeCallback(Environment *env,
Local<Value> recv,
const Local<Function> callback,
int argc,
Local<Value> argv[],
async_context asyncContext) {
// If you hit this assertion, you forgot to enter the v8::Context first.
CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
Local<Object> object;
// Environment::AsyncCallbackScope callback_scope(env);
// bool disposed_domain = false;
//
// if (recv->IsObject()) {
// object = recv.As<Object>();
// }
//
// if (env->using_domains()) {
// CHECK(recv->IsObject());
// disposed_domain = DomainEnter(env, object);
// if (disposed_domain) return Undefined(env->isolate());
// }
MaybeLocal<Value> ret;
// {
// AsyncHooks::ExecScope exec_scope(env, asyncContext.async_id,
// asyncContext.trigger_async_id);
//
// if (asyncContext.async_id != 0) {
// if (!AsyncWrap::EmitBefore(env, asyncContext.async_id))
// return Local<Value>();
// }
//
// ret = callback->Call(env->context(), recv, argc, argv);
//
// if (ret.IsEmpty()) {
// // NOTE: For backwards compatibility with public API we return Undefined()
// // if the top level call threw.
// return callback_scope.in_makecallback() ?
// ret : Undefined(env->isolate());
// }
//
// if (asyncContext.async_id != 0) {
// if (!AsyncWrap::EmitAfter(env, asyncContext.async_id))
// return Local<Value>();
// }
// }
//
// if (env->using_domains()) {
// disposed_domain = DomainExit(env, object);
// if (disposed_domain) return Undefined(env->isolate());
// }
//
// if (callback_scope.in_makecallback()) {
// return ret;
// }
//
// Environment::TickInfo* tick_info = env->tick_info();
//
// if (tick_info->length() == 0) {
// env->isolate()->RunMicrotasks();
// }
//
// // Make sure the stack unwound properly. If there are nested MakeCallback's
// // then it should return early and not reach this code.
// CHECK_EQ(env->current_async_id(), asyncContext.async_id);
// CHECK_EQ(env->trigger_id(), asyncContext.trigger_async_id);
//
// Local<Object> process = env->process_object();
//
// if (tick_info->length() == 0) {
// tick_info->set_index(0);
// return ret;
// }
//
// if (env->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
// return Undefined(env->isolate());
// }
return ret;
}
// Public MakeCallback()s
MaybeLocal<Value> MakeCallback(Isolate *isolate,
Local<Object> recv,
const char *method,
int argc,
Local<Value> argv[],
async_context asyncContext) {
Local<String> method_string =
String::NewFromUtf8(isolate, method, v8::NewStringType::kNormal)
.ToLocalChecked();
return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
}
MaybeLocal<Value> MakeCallback(Isolate *isolate,
Local<Object> recv,
Local<String> symbol,
int argc,
Local<Value> argv[],
async_context asyncContext) {
Local<Value> callback_v = recv->Get(isolate->GetCurrentContext(), symbol).ToLocalChecked();
if (callback_v.IsEmpty()) return Local<Value>();
if (!callback_v->IsFunction()) return Local<Value>();
Local<Function> callback = callback_v.As<Function>();
return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
}
MaybeLocal<Value> MakeCallback(Isolate *isolate,
Local<Object> recv,
Local<Function> callback,
int argc,
Local<Value> argv[],
async_context asyncContext) {
// Observe the following two subtleties:
//
// 1. The environment is retrieved from the callback function's context.
// 2. The context to enter is retrieved from the environment.
//
// Because of the AssignToContext() call in src/node_contextify.cc,
// the two contexts need not be the same.
Environment *env = Environment::GetCurrent(callback->GetCreationContext().ToLocalChecked());
Context::Scope context_scope(env->context());
return MakeCallback(env, recv.As<Value>(), callback, argc, argv,
asyncContext);
}
// Legacy MakeCallback()s
Local<Value> MakeCallback(Isolate *isolate,
Local<Object> recv,
const char *method,
int argc,
Local<Value> *argv) {
EscapableHandleScope handle_scope(isolate);
return handle_scope.Escape(
MakeCallback(isolate, recv, method, argc, argv, {0, 0})
.FromMaybe(Local<Value>()));
}
Local<Value> MakeCallback(Isolate *isolate,
Local<Object> recv,
Local<String> symbol,
int argc,
Local<Value> *argv) {
EscapableHandleScope handle_scope(isolate);
return handle_scope.Escape(
MakeCallback(isolate, recv, symbol, argc, argv, {0, 0})
.FromMaybe(Local<Value>()));
}
Local<Value> MakeCallback(Isolate *isolate,
Local<Object> recv,
Local<Function> callback,
int argc,
Local<Value> *argv) {
EscapableHandleScope handle_scope(isolate);
return handle_scope.Escape(
MakeCallback(isolate, recv, callback, argc, argv, {0, 0})
.FromMaybe(Local<Value>()));
}
IsolateData *CreateIsolateData(Isolate *isolate, uv_loop_t *loop) {
return new IsolateData(isolate, loop);
}
void FreeIsolateData(IsolateData *isolate_data) {
delete isolate_data;
}
Environment *CreateEnvironment(IsolateData *isolate_data,
Local<Context> context,
int argc,
const char *const *argv,
int exec_argc,
const char *const *exec_argv) {
Isolate *isolate = context->GetIsolate();
HandleScope handle_scope(isolate);
Context::Scope context_scope(context);
auto env = new Environment(isolate_data, context);
env->Start(argc, argv, exec_argc, exec_argv, v8_is_profiling);
return env;
}
void FreeEnvironment(Environment *env) {
delete env;
}
NO_RETURN void Abort() {
DumpBacktrace(stderr);
fflush(stderr);
ABORT_NO_BACKTRACE();
}
NO_RETURN void Assert(const char *const (*args)[4]) {
auto filename = (*args)[0];
auto linenum = (*args)[1];
auto message = (*args)[2];
auto function = (*args)[3];
char exepath[256];
size_t exepath_size = sizeof(exepath);
if (uv_exepath(exepath, &exepath_size))
snprintf(exepath, sizeof(exepath), "node");
char pid[12] = {0};
#ifndef _WIN32
snprintf(pid, sizeof(pid), "[%u]", getpid());
#endif
SE_LOGE("%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
exepath, pid, filename, linenum,
function, *function ? ":" : "", message);
Abort();
}
static void Abort(const FunctionCallbackInfo<Value> &args) {
Abort();
}
#define READONLY_PROPERTY(obj, str, var) \
do { \
obj->DefineOwnProperty(env->context(), \
OneByteString(env->isolate(), str), \
var, \
v8::ReadOnly) \
.FromJust(); \
} while (0)
#define READONLY_DONT_ENUM_PROPERTY(obj, str, var) \
do { \
obj->DefineOwnProperty(env->context(), \
OneByteString(env->isolate(), str), \
var, \
static_cast<v8::PropertyAttribute>(v8::ReadOnly | \
v8::DontEnum)) \
.FromJust(); \
} while (0)
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);
// REFINE(piscisaureus): protect with a lock
uv_set_process_title(*title);
}
void SetupProcessObject(Environment *env,
int argc,
const char *const *argv,
int exec_argc,
const char *const *exec_argv) {
HandleScope scope(env->isolate());
Local<Object> process = env->process_object();
auto title_string = FIXED_ONE_BYTE_STRING(env->isolate(), "title");
CHECK(process->SetAccessor(env->context(),
title_string,
ProcessTitleGetter,
ProcessTitleSetter,
env->as_external())
.FromJust());
// process.version
READONLY_PROPERTY(process,
"version",
FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
// process.moduleLoadList
READONLY_PROPERTY(process,
"moduleLoadList",
env->module_load_list_array());
// process.versions
Local<Object> versions = Object::New(env->isolate());
READONLY_PROPERTY(process, "versions", versions);
const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) "." NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR) "." NODE_STRINGIFY(HTTP_PARSER_VERSION_PATCH);
READONLY_PROPERTY(versions,
"http_parser",
FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version));
// +1 to get rid of the leading 'v'
READONLY_PROPERTY(versions,
"node",
OneByteString(env->isolate(), NODE_VERSION));
READONLY_PROPERTY(versions,
"v8",
OneByteString(env->isolate(), V8::GetVersion()));
READONLY_PROPERTY(versions,
"uv",
OneByteString(env->isolate(), uv_version_string()));
SE_LOGD("libuv version: %s\n", uv_version_string());
// READONLY_PROPERTY(versions,
// "zlib",
// FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
// READONLY_PROPERTY(versions,
// "ares",
// FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR));
// const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
// READONLY_PROPERTY(
// versions,
// "modules",
// FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));
// process._promiseRejectEvent
Local<Object> promiseRejectEvent = Object::New(env->isolate());
READONLY_DONT_ENUM_PROPERTY(process,
"_promiseRejectEvent",
promiseRejectEvent);
READONLY_PROPERTY(promiseRejectEvent,
"unhandled",
Integer::New(env->isolate(),
v8::kPromiseRejectWithNoHandler));
READONLY_PROPERTY(promiseRejectEvent,
"handled",
Integer::New(env->isolate(),
v8::kPromiseHandlerAddedAfterReject));
//#if HAVE_OPENSSL
// // Stupid code to slice out the version string.
// { // NOLINT(whitespace/braces)
// size_t i, j, k;
// int c;
// for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
// c = OPENSSL_VERSION_TEXT[i];
// if ('0' <= c && c <= '9') {
// for (j = i + 1; j < k; ++j) {
// c = OPENSSL_VERSION_TEXT[j];
// if (c == ' ')
// break;
// }
// break;
// }
// }
// READONLY_PROPERTY(
// versions,
// "openssl",
// OneByteString(env->isolate(), &OPENSSL_VERSION_TEXT[i], j - i));
// }
//#endif
// process.arch
READONLY_PROPERTY(process, "arch", OneByteString(env->isolate(), "x64")); //IDEA: cjh
// process.platform
READONLY_PROPERTY(process,
"platform",
OneByteString(env->isolate(), "macOS")); //IDEA: cjh
// process.release
Local<Object> release = Object::New(env->isolate());
READONLY_PROPERTY(process, "release", release);
READONLY_PROPERTY(release, "name", OneByteString(env->isolate(), "node"));
// if this is a release build and no explicit base has been set
// substitute the standard release download URL
#ifndef NODE_RELEASE_URLBASE
#if NODE_VERSION_IS_RELEASE
#define NODE_RELEASE_URLBASE "https://nodejs.org/download/release/"
#endif
#endif
#if defined(NODE_RELEASE_URLBASE)
#define NODE_RELEASE_URLPFX NODE_RELEASE_URLBASE "v" NODE_VERSION_STRING "/"
#define NODE_RELEASE_URLFPFX NODE_RELEASE_URLPFX "node-v" NODE_VERSION_STRING
READONLY_PROPERTY(release,
"sourceUrl",
OneByteString(env->isolate(),
NODE_RELEASE_URLFPFX ".tar.gz"));
READONLY_PROPERTY(release,
"headersUrl",
OneByteString(env->isolate(),
NODE_RELEASE_URLFPFX "-headers.tar.gz"));
#ifdef _WIN32
READONLY_PROPERTY(release,
"libUrl",
OneByteString(env->isolate(),
strcmp(NODE_ARCH, "ia32") ? NODE_RELEASE_URLPFX "win-" NODE_ARCH "/node.lib"
: NODE_RELEASE_URLPFX
"win-x86/node.lib"));
#endif
#endif
// process.argv
Local<Array> arguments = Array::New(env->isolate(), argc);
for (int i = 0; i < argc; ++i) {
arguments->Set(env->context(), i, String::NewFromUtf8(env->isolate(), argv[i], v8::NewStringType::kNormal).ToLocalChecked()).Check();
}
process->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "argv"), arguments).Check();
// process.execArgv
Local<Array> exec_arguments = Array::New(env->isolate(), exec_argc);
for (int i = 0; i < exec_argc; ++i) {
exec_arguments->Set(env->context(), i, String::NewFromUtf8(env->isolate(), exec_argv[i], v8::NewStringType::kNormal).ToLocalChecked()).Check();
}
process->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "execArgv"),
exec_arguments)
.Check();
// create process.env
// Local<ObjectTemplate> process_env_template =
// ObjectTemplate::New(env->isolate());
// process_env_template->SetHandler(NamedPropertyHandlerConfiguration(
// EnvGetter,
// EnvSetter,
// EnvQuery,
// EnvDeleter,
// EnvEnumerator,
// env->as_external()));
//
// Local<Object> process_env =
// process_env_template->NewInstance(env->context()).ToLocalChecked();
// process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "env"), process_env);
//
// READONLY_PROPERTY(process, "pid", Integer::New(env->isolate(), getpid()));
// READONLY_PROPERTY(process, "features", GetFeatures(env));
//
// auto need_immediate_callback_string =
// FIXED_ONE_BYTE_STRING(env->isolate(), "_needImmediateCallback");
// CHECK(process->SetAccessor(env->context(), need_immediate_callback_string,
// NeedImmediateCallbackGetter,
// NeedImmediateCallbackSetter,
// env->as_external()).FromJust());
//
// // -e, --eval
// if (eval_string) {
// READONLY_PROPERTY(process,
// "_eval",
// String::NewFromUtf8(env->isolate(), eval_string));
// }
//
// // -p, --print
// if (print_eval) {
// READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
// }
//
// // -c, --check
// if (syntax_check_only) {
// READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
// }
//
// // -i, --interactive
// if (force_repl) {
// READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
// }
// // -r, --require
// if (!preload_modules.empty()) {
// Local<Array> array = Array::New(env->isolate());
// for (unsigned int i = 0; i < preload_modules.size(); ++i) {
// Local<String> module = String::NewFromUtf8(env->isolate(),
// preload_modules[i].c_str());
// array->Set(i, module);
// }
// READONLY_PROPERTY(process,
// "_preload_modules",
// array);
//
// preload_modules.clear();
// }
//
// // --no-deprecation
// if (no_deprecation) {
// READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
// }
//
// // --no-warnings
// if (no_process_warnings) {
// READONLY_PROPERTY(process, "noProcessWarnings", True(env->isolate()));
// }
//
// // --trace-warnings
// if (trace_warnings) {
// READONLY_PROPERTY(process, "traceProcessWarnings", True(env->isolate()));
// }
//
// // --throw-deprecation
// if (throw_deprecation) {
// READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
// }
//
//#ifdef NODE_NO_BROWSER_GLOBALS
// // configure --no-browser-globals
// READONLY_PROPERTY(process, "_noBrowserGlobals", True(env->isolate()));
//#endif // NODE_NO_BROWSER_GLOBALS
//
// // --prof-process
// if (prof_process) {
// READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
// }
//
// // --trace-deprecation
// if (trace_deprecation) {
// READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
// }
//
// // REFINE(refack): move the following 3 to `node_config`
// // --inspect-brk
// if (debug_options.wait_for_connect()) {
// READONLY_DONT_ENUM_PROPERTY(process,
// "_breakFirstLine", True(env->isolate()));
// }
//
// // --inspect --debug-brk
// if (debug_options.deprecated_invocation()) {
// READONLY_DONT_ENUM_PROPERTY(process,
// "_deprecatedDebugBrk", True(env->isolate()));
// }
//
// // --debug or, --debug-brk without --inspect
// if (debug_options.invalid_invocation()) {
// READONLY_DONT_ENUM_PROPERTY(process,
// "_invalidDebug", True(env->isolate()));
// }
//
// // --security-revert flags
//#define V(code, _, __) \
//do { \
//if (IsReverted(REVERT_ ## code)) { \
//READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \
//} \
//} while (0);
// REVERSIONS(V)
//#undef V
//
// size_t exec_path_len = 2 * PATH_MAX;
// char* exec_path = new char[exec_path_len];
// Local<String> exec_path_value;
// if (uv_exepath(exec_path, &exec_path_len) == 0) {
// exec_path_value = String::NewFromUtf8(env->isolate(),
// exec_path,
// String::kNormalString,
// exec_path_len);
// } else {
// exec_path_value = String::NewFromUtf8(env->isolate(), argv[0]);
// }
// process->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
// exec_path_value);
// delete[] exec_path;
//
// auto debug_port_string = FIXED_ONE_BYTE_STRING(env->isolate(), "debugPort");
// CHECK(process->SetAccessor(env->context(),
// debug_port_string,
// DebugPortGetter,
// DebugPortSetter,
// env->as_external()).FromJust());
//
// // define various internal methods
// env->SetMethod(process,
// "_startProfilerIdleNotifier",
// StartProfilerIdleNotifier);
// env->SetMethod(process,
// "_stopProfilerIdleNotifier",
// StopProfilerIdleNotifier);
// env->SetMethod(process, "_getActiveRequests", GetActiveRequests);
// env->SetMethod(process, "_getActiveHandles", GetActiveHandles);
// env->SetMethod(process, "reallyExit", Exit);
// env->SetMethod(process, "abort", Abort);
// env->SetMethod(process, "chdir", Chdir);
// env->SetMethod(process, "cwd", Cwd);
//
// env->SetMethod(process, "umask", Umask);
//
//#if defined(__POSIX__) && !defined(__ANDROID__)
// env->SetMethod(process, "getuid", GetUid);
// env->SetMethod(process, "geteuid", GetEUid);
// env->SetMethod(process, "setuid", SetUid);
// env->SetMethod(process, "seteuid", SetEUid);
//
// env->SetMethod(process, "setgid", SetGid);
// env->SetMethod(process, "setegid", SetEGid);
// env->SetMethod(process, "getgid", GetGid);
// env->SetMethod(process, "getegid", GetEGid);
//
// env->SetMethod(process, "getgroups", GetGroups);
// env->SetMethod(process, "setgroups", SetGroups);
// env->SetMethod(process, "initgroups", InitGroups);
//#endif // __POSIX__ && !defined(__ANDROID__)
//
// env->SetMethod(process, "_kill", Kill);
//
// env->SetMethod(process, "_debugProcess", DebugProcess);
// env->SetMethod(process, "_debugPause", DebugPause);
// env->SetMethod(process, "_debugEnd", DebugEnd);
//
// env->SetMethod(process, "hrtime", Hrtime);
//
// env->SetMethod(process, "cpuUsage", CPUUsage);
//
// env->SetMethod(process, "dlopen", DLOpen);
//
// env->SetMethod(process, "uptime", Uptime);
// env->SetMethod(process, "memoryUsage", MemoryUsage);
//
// env->SetMethod(process, "binding", Binding);
// env->SetMethod(process, "_linkedBinding", LinkedBinding);
//
// env->SetMethod(process, "_setupProcessObject", SetupProcessObject);
// env->SetMethod(process, "_setupNextTick", SetupNextTick);
// env->SetMethod(process, "_setupPromises", SetupPromises);
// env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
// pre-set _events object for faster emit checks
Local<Object> events_obj = Object::New(env->isolate());
CHECK(events_obj->SetPrototype(env->context(),
Null(env->isolate()))
.FromJust());
process->Set(env->context(), env->events_string(), events_obj).Check();
}
#undef READONLY_PROPERTY
} // namespace node
#endif // #if (SCRIPT_ENGINE_TYPE == SCRIPT_ENGINE_V8) && SE_ENABLE_INSPECTOR