Path: blob/main/extensions/copilot/src/util/vs/base/common/errors.ts
13405 views
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'12/*---------------------------------------------------------------------------------------------3* Copyright (c) Microsoft Corporation. All rights reserved.4* Licensed under the MIT License. See License.txt in the project root for license information.5*--------------------------------------------------------------------------------------------*/67export interface ErrorListenerCallback {8(error: any): void;9}1011export interface ErrorListenerUnbind {12(): void;13}1415// Avoid circular dependency on EventEmitter by implementing a subset of the interface.16export class ErrorHandler {17private unexpectedErrorHandler: (e: any) => void;18private listeners: ErrorListenerCallback[];1920constructor() {2122this.listeners = [];2324this.unexpectedErrorHandler = function (e: any) {25setTimeout(() => {26if (e.stack) {27if (ErrorNoTelemetry.isErrorNoTelemetry(e)) {28throw new ErrorNoTelemetry(e.message + '\n\n' + e.stack);29}3031throw new Error(e.message + '\n\n' + e.stack);32}3334throw e;35}, 0);36};37}3839addListener(listener: ErrorListenerCallback): ErrorListenerUnbind {40this.listeners.push(listener);4142return () => {43this._removeListener(listener);44};45}4647private emit(e: any): void {48this.listeners.forEach((listener) => {49listener(e);50});51}5253private _removeListener(listener: ErrorListenerCallback): void {54this.listeners.splice(this.listeners.indexOf(listener), 1);55}5657setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void {58this.unexpectedErrorHandler = newUnexpectedErrorHandler;59}6061getUnexpectedErrorHandler(): (e: any) => void {62return this.unexpectedErrorHandler;63}6465onUnexpectedError(e: any): void {66this.unexpectedErrorHandler(e);67this.emit(e);68}6970// For external errors, we don't want the listeners to be called71onUnexpectedExternalError(e: any): void {72this.unexpectedErrorHandler(e);73}74}7576export const errorHandler = new ErrorHandler();7778/** @skipMangle */79export function setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void {80errorHandler.setUnexpectedErrorHandler(newUnexpectedErrorHandler);81}8283/**84* Returns if the error is a SIGPIPE error. SIGPIPE errors should generally be85* logged at most once, to avoid a loop.86*87* @see https://github.com/microsoft/vscode-remote-release/issues/648188*/89export function isSigPipeError(e: unknown): e is Error {90if (!e || typeof e !== 'object') {91return false;92}9394const cast = e as Record<string, string | undefined>;95return cast.code === 'EPIPE' && cast.syscall?.toUpperCase() === 'WRITE';96}9798/**99* This function should only be called with errors that indicate a bug in the product.100* E.g. buggy extensions/invalid user-input/network issues should not be able to trigger this code path.101* If they are, this indicates there is also a bug in the product.102*/103export function onBugIndicatingError(e: any): undefined {104errorHandler.onUnexpectedError(e);105return undefined;106}107108export function onUnexpectedError(e: any): undefined {109// ignore errors from cancelled promises110if (!isCancellationError(e)) {111errorHandler.onUnexpectedError(e);112}113return undefined;114}115116export function onUnexpectedExternalError(e: any): undefined {117// ignore errors from cancelled promises118if (!isCancellationError(e)) {119errorHandler.onUnexpectedExternalError(e);120}121return undefined;122}123124export interface SerializedError {125readonly $isError: true;126readonly name: string;127readonly message: string;128readonly stack: string;129readonly noTelemetry: boolean;130readonly code?: string;131readonly cause?: SerializedError;132}133134type ErrorWithCode = Error & {135code: string | undefined;136};137138export function transformErrorForSerialization(error: Error): SerializedError;139export function transformErrorForSerialization(error: any): any;140export function transformErrorForSerialization(error: any): any {141if (error instanceof Error) {142const { name, message, cause } = error;143// eslint-disable-next-line local/code-no-any-casts144const stack: string = (<any>error).stacktrace || (<any>error).stack;145return {146$isError: true,147name,148message,149stack,150noTelemetry: ErrorNoTelemetry.isErrorNoTelemetry(error),151cause: cause ? transformErrorForSerialization(cause) : undefined,152code: (<ErrorWithCode>error).code153};154}155156// return as is157return error;158}159160export function transformErrorFromSerialization(data: SerializedError): Error {161let error: Error;162if (data.noTelemetry) {163error = new ErrorNoTelemetry();164} else {165error = new Error();166error.name = data.name;167}168error.message = data.message;169error.stack = data.stack;170if (data.code) {171(<ErrorWithCode>error).code = data.code;172}173if (data.cause) {174error.cause = transformErrorFromSerialization(data.cause);175}176return error;177}178179// see https://github.com/v8/v8/wiki/Stack%20Trace%20API#basic-stack-traces180export interface V8CallSite {181getThis(): unknown;182getTypeName(): string | null;183getFunction(): Function | undefined;184getFunctionName(): string | null;185getMethodName(): string | null;186getFileName(): string | null;187getLineNumber(): number | null;188getColumnNumber(): number | null;189getEvalOrigin(): string | undefined;190isToplevel(): boolean;191isEval(): boolean;192isNative(): boolean;193isConstructor(): boolean;194toString(): string;195}196197export const canceledName = 'Canceled';198199/**200* Checks if the given error is a promise in canceled state201*/202export function isCancellationError(error: any): boolean {203if (error instanceof CancellationError) {204return true;205}206return error instanceof Error && error.name === canceledName && error.message === canceledName;207}208209// !!!IMPORTANT!!!210// Do NOT change this class because it is also used as an API-type.211export class CancellationError extends Error {212constructor() {213super(canceledName);214this.name = this.message;215}216}217218export class PendingMigrationError extends Error {219220private static readonly _name = 'PendingMigrationError';221222static is(error: unknown): error is PendingMigrationError {223return error instanceof PendingMigrationError || (error instanceof Error && error.name === PendingMigrationError._name);224}225226constructor(message: string) {227super(message);228this.name = PendingMigrationError._name;229}230}231232/**233* @deprecated use {@link CancellationError `new CancellationError()`} instead234*/235export function canceled(): Error {236const error = new Error(canceledName);237error.name = error.message;238return error;239}240241export function illegalArgument(name?: string): Error {242if (name) {243return new Error(`Illegal argument: ${name}`);244} else {245return new Error('Illegal argument');246}247}248249export function illegalState(name?: string): Error {250if (name) {251return new Error(`Illegal state: ${name}`);252} else {253return new Error('Illegal state');254}255}256257export class ReadonlyError extends TypeError {258constructor(name?: string) {259super(name ? `${name} is read-only and cannot be changed` : 'Cannot change read-only property');260}261}262263export function getErrorMessage(err: any): string {264if (!err) {265return 'Error';266}267268if (err.message) {269return err.message;270}271272if (err.stack) {273return err.stack.split('\n')[0];274}275276return String(err);277}278279export class NotImplementedError extends Error {280constructor(message?: string) {281super('NotImplemented');282if (message) {283this.message = message;284}285}286}287288export class NotSupportedError extends Error {289constructor(message?: string) {290super('NotSupported');291if (message) {292this.message = message;293}294}295}296297export class ExpectedError extends Error {298readonly isExpected = true;299}300301/**302* Error that when thrown won't be logged in telemetry as an unhandled error.303*/304export class ErrorNoTelemetry extends Error {305override readonly name: string;306307constructor(msg?: string) {308super(msg);309this.name = 'CodeExpectedError';310}311312public static fromError(err: Error): ErrorNoTelemetry {313if (err instanceof ErrorNoTelemetry) {314return err;315}316317const result = new ErrorNoTelemetry();318result.message = err.message;319result.stack = err.stack;320return result;321}322323public static isErrorNoTelemetry(err: Error): err is ErrorNoTelemetry {324return err.name === 'CodeExpectedError';325}326}327328/**329* This error indicates a bug.330* Do not throw this for invalid user input.331* Only catch this error to recover gracefully from bugs.332*/333export class BugIndicatingError extends Error {334constructor(message?: string) {335super(message || 'An unexpected bug occurred.');336Object.setPrototypeOf(this, BugIndicatingError.prototype);337338// Because we know for sure only buggy code throws this,339// we definitely want to break here and fix the bug.340// debugger;341}342}343344345