• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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