Skip to content

Commit 8dc39e5

Browse files
jasnelladuh95
authored andcommitted
process: add process.ref() and process.unref() methods
The `process.ref(...)` and `process.unref(...)` methods are intended to replace the use of `ref()` and `unref()` methods defined directly on individual API objects. The existing `ref()` and `unref()` methods will be marked as legacy and won't be removed but new APIs should use `process.ref()` and `process.unref()` instead. Refs: #53266 PR-URL: #56400 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
1 parent c2f4d8d commit 8dc39e5

File tree

4 files changed

+110
-0
lines changed

4 files changed

+110
-0
lines changed

doc/api/process.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3228,6 +3228,23 @@ const { ppid } = require('node:process');
32283228
console.log(`The parent process is pid ${ppid}`);
32293229
```
32303230
3231+
## `process.ref(maybeRefable)`
3232+
3233+
<!-- YAML
3234+
added: REPLACEME
3235+
-->
3236+
3237+
* `maybeRefable` {any} An object that may be "refable".
3238+
3239+
An object is "refable" if it implements the Node.js "Refable protocol".
3240+
Specifically, this means that the object implements the `Symbol.for('node:ref')`
3241+
and `Symbol.for('node:unref')` methods. "Ref'd" objects will keep the Node.js
3242+
event loop alive, while "unref'd" objects will not. Historically, this was
3243+
implemented by using `ref()` and `unref()` methods directly on the objects.
3244+
This pattern, however, is being deprecated in favor of the "Refable protocol"
3245+
in order to better support Web Platform API types whose APIs cannot be modified
3246+
to add `ref()` and `unref()` methods but still need to support that behavior.
3247+
32313248
## `process.release`
32323249
32333250
<!-- YAML
@@ -4268,6 +4285,23 @@ console.log(
42684285
42694286
In [`Worker`][] threads, `process.umask(mask)` will throw an exception.
42704287
4288+
## `process.unref(maybeRefable)`
4289+
4290+
<!-- YAML
4291+
added: REPLACEME
4292+
-->
4293+
4294+
* `maybeUnfefable` {any} An object that may be "unref'd".
4295+
4296+
An object is "unrefable" if it implements the Node.js "Refable protocol".
4297+
Specifically, this means that the object implements the `Symbol.for('node:ref')`
4298+
and `Symbol.for('node:unref')` methods. "Ref'd" objects will keep the Node.js
4299+
event loop alive, while "unref'd" objects will not. Historically, this was
4300+
implemented by using `ref()` and `unref()` methods directly on the objects.
4301+
This pattern, however, is being deprecated in favor of the "Refable protocol"
4302+
in order to better support Web Platform API types whose APIs cannot be modified
4303+
to add `ref()` and `unref()` methods but still need to support that behavior.
4304+
42714305
## `process.uptime()`
42724306
42734307
<!-- YAML

lib/internal/bootstrap/node.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ const rawMethods = internalBinding('process_methods');
178178
process.availableMemory = rawMethods.availableMemory;
179179
process.kill = wrapped.kill;
180180
process.exit = wrapped.exit;
181+
process.ref = perThreadSetup.ref;
182+
process.unref = perThreadSetup.unref;
181183

182184
let finalizationMod;
183185
ObjectDefineProperty(process, 'finalization', {

lib/internal/process/per_thread.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
ArrayPrototypeSplice,
1414
BigUint64Array,
1515
Float64Array,
16+
FunctionPrototypeCall,
1617
NumberMAX_SAFE_INTEGER,
1718
ObjectDefineProperty,
1819
ObjectFreeze,
@@ -26,6 +27,7 @@ const {
2627
StringPrototypeReplace,
2728
StringPrototypeSlice,
2829
Symbol,
30+
SymbolFor,
2931
SymbolIterator,
3032
} = primordials;
3133

@@ -418,6 +420,16 @@ function toggleTraceCategoryState(asyncHooksEnabled) {
418420

419421
const { arch, platform, version } = process;
420422

423+
function ref(maybeRefable) {
424+
const fn = maybeRefable?.[SymbolFor('node:ref')] || maybeRefable?.ref;
425+
if (typeof fn === 'function') FunctionPrototypeCall(fn, maybeRefable);
426+
}
427+
428+
function unref(maybeRefable) {
429+
const fn = maybeRefable?.[SymbolFor('node:unref')] || maybeRefable?.unref;
430+
if (typeof fn === 'function') FunctionPrototypeCall(fn, maybeRefable);
431+
}
432+
421433
module.exports = {
422434
toggleTraceCategoryState,
423435
buildAllowedFlags,
@@ -427,4 +439,6 @@ module.exports = {
427439
arch,
428440
platform,
429441
version,
442+
ref,
443+
unref,
430444
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
const {
6+
describe,
7+
it,
8+
} = require('node:test');
9+
10+
const {
11+
strictEqual,
12+
} = require('node:assert');
13+
14+
class Foo {
15+
refCalled = 0;
16+
unrefCalled = 0;
17+
ref() {
18+
this.refCalled++;
19+
}
20+
unref() {
21+
this.unrefCalled++;
22+
}
23+
}
24+
25+
class Foo2 {
26+
refCalled = 0;
27+
unrefCalled = 0;
28+
[Symbol.for('node:ref')]() {
29+
this.refCalled++;
30+
}
31+
[Symbol.for('node:unref')]() {
32+
this.unrefCalled++;
33+
}
34+
}
35+
36+
describe('process.ref/unref work as expected', () => {
37+
it('refs...', () => {
38+
// Objects that implement the new Symbol-based API
39+
// just work.
40+
const foo1 = new Foo();
41+
const foo2 = new Foo2();
42+
process.ref(foo1);
43+
process.unref(foo1);
44+
process.ref(foo2);
45+
process.unref(foo2);
46+
strictEqual(foo1.refCalled, 1);
47+
strictEqual(foo1.unrefCalled, 1);
48+
strictEqual(foo2.refCalled, 1);
49+
strictEqual(foo2.unrefCalled, 1);
50+
51+
// Objects that implement the legacy API also just work.
52+
const i = setInterval(() => {}, 1000);
53+
strictEqual(i.hasRef(), true);
54+
process.unref(i);
55+
strictEqual(i.hasRef(), false);
56+
process.ref(i);
57+
strictEqual(i.hasRef(), true);
58+
clearInterval(i);
59+
});
60+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy