Skip to main content
Module

std/node/async_hooks.ts

Deno standard library
Go to Latest
File
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.// Copyright Joyent and Node contributors. All rights reserved. MIT license.
import { ERR_ASYNC_TYPE, ERR_INVALID_ASYNC_ID } from "./internal/errors.ts";import { validateFunction, validateString } from "./internal/validators.mjs";import { // deno-lint-ignore camelcase async_id_symbol, destroyHooksExist, emitInit, enabledHooksExist, getDefaultTriggerAsyncId, hasAsyncIdStack, initHooksExist, newAsyncId, registerDestroyHook, // deno-lint-ignore camelcase trigger_async_id_symbol,} from "./internal/async_hooks.ts";
const destroyedSymbol = Symbol("destroyed");
type AsyncResourceOptions = number | { triggerAsyncId?: number; requireManualDestroy?: boolean;};
export class AsyncResource { [async_id_symbol]: number; [trigger_async_id_symbol]: number; [destroyedSymbol]!: { destroyed: boolean };
constructor(type: string, opts: AsyncResourceOptions = {}) { validateString(type, "type");
let triggerAsyncId: number; let requireManualDestroy = false; if (typeof opts !== "number") { triggerAsyncId = opts.triggerAsyncId === undefined ? getDefaultTriggerAsyncId() : opts.triggerAsyncId; requireManualDestroy = !!opts.requireManualDestroy; } else { triggerAsyncId = opts; }
// Unlike emitInitScript, AsyncResource doesn't supports null as the // triggerAsyncId. if (!Number.isSafeInteger(triggerAsyncId) || triggerAsyncId < -1) { throw new ERR_INVALID_ASYNC_ID("triggerAsyncId", triggerAsyncId); }
const asyncId = newAsyncId(); this[async_id_symbol] = asyncId; this[trigger_async_id_symbol] = triggerAsyncId;
if (initHooksExist()) { if (enabledHooksExist() && type.length === 0) { throw new ERR_ASYNC_TYPE(type); }
emitInit(asyncId, type, triggerAsyncId, this); }
if (!requireManualDestroy && destroyHooksExist()) { // This prop name (destroyed) has to be synchronized with C++ const destroyed = { destroyed: false }; this[destroyedSymbol] = destroyed; registerDestroyHook(this, asyncId, destroyed); } }
runInAsyncScope( fn: (...args: unknown[]) => unknown, thisArg: unknown, ...args: unknown[] ) { // deno-lint-ignore no-unused-vars const asyncId = this[async_id_symbol]; // TODO(kt3k): Uncomment the below // emitBefore(asyncId, this[trigger_async_id_symbol], this);
try { const ret = Reflect.apply(fn, thisArg, args);
return ret; } finally { if (hasAsyncIdStack()) { // TODO(kt3k): Uncomment the below // emitAfter(asyncId); } } }
emitDestroy() { if (this[destroyedSymbol] !== undefined) { this[destroyedSymbol].destroyed = true; } // TODO(kt3k): Uncomment the below // emitDestroy(this[async_id_symbol]); return this; }
asyncId() { return this[async_id_symbol]; }
triggerAsyncId() { return this[trigger_async_id_symbol]; }
bind(fn: (...args: unknown[]) => unknown, thisArg = this) { validateFunction(fn, "fn"); const ret = this.runInAsyncScope.bind( this, fn, thisArg, ); Object.defineProperties(ret, { "length": { configurable: true, enumerable: false, value: fn.length, writable: false, }, "asyncResource": { configurable: true, enumerable: true, value: this, writable: true, }, }); return ret; }
static bind( fn: (...args: unknown[]) => unknown, type: string | undefined, thisArg: AsyncResource | undefined, ) { type = type || fn.name; return (new AsyncResource(type || "bound-anonymous-fn")).bind(fn, thisArg); }}
function executionAsyncId() { return 1;}
class AsyncHook { enable() { }
disable() { }}
function createHook() { return new AsyncHook();}
// Placing all exports down here because the exported classes won't export// otherwise.export default { // Embedder API AsyncResource, executionAsyncId, createHook,};