UNPKG

8.09 kBJavaScriptView Raw
1import { __assign } from "tslib";
2import { Severity } from '@sentry/types';
3import { addExceptionMechanism, addExceptionTypeValue, createStackParser, extractExceptionKeysForMessage, isDOMError, isDOMException, isError, isErrorEvent, isEvent, isPlainObject, normalizeToSize, resolvedSyncPromise, } from '@sentry/utils';
4import { chromeStackParser, geckoStackParser, opera10StackParser, opera11StackParser, winjsStackParser, } from './stack-parsers';
5/**
6 * This function creates an exception from an TraceKitStackTrace
7 * @param stacktrace TraceKitStackTrace that will be converted to an exception
8 * @hidden
9 */
10export function exceptionFromError(ex) {
11 // Get the frames first since Opera can lose the stack if we touch anything else first
12 var frames = parseStackFrames(ex);
13 var exception = {
14 type: ex && ex.name,
15 value: extractMessage(ex),
16 };
17 if (frames.length) {
18 exception.stacktrace = { frames: frames };
19 }
20 if (exception.type === undefined && exception.value === '') {
21 exception.value = 'Unrecoverable error caught';
22 }
23 return exception;
24}
25/**
26 * @hidden
27 */
28export function eventFromPlainObject(exception, syntheticException, isUnhandledRejection) {
29 var event = {
30 exception: {
31 values: [
32 {
33 type: isEvent(exception) ? exception.constructor.name : isUnhandledRejection ? 'UnhandledRejection' : 'Error',
34 value: "Non-Error " + (isUnhandledRejection ? 'promise rejection' : 'exception') + " captured with keys: " + extractExceptionKeysForMessage(exception),
35 },
36 ],
37 },
38 extra: {
39 __serialized__: normalizeToSize(exception),
40 },
41 };
42 if (syntheticException) {
43 var frames_1 = parseStackFrames(syntheticException);
44 if (frames_1.length) {
45 event.stacktrace = { frames: frames_1 };
46 }
47 }
48 return event;
49}
50/**
51 * @hidden
52 */
53export function eventFromError(ex) {
54 return {
55 exception: {
56 values: [exceptionFromError(ex)],
57 },
58 };
59}
60/** Parses stack frames from an error */
61export function parseStackFrames(ex) {
62 // Access and store the stacktrace property before doing ANYTHING
63 // else to it because Opera is not very good at providing it
64 // reliably in other circumstances.
65 var stacktrace = ex.stacktrace || ex.stack || '';
66 var popSize = getPopSize(ex);
67 try {
68 return createStackParser(opera10StackParser, opera11StackParser, chromeStackParser, winjsStackParser, geckoStackParser)(stacktrace, popSize);
69 }
70 catch (e) {
71 // no-empty
72 }
73 return [];
74}
75// Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108
76var reactMinifiedRegexp = /Minified React error #\d+;/i;
77function getPopSize(ex) {
78 if (ex) {
79 if (typeof ex.framesToPop === 'number') {
80 return ex.framesToPop;
81 }
82 if (reactMinifiedRegexp.test(ex.message)) {
83 return 1;
84 }
85 }
86 return 0;
87}
88/**
89 * There are cases where stacktrace.message is an Event object
90 * https://github.com/getsentry/sentry-javascript/issues/1949
91 * In this specific case we try to extract stacktrace.message.error.message
92 */
93function extractMessage(ex) {
94 var message = ex && ex.message;
95 if (!message) {
96 return 'No error message';
97 }
98 if (message.error && typeof message.error.message === 'string') {
99 return message.error.message;
100 }
101 return message;
102}
103/**
104 * Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`.
105 * @hidden
106 */
107export function eventFromException(exception, hint, attachStacktrace) {
108 var syntheticException = (hint && hint.syntheticException) || undefined;
109 var event = eventFromUnknownInput(exception, syntheticException, attachStacktrace);
110 addExceptionMechanism(event); // defaults to { type: 'generic', handled: true }
111 event.level = Severity.Error;
112 if (hint && hint.event_id) {
113 event.event_id = hint.event_id;
114 }
115 return resolvedSyncPromise(event);
116}
117/**
118 * Builds and Event from a Message
119 * @hidden
120 */
121export function eventFromMessage(message, level, hint, attachStacktrace) {
122 if (level === void 0) { level = Severity.Info; }
123 var syntheticException = (hint && hint.syntheticException) || undefined;
124 var event = eventFromString(message, syntheticException, attachStacktrace);
125 event.level = level;
126 if (hint && hint.event_id) {
127 event.event_id = hint.event_id;
128 }
129 return resolvedSyncPromise(event);
130}
131/**
132 * @hidden
133 */
134export function eventFromUnknownInput(exception, syntheticException, attachStacktrace, isUnhandledRejection) {
135 var event;
136 if (isErrorEvent(exception) && exception.error) {
137 // If it is an ErrorEvent with `error` property, extract it to get actual Error
138 var errorEvent = exception;
139 return eventFromError(errorEvent.error);
140 }
141 // If it is a `DOMError` (which is a legacy API, but still supported in some browsers) then we just extract the name
142 // and message, as it doesn't provide anything else. According to the spec, all `DOMExceptions` should also be
143 // `Error`s, but that's not the case in IE11, so in that case we treat it the same as we do a `DOMError`.
144 //
145 // https://developer.mozilla.org/en-US/docs/Web/API/DOMError
146 // https://developer.mozilla.org/en-US/docs/Web/API/DOMException
147 // https://webidl.spec.whatwg.org/#es-DOMException-specialness
148 if (isDOMError(exception) || isDOMException(exception)) {
149 var domException = exception;
150 if ('stack' in exception) {
151 event = eventFromError(exception);
152 }
153 else {
154 var name_1 = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException');
155 var message = domException.message ? name_1 + ": " + domException.message : name_1;
156 event = eventFromString(message, syntheticException, attachStacktrace);
157 addExceptionTypeValue(event, message);
158 }
159 if ('code' in domException) {
160 event.tags = __assign(__assign({}, event.tags), { 'DOMException.code': "" + domException.code });
161 }
162 return event;
163 }
164 if (isError(exception)) {
165 // we have a real Error object, do nothing
166 return eventFromError(exception);
167 }
168 if (isPlainObject(exception) || isEvent(exception)) {
169 // If it's a plain object or an instance of `Event` (the built-in JS kind, not this SDK's `Event` type), serialize
170 // it manually. This will allow us to group events based on top-level keys which is much better than creating a new
171 // group on any key/value change.
172 var objectException = exception;
173 event = eventFromPlainObject(objectException, syntheticException, isUnhandledRejection);
174 addExceptionMechanism(event, {
175 synthetic: true,
176 });
177 return event;
178 }
179 // If none of previous checks were valid, then it means that it's not:
180 // - an instance of DOMError
181 // - an instance of DOMException
182 // - an instance of Event
183 // - an instance of Error
184 // - a valid ErrorEvent (one with an error property)
185 // - a plain Object
186 //
187 // So bail out and capture it as a simple message:
188 event = eventFromString(exception, syntheticException, attachStacktrace);
189 addExceptionTypeValue(event, "" + exception, undefined);
190 addExceptionMechanism(event, {
191 synthetic: true,
192 });
193 return event;
194}
195/**
196 * @hidden
197 */
198export function eventFromString(input, syntheticException, attachStacktrace) {
199 var event = {
200 message: input,
201 };
202 if (attachStacktrace && syntheticException) {
203 var frames_2 = parseStackFrames(syntheticException);
204 if (frames_2.length) {
205 event.stacktrace = { frames: frames_2 };
206 }
207 }
208 return event;
209}
210//# sourceMappingURL=eventbuilder.js.map
\No newline at end of file