GeezerVison is showing github.com — process: add process.ref() and process.unref() methods · nodejs/node@8dc39e5
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/process.md +34Lines changed: 34 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -3228,6 +3228,23 @@ const { ppid } = require('node:process'); | 3228 | 3228 | console.log(`The parent process is pid ${ppid}`); | 3229 | 3229 | ``` | 3230 | 3230 |
| | 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 | +
| 3231 | 3248 | ## `process.release` | 3232 | 3249 |
| 3233 | 3250 | <!-- YAML | @@ -4268,6 +4285,23 @@ console.log( | 4268 | 4285 |
| 4269 | 4286 | In [`Worker`][] threads, `process.umask(mask)` will throw an exception. | 4270 | 4287 |
| | 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 | +
| 4271 | 4305 | ## `process.uptime()` | 4272 | 4306 |
| 4273 | 4307 | <!-- YAML | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/bootstrap/node.js +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -178,6 +178,8 @@ const rawMethods = internalBinding('process_methods'); | 178 | 178 | process.availableMemory = rawMethods.availableMemory; | 179 | 179 | process.kill = wrapped.kill; | 180 | 180 | process.exit = wrapped.exit; | | 181 | + process.ref = perThreadSetup.ref; | | 182 | + process.unref = perThreadSetup.unref; | 181 | 183 |
| 182 | 184 | let finalizationMod; | 183 | 185 | ObjectDefineProperty(process, 'finalization', { | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/process/per_thread.js +14Lines changed: 14 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -13,6 +13,7 @@ const { | 13 | 13 | ArrayPrototypeSplice, | 14 | 14 | BigUint64Array, | 15 | 15 | Float64Array, | | 16 | + FunctionPrototypeCall, | 16 | 17 | NumberMAX_SAFE_INTEGER, | 17 | 18 | ObjectDefineProperty, | 18 | 19 | ObjectFreeze, | @@ -26,6 +27,7 @@ const { | 26 | 27 | StringPrototypeReplace, | 27 | 28 | StringPrototypeSlice, | 28 | 29 | Symbol, | | 30 | + SymbolFor, | 29 | 31 | SymbolIterator, | 30 | 32 | } = primordials; | 31 | 33 |
| @@ -418,6 +420,16 @@ function toggleTraceCategoryState(asyncHooksEnabled) { | 418 | 420 |
| 419 | 421 | const { arch, platform, version } = process; | 420 | 422 |
| | 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 | + | 421 | 433 | module.exports = { | 422 | 434 | toggleTraceCategoryState, | 423 | 435 | buildAllowedFlags, | @@ -427,4 +439,6 @@ module.exports = { | 427 | 439 | arch, | 428 | 440 | platform, | 429 | 441 | version, | | 442 | + ref, | | 443 | + unref, | 430 | 444 | }; |
Collapse file Copy file name to clipboard +60Lines changed: 60 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 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 | +}); |
|