diff options
-rw-r--r-- | lib/internal/worker.js | 3 | ||||
-rw-r--r-- | node.gyp | 1 | ||||
-rw-r--r-- | src/async_wrap.cc | 25 | ||||
-rw-r--r-- | src/async_wrap.h | 10 | ||||
-rw-r--r-- | src/cares_wrap.cc | 8 | ||||
-rw-r--r-- | src/env.h | 5 | ||||
-rw-r--r-- | src/fs_event_wrap.cc | 2 | ||||
-rw-r--r-- | src/handle_wrap.cc | 20 | ||||
-rw-r--r-- | src/handle_wrap.h | 4 | ||||
-rw-r--r-- | src/inspector_js_api.cc | 2 | ||||
-rw-r--r-- | src/js_stream.cc | 3 | ||||
-rw-r--r-- | src/node_file.cc | 10 | ||||
-rw-r--r-- | src/node_http2.cc | 8 | ||||
-rw-r--r-- | src/node_http_parser.cc | 2 | ||||
-rw-r--r-- | src/node_messaging.cc | 4 | ||||
-rw-r--r-- | src/node_stat_watcher.cc | 4 | ||||
-rw-r--r-- | src/node_worker.cc | 2 | ||||
-rw-r--r-- | src/node_wrap.h | 72 | ||||
-rw-r--r-- | src/node_zlib.cc | 2 | ||||
-rw-r--r-- | src/pipe_wrap.cc | 7 | ||||
-rw-r--r-- | src/process_wrap.cc | 33 | ||||
-rw-r--r-- | src/signal_wrap.cc | 4 | ||||
-rw-r--r-- | src/stream_pipe.cc | 2 | ||||
-rw-r--r-- | src/stream_wrap.cc | 70 | ||||
-rw-r--r-- | src/stream_wrap.h | 6 | ||||
-rw-r--r-- | src/tcp_wrap.cc | 6 | ||||
-rw-r--r-- | src/tls_wrap.cc | 2 | ||||
-rw-r--r-- | src/tty_wrap.cc | 6 | ||||
-rw-r--r-- | src/udp_wrap.cc | 5 | ||||
-rw-r--r-- | test/parallel/test-accessor-properties.js | 10 |
30 files changed, 140 insertions, 198 deletions
diff --git a/lib/internal/worker.js b/lib/internal/worker.js index ceec8469b1..2cffb77e52 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -73,7 +73,8 @@ Object.setPrototypeOf(MessagePort.prototype, EventEmitter.prototype); delete MessagePort.prototype.stop; delete MessagePort.prototype.drain; delete MessagePort.prototype.hasRef; -delete MessagePort.prototype.getAsyncId; +MessagePort.prototype.ref = MessagePortPrototype.ref; +MessagePort.prototype.unref = MessagePortPrototype.unref; // A communication channel consisting of a handle (that wraps around an // uv_async_t) which can receive information from other threads and emits @@ -422,7 +422,6 @@ 'src/node_root_certs.h', 'src/node_version.h', 'src/node_watchdog.h', - 'src/node_wrap.h', 'src/node_revert.h', 'src/node_i18n.h', 'src/node_worker.h', diff --git a/src/async_wrap.cc b/src/async_wrap.cc index b04ab68087..eb67433c39 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -64,7 +64,7 @@ struct AsyncWrapObject : public AsyncWrap { static inline void New(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); CHECK(args.IsConstructCall()); - CHECK(env->async_wrap_constructor_template()->HasInstance(args.This())); + CHECK(env->async_wrap_object_ctor_template()->HasInstance(args.This())); CHECK(args[0]->IsUint32()); auto type = static_cast<ProviderType>(args[0].As<Uint32>()->Value()); new AsyncWrapObject(env, args.This(), type); @@ -424,12 +424,16 @@ void AsyncWrap::QueueDestroyAsyncId(const FunctionCallbackInfo<Value>& args) { args[0].As<Number>()->Value()); } -void AsyncWrap::AddWrapMethods(Environment* env, - Local<FunctionTemplate> constructor, - int flag) { - env->SetProtoMethod(constructor, "getAsyncId", AsyncWrap::GetAsyncId); - if (flag & kFlagHasReset) - env->SetProtoMethod(constructor, "asyncReset", AsyncWrap::AsyncReset); +Local<FunctionTemplate> AsyncWrap::GetConstructorTemplate(Environment* env) { + Local<FunctionTemplate> tmpl = env->async_wrap_ctor_template(); + if (tmpl.IsEmpty()) { + tmpl = env->NewFunctionTemplate(nullptr); + tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "AsyncWrap")); + env->SetProtoMethod(tmpl, "getAsyncId", AsyncWrap::GetAsyncId); + env->SetProtoMethod(tmpl, "asyncReset", AsyncWrap::AsyncReset); + env->set_async_wrap_ctor_template(tmpl); + } + return tmpl; } void AsyncWrap::Initialize(Local<Object> target, @@ -525,17 +529,20 @@ void AsyncWrap::Initialize(Local<Object> target, env->set_async_hooks_promise_resolve_function(Local<Function>()); env->set_async_hooks_binding(target); + // TODO(addaleax): This block might better work as a + // AsyncWrapObject::Initialize() or AsyncWrapObject::GetConstructorTemplate() + // function. { auto class_name = FIXED_ONE_BYTE_STRING(env->isolate(), "AsyncWrap"); auto function_template = env->NewFunctionTemplate(AsyncWrapObject::New); function_template->SetClassName(class_name); - AsyncWrap::AddWrapMethods(env, function_template); + function_template->Inherit(AsyncWrap::GetConstructorTemplate(env)); auto instance_template = function_template->InstanceTemplate(); instance_template->SetInternalFieldCount(1); auto function = function_template->GetFunction(env->context()).ToLocalChecked(); target->Set(env->context(), class_name, function).FromJust(); - env->set_async_wrap_constructor_template(function_template); + env->set_async_wrap_object_ctor_template(function_template); } } diff --git a/src/async_wrap.h b/src/async_wrap.h index 50864837d6..360380afc3 100644 --- a/src/async_wrap.h +++ b/src/async_wrap.h @@ -104,11 +104,6 @@ class AsyncWrap : public BaseObject { PROVIDERS_LENGTH, }; - enum Flags { - kFlagNone = 0x0, - kFlagHasReset = 0x1 - }; - AsyncWrap(Environment* env, v8::Local<v8::Object> object, ProviderType provider, @@ -116,9 +111,8 @@ class AsyncWrap : public BaseObject { virtual ~AsyncWrap(); - static void AddWrapMethods(Environment* env, - v8::Local<v8::FunctionTemplate> constructor, - int flags = kFlagNone); + static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( + Environment* env); static void Initialize(v8::Local<v8::Object> target, v8::Local<v8::Value> unused, diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index a967414aec..3187b7d476 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -2220,7 +2220,7 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> aiw = BaseObject::MakeLazilyInitializedJSTemplate(env); - AsyncWrap::AddWrapMethods(env, aiw); + aiw->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> addrInfoWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap"); aiw->SetClassName(addrInfoWrapString); @@ -2228,7 +2228,7 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> niw = BaseObject::MakeLazilyInitializedJSTemplate(env); - AsyncWrap::AddWrapMethods(env, niw); + niw->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> nameInfoWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"); niw->SetClassName(nameInfoWrapString); @@ -2236,7 +2236,7 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> qrw = BaseObject::MakeLazilyInitializedJSTemplate(env); - AsyncWrap::AddWrapMethods(env, qrw); + qrw->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> queryWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"); qrw->SetClassName(queryWrapString); @@ -2245,7 +2245,7 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> channel_wrap = env->NewFunctionTemplate(ChannelWrap::New); channel_wrap->InstanceTemplate()->SetInternalFieldCount(1); - AsyncWrap::AddWrapMethods(env, channel_wrap); + channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>); env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>); @@ -319,7 +319,8 @@ struct PackageConfig { V(async_hooks_destroy_function, v8::Function) \ V(async_hooks_init_function, v8::Function) \ V(async_hooks_promise_resolve_function, v8::Function) \ - V(async_wrap_constructor_template, v8::FunctionTemplate) \ + V(async_wrap_object_ctor_template, v8::FunctionTemplate) \ + V(async_wrap_ctor_template, v8::FunctionTemplate) \ V(buffer_prototype_object, v8::Object) \ V(context, v8::Context) \ V(domain_callback, v8::Function) \ @@ -329,6 +330,7 @@ struct PackageConfig { V(filehandlereadwrap_template, v8::ObjectTemplate) \ V(fsreqpromise_constructor_template, v8::ObjectTemplate) \ V(fs_use_promises_symbol, v8::Symbol) \ + V(handle_wrap_ctor_template, v8::FunctionTemplate) \ V(host_import_module_dynamically_callback, v8::Function) \ V(host_initialize_import_meta_object_callback, v8::Function) \ V(http2ping_constructor_template, v8::ObjectTemplate) \ @@ -336,6 +338,7 @@ struct PackageConfig { V(http2stream_constructor_template, v8::ObjectTemplate) \ V(immediate_callback_function, v8::Function) \ V(inspector_console_api_object, v8::Object) \ + V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate) \ V(message_port, v8::Object) \ V(message_port_constructor_template, v8::FunctionTemplate) \ V(pipe_constructor_template, v8::FunctionTemplate) \ diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index c51054819f..aaf03dcb2b 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -105,7 +105,7 @@ void FSEventWrap::Initialize(Local<Object> target, t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(fsevent_string); - AsyncWrap::AddWrapMethods(env, t); + t->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "start", Start); env->SetProtoMethod(t, "close", Close); diff --git a/src/handle_wrap.cc b/src/handle_wrap.cc index 9281300146..d4c5962c35 100644 --- a/src/handle_wrap.cc +++ b/src/handle_wrap.cc @@ -130,13 +130,19 @@ void HandleWrap::OnClose(uv_handle_t* handle) { } } - -void HandleWrap::AddWrapMethods(Environment* env, - Local<FunctionTemplate> t) { - env->SetProtoMethod(t, "close", HandleWrap::Close); - env->SetProtoMethodNoSideEffect(t, "hasRef", HandleWrap::HasRef); - env->SetProtoMethod(t, "ref", HandleWrap::Ref); - env->SetProtoMethod(t, "unref", HandleWrap::Unref); +Local<FunctionTemplate> HandleWrap::GetConstructorTemplate(Environment* env) { + Local<FunctionTemplate> tmpl = env->handle_wrap_ctor_template(); + if (tmpl.IsEmpty()) { + tmpl = env->NewFunctionTemplate(nullptr); + tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HandleWrap")); + tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env)); + env->SetProtoMethod(tmpl, "close", HandleWrap::Close); + env->SetProtoMethodNoSideEffect(tmpl, "hasRef", HandleWrap::HasRef); + env->SetProtoMethod(tmpl, "ref", HandleWrap::Ref); + env->SetProtoMethod(tmpl, "unref", HandleWrap::Unref); + env->set_handle_wrap_ctor_template(tmpl); + } + return tmpl; } diff --git a/src/handle_wrap.h b/src/handle_wrap.h index 443d28bf52..b2722511c3 100644 --- a/src/handle_wrap.h +++ b/src/handle_wrap.h @@ -73,8 +73,8 @@ class HandleWrap : public AsyncWrap { virtual void Close( v8::Local<v8::Value> close_callback = v8::Local<v8::Value>()); - static void AddWrapMethods(Environment* env, - v8::Local<v8::FunctionTemplate> constructor); + static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( + Environment* env); protected: HandleWrap(Environment* env, diff --git a/src/inspector_js_api.cc b/src/inspector_js_api.cc index 52184111f5..49e1dcc6e8 100644 --- a/src/inspector_js_api.cc +++ b/src/inspector_js_api.cc @@ -307,7 +307,7 @@ void Initialize(Local<Object> target, Local<Value> unused, env->NewFunctionTemplate(JSBindingsConnection::New); tmpl->InstanceTemplate()->SetInternalFieldCount(1); tmpl->SetClassName(conn_str); - AsyncWrap::AddWrapMethods(env, tmpl); + tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(tmpl, "dispatch", JSBindingsConnection::Dispatch); env->SetProtoMethod(tmpl, "disconnect", JSBindingsConnection::Disconnect); target diff --git a/src/js_stream.cc b/src/js_stream.cc index 9aca2f1d4b..99ea7d870b 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -202,8 +202,7 @@ void JSStream::Initialize(Local<Object> target, FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream"); t->SetClassName(jsStreamString); t->InstanceTemplate()->SetInternalFieldCount(1); - - AsyncWrap::AddWrapMethods(env, t); + t->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "finishWrite", Finish<WriteWrap>); env->SetProtoMethod(t, "finishShutdown", Finish<ShutdownWrap>); diff --git a/src/node_file.cc b/src/node_file.cc index 6a71ef1124..f4f5b263a6 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2250,7 +2250,7 @@ void Initialize(Local<Object> target, // Create FunctionTemplate for FSReqCallback Local<FunctionTemplate> fst = env->NewFunctionTemplate(NewFSReqCallback); fst->InstanceTemplate()->SetInternalFieldCount(1); - AsyncWrap::AddWrapMethods(env, fst); + fst->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> wrapString = FIXED_ONE_BYTE_STRING(isolate, "FSReqCallback"); fst->SetClassName(wrapString); @@ -2263,7 +2263,7 @@ void Initialize(Local<Object> target, // to do anything in the constructor, so we only store the instance template. Local<FunctionTemplate> fh_rw = FunctionTemplate::New(isolate); fh_rw->InstanceTemplate()->SetInternalFieldCount(1); - AsyncWrap::AddWrapMethods(env, fh_rw); + fh_rw->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> fhWrapString = FIXED_ONE_BYTE_STRING(isolate, "FileHandleReqWrap"); fh_rw->SetClassName(fhWrapString); @@ -2272,7 +2272,7 @@ void Initialize(Local<Object> target, // Create Function Template for FSReqPromise Local<FunctionTemplate> fpt = FunctionTemplate::New(isolate); - AsyncWrap::AddWrapMethods(env, fpt); + fpt->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> promiseString = FIXED_ONE_BYTE_STRING(isolate, "FSReqPromise"); fpt->SetClassName(promiseString); @@ -2282,7 +2282,7 @@ void Initialize(Local<Object> target, // Create FunctionTemplate for FileHandle Local<FunctionTemplate> fd = env->NewFunctionTemplate(FileHandle::New); - AsyncWrap::AddWrapMethods(env, fd); + fd->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(fd, "close", FileHandle::Close); env->SetProtoMethod(fd, "releaseFD", FileHandle::ReleaseFD); Local<ObjectTemplate> fdt = fd->InstanceTemplate(); @@ -2301,7 +2301,7 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> fdclose = FunctionTemplate::New(isolate); fdclose->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "FileHandleCloseReq")); - AsyncWrap::AddWrapMethods(env, fdclose); + fdclose->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<ObjectTemplate> fdcloset = fdclose->InstanceTemplate(); fdcloset->SetInternalFieldCount(1); env->set_fdclose_constructor_template(fdcloset); diff --git a/src/node_http2.cc b/src/node_http2.cc index 09662b08a4..b95a81e385 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -2960,14 +2960,14 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> ping = FunctionTemplate::New(env->isolate()); ping->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Ping")); - AsyncWrap::AddWrapMethods(env, ping); + ping->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<ObjectTemplate> pingt = ping->InstanceTemplate(); pingt->SetInternalFieldCount(1); env->set_http2ping_constructor_template(pingt); Local<FunctionTemplate> setting = FunctionTemplate::New(env->isolate()); setting->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Http2Setting")); - AsyncWrap::AddWrapMethods(env, setting); + setting->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<ObjectTemplate> settingt = setting->InstanceTemplate(); settingt->SetInternalFieldCount(1); env->set_http2settings_constructor_template(settingt); @@ -2984,7 +2984,7 @@ void Initialize(Local<Object> target, env->SetProtoMethod(stream, "respond", Http2Stream::Respond); env->SetProtoMethod(stream, "rstStream", Http2Stream::RstStream); env->SetProtoMethod(stream, "refreshState", Http2Stream::RefreshState); - AsyncWrap::AddWrapMethods(env, stream); + stream->Inherit(AsyncWrap::GetConstructorTemplate(env)); StreamBase::AddMethods<Http2Stream>(env, stream); Local<ObjectTemplate> streamt = stream->InstanceTemplate(); streamt->SetInternalFieldCount(1); @@ -2997,7 +2997,7 @@ void Initialize(Local<Object> target, env->NewFunctionTemplate(Http2Session::New); session->SetClassName(http2SessionClassName); session->InstanceTemplate()->SetInternalFieldCount(1); - AsyncWrap::AddWrapMethods(env, session); + session->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(session, "origin", Http2Session::Origin); env->SetProtoMethod(session, "altsvc", Http2Session::AltSvc); env->SetProtoMethod(session, "ping", Http2Session::Ping); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 3236dd4f9f..dcaf3d211a 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -763,7 +763,7 @@ void Initialize(Local<Object> target, #undef V target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "methods"), methods); - AsyncWrap::AddWrapMethods(env, t); + t->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "close", Parser::Close); env->SetProtoMethod(t, "free", Parser::Free); env->SetProtoMethod(t, "execute", Parser::Execute); diff --git a/src/node_messaging.cc b/src/node_messaging.cc index 6dd66f243e..0a79d6f9d3 100644 --- a/src/node_messaging.cc +++ b/src/node_messaging.cc @@ -722,9 +722,7 @@ MaybeLocal<Function> GetMessagePortConstructor( Local<FunctionTemplate> m = env->NewFunctionTemplate(MessagePort::New); m->SetClassName(env->message_port_constructor_string()); m->InstanceTemplate()->SetInternalFieldCount(1); - - AsyncWrap::AddWrapMethods(env, m); - HandleWrap::AddWrapMethods(env, m); + m->Inherit(HandleWrap::GetConstructorTemplate(env)); env->SetProtoMethod(m, "postMessage", MessagePort::PostMessage); env->SetProtoMethod(m, "start", MessagePort::Start); diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 91333714b2..ca0927af66 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -50,9 +50,7 @@ void StatWatcher::Initialize(Environment* env, Local<Object> target) { Local<String> statWatcherString = FIXED_ONE_BYTE_STRING(env->isolate(), "StatWatcher"); t->SetClassName(statWatcherString); - - AsyncWrap::AddWrapMethods(env, t); - HandleWrap::AddWrapMethods(env, t); + t->Inherit(HandleWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "start", StatWatcher::Start); diff --git a/src/node_worker.cc b/src/node_worker.cc index aee97095a4..63d89a966d 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -482,8 +482,8 @@ void InitWorker(Local<Object> target, Local<FunctionTemplate> w = env->NewFunctionTemplate(Worker::New); w->InstanceTemplate()->SetInternalFieldCount(1); + w->Inherit(AsyncWrap::GetConstructorTemplate(env)); - AsyncWrap::AddWrapMethods(env, w); env->SetProtoMethod(w, "startThread", Worker::StartThread); env->SetProtoMethod(w, "stopThread", Worker::StopThread); env->SetProtoMethod(w, "ref", Worker::Ref); diff --git a/src/node_wrap.h b/src/node_wrap.h deleted file mode 100644 index 42caca2dc6..0000000000 --- a/src/node_wrap.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SRC_NODE_WRAP_H_ -#define SRC_NODE_WRAP_H_ - -#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -#include "env.h" -#include "pipe_wrap.h" -#include "tcp_wrap.h" -#include "tty_wrap.h" -#include "uv.h" -#include "v8.h" - -namespace node { - -// TODO(addaleax): Use real inheritance for the JS object templates to avoid -// this unnecessary case switching. -#define WITH_GENERIC_UV_STREAM(env, obj, BODY) \ - do { \ - if (env->tcp_constructor_template().IsEmpty() == false && \ - env->tcp_constructor_template()->HasInstance(obj)) { \ - TCPWrap* const wrap = Unwrap<TCPWrap>(obj); \ - BODY \ - } else if (env->tty_constructor_template().IsEmpty() == false && \ - env->tty_constructor_template()->HasInstance(obj)) { \ - TTYWrap* const wrap = Unwrap<TTYWrap>(obj); \ - BODY \ - } else if (env->pipe_constructor_template().IsEmpty() == false && \ - env->pipe_constructor_template()->HasInstance(obj)) { \ - PipeWrap* const wrap = Unwrap<PipeWrap>(obj); \ - BODY \ - } \ - } while (0) - -inline uv_stream_t* HandleToStream(Environment* env, - v8::Local<v8::Object> obj) { - v8::HandleScope scope(env->isolate()); - - WITH_GENERIC_UV_STREAM(env, obj, { - if (wrap == nullptr) - return nullptr; - return reinterpret_cast<uv_stream_t*>(wrap->UVHandle()); - }); - - return nullptr; -} - -} // namespace node - -#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS - -#endif // SRC_NODE_WRAP_H_ diff --git a/src/node_zlib.cc b/src/node_zlib.cc index d0cc54c943..93dcf0122d 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -755,8 +755,8 @@ void Initialize(Local<Object> target, Local<FunctionTemplate> z = env->NewFunctionTemplate(ZCtx::New); z->InstanceTemplate()->SetInternalFieldCount(1); + z->Inherit(AsyncWrap::GetConstructorTemplate(env)); - AsyncWrap::AddWrapMethods(env, z); env->SetProtoMethod(z, "write", ZCtx::Write<true>); env->SetProtoMethod(z, "writeSync", ZCtx::Write<false>); env->SetProtoMethod(z, "init", ZCtx::Init); diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index f3317ecc8c..eb1e06876c 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -28,7 +28,6 @@ #include "node.h" #include "node_buffer.h" #include "node_internals.h" -#include "node_wrap.h" #include "connect_wrap.h" #include "stream_base-inl.h" #include "stream_wrap.h" @@ -78,9 +77,7 @@ void PipeWrap::Initialize(Local<Object> target, t->SetClassName(pipeString); t->InstanceTemplate()->SetInternalFieldCount(1); - AsyncWrap::AddWrapMethods(env, t); - HandleWrap::AddWrapMethods(env, t); - LibuvStreamWrap::AddMethods(env, t); + t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "bind", Bind); env->SetProtoMethod(t, "listen", Listen); @@ -98,7 +95,7 @@ void PipeWrap::Initialize(Local<Object> target, // Create FunctionTemplate for PipeConnectWrap. auto cwt = BaseObject::MakeLazilyInitializedJSTemplate(env); - AsyncWrap::AddWrapMethods(env, cwt); + cwt->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> wrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap"); cwt->SetClassName(wrapString); diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 1daa437b29..af6cbfb4e5 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -20,10 +20,9 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "env-inl.h" -#include "handle_wrap.h" #include "node_internals.h" -#include "node_wrap.h" #include "stream_base-inl.h" +#include "stream_wrap.h" #include "util-inl.h" #include <string.h> @@ -58,8 +57,7 @@ class ProcessWrap : public HandleWrap { FIXED_ONE_BYTE_STRING(env->isolate(), "Process"); constructor->SetClassName(processString); - AsyncWrap::AddWrapMethods(env, constructor); - HandleWrap::AddWrapMethods(env, constructor); + constructor->Inherit(HandleWrap::GetConstructorTemplate(env)); env->SetProtoMethod(constructor, "spawn", Spawn); env->SetProtoMethod(constructor, "kill", Kill); @@ -92,6 +90,17 @@ class ProcessWrap : public HandleWrap { MarkAsUninitialized(); } + static uv_stream_t* StreamForWrap(Environment* env, Local<Object> stdio) { + Local<String> handle_key = env->handle_string(); + // This property has always been set by JS land if we are in this code path. + Local<Object> handle = + stdio->Get(env->context(), handle_key).ToLocalChecked().As<Object>(); + + uv_stream_t* stream = LibuvStreamWrap::From(env, handle)->stream(); + CHECK_NOT_NULL(stream); + return stream; + } + static void ParseStdioOptions(Environment* env, Local<Object> js_options, uv_process_options_t* options) { @@ -115,22 +124,10 @@ class ProcessWrap : public HandleWrap { } else if (type->StrictEquals(env->pipe_string())) { options->stdio[i].flags = static_cast<uv_stdio_flags>( UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE); - Local<String> handle_key = env->handle_string(); - Local<Object> handle = - stdio->Get(context, handle_key).ToLocalChecked().As<Object>(); - CHECK(!handle.IsEmpty()); - options->stdio[i].data.stream = - reinterpret_cast<uv_stream_t*>( - Unwrap<PipeWrap>(handle)->UVHandle()); + options->stdio[i].data.stream = StreamForWrap(env, stdio); } else if (type->StrictEquals(env->wrap_string())) { - Local<String> handle_key = env->handle_string(); - Local<Object> handle = - stdio->Get(context, handle_key).ToLocalChecked().As<Object>(); - uv_stream_t* stream = HandleToStream(env, handle); - CHECK_NOT_NULL(stream); - options->stdio[i].flags = UV_INHERIT_STREAM; - options->stdio[i].data.stream = stream; + options->stdio[i].data.stream = StreamForWrap(env, stdio); } else { Local<String> fd_key = env->fd_string(); Local<Value> fd_value = stdio->Get(context, fd_key).ToLocalChecked(); diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index b9ec037b45..e1792a0267 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -50,9 +50,7 @@ class SignalWrap : public HandleWrap { Local<String> signalString = FIXED_ONE_BYTE_STRING(env->isolate(), "Signal"); constructor->SetClassName(signalString); - - AsyncWrap::AddWrapMethods(env, constructor); - HandleWrap::AddWrapMethods(env, constructor); + constructor->Inherit(HandleWrap::GetConstructorTemplate(env)); env->SetProtoMethod(constructor, "start", Start); env->SetProtoMethod(constructor, "stop", Stop); diff --git a/src/stream_pipe.cc b/src/stream_pipe.cc index 90da2043af..0b00f225d8 100644 --- a/src/stream_pipe.cc +++ b/src/stream_pipe.cc @@ -257,7 +257,7 @@ void InitializeStreamPipe(Local<Object> target, FIXED_ONE_BYTE_STRING(env->isolate(), "StreamPipe"); env->SetProtoMethod(pipe, "unpipe", StreamPipe::Unpipe); env->SetProtoMethod(pipe, "start", StreamPipe::Start); - AsyncWrap::AddWrapMethods(env, pipe); + pipe->Inherit(AsyncWrap::GetConstructorTemplate(env)); pipe->SetClassName(stream_pipe_string); pipe->InstanceTemplate()->SetInternalFieldCount(1); target diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 9738d2a53b..9ccace435c 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -66,7 +66,7 @@ void LibuvStreamWrap::Initialize(Local<Object> target, Local<String> wrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "ShutdownWrap"); sw->SetClassName(wrapString); - AsyncWrap::AddWrapMethods(env, sw); + sw->Inherit(AsyncWrap::GetConstructorTemplate(env)); target->Set(wrapString, sw->GetFunction(env->context()).ToLocalChecked()); env->set_shutdown_wrap_template(sw->InstanceTemplate()); @@ -76,7 +76,7 @@ void LibuvStreamWrap::Initialize(Local<Object> target, Local<String> writeWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "WriteWrap"); ww->SetClassName(writeWrapString); - AsyncWrap::AddWrapMethods(env, ww); + ww->Inherit(AsyncWrap::GetConstructorTemplate(env)); target->Set(writeWrapString, ww->GetFunction(env->context()).ToLocalChecked()); env->set_write_wrap_template(ww->InstanceTemplate()); @@ -96,20 +96,36 @@ LibuvStreamWrap::LibuvStreamWrap(Environment* env, } -void LibuvStreamWrap::AddMethods(Environment* env, - v8::Local<v8::FunctionTemplate> target) { - Local<FunctionTemplate> get_write_queue_size = - FunctionTemplate::New(env->isolate(), - GetWriteQueueSize, - env->as_external(), - Signature::New(env->isolate(), target)); - target->PrototypeTemplate()->SetAccessorProperty( - env->write_queue_size_string(), - get_write_queue_size, - Local<FunctionTemplate>(), - static_cast<PropertyAttribute>(ReadOnly | DontDelete)); - env->SetProtoMethod(target, "setBlocking", SetBlocking); - StreamBase::AddMethods<LibuvStreamWrap>(env, target); +Local<FunctionTemplate> LibuvStreamWrap::GetConstructorTemplate( + Environment* env) { + Local<FunctionTemplate> tmpl = env->libuv_stream_wrap_ctor_template(); + if (tmpl.IsEmpty()) { + tmpl = env->NewFunctionTemplate(nullptr); + tmpl->SetClassName( + FIXED_ONE_BYTE_STRING(env->isolate(), "LibuvStreamWrap")); + tmpl->Inherit(HandleWrap::GetConstructorTemplate(env)); + Local<FunctionTemplate> get_write_queue_size = + FunctionTemplate::New(env->isolate(), + GetWriteQueueSize, + env->as_external(), + Signature::New(env->isolate(), tmpl)); + tmpl->PrototypeTemplate()->SetAccessorProperty( + env->write_queue_size_string(), + get_write_queue_size, + Local<FunctionTemplate>(), + static_cast<PropertyAttribute>(ReadOnly | DontDelete)); + env->SetProtoMethod(tmpl, "setBlocking", SetBlocking); + StreamBase::AddMethods<LibuvStreamWrap>(env, tmpl); + env->set_libuv_stream_wrap_ctor_template(tmpl); + } + return tmpl; +} + + +LibuvStreamWrap* LibuvStreamWrap::From(Environment* env, Local<Object> object) { + Local<FunctionTemplate> sw = env->libuv_stream_wrap_ctor_template(); + CHECK(!sw.IsEmpty() && sw->HasInstance(object)); + return Unwrap<LibuvStreamWrap>(object); } @@ -170,21 +186,25 @@ void LibuvStreamWrap::OnUvAlloc(size_t suggested_size, uv_buf_t* buf) { -template <class WrapType, class UVType> +template <class WrapType> static Local<Object> AcceptHandle(Environment* env, LibuvStreamWrap* parent) { + static_assert(std::is_base_of<LibuvStreamWrap, WrapType>::value || + std::is_base_of<UDPWrap, WrapType>::value, + "Can only accept stream handles"); + EscapableHandleScope scope(env->isolate()); Local<Object> wrap_obj; - UVType* handle; wrap_obj = WrapType::Instantiate(env, parent, WrapType::SOCKET); if (wrap_obj.IsEmpty()) return Local<Object>(); - WrapType* wrap; - ASSIGN_OR_RETURN_UNWRAP(&wrap, wrap_obj, Local<Object>()); - handle = wrap->UVHandle(); + HandleWrap* wrap = Unwrap<HandleWrap>(wrap_obj); + CHECK_NOT_NULL(wrap); + uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(wrap->GetHandle()); + CHECK_NOT_NULL(stream); - if (uv_accept(parent->stream(), reinterpret_cast<uv_stream_t*>(handle))) + if (uv_accept(parent->stream(), stream)) ABORT(); return scope.Escape(wrap_obj); @@ -209,11 +229,11 @@ void LibuvStreamWrap::OnUvRead(ssize_t nread, const uv_buf_t* buf) { Local<Object> pending_obj; if (type == UV_TCP) { - pending_obj = AcceptHandle<TCPWrap, uv_tcp_t>(env(), this); + pending_obj = AcceptHandle<TCPWrap>(env(), this); } else if (type == UV_NAMED_PIPE) { - pending_obj = AcceptHandle<PipeWrap, uv_pipe_t>(env(), this); + pending_obj = AcceptHandle<PipeWrap>(env(), this); } else if (type == UV_UDP) { - pending_obj = AcceptHandle<UDPWrap, uv_udp_t>(env(), this); + pending_obj = AcceptHandle<UDPWrap>(env(), this); } else { CHECK_EQ(type, UV_UNKNOWN_HANDLE); } diff --git a/src/stream_wrap.h b/src/stream_wrap.h index 487a40b7ff..98f0ca4ac4 100644 --- a/src/stream_wrap.h +++ b/src/stream_wrap.h @@ -76,6 +76,8 @@ class LibuvStreamWrap : public HandleWrap, public StreamBase { ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override; WriteWrap* CreateWriteWrap(v8::Local<v8::Object> object) override; + static LibuvStreamWrap* From(Environment* env, v8::Local<v8::Object> object); + protected: LibuvStreamWrap(Environment* env, v8::Local<v8::Object> object, @@ -84,8 +86,8 @@ class LibuvStreamWrap : public HandleWrap, public StreamBase { AsyncWrap* GetAsyncWrap() override; - static void AddMethods(Environment* env, - v8::Local<v8::FunctionTemplate> target); + static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( + Environment* env); protected: inline void set_fd(int fd) { diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 554b0216fa..ff30be3363 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -88,9 +88,7 @@ void TCPWrap::Initialize(Local<Object> target, t->InstanceTemplate()->Set(env->onread_string(), Null(env->isolate())); t->InstanceTemplate()->Set(env->onconnection_string(), Null(env->isolate())); - AsyncWrap::AddWrapMethods(env, t, AsyncWrap::kFlagHasReset); - HandleWrap::AddWrapMethods(env, t); - LibuvStreamWrap::AddMethods(env, t); + t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "open", Open); env->SetProtoMethod(t, "bind", Bind); @@ -115,7 +113,7 @@ void TCPWrap::Initialize(Local<Object> target, // Create FunctionTemplate for TCPConnectWrap. Local<FunctionTemplate> cwt = BaseObject::MakeLazilyInitializedJSTemplate(env); - AsyncWrap::AddWrapMethods(env, cwt); + cwt->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> wrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap"); cwt->SetClassName(wrapString); diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 27bedd08ce..3462dac8ae 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -891,7 +891,7 @@ void TLSWrap::Initialize(Local<Object> target, Local<FunctionTemplate>(), static_cast<PropertyAttribute>(ReadOnly | DontDelete)); - AsyncWrap::AddWrapMethods(env, t, AsyncWrap::kFlagHasReset); + t->Inherit(AsyncWrap::GetConstructorTemplate(env)); env->SetProtoMethod(t, "receive", Receive); env->SetProtoMethod(t, "start", Start); env->SetProtoMethod(t, "setVerifyMode", SetVerifyMode); diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index e7b684a7ee..1d0ea90f36 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -24,7 +24,6 @@ #include "env-inl.h" #include "handle_wrap.h" #include "node_buffer.h" -#include "node_wrap.h" #include "stream_base-inl.h" #include "stream_wrap.h" #include "util-inl.h" @@ -52,10 +51,7 @@ void TTYWrap::Initialize(Local<Object> target, Local<FunctionTemplate> t = env->NewFunctionTemplate(New); t->SetClassName(ttyString); t->InstanceTemplate()->SetInternalFieldCount(1); - - AsyncWrap::AddWrapMethods(env, t); - HandleWrap::AddWrapMethods(env, t); - LibuvStreamWrap::AddMethods(env, t); + t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env)); env->SetProtoMethodNoSideEffect(t, "getWindowSize", TTYWrap::GetWindowSize); env->SetProtoMethod(t, "setRawMode", SetRawMode); diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 510926abde..77139c2f93 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -135,8 +135,7 @@ void UDPWrap::Initialize(Local<Object> target, env->SetProtoMethod(t, "setTTL", SetTTL); env->SetProtoMethod(t, "bufferSize", BufferSize); - AsyncWrap::AddWrapMethods(env, t); - HandleWrap::AddWrapMethods(env, t); + t->Inherit(HandleWrap::GetConstructorTemplate(env)); target->Set(udpString, t->GetFunction(env->context()).ToLocalChecked()); env->set_udp_constructor_function( @@ -145,7 +144,7 @@ void UDPWrap::Initialize(Local<Object> target, // Create FunctionTemplate for SendWrap Local<FunctionTemplate> swt = BaseObject::MakeLazilyInitializedJSTemplate(env); - AsyncWrap::AddWrapMethods(env, swt); + swt->Inherit(AsyncWrap::GetConstructorTemplate(env)); Local<String> sendWrapString = FIXED_ONE_BYTE_STRING(env->isolate(), "SendWrap"); swt->SetClassName(sendWrapString); diff --git a/test/parallel/test-accessor-properties.js b/test/parallel/test-accessor-properties.js index ce026313d0..453100d108 100644 --- a/test/parallel/test-accessor-properties.js +++ b/test/parallel/test-accessor-properties.js @@ -32,24 +32,26 @@ const UDP = internalBinding('udp_wrap').UDP; UDP.prototype.fd; }, TypeError); + const StreamWrapProto = Object.getPrototypeOf(TTY.prototype); + // Should not throw for Object.getOwnPropertyDescriptor assert.strictEqual( - typeof Object.getOwnPropertyDescriptor(TTY.prototype, 'bytesRead'), + typeof Object.getOwnPropertyDescriptor(StreamWrapProto, 'bytesRead'), 'object' ); assert.strictEqual( - typeof Object.getOwnPropertyDescriptor(TTY.prototype, 'fd'), + typeof Object.getOwnPropertyDescriptor(StreamWrapProto, 'fd'), 'object' ); assert.strictEqual( - typeof Object.getOwnPropertyDescriptor(TTY.prototype, '_externalStream'), + typeof Object.getOwnPropertyDescriptor(StreamWrapProto, '_externalStream'), 'object' ); assert.strictEqual( - typeof Object.getOwnPropertyDescriptor(UDP.prototype, 'fd'), + typeof Object.getOwnPropertyDescriptor(StreamWrapProto, 'fd'), 'object' ); } |