| #include <cstdarg> |
| #include <set> |
| |
| #include "env-inl.h" |
| #include "node_process.h" |
| #include "util.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 |
| Isolate* isolate = env->isolate(); |
| |
| Local<String> event_string; |
| if (!String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(event)) |
| .ToLocal(&event_string)) return MaybeLocal<Value>(); |
| |
| Local<Object> process = env->process_object(); |
| Local<Value> argv[] = {event_string, 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) { |
| if (!env->can_call_into_js()) return Just(false); |
| |
| 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); |
| } |
| |
| |
| std::set<std::string> experimental_warnings; |
| |
| Maybe<bool> ProcessEmitExperimentalWarning(Environment* env, |
| const char* warning) { |
| if (experimental_warnings.find(warning) != experimental_warnings.end()) |
| return Nothing<bool>(); |
| |
| experimental_warnings.insert(warning); |
| std::string message(warning); |
| message.append( |
| " is an experimental feature. This feature could change at any time"); |
| return ProcessEmitWarningGeneric(env, message.c_str(), "ExperimentalWarning"); |
| } |
| |
| Maybe<bool> ProcessEmitDeprecationWarning(Environment* env, |
| const char* warning, |
| const char* deprecation_code) { |
| return ProcessEmitWarningGeneric( |
| env, warning, "DeprecationWarning", deprecation_code); |
| } |
| |
| } // namespace node |