Skip to content

Commit

Permalink
process: move C++ process events into node_process_events.cc
Browse files Browse the repository at this point in the history
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: nodejs#25397
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
joyeecheung authored and BridgeAR committed Jan 17, 2019
1 parent 2ed3fa1 commit 28baf26
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 113 deletions.
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,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',
Expand Down
17 changes: 2 additions & 15 deletions src/inspector_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
105 changes: 7 additions & 98 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -586,82 +584,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()) {
Expand Down Expand Up @@ -1164,19 +1086,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());
Expand All @@ -1189,15 +1106,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()
Expand Down
9 changes: 9 additions & 0 deletions src/node_process.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
103 changes: 103 additions & 0 deletions src/node_process_events.cc
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 28baf26

Please sign in to comment.