@@ -10,6 +10,7 @@ import type {
10
10
APISimStartParams ,
11
11
PinReadResponse ,
12
12
} from './APITypes.js' ;
13
+ import { PausePoint , type PausePointParams } from './PausePoint.js' ;
13
14
import { readVersion } from './readVersion.js' ;
14
15
15
16
const DEFAULT_SERVER = process . env . WOKWI_CLI_SERVER ?? 'wss://wokwi.com/api/ws/beta' ;
@@ -19,10 +20,12 @@ export class APIClient {
19
20
private socket : WebSocket ;
20
21
private connectionAttempts = 0 ;
21
22
private lastId = 0 ;
23
+ private lastPausePointId = 0 ;
22
24
private closed = false ;
23
25
private _running = false ;
24
26
private _lastNanos = 0 ;
25
27
private readonly apiEvents = new EventTarget ( ) ;
28
+ private readonly pausePoints = new Map < string , PausePoint > ( ) ;
26
29
private readonly pendingCommands = new Map <
27
30
string ,
28
31
[ ( result : any ) => void , ( error : Error ) => void ]
@@ -139,9 +142,9 @@ export class APIClient {
139
142
return await this . sendCommand ( 'sim:pause' ) ;
140
143
}
141
144
142
- async simResume ( pauseAfter ?: number , { waitForBytes } : { waitForBytes ?: number [ ] } = { } ) {
145
+ async simResume ( pauseAfter ?: number ) {
143
146
this . _running = true ;
144
- return await this . sendCommand ( 'sim:resume' , { pauseAfter, waitForBytes } ) ;
147
+ return await this . sendCommand ( 'sim:resume' , { pauseAfter } ) ;
145
148
}
146
149
147
150
async simRestart ( { pause } : { pause ?: boolean } = { } ) {
@@ -162,6 +165,15 @@ export class APIClient {
162
165
} ) ;
163
166
}
164
167
168
+ get pausedPromise ( ) {
169
+ if ( ! this . _running ) {
170
+ return Promise . resolve ( ) ;
171
+ }
172
+ return new Promise < APIEvent < any > > ( ( resolve ) => {
173
+ this . listen ( 'sim:pause' , resolve , { once : true } ) ;
174
+ } ) ;
175
+ }
176
+
165
177
serialMonitorWritable ( ) {
166
178
return new Writable ( {
167
179
write : ( chunk , encoding , callback ) => {
@@ -196,6 +208,46 @@ export class APIClient {
196
208
} ) ;
197
209
}
198
210
211
+ async addPausePoint ( params : PausePointParams , resume = false ) {
212
+ const id = `pp${ this . lastPausePointId ++ } _${ params . type } ` ;
213
+ const commands = [ this . sendCommand ( 'pause-point:add' , { id, ...params } ) ] ;
214
+ if ( resume && ! this . _running ) {
215
+ commands . push ( this . simResume ( ) ) ;
216
+ this . _running = true ;
217
+ }
218
+ await Promise . all ( commands ) ;
219
+ const pausePoint = new PausePoint ( id , params ) ;
220
+ this . pausePoints . set ( id , pausePoint ) ;
221
+ return pausePoint ;
222
+ }
223
+
224
+ async removePausePoint ( pausePoint : PausePoint ) {
225
+ if ( this . pausePoints . has ( pausePoint . id ) ) {
226
+ this . pausePoints . delete ( pausePoint . id ) ;
227
+ await this . sendCommand ( 'pause-point:remove' , { id : pausePoint . id } ) ;
228
+ return true ;
229
+ }
230
+ return false ;
231
+ }
232
+
233
+ async atNanos ( nanos : number ) {
234
+ const pausePoint = await this . addPausePoint ( { type : 'time-absolute' , nanos } ) ;
235
+ await pausePoint . promise ;
236
+ }
237
+
238
+ async delay ( nanos : number ) {
239
+ const pausePoint = await this . addPausePoint ( { type : 'time-relative' , nanos } , true ) ;
240
+ await pausePoint . promise ;
241
+ }
242
+
243
+ async waitForSerialBytes ( bytes : number [ ] | Uint8Array ) {
244
+ if ( bytes instanceof Uint8Array ) {
245
+ bytes = Array . from ( bytes ) ;
246
+ }
247
+ const pausePoint = await this . addPausePoint ( { type : 'serial-bytes' , bytes } , true ) ;
248
+ await pausePoint . promise ;
249
+ }
250
+
199
251
async sendCommand < T = unknown > ( command : string , params ?: any ) {
200
252
return await new Promise < T > ( ( resolve , reject ) => {
201
253
const id = this . lastId ++ ;
@@ -251,6 +303,12 @@ export class APIClient {
251
303
processEvent ( message : APIEvent ) {
252
304
if ( message . event === 'sim:pause' ) {
253
305
this . _running = false ;
306
+ const pausePointId : string = message . payload . pausePoint ;
307
+ const pausePoint = this . pausePoints . get ( pausePointId ) ;
308
+ if ( pausePoint ) {
309
+ pausePoint . resolve ( message . payload . pausePointInfo ) ;
310
+ this . pausePoints . delete ( pausePointId ) ;
311
+ }
254
312
}
255
313
this . _lastNanos = message . nanos ;
256
314
this . apiEvents . dispatchEvent ( new CustomEvent < APIEvent > ( message . event , { detail : message } ) ) ;
0 commit comments