@@ -38,13 +38,11 @@ interface MergeSnapshot<Snapshot> {
38
38
) : void ;
39
39
}
40
40
41
- export interface ProfiledComponentOnlyFields < Snapshot > {
41
+ export interface RenderStream < Snapshot extends ValidSnapshot > {
42
42
// Allows for partial updating of the snapshot by shallow merging the results
43
43
mergeSnapshot : MergeSnapshot < Snapshot > ;
44
44
// Performs a full replacement of the snapshot
45
45
replaceSnapshot : ReplaceSnapshot < Snapshot > ;
46
- }
47
- export interface ProfiledComponentFields < Snapshot > {
48
46
/**
49
47
* An array of all renders that have happened so far.
50
48
* Errors thrown during component render will be captured here, too.
@@ -81,10 +79,6 @@ export interface ProfiledComponentFields<Snapshot> {
81
79
waitForNextRender ( options ?: NextRenderOptions ) : Promise < Render < Snapshot > > ;
82
80
}
83
81
84
- export interface RenderStream < Snapshot extends ValidSnapshot >
85
- extends ProfiledComponentFields < Snapshot > ,
86
- ProfiledComponentOnlyFields < Snapshot > { }
87
-
88
82
export interface RenderStreamWithRenderFn < Snapshot extends ValidSnapshot >
89
83
extends RenderStream < Snapshot > {
90
84
render : typeof baseRender ;
@@ -172,7 +166,7 @@ export function createRenderStream<Snapshot extends ValidSnapshot = void>({
172
166
baseDuration,
173
167
startTime,
174
168
commitTime,
175
- count : Profiler . renders . length + 1 ,
169
+ count : stream . renders . length + 1 ,
176
170
} ;
177
171
try {
178
172
/*
@@ -200,12 +194,12 @@ export function createRenderStream<Snapshot extends ValidSnapshot = void>({
200
194
profilerContext . renderedComponents
201
195
) ;
202
196
profilerContext . renderedComponents = [ ] ;
203
- Profiler . renders . push ( render ) ;
197
+ stream . renders . push ( render ) ;
204
198
resolveNextRender ?.( render ) ;
205
199
} catch ( error ) {
206
- Profiler . renders . push ( {
200
+ stream . renders . push ( {
207
201
phase : "snapshotError" ,
208
- count : Profiler . renders . length ,
202
+ count : stream . renders . length ,
209
203
error,
210
204
} ) ;
211
205
rejectNextRender ?.( error ) ;
@@ -245,110 +239,106 @@ export function createRenderStream<Snapshot extends ValidSnapshot = void>({
245
239
} ) ;
246
240
} ) as typeof baseRender ;
247
241
248
- let Profiler : RenderStreamWithRenderFn < Snapshot > = { } as any ;
249
- Profiler = Object . assign (
250
- Profiler as { } ,
251
- {
252
- replaceSnapshot,
253
- mergeSnapshot,
254
- } satisfies ProfiledComponentOnlyFields < Snapshot > ,
255
- {
256
- renders : new Array <
257
- | Render < Snapshot >
258
- | { phase : "snapshotError" ; count : number ; error : unknown }
259
- > ( ) ,
260
- totalRenderCount ( ) {
261
- return Profiler . renders . length ;
262
- } ,
263
- async peekRender ( options : NextRenderOptions = { } ) {
264
- if ( iteratorPosition < Profiler . renders . length ) {
265
- const render = Profiler . renders [ iteratorPosition ] ;
266
-
267
- if ( render . phase === "snapshotError" ) {
268
- throw render . error ;
269
- }
242
+ // creating the object first and then assigning in all the properties
243
+ // allows keeping the object instance for reference while the members are
244
+ // created, which is important for the `markAssertable` function
245
+ let stream : RenderStreamWithRenderFn < Snapshot > = { } as any ;
246
+ Object . assign < typeof stream , typeof stream > ( stream , {
247
+ replaceSnapshot,
248
+ mergeSnapshot,
249
+ renders : new Array <
250
+ | Render < Snapshot >
251
+ | { phase : "snapshotError" ; count : number ; error : unknown }
252
+ > ( ) ,
253
+ totalRenderCount ( ) {
254
+ return stream . renders . length ;
255
+ } ,
256
+ async peekRender ( options : NextRenderOptions = { } ) {
257
+ if ( iteratorPosition < stream . renders . length ) {
258
+ const render = stream . renders [ iteratorPosition ] ;
270
259
271
- return render ;
260
+ if ( render . phase === "snapshotError" ) {
261
+ throw render . error ;
272
262
}
273
- return Profiler . waitForNextRender ( {
274
- [ _stackTrace ] : captureStackTrace ( Profiler . peekRender ) ,
263
+
264
+ return render ;
265
+ }
266
+ return stream . waitForNextRender ( {
267
+ [ _stackTrace ] : captureStackTrace ( stream . peekRender ) ,
268
+ ...options ,
269
+ } ) ;
270
+ } ,
271
+ takeRender : markAssertable ( async function takeRender (
272
+ options : NextRenderOptions = { }
273
+ ) {
274
+ // In many cases we do not control the resolution of the suspended
275
+ // promise which results in noisy tests when the profiler due to
276
+ // repeated act warnings.
277
+ using _disabledActWarnings = disableActWarnings ( ) ;
278
+
279
+ let error : unknown = undefined ;
280
+
281
+ try {
282
+ return await stream . peekRender ( {
283
+ [ _stackTrace ] : captureStackTrace ( stream . takeRender ) ,
275
284
...options ,
276
285
} ) ;
277
- } ,
278
- takeRender : markAssertable ( async function takeRender (
279
- options : NextRenderOptions = { }
280
- ) {
281
- // In many cases we do not control the resolution of the suspended
282
- // promise which results in noisy tests when the profiler due to
283
- // repeated act warnings.
284
- using _disabledActWarnings = disableActWarnings ( ) ;
285
-
286
- let error : unknown = undefined ;
287
-
288
- try {
289
- return await Profiler . peekRender ( {
290
- [ _stackTrace ] : captureStackTrace ( Profiler . takeRender ) ,
291
- ...options ,
292
- } ) ;
293
- } catch ( e ) {
294
- error = e ;
295
- throw e ;
296
- } finally {
297
- if ( ! ( error && error instanceof WaitForRenderTimeoutError ) ) {
298
- iteratorPosition ++ ;
299
- }
300
- }
301
- } , Profiler ) ,
302
- getCurrentRender ( ) {
303
- // The "current" render should point at the same render that the most
304
- // recent `takeRender` call returned, so we need to get the "previous"
305
- // iterator position, otherwise `takeRender` advances the iterator
306
- // to the next render. This means we need to call `takeRender` at least
307
- // once before we can get a current render.
308
- const currentPosition = iteratorPosition - 1 ;
309
-
310
- if ( currentPosition < 0 ) {
311
- throw new Error (
312
- "No current render available. You need to call `takeRender` before you can get the current render."
313
- ) ;
286
+ } catch ( e ) {
287
+ error = e ;
288
+ throw e ;
289
+ } finally {
290
+ if ( ! ( error && error instanceof WaitForRenderTimeoutError ) ) {
291
+ iteratorPosition ++ ;
314
292
}
293
+ }
294
+ } , stream ) ,
295
+ getCurrentRender ( ) {
296
+ // The "current" render should point at the same render that the most
297
+ // recent `takeRender` call returned, so we need to get the "previous"
298
+ // iterator position, otherwise `takeRender` advances the iterator
299
+ // to the next render. This means we need to call `takeRender` at least
300
+ // once before we can get a current render.
301
+ const currentPosition = iteratorPosition - 1 ;
302
+
303
+ if ( currentPosition < 0 ) {
304
+ throw new Error (
305
+ "No current render available. You need to call `takeRender` before you can get the current render."
306
+ ) ;
307
+ }
315
308
316
- const render = Profiler . renders [ currentPosition ] ;
309
+ const render = stream . renders [ currentPosition ] ;
317
310
318
- if ( render . phase === "snapshotError" ) {
319
- throw render . error ;
320
- }
321
- return render ;
322
- } ,
323
- waitForNextRender ( {
324
- timeout = 1000 ,
325
- // capture the stack trace here so its stack trace is as close to the calling code as possible
326
- [ _stackTrace ] : stackTrace = captureStackTrace (
327
- Profiler . waitForNextRender
328
- ) ,
329
- } : NextRenderOptions = { } ) {
330
- if ( ! nextRender ) {
331
- nextRender = Promise . race < Render < Snapshot > > ( [
332
- new Promise < Render < Snapshot > > ( ( resolve , reject ) => {
333
- resolveNextRender = resolve ;
334
- rejectNextRender = reject ;
335
- } ) ,
336
- new Promise < Render < Snapshot > > ( ( _ , reject ) =>
337
- setTimeout ( ( ) => {
338
- reject (
339
- applyStackTrace ( new WaitForRenderTimeoutError ( ) , stackTrace )
340
- ) ;
341
- resetNextRender ( ) ;
342
- } , timeout )
343
- ) ,
344
- ] ) ;
345
- }
346
- return nextRender ;
347
- } ,
348
- } satisfies ProfiledComponentFields < Snapshot > ,
349
- { render }
350
- ) ;
351
- return Profiler ;
311
+ if ( render . phase === "snapshotError" ) {
312
+ throw render . error ;
313
+ }
314
+ return render ;
315
+ } ,
316
+ waitForNextRender ( {
317
+ timeout = 1000 ,
318
+ // capture the stack trace here so its stack trace is as close to the calling code as possible
319
+ [ _stackTrace ] : stackTrace = captureStackTrace ( stream . waitForNextRender ) ,
320
+ } : NextRenderOptions = { } ) {
321
+ if ( ! nextRender ) {
322
+ nextRender = Promise . race < Render < Snapshot > > ( [
323
+ new Promise < Render < Snapshot > > ( ( resolve , reject ) => {
324
+ resolveNextRender = resolve ;
325
+ rejectNextRender = reject ;
326
+ } ) ,
327
+ new Promise < Render < Snapshot > > ( ( _ , reject ) =>
328
+ setTimeout ( ( ) => {
329
+ reject (
330
+ applyStackTrace ( new WaitForRenderTimeoutError ( ) , stackTrace )
331
+ ) ;
332
+ resetNextRender ( ) ;
333
+ } , timeout )
334
+ ) ,
335
+ ] ) ;
336
+ }
337
+ return nextRender ;
338
+ } ,
339
+ render,
340
+ } ) ;
341
+ return stream ;
352
342
}
353
343
354
344
export class WaitForRenderTimeoutError extends Error {
0 commit comments