Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async_hooks: remove deprecated emitBefore and emitAfter #26530

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions doc/api/async_hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -659,41 +659,6 @@ of the async resource. This will establish the context, trigger the AsyncHooks
before callbacks, call the function, trigger the AsyncHooks after callbacks, and
then restore the original execution context.

#### asyncResource.emitBefore()
<!-- YAML
deprecated: v9.6.0
-->
> Stability: 0 - Deprecated: Use [`asyncResource.runInAsyncScope()`][] instead.

Call all `before` callbacks to notify that a new asynchronous execution context
is being entered. If nested calls to `emitBefore()` are made, the stack of
`asyncId`s will be tracked and properly unwound.

`before` and `after` calls must be unwound in the same order that they
are called. Otherwise, an unrecoverable exception will occur and the process
will abort. For this reason, the `emitBefore` and `emitAfter` APIs are
considered deprecated. Please use `runInAsyncScope`, as it provides a much safer
alternative.

#### asyncResource.emitAfter()
<!-- YAML
deprecated: v9.6.0
-->
> Stability: 0 - Deprecated: Use [`asyncResource.runInAsyncScope()`][] instead.

Call all `after` callbacks. If nested calls to `emitBefore()` were made, then
make sure the stack is unwound properly. Otherwise an error will be thrown.

If the user's callback throws an exception, `emitAfter()` will automatically be
called for all `asyncId`s on the stack if the error is handled by a domain or
`'uncaughtException'` handler.

`before` and `after` calls must be unwound in the same order that they
are called. Otherwise, an unrecoverable exception will occur and the process
will abort. For this reason, the `emitBefore` and `emitAfter` APIs are
considered deprecated. Please use `runInAsyncScope`, as it provides a much safer
alternative.

#### asyncResource.emitDestroy()

* Returns: {AsyncResource} A reference to `asyncResource`.
Expand All @@ -713,7 +678,6 @@ never be called.
`AsyncResource` constructor.

[`after` callback]: #async_hooks_after_asyncid
[`asyncResource.runInAsyncScope()`]: #async_hooks_asyncresource_runinasyncscope_fn_thisarg_args
[`before` callback]: #async_hooks_before_asyncid
[`destroy` callback]: #async_hooks_destroy_asyncid
[`init` callback]: #async_hooks_init_asyncid_type_triggerasyncid_resource
Expand Down
5 changes: 4 additions & 1 deletion doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1905,6 +1905,9 @@ should start using the `async_context` variant of `MakeCallback` or
### DEP0098: AsyncHooks Embedder AsyncResource.emitBefore and AsyncResource.emitAfter APIs
<!-- YAML
changes:
- version: REPLACEME
pr-url:
description: End-of-Life
- version:
- v8.12.0
- v9.6.0
Expand All @@ -1913,7 +1916,7 @@ changes:
description: Runtime deprecation.
-->

Type: Runtime
Type: End-of-Life

