src: use JS inheritance for AsyncWrap
For all classes descending from `AsyncWrap`, use JS inheritance instead of manually adding methods to the individual classes. This allows cleanup of some code around transferring handles over IPC. PR-URL: https://github.com/nodejs/node/pull/23094 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
2ebdba1229
commit
d527dde360
@ -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
|
||||
|
1
node.gyp
1
node.gyp
@ -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',
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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>);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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_
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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'
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user