1/* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package escompat; 17 18export class ErrorOptions { 19 cause: Object | undefined = undefined 20 21 constructor(cause: Object | undefined) { 22 this.cause = cause 23 } 24} 25 26/** 27 * Strores information about stacktrace and cause in case of an error. 28 * Serves as a base class for all error classes. 29 */ 30export class Error { 31 cause: Object | undefined 32 message: String 33 name: String 34 private stackLines: StackTraceElement[] = [] 35 private stack_: String | undefined = undefined 36 37 /** 38 * Constructs a new error instance with provided message and cause 39 * 40 * @param message message of the error 41 * 42 * @param options options of the error 43 */ 44 constructor(message?: String, options?: ErrorOptions) { 45 this("Error", message, options) 46 } 47 48 49 /** 50 * Constructs a new error instance with provided message, options and name 51 * 52 * @param name name of the error 53 * 54 * @param message message of the error 55 * 56 * @param options options of the error 57 */ 58 constructor(name: String, message: String | undefined, options: ErrorOptions | undefined) { 59 this.message = (message == undefined) ? "" : message 60 this.cause = (options == undefined) ? undefined : options.cause 61 this.name = name 62 this.stackLines = StackTrace.provisionStackTrace() 63 } 64 65 static invoke(message?: String, options?: ErrorOptions): Error { 66 return new Error(message, options) 67 } 68 69 static invoke(message: String): Error { 70 return new Error(message) 71 } 72 73 /** 74 * Converts this error to a string 75 * Result includes error message and the stacktrace 76 * 77 * @returns result of the conversion 78 */ 79 override toString(): String { 80 if (this.message != "") { 81 return this.name + ": " + this.message; 82 } 83 return this.name; 84 } 85 86 /** 87 * Forms stack and returns it 88 */ 89 get stack(): String | undefined { 90 this.formStack() 91 return this.stack_ 92 } 93 94 /** 95 * Cleans up stack lines 96 */ 97 set stack(newStack: String | undefined) { 98 this.stack_ = newStack 99 this.stackLines = [] 100 } 101 102 /** 103 * Forms stack from this.stackLines and stores it in this.stack_ 104 */ 105 private formStack() { 106 if (this.stack_ != undefined) { 107 return 108 } 109 if (this.stackLines.length == 0) { 110 return 111 } 112 let builder = new StringBuilder("") 113 114 if (this.message != "") { 115 let val = this.name + ": " + this.message + "\n" 116 builder.append(val) 117 } 118 119 // NOTE(kparshukov): find a better way to erase Error's ctors lines 120 const provisionStackTraceLevel = 2 121 const realStackStart = (this.stackLines.length > provisionStackTraceLevel ? provisionStackTraceLevel : 0) 122 for (let i: int = realStackStart; i < this.stackLines.length; i++) { 123 builder.append(this.stackLines[i].toString() + '\n') 124 } 125 126 this.stack_ = builder.toString() 127 this.stackLines = [] 128 } 129} 130