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.
  • Loading branch information
mcollina committed Mar 15, 2019
1 parent 3c83f93 commit 68a5477
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 68a5477

Please sign in to comment.