{"version":3,"file":"LogSerialization.js","sourceRoot":"","sources":["../../src/logs/LogSerialization.ts"],"names":[],"mappings":"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","sourcesContent":["import Constants from 'expo-constants';\nimport prettyFormat from 'pretty-format';\nimport parseErrorStack, { StackFrame } from 'react-native/Libraries/Core/Devtools/parseErrorStack';\nimport symbolicateStackTrace from 'react-native/Libraries/Core/Devtools/symbolicateStackTrace';\n\nimport { LogData, LogLevel } from './RemoteLogging';\nimport ReactNodeFormatter from './format/ReactNodeFormatter';\n\ntype SerializedData = {\n body: LogData[];\n includesStack: boolean;\n};\n\nexport const EXPO_CONSOLE_METHOD_NAME = '__expoConsoleLog';\n\nasync function serializeLogDataAsync(data: unknown[], level: LogLevel): Promise {\n let serializedValues: readonly LogData[];\n let includesStack = false;\n\n if (_stackTraceLogsSupported()) {\n if (_isUnhandledPromiseRejection(data, level)) {\n const rawStack = data[0] as string;\n const syntheticError = { stack: rawStack };\n const stack = await _symbolicateErrorAsync(syntheticError as Error);\n\n if (!stack.length) {\n serializedValues = _stringifyLogData(data);\n } else {\n // NOTE: This doesn't handle error messages with newlines\n const errorMessage = rawStack.split('\\n')[1];\n serializedValues = [\n {\n message: `[Unhandled promise rejection: ${errorMessage}]`,\n stack: _formatStack(stack),\n },\n ];\n includesStack = true;\n }\n } else if (data.length === 1 && data[0] instanceof Error) {\n // When there's only one argument to the log function and that argument is an error, we\n // include the error's stack. If there's more than one argument then we don't include the\n // stack because it's not easy to display nicely in our current UI.\n\n const serializedError = await _serializeErrorAsync(data[0] as Error);\n serializedValues = [serializedError];\n includesStack = serializedError.hasOwnProperty('stack');\n } else if (level === 'warn' || level === 'error') {\n // For console.warn and console.error it is usually useful to know the stack that leads to the\n // warning or error, so we provide this information to help out with debugging\n\n const error = _captureConsoleStackTrace();\n // [\"hello\", \"world\"] becomes \"hello, world\"\n const errorMessage = _stringifyLogData(data).join(', ');\n\n const serializedError = await _serializeErrorAsync(error, errorMessage);\n serializedValues = [serializedError];\n includesStack = serializedError.hasOwnProperty('stack');\n } else {\n serializedValues = _stringifyLogData(data);\n }\n } else {\n serializedValues = _stringifyLogData(data);\n }\n\n return {\n body: [...serializedValues],\n includesStack,\n };\n}\n\nfunction _stringifyLogData(data: unknown[]): string[] {\n return data.map(item => {\n // define the max length for log msg to be first 10000 characters\n const LOG_MESSAGE_MAX_LENGTH = 10000;\n const result =\n typeof item === 'string' ? item : prettyFormat(item, { plugins: [ReactNodeFormatter] });\n // check the size of string returned\n if (result.length > LOG_MESSAGE_MAX_LENGTH) {\n let truncatedResult = result.substring(0, LOG_MESSAGE_MAX_LENGTH);\n // truncate the result string to the max length\n truncatedResult += `...(truncated to the first ${LOG_MESSAGE_MAX_LENGTH} characters)`;\n return truncatedResult;\n } else {\n return result;\n }\n });\n}\n\nasync function _serializeErrorAsync(error: Error, message?: string): Promise {\n if (message == null) {\n message = error.message;\n }\n\n if (!error.stack || !error.stack.length) {\n return prettyFormat(error);\n }\n\n const stack = await _symbolicateErrorAsync(error);\n const formattedStack = _formatStack(stack);\n\n return { message, stack: formattedStack };\n}\n\nasync function _symbolicateErrorAsync(error: Error): Promise {\n const parsedStack = parseErrorStack(error);\n let symbolicatedStack: StackFrame[] | null;\n try {\n // @ts-ignore: symbolicateStackTrace has different real/Flow declaration\n // than the one in DefinitelyTyped.\n symbolicatedStack = (await symbolicateStackTrace(parsedStack))?.stack ?? null;\n } catch (error) {\n return parsedStack;\n }\n\n // In this context an unsymbolicated stack is better than no stack\n if (!symbolicatedStack) {\n return parsedStack;\n }\n\n // Clean the stack trace\n return symbolicatedStack.map(_removeProjectRoot);\n}\n\nfunction _formatStack(stack: StackFrame[]): string {\n return stack\n .map(frame => {\n let line = `${frame.file}:${frame.lineNumber}`;\n if (frame.column != null) {\n line += `:${frame.column}`;\n }\n line += ` in ${frame.methodName}`;\n return line;\n })\n .join('\\n');\n}\n\nfunction _removeProjectRoot(frame: StackFrame): StackFrame {\n let filename = frame.file;\n if (filename == null) {\n return frame;\n }\n\n const projectRoot = _getProjectRoot();\n if (projectRoot == null) {\n return frame;\n }\n\n if (filename.startsWith(projectRoot)) {\n filename = filename.substring(projectRoot.length);\n if (filename[0] === '/' || filename[0] === '\\\\') {\n filename = filename.substring(1);\n }\n frame.file = filename;\n }\n\n return frame;\n}\n\n/**\n * Returns whether the development server that served this project supports logs with a stack trace.\n * Specifically, the version of Expo CLI that includes `projectRoot` in the manifest also accepts\n * payloads of the form:\n *\n * {\n * includesStack: boolean, body: [{ message: string, stack: string }],\n * }\n */\nfunction _stackTraceLogsSupported(): boolean {\n return !!(__DEV__ && _getProjectRoot());\n}\n\nfunction _isUnhandledPromiseRejection(data: unknown[], level: LogLevel): boolean {\n return (\n level === 'warn' &&\n typeof data[0] === 'string' &&\n /^Possible Unhandled Promise Rejection/.test(data[0] as string)\n );\n}\n\nfunction _captureConsoleStackTrace(): Error {\n try {\n throw new Error();\n } catch (error) {\n let stackLines = error.stack.split('\\n');\n const consoleMethodIndex = stackLines.findIndex(frame =>\n frame.includes(EXPO_CONSOLE_METHOD_NAME)\n );\n if (consoleMethodIndex !== -1) {\n stackLines = stackLines.slice(consoleMethodIndex + 1);\n error.stack = stackLines.join('\\n');\n }\n return error;\n }\n}\n\nfunction _getProjectRoot(): string | null {\n return Constants.manifest?.developer?.projectRoot ?? null;\n}\n\nexport default {\n serializeLogDataAsync,\n};\n"]}