Skip to content

Commit

Permalink
src: use JS inheritance for AsyncWrap
Browse files Browse the repository at this point in the history
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.

Backport-PR-URL: #23247
PR-URL: #23094
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
addaleax authored and targos committed Oct 7, 2018
1 parent 11c6745 commit 5a83967
Show file tree
Hide file tree
Showing 32 changed files with 141 additions and 204 deletions.
3 changes: 2 additions & 1 deletion lib/internal/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,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',
Expand Down
25 changes: 16 additions & 9 deletions src/async_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,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);
Expand Down Expand Up @@ -423,12 +423,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,
Expand Down Expand Up @@ -524,17 +528,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);
}
}

Expand Down
10 changes: 2 additions & 8 deletions src/async_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,21 +105,15 @@ class AsyncWrap : public BaseObject {
PROVIDERS_LENGTH,
};

enum Flags {
kFlagNone = 0x0,
kFlagHasReset = 0x1
};

AsyncWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
double execution_async_id = -1);

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,
Expand Down
8 changes: 4 additions & 4 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2220,23 +2220,23 @@ 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);
target->Set(addrInfoWrapString, aiw->GetFunction(context).ToLocalChecked());

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);
target->Set(nameInfoWrapString, niw->GetFunction(context).ToLocalChecked());

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);
Expand All @@ -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>);
Expand Down
5 changes: 4 additions & 1 deletion src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand All @@ -329,13 +330,15 @@ 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) \
V(http2settings_constructor_template, v8::ObjectTemplate) \
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) \
Expand Down
2 changes: 1 addition & 1 deletion src/fs_event_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
20 changes: 13 additions & 7 deletions src/handle_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down
4 changes: 2 additions & 2 deletions src/handle_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/inspector_js_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/js_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>);
Expand Down
10 changes: 5 additions & 5 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2250,7 +2250,7 @@ void Initialize(Local<Object> target,
// Create FunctionTemplate for FSReqCallback
Local<FunctionTemplate> fst = env->NewFunctionTemplate(NewFSReqWrap);
fst->InstanceTemplate()->SetInternalFieldCount(1);
AsyncWrap::AddWrapMethods(env, fst);
fst->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<String> wrapString = FIXED_ONE_BYTE_STRING(isolate, "FSReqWrap");
fst->SetClassName(wrapString);
target
Expand All @@ -2262,7 +2262,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);
Expand All @@ -2271,7 +2271,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);
Expand All @@ -2281,7 +2281,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();
Expand All @@ -2300,7 +2300,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);
Expand Down
8 changes: 4 additions & 4 deletions src/node_http2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/node_http_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions src/node_messaging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions src/node_stat_watcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/node_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,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);
Expand Down
Loading

0 comments on commit 5a83967

Please sign in to comment.