UNPKG

2.28 kBJavaScriptView Raw
1// Cache the generated error records, but let them be garbage collected.
2const errorRecords = new WeakMap();
3const { error: logError } = console;
4
5/**
6 * This function builds an {error, id, loc} tuple from errors. It aids in
7 * production-mode debugging by providing a unique ID to each error, plus a
8 * hint as to the error source location, for a user to report on a support
9 * call.
10 * @param {Error} error The error to create or retrieve a record for.
11 * @param {Window} window Window object, as an argument for testability.
12 * @param {Object} context Context codesite to help make useful stacktraces.
13 * @param {Object} customStack React custom stack trace for render errors.
14 */
15export default function errorRecord(error, window, context, customStack) {
16 const { Date, Math } = window;
17 let record = errorRecords.get(error);
18 if (record) {
19 return record;
20 }
21 record = { error, loc: '' };
22 const { constructor, message, name } = error;
23 // Reasonably unique, yet readable error ID.
24 const seconds = new Date().getSeconds();
25 const randomChar = Math.random()
26 .toString(36)
27 .slice(2, 3)
28 .toUpperCase();
29 record.id =
30 ((constructor && constructor.name) || name) + seconds + randomChar;
31
32 // Add offending line, if possible.
33 let stack;
34 if (customStack) {
35 stack = customStack;
36 } else {
37 /* istanbul ignore next */
38 if (Error.captureStackTrace) {
39 Error.captureStackTrace(error, context);
40 }
41 stack = error.stack;
42 }
43 const messageStart = stack.indexOf(message);
44 if (messageStart > -1) {
45 const traceStart = messageStart + message.length;
46 record.loc = stack
47 .slice(traceStart)
48 .replace(window.location.origin, '')
49 .trim()
50 .split('\n')[0];
51 }
52 errorRecords.set(error, record);
53 // In development mode, React logs these already.
54 // Log in production mode so that users can give Support helpful debug info.
55 /* istanbul ignore next */
56 if (process.env.NODE_ENV === 'production') {
57 logError(
58 `%cUnhandled ${record.id}`,
59 'background: #CC0000; color: white; padding: 0.1em 0.5em',
60 stack
61 );
62 }
63 return record;
64}