Path: blob/main/puppet-chrome/lib/ConsoleMessage.ts
1028 views
/**1* Copyright 2018 Google Inc. All rights reserved.2* Modifications copyright (c) Data Liberation Foundation Inc.3*4* Licensed under the Apache License, Version 2.0 (the "License");5* you may not use this file except in compliance with the License.6* You may obtain a copy of the License at7*8* http://www.apache.org/licenses/LICENSE-2.09*10* Unless required by applicable law or agreed to in writing, software11* distributed under the License is distributed on an "AS IS" BASIS,12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13* See the License for the specific language governing permissions and14* limitations under the License.15*/16import { Protocol } from 'devtools-protocol';17import { DevtoolsSession } from './DevtoolsSession';18import ExceptionDetails = Protocol.Runtime.ExceptionDetails;19import StackTrace = Protocol.Runtime.StackTrace;20import ObjectPreview = Protocol.Runtime.ObjectPreview;21import ConsoleAPICalledEvent = Protocol.Runtime.ConsoleAPICalledEvent;2223export default class ConsoleMessage {24constructor(readonly message: string, readonly location: string, readonly type: string) {}2526static create(devtoolsSession: DevtoolsSession, event: ConsoleAPICalledEvent) {27const { args, stackTrace, type, context } = event;2829const message = args30.map(arg => {31devtoolsSession.disposeRemoteObject(arg);3233return stringifyRemoteObject(arg);34})35.join(' ');3637const location = `//#${context ?? 'nocontext'}${this.printStackTrace(stackTrace)}`;38return new ConsoleMessage(message, location, type);39}4041static exceptionToError(exceptionDetails: ExceptionDetails) {42const error = new Error(exceptionDetails.text);43if (exceptionDetails.exception) {44error.stack = stringifyRemoteObject(exceptionDetails.exception);45} else if (exceptionDetails.stackTrace) {46error.stack = this.printStackTrace(exceptionDetails.stackTrace);47}48return error;49}5051private static printStackTrace(stackTrace: StackTrace) {52let message = '';53if (!stackTrace) return message;54for (const callframe of stackTrace.callFrames) {55const location = `${callframe.url}:${callframe.lineNumber}:${callframe.columnNumber}`;56const functionName = callframe.functionName || '<anonymous>';57message += `\n at ${functionName} (${location})`;58}59return message;60}61}6263function stringifyRemoteObject(remoteObject: Protocol.Runtime.RemoteObject) {64if (remoteObject.unserializableValue) {65if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined') {66return BigInt(remoteObject.unserializableValue.replace('n', ''));67}6869switch (remoteObject.unserializableValue) {70case '-0':71return -0;72case 'NaN':73return NaN;74case 'Infinity':75return Infinity;76case '-Infinity':77return -Infinity;78default:79throw new Error(`Unsupported unserializable value: ${remoteObject.unserializableValue}`);80}81}82if (remoteObject.type === 'object' && remoteObject.preview) {83return JSON.stringify(previewToObject(remoteObject.preview));84}85return remoteObject.value ?? remoteObject.description;86}8788function previewToObject(preview: ObjectPreview) {89const subProps = preview.properties.map(90prop => `${prop.name}: ${prop.valuePreview ? previewToObject(prop.valuePreview) : prop.value}`,91);92const props = `{ ${subProps.join(', ')} }`;93if (preview.description === 'Object') return props;94return `${preview.description}(${props})`;95}969798