diff --git a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js index 8de9a84f326..6df61b51761 100644 --- a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js +++ b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js @@ -13,7 +13,11 @@ import type {StackFrame} from '../../../Core/NativeExceptionsManager'; -const {parseLogBoxException, parseLogBoxLog} = require('../parseLogBoxLog'); +const { + parseLogBoxException, + parseLogBoxLog, + withoutANSIColorStyles, +} = require('../parseLogBoxLog'); describe('parseLogBoxLog', () => { it('parses strings', () => { @@ -1656,3 +1660,36 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, }); }); }); + +describe('withoutANSIColorStyles', () => { + it('works with non-strings', () => { + expect(withoutANSIColorStyles(null)).toEqual(null); + expect(withoutANSIColorStyles(undefined)).toEqual(undefined); + expect(withoutANSIColorStyles({})).toEqual({}); + expect(withoutANSIColorStyles(1)).toEqual(1); + }); + + it('works with empty string', () => { + expect(withoutANSIColorStyles('')).toEqual(''); + }); + + it("doesn't modify string that don't have ANSI escape sequences", () => { + expect( + withoutANSIColorStyles('Warning: this is the React warning %s'), + ).toEqual('Warning: this is the React warning %s'); + }); + + it('filters out ANSI escape sequences and preserves console substitutions', () => { + expect( + withoutANSIColorStyles( + '\x1b[2;38;2;124;124;124mWarning: this is the React warning %s\x1b[0m', + ), + ).toEqual('Warning: this is the React warning %s'); + }); + + it('filters out ANSI escape sequences for string with only console substitutions', () => { + expect( + withoutANSIColorStyles('\x1b[2;38;2;124;124;124m%s %s\x1b[0m'), + ).toEqual('%s %s'); + }); +}); diff --git a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js index af0bb5c2010..a7cca640b0f 100644 --- a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js +++ b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js @@ -435,13 +435,25 @@ export function parseLogBoxException( }; } +export function withoutANSIColorStyles(message: mixed): mixed { + if (typeof message !== 'string') { + return message; + } + + return message.replace( + // eslint-disable-next-line no-control-regex + /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, + '', + ); +} + export function parseLogBoxLog(args: $ReadOnlyArray): {| componentStack: ComponentStack, componentStackType: ComponentStackType, category: Category, message: Message, |} { - const message = args[0]; + const message = withoutANSIColorStyles(args[0]); let argsWithoutComponentStack: Array = []; let componentStack: ComponentStack = []; let componentStackType = 'legacy'; diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 9e224612153..2629df495fa 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -5460,6 +5460,7 @@ declare export function parseComponentStack(message: string): { declare export function parseLogBoxException( error: ExtendedExceptionData ): LogBoxLogData; +declare export function withoutANSIColorStyles(message: mixed): mixed; declare export function parseLogBoxLog(args: $ReadOnlyArray): {| componentStack: ComponentStack, componentStackType: ComponentStackType,