Skip to content

Commit

Permalink
async_hooks: remove deprecated emitBefore and emitAfter
Browse files Browse the repository at this point in the history
AsyncResource.emitBefore and AsyncResource.emitAfter have been
deprecated in #18632. This PR removes
it all.
This commit also updates some embedder tests to use internal APIs.
The conditions are still possible for Node.js core developers but not
for end users.

PR-URL: #26530
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
mcollina committed Mar 18, 2019
1 parent abafd38 commit 9d06443
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 133 deletions.
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

0 comments on commit 9d06443

Please sign in to comment.