1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22#include "uv.h" 23#include "env-inl.h" 24#include "node.h" 25#include "node_external_reference.h" 26#include "node_process-inl.h" 27 28namespace node { 29 30namespace per_process { 31struct UVError { 32 int value; 33 const char* name; 34 const char* message; 35}; 36 37// We only expand the macro once here to reduce the amount of code 38// generated. 39static const struct UVError uv_errors_map[] = { 40#define V(name, message) {UV_##name, #name, message}, 41 UV_ERRNO_MAP(V) 42#undef V 43}; 44} // namespace per_process 45 46namespace uv { 47 48using v8::Array; 49using v8::Context; 50using v8::DontDelete; 51using v8::FunctionCallbackInfo; 52using v8::Integer; 53using v8::Isolate; 54using v8::Local; 55using v8::Map; 56using v8::Object; 57using v8::PropertyAttribute; 58using v8::ReadOnly; 59using v8::String; 60using v8::Value; 61 62void ErrName(const FunctionCallbackInfo<Value>& args) { 63 Environment* env = Environment::GetCurrent(args); 64 if (env->options()->pending_deprecation && env->EmitErrNameWarning()) { 65 if (ProcessEmitDeprecationWarning( 66 env, 67 "Directly calling process.binding('uv').errname(<val>) is being" 68 " deprecated. " 69 "Please make sure to use util.getSystemErrorName() instead.", 70 "DEP0119").IsNothing()) 71 return; 72 } 73 int err; 74 if (!args[0]->Int32Value(env->context()).To(&err)) return; 75 CHECK_LT(err, 0); 76 char name[50]; 77 uv_err_name_r(err, name, sizeof(name)); 78 args.GetReturnValue().Set(OneByteString(env->isolate(), name)); 79} 80 81void GetErrMap(const FunctionCallbackInfo<Value>& args) { 82 Environment* env = Environment::GetCurrent(args); 83 Isolate* isolate = env->isolate(); 84 Local<Context> context = env->context(); 85 86 // This can't return a SafeMap, because the uv binding can be referenced 87 // by user code by using `process.binding('uv').getErrorMap()`: 88 Local<Map> err_map = Map::New(isolate); 89 90 size_t errors_len = arraysize(per_process::uv_errors_map); 91 for (size_t i = 0; i < errors_len; ++i) { 92 const auto& error = per_process::uv_errors_map[i]; 93 Local<Value> arr[] = {OneByteString(isolate, error.name), 94 OneByteString(isolate, error.message)}; 95 if (err_map 96 ->Set(context, 97 Integer::New(isolate, error.value), 98 Array::New(isolate, arr, arraysize(arr))) 99 .IsEmpty()) { 100 return; 101 } 102 } 103 104 args.GetReturnValue().Set(err_map); 105} 106 107void Initialize(Local<Object> target, 108 Local<Value> unused, 109 Local<Context> context, 110 void* priv) { 111 Environment* env = Environment::GetCurrent(context); 112 Isolate* isolate = env->isolate(); 113 SetConstructorFunction( 114 context, target, "errname", NewFunctionTemplate(isolate, ErrName)); 115 116 // TODO(joyeecheung): This should be deprecated in user land in favor of 117 // `util.getSystemErrorName(err)`. 118 PropertyAttribute attributes = 119 static_cast<PropertyAttribute>(ReadOnly | DontDelete); 120 size_t errors_len = arraysize(per_process::uv_errors_map); 121 const std::string prefix = "UV_"; 122 for (size_t i = 0; i < errors_len; ++i) { 123 const auto& error = per_process::uv_errors_map[i]; 124 const std::string prefixed_name = prefix + error.name; 125 Local<String> name = OneByteString(isolate, prefixed_name.c_str()); 126 Local<Integer> value = Integer::New(isolate, error.value); 127 target->DefineOwnProperty(context, name, value, attributes).Check(); 128 } 129 130 SetMethod(context, target, "getErrorMap", GetErrMap); 131} 132 133void RegisterExternalReferences(ExternalReferenceRegistry* registry) { 134 registry->Register(ErrName); 135 registry->Register(GetErrMap); 136} 137} // namespace uv 138} // namespace node 139 140NODE_BINDING_CONTEXT_AWARE_INTERNAL(uv, node::uv::Initialize) 141NODE_BINDING_EXTERNAL_REFERENCE(uv, node::uv::RegisterExternalReferences) 142