Skip to content

Commit d313204

Browse files
Fishrock123evanlucas
authored andcommitted
handle_wrap: expose an isRefed() check to JS
This allows third-party tools to check whether or not a handle that can be unreferenced is unreferenced at a particular time. Notably, this should be helpful for inspection via AsyncWrap. Also, this is useful even to node's internals, particularly timers. Refs: #5828 Refs: #5827 PR-URL: #5834 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
1 parent 5c7da21 commit d313204

11 files changed

+146
-0
lines changed

src/handle_wrap.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace node {
1111

12+
using v8::Boolean;
1213
using v8::Context;
1314
using v8::FunctionCallbackInfo;
1415
using v8::HandleScope;
@@ -37,6 +38,15 @@ void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) {
3738
}
3839

3940

41+
void HandleWrap::IsRefed(const FunctionCallbackInfo<Value>& args) {
42+
Environment* env = Environment::GetCurrent(args);
43+
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
44+
45+
bool refed = IsAlive(wrap) && (wrap->flags_ & kUnref) == 0;
46+
args.GetReturnValue().Set(refed);
47+
}
48+
49+
4050
void HandleWrap::Close(const FunctionCallbackInfo<Value>& args) {
4151
Environment* env = Environment::GetCurrent(args);
4252

src/handle_wrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class HandleWrap : public AsyncWrap {
3535
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
3636
static void Ref(const v8::FunctionCallbackInfo<v8::Value>& args);
3737
static void Unref(const v8::FunctionCallbackInfo<v8::Value>& args);
38+
static void IsRefed(const v8::FunctionCallbackInfo<v8::Value>& args);
3839

3940
static inline bool IsAlive(const HandleWrap* wrap) {
4041
return wrap != nullptr && wrap->GetHandle() != nullptr;

src/pipe_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ void PipeWrap::Initialize(Local<Object> target,
8080
env->SetProtoMethod(t, "close", HandleWrap::Close);
8181
env->SetProtoMethod(t, "unref", HandleWrap::Unref);
8282
env->SetProtoMethod(t, "ref", HandleWrap::Ref);
83+
env->SetProtoMethod(t, "isRefed", HandleWrap::IsRefed);
8384

8485
StreamWrap::AddMethods(env, t);
8586

src/process_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class ProcessWrap : public HandleWrap {
4040

4141
env->SetProtoMethod(constructor, "ref", HandleWrap::Ref);
4242
env->SetProtoMethod(constructor, "unref", HandleWrap::Unref);
43+
env->SetProtoMethod(constructor, "isRefed", HandleWrap::IsRefed);
4344

4445
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Process"),
4546
constructor->GetFunction());

src/signal_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class SignalWrap : public HandleWrap {
3232
env->SetProtoMethod(constructor, "close", HandleWrap::Close);
3333
env->SetProtoMethod(constructor, "ref", HandleWrap::Ref);
3434
env->SetProtoMethod(constructor, "unref", HandleWrap::Unref);
35+
env->SetProtoMethod(constructor, "isRefed", HandleWrap::IsRefed);
3536
env->SetProtoMethod(constructor, "start", Start);
3637
env->SetProtoMethod(constructor, "stop", Stop);
3738

src/tcp_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ void TCPWrap::Initialize(Local<Object> target,
8787

8888
env->SetProtoMethod(t, "ref", HandleWrap::Ref);
8989
env->SetProtoMethod(t, "unref", HandleWrap::Unref);
90+
env->SetProtoMethod(t, "isRefed", HandleWrap::IsRefed);
9091

9192
StreamWrap::AddMethods(env, t, StreamBase::kFlagHasWritev);
9293

src/timer_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class TimerWrap : public HandleWrap {
3939
env->SetProtoMethod(constructor, "close", HandleWrap::Close);
4040
env->SetProtoMethod(constructor, "ref", HandleWrap::Ref);
4141
env->SetProtoMethod(constructor, "unref", HandleWrap::Unref);
42+
env->SetProtoMethod(constructor, "isRefed", HandleWrap::IsRefed);
4243

4344
env->SetProtoMethod(constructor, "start", Start);
4445
env->SetProtoMethod(constructor, "stop", Stop);

src/tty_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void TTYWrap::Initialize(Local<Object> target,
3636

3737
env->SetProtoMethod(t, "close", HandleWrap::Close);
3838
env->SetProtoMethod(t, "unref", HandleWrap::Unref);
39+
env->SetProtoMethod(t, "isRefed", HandleWrap::IsRefed);
3940

4041
StreamWrap::AddMethods(env, t, StreamBase::kFlagNoShutdown);
4142

src/udp_wrap.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ void UDPWrap::Initialize(Local<Object> target,
108108

109109
env->SetProtoMethod(t, "ref", HandleWrap::Ref);
110110
env->SetProtoMethod(t, "unref", HandleWrap::Unref);
111+
env->SetProtoMethod(t, "isRefed", HandleWrap::IsRefed);
111112

112113
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "UDP"), t->GetFunction());
113114
env->set_udp_constructor_function(t->GetFunction());
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const strictEqual = require('assert').strictEqual;
5+
const spawn = require('child_process').spawn;
6+
7+
function makeAssert(message) {
8+
return function(actual, expected) {
9+
strictEqual(actual, expected, message);
10+
};
11+
}
12+
const assert = makeAssert('isRefed() not working on tty_wrap');
13+
14+
if (process.argv[2] === 'child') {
15+
// Test tty_wrap in piped child to guarentee stdin being a TTY.
16+
const ReadStream = require('tty').ReadStream;
17+
const tty = new ReadStream(0);
18+
assert(Object.getPrototypeOf(tty._handle).hasOwnProperty('isRefed'), true);
19+
assert(tty._handle.isRefed(), true);
20+
tty.unref();
21+
assert(tty._handle.isRefed(), false);
22+
return;
23+
}
24+
25+
// Use spawn so that we can be sure that stdin has a _handle property.
26+
// Refs: https://github.com/nodejs/node/pull/5916
27+
const proc = spawn(process.execPath, [__filename, 'child'], { stdio: 'pipe' });
28+
proc.stderr.pipe(process.stderr);
29+
proc.on('exit', common.mustCall(function(exitCode) {
30+
process.exitCode = exitCode;
31+
}));

0 commit comments

Comments
 (0)