The embedded API provided by AsyncHooks exposes `.emitBefore()` and
`.emitAfter()` methods which are very easy to use incorrectly which can lead
Expand Down
23 changes: 0 additions & 23 deletions lib/async_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,6 @@ function createHook(fns) {

const destroyedSymbol = Symbol('destroyed');

let emitBeforeAfterWarning = true;
function showEmitBeforeAfterWarning() {
if (emitBeforeAfterWarning) {
process.emitWarning(
'asyncResource.emitBefore and emitAfter are deprecated. Please use ' +
'asyncResource.runInAsyncScope instead',
'DeprecationWarning', 'DEP0098');
emitBeforeAfterWarning = false;
}
}

class AsyncResource {
constructor(type, opts = {}) {
validateString(type, 'type');
Expand Down Expand Up @@ -169,18 +158,6 @@ class AsyncResource {
}
}

emitBefore() {
showEmitBeforeAfterWarning();
emitBefore(this[async_id_symbol], this[trigger_async_id_symbol]);
return this;
}

emitAfter() {
showEmitBeforeAfterWarning();
emitAfter(this[async_id_symbol]);
return this;
}

runInAsyncScope(fn, thisArg, ...args) {
emitBefore(this[async_id_symbol], this[trigger_async_id_symbol]);
let ret;
Expand Down
2 changes: 1 addition & 1 deletion test/async-hooks/test-callback-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ switch (arg) {
onbefore: common.mustCall(() => { throw new Error(arg); })
}).enable();
const resource = new async_hooks.AsyncResource(`${arg}_type`);
resource.emitBefore();
resource.runInAsyncScope(() => {});
return;

case 'test_callback_abort':
Expand Down
24 changes: 12 additions & 12 deletions test/async-hooks/test-embedder.api.async-resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ assert.strictEqual(typeof alcaEvent.asyncId(), 'number');
assert.notStrictEqual(alcaEvent.asyncId(), alcaTriggerId);
assert.strictEqual(alcaEvent.triggerAsyncId(), alcaTriggerId);

alcaEvent.emitBefore();
checkInvocations(alcazares, { init: 1, before: 1 },
'alcazares emitted before');
alcaEvent.emitAfter();
alcaEvent.runInAsyncScope(() => {
checkInvocations(alcazares, { init: 1, before: 1 },
'alcazares emitted before');
});
checkInvocations(alcazares, { init: 1, before: 1, after: 1 },
'alcazares emitted after');
alcaEvent.emitBefore();
checkInvocations(alcazares, { init: 1, before: 2, after: 1 },
'alcazares emitted before again');
alcaEvent.emitAfter();
alcaEvent.runInAsyncScope(() => {
checkInvocations(alcazares, { init: 1, before: 2, after: 1 },
'alcazares emitted before again');
});
checkInvocations(alcazares, { init: 1, before: 2, after: 2 },
'alcazares emitted after again');
alcaEvent.emitDestroy();
Expand All @@ -75,11 +75,11 @@ function tick1() {
assert.strictEqual(typeof poblado.uid, 'number');
assert.strictEqual(poblado.triggerAsyncId, pobTriggerId);
checkInvocations(poblado, { init: 1 }, 'poblado constructed');
pobEvent.emitBefore();
checkInvocations(poblado, { init: 1, before: 1 },
'poblado emitted before');
pobEvent.runInAsyncScope(() => {
checkInvocations(poblado, { init: 1, before: 1 },
'poblado emitted before');
});

pobEvent.emitAfter();
checkInvocations(poblado, { init: 1, before: 1, after: 1 },
'poblado emitted after');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');
const { AsyncResource } = async_hooks;
const internal_async_hooks = require('internal/async_hooks');
const { spawn } = require('child_process');
const corruptedMsg = /async hook stack has become corrupted/;
const heartbeatMsg = /heartbeat: still alive/;

const {
newAsyncId, getDefaultTriggerAsyncId,
emitInit, emitBefore, emitAfter, emitDestroy
} = internal_async_hooks;

const initHooks = require('./init-hooks');

if (process.argv[2] === 'child') {
Expand All @@ -17,20 +22,29 @@ if (process.argv[2] === 'child') {
// Once 'destroy' has been emitted, we can no longer emit 'after'

// Emitting 'before', 'after' and then 'destroy'
const event1 = new AsyncResource('event1', async_hooks.executionAsyncId());
event1.emitBefore();
event1.emitAfter();
event1.emitDestroy();
{
const asyncId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(asyncId, 'event1', triggerId, {});
emitBefore(asyncId, triggerId);
emitAfter(asyncId);
emitDestroy(asyncId);
}

// Emitting 'after' after 'destroy'
const event2 = new AsyncResource('event2', async_hooks.executionAsyncId());
event2.emitDestroy();

console.log('heartbeat: still alive');
event2.emitAfter();
{
const asyncId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(asyncId, 'event2', triggerId, {});
emitDestroy(asyncId);

console.log('heartbeat: still alive');
emitAfter(asyncId);
}
} else {
const args = process.argv.slice(1).concat('child');
const args = ['--expose-internals']
.concat(process.argv.slice(1))
.concat('child');
let errData = Buffer.from('');
let outData = Buffer.from('');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');
const { AsyncResource } = async_hooks;
const internal_async_hooks = require('internal/async_hooks');
const { spawn } = require('child_process');
const corruptedMsg = /async hook stack has become corrupted/;
const heartbeatMsg = /heartbeat: still alive/;

const {
newAsyncId, getDefaultTriggerAsyncId,
emitInit, emitBefore, emitAfter, emitDestroy
} = internal_async_hooks;

const initHooks = require('./init-hooks');

if (process.argv[2] === 'child') {
Expand All @@ -17,20 +22,29 @@ if (process.argv[2] === 'child') {
// Once 'destroy' has been emitted, we can no longer emit 'before'

// Emitting 'before', 'after' and then 'destroy'
const event1 = new AsyncResource('event1', async_hooks.executionAsyncId());
event1.emitBefore();
event1.emitAfter();
event1.emitDestroy();
{
const asyncId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(asyncId, 'event1', triggerId, {});
emitBefore(asyncId, triggerId);
emitAfter(asyncId);
emitDestroy(asyncId);
}

// Emitting 'before' after 'destroy'
const event2 = new AsyncResource('event2', async_hooks.executionAsyncId());
event2.emitDestroy();

console.log('heartbeat: still alive');
event2.emitBefore();
{
const asyncId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(asyncId, 'event2', triggerId, {});
emitDestroy(asyncId);

console.log('heartbeat: still alive');
emitBefore(asyncId, triggerId);
}
} else {
const args = process.argv.slice(1).concat('child');
const args = ['--expose-internals']
.concat(process.argv.slice(1))
.concat('child');
let errData = Buffer.from('');
let outData = Buffer.from('');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');
const { AsyncResource } = async_hooks;
const internal_async_hooks = require('internal/async_hooks');
const { spawn } = require('child_process');
const corruptedMsg = /async hook stack has become corrupted/;
const heartbeatMsg = /heartbeat: still alive/;

const {
newAsyncId, getDefaultTriggerAsyncId,
emitInit, emitBefore, emitAfter
} = internal_async_hooks;

const initHooks = require('./init-hooks');

if (process.argv[2] === 'child') {
Expand All @@ -17,18 +22,28 @@ if (process.argv[2] === 'child') {
// Async hooks enforce proper order of 'before' and 'after' invocations

// Proper ordering
const event1 = new AsyncResource('event1', async_hooks.executionAsyncId());
event1.emitBefore();
event1.emitAfter();
{
const asyncId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(asyncId, 'event1', triggerId, {});
emitBefore(asyncId, triggerId);
emitAfter(asyncId);
}

// Improper ordering
// Emitting 'after' without 'before' which is illegal
const event2 = new AsyncResource('event2', async_hooks.executionAsyncId());

console.log('heartbeat: still alive');
event2.emitAfter();
{
const asyncId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(asyncId, 'event2', triggerId, {});

console.log('heartbeat: still alive');
emitAfter(asyncId);
}
} else {
const args = process.argv.slice(1).concat('child');
const args = ['--expose-internals']
.concat(process.argv.slice(1))
.concat('child');
let errData = Buffer.from('');
let outData = Buffer.from('');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// Flags: --expose-internals
'use strict';

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');
const { AsyncResource } = async_hooks;
const internal_async_hooks = require('internal/async_hooks');
const { spawn } = require('child_process');
const corruptedMsg = /async hook stack has become corrupted/;
const heartbeatMsg = /heartbeat: still alive/;

const {
newAsyncId, getDefaultTriggerAsyncId,
emitInit, emitBefore, emitAfter
} = internal_async_hooks;

const initHooks = require('./init-hooks');

if (process.argv[2] === 'child') {
Expand All @@ -21,23 +26,28 @@ if (process.argv[2] === 'child') {
// The first test of the two below follows that rule,
// the second one doesn't.

const event1 = new AsyncResource('event1', async_hooks.executionAsyncId());
const event2 = new AsyncResource('event2', async_hooks.executionAsyncId());
const eventOneId = newAsyncId();
const eventTwoId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(eventOneId, 'event1', triggerId, {});
emitInit(eventTwoId, 'event2', triggerId, {});

// Proper unwind
event1.emitBefore();
event2.emitBefore();
event2.emitAfter();
event1.emitAfter();
emitBefore(eventOneId, triggerId);
emitBefore(eventTwoId, triggerId);
emitAfter(eventTwoId);
emitAfter(eventOneId);

// Improper unwind
event1.emitBefore();
event2.emitBefore();
emitBefore(eventOneId, triggerId);
emitBefore(eventTwoId, triggerId);

console.log('heartbeat: still alive');
event1.emitAfter();
emitAfter(eventOneId);
} else {
const args = process.argv.slice(1).concat('child');
const args = ['--expose-internals']
.concat(process.argv.slice(1))
.concat('child');
let errData = Buffer.from('');
let outData = Buffer.from('');

Expand Down
Loading