1- import type { Executor , ExecuteResult , SandboxOptions } from "../types.js" ;
1+ import type { Executor , ExecuteResult , ExecuteStats , SandboxOptions } from "../types.js" ;
22
33/**
44 * Executor implementation using isolated-vm (V8 isolates).
@@ -123,11 +123,14 @@ export class IsolatedVMExecutor implements Executor {
123123 } ) ,
124124 ] ) ;
125125
126- return { result } ;
126+ const stats = captureStats ( isolate ) ;
127+ return { result, stats } ;
127128 } catch ( err ) {
129+ const stats = captureStats ( isolate ) ;
128130 return {
129131 result : undefined ,
130132 error : err instanceof Error ? err . message : String ( err ) ,
133+ stats,
131134 } ;
132135 } finally {
133136 context ?. release ( ) ;
@@ -138,6 +141,42 @@ export class IsolatedVMExecutor implements Executor {
138141 }
139142}
140143
144+ /**
145+ * Capture execution stats from an isolate before it is disposed.
146+ * Safe to call even if the isolate is already disposed (returns zeroed stats).
147+ */
148+ function captureStats ( isolate : { isDisposed : boolean ; cpuTime : bigint ; wallTime : bigint ; getHeapStatisticsSync ( ) : Record < string , number > } ) : ExecuteStats {
149+ if ( isolate . isDisposed ) {
150+ return {
151+ cpuTimeMs : 0 ,
152+ wallTimeMs : 0 ,
153+ heapUsedBytes : 0 ,
154+ heapTotalBytes : 0 ,
155+ externalBytes : 0 ,
156+ heapSizeLimitBytes : 0 ,
157+ totalPhysicalBytes : 0 ,
158+ availableBytes : 0 ,
159+ executableBytes : 0 ,
160+ mallocedBytes : 0 ,
161+ peakMallocedBytes : 0 ,
162+ } ;
163+ }
164+ const heap = isolate . getHeapStatisticsSync ( ) ;
165+ return {
166+ cpuTimeMs : Number ( isolate . cpuTime ) / 1e6 ,
167+ wallTimeMs : Number ( isolate . wallTime ) / 1e6 ,
168+ heapUsedBytes : heap . used_heap_size ?? 0 ,
169+ heapTotalBytes : heap . total_heap_size ?? 0 ,
170+ externalBytes : heap . externally_allocated_size ?? 0 ,
171+ heapSizeLimitBytes : heap . heap_size_limit ?? 0 ,
172+ totalPhysicalBytes : heap . total_physical_size ?? 0 ,
173+ availableBytes : heap . total_available_size ?? 0 ,
174+ executableBytes : heap . total_heap_size_executable ?? 0 ,
175+ mallocedBytes : heap . malloced_memory ?? 0 ,
176+ peakMallocedBytes : heap . peak_malloced_memory ?? 0 ,
177+ } ;
178+ }
179+
141180function isNamespaceWithMethods ( value : unknown ) : boolean {
142181 return (
143182 typeof value === "object" &&
0 commit comments