1import { assert, describe, it } from "@effect/vitest"
2import { Effect, References } from "effect"
3
4const withCaptureDisabled = <A>(run: () => A): A => {
5 const limit = Error.stackTraceLimit
6 Error.stackTraceLimit = 0
7 try {
8 return run()
9 } finally {
10 Error.stackTraceLimit = limit
11 }
12}
13
14// Even an empty stack costs a capture in workerd, so count Error allocations.
15const countErrors = (run: () => void): number => {
16 const original = globalThis.Error
17 let count = 0
18 globalThis.Error = new Proxy(original, {
19 construct(target, args, newTarget) {
20 count++
21 return Reflect.construct(target, args, newTarget)
22 }
23 })
24 try {
25 run()
26 return count
27 } finally {
28 globalThis.Error = original
29 }
30}
31
32describe("stack capture", { concurrent: false }, () => {
33 it("Effect.fn skips definition capture at limit zero", () => {
34 const count = withCaptureDisabled(() => countErrors(() => Effect.fn("test")(() => Effect.void)))
35 assert.strictEqual(count, 0)
36 })
37
38 it("Effect.fn skips invocation capture at limit zero", () => {
39 const fn = Effect.fn("test")(() => Effect.void)
40 const count = withCaptureDisabled(() => countErrors(() => Effect.runSync(fn())))
41 assert.strictEqual(count, 0)
42 })
43
44 it("default spans skip capture at limit zero", () => {
45 const count = withCaptureDisabled(() => countErrors(() => Effect.runSync(Effect.withSpan(Effect.void, "test"))))
46 assert.strictEqual(count, 0)
47 })
48
49 it("explicit span capture works at limit zero", () => {
50 const frame = withCaptureDisabled(() => {
51 const frame = Effect.runSync(Effect.withSpan(References.CurrentStackFrame, "test", { captureStackTrace: true }))
52 assert.strictEqual(Error.stackTraceLimit, 0)
53 return frame
54 })
55 assert.match(frame!.stack()!, /StackCapture\.test\.ts:\d+:\d+/)
56 })
57})