|
@ -49,15 +49,18 @@ const init_symbol = Symbol('init'); |
|
|
const before_symbol = Symbol('before'); |
|
|
const before_symbol = Symbol('before'); |
|
|
const after_symbol = Symbol('after'); |
|
|
const after_symbol = Symbol('after'); |
|
|
const destroy_symbol = Symbol('destroy'); |
|
|
const destroy_symbol = Symbol('destroy'); |
|
|
|
|
|
const emitBeforeNative = emitHookFactory(before_symbol, 'emitBeforeNative'); |
|
|
|
|
|
const emitAfterNative = emitHookFactory(after_symbol, 'emitAfterNative'); |
|
|
|
|
|
const emitDestroyNative = emitHookFactory(destroy_symbol, 'emitDestroyNative'); |
|
|
|
|
|
|
|
|
// Setup the callbacks that node::AsyncWrap will call when there are hooks to
|
|
|
// Setup the callbacks that node::AsyncWrap will call when there are hooks to
|
|
|
// process. They use the same functions as the JS embedder API. These callbacks
|
|
|
// process. They use the same functions as the JS embedder API. These callbacks
|
|
|
// are setup immediately to prevent async_wrap.setupHooks() from being hijacked
|
|
|
// are setup immediately to prevent async_wrap.setupHooks() from being hijacked
|
|
|
// and the cost of doing so is negligible.
|
|
|
// and the cost of doing so is negligible.
|
|
|
async_wrap.setupHooks({ init, |
|
|
async_wrap.setupHooks({ init, |
|
|
before: emitBeforeN, |
|
|
before: emitBeforeNative, |
|
|
after: emitAfterN, |
|
|
after: emitAfterNative, |
|
|
destroy: emitDestroyN }); |
|
|
destroy: emitDestroyNative }); |
|
|
|
|
|
|
|
|
// Used to fatally abort the process if a callback throws.
|
|
|
// Used to fatally abort the process if a callback throws.
|
|
|
function fatalError(e) { |
|
|
function fatalError(e) { |
|
@ -325,8 +328,8 @@ function emitInitS(asyncId, type, triggerAsyncId, resource) { |
|
|
triggerAsyncId = initTriggerId(); |
|
|
triggerAsyncId = initTriggerId(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// I'd prefer allowing these checks to not exist, or only throw in a debug
|
|
|
// TODO(trevnorris): I'd prefer allowing these checks to not exist, or only
|
|
|
// build, in order to improve performance.
|
|
|
// throw in a debug build, in order to improve performance.
|
|
|
if (!Number.isSafeInteger(asyncId) || asyncId < 0) |
|
|
if (!Number.isSafeInteger(asyncId) || asyncId < 0) |
|
|
throw new RangeError('asyncId must be an unsigned integer'); |
|
|
throw new RangeError('asyncId must be an unsigned integer'); |
|
|
if (typeof type !== 'string' || type.length <= 0) |
|
|
if (typeof type !== 'string' || type.length <= 0) |
|
@ -342,24 +345,35 @@ function emitInitS(asyncId, type, triggerAsyncId, resource) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function emitHookFactory(symbol, name) { |
|
|
function emitBeforeN(asyncId) { |
|
|
// Called from native. The asyncId stack handling is taken care of there
|
|
|
processing_hook = true; |
|
|
// before this is called.
|
|
|
// Use a single try/catch for all hook to avoid setting up one per iteration.
|
|
|
// eslint-disable-next-line func-style
|
|
|
try { |
|
|
const fn = function(asyncId) { |
|
|
for (var i = 0; i < active_hooks_array.length; i++) { |
|
|
processing_hook = true; |
|
|
if (typeof active_hooks_array[i][before_symbol] === 'function') { |
|
|
// Use a single try/catch for all hook to avoid setting up one per
|
|
|
active_hooks_array[i][before_symbol](asyncId); |
|
|
// iteration.
|
|
|
|
|
|
try { |
|
|
|
|
|
for (var i = 0; i < active_hooks_array.length; i++) { |
|
|
|
|
|
if (typeof active_hooks_array[i][symbol] === 'function') { |
|
|
|
|
|
active_hooks_array[i][symbol](asyncId); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
fatalError(e); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
processing_hook = false; |
|
|
fatalError(e); |
|
|
|
|
|
} |
|
|
|
|
|
processing_hook = false; |
|
|
|
|
|
|
|
|
|
|
|
if (tmp_active_hooks_array !== null) { |
|
|
if (tmp_active_hooks_array !== null) { |
|
|
restoreTmpHooks(); |
|
|
restoreTmpHooks(); |
|
|
} |
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
// Set the name property of the anonymous function as it looks good in the
|
|
|
|
|
|
// stack trace.
|
|
|
|
|
|
Object.defineProperty(fn, 'name', { |
|
|
|
|
|
value: name |
|
|
|
|
|
}); |
|
|
|
|
|
return fn; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -379,29 +393,7 @@ function emitBeforeS(asyncId, triggerAsyncId = asyncId) { |
|
|
|
|
|
|
|
|
if (async_hook_fields[kBefore] === 0) |
|
|
if (async_hook_fields[kBefore] === 0) |
|
|
return; |
|
|
return; |
|
|
emitBeforeN(asyncId); |
|
|
emitBeforeNative(asyncId); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Called from native. The asyncId stack handling is taken care of there before
|
|
|
|
|
|
// this is called.
|
|
|
|
|
|
function emitAfterN(asyncId) { |
|
|
|
|
|
processing_hook = true; |
|
|
|
|
|
// Use a single try/catch for all hook to avoid setting up one per iteration.
|
|
|
|
|
|
try { |
|
|
|
|
|
for (var i = 0; i < active_hooks_array.length; i++) { |
|
|
|
|
|
if (typeof active_hooks_array[i][after_symbol] === 'function') { |
|
|
|
|
|
active_hooks_array[i][after_symbol](asyncId); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
fatalError(e); |
|
|
|
|
|
} |
|
|
|
|
|
processing_hook = false; |
|
|
|
|
|
|
|
|
|
|
|
if (tmp_active_hooks_array !== null) { |
|
|
|
|
|
restoreTmpHooks(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -410,7 +402,7 @@ function emitAfterN(asyncId) { |
|
|
// after callbacks.
|
|
|
// after callbacks.
|
|
|
function emitAfterS(asyncId) { |
|
|
function emitAfterS(asyncId) { |
|
|
if (async_hook_fields[kAfter] > 0) |
|
|
if (async_hook_fields[kAfter] > 0) |
|
|
emitAfterN(asyncId); |
|
|
emitAfterNative(asyncId); |
|
|
|
|
|
|
|
|
popAsyncIds(asyncId); |
|
|
popAsyncIds(asyncId); |
|
|
} |
|
|
} |
|
@ -425,26 +417,6 @@ function emitDestroyS(asyncId) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function emitDestroyN(asyncId) { |
|
|
|
|
|
processing_hook = true; |
|
|
|
|
|
// Use a single try/catch for all hook to avoid setting up one per iteration.
|
|
|
|
|
|
try { |
|
|
|
|
|
for (var i = 0; i < active_hooks_array.length; i++) { |
|
|
|
|
|
if (typeof active_hooks_array[i][destroy_symbol] === 'function') { |
|
|
|
|
|
active_hooks_array[i][destroy_symbol](asyncId); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
fatalError(e); |
|
|
|
|
|
} |
|
|
|
|
|
processing_hook = false; |
|
|
|
|
|
|
|
|
|
|
|
if (tmp_active_hooks_array !== null) { |
|
|
|
|
|
restoreTmpHooks(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Emit callbacks for native calls. Since some state can be setup directly from
|
|
|
// Emit callbacks for native calls. Since some state can be setup directly from
|
|
|
// C++ there's no need to perform all the work here.
|
|
|
// C++ there's no need to perform all the work here.
|
|
|
|
|
|
|
|
|