diff --git a/binding.gyp b/binding.gyp index 651ff59..531c3c1 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,11 +2,20 @@ 'targets': [ { 'target_name': 'raw', + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions' ], + 'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', + 'CLANG_CXX_LIBRARY': 'libc++', + 'MACOSX_DEPLOYMENT_TARGET': '10.7', + }, + 'msvs_settings': { + 'VCCLCompilerTool': { 'ExceptionHandling': 1 }, + }, 'sources': [ 'src/raw.cc' ], "include_dirs" : [ - " SocketWrap_constructor; +static Napi::FunctionReference SocketWrap_constructor; -void InitAll (Local exports) { - ExportConstants (exports); - ExportFunctions (exports); +Napi::Object InitAll (Napi::Env env, Napi::Object exports) { + ExportConstants (env, exports); + ExportFunctions (env, exports); - SocketWrap::Init (exports); + SocketWrap::Init (env, exports); + + return exports; } -NODE_MODULE(raw, InitAll) +NODE_API_MODULE(raw, InitAll) -NAN_METHOD(CreateChecksum) { - Nan::HandleScope scope; +Napi::Value CreateChecksum(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); if (info.Length () < 2) { - Nan::ThrowError("At least one argument is required"); - return; + Napi::Error::New(env, "At least one argument is required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsUint32 ()) { - Nan::ThrowTypeError("Start with argument must be an unsigned integer"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Start with argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - uint32_t start_with = Nan::To(info[0]).ToLocalChecked()->Value(); + uint32_t start_with = info[0].As(); if (start_with > 65535) { - Nan::ThrowRangeError("Start with argument cannot be larger than 65535"); - return; + Napi::RangeError::New(env, "Start with argument cannot be larger than 65535").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! node::Buffer::HasInstance (info[1])) { - Nan::ThrowTypeError("Buffer argument must be a node Buffer object"); - return; + if (! info[1].IsBuffer()) { + Napi::TypeError::New(env, "Buffer argument must be a node Buffer object").ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local buffer = Nan::To(info[1]).ToLocalChecked(); - char *data = node::Buffer::Data (buffer); - size_t length = node::Buffer::Length (buffer); + Napi::Buffer buffer = info[1].As >(); + char *data = buffer.Data(); + size_t length = buffer.Length(); unsigned int offset = 0; if (info.Length () > 2) { - if (! info[2]->IsUint32 ()) { - Nan::ThrowTypeError("Offset argument must be an unsigned integer"); - return; + if (! info[2].IsNumber ()) { + Napi::TypeError::New(env, "Offset argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - offset = Nan::To(info[2]).ToLocalChecked()->Value(); + offset = info[2].As(); if (offset >= length) { - Nan::ThrowRangeError("Offset argument must be smaller than length of the buffer"); - return; + Napi::RangeError::New(env, "Offset argument must be smaller than length of the buffer").ThrowAsJavaScriptException(); + + return env.Undefined(); } } if (info.Length () > 3) { - if (! info[3]->IsUint32 ()) { - Nan::ThrowTypeError("Length argument must be an unsigned integer"); - return; + if (! info[3].IsNumber ()) { + Napi::TypeError::New(env, "Length argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - unsigned int new_length = Nan::To(info[3]).ToLocalChecked()->Value(); + unsigned int new_length = info[3].As(); if (new_length > length) { - Nan::ThrowRangeError("Length argument must be smaller than length of the buffer"); - return; + Napi::RangeError::New(env, "Length argument must be smaller than length of the buffer").ThrowAsJavaScriptException(); + + return env.Undefined(); } length = new_length; } @@ -112,162 +123,170 @@ NAN_METHOD(CreateChecksum) { uint16_t sum = checksum ((uint16_t) start_with, (unsigned char *) data + offset, length); - Local number = Nan::New(sum); - - info.GetReturnValue().Set(number); + Napi::Number number = Napi::Number::New(env, sum); + return number; } -NAN_METHOD(Htonl) { - Nan::HandleScope scope; +Napi::Value Htonl(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); if (info.Length () < 1) { - Nan::ThrowError("One arguments is required"); - return; + Napi::Error::New(env, "One arguments is required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsUint32 ()) { - Nan::ThrowTypeError("Number must be a 32 unsigned integer"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Number must be a 32 unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - unsigned int number = Nan::To(info[0]).ToLocalChecked()->Value(); - Local converted = Nan::New((unsigned int) htonl (number)); + unsigned int number = info[0].As(); + Napi::Number converted = Napi::Number::New(env, (unsigned int) htonl (number)); - info.GetReturnValue().Set(converted); + return converted; } -NAN_METHOD(Htons) { - Nan::HandleScope scope; +Napi::Value Htons(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); if (info.Length () < 1) { - Nan::ThrowError("One arguments is required"); - return; + Napi::Error::New(env, "One arguments is required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsUint32 ()) { - Nan::ThrowTypeError("Number must be a 16 unsigned integer"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Number must be a 16 unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - unsigned int number = Nan::To(info[0]).ToLocalChecked()->Value(); + unsigned int number = info[0].As(); if (number > 65535) { - Nan::ThrowRangeError("Number cannot be larger than 65535"); - return; + Napi::RangeError::New(env, "Number cannot be larger than 65535").ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local converted = Nan::New(htons (number)); + Napi::Number converted = Napi::Number::New(env, htons (number)); - info.GetReturnValue().Set(converted); + return converted; } -NAN_METHOD(Ntohl) { - Nan::HandleScope scope; +Napi::Value Ntohl(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); if (info.Length () < 1) { - Nan::ThrowError("One arguments is required"); - return; + Napi::Error::New(env, "One arguments is required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsUint32 ()) { - Nan::ThrowTypeError("Number must be a 32 unsigned integer"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Number must be a 32 unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - unsigned int number = Nan::To(info[0]).ToLocalChecked()->Value(); - Local converted = Nan::New((unsigned int) ntohl (number)); + unsigned int number = info[0].As(); + Napi::Number converted = Napi::Number::New(env, (unsigned int) ntohl (number)); - info.GetReturnValue().Set(converted); + return converted; } -NAN_METHOD(Ntohs) { - Nan::HandleScope scope; +Napi::Value Ntohs(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); if (info.Length () < 1) { - Nan::ThrowError("One arguments is required"); - return; + Napi::Error::New(env, "One arguments is required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsUint32 ()) { - Nan::ThrowTypeError("Number must be a 16 unsigned integer"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Number must be a 16 unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - unsigned int number = Nan::To(info[0]).ToLocalChecked()->Value(); + unsigned int number = info[0].As(); if (number > 65535) { - Nan::ThrowRangeError("Number cannot be larger than 65535"); - return; + Napi::RangeError::New(env, "Number cannot be larger than 65535").ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local converted = Nan::New(htons (number)); + Napi::Number converted = Napi::Number::New(env, ntohs (number)); - info.GetReturnValue().Set(converted); + return converted; } -void ExportConstants (Local target) { - Local socket_level = Nan::New(); - Local socket_option = Nan::New(); +void ExportConstants (Napi::Env env, Napi::Object target) { + Napi::Object socket_level = Napi::Object::New(env); + Napi::Object socket_option = Napi::Object::New(env); - Nan::Set(target, Nan::New("SocketLevel").ToLocalChecked(), socket_level); - Nan::Set(target, Nan::New("SocketOption").ToLocalChecked(), socket_option); + (target).Set(Napi::String::New(env, "SocketLevel"), socket_level); + (target).Set(Napi::String::New(env, "SocketOption"), socket_option); - Nan::Set(socket_level, Nan::New("SOL_SOCKET").ToLocalChecked(), Nan::New(SOL_SOCKET)); - Nan::Set(socket_level, Nan::New("IPPROTO_IP").ToLocalChecked(), Nan::New(IPPROTO_IP + 0)); - Nan::Set(socket_level, Nan::New("IPPROTO_IPV6").ToLocalChecked(), Nan::New(IPPROTO_IPV6 + 0)); + (socket_level).Set(Napi::String::New(env, "SOL_SOCKET"), Napi::Number::New(env, SOL_SOCKET)); + (socket_level).Set(Napi::String::New(env, "IPPROTO_IP"), Napi::Number::New(env, IPPROTO_IP + 0)); + (socket_level).Set(Napi::String::New(env, "IPPROTO_IPV6"), Napi::Number::New(env, IPPROTO_IPV6 + 0)); - Nan::Set(socket_option, Nan::New("SO_BROADCAST").ToLocalChecked(), Nan::New(SO_BROADCAST)); - Nan::Set(socket_option, Nan::New("SO_RCVBUF").ToLocalChecked(), Nan::New(SO_RCVBUF)); - Nan::Set(socket_option, Nan::New("SO_RCVTIMEO").ToLocalChecked(), Nan::New(SO_RCVTIMEO)); - Nan::Set(socket_option, Nan::New("SO_SNDBUF").ToLocalChecked(), Nan::New(SO_SNDBUF)); - Nan::Set(socket_option, Nan::New("SO_SNDTIMEO").ToLocalChecked(), Nan::New(SO_SNDTIMEO)); + (socket_option).Set(Napi::String::New(env, "SO_BROADCAST"), Napi::Number::New(env, SO_BROADCAST)); + (socket_option).Set(Napi::String::New(env, "SO_RCVBUF"), Napi::Number::New(env, SO_RCVBUF)); + (socket_option).Set(Napi::String::New(env, "SO_RCVTIMEO"), Napi::Number::New(env, SO_RCVTIMEO)); + (socket_option).Set(Napi::String::New(env, "SO_SNDBUF"), Napi::Number::New(env, SO_SNDBUF)); + (socket_option).Set(Napi::String::New(env, "SO_SNDTIMEO"), Napi::Number::New(env, SO_SNDTIMEO)); #ifdef __linux__ - Nan::Set(socket_option, Nan::New("SO_BINDTODEVICE").ToLocalChecked(), Nan::New(SO_BINDTODEVICE)); + (socket_option).Set(Napi::String::New(env, "SO_BINDTODEVICE"), Napi::Number::New(env, SO_BINDTODEVICE)); #endif - Nan::Set(socket_option, Nan::New("IP_HDRINCL").ToLocalChecked(), Nan::New(IP_HDRINCL)); - Nan::Set(socket_option, Nan::New("IP_OPTIONS").ToLocalChecked(), Nan::New(IP_OPTIONS)); - Nan::Set(socket_option, Nan::New("IP_TOS").ToLocalChecked(), Nan::New(IP_TOS)); - Nan::Set(socket_option, Nan::New("IP_TTL").ToLocalChecked(), Nan::New(IP_TTL)); + (socket_option).Set(Napi::String::New(env, "IP_HDRINCL"), Napi::Number::New(env, IP_HDRINCL)); + (socket_option).Set(Napi::String::New(env, "IP_OPTIONS"), Napi::Number::New(env, IP_OPTIONS)); + (socket_option).Set(Napi::String::New(env, "IP_TOS"), Napi::Number::New(env, IP_TOS)); + (socket_option).Set(Napi::String::New(env, "IP_TTL"), Napi::Number::New(env, IP_TTL)); #ifdef _WIN32 - Nan::Set(socket_option, Nan::New("IPV6_HDRINCL").ToLocalChecked(), Nan::New(IPV6_HDRINCL)); + (socket_option).Set(Napi::String::New(env, "IPV6_HDRINCL"), Napi::Number::New(env, IPV6_HDRINCL)); #endif - Nan::Set(socket_option, Nan::New("IPV6_TTL").ToLocalChecked(), Nan::New(IPV6_UNICAST_HOPS)); - Nan::Set(socket_option, Nan::New("IPV6_UNICAST_HOPS").ToLocalChecked(), Nan::New(IPV6_UNICAST_HOPS)); - Nan::Set(socket_option, Nan::New("IPV6_V6ONLY").ToLocalChecked(), Nan::New(IPV6_V6ONLY)); + (socket_option).Set(Napi::String::New(env, "IPV6_TTL"), Napi::Number::New(env, IPV6_UNICAST_HOPS)); + (socket_option).Set(Napi::String::New(env, "IPV6_UNICAST_HOPS"), Napi::Number::New(env, IPV6_UNICAST_HOPS)); + (socket_option).Set(Napi::String::New(env, "IPV6_V6ONLY"), Napi::Number::New(env, IPV6_V6ONLY)); } -void ExportFunctions (Local target) { - Nan::Set(target, Nan::New("createChecksum").ToLocalChecked(), Nan::GetFunction(Nan::New(CreateChecksum)).ToLocalChecked()); +void ExportFunctions (Napi::Env env, Napi::Object target) { + (target).Set(Napi::String::New(env, "createChecksum"), Napi::Function::New(env, CreateChecksum)); - Nan::Set(target, Nan::New("htonl").ToLocalChecked(), Nan::GetFunction(Nan::New(Htonl)).ToLocalChecked()); - Nan::Set(target, Nan::New("htons").ToLocalChecked(), Nan::GetFunction(Nan::New(Htons)).ToLocalChecked()); - Nan::Set(target, Nan::New("ntohl").ToLocalChecked(), Nan::GetFunction(Nan::New(Ntohl)).ToLocalChecked()); - Nan::Set(target, Nan::New("ntohs").ToLocalChecked(), Nan::GetFunction(Nan::New(Ntohs)).ToLocalChecked()); -} - -void SocketWrap::Init (Local exports) { - Nan::HandleScope scope; - - Local tpl = Nan::New(SocketWrap::New); - tpl->SetClassName(Nan::New("SocketWrap").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "close", Close); - Nan::SetPrototypeMethod(tpl, "getOption", GetOption); - Nan::SetPrototypeMethod(tpl, "pause", Pause); - Nan::SetPrototypeMethod(tpl, "recv", Recv); - Nan::SetPrototypeMethod(tpl, "send", Send); - Nan::SetPrototypeMethod(tpl, "setOption", SetOption); - - SocketWrap_constructor.Reset(tpl); - Nan::Set(exports, Nan::New("SocketWrap").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked()); + (target).Set(Napi::String::New(env, "htonl"), Napi::Function::New(env, Htonl)); + (target).Set(Napi::String::New(env, "htons"), Napi::Function::New(env, Htons)); + (target).Set(Napi::String::New(env, "ntohl"), Napi::Function::New(env, Ntohl)); + (target).Set(Napi::String::New(env, "ntohs"), Napi::Function::New(env, Ntohs)); } -SocketWrap::SocketWrap () { - deconstructing_ = false; +void SocketWrap::Init (Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + + Napi::Function tpl = DefineClass(env, "SocketWrap", { + InstanceMethod<&SocketWrap::Close>("close"), + InstanceMethod<&SocketWrap::GetOption>("getOption"), + InstanceMethod<&SocketWrap::Pause>("pause"), + InstanceMethod<&SocketWrap::Recv>("recv"), + InstanceMethod<&SocketWrap::Send>("send"), + InstanceMethod<&SocketWrap::SetOption>("setOption") + }); + SocketWrap_constructor = Napi::Persistent(tpl); + SocketWrap_constructor.SuppressDestruct(); + + (exports).Set(Napi::String::New(env, "SocketWrap"), tpl); } SocketWrap::~SocketWrap () { @@ -275,21 +294,21 @@ SocketWrap::~SocketWrap () { this->CloseSocket (); } -NAN_METHOD(SocketWrap::Close) { - Nan::HandleScope scope; +Napi::Value SocketWrap::Close(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = SocketWrap::Unwrap (info.This ()); + SocketWrap* socket = this; socket->CloseSocket (); - Local args[1]; - args[0] = Nan::New("close").ToLocalChecked(); + Napi::Value args[1]; + args[0] = Napi::String::New(env, "close"); - Nan::Call(Nan::New("emit").ToLocalChecked(), info.This(), 1, args); + Napi::Value(info.This().As()["emit"]).As().Call(info.This(), std::initializer_list{ args[0] }); - info.GetReturnValue().Set(info.This()); + return info.This(); } - void SocketWrap::CloseSocket (void) { if (this->poll_initialised_) { uv_close ((uv_handle_t *) this->poll_watcher_, OnClose); @@ -346,66 +365,78 @@ int SocketWrap::CreateSocket (void) { return 0; } -NAN_METHOD(SocketWrap::GetOption) { - Nan::HandleScope scope; +Napi::Value SocketWrap::GetOption(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = SocketWrap::Unwrap (info.This ()); + SocketWrap* socket = this; if (info.Length () < 3) { - Nan::ThrowError("Three arguments are required"); - return; + Napi::Error::New(env, "Three arguments are required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsNumber ()) { - Nan::ThrowTypeError("Level argument must be a number"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Level argument must be a number").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[1]->IsNumber ()) { - Nan::ThrowTypeError("Option argument must be a number"); - return; + if (! info[1].IsNumber ()) { + Napi::TypeError::New(env, "Option argument must be a number").ThrowAsJavaScriptException(); + + return env.Undefined(); } - int level = Nan::To(info[0]).ToLocalChecked()->Value(); - int option = Nan::To(info[1]).ToLocalChecked()->Value(); + int level = info[0].As(); + int option = info[1].As(); SOCKET_OPT_TYPE val = NULL; unsigned int ival = 0; SOCKET_LEN_TYPE len; - if (! node::Buffer::HasInstance (info[2])) { - Nan::ThrowTypeError("Value argument must be a node Buffer object if length is provided"); - return; + if (! info[2].IsBuffer()) { + Napi::TypeError::New(env, "Value argument must be a node Buffer object if length is provided").ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local buffer = Nan::To(info[2]).ToLocalChecked(); - val = node::Buffer::Data (buffer); + Napi::Buffer buffer = info[2].As >(); + val = buffer.Data(); - if (! info[3]->IsInt32 ()) { - Nan::ThrowTypeError("Length argument must be an unsigned integer"); - return; + if (! info[3].IsNumber ()) { + Napi::TypeError::New(env, "Length argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - len = (SOCKET_LEN_TYPE) node::Buffer::Length (buffer); + len = (SOCKET_LEN_TYPE) buffer.Length(); int rc = getsockopt (socket->poll_fd_, level, option, (val ? val : (SOCKET_OPT_TYPE) &ival), &len); if (rc == SOCKET_ERROR) { - Nan::ThrowError(raw_strerror (SOCKET_ERRNO)); - return; + Napi::Error::New(env, raw_strerror (SOCKET_ERRNO)).ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local got = Nan::New(len); + Napi::Number got = Napi::Number::New(env, len); - info.GetReturnValue().Set(got); + return got; +} + +Napi::Value SocketWrap::handle() { + return Value(); } void SocketWrap::HandleIOEvent (int status, int revents) { - Nan::HandleScope scope; + Napi::Env env = Env(); + Napi::HandleScope scope(env); if (status) { - Local args[2]; - args[0] = Nan::New("error").ToLocalChecked(); + Napi::Value args[2]; + args[0] = Napi::String::New(env, "error"); /** ** The uv_last_error() function doesn't seem to be available in recent @@ -415,44 +446,49 @@ void SocketWrap::HandleIOEvent (int status, int revents) { **/ char status_str[32]; sprintf(status_str, "%d", status); - args[1] = Nan::Error(status_str); + Napi::Error error = Napi::Error::New(env, status_str); + args[1] = error.Value(); - Nan::Call(Nan::New("emit").ToLocalChecked(), handle(), 1, args); + Napi::Value(handle().As()["emit"]).As().Call(handle(), std::initializer_list{ args[0] }); } else { - Local args[1]; + Napi::Value args[1]; if (revents & UV_READABLE) - args[0] = Nan::New("recvReady").ToLocalChecked(); + args[0] = Napi::String::New(env, "recvReady"); else - args[0] = Nan::New("sendReady").ToLocalChecked(); + args[0] = Napi::String::New(env, "sendReady"); - Nan::Call(Nan::New("emit").ToLocalChecked(), handle(), 1, args); + Napi::Value(handle().As()["emit"]).As().Call(handle(), std::initializer_list{ args[0] }); } } -NAN_METHOD(SocketWrap::New) { - Nan::HandleScope scope; +SocketWrap::SocketWrap(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info), deconstructing_(false) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = new SocketWrap (); + SocketWrap* socket = this; int rc, family = AF_INET; if (info.Length () < 1) { - Nan::ThrowError("One argument is required"); + Napi::Error::New(env, "One argument is required").ThrowAsJavaScriptException(); + return; } - if (! info[0]->IsUint32 ()) { - Nan::ThrowTypeError("Protocol argument must be an unsigned integer"); + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Protocol argument must be an unsigned integer").ThrowAsJavaScriptException(); + return; } else { - socket->protocol_ = Nan::To(info[0]).ToLocalChecked()->Value(); + socket->protocol_ = info[0].As(); } if (info.Length () > 1) { - if (! info[1]->IsUint32 ()) { - Nan::ThrowTypeError("Address family argument must be an unsigned integer"); + if (! info[1].IsNumber ()) { + Napi::TypeError::New(env, "Address family argument must be an unsigned integer").ThrowAsJavaScriptException(); + return; } else { - if (Nan::To(info[1]).ToLocalChecked()->Value() == 2) + if (uint32_t(info[1].As()) == 2) family = AF_INET6; } } @@ -465,40 +501,41 @@ NAN_METHOD(SocketWrap::New) { rc = socket->CreateSocket (); if (rc != 0) { - Nan::ThrowError(raw_strerror (rc)); + Napi::Error::New(env, raw_strerror (rc)).ThrowAsJavaScriptException(); + return; } - - socket->Wrap (info.This ()); - - info.GetReturnValue().Set(info.This()); } void SocketWrap::OnClose (uv_handle_t *handle) { delete handle; } -NAN_METHOD(SocketWrap::Pause) { - Nan::HandleScope scope; +Napi::Value SocketWrap::Pause(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = SocketWrap::Unwrap (info.This ()); + SocketWrap* socket = this; if (info.Length () < 2) { - Nan::ThrowError("Two arguments are required"); - return; + Napi::Error::New(env, "Two arguments are required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsBoolean ()) { - Nan::ThrowTypeError("Recv argument must be a boolean"); - return; + if (! info[0].IsBoolean ()) { + Napi::TypeError::New(env, "Recv argument must be a boolean").ThrowAsJavaScriptException(); + + return env.Undefined(); } - bool pause_recv = Nan::To(info[0]).ToLocalChecked()->Value(); + bool pause_recv = info[0].As(); - if (! info[1]->IsBoolean ()) { - Nan::ThrowTypeError("Send argument must be a boolean"); - return; + if (! info[1].IsBoolean ()) { + Napi::TypeError::New(env, "Send argument must be a boolean").ThrowAsJavaScriptException(); + + return env.Undefined(); } - bool pause_send = Nan::To(info[1]).ToLocalChecked()->Value(); + bool pause_send = info[1].As(); int events = (pause_recv ? 0 : UV_READABLE) | (pause_send ? 0 : UV_WRITABLE); @@ -509,14 +546,15 @@ NAN_METHOD(SocketWrap::Pause) { uv_poll_start (socket->poll_watcher_, events, IoEvent); } - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(SocketWrap::Recv) { - Nan::HandleScope scope; +Napi::Value SocketWrap::Recv(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = SocketWrap::Unwrap (info.This ()); - Local buffer; + SocketWrap* socket = this; + Napi::Buffer buffer; sockaddr_in sin_address; sockaddr_in6 sin6_address; char addr[50]; @@ -529,46 +567,51 @@ NAN_METHOD(SocketWrap::Recv) { socklen_t sin_length = socket->family_ == AF_INET6 ? sizeof (sin6_address) : sizeof (sin_address); -#endif +#endif if (info.Length () < 2) { - Nan::ThrowError("Five arguments are required"); - return; + Napi::Error::New(env, "Five arguments are required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! node::Buffer::HasInstance (info[0])) { - Nan::ThrowTypeError("Buffer argument must be a node Buffer object"); - return; + if (! info[0].IsBuffer()) { + Napi::TypeError::New(env, "Buffer argument must be a node Buffer object").ThrowAsJavaScriptException(); + + return env.Undefined(); } else { - buffer = Nan::To(info[0]).ToLocalChecked(); + buffer = info[0].As >(); } - if (! info[1]->IsFunction ()) { - Nan::ThrowTypeError("Callback argument must be a function"); - return; + if (! info[1].IsFunction ()) { + Napi::TypeError::New(env, "Callback argument must be a function").ThrowAsJavaScriptException(); + + return env.Undefined(); } rc = socket->CreateSocket (); if (rc != 0) { - Nan::ThrowError(raw_strerror (errno)); - return; + Napi::Error::New(env, raw_strerror (errno)).ThrowAsJavaScriptException(); + + return env.Undefined(); } if (socket->family_ == AF_INET6) { memset (&sin6_address, 0, sizeof (sin6_address)); - rc = recvfrom (socket->poll_fd_, node::Buffer::Data (buffer), - (int) node::Buffer::Length (buffer), 0, (sockaddr *) &sin6_address, + rc = recvfrom (socket->poll_fd_, buffer.Data(), + (int) buffer.Length(), 0, (sockaddr *) &sin6_address, &sin_length); } else { memset (&sin_address, 0, sizeof (sin_address)); - rc = recvfrom (socket->poll_fd_, node::Buffer::Data (buffer), - (int) node::Buffer::Length (buffer), 0, (sockaddr *) &sin_address, + rc = recvfrom (socket->poll_fd_, buffer.Data(), + (int) buffer.Length(), 0, (sockaddr *) &sin_address, &sin_length); } if (rc == SOCKET_ERROR) { - Nan::ThrowError(raw_strerror (SOCKET_ERRNO)); - return; + Napi::Error::New(env, raw_strerror (SOCKET_ERRNO)).ThrowAsJavaScriptException(); + + return env.Undefined(); } if (socket->family_ == AF_INET6) @@ -576,74 +619,82 @@ NAN_METHOD(SocketWrap::Recv) { else uv_ip4_name (&sin_address, addr, 50); - Local cb = Local::Cast (info[1]); + Napi::Function cb = info[1].As(); const unsigned argc = 3; - Local argv[argc]; + Napi::Value argv[argc]; argv[0] = info[0]; - argv[1] = Nan::New(rc); - argv[2] = Nan::New(addr).ToLocalChecked(); - Nan::Call(Nan::Callback(cb), argc, argv); + argv[1] = Napi::Number::New(env, rc); + argv[2] = Napi::String::New(env, addr); + cb.Call(std::initializer_list{ argv[0], argv[1], argv[2] }); - info.GetReturnValue().Set(info.This()); + return info.This(); } -NAN_METHOD(SocketWrap::Send) { - Nan::HandleScope scope; +Napi::Value SocketWrap::Send(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = SocketWrap::Unwrap (info.This ()); - Local buffer; + SocketWrap* socket = this; + Napi::Buffer buffer; uint32_t offset; uint32_t length; int rc; char *data; if (info.Length () < 5) { - Nan::ThrowError("Five arguments are required"); - return; + Napi::Error::New(env, "Five arguments are required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! node::Buffer::HasInstance (info[0])) { - Nan::ThrowTypeError("Buffer argument must be a node Buffer object"); - return; + if (! info[0].IsBuffer()) { + Napi::TypeError::New(env, "Buffer argument must be a node Buffer object").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[1]->IsUint32 ()) { - Nan::ThrowTypeError("Offset argument must be an unsigned integer"); - return; + if (! info[1].IsNumber ()) { + Napi::TypeError::New(env, "Offset argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[2]->IsUint32 ()) { - Nan::ThrowTypeError("Length argument must be an unsigned integer"); - return; + if (! info[2].IsNumber ()) { + Napi::TypeError::New(env, "Length argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[3]->IsString ()) { - Nan::ThrowTypeError("Address argument must be a string"); - return; + if (! info[3].IsString ()) { + Napi::TypeError::New(env, "Address argument must be a string").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[4]->IsFunction ()) { - Nan::ThrowTypeError("Callback argument must be a function"); - return; + if (! info[4].IsFunction ()) { + Napi::TypeError::New(env, "Callback argument must be a function").ThrowAsJavaScriptException(); + + return env.Undefined(); } rc = socket->CreateSocket (); if (rc != 0) { - Nan::ThrowError(raw_strerror (errno)); - return; + Napi::Error::New(env, raw_strerror (errno)).ThrowAsJavaScriptException(); + + return env.Undefined(); } - buffer = Nan::To(info[0]).ToLocalChecked(); - offset = Nan::To(info[1]).ToLocalChecked()->Value(); - length = Nan::To(info[2]).ToLocalChecked()->Value(); + buffer = info[0].As >(); + offset = info[1].As(); + length = info[2].As(); - data = node::Buffer::Data (buffer) + offset; + data = buffer.Data() + offset; if (socket->family_ == AF_INET6) { #if UV_VERSION_MAJOR > 0 struct sockaddr_in6 addr; - uv_ip6_addr(*Nan::Utf8String(info[3]), 0, &addr); + uv_ip6_addr(info[3].As().Utf8Value().c_str(), 0, &addr); #else String::Utf8String address (args[3]); struct sockaddr_in6 addr = uv_ip6_addr (*address, 0); @@ -654,7 +705,7 @@ NAN_METHOD(SocketWrap::Send) { } else { #if UV_VERSION_MAJOR > 0 struct sockaddr_in addr; - uv_ip4_addr(*Nan::Utf8String(info[3]), 0, &addr); + uv_ip4_addr(info[3].As().Utf8Value().c_str(), 0, &addr); #else String::Utf8String address (info[3]); struct sockaddr_in addr = uv_ip4_addr (*address, 0); @@ -665,72 +716,81 @@ NAN_METHOD(SocketWrap::Send) { } if (rc == SOCKET_ERROR) { - Nan::ThrowError(raw_strerror (SOCKET_ERRNO)); - return; + Napi::Error::New(env, raw_strerror (SOCKET_ERRNO)).ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local cb = Local::Cast (info[4]); + Napi::Function cb = info[4].As(); const unsigned argc = 1; - Local argv[argc]; - argv[0] = Nan::New(rc); - Nan::Call(Nan::Callback(cb), argc, argv); + Napi::Value argv[argc]; + argv[0] = Napi::Number::New(env, rc); - info.GetReturnValue().Set(info.This()); + cb.Call(std::initializer_list{ argv[0] }); + return info.This(); } -NAN_METHOD(SocketWrap::SetOption) { - Nan::HandleScope scope; +Napi::Value SocketWrap::SetOption(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); - SocketWrap* socket = SocketWrap::Unwrap (info.This ()); + SocketWrap* socket = this; if (info.Length () < 3) { - Nan::ThrowError("Three or four arguments are required"); - return; + Napi::Error::New(env, "Three or four arguments are required").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[0]->IsNumber ()) { - Nan::ThrowTypeError("Level argument must be a number"); - return; + if (! info[0].IsNumber ()) { + Napi::TypeError::New(env, "Level argument must be a number").ThrowAsJavaScriptException(); + + return env.Undefined(); } - if (! info[1]->IsNumber ()) { - Nan::ThrowTypeError("Option argument must be a number"); - return; + if (! info[1].IsNumber ()) { + Napi::TypeError::New(env, "Option argument must be a number").ThrowAsJavaScriptException(); + + return env.Undefined(); } - int level = Nan::To(info[0]).ToLocalChecked()->Value(); - int option = Nan::To(info[1]).ToLocalChecked()->Value(); + int level = info[0].As(); + int option = info[1].As(); SOCKET_OPT_TYPE val = NULL; unsigned int ival = 0; SOCKET_LEN_TYPE len; if (info.Length () > 3) { - if (! node::Buffer::HasInstance (info[2])) { - Nan::ThrowTypeError("Value argument must be a node Buffer object if length is provided"); - return; + if (! info[2].IsBuffer()) { + Napi::TypeError::New(env, "Value argument must be a node Buffer object if length is provided").ThrowAsJavaScriptException(); + + return env.Undefined(); } - Local buffer = Nan::To(info[2]).ToLocalChecked(); - val = node::Buffer::Data (buffer); + Napi::Buffer buffer = info[2].As >(); + val = buffer.Data(); - if (! info[3]->IsInt32 ()) { - Nan::ThrowTypeError("Length argument must be an unsigned integer"); - return; + if (! info[3].IsNumber ()) { + Napi::TypeError::New(env, "Length argument must be an unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - len = Nan::To(info[3]).ToLocalChecked()->Value(); + len = info[3].As(); - if (len > node::Buffer::Length (buffer)) { - Nan::ThrowTypeError("Length argument is larger than buffer length"); - return; + if (len > buffer.Length()) { + Napi::TypeError::New(env, "Length argument is larger than buffer length").ThrowAsJavaScriptException(); + + return env.Undefined(); } } else { - if (! info[2]->IsUint32 ()) { - Nan::ThrowTypeError("Value argument must be a unsigned integer"); - return; + if (! info[2].IsNumber ()) { + Napi::TypeError::New(env, "Value argument must be a unsigned integer").ThrowAsJavaScriptException(); + + return env.Undefined(); } - ival = Nan::To(info[2]).ToLocalChecked()->Value(); + ival = info[2].As(); len = 4; } @@ -738,11 +798,12 @@ NAN_METHOD(SocketWrap::SetOption) { (val ? val : (SOCKET_OPT_TYPE) &ival), len); if (rc == SOCKET_ERROR) { - Nan::ThrowError(raw_strerror(SOCKET_ERRNO)); - return; + Napi::Error::New(env, raw_strerror(SOCKET_ERRNO)).ThrowAsJavaScriptException(); + + return env.Undefined(); } - info.GetReturnValue().Set(info.This()); + return info.This(); } static void IoEvent (uv_poll_t* watcher, int status, int revents) { diff --git a/src/raw.h b/src/raw.h index ff1928a..3de5c6b 100644 --- a/src/raw.h +++ b/src/raw.h @@ -18,9 +18,11 @@ #include -#include +#include +#include #include -#include +#include +#include #ifdef _WIN32 #include @@ -45,45 +47,46 @@ #define SOCKET_LEN_TYPE socklen_t #endif -using namespace v8; +using namespace Napi; namespace raw { -NAN_METHOD(CreateChecksum); +Napi::Value CreateChecksum(const Napi::CallbackInfo& info); -void ExportConstants (Local target); -void ExportFunctions (Local target); +void ExportConstants (Napi::Env env, Napi::Object target); +void ExportFunctions (Napi::Env env, Napi::Object target); -NAN_METHOD(Htonl); -NAN_METHOD(Htons); -NAN_METHOD(Ntohl); -NAN_METHOD(Ntohs); +Napi::Value Htonl(const Napi::CallbackInfo& info); +Napi::Value Htons(const Napi::CallbackInfo& info); +Napi::Value Ntohl(const Napi::CallbackInfo& info); +Napi::Value Ntohs(const Napi::CallbackInfo& info); -class SocketWrap : public Nan::ObjectWrap { +class SocketWrap : public Napi::ObjectWrap { public: + SocketWrap(const Napi::CallbackInfo& info); + virtual ~SocketWrap (); + void HandleIOEvent (int status, int revents); - static void Init (Local exports); + static void Init (Napi::Env env, Napi::Object exports); -private: - SocketWrap (); - ~SocketWrap (); - static NAN_METHOD(Close); +private: + Napi::Value Close(const Napi::CallbackInfo& info); void CloseSocket (void); int CreateSocket (void); - static NAN_METHOD(GetOption); - - static NAN_METHOD(New); + Napi::Value GetOption(const Napi::CallbackInfo& info); static void OnClose (uv_handle_t *handle); - static NAN_METHOD(Pause); - static NAN_METHOD(Recv); - static NAN_METHOD(Send); - static NAN_METHOD(SetOption); + Napi::Value Pause(const Napi::CallbackInfo& info); + Napi::Value Recv(const Napi::CallbackInfo& info); + Napi::Value Send(const Napi::CallbackInfo& info); + Napi::Value SetOption(const Napi::CallbackInfo& info); + + Napi::Value handle(); bool no_ip_header_;