log_message.ts (2439B)
1 import { ErrorWithExtra } from '../../util/util.js'; 2 import { extractImportantStackTrace } from '../stack.js'; 3 4 import { LogMessageRawData } from './result.js'; 5 6 export class LogMessageWithStack extends Error { 7 readonly extra: unknown; 8 9 private stackHiddenMessage: string | undefined = undefined; 10 11 /** 12 * Wrap an Error (which was created to capture the stack at that point) into a 13 * LogMessageWithStack (which has extra stuff for good log messages). 14 * 15 * The original `ex.name` is ignored. Inclued it in the `name` parameter if it 16 * needs to be preserved. 17 */ 18 static wrapError(name: string, ex: Error | ErrorWithExtra) { 19 return new LogMessageWithStack({ 20 name, 21 message: ex.message, 22 stackHiddenMessage: undefined, 23 stack: ex.stack, 24 extra: 'extra' in ex ? ex.extra : undefined, 25 }); 26 } 27 28 constructor(o: LogMessageRawData) { 29 super(o.message); 30 this.name = o.name; 31 this.stackHiddenMessage = o.stackHiddenMessage; 32 this.stack = o.stack; 33 this.extra = o.extra; 34 } 35 36 /** Set a flag so the stack is not printed in toJSON(). */ 37 setStackHidden(stackHiddenMessage: string) { 38 this.stackHiddenMessage ??= stackHiddenMessage; 39 } 40 41 /** 42 * Print the message for display. 43 * 44 * Note: This is toJSON instead of toString to make it easy to save logs using JSON.stringify. 45 */ 46 toJSON(): string { 47 let m = this.name; 48 if (this.message) m += ': ' + this.message; 49 if (this.stack) { 50 if (this.stackHiddenMessage === undefined) { 51 m += '\n' + extractImportantStackTrace(this); 52 } else if (this.stackHiddenMessage) { 53 m += `\n at (elided: ${this.stackHiddenMessage})`; 54 } 55 } 56 return m; 57 } 58 59 /** 60 * Flatten the message for sending over a message channel. 61 * 62 * Note `extra` may get mangled by postMessage. 63 */ 64 toRawData(): LogMessageRawData { 65 let extra = this.extra; 66 if (extra !== undefined) { 67 extra = JSON.parse(JSON.stringify(extra)); 68 } 69 70 return { 71 name: this.name, 72 message: this.message, 73 stackHiddenMessage: this.stackHiddenMessage, 74 stack: this.stack, 75 extra, 76 }; 77 } 78 } 79 80 /** 81 * Returns a string, nicely indented, for debug logs. 82 * This is used in the cmdline and wpt runtimes. In WPT, it shows up in the `*-actual.txt` file. 83 */ 84 export function prettyPrintLog(log: LogMessageWithStack): string { 85 return ' - ' + log.toJSON().replace(/\n/g, '\n '); 86 }