diff options
Diffstat (limited to 'js/trace.ts')
-rw-r--r-- | js/trace.ts | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/js/trace.ts b/js/trace.ts new file mode 100644 index 000000000..42a9fe015 --- /dev/null +++ b/js/trace.ts @@ -0,0 +1,80 @@ +// Copyright 2018 the Deno authors. All rights reserved. MIT license. +import * as fbs from "gen/msg_generated"; + +export interface TraceInfo { + sync: boolean; // is synchronous call + name: string; // name of operation +} + +interface TraceStackNode { + list: TraceInfo[]; + prev: TraceStackNode | null; +} + +let current: TraceStackNode | null = null; + +// Push a new list to trace stack +function pushStack(): void { + if (current === null) { + current = { list: [], prev: null }; + } else { + const newStack = { list: [], prev: current }; + current = newStack; + } +} + +// Pop from trace stack and (if possible) concat to parent trace stack node +function popStack(): TraceInfo[] { + if (current === null) { + throw new Error("trace list stack should not be empty"); + } + const resultList = current!.list; + if (!!current!.prev) { + const prev = current!.prev!; + // concat inner results to outer stack + prev.list = prev.list.concat(resultList); + current = prev; + } else { + current = null; + } + return resultList; +} + +// Push to trace stack if we are tracing +export function maybePushTrace(op: fbs.Any, sync: boolean): void { + if (current === null) { + return; // no trace requested + } + // Freeze the object, avoid tampering + current!.list.push( + Object.freeze({ + sync, + name: fbs.Any[op] // convert to enum names + }) + ); +} + +/** + * Trace operations executed inside a given function or promise. + * Notice: To capture every operation in asynchronous deno.* calls, + * you might want to put them in functions instead of directly invoking. + * + * import { trace, mkdir } from "deno"; + * + * const ops = await trace(async () => { + * await mkdir("my_dir"); + * }); + * // ops becomes [{ sync: false, name: "Mkdir" }] + */ +export async function trace( + // tslint:disable-next-line:no-any + fnOrPromise: Function | Promise<any> +): Promise<TraceInfo[]> { + pushStack(); + if (typeof fnOrPromise === "function") { + await fnOrPromise(); + } else { + await fnOrPromise; + } + return popStack(); +} |