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