mirror of
https://github.com/facebook/react-native.git
synced 2024-11-21 22:10:14 +00:00
Prevent LogBox from crashing on long messages (#38005)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/38005 Fixes https://github.com/facebook/react-native/issues/32093 by guarding the expensive `BABEL_CODE_FRAME_ERROR_FORMAT` regex with a cheaper initial scan. (Longer term, we should reduce our reliance on string parsing and propagate more structured errors.) Changelog: [General][Fixed] Prevent LogBox from crashing on very long messages Reviewed By: GijsWeterings Differential Revision: D46892454 fbshipit-source-id: 3afadcdd75969c2589bbb06f47d1c4c1c2690abd
This commit is contained in:
parent
f544376f7c
commit
cd56347dca
14
flow-typed/npm/ansi-regex_v5.x.x.js
vendored
Normal file
14
flow-typed/npm/ansi-regex_v5.x.x.js
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @flow strict
|
||||
* @format
|
||||
*/
|
||||
|
||||
declare module 'ansi-regex' {
|
||||
declare export type Options = {
|
||||
/**
|
||||
* Match only the first ANSI escape.
|
||||
*/
|
||||
+onlyFirst?: boolean,
|
||||
};
|
||||
declare export default function ansiRegex(options?: Options): RegExp;
|
||||
}
|
@ -14,12 +14,38 @@ import type {LogBoxLogData} from './LogBoxLog';
|
||||
import parseErrorStack from '../../Core/Devtools/parseErrorStack';
|
||||
import UTFSequence from '../../UTFSequence';
|
||||
import stringifySafe from '../../Utilities/stringifySafe';
|
||||
import ansiRegex from 'ansi-regex';
|
||||
|
||||
const ANSI_REGEX = ansiRegex().source;
|
||||
|
||||
const BABEL_TRANSFORM_ERROR_FORMAT =
|
||||
/^(?:TransformError )?(?:SyntaxError: |ReferenceError: )(.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/;
|
||||
|
||||
// https://github.com/babel/babel/blob/33dbb85e9e9fe36915273080ecc42aee62ed0ade/packages/babel-code-frame/src/index.ts#L183-L184
|
||||
const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp(
|
||||
[
|
||||
// Beginning of a line (per 'm' flag)
|
||||
'^',
|
||||
// Optional ANSI escapes for colors
|
||||
`(?:${ANSI_REGEX})*`,
|
||||
// Marker
|
||||
'>',
|
||||
// Optional ANSI escapes for colors
|
||||
`(?:${ANSI_REGEX})*`,
|
||||
// Left padding for line number
|
||||
' +',
|
||||
// Line number
|
||||
'[0-9]+',
|
||||
// Gutter
|
||||
' \\|',
|
||||
].join(''),
|
||||
'm',
|
||||
);
|
||||
|
||||
const BABEL_CODE_FRAME_ERROR_FORMAT =
|
||||
// eslint-disable-next-line no-control-regex
|
||||
/^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u;
|
||||
|
||||
const METRO_ERROR_FORMAT =
|
||||
/^(?:InternalError Metro has encountered an error:) (.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/u;
|
||||
|
||||
@ -243,28 +269,32 @@ export function parseLogBoxException(
|
||||
};
|
||||
}
|
||||
|
||||
const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT);
|
||||
// Perform a cheap match first before trying to parse the full message, which
|
||||
// can get expensive for arbitrary input.
|
||||
if (BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) {
|
||||
const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT);
|
||||
|
||||
if (babelCodeFrameError) {
|
||||
// Codeframe errors are thrown from any use of buildCodeFrameError.
|
||||
const [fileName, content, codeFrame] = babelCodeFrameError.slice(1);
|
||||
return {
|
||||
level: 'syntax',
|
||||
stack: [],
|
||||
isComponentError: false,
|
||||
componentStack: [],
|
||||
codeFrame: {
|
||||
fileName,
|
||||
location: null, // We are not given the location.
|
||||
content: codeFrame,
|
||||
},
|
||||
message: {
|
||||
content,
|
||||
substitutions: [],
|
||||
},
|
||||
category: `${fileName}-${1}-${1}`,
|
||||
extraData: error.extraData,
|
||||
};
|
||||
if (babelCodeFrameError) {
|
||||
// Codeframe errors are thrown from any use of buildCodeFrameError.
|
||||
const [fileName, content, codeFrame] = babelCodeFrameError.slice(1);
|
||||
return {
|
||||
level: 'syntax',
|
||||
stack: [],
|
||||
isComponentError: false,
|
||||
componentStack: [],
|
||||
codeFrame: {
|
||||
fileName,
|
||||
location: null, // We are not given the location.
|
||||
content: codeFrame,
|
||||
},
|
||||
message: {
|
||||
content,
|
||||
substitutions: [],
|
||||
},
|
||||
category: `${fileName}-${1}-${1}`,
|
||||
extraData: error.extraData,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (message.match(/^TransformError /)) {
|
||||
|
@ -105,6 +105,7 @@
|
||||
"@react-native/virtualized-lists": "^0.73.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"anser": "^1.4.9",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"deprecated-react-native-prop-types": "4.1.0",
|
||||
"event-target-shim": "^5.0.1",
|
||||
|
Loading…
Reference in New Issue
Block a user