1 #include <cstdarg>
2 #include <set>
3
4 #include "env-inl.h"
5 #include "node_process.h"
6 #include "util.h"
7
8 namespace node {
9 using v8::Context;
10 using v8::Function;
11 using v8::HandleScope;
12 using v8::Isolate;
13 using v8::Just;
14 using v8::Local;
15 using v8::Maybe;
16 using v8::MaybeLocal;
17 using v8::NewStringType;
18 using v8::Nothing;
19 using v8::Object;
20 using v8::String;
21 using v8::Value;
22
ProcessEmit(Environment * env,const char * event,Local<Value> message)23 MaybeLocal<Value> ProcessEmit(Environment* env,
24 const char* event,
25 Local<Value> message) {
26 // Send message to enable debug in cluster workers
27 Isolate* isolate = env->isolate();
28
29 Local<String> event_string;
30 if (!String::NewFromOneByte(isolate,
31 reinterpret_cast<const uint8_t*>(event),
32 NewStringType::kNormal)
33 .ToLocal(&event_string)) return MaybeLocal<Value>();
34
35 Local<Object> process = env->process_object();
36 Local<Value> argv[] = {event_string, message};
37 return MakeCallback(isolate, process, "emit", arraysize(argv), argv, {0, 0});
38 }
39
ProcessEmitWarningGeneric(Environment * env,const char * warning,const char * type,const char * code)40 Maybe<bool> ProcessEmitWarningGeneric(Environment* env,
41 const char* warning,
42 const char* type,
43 const char* code) {
44 if (!env->can_call_into_js()) return Just(false);
45
46 HandleScope handle_scope(env->isolate());
47 Context::Scope context_scope(env->context());
48
49 Local<Object> process = env->process_object();
50 Local<Value> emit_warning;
51 if (!process->Get(env->context(), env->emit_warning_string())
52 .ToLocal(&emit_warning)) {
53 return Nothing<bool>();
54 }
55
56 if (!emit_warning->IsFunction()) return Just(false);
57
58 int argc = 0;
59 Local<Value> args[3]; // warning, type, code
60
61 // The caller has to be able to handle a failure anyway, so we might as well
62 // do proper error checking for string creation.
63 if (!String::NewFromUtf8(env->isolate(), warning, NewStringType::kNormal)
64 .ToLocal(&args[argc++])) {
65 return Nothing<bool>();
66 }
67 if (type != nullptr) {
68 if (!String::NewFromOneByte(env->isolate(),
69 reinterpret_cast<const uint8_t*>(type),
70 NewStringType::kNormal)
71 .ToLocal(&args[argc++])) {
72 return Nothing<bool>();
73 }
74 if (code != nullptr &&
75 !String::NewFromOneByte(env->isolate(),
76 reinterpret_cast<const uint8_t*>(code),
77 NewStringType::kNormal)
78 .ToLocal(&args[argc++])) {
79 return Nothing<bool>();
80 }
81 }
82
83 // MakeCallback() unneeded because emitWarning is internal code, it calls
84 // process.emit('warning', ...), but does so on the nextTick.
85 if (emit_warning.As<Function>()
86 ->Call(env->context(), process, argc, args)
87 .IsEmpty()) {
88 return Nothing<bool>();
89 }
90 return Just(true);
91 }
92
93 // Call process.emitWarning(str), fmt is a snprintf() format string
ProcessEmitWarning(Environment * env,const char * fmt,...)94 Maybe<bool> ProcessEmitWarning(Environment* env, const char* fmt, ...) {
95 char warning[1024];
96 va_list ap;
97
98 va_start(ap, fmt);
99 vsnprintf(warning, sizeof(warning), fmt, ap);
100 va_end(ap);
101
102 return ProcessEmitWarningGeneric(env, warning);
103 }
104
105
106 std::set<std::string> experimental_warnings;
107
ProcessEmitExperimentalWarning(Environment * env,const char * warning)108 Maybe<bool> ProcessEmitExperimentalWarning(Environment* env,
109 const char* warning) {
110 if (experimental_warnings.find(warning) != experimental_warnings.end())
111 return Nothing<bool>();
112
113 experimental_warnings.insert(warning);
114 std::string message(warning);
115 message.append(
116 " is an experimental feature. This feature could change at any time");
117 return ProcessEmitWarningGeneric(env, message.c_str(), "ExperimentalWarning");
118 }
119
ProcessEmitDeprecationWarning(Environment * env,const char * warning,const char * deprecation_code)120 Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
121 const char* warning,
122 const char* deprecation_code) {
123 return ProcessEmitWarningGeneric(
124 env, warning, "DeprecationWarning", deprecation_code);
125 }
126
127 } // namespace node
128