0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00

async_hooks: remove internal only error checking

This error checking is mostly unnecessary and is just a Node core
developer nicety, rather than something that is needed for the
user-land. It can be safely removed without any practical
impact while making nextTick, timers, immediates and AsyncResource
substantially faster.

PR-URL: https://github.com/nodejs/node/pull/30967
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
Anatoli Papirovski 2019-12-14 15:02:50 -05:00 committed by Rich Trott
parent 625a81dea3
commit 4de31d517f
4 changed files with 26 additions and 110 deletions

View File

@ -8,6 +8,7 @@ const {
const {
ERR_ASYNC_CALLBACK,
ERR_ASYNC_TYPE,
ERR_INVALID_ASYNC_ID
} = require('internal/errors').codes;
const { validateString } = require('internal/validators');
@ -31,6 +32,7 @@ const {
emitBefore,
emitAfter,
emitDestroy,
enabledHooksExist,
initHooksExist,
} = internal_async_hooks;
@ -157,6 +159,10 @@ class AsyncResource {
this[trigger_async_id_symbol] = triggerAsyncId;
if (initHooksExist()) {
if (enabledHooksExist() && type.length === 0) {
throw new ERR_ASYNC_TYPE(type);
}
emitInit(asyncId, type, triggerAsyncId, this);
}

View File

@ -3,16 +3,10 @@
const {
Error,
FunctionPrototypeBind,
NumberIsSafeInteger,
ObjectDefineProperty,
Symbol,
} = primordials;
const {
ERR_ASYNC_TYPE,
ERR_INVALID_ASYNC_ID
} = require('internal/errors').codes;
const async_wrap = internalBinding('async_wrap');
/* async_hook_fields is a Uint32Array wrapping the uint32_t array of
* Environment::AsyncHooks::fields_[]. Each index tracks the number of active
@ -117,15 +111,6 @@ function fatalError(e) {
}
function validateAsyncId(asyncId, type) {
// Skip validation when async_hooks is disabled
if (async_hook_fields[kCheck] <= 0) return;
if (!NumberIsSafeInteger(asyncId) || asyncId < -1) {
fatalError(new ERR_INVALID_ASYNC_ID(type, asyncId));
}
}
// Emit From Native //
// Used by C++ to call all init() callbacks. Because some state can be setup
@ -314,6 +299,9 @@ function defaultTriggerAsyncIdScope(triggerAsyncId, block, ...args) {
}
}
function enabledHooksExist() {
return async_hook_fields[kCheck] > 0;
}
function initHooksExist() {
return async_hook_fields[kInit] > 0;
@ -329,21 +317,11 @@ function destroyHooksExist() {
function emitInitScript(asyncId, type, triggerAsyncId, resource) {
validateAsyncId(asyncId, 'asyncId');
if (triggerAsyncId !== null)
validateAsyncId(triggerAsyncId, 'triggerAsyncId');
if (async_hook_fields[kCheck] > 0 &&
(typeof type !== 'string' || type.length <= 0)) {
throw new ERR_ASYNC_TYPE(type);
}
// Short circuit all checks for the common case. Which is that no hooks have
// been set. Do this to remove performance impact for embedders (and core).
if (async_hook_fields[kInit] === 0)
return;
// This can run after the early return check b/c running this function
// manually means that the embedder must have used getDefaultTriggerAsyncId().
if (triggerAsyncId === null) {
triggerAsyncId = getDefaultTriggerAsyncId();
}
@ -353,12 +331,6 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
function emitBeforeScript(asyncId, triggerAsyncId) {
// Validate the ids. An id of -1 means it was never set and is visible on the
// call graph. An id < -1 should never happen in any circumstance. Throw
// on user calls because async state should still be recoverable.
validateAsyncId(asyncId, 'asyncId');
validateAsyncId(triggerAsyncId, 'triggerAsyncId');
pushAsyncIds(asyncId, triggerAsyncId);
if (async_hook_fields[kBefore] > 0)
@ -367,8 +339,6 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
function emitAfterScript(asyncId) {
validateAsyncId(asyncId, 'asyncId');
if (async_hook_fields[kAfter] > 0)
emitAfterNative(asyncId);
@ -377,8 +347,6 @@ function emitAfterScript(asyncId) {
function emitDestroyScript(asyncId) {
validateAsyncId(asyncId, 'asyncId');
// Return early if there are no destroy callbacks, or invalid asyncId.
if (async_hook_fields[kDestroy] === 0 || asyncId <= 0)
return;
@ -418,8 +386,7 @@ function popAsyncIds(asyncId) {
const stackLength = async_hook_fields[kStackLength];
if (stackLength === 0) return false;
if (async_hook_fields[kCheck] > 0 &&
async_id_fields[kExecutionAsyncId] !== asyncId) {
if (enabledHooksExist() && async_id_fields[kExecutionAsyncId] !== asyncId) {
// Do the same thing as the native code (i.e. crash hard).
return popAsyncIds_(asyncId);
}
@ -464,6 +431,7 @@ module.exports = {
getOrSetAsyncId,
getDefaultTriggerAsyncId,
defaultTriggerAsyncIdScope,
enabledHooksExist,
initHooksExist,
afterHooksExist,
destroyHooksExist,

View File

@ -3,40 +3,9 @@
const common = require('../common');
const assert = require('assert');
const spawnSync = require('child_process').spawnSync;
const async_hooks = require('internal/async_hooks');
const initHooks = require('./init-hooks');
if (!common.isMainThread)
common.skip('Worker bootstrapping works differently -> different async IDs');
switch (process.argv[2]) {
case 'test_invalid_async_id':
async_hooks.emitBefore(-2, 1);
return;
case 'test_invalid_trigger_id':
async_hooks.emitBefore(1, -2);
return;
}
assert.ok(!process.argv[2]);
const c1 = spawnSync(process.execPath, [
'--expose-internals', __filename, 'test_invalid_async_id'
]);
assert.strictEqual(
c1.stderr.toString().split(/[\r\n]+/g)[0],
'RangeError [ERR_INVALID_ASYNC_ID]: Invalid asyncId value: -2');
assert.strictEqual(c1.status, 1);
const c2 = spawnSync(process.execPath, [
'--expose-internals', __filename, 'test_invalid_trigger_id'
]);
assert.strictEqual(
c2.stderr.toString().split(/[\r\n]+/g)[0],
'RangeError [ERR_INVALID_ASYNC_ID]: Invalid triggerAsyncId value: -2');
assert.strictEqual(c2.status, 1);
const expectedId = async_hooks.newAsyncId();
const expectedTriggerId = async_hooks.newAsyncId();
const expectedType = 'test_emit_before_after_type';
@ -45,9 +14,22 @@ const expectedType = 'test_emit_before_after_type';
async_hooks.emitBefore(expectedId, expectedTriggerId);
async_hooks.emitAfter(expectedId);
const chkBefore = common.mustCall((id) => assert.strictEqual(id, expectedId));
const chkAfter = common.mustCall((id) => assert.strictEqual(id, expectedId));
const checkOnce = (fn) => {
let called = false;
return (...args) => {
if (called) return;
called = true;
fn(...args);
};
};
initHooks({
onbefore: common.mustCall((id) => assert.strictEqual(id, expectedId)),
onafter: common.mustCall((id) => assert.strictEqual(id, expectedId)),
onbefore: checkOnce(chkBefore),
onafter: checkOnce(chkAfter),
allowNoInit: true
}).enable();

View File

@ -3,7 +3,6 @@
const common = require('../common');
const assert = require('assert');
const spawnSync = require('child_process').spawnSync;
const async_hooks = require('internal/async_hooks');
const initHooks = require('./init-hooks');
@ -23,45 +22,6 @@ const hooks1 = initHooks({
hooks1.enable();
switch (process.argv[2]) {
case 'test_invalid_async_id':
async_hooks.emitInit();
return;
case 'test_invalid_trigger_id':
async_hooks.emitInit(expectedId);
return;
case 'test_invalid_trigger_id_negative':
async_hooks.emitInit(expectedId, expectedType, -2);
return;
}
assert.ok(!process.argv[2]);
const c1 = spawnSync(process.execPath, [
'--expose-internals', __filename, 'test_invalid_async_id'
]);
assert.strictEqual(
c1.stderr.toString().split(/[\r\n]+/g)[0],
'RangeError [ERR_INVALID_ASYNC_ID]: Invalid asyncId value: undefined');
assert.strictEqual(c1.status, 1);
const c2 = spawnSync(process.execPath, [
'--expose-internals', __filename, 'test_invalid_trigger_id'
]);
assert.strictEqual(
c2.stderr.toString().split(/[\r\n]+/g)[0],
'RangeError [ERR_INVALID_ASYNC_ID]: Invalid triggerAsyncId value: undefined');
assert.strictEqual(c2.status, 1);
const c3 = spawnSync(process.execPath, [
'--expose-internals', __filename, 'test_invalid_trigger_id_negative'
]);
assert.strictEqual(
c3.stderr.toString().split(/[\r\n]+/g)[0],
'RangeError [ERR_INVALID_ASYNC_ID]: Invalid triggerAsyncId value: -2');
assert.strictEqual(c3.status, 1);
async_hooks.emitInit(expectedId, expectedType, expectedTriggerId,
expectedResource);