@sentry/browser 6.17.8-beta.0 → 6.17.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/build/bundle.es6.js +192 -264
  2. package/build/bundle.es6.js.map +1 -1
  3. package/build/bundle.es6.min.js +2 -2
  4. package/build/bundle.es6.min.js.map +1 -1
  5. package/build/bundle.js +223 -279
  6. package/build/bundle.js.map +1 -1
  7. package/build/bundle.min.js +2 -2
  8. package/build/bundle.min.js.map +1 -1
  9. package/dist/eventbuilder.d.ts.map +1 -1
  10. package/dist/eventbuilder.js +4 -11
  11. package/dist/eventbuilder.js.map +1 -1
  12. package/dist/integrations/linkederrors.d.ts.map +1 -1
  13. package/dist/integrations/linkederrors.js +1 -3
  14. package/dist/integrations/linkederrors.js.map +1 -1
  15. package/dist/parsers.d.ts +7 -7
  16. package/dist/parsers.d.ts.map +1 -1
  17. package/dist/parsers.js +52 -40
  18. package/dist/parsers.js.map +1 -1
  19. package/dist/stack-parsers.d.ts +7 -0
  20. package/dist/stack-parsers.d.ts.map +1 -0
  21. package/dist/stack-parsers.js +117 -0
  22. package/dist/stack-parsers.js.map +1 -0
  23. package/esm/eventbuilder.d.ts.map +1 -1
  24. package/esm/eventbuilder.js +5 -12
  25. package/esm/eventbuilder.js.map +1 -1
  26. package/esm/integrations/linkederrors.d.ts.map +1 -1
  27. package/esm/integrations/linkederrors.js +2 -4
  28. package/esm/integrations/linkederrors.js.map +1 -1
  29. package/esm/parsers.d.ts +7 -7
  30. package/esm/parsers.d.ts.map +1 -1
  31. package/esm/parsers.js +50 -38
  32. package/esm/parsers.js.map +1 -1
  33. package/esm/stack-parsers.d.ts +7 -0
  34. package/esm/stack-parsers.d.ts.map +1 -0
  35. package/esm/stack-parsers.js +116 -0
  36. package/esm/stack-parsers.js.map +1 -0
  37. package/package.json +4 -4
  38. package/dist/tracekit.d.ts +0 -23
  39. package/dist/tracekit.d.ts.map +0 -1
  40. package/dist/tracekit.js +0 -184
  41. package/dist/tracekit.js.map +0 -1
  42. package/esm/tracekit.d.ts +0 -23
  43. package/esm/tracekit.d.ts.map +0 -1
  44. package/esm/tracekit.js +0 -182
  45. package/esm/tracekit.js.map +0 -1
@@ -1,4 +1,4 @@
1
- /*! @sentry/browser 6.17.8-beta.0 (07f9257) | https://github.com/getsentry/sentry-javascript */
1
+ /*! @sentry/browser 6.17.8 (db493a0) | https://github.com/getsentry/sentry-javascript */
2
2
  var Sentry = (function (exports) {
3
3
  /**
4
4
  * TODO(v7): Remove this enum and replace with SeverityLevel
@@ -49,41 +49,7 @@ var Sentry = (function (exports) {
49
49
  * @returns true if this is a debug build
50
50
  */
51
51
  function isDebugBuild() {
52
- return typeof __SENTRY_NO_DEBUG__ !== 'undefined' && !__SENTRY_BROWSER_BUNDLE__;
53
- }
54
- /**
55
- * Figures out if we're building a browser bundle.
56
- *
57
- * @returns true if this is a browser bundle build.
58
- */
59
- function isBrowserBundle() {
60
- return typeof __SENTRY_BROWSER_BUNDLE__ !== 'undefined' && !!__SENTRY_BROWSER_BUNDLE__;
61
- }
62
-
63
- /**
64
- * NOTE: In order to avoid circular dependencies, if you add a function to this module and it needs to print something,
65
- * you must either a) use `console.log` rather than the logger, or b) put your function elsewhere.
66
- */
67
- /**
68
- * Checks whether we're in the Node.js or Browser environment
69
- *
70
- * @returns Answer to given question
71
- */
72
- function isNodeEnv() {
73
- // explicitly check for browser bundles as those can be optimized statically
74
- // by terser/rollup.
75
- return (!isBrowserBundle() &&
76
- Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]');
77
- }
78
- /**
79
- * Requires a module which is protected against bundler minification.
80
- *
81
- * @param request The module path to resolve
82
- */
83
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
84
- function dynamicRequire(mod, request) {
85
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
86
- return mod.require(request);
52
+ return typeof __SENTRY_NO_DEBUG__ !== 'undefined' && !true;
87
53
  }
88
54
 
89
55
  /**
@@ -97,9 +63,7 @@ var Sentry = (function (exports) {
97
63
  * @returns Global scope object
98
64
  */
99
65
  function getGlobalObject() {
100
- return (isNodeEnv()
101
- ? global
102
- : typeof window !== 'undefined' // eslint-disable-line no-restricted-globals
66
+ return ( typeof window !== 'undefined' // eslint-disable-line no-restricted-globals
103
67
  ? window // eslint-disable-line no-restricted-globals
104
68
  : typeof self !== 'undefined'
105
69
  ? self
@@ -603,6 +567,53 @@ var Sentry = (function (exports) {
603
567
  return [memoize, unmemoize];
604
568
  }
605
569
 
570
+ const STACKTRACE_LIMIT = 50;
571
+ /**
572
+ * Creates a stack parser with the supplied line parsers
573
+ *
574
+ * StackFrames are returned in the correct order for Sentry Exception
575
+ * frames and with Sentry SDK internal frames removed from the top and bottom
576
+ *
577
+ * */
578
+ function createStackParser(...parsers) {
579
+ return (stack, skipFirst = 0) => {
580
+ const frames = [];
581
+ for (const line of stack.split('\n').slice(skipFirst)) {
582
+ for (const parser of parsers) {
583
+ const frame = parser(line);
584
+ if (frame) {
585
+ frames.push(frame);
586
+ break;
587
+ }
588
+ }
589
+ }
590
+ return stripSentryFramesAndReverse(frames);
591
+ };
592
+ }
593
+ /**
594
+ * @hidden
595
+ */
596
+ function stripSentryFramesAndReverse(stack) {
597
+ if (!stack.length) {
598
+ return [];
599
+ }
600
+ let localStack = stack;
601
+ const firstFrameFunction = localStack[0].function || '';
602
+ const lastFrameFunction = localStack[localStack.length - 1].function || '';
603
+ // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
604
+ if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) {
605
+ localStack = localStack.slice(1);
606
+ }
607
+ // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
608
+ if (lastFrameFunction.indexOf('sentryWrapped') !== -1) {
609
+ localStack = localStack.slice(0, -1);
610
+ }
611
+ // The frame where the crash happened, should be the last entry in the array
612
+ return localStack
613
+ .slice(0, STACKTRACE_LIMIT)
614
+ .map(frame => (Object.assign(Object.assign({}, frame), { filename: frame.filename || localStack[0].filename, function: frame.function || '?' })))
615
+ .reverse();
616
+ }
606
617
  const defaultFunctionName = '<anonymous>';
607
618
  /**
608
619
  * Safely extract function name from itself
@@ -1219,7 +1230,7 @@ var Sentry = (function (exports) {
1219
1230
  triggerHandlers('console', { args, level });
1220
1231
  // this fails for some browsers. :(
1221
1232
  if (originalConsoleMethod) {
1222
- originalConsoleMethod.call(global$2.console, args);
1233
+ originalConsoleMethod.apply(global$2.console, args);
1223
1234
  }
1224
1235
  };
1225
1236
  });
@@ -2109,23 +2120,10 @@ var Sentry = (function (exports) {
2109
2120
  timeOrigin,
2110
2121
  };
2111
2122
  }
2112
- /**
2113
- * Returns the native Performance API implementation from Node.js. Returns undefined in old Node.js versions that don't
2114
- * implement the API.
2115
- */
2116
- function getNodePerformance() {
2117
- try {
2118
- const perfHooks = dynamicRequire(module, 'perf_hooks');
2119
- return perfHooks.performance;
2120
- }
2121
- catch (_) {
2122
- return undefined;
2123
- }
2124
- }
2125
2123
  /**
2126
2124
  * The Performance API implementation for the current platform, if available.
2127
2125
  */
2128
- const platformPerformance = isNodeEnv() ? getNodePerformance() : getBrowserPerformance();
2126
+ const platformPerformance = getBrowserPerformance();
2129
2127
  const timestampSource = platformPerformance === undefined
2130
2128
  ? dateTimestampSource
2131
2129
  : {
@@ -3162,38 +3160,9 @@ var Sentry = (function (exports) {
3162
3160
  if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(API_VERSION)) {
3163
3161
  setHubOnCarrier(registry, new Hub());
3164
3162
  }
3165
- // Prefer domains over global if they are there (applicable only to Node environment)
3166
- if (isNodeEnv()) {
3167
- return getHubFromActiveDomain(registry);
3168
- }
3169
3163
  // Return hub that lives on a global object
3170
3164
  return getHubFromCarrier(registry);
3171
3165
  }
3172
- /**
3173
- * Try to read the hub from an active domain, and fallback to the registry if one doesn't exist
3174
- * @returns discovered hub
3175
- */
3176
- function getHubFromActiveDomain(registry) {
3177
- try {
3178
- const sentry = getMainCarrier().__SENTRY__;
3179
- const activeDomain = sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
3180
- // If there's no active domain, just return global hub
3181
- if (!activeDomain) {
3182
- return getHubFromCarrier(registry);
3183
- }
3184
- // If there's no hub on current domain, or it's an old API, assign a new one
3185
- if (!hasHubOnCarrier(activeDomain) || getHubFromCarrier(activeDomain).isOlderThan(API_VERSION)) {
3186
- const registryHubTopStack = getHubFromCarrier(registry).getStackTop();
3187
- setHubOnCarrier(activeDomain, new Hub(registryHubTopStack.client, Scope.clone(registryHubTopStack.scope)));
3188
- }
3189
- // Return hub that lives on a domain
3190
- return getHubFromCarrier(activeDomain);
3191
- }
3192
- catch (_Oo) {
3193
- // Return hub that lives on a global object
3194
- return getHubFromCarrier(registry);
3195
- }
3196
- }
3197
3166
  /**
3198
3167
  * This will tell whether a carrier has a hub on it or not
3199
3168
  * @param carrier object
@@ -3822,6 +3791,11 @@ var Sentry = (function (exports) {
3822
3791
  result = finalScope.applyToEvent(prepared, hint);
3823
3792
  }
3824
3793
  return result.then(evt => {
3794
+ if (evt) {
3795
+ // TODO this is more of the hack trying to solve https://github.com/getsentry/sentry-javascript/issues/2809
3796
+ // it is only attached as extra data to the event if the event somehow skips being normalized
3797
+ evt.sdkProcessingMetadata = Object.assign(Object.assign({}, evt.sdkProcessingMetadata), { normalizeDepth: normalize(normalizeDepth) });
3798
+ }
3825
3799
  if (typeof normalizeDepth === 'number' && normalizeDepth > 0) {
3826
3800
  return this._normalizeEvent(evt, normalizeDepth);
3827
3801
  }
@@ -4166,22 +4140,27 @@ var Sentry = (function (exports) {
4166
4140
  const { transactionSampling } = event.sdkProcessingMetadata || {};
4167
4141
  const { method: samplingMethod, rate: sampleRate } = transactionSampling || {};
4168
4142
  // TODO: Below is a temporary hack in order to debug a serialization error - see
4169
- // https://github.com/getsentry/sentry-javascript/issues/2809 and
4170
- // https://github.com/getsentry/sentry-javascript/pull/4425. TL;DR: even though we normalize all events (which should
4171
- // prevent this), something is causing `JSON.stringify` to throw a circular reference error.
4143
+ // https://github.com/getsentry/sentry-javascript/issues/2809,
4144
+ // https://github.com/getsentry/sentry-javascript/pull/4425, and
4145
+ // https://github.com/getsentry/sentry-javascript/pull/4574.
4146
+ //
4147
+ // TL; DR: even though we normalize all events (which should prevent this), something is causing `JSON.stringify` to
4148
+ // throw a circular reference error.
4172
4149
  //
4173
4150
  // When it's time to remove it:
4174
4151
  // 1. Delete everything between here and where the request object `req` is created, EXCEPT the line deleting
4175
4152
  // `sdkProcessingMetadata`
4176
4153
  // 2. Restore the original version of the request body, which is commented out
4177
- // 3. Search for `skippedNormalization` and pull out the companion hack in the browser playwright tests
4154
+ // 3. Search for either of the PR URLs above and pull out the companion hacks in the browser playwright tests and the
4155
+ // baseClient tests in this package
4178
4156
  enhanceEventWithSdkInfo(event, api.metadata.sdk);
4179
4157
  event.tags = event.tags || {};
4180
4158
  event.extra = event.extra || {};
4181
4159
  // In theory, all events should be marked as having gone through normalization and so
4182
- // we should never set this tag
4160
+ // we should never set this tag/extra data
4183
4161
  if (!(event.sdkProcessingMetadata && event.sdkProcessingMetadata.baseClientNormalized)) {
4184
4162
  event.tags.skippedNormalization = true;
4163
+ event.extra.normalizeDepth = event.sdkProcessingMetadata ? event.sdkProcessingMetadata.normalizeDepth : 'unset';
4185
4164
  }
4186
4165
  // prevent this data from being sent to sentry
4187
4166
  // TODO: This is NOT part of the hack - DO NOT DELETE
@@ -4263,7 +4242,7 @@ var Sentry = (function (exports) {
4263
4242
  hub.bindClient(client);
4264
4243
  }
4265
4244
 
4266
- const SDK_VERSION = '6.17.8-beta.0';
4245
+ const SDK_VERSION = '6.17.8';
4267
4246
 
4268
4247
  let originalFunctionToString;
4269
4248
  /** Patch toString calls to return proper name for wrapped functions */
@@ -4496,127 +4475,87 @@ var Sentry = (function (exports) {
4496
4475
 
4497
4476
  // global reference to slice
4498
4477
  const UNKNOWN_FUNCTION = '?';
4499
- // Chromium based browsers: Chrome, Brave, new Opera, new Edge
4500
- const chrome = /^\s*at (?:(.*?) ?\((?:address at )?)?((?:file|https?|blob|chrome-extension|address|native|eval|webpack|<anonymous>|[-a-z]+:|.*bundle|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
4501
- // gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it
4502
- // generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
4503
- // We need this specific case for now because we want no other regex to match.
4504
- const gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:file|https?|blob|chrome|webpack|resource|moz-extension|capacitor).*?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
4505
- const winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
4506
- const geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
4507
- const chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/;
4508
- // Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108
4509
- const reactMinifiedRegexp = /Minified React error #\d+;/i;
4510
- const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
4511
- const opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
4512
- /** JSDoc */
4513
- function computeStackTrace(ex) {
4514
- let frames = [];
4515
- let popSize = 0;
4516
- if (ex) {
4517
- if (typeof ex.framesToPop === 'number') {
4518
- popSize = ex.framesToPop;
4519
- }
4520
- else if (reactMinifiedRegexp.test(ex.message)) {
4521
- popSize = 1;
4522
- }
4523
- }
4524
- try {
4525
- // Access and store the stacktrace property before doing ANYTHING
4526
- // else to it because Opera is not very good at providing it
4527
- // reliably in other circumstances.
4528
- const stacktrace = ex.stacktrace || ex.stack || '';
4529
- frames = parseFrames(stacktrace);
4530
- }
4531
- catch (e) {
4532
- // no-empty
4478
+ function createFrame(filename, func, lineno, colno) {
4479
+ const frame = {
4480
+ filename,
4481
+ function: func,
4482
+ // All browser frames are considered in_app
4483
+ in_app: true,
4484
+ };
4485
+ if (lineno !== undefined) {
4486
+ frame.lineno = lineno;
4533
4487
  }
4534
- if (frames.length && popSize > 0) {
4535
- frames = frames.slice(popSize);
4488
+ if (colno !== undefined) {
4489
+ frame.colno = colno;
4536
4490
  }
4537
- return {
4538
- message: extractMessage(ex),
4539
- name: ex && ex.name,
4540
- stack: frames,
4541
- };
4491
+ return frame;
4542
4492
  }
4543
- /** JSDoc */
4544
- // eslint-disable-next-line complexity
4545
- function parseFrames(stackString) {
4546
- const frames = [];
4547
- const lines = stackString.split('\n');
4548
- let isEval;
4549
- let submatch;
4550
- let parts;
4551
- let element;
4552
- for (const line of lines) {
4553
- if ((parts = opera10Regex.exec(line))) {
4554
- element = {
4555
- filename: parts[2],
4556
- function: parts[3] || UNKNOWN_FUNCTION,
4557
- lineno: +parts[1],
4558
- };
4559
- }
4560
- else if ((parts = opera11Regex.exec(line))) {
4561
- element = {
4562
- filename: parts[5],
4563
- function: parts[3] || parts[4] || UNKNOWN_FUNCTION,
4564
- lineno: +parts[1],
4565
- colno: +parts[2],
4566
- };
4567
- }
4568
- else if ((parts = chrome.exec(line))) {
4569
- isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
4570
- if (isEval && (submatch = chromeEval.exec(parts[2]))) {
4493
+ // Chromium based browsers: Chrome, Brave, new Opera, new Edge
4494
+ const chromeRegex = /^\s*at (?:(.*?) ?\((?:address at )?)?((?:file|https?|blob|chrome-extension|address|native|eval|webpack|<anonymous>|[-a-z]+:|.*bundle|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
4495
+ const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
4496
+ const chrome = line => {
4497
+ const parts = chromeRegex.exec(line);
4498
+ if (parts) {
4499
+ const isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
4500
+ if (isEval) {
4501
+ const subMatch = chromeEvalRegex.exec(parts[2]);
4502
+ if (subMatch) {
4571
4503
  // throw out eval line/column and use top-most line/column number
4572
- parts[2] = submatch[1]; // url
4573
- parts[3] = submatch[2]; // line
4574
- parts[4] = submatch[3]; // column
4504
+ parts[2] = subMatch[1]; // url
4505
+ parts[3] = subMatch[2]; // line
4506
+ parts[4] = subMatch[3]; // column
4575
4507
  }
4576
- // Kamil: One more hack won't hurt us right? Understanding and adding more rules on top of these regexps right now
4577
- // would be way too time consuming. (TODO: Rewrite whole RegExp to be more readable)
4578
- const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]);
4579
- element = {
4580
- filename,
4581
- function: func,
4582
- lineno: parts[3] ? +parts[3] : undefined,
4583
- colno: parts[4] ? +parts[4] : undefined,
4584
- };
4585
- }
4586
- else if ((parts = winjs.exec(line))) {
4587
- element = {
4588
- filename: parts[2],
4589
- function: parts[1] || UNKNOWN_FUNCTION,
4590
- lineno: +parts[3],
4591
- colno: parts[4] ? +parts[4] : undefined,
4592
- };
4593
4508
  }
4594
- else if ((parts = gecko.exec(line))) {
4595
- isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
4596
- if (isEval && (submatch = geckoEval.exec(parts[3]))) {
4509
+ // Kamil: One more hack won't hurt us right? Understanding and adding more rules on top of these regexps right now
4510
+ // would be way too time consuming. (TODO: Rewrite whole RegExp to be more readable)
4511
+ const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]);
4512
+ return createFrame(filename, func, parts[3] ? +parts[3] : undefined, parts[4] ? +parts[4] : undefined);
4513
+ }
4514
+ return;
4515
+ };
4516
+ // gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it
4517
+ // generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
4518
+ // We need this specific case for now because we want no other regex to match.
4519
+ const geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:file|https?|blob|chrome|webpack|resource|moz-extension|capacitor).*?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
4520
+ const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
4521
+ const gecko = line => {
4522
+ const parts = geckoREgex.exec(line);
4523
+ if (parts) {
4524
+ const isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
4525
+ if (isEval) {
4526
+ const subMatch = geckoEvalRegex.exec(parts[3]);
4527
+ if (subMatch) {
4597
4528
  // throw out eval line/column and use top-most line number
4598
4529
  parts[1] = parts[1] || `eval`;
4599
- parts[3] = submatch[1];
4600
- parts[4] = submatch[2];
4530
+ parts[3] = subMatch[1];
4531
+ parts[4] = subMatch[2];
4601
4532
  parts[5] = ''; // no column when eval
4602
4533
  }
4603
- let filename = parts[3];
4604
- let func = parts[1] || UNKNOWN_FUNCTION;
4605
- [func, filename] = extractSafariExtensionDetails(func, filename);
4606
- element = {
4607
- filename,
4608
- function: func,
4609
- lineno: parts[4] ? +parts[4] : undefined,
4610
- colno: parts[5] ? +parts[5] : undefined,
4611
- };
4612
4534
  }
4613
- else {
4614
- continue;
4615
- }
4616
- frames.push(element);
4535
+ let filename = parts[3];
4536
+ let func = parts[1] || UNKNOWN_FUNCTION;
4537
+ [func, filename] = extractSafariExtensionDetails(func, filename);
4538
+ return createFrame(filename, func, parts[4] ? +parts[4] : undefined, parts[5] ? +parts[5] : undefined);
4617
4539
  }
4618
- return frames;
4619
- }
4540
+ return;
4541
+ };
4542
+ const winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
4543
+ const winjs = line => {
4544
+ const parts = winjsRegex.exec(line);
4545
+ return parts
4546
+ ? createFrame(parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined)
4547
+ : undefined;
4548
+ };
4549
+ const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
4550
+ const opera10 = line => {
4551
+ const parts = opera10Regex.exec(line);
4552
+ return parts ? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1]) : undefined;
4553
+ };
4554
+ const opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
4555
+ const opera11 = line => {
4556
+ const parts = opera11Regex.exec(line);
4557
+ return parts ? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : undefined;
4558
+ };
4620
4559
  /**
4621
4560
  * Safari web extensions, starting version unknown, can produce "frames-only" stacktraces.
4622
4561
  * What it means, is that instead of format like:
@@ -4634,7 +4573,7 @@ var Sentry = (function (exports) {
4634
4573
  *
4635
4574
  * Because of that, it won't be captured by `chrome` RegExp and will fall into `Gecko` branch.
4636
4575
  * This function is extracted so that we can use it in both places without duplicating the logic.
4637
- * Unfortunatelly "just" changing RegExp is too complicated now and making it pass all tests
4576
+ * Unfortunately "just" changing RegExp is too complicated now and making it pass all tests
4638
4577
  * and fix this case seems like an impossible, or at least way too time-consuming task.
4639
4578
  */
4640
4579
  const extractSafariExtensionDetails = (func, filename) => {
@@ -4646,35 +4585,19 @@ var Sentry = (function (exports) {
4646
4585
  isSafariExtension ? `safari-extension:${filename}` : `safari-web-extension:${filename}`,
4647
4586
  ]
4648
4587
  : [func, filename];
4649
- };
4650
- /**
4651
- * There are cases where stacktrace.message is an Event object
4652
- * https://github.com/getsentry/sentry-javascript/issues/1949
4653
- * In this specific case we try to extract stacktrace.message.error.message
4654
- */
4655
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4656
- function extractMessage(ex) {
4657
- const message = ex && ex.message;
4658
- if (!message) {
4659
- return 'No error message';
4660
- }
4661
- if (message.error && typeof message.error.message === 'string') {
4662
- return message.error.message;
4663
- }
4664
- return message;
4665
- }
4588
+ };
4666
4589
 
4667
- const STACKTRACE_LIMIT = 50;
4668
4590
  /**
4669
4591
  * This function creates an exception from an TraceKitStackTrace
4670
4592
  * @param stacktrace TraceKitStackTrace that will be converted to an exception
4671
4593
  * @hidden
4672
4594
  */
4673
- function exceptionFromStacktrace(stacktrace) {
4674
- const frames = prepareFramesForEvent(stacktrace.stack);
4595
+ function exceptionFromError(ex) {
4596
+ // Get the frames first since Opera can lose the stack if we touch anything else first
4597
+ const frames = parseStackFrames(ex);
4675
4598
  const exception = {
4676
- type: stacktrace.name,
4677
- value: stacktrace.message,
4599
+ type: ex && ex.name,
4600
+ value: extractMessage(ex),
4678
4601
  };
4679
4602
  if (frames && frames.length) {
4680
4603
  exception.stacktrace = { frames };
@@ -4702,10 +4625,8 @@ var Sentry = (function (exports) {
4702
4625
  },
4703
4626
  };
4704
4627
  if (syntheticException) {
4705
- const stacktrace = computeStackTrace(syntheticException);
4706
- const frames = prepareFramesForEvent(stacktrace.stack);
4707
4628
  event.stacktrace = {
4708
- frames,
4629
+ frames: parseStackFrames(syntheticException),
4709
4630
  };
4710
4631
  }
4711
4632
  return event;
@@ -4713,43 +4634,57 @@ var Sentry = (function (exports) {
4713
4634
  /**
4714
4635
  * @hidden
4715
4636
  */
4716
- function eventFromStacktrace(stacktrace) {
4717
- const exception = exceptionFromStacktrace(stacktrace);
4637
+ function eventFromError(ex) {
4718
4638
  return {
4719
4639
  exception: {
4720
- values: [exception],
4640
+ values: [exceptionFromError(ex)],
4721
4641
  },
4722
4642
  };
4723
4643
  }
4644
+ /** Parses stack frames from an error */
4645
+ function parseStackFrames(ex) {
4646
+ // Access and store the stacktrace property before doing ANYTHING
4647
+ // else to it because Opera is not very good at providing it
4648
+ // reliably in other circumstances.
4649
+ const stacktrace = ex.stacktrace || ex.stack || '';
4650
+ const popSize = getPopSize(ex);
4651
+ try {
4652
+ // The order of the parsers in important
4653
+ return createStackParser(opera10, opera11, chrome, winjs, gecko)(stacktrace, popSize);
4654
+ }
4655
+ catch (e) {
4656
+ // no-empty
4657
+ }
4658
+ return [];
4659
+ }
4660
+ // Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108
4661
+ const reactMinifiedRegexp = /Minified React error #\d+;/i;
4662
+ function getPopSize(ex) {
4663
+ if (ex) {
4664
+ if (typeof ex.framesToPop === 'number') {
4665
+ return ex.framesToPop;
4666
+ }
4667
+ if (reactMinifiedRegexp.test(ex.message)) {
4668
+ return 1;
4669
+ }
4670
+ }
4671
+ return 0;
4672
+ }
4724
4673
  /**
4725
- * @hidden
4674
+ * There are cases where stacktrace.message is an Event object
4675
+ * https://github.com/getsentry/sentry-javascript/issues/1949
4676
+ * In this specific case we try to extract stacktrace.message.error.message
4726
4677
  */
4727
- function prepareFramesForEvent(stack) {
4728
- if (!stack.length) {
4729
- return [];
4730
- }
4731
- let localStack = stack;
4732
- const firstFrameFunction = localStack[0].function || '';
4733
- const lastFrameFunction = localStack[localStack.length - 1].function || '';
4734
- // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
4735
- if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) {
4736
- localStack = localStack.slice(1);
4678
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4679
+ function extractMessage(ex) {
4680
+ const message = ex && ex.message;
4681
+ if (!message) {
4682
+ return 'No error message';
4737
4683
  }
4738
- // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
4739
- if (lastFrameFunction.indexOf('sentryWrapped') !== -1) {
4740
- localStack = localStack.slice(0, -1);
4684
+ if (message.error && typeof message.error.message === 'string') {
4685
+ return message.error.message;
4741
4686
  }
4742
- // The frame where the crash happened, should be the last entry in the array
4743
- return localStack
4744
- .slice(0, STACKTRACE_LIMIT)
4745
- .map(frame => ({
4746
- filename: frame.filename || localStack[0].filename,
4747
- function: frame.function || '?',
4748
- lineno: frame.lineno,
4749
- colno: frame.colno,
4750
- in_app: true,
4751
- }))
4752
- .reverse();
4687
+ return message;
4753
4688
  }
4754
4689
 
4755
4690
  /**
@@ -4791,10 +4726,7 @@ var Sentry = (function (exports) {
4791
4726
  if (isErrorEvent(exception) && exception.error) {
4792
4727
  // If it is an ErrorEvent with `error` property, extract it to get actual Error
4793
4728
  const errorEvent = exception;
4794
- // eslint-disable-next-line no-param-reassign
4795
- exception = errorEvent.error;
4796
- event = eventFromStacktrace(computeStackTrace(exception));
4797
- return event;
4729
+ return eventFromError(errorEvent.error);
4798
4730
  }
4799
4731
  // If it is a `DOMError` (which is a legacy API, but still supported in some browsers) then we just extract the name
4800
4732
  // and message, as it doesn't provide anything else. According to the spec, all `DOMExceptions` should also be
@@ -4806,7 +4738,7 @@ var Sentry = (function (exports) {
4806
4738
  if (isDOMError(exception) || isDOMException(exception)) {
4807
4739
  const domException = exception;
4808
4740
  if ('stack' in exception) {
4809
- event = eventFromStacktrace(computeStackTrace(exception));
4741
+ event = eventFromError(exception);
4810
4742
  }
4811
4743
  else {
4812
4744
  const name = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException');
@@ -4821,8 +4753,7 @@ var Sentry = (function (exports) {
4821
4753
  }
4822
4754
  if (isError(exception)) {
4823
4755
  // we have a real Error object, do nothing
4824
- event = eventFromStacktrace(computeStackTrace(exception));
4825
- return event;
4756
+ return eventFromError(exception);
4826
4757
  }
4827
4758
  if (isPlainObject(exception) || isEvent(exception)) {
4828
4759
  // If it's a plain object or an instance of `Event` (the built-in JS kind, not this SDK's `Event` type), serialize
@@ -4859,10 +4790,8 @@ var Sentry = (function (exports) {
4859
4790
  message: input,
4860
4791
  };
4861
4792
  if (options.attachStacktrace && syntheticException) {
4862
- const stacktrace = computeStackTrace(syntheticException);
4863
- const frames = prepareFramesForEvent(stacktrace.stack);
4864
4793
  event.stacktrace = {
4865
- frames,
4794
+ frames: parseStackFrames(syntheticException),
4866
4795
  };
4867
4796
  }
4868
4797
  return event;
@@ -6129,8 +6058,7 @@ var Sentry = (function (exports) {
6129
6058
  if (!isInstanceOf(error[key], Error) || stack.length + 1 >= limit) {
6130
6059
  return stack;
6131
6060
  }
6132
- const stacktrace = computeStackTrace(error[key]);
6133
- const exception = exceptionFromStacktrace(stacktrace);
6061
+ const exception = exceptionFromError(error[key]);
6134
6062
  return _walkErrorTree(limit, error[key], key, [exception, ...stack]);
6135
6063
  }
6136
6064