summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/01_core.js23
-rw-r--r--core/lib.deno_core.d.ts23
2 files changed, 45 insertions, 1 deletions
diff --git a/core/01_core.js b/core/01_core.js
index d9a110eea..3a05a0cff 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -22,6 +22,8 @@
MapPrototypeDelete,
MapPrototypeSet,
PromisePrototypeThen,
+ PromisePrototypeFinally,
+ StringPrototypeSlice,
ObjectAssign,
SymbolFor,
} = window.__bootstrap.primordials;
@@ -48,6 +50,13 @@
// to users. Currently missing bindings.
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
+ let opCallTracingEnabled = false;
+ const opCallTraces = new Map();
+
+ function enableOpCallTracing() {
+ opCallTracingEnabled = true;
+ }
+
function setPromise(promiseId) {
const idx = promiseId % RING_SIZE;
// Move old promise from ring to map
@@ -139,7 +148,17 @@
const maybeError = opcallAsync(opsCache[opName], promiseId, arg1, arg2);
// Handle sync error (e.g: error parsing args)
if (maybeError) return unwrapOpResult(maybeError);
- const p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult);
+ let p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult);
+ if (opCallTracingEnabled) {
+ // Capture a stack trace by creating a new `Error` object. We remove the
+ // first 6 characters (the `Error\n` prefix) to get just the stack trace.
+ const stack = StringPrototypeSlice(new Error().stack, 6);
+ MapPrototypeSet(opCallTraces, promiseId, { opName, stack });
+ p = PromisePrototypeFinally(
+ p,
+ () => MapPrototypeDelete(opCallTraces, promiseId),
+ );
+ }
// Save the id on the promise so it can later be ref'ed or unref'ed
p[promiseIdSymbol] = promiseId;
return p;
@@ -226,6 +245,8 @@
BadResourcePrototype,
Interrupted,
InterruptedPrototype,
+ enableOpCallTracing,
+ opCallTraces,
});
ObjectAssign(globalThis.__bootstrap, { core });
diff --git a/core/lib.deno_core.d.ts b/core/lib.deno_core.d.ts
index 9f554f12b..37cd33190 100644
--- a/core/lib.deno_core.d.ts
+++ b/core/lib.deno_core.d.ts
@@ -141,5 +141,28 @@ declare namespace Deno {
): undefined | UncaughtExceptionCallback;
export type UncaughtExceptionCallback = (err: any) => void;
+
+ /**
+ * Enables collection of stack traces of all async ops. This allows for
+ * debugging of where a given async op was started. Deno CLI uses this for
+ * improving error message in op sanitizer errors for `deno test`.
+ *
+ * **NOTE:** enabling tracing has a significant negative performance impact.
+ * To get high level metrics on async ops with no added performance cost,
+ * use `Deno.core.metrics()`.
+ */
+ function enableOpCallTracing(): void;
+
+ export interface OpCallTrace {
+ opName: string;
+ stack: string;
+ }
+
+ /**
+ * A map containing traces for all ongoing async ops. The key is the op id.
+ * Tracing only occurs when `Deno.core.enableOpCallTracing()` was previously
+ * enabled.
+ */
+ const opCallTraces: Map<number, OpCallTrace>;
}
}