@flex-development/when 1.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,44 +17,94 @@ like `.then`, but for synchronous values *and* thenables.
17
17
  ## Contents
18
18
 
19
19
  - [What is this?](#what-is-this)
20
+ - [When should I use this?](#when-should-i-use-this)
20
21
  - [Why not `Promise.resolve`?](#why-not-promiseresolve)
22
+ - [Design guarantees](#design-guarantees)
21
23
  - [Install](#install)
22
24
  - [Use](#use)
23
25
  - [Chain a synchronous value](#chain-a-synchronous-value)
24
26
  - [Chain a *thenable*](#chain-a-thenable)
25
27
  - [Pass arguments to the chain callback](#pass-arguments-to-the-chain-callback)
26
- - [Handle rejections / thrown errors](#handle-rejections--thrown-errors)
28
+ - [Handle failures](#handle-failures)
27
29
  - [Bind `this` context](#bind-this-context)
28
30
  - [Use an options object](#use-an-options-object)
31
+ - [Integrate with `@typescript-eslint`](#integrate-with-typescript-eslint)
29
32
  - [API](#api)
33
+ - [`isCatchable<T>(value)`][iscatchable]
34
+ - [`isFinalizable<T>(value)`][isfinalizable]
35
+ - [`isPromise<T>(value[, finalizable])`][ispromise]
36
+ - [`isPromiseLike<T>(value)`][ispromiselike]
30
37
  - [`isThenable<T>(value)`][isthenable]
31
- - [`when<[T][, Next][, Args][, Self]>(value, chain[, reject][, context][, ...args])`][when]
38
+ <!--lint disable-->
39
+ - [`when<T[, Next][, Failure][, Args][, Error][, This][, Result]>(value, chain[, fail][, context][, ...args])`][when]
40
+ <!--lint enable-->
41
+ - [Testing](#testing)
42
+ - [`createThenable<T[, Reason][, Result]>(executor[, options])`][createthenable]
32
43
  - [Types](#types)
33
44
  - [`Awaitable<T>`][awaitable]
34
- - [`Chain<[T][, Next][, Args][, Self]>`][chain]
35
- - [`Options<[T][, Next][, Args][, Self]>`][options]
36
- - [`Reject<[Next][, Fail][, Self]>`][reject]
45
+ - [`Catch<[T][, Reason]>`][catch]
46
+ - [`Catchable<[T]>`][catchable]
47
+ - [`Chain<[T][, Next][, Args][, This]>`][chain]
48
+ - [`CreateThenableOptions`][createthenableoptions]
49
+ - [`Executor<[T][, Reason]>`][executor]
50
+ - [`Fail<[Next][, Reason][, This]>`][fail]
51
+ - [`Finalizable<[T]>`][finalizable]
52
+ - [`Finally<[T]>`][finally]
53
+ - [`Finish<[This]>`][finish]
54
+ - [`OnFinally`][onfinally]
55
+ - [`OnFulfilled<T[, Next]>`][onfulfilled]
56
+ - [`OnRejected<Next[, Reason]>`][onrejected]
57
+ - [`Options<[T][, Next][, Failure][, Args][, Error][, This]>`][options]
58
+ - [`PromiseLike<T>`][promiselike]
59
+ - [`Reject<[Reason]>`][reject]
60
+ - [`Resolve<[T]>`][resolve]
61
+ - [`Then<[T][, Reason]>`][then]
62
+ - [`Thenable<[T]>`][thenable]
37
63
  - [Glossary](#glossary)
38
64
  - [Project](#project)
39
65
  - [Version](#version)
40
66
  - [Contribute](#contribute)
67
+ - [Sponsor](#sponsor)
41
68
 
42
69
  ## What is this?
43
70
 
44
- `when` is a small, but useful package for chaining a callback
45
- onto an [awaitable][] (a value or a [*thenable*][thenable]).
71
+ `when` is a tiny primitive for chaining callbacks
72
+ onto [awaitables][awaitable] (synchronous or [*thenable*][thenable-term] values).
46
73
 
47
- For thenable values, `.then` is used to invoke the callback after resolution.
48
- Otherwise, the callback is called immediately.
49
- This makes it easy to write one code path that supports both synchronous and asynchronous values.
74
+ For thenable values, `then` is used to invoke the callback after resolution. Otherwise, the callback fires immediately.
75
+ This makes it easy to write one code path that supports both synchronous values and promises.
50
76
 
51
- `when` is especially useful in libraries supporting awaitable APIs or libraries that accept user-provided hooks,
52
- loaders, or resolvers that may or may not return promises.
77
+ ## When should I use this?
53
78
 
54
- ### Why not `Promise.resolve`?
79
+ `when` is especially useful in libraries implementing awaitable APIs.
55
80
 
56
- `when` preserves synchronous values when possible, thus avoiding microtask scheduling and needless promise-allocation
57
- for these values, as well as making it a great choice for libraries offering API flexibility.
81
+ It provides [`Promise.prototype.then`][promise-then] semantics without forcing [`Promise.resolve`][promise-resolve],
82
+ preserving synchronous execution whenever possible.
83
+
84
+ Typical use cases include plugin systems, hook pipelines, module resolvers, data loaders, and file system adapters where
85
+ users may return both synchronous or asynchronous values.
86
+
87
+ If you're only dealing with promises and thenables, consider using native `async/await` or `Promise` chaining instead.
88
+
89
+ ### Why not [`Promise.resolve`][promise-resolve]?
90
+
91
+ `when` preserves synchronous operations whenever possible,
92
+ avoiding unnecessary promise allocation and microtask scheduling.
93
+
94
+ ```ts
95
+ Promise.resolve(value).then(fn) // always a promise
96
+ ```
97
+
98
+ ```ts
99
+ when(value, fn) // only a promise if `value` is a thenable, or `fn` returns one
100
+ ```
101
+
102
+ ### Design guarantees
103
+
104
+ - Synchronous values remain synchronous
105
+ - [*Thenable*s][thenable-term] are chained directly without wrapping in [`Promise.resolve`][promise-resolve]
106
+ - No additional microtasks are scheduled for non-thenables
107
+ - Failures propagate unless a `fail` handler is provided
58
108
 
59
109
  ## Install
60
110
 
@@ -92,60 +142,71 @@ In browsers with [`esm.sh`][esmsh]:
92
142
  ### Chain a synchronous value
93
143
 
94
144
  ```ts
95
- import { isThenable, when, type Awaitable } from '@flex-development/when'
145
+ import { isThenable, when } from '@flex-development/when'
96
146
  import { ok } from 'devlop'
97
147
 
98
148
  /**
99
149
  * The result.
100
150
  *
101
- * @const {Awaitable<number>} result
151
+ * @const {number} result
102
152
  */
103
- const result: Awaitable<number> = when(0, n => n + 1)
153
+ const result: number = when(0, n => n + 1)
104
154
 
105
155
  ok(!isThenable(result), 'expected `result` to not be thenable')
106
156
  console.dir(result) // 1
107
157
  ```
108
158
 
109
- ### Chain a [*thenable*][thenable]
159
+ ### Chain a [*thenable*][thenable-term]
110
160
 
111
161
  ```ts
112
- import { isThenable, when, type Awaitable } from '@flex-development/when'
162
+ import { isPromise, when } from '@flex-development/when'
113
163
  import { ok } from 'devlop'
114
164
 
115
165
  /**
116
166
  * The result.
117
167
  *
118
- * @const {Awaitable<number>} result
168
+ * @const {Promise<number>} result
119
169
  */
120
- const result: Awaitable<number> = when(Promise.resolve(2), n => n + 1)
170
+ const result: Promise<number> = when(Promise.resolve(2), n => n + 1)
121
171
 
122
- ok(isThenable(result), 'expected `result` to be thenable')
172
+ ok(isPromise(result), 'expected `result` to be a promise')
123
173
  console.dir(await result) // 3
124
174
  ```
125
175
 
126
176
  ### Pass arguments to the chain callback
127
177
 
128
- Arguments are passed first, and the resolved value is passed last.
178
+ When arguments are provided, they are passed to the [`chain`][chain] callback first, followed by the resolved value.
129
179
 
130
- When the `value` passed to `when` is not [*thenable*][thenable], the resolved value is the same `value`.
180
+ When the `value` passed to `when` is not a [*thenable*][thenable-term], the resolved value is the same `value`.
131
181
 
132
182
  ```ts
133
- import when, { type Awaitable } from '@flex-development/when'
183
+ import when from '@flex-development/when'
134
184
 
135
185
  /**
136
186
  * The result.
137
187
  *
138
- * @const {Awaitable<number>} result
188
+ * @const {number} result
139
189
  */
140
- const result: Awaitable<number> = when(1, Math.min, null, undefined, 2, 3, 4)
190
+ const result: number = when(
191
+ 1, // last argument passed to `Math.min`
192
+ Math.min, // `chain`
193
+ null, // `fail`
194
+ undefined, // `context`
195
+ 2, // first argument passed to `Math.min`
196
+ 3, // second argument passed to `Math.min`
197
+ 4 // third argument passed to `Math.min`
198
+ )
141
199
 
142
200
  console.dir(result) // 1
143
201
  ```
144
202
 
145
- ### Handle rejections / thrown errors
203
+ ### Handle failures
204
+
205
+ For [*thenable*s][thenable-term], the [`fail`][fail] callback is passed to [`then`][then] as the `onrejected` parameter,
206
+ and if implemented, to [`catch`][catch] as well to prevent unhandled rejections.
146
207
 
147
208
  ```ts
148
- import when, { type Awaitable } from '@flex-development/when'
209
+ import when from '@flex-development/when'
149
210
 
150
211
  /**
151
212
  * The thenable value.
@@ -159,9 +220,9 @@ const value: PromiseLike<never> = new Promise((resolve, reject) => {
159
220
  /**
160
221
  * The result.
161
222
  *
162
- * @const {Awaitable<boolean>} result
223
+ * @const {Promise<boolean>} result
163
224
  */
164
- const result: Awaitable<boolean> = when(value, chain, reject)
225
+ const result: Promise<boolean> = when(value, chain, fail)
165
226
 
166
227
  console.dir(await result) // false
167
228
 
@@ -183,7 +244,7 @@ function chain(this: void): true {
183
244
  * @return {false}
184
245
  * The failure result
185
246
  */
186
- function reject(this: void, e: Error): false {
247
+ function fail(this: void, e: Error): false {
187
248
  return console.dir(e), false
188
249
  }
189
250
  ```
@@ -191,7 +252,7 @@ function reject(this: void, e: Error): false {
191
252
  ### Bind `this` context
192
253
 
193
254
  ```ts
194
- import when, { type Awaitable } from '@flex-development/when'
255
+ import when from '@flex-development/when'
195
256
 
196
257
  /**
197
258
  * The `this` context.
@@ -201,9 +262,9 @@ type Context = { prefix: string }
201
262
  /**
202
263
  * The result.
203
264
  *
204
- * @const {Awaitable<string>} result
265
+ * @const {string} result
205
266
  */
206
- const result: Awaitable<string> = when(13, id, null, { prefix: 'id:' })
267
+ const result: string = when(13, id, null, { prefix: 'id:' })
207
268
 
208
269
  console.log(result) // 'id:13'
209
270
 
@@ -223,8 +284,6 @@ function id(this: Context, num: number | string): string {
223
284
  ### Use an options object
224
285
 
225
286
  ```ts
226
- import when, { type Awaitable } from '@flex-development/when'
227
-
228
287
  /**
229
288
  * The `this` context.
230
289
  */
@@ -240,13 +299,13 @@ const value: Promise<number> = new Promise(resolve => resolve(3))
240
299
  /**
241
300
  * The result.
242
301
  *
243
- * @const {Awaitable<number | undefined>} result
302
+ * @const {Promise<number | undefined>} result
244
303
  */
245
- const result: Awaitable<number | undefined> = when(value, {
304
+ const result: Promise<number | undefined> = when(value, {
246
305
  args: [39],
247
306
  chain: divide,
248
307
  context: { errors: [] },
249
- reject
308
+ fail
250
309
  })
251
310
 
252
311
  console.dir(await result) // 13
@@ -272,22 +331,130 @@ function divide(this: void, dividend: number, divisor: number): number {
272
331
  * The error to handle
273
332
  * @return {undefined}
274
333
  */
275
- function reject(this: Context, e: Error): undefined {
334
+ function fail(this: Context, e: Error): undefined {
276
335
  return void this.errors.push(e)
277
336
  }
278
337
  ```
279
338
 
339
+ ### Integrate with [`@typescript-eslint`][typescript-eslint]
340
+
341
+ ```js
342
+ /**
343
+ * The eslint configuration.
344
+ *
345
+ * @type {import('eslint').Linter.Config[]}
346
+ * @const config
347
+ */
348
+ const config = [
349
+ {
350
+ files: ['**/*.+(cjs|cts|js|jsx|mjs|mts|ts|tsx)'],
351
+ rules: {
352
+ '@typescript-eslint/promise-function-async': [
353
+ 2,
354
+ {
355
+ allowedPromiseNames: ['Thenable']
356
+ }
357
+ ]
358
+ }
359
+ }
360
+ ]
361
+
362
+ export default config
363
+ ```
364
+
280
365
  ## API
281
366
 
282
367
  `when` exports the identifiers listed below.
283
368
 
284
369
  The default export is [`when`][when].
285
370
 
286
- ### `isThenable<T>(value)`
371
+ ### `isCatchable<T>(value)`
372
+
373
+ Check if `value` looks like a [`Thenable`][thenable] that can be caught.
374
+
375
+ #### Type Parameters
376
+
377
+ - `T` (`any`)
378
+ — the resolved value
379
+
380
+ #### Parameters
381
+
382
+ - `value` (`unknown`)
383
+ — the thing to check
384
+
385
+ #### Returns
386
+
387
+ ([`value is Catchable<T>`][catchable])
388
+ `true` if `value` is a [*thenable*][thenable-term] with a [`catch`][catch] method, `false` otherwise
389
+
390
+ ### `isFinalizable<T>(value)`
391
+
392
+ Check if `value` looks like a [`Thenable`][thenable] that can be finalized.
393
+
394
+ #### Type Parameters
395
+
396
+ - `T` (`any`)
397
+ — the resolved value
398
+
399
+ #### Parameters
400
+
401
+ - `value` (`unknown`)
402
+ — the thing to check
403
+
404
+ #### Returns
405
+
406
+ ([`value is Finalizable<T>`][finalizable])
407
+ `true` if `value` is a [*thenable*][thenable-term] with a [`finally`][finally] method, `false` otherwise
408
+
409
+ ### `isPromise<T>(value[, finalizable])`
410
+
411
+ Check if `value` looks like a `Promise`.
412
+
413
+ > 👉 **Note**: This function intentionally performs structural checks instead of brand checks.
414
+ > It does not rely on `instanceof Promise` or constructors, making it compatible with cross-realm
415
+ > promises and custom thenables.
416
+
417
+ #### Type Parameters
418
+
419
+ - `T` (`any`)
420
+ — the resolved value
421
+
422
+ #### Parameters
423
+
424
+ - `value` (`unknown`)
425
+ — the thing to check
426
+ - `finalizable` (`boolean` | `null` | `undefined`)
427
+ — whether a [`finally`][finally] method is required.\
428
+ when `false`, only [`then`][then] and [`catch`][catch] are checked
429
+
430
+ #### Returns
431
+
432
+ (`value is Promise<T>`)
433
+ `true` if `value` is a [*thenable*][thenable-term] with a [`catch`][catch] method,
434
+ and [`finally`][finally] method (if requested), `false` otherwise
435
+
436
+ ### `isPromiseLike<T>(value)`
437
+
438
+ Check if `value` looks like a [`PromiseLike`][promiselike] structure.
439
+
440
+ #### Type Parameters
441
+
442
+ - `T` (`any`)
443
+ — the resolved value
444
+
445
+ #### Parameters
446
+
447
+ - `value` (`unknown`)
448
+ — the thing to check
287
449
 
288
- Check if `value` looks like a [*thenable*][thenable].
450
+ #### Returns
451
+
452
+ ([`value is PromiseLike<T>`][promiselike])
453
+ `true` if `value` is an object or function with a [`then`][then] method, `false` otherwise
454
+
455
+ ### `isThenable<T>(value)`
289
456
 
290
- > 👉 **Note**: Also exported as `isPromiseLike`.
457
+ Check if `value` looks like a [*thenable*][thenable-term].
291
458
 
292
459
  #### Type Parameters
293
460
 
@@ -301,15 +468,17 @@ Check if `value` looks like a [*thenable*][thenable].
301
468
 
302
469
  #### Returns
303
470
 
304
- (`value is PromiseLike<T>`) `true` if `value` is a thenable, `false` otherwise
471
+ ([`value is Thenable<T>`][thenable]) `true` if `value` is an object or function with a [`then`][then] method,
472
+ and maybe-callable methods [`catch`][catch] and/or [`finally`][finally], `false` otherwise
305
473
 
306
474
  <!--lint disable-->
307
475
 
308
- ### `when<[T][, Next][, Args][, Self]>(value, chain[, reject][, context][, ...args])`
476
+ ### `when<T[, Next][, Failure][, Args][, Error][, This][, Result]>(value, chain[, fail][, context][, ...args])`
309
477
 
310
478
  <!--lint enable-->
311
479
 
312
- Chain a callback, calling the function after `value` is resolved, or immediately if `value` is not thenable.
480
+ Chain a callback, calling the function after `value` is resolved,
481
+ or immediately if `value` is not a [*thenable*][thenable-term].
313
482
 
314
483
  #### Overloads
315
484
 
@@ -318,28 +487,51 @@ function when<
318
487
  T,
319
488
  Next = any,
320
489
  Args extends any[] = any[],
321
- Self = unknown
490
+ This = unknown,
491
+ Result extends Awaitable<Next> = Awaitable<Next>
492
+ >(
493
+ this: void,
494
+ value: Awaitable<T>,
495
+ chain: Chain<T, Next, Args, This>,
496
+ fail?: null | undefined,
497
+ context?: This | null | undefined,
498
+ ...args: Args
499
+ ): Result
500
+ ```
501
+
502
+ ```ts
503
+ function when<
504
+ T,
505
+ Next = any,
506
+ Failure = Next,
507
+ Args extends any[] = any[],
508
+ Error = any,
509
+ This = unknown,
510
+ Result extends Awaitable<Failure | Next> = Awaitable<Failure | Next>
322
511
  >(
323
512
  this: void,
324
513
  value: Awaitable<T>,
325
- chain: Chain<T, Next, Args, Self>,
326
- reject?: Reject<Next, any, Self> | null | undefined,
327
- context?: Self | null | undefined,
514
+ chain: Chain<T, Next, Args, This>,
515
+ fail?: Fail<Failure, Error, This> | null | undefined,
516
+ context?: This | null | undefined,
328
517
  ...args: Args
329
- ): Awaitable<Next>
518
+ ): Result
330
519
  ```
331
520
 
332
521
  ```ts
333
522
  function when<
334
523
  T,
335
524
  Next = any,
525
+ Failure = Next,
336
526
  Args extends any[] = any[],
337
- Self = unknown
527
+ Error = any,
528
+ This = unknown,
529
+ Result extends Awaitable<Failure | Next> = Awaitable<Failure | Next>
338
530
  >(
339
531
  this: void,
340
532
  value: Awaitable<T>,
341
- chain: Options<T, Next, Args, Self>
342
- ): Awaitable<Next>
533
+ chain: Options<T, Next, Failure, Args, Error, This>
534
+ ): Result
343
535
  ```
344
536
 
345
537
  #### Type Parameters
@@ -349,29 +541,106 @@ function when<
349
541
  - `Next` (`any`, optional)
350
542
  — the next resolved value
351
543
  - **default**: `any`
544
+ - `Failure` (`any`, optional)
545
+ — the next resolved value on failure
546
+ - **default**: `Next`
352
547
  - `Args` (`readonly any[]`, optional)
353
- — the function arguments
548
+ — the chain function arguments
354
549
  - **default**: `any[]`
355
- - `Self` (`any`, optional)
550
+ - `Error` (`any`, optional)
551
+ — the error to possibly handle
552
+ - **default**: `any`
553
+ - `This` (`any`, optional)
356
554
  — the `this` context
357
555
  - **default**: `unknown`
556
+ - `Result` ([`Awaitable<Failure | Next>`][awaitable], optional)
557
+ — the next awaitable
558
+ - **default**: [`Awaitable<Failure | Next>`][awaitable]
358
559
 
359
560
  #### Parameters
360
561
 
361
562
  - `value` ([`Awaitable<T>`][awaitable])
362
- — the promise or the resolved value
363
- - `chain` ([`Chain<T, Next, Args, Self>`][chain] | [`Options<T, Next, Args, Self>`][options])
563
+ — the current [*awaitable*][awaitable-term]
564
+ - `chain` ([`Chain<T, Next, Args, This>`][chain] | [`Options<T, Next, Failure, Args, Error, This>`][options])
364
565
  — the chain callback or options for chaining
365
- - `reject` ([`Reject<Next, any, Self>`][reject] | `null` | `undefined`)
366
- — the callback to fire when a promise is rejected or an error is thrown
367
- - `context` (`Self` | `null` | `undefined`)
368
- the `this` context of the chain and error callbacks
566
+ - `fail` ([`Fail<Failure, Error, This>`][fail] | `null` | `undefined`)
567
+ — the callback to fire when a failure occurs. failures include:
568
+ - rejections of the input [*thenable*][thenable-term]
569
+ - rejections returned from `chain`
570
+ - synchronous errors thrown in `chain`\
571
+ if no `fail` handler is provided, failures are re-thrown or re-propagated.
572
+ > 👉 **note**: for thenables, this callback is passed to `then` as the `onrejected` parameter,
573
+ > and if implemented, to `catch` as well to prevent unhandled rejections.
574
+ - `context` (`This` | `null` | `undefined`)
575
+ — the `this` context of the chain and `fail` callbacks
369
576
  - `...args` (`Args`)
370
577
  — the arguments to pass to the chain callback
371
578
 
372
579
  #### Returns
373
580
 
374
- ([`Awaitable<Next>`][awaitable]) The next promise or value
581
+ ([`Awaitable<Failure | Next>`][awaitable] | [`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
582
+
583
+ ## Testing
584
+
585
+ Test utilities are exported from `@flex-development/when/testing`.
586
+
587
+ There is no default export.
588
+
589
+ ```ts
590
+ import {
591
+ isCatchable,
592
+ isFinalizable,
593
+ type Thenable
594
+ } from '@flex-development/when'
595
+ import { createThenable } from '@flex-development/when/testing'
596
+ import { ok } from 'devlop'
597
+
598
+ /**
599
+ * The thenable.
600
+ *
601
+ * @const {Thenable<number>} thenable
602
+ */
603
+ const thenable: Thenable<number> = createThenable(resolve => resolve(10))
604
+
605
+ ok(isCatchable(thenable), 'expected `thenable` to be a catchable')
606
+ ok(isFinalizable(thenable), 'expected `thenable` to be a finalizable')
607
+
608
+ console.dir(await thenable.then(value => value + 3)) // 13
609
+ ```
610
+
611
+ ### `createThenable<T[, Reason][, Result]>(executor[, options])`
612
+
613
+ Create a thenable.
614
+
615
+ The returned object conforms to [`Thenable`][thenable] and ensures [`then`][then] always returns another `Thenable`,
616
+ even when adopting a foreign [*thenable*][thenable-term].
617
+
618
+ When `options` is omitted, `null`, or `undefined`, the returned thenable is *modern* (a [*thenable*][thenable-term]
619
+ with [`then`][then], [`catch`][catch], and [`finally`][finally] methods).
620
+ Pass an options object (e.g. `{}`) to start from a *bare* ([`then`][then] method only) thenable
621
+ and selectively enable methods.
622
+
623
+ #### Type Parameters
624
+
625
+ - `T` (`any`)
626
+ — the resolved value
627
+ - `Reason` (`any`, optional)
628
+ — the reason for a rejection
629
+ - **default**: `Error`
630
+ - `Result` ([`Thenable<T>`][thenable], optional)
631
+ — the thenable
632
+ - **default**: [`Thenable<T>`][thenable]
633
+
634
+ #### Parameters
635
+
636
+ - `executor` ([`Executor<T, Reason>`][executor])
637
+ — the initialization callback
638
+ - `options` ([`CreateThenableOptions`][createthenableoptions] | `null` | `undefined`, optional)
639
+ — options for creating a thenable
640
+
641
+ #### Returns
642
+
643
+ (`Result`) The [*thenable*][thenable-term]
375
644
 
376
645
  ## Types
377
646
 
@@ -379,10 +648,10 @@ This package is fully typed with [TypeScript][].
379
648
 
380
649
  ### `Awaitable<T>`
381
650
 
382
- A synchronous or [*thenable*][thenable] value (`type`).
651
+ A synchronous or [*thenable*][thenable-term] value (`type`).
383
652
 
384
653
  ```ts
385
- type Awaitable<T> = PromiseLike<T> | T
654
+ type Awaitable<T> = Thenable<T> | T
386
655
  ```
387
656
 
388
657
  #### Type Parameters
@@ -390,7 +659,58 @@ type Awaitable<T> = PromiseLike<T> | T
390
659
  - `T` (`any`)
391
660
  — the resolved value
392
661
 
393
- ### `Chain<[T][, Next][, Args][, Self]>`
662
+ ### `Catch<[T][, Reason]>`
663
+
664
+ Attach a callback only for the rejection of a [`Thenable`][thenable] (`type`).
665
+
666
+ ```ts
667
+ type Catch<T = unknown, Reason = any> = <Next = never>(
668
+ this: any,
669
+ onrejected?: OnRejected<Next, Reason> | null | undefined
670
+ ) => Thenable<Next | T>
671
+ ```
672
+
673
+ #### Type Parameters
674
+
675
+ - `T` (`any`, optional)
676
+ — the resolved value
677
+ - **default**: `unknown`
678
+ - `Reason` (`any`, optional)
679
+ — the reason for the rejection
680
+ - **default**: `any`
681
+ - `Next` (`any`, optional)
682
+ — the next resolved value
683
+ - **default**: `never`
684
+
685
+ #### Parameters
686
+
687
+ - `onrejected` ([`OnRejected<Next, Reason>`][onrejected] | `null` | `undefined`)
688
+ — the callback to execute when the thenable is rejected
689
+
690
+ #### Returns
691
+
692
+ ([`Thenable<Next | T>`][thenable]) The next [*thenable*][thenable-term]
693
+
694
+ ### `Catchable<[T]>`
695
+
696
+ A [`Thenable`][thenable] that can be caught (`interface`).
697
+
698
+ #### Extends
699
+
700
+ - [`Thenable<T>`][thenable]
701
+
702
+ #### Type Parameters
703
+
704
+ - `T` (`any`, optional)
705
+ — the resolved value
706
+ - **default**: `any`
707
+
708
+ #### Properties
709
+
710
+ - `catch` ([`Catch<T>`][catch])
711
+ — attach a callback only to be invoked on rejection
712
+
713
+ ### `Chain<[T][, Next][, Args][, This]>`
394
714
 
395
715
  A chain callback (`type`).
396
716
 
@@ -399,8 +719,8 @@ type Chain<
399
719
  T = any,
400
720
  Next = any,
401
721
  Args extends readonly any[] = any[],
402
- Self = unknown
403
- > = (this: Self, ...params: [...Args, T]) => Awaitable<Next>
722
+ This = unknown
723
+ > = (this: This, ...params: [...Args, T]) => Awaitable<Next>
404
724
  ```
405
725
 
406
726
  #### Type Parameters
@@ -414,22 +734,244 @@ type Chain<
414
734
  - `Args` (`readonly any[]`, optional)
415
735
  — the function arguments
416
736
  - **default**: `any[]`
417
- - `Self` (`any`, optional)
737
+ - `This` (`any`, optional)
418
738
  — the `this` context
419
739
  - **default**: `unknown`
420
740
 
421
741
  #### Parameters
422
742
 
423
- - **`this`** (`Self`)
743
+ - **`this`** (`This`)
424
744
  - `...params` (`[...Args, T]`)
425
745
  — the function parameters, with the last being the previously resolved value.
426
746
  in cases where a promise is not being resolved, this is the same `value` passed to `when`
427
747
 
428
748
  #### Returns
429
749
 
430
- ([`Awaitable<Next>`][awaitable]) The next promise or value
750
+ ([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
751
+
752
+ ### `CreateThenableOptions`
753
+
754
+ Options for creating a [*thenable*][thenable-term] (`interface`).
755
+
756
+ > 👉 **Note**: Exported from `@flex-development/when/testing` only.
757
+
758
+ #### Properties
759
+
760
+ - `catch?` (`boolean` | `null` | `undefined`)
761
+ — control whether returned thenables implement a [`catch`][catch] method.\
762
+ when an options object is omitted, `null`, or `undefined`, the method will be implemented.\<br/>
763
+ when an options object is provided, `catch` is only implemented if `options.catch` is `true`.\
764
+ if `options.catch` is `null` or `undefined`, the thenable's `catch` property will have the same value.\
765
+ pass `false` to disable the method implementation
766
+ - `finally?` (`boolean` | `null` | `undefined`)
767
+ — control whether returned thenables implement a [`finally`][finally] method.\
768
+ when an options object is omitted, `null`, or `undefined`, the method will be implemented.\
769
+ when an options object is provided, `finally` is only implemented if `options.finally` is `true`.\
770
+ if `options.finally` is `null` or `undefined`, the thenable's `finally` property will have the same value.\
771
+ pass `false` to disable the method implementation
772
+
773
+ ### `Executor<[T][, Reason]>`
774
+
775
+ The callback used to initialize a [*thenable*][thenable-term] (`type`).
431
776
 
432
- ### `Options<[T][, Next][, Args][, Self]>`
777
+ > 👉 **Note**: Exported from `@flex-development/when/testing` only.
778
+
779
+ ```ts
780
+ type Executor<T = any, Reason = Error> = (
781
+ this: void,
782
+ resolve: Resolve<T>,
783
+ reject: Reject<Reason>
784
+ ) => undefined | void
785
+ ```
786
+
787
+ #### Type Parameters
788
+
789
+ - `T` (`any`, optional)
790
+ — the resolved value
791
+ - **default**: `any`
792
+ - `Reason` (`any`, optional)
793
+ — the reason for a rejection
794
+ - **default**: `Error`
795
+
796
+ #### Parameters
797
+
798
+ - `resolve` ([`Resolve<T>`][resolve])
799
+ — the callback used to resolve the thenable with a value or the result of another [*awaitable*][awaitable-term]
800
+ - `reject` ([`Reject<Reason>`][reject])
801
+ — the callback used to reject the thenable with a provided reason or error
802
+
803
+ #### Returns
804
+
805
+ (`undefined` | `void`) Nothing
806
+
807
+ ### `Fail<[Next][, Reason][, This]>`
808
+
809
+ The callback to fire when a failure occurs (`type`).
810
+
811
+ ```ts
812
+ type Fail<
813
+ Next = any,
814
+ Reason = any,
815
+ This = unknown
816
+ > = (this: This, reason: Reason) => Awaitable<Next>
817
+ ```
818
+
819
+ #### Type Parameters
820
+
821
+ - `Next` (`any`, optional)
822
+ — the next resolved value
823
+ - **default**: `any`
824
+ - `Reason` (`any`, optional)
825
+ — the reason for the failure
826
+ - **default**: `any`
827
+ - `This` (`any`, optional)
828
+ — the `this` context
829
+ - **default**: `unknown`
830
+
831
+ #### Parameters
832
+
833
+ - **`this`** (`This`)
834
+ - `reason` (`Reason`)
835
+ — the reason for the failure
836
+
837
+ #### Returns
838
+
839
+ ([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
840
+
841
+ ### `Finalizable<[T]>`
842
+
843
+ A [`Thenable`][thenable] that can be finalized (`interface`).
844
+
845
+ #### Extends
846
+
847
+ - [`Thenable<T>`][thenable]
848
+
849
+ #### Type Parameters
850
+
851
+ - `T` (`any`, optional)
852
+ — the resolved value
853
+ - **default**: `any`
854
+
855
+ #### Properties
856
+
857
+ - `finally` ([`Finally<T>`][finally])
858
+ — attach a callback only to be invoked on settlement (fulfillment or rejection)
859
+ > 👉 **note**: the resolved value cannot be modified from the callback
860
+
861
+ ### `Finally<[T]>`
862
+
863
+ Attach a callback that is invoked only when a [`Thenable`][thenable] is settled (fulfilled or rejected) (`type`).
864
+
865
+ ```ts
866
+ type Finally<T = unknown> = (
867
+ this: any,
868
+ onfinally?: OnFinally | null | undefined
869
+ ) => Thenable<T>
870
+ ```
871
+
872
+ #### Type Parameters
873
+
874
+ - `T` (`any`, optional)
875
+ — the resolved value
876
+ - **default**: `unknown`
877
+
878
+ #### Parameters
879
+
880
+ - `onfinally` ([`OnFinally`][onfinally] | `null` | `undefined`)
881
+ — the callback to execute when the thenable is settled
882
+
883
+ #### Returns
884
+
885
+ ([`Thenable<T>`][thenable]) The next [*thenable*][thenable-term]
886
+
887
+ ### `Finish<[This]>`
888
+
889
+ A post-processing hook invoked exactly once after an [*awaitable*][awaitable-term] settles,
890
+ regardless of success or failure (`type`).
891
+
892
+ The resolved value cannot be modified from the hook, and any error is re-thrown after execution.
893
+
894
+ ```ts
895
+ type Finish<This = unknown> = (this: This) => undefined | void
896
+ ```
897
+
898
+ #### Type Parameters
899
+
900
+ - `This` (`any`, optional)
901
+ — the `this` context
902
+ - **default**: `unknown`
903
+
904
+ #### Returns
905
+
906
+ (`undefined` | `void`) Nothing
907
+
908
+ ### `OnFinally`
909
+
910
+ The callback to execute when a [`Thenable`][thenable] is settled (fulfilled or rejected) (`type`).
911
+
912
+ ```ts
913
+ type OnFinally = (this: unknown) => undefined | void
914
+ ```
915
+
916
+ #### Returns
917
+
918
+ (`undefined` | `void`) Nothing
919
+
920
+ ### `OnFulfilled<T[, Next]>`
921
+
922
+ The callback to execute when a [`Thenable`][thenable] is resolved (`type`).
923
+
924
+ ```ts
925
+ type OnFulfilled<T, Next = T> = (this: unknown, value: T) => Awaitable<Next>
926
+ ```
927
+
928
+ #### Type Parameters
929
+
930
+ - `T` (`any`)
931
+ — the resolved value
932
+ - `Next` (`any`, optional)
933
+ — the next resolved value
934
+ - **default**: `T`
935
+
936
+ #### Parameters
937
+
938
+ - `value` (`T`)
939
+ — the resolved value
940
+
941
+ #### Returns
942
+
943
+ ([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
944
+
945
+ ### `OnRejected<Next[, Reason]>`
946
+
947
+ The callback to execute when a [`Thenable`][thenable] is rejected (`type`).
948
+
949
+ ```ts
950
+ type OnRejected<
951
+ Next,
952
+ Reason = any
953
+ > = (this: unknown, reason: Reason) => Awaitable<Next>
954
+ ```
955
+
956
+ #### Type Parameters
957
+
958
+ - `Next` (`any`, optional)
959
+ — the next resolved value
960
+ - **default**: `any`
961
+ - `Reason` (`any`, optional)
962
+ — the reason for the rejection
963
+ - **default**: `any`
964
+
965
+ #### Parameters
966
+
967
+ - `reason` (`Reason`)
968
+ — the reason for the rejection
969
+
970
+ #### Returns
971
+
972
+ ([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
973
+
974
+ ### `Options<[T][, Next][, Failure][, Args][, Error][, This]>`
433
975
 
434
976
  Options for chaining (`interface`).
435
977
 
@@ -437,8 +979,10 @@ Options for chaining (`interface`).
437
979
  interface Options<
438
980
  T = any,
439
981
  Next = any,
982
+ Failure = Next,
440
983
  Args extends readonly any[] = any[],
441
- Self = any
984
+ Error = any,
985
+ This = any
442
986
  > { /* ... */ }
443
987
  ```
444
988
 
@@ -450,10 +994,16 @@ interface Options<
450
994
  - `Next` (`any`, optional)
451
995
  — the next resolved value
452
996
  - **default**: `any`
997
+ - `Failure` (`any`, optional)
998
+ — the next resolved value on failure
999
+ - **default**: `Next`
453
1000
  - `Args` (`readonly any[]`, optional)
454
1001
  — the chain function arguments
455
1002
  - **default**: `any[]`
456
- - `Self` (`any`, optional)
1003
+ - `Error` (`any`, optional)
1004
+ — the error to possibly handle
1005
+ - **default**: `any`
1006
+ - `This` (`any`, optional)
457
1007
  — the `this` context
458
1008
  - **default**: `any`
459
1009
 
@@ -461,60 +1011,169 @@ interface Options<
461
1011
 
462
1012
  - `args?` (`Args` | `null` | `undefined`)
463
1013
  — the arguments to pass to the `chain` callback
464
- - `chain` ([`Chain<T, Next, Args, Self>`][chain])
1014
+ - `chain` ([`Chain<T, Next, Args, This>`][chain])
465
1015
  — the chain callback
466
- - `context?` (`Self` | `null` | `undefined`)
467
- — the `this` context of the `chain` and `reject` callbacks
468
- - `reject?` ([`Reject<Next, any, Self>`][reject] | `null` | `undefined`)
469
- — the callback to fire when a promise is rejected or an error is thrown
1016
+ - `context?` (`This` | `null` | `undefined`)
1017
+ — the `this` context of the `chain` and `fail` callbacks
1018
+ - `fail?` ([`Fail<Next, Error, This>`][fail] | `null` | `undefined`)
1019
+ — the callback to fire when a failure occurs. failures include:
1020
+ - rejections of the input [*thenable*][thenable-term]
1021
+ - rejections returned from `chain`
1022
+ - synchronous errors thrown in `chain`\
1023
+ if no `fail` handler is provided, failures are re-thrown or re-propagated.
1024
+ > 👉 **note**: for thenables, this callback is passed to `then` as the `onrejected` parameter,
1025
+ > and if implemented, to [`catch`][catch] as well to prevent unhandled rejections.
1026
+ - `finish?` ([`Finish<This>`][finish] | `null` | `undefined`)
1027
+ — the callback to invoke after chaining completes, whether the operation succeeds or fails.\
1028
+ it runs exactly once after `chain` and `fail`, cannot affect the resolved value, and does not intercept errors
1029
+
1030
+ ### `PromiseLike<T>`
1031
+
1032
+ To ensure native `Promise` and `PromiseLike` are assignable to [`Thenable`][thenable],
1033
+ `when` ships a small global augmentation for `PromiseLike`.
1034
+
1035
+ No new methods or overloads are introduced — the `then` signature is rewritten to match
1036
+ the official [TypeScript][] lib definition (as in `lib.es2015.d.ts`).
1037
+
1038
+ This is required for both compatibility, and type inference when mixing `Thenable` with built-in promise types.
1039
+
1040
+ #### Type Parameters
1041
+
1042
+ - `T` (`any`)
1043
+ — the resolved value
470
1044
 
471
- ### `Reject<[Next][, Fail][, Self]>`
1045
+ ### `Reject<[Reason]>`
472
1046
 
473
- The callback to fire when a promise is rejected or an error is thrown from a synchronous function (`type`).
1047
+ The callback used to reject a [*thenable*][thenable-term] with a provided reason or error (`type`).
1048
+
1049
+ > 👉 **Note**: Exported from `@flex-development/when/testing` only.
474
1050
 
475
1051
  ```ts
476
- type Reject<
477
- Next = any,
478
- Fail = any,
479
- Self = unknown
480
- > = (this: Self, e: Fail) => Awaitable<Next>
1052
+ type Reject<Reason = Error> = (this: void, reason: Reason) => undefined
481
1053
  ```
482
1054
 
483
1055
  #### Type Parameters
484
1056
 
485
- - `Next` (`any`, optional)
486
- — the next resolved value
487
- - **default**: `any`
488
- - `Fail` (`any`, optional)
489
- the error to handle
1057
+ - `Reason` (`any`, optional)
1058
+ — the reason for the rejection
1059
+ - **default**: `Error`
1060
+
1061
+ #### Parameters
1062
+
1063
+ - `reason` (`Reason`)
1064
+ — the reason for the rejection
1065
+
1066
+ #### Returns
1067
+
1068
+ (`undefined`) Nothing
1069
+
1070
+ ### `Resolve<[T]>`
1071
+
1072
+ The callback used to resolve a [*thenable*][thenable-term] with a value
1073
+ or the result of another [*awaitable*][awaitable-term] (`type`).
1074
+
1075
+ > 👉 **Note**: Exported from `@flex-development/when/testing` only.
1076
+
1077
+ ```ts
1078
+ type Resolve<T = any> = (this: void, value: Awaitable<T>) => undefined
1079
+ ```
1080
+
1081
+ #### Type Parameters
1082
+
1083
+ - `T` (`any`, optional)
1084
+ — the resolved value
490
1085
  - **default**: `any`
491
- - `Self` (`any`, optional)
492
- the `this` context
1086
+
1087
+ #### Parameters
1088
+
1089
+ - `value` ([`Awaitable<T>`][awaitable])
1090
+ — the awaitable
1091
+
1092
+ #### Returns
1093
+
1094
+ (`undefined`) Nothing
1095
+
1096
+ ### `Then<T[, Reason]>`
1097
+
1098
+ Attach callbacks for the resolution and/or rejection of a [`Thenable`][thenable] (`type`).
1099
+
1100
+ ```ts
1101
+ type Then<T = unknown, Reason = any> = <Succ = T, Fail = never>(
1102
+ this: any,
1103
+ onfulfilled?: OnFulfilled<T, Succ> | null | undefined,
1104
+ onrejected?: OnRejected<Fail, Reason> | null | undefined
1105
+ ) => Thenable<Fail | Succ>
1106
+ ```
1107
+
1108
+ #### Type Parameters
1109
+
1110
+ - `T` (`any`, optional)
1111
+ — the previously resolved value
493
1112
  - **default**: `unknown`
1113
+ - `Reason` (`any`, optional)
1114
+ — the reason for a rejection
1115
+ - **default**: `any`
1116
+ - `Succ` (`any`, optional)
1117
+ — the next resolved value on success
1118
+ - **default**: `T`
1119
+ - `Fail` (`any`, optional)
1120
+ — the next resolved value on failure
1121
+ - **default**: `never`
494
1122
 
495
1123
  #### Parameters
496
1124
 
497
- - **`this`** (`Self`)
498
- - `e` (`Fail`)
499
- the error
1125
+ - `onfulfilled` ([`OnFulfilled<T, Succ>`][onfulfilled] | `null` | `undefined`)
1126
+ the callback to execute when the thenable is resolved
1127
+ - `onrejected` ([`OnRejected<Fail, Reason>`][onrejected] | `null` | `undefined`)
1128
+ — the callback to execute when the thenable is rejected
500
1129
 
501
1130
  #### Returns
502
1131
 
503
- ([`Awaitable<Next>`][awaitable]) The next promise or value
1132
+ ([`Thenable<Fail | Succ>`][thenable]) The next [*thenable*][thenable-term]
1133
+
1134
+ ### `Thenable<[T]>`
1135
+
1136
+ The completion of an asynchronous operation, and the minimal structural contract required
1137
+ by [`when`][when] to treat a value as asynchronous (`interface`).
1138
+
1139
+ Unlike `PromiseLike`, this interface allows a maybe-callable [`catch`][catch] method, which when present,
1140
+ is used by [`when`][when] to ensure failures are handled without forcing promise allocation.
1141
+
1142
+ Maybe-callable methods are named so because they are not required,
1143
+ and may be a method implementation, `null`, or `undefined`.
1144
+
1145
+ #### Type Parameters
1146
+
1147
+ - `T` (`any`, optional)
1148
+ — the resolved value
1149
+ - **default**: `any`
1150
+
1151
+ #### Properties
1152
+
1153
+ - `catch?` ([`Catch<T>`][catch] | `null` | `undefined`)
1154
+ — attach a callback only to be invoked on rejection
1155
+ - `then` ([`Then<T>`][then])
1156
+ — attach callbacks to be invoked on resolution (fulfillment) and/or rejection
1157
+ - `finally?` ([`Finally<T>`][finally] | `null` | `undefined`)
1158
+ — attach a callback only to be invoked on settlement (fulfillment or rejection)
1159
+ > 👉 **note**: the resolved value cannot be modified from the callback
504
1160
 
505
1161
  ## Glossary
506
1162
 
507
1163
  ### *awaitable*
508
1164
 
509
- A synchronous or [*thenable*][thenable] value.
1165
+ A synchronous or [*thenable*][thenable-term] value.
510
1166
 
511
1167
  ### *thenable*
512
1168
 
513
- An object or function with a `.then` method.
1169
+ An object or function with a [`then`][then] method.
514
1170
 
515
1171
  JavaScript engines use duck-typing for promises.
516
- Structures with a `.then` method will be treated as promise-like objects, and work with built-in mechanisms
517
- like [`Promise.resolve`][promise-resolve] and the [`await` keyword][await] like native promises.
1172
+ Arrays, functions, and objects with a `then` method will be treated as promise-like objects, and work with built-in
1173
+ mechanisms like [`Promise.resolve`][promise-resolve] and the [`await` keyword][await] like native promises.
1174
+
1175
+ Some thenables also implement a [`catch`][catch] method (like native promises).
1176
+ When available, [`when`][when] uses it to ensure rejections are handled.
518
1177
 
519
1178
  ## Project
520
1179
 
@@ -529,30 +1188,83 @@ See [`CONTRIBUTING.md`](CONTRIBUTING.md).
529
1188
  This project has a [code of conduct](./CODE_OF_CONDUCT.md).
530
1189
  By interacting with this repository, organization, or community you agree to abide by its terms.
531
1190
 
1191
+ ### Sponsor
1192
+
1193
+ This package is intentionally small — and intentionally maintained.
1194
+
1195
+ Small primitives power larger systems.
1196
+ Support long-term stability by sponsoring Flex Development.
1197
+
532
1198
  [await]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/await
533
1199
 
1200
+ [awaitable-term]: #awaitable
1201
+
534
1202
  [awaitable]: #awaitablet
535
1203
 
536
- [chain]: #chaint-next-args-self
1204
+ [catch]: #catcht-reason
1205
+
1206
+ [catchable]: #catchablet
1207
+
1208
+ [chain]: #chaint-next-args-this
1209
+
1210
+ [createthenable]: #createthenablet-reason-resultexecutor-options
1211
+
1212
+ [createthenableoptions]: #createthenableoptions
537
1213
 
538
1214
  [esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
539
1215
 
540
1216
  [esmsh]: https://esm.sh
541
1217
 
1218
+ [executor]: #executort-reason
1219
+
1220
+ [fail]: #failnext-reason-this
1221
+
1222
+ [finalizable]: #finalizablet
1223
+
1224
+ [finally]: #finallyt
1225
+
1226
+ [finish]: #finishthis
1227
+
1228
+ [iscatchable]: #iscatchabletvalue
1229
+
1230
+ [isfinalizable]: #isfinalizabletvalue
1231
+
1232
+ [ispromise]: #ispromisetvalue-finalizable
1233
+
1234
+ [ispromiselike]: #ispromiseliketvalue
1235
+
542
1236
  [isthenable]: #isthenabletvalue
543
1237
 
544
- [options]: #optionst-next-args-self
1238
+ [onfinally]: #onfinally
1239
+
1240
+ [onfulfilled]: #onfulfilledt-next
1241
+
1242
+ [onrejected]: #onrejectednext-reason
1243
+
1244
+ [options]: #optionst-next-failure-args-error-this
545
1245
 
546
1246
  [promise-resolve]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve
547
1247
 
548
- [reject]: #rejectnext-fail-self
1248
+ [promise-then]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
1249
+
1250
+ [promiselike]: #promiseliket
1251
+
1252
+ [reject]: #rejectreason
1253
+
1254
+ [resolve]: #resolvet
549
1255
 
550
1256
  [semver]: https://semver.org
551
1257
 
552
- [thenable]: #thenable
1258
+ [then]: #thent-reason
1259
+
1260
+ [thenable-term]: #thenable
1261
+
1262
+ [thenable]: #thenablet
1263
+
1264
+ [typescript-eslint]: https://typescript-eslint.io
553
1265
 
554
1266
  [typescript]: https://www.typescriptlang.org
555
1267
 
556
- [when]: #whent-next-args-selfvalue-chain-reject-context-args
1268
+ [when]: #whent-next-failure-args-error-this-resultvalue-chain-fail-context-args
557
1269
 
558
1270
  [yarn]: https://yarnpkg.com