UNPKG

execa

Version:
45 lines (37 loc) 1.76 kB
// When the subprocess fails, this is the error instance being returned. // If another error instance is being thrown, it is kept as `error.cause`. export const getFinalError = (originalError, message, isSync) => { const ErrorClass = isSync ? ExecaSyncError : ExecaError; const options = originalError instanceof DiscardedError ? {} : {cause: originalError}; return new ErrorClass(message, options); }; // Indicates that the error is used only to interrupt control flow, but not in the return value export class DiscardedError extends Error {} // Proper way to set `error.name`: it should be inherited and non-enumerable const setErrorName = (ErrorClass, value) => { Object.defineProperties(ErrorClass.prototype, { name: { value, writable: true, enumerable: false, configurable: true, }, [execaErrorSymbol]: { value: true, writable: false, enumerable: false, configurable: false, }, }); }; // Unlike `instanceof`, this works across realms export const isExecaError = error => isErrorInstance(error) && execaErrorSymbol in error; const execaErrorSymbol = Symbol('isExecaError'); export const isErrorInstance = value => Object.prototype.toString.call(value) === '[object Error]'; // We use two different Error classes for async/sync methods since they have slightly different shape and types export class ExecaError extends Error {} // eslint-disable-next-line unicorn/no-top-level-side-effects -- `error.name` must be set as soon as the class is defined setErrorName(ExecaError, ExecaError.name); export class ExecaSyncError extends Error {} // eslint-disable-next-line unicorn/no-top-level-side-effects -- `error.name` must be set as soon as the class is defined setErrorName(ExecaSyncError, ExecaSyncError.name);