|
7 | 7 | getOwnPropertyDescriptor, |
8 | 8 | defineProperty, |
9 | 9 | getOwnPropertyDescriptors, |
| 10 | + isArray, |
10 | 11 | } from '../commons.js'; |
11 | 12 | import { NativeErrors } from '../permits.js'; |
12 | 13 | import { tameV8ErrorConstructor } from './tame-v8-error-constructor.js'; |
@@ -37,9 +38,44 @@ export default function tameErrorConstructor( |
37 | 38 | ) { |
38 | 39 | const ErrorPrototype = FERAL_ERROR.prototype; |
39 | 40 |
|
40 | | - const { captureStackTrace: originalCaptureStackTrace } = FERAL_ERROR; |
41 | | - const platform = |
42 | | - typeof originalCaptureStackTrace === 'function' ? 'v8' : 'unknown'; |
| 41 | + const { |
| 42 | + captureStackTrace: originalCaptureStackTrace, |
| 43 | + prepareStackTrace: originalPrepareStackTrace, |
| 44 | + } = FERAL_ERROR; |
| 45 | + let platform = 'unknown'; |
| 46 | + if (typeof originalCaptureStackTrace === 'function') { |
| 47 | + // we might be on v8 |
| 48 | + if (typeof originalPrepareStackTrace === 'function') { |
| 49 | + // This case should not occur on v8 or any other platform. |
| 50 | + // But if it does, we assume we're on v8, or a platform whose |
| 51 | + // error stack logic is close enough that we can treat it |
| 52 | + // like v8. |
| 53 | + platform = 'v8'; |
| 54 | + } else { |
| 55 | + try { |
| 56 | + FERAL_ERROR.prepareStackTrace = (error, sst) => { |
| 57 | + // eslint-disable-next-line no-use-before-define |
| 58 | + if (error === sacrificialError && isArray(sst)) { |
| 59 | + // v8 implements `prepareStackTrace`. But on v8 the initial state |
| 60 | + // of the original error constructor, `FERAL_ERROR`, has no |
| 61 | + // `prepareStackTrace` property. To test whether the current |
| 62 | + // platform implements it, |
| 63 | + // we must set our own and then see if `error.stack` triggers it. |
| 64 | + // If so, then we assume we're on v8, or a platform whose |
| 65 | + // error stack logic is close enough that we can treat it |
| 66 | + // like v8. |
| 67 | + platform = 'v8'; |
| 68 | + } |
| 69 | + }; |
| 70 | + const sacrificialError = new FERAL_ERROR('just for testing'); |
| 71 | + // Intentionally accesses `sacrificialError.stack` only to trigger |
| 72 | + // the test `prepareStackTrace` for platform detection. |
| 73 | + sacrificialError.stack; |
| 74 | + } finally { |
| 75 | + delete FERAL_ERROR.prepareStackTrace; |
| 76 | + } |
| 77 | + } |
| 78 | + } |
43 | 79 |
|
44 | 80 | const makeErrorConstructor = (_ = {}) => { |
45 | 81 | // eslint-disable-next-line no-shadow |
|
0 commit comments