| 620 | } |
| 621 | |
| 622 | function expectsError(stackStartFn, actual, error, message) { |
| 623 | if (typeof error === 'string') { |
| 624 | if (arguments.length === 4) { |
| 625 | throw new ERR_INVALID_ARG_TYPE('error', |
| 626 | ['Object', 'Error', 'Function', 'RegExp'], |
| 627 | error); |
| 628 | } |
| 629 | if (typeof actual === 'object' && actual !== null) { |
| 630 | if (actual.message === error) { |
| 631 | throw new ERR_AMBIGUOUS_ARGUMENT( |
| 632 | 'error/message', |
| 633 | `The error message "${actual.message}" is identical to the message.`, |
| 634 | ); |
| 635 | } |
| 636 | } else if (actual === error) { |
| 637 | throw new ERR_AMBIGUOUS_ARGUMENT( |
| 638 | 'error/message', |
| 639 | `The error "${actual}" is identical to the message.`, |
| 640 | ); |
| 641 | } |
| 642 | message = error; |
| 643 | error = undefined; |
| 644 | } else if (error != null && |
| 645 | typeof error !== 'object' && |
| 646 | typeof error !== 'function') { |
| 647 | throw new ERR_INVALID_ARG_TYPE('error', |
| 648 | ['Object', 'Error', 'Function', 'RegExp'], |
| 649 | error); |
| 650 | } |
| 651 | |
| 652 | if (actual === NO_EXCEPTION_SENTINEL) { |
| 653 | let details = ''; |
| 654 | if (error?.name) { |
| 655 | details += ` (${error.name})`; |
| 656 | } |
| 657 | details += message ? `: ${message}` : '.'; |
| 658 | const fnType = stackStartFn === Assert.prototype.rejects ? 'rejection' : 'exception'; |
| 659 | innerFail({ |
| 660 | actual: undefined, |
| 661 | expected: error, |
| 662 | operator: stackStartFn.name, |
| 663 | message: [`Missing expected ${fnType}${details}`], |
| 664 | stackStartFn, |
| 665 | diff: this?.[kOptions]?.diff, |
| 666 | }); |
| 667 | } |
| 668 | |
| 669 | if (!error) |
| 670 | return; |
| 671 | |
| 672 | expectedException.call(this, actual, error, message, stackStartFn); |
| 673 | } |
| 674 | |
| 675 | function hasMatchingError(actual, expected) { |
| 676 | if (typeof expected !== 'function') { |