process: move C++ process events into node_process_events.cc

Move the C++ `process.emit` and `process.emitWarning` methods
from `node.cc` into into `node_process_events.cc`, and
reuse the implementation in other places that need to do
`process.emit` in C++.

PR-URL: https://github.com/nodejs/node/pull/25397
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
Joyee Cheung 2018-12-31 22:59:40 +08:00
parent 7824280b58
commit 84f0581d36
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
5 changed files with 122 additions and 113 deletions

View File

@ -370,6 +370,7 @@
'src/node_perf.cc',
'src/node_platform.cc',
'src/node_postmortem_metadata.cc',
'src/node_process_events.cc',
'src/node_process_methods.cc',
'src/node_process_object.cc',
'src/node_serdes.cc',

View File

@ -370,26 +370,13 @@ class SameThreadInspectorSession : public InspectorSession {
void NotifyClusterWorkersDebugEnabled(Environment* env) {
Isolate* isolate = env->isolate();
HandleScope handle_scope(isolate);
auto context = env->context();
Local<Context> context = env->context();
// Send message to enable debug in cluster workers
Local<Object> process_object = env->process_object();
Local<Value> emit_fn =
process_object->Get(context, FIXED_ONE_BYTE_STRING(isolate, "emit"))
.ToLocalChecked();
// In case the thread started early during the startup
if (!emit_fn->IsFunction())
return;
Local<Object> message = Object::New(isolate);
message->Set(context, FIXED_ONE_BYTE_STRING(isolate, "cmd"),
FIXED_ONE_BYTE_STRING(isolate, "NODE_DEBUG_ENABLED")).FromJust();
Local<Value> argv[] = {
FIXED_ONE_BYTE_STRING(isolate, "internalMessage"),
message
};
MakeCallback(env->isolate(), process_object, emit_fn.As<Function>(),
arraysize(argv), argv, {0, 0});
ProcessEmit(env, "internalMessage", message);
}
#ifdef _WIN32

View File

@ -124,8 +124,6 @@ using v8::Maybe;
using v8::MaybeLocal;
using v8::Message;
using v8::MicrotasksPolicy;
using v8::NewStringType;
using v8::Nothing;
using v8::Object;
using v8::ObjectTemplate;
using v8::Script;
@ -582,82 +580,6 @@ void Exit(const FunctionCallbackInfo<Value>& args) {
env->Exit(code);
}
static Maybe<bool> ProcessEmitWarningGeneric(Environment* env,
const char* warning,
const char* type = nullptr,
const char* code = nullptr) {
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
Local<Object> process = env->process_object();
Local<Value> emit_warning;
if (!process->Get(env->context(),
env->emit_warning_string()).ToLocal(&emit_warning)) {
return Nothing<bool>();
}
if (!emit_warning->IsFunction()) return Just(false);
int argc = 0;
Local<Value> args[3]; // warning, type, code
// The caller has to be able to handle a failure anyway, so we might as well
// do proper error checking for string creation.
if (!String::NewFromUtf8(env->isolate(),
warning,
NewStringType::kNormal).ToLocal(&args[argc++])) {
return Nothing<bool>();
}
if (type != nullptr) {
if (!String::NewFromOneByte(env->isolate(),
reinterpret_cast<const uint8_t*>(type),
NewStringType::kNormal)
.ToLocal(&args[argc++])) {
return Nothing<bool>();
}
if (code != nullptr &&
!String::NewFromOneByte(env->isolate(),
reinterpret_cast<const uint8_t*>(code),
NewStringType::kNormal)
.ToLocal(&args[argc++])) {
return Nothing<bool>();
}
}
// MakeCallback() unneeded because emitWarning is internal code, it calls
// process.emit('warning', ...), but does so on the nextTick.
if (emit_warning.As<Function>()->Call(env->context(),
process,
argc,
args).IsEmpty()) {
return Nothing<bool>();
}
return Just(true);
}
// Call process.emitWarning(str), fmt is a snprintf() format string
Maybe<bool> ProcessEmitWarning(Environment* env, const char* fmt, ...) {
char warning[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(warning, sizeof(warning), fmt, ap);
va_end(ap);
return ProcessEmitWarningGeneric(env, warning);
}
Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
const char* warning,
const char* deprecation_code) {
return ProcessEmitWarningGeneric(env,
warning,
"DeprecationWarning",
deprecation_code);
}
static void OnMessage(Local<Message> message, Local<Value> error) {
Isolate* isolate = message->GetIsolate();
switch (message->ErrorLevel()) {
@ -1160,19 +1082,14 @@ void RunBeforeExit(Environment* env) {
void EmitBeforeExit(Environment* env) {
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
Local<Object> process_object = env->process_object();
Local<String> exit_code = env->exit_code_string();
Local<Value> args[] = {
FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
process_object->Get(env->context(), exit_code).ToLocalChecked()
->ToInteger(env->context()).ToLocalChecked()
};
MakeCallback(env->isolate(),
process_object, "emit", arraysize(args), args,
{0, 0}).ToLocalChecked();
Local<Value> exit_code = env->process_object()
->Get(env->context(), env->exit_code_string())
.ToLocalChecked()
->ToInteger(env->context())
.ToLocalChecked();
ProcessEmit(env, "beforeExit", exit_code).ToLocalChecked();
}
int EmitExit(Environment* env) {
// process.emit('exit')
HandleScope handle_scope(env->isolate());
@ -1185,15 +1102,7 @@ int EmitExit(Environment* env) {
Local<String> exit_code = env->exit_code_string();
int code = process_object->Get(env->context(), exit_code).ToLocalChecked()
->Int32Value(env->context()).ToChecked();
Local<Value> args[] = {
FIXED_ONE_BYTE_STRING(env->isolate(), "exit"),
Integer::New(env->isolate(), code)
};
MakeCallback(env->isolate(),
process_object, "emit", arraysize(args), args,
{0, 0}).ToLocalChecked();
ProcessEmit(env, "exit", Integer::New(env->isolate(), code));
// Reload exit code, it may be changed by `emit('exit')`
return process_object->Get(env->context(), exit_code).ToLocalChecked()

View File

@ -17,6 +17,15 @@ v8::Local<v8::Object> CreateEnvVarProxy(v8::Local<v8::Context> context,
// function, it is useful to bypass JavaScript entirely.
void RawDebug(const v8::FunctionCallbackInfo<v8::Value>& args);
v8::MaybeLocal<v8::Value> ProcessEmit(Environment* env,
const char* event,
v8::Local<v8::Value> message);
v8::Maybe<bool> ProcessEmitWarningGeneric(Environment* env,
const char* warning,
const char* type = nullptr,
const char* code = nullptr);
v8::Maybe<bool> ProcessEmitWarning(Environment* env, const char* fmt, ...);
v8::Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
const char* warning,

103
src/node_process_events.cc Normal file
View File

@ -0,0 +1,103 @@
#include <stdarg.h>
#include "env.h"
#include "node_internals.h"
#include "node_process.h"
namespace node {
using v8::Context;
using v8::Function;
using v8::HandleScope;
using v8::Isolate;
using v8::Just;
using v8::Local;
using v8::Maybe;
using v8::MaybeLocal;
using v8::NewStringType;
using v8::Nothing;
using v8::Object;
using v8::String;
using v8::Value;
MaybeLocal<Value> ProcessEmit(Environment* env,
const char* event,
Local<Value> message) {
// Send message to enable debug in cluster workers
Local<Object> process = env->process_object();
Isolate* isolate = env->isolate();
Local<Value> argv[] = {OneByteString(isolate, event), message};
return MakeCallback(isolate, process, "emit", arraysize(argv), argv, {0, 0});
}
Maybe<bool> ProcessEmitWarningGeneric(Environment* env,
const char* warning,
const char* type,
const char* code) {
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
Local<Object> process = env->process_object();
Local<Value> emit_warning;
if (!process->Get(env->context(), env->emit_warning_string())
.ToLocal(&emit_warning)) {
return Nothing<bool>();
}
if (!emit_warning->IsFunction()) return Just(false);
int argc = 0;
Local<Value> args[3]; // warning, type, code
// The caller has to be able to handle a failure anyway, so we might as well
// do proper error checking for string creation.
if (!String::NewFromUtf8(env->isolate(), warning, NewStringType::kNormal)
.ToLocal(&args[argc++])) {
return Nothing<bool>();
}
if (type != nullptr) {
if (!String::NewFromOneByte(env->isolate(),
reinterpret_cast<const uint8_t*>(type),
NewStringType::kNormal)
.ToLocal(&args[argc++])) {
return Nothing<bool>();
}
if (code != nullptr &&
!String::NewFromOneByte(env->isolate(),
reinterpret_cast<const uint8_t*>(code),
NewStringType::kNormal)
.ToLocal(&args[argc++])) {
return Nothing<bool>();
}
}
// MakeCallback() unneeded because emitWarning is internal code, it calls
// process.emit('warning', ...), but does so on the nextTick.
if (emit_warning.As<Function>()
->Call(env->context(), process, argc, args)
.IsEmpty()) {
return Nothing<bool>();
}
return Just(true);
}
// Call process.emitWarning(str), fmt is a snprintf() format string
Maybe<bool> ProcessEmitWarning(Environment* env, const char* fmt, ...) {
char warning[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(warning, sizeof(warning), fmt, ap);
va_end(ap);
return ProcessEmitWarningGeneric(env, warning);
}
Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
const char* warning,
const char* deprecation_code) {
return ProcessEmitWarningGeneric(
env, warning, "DeprecationWarning", deprecation_code);
}
} // namespace node