@sentry/browser 6.19.1 → 6.19.4

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 (56) hide show
  1. package/bundles/bundle.debug.min.js +2 -2
  2. package/bundles/bundle.debug.min.js.map +1 -1
  3. package/bundles/bundle.es6.debug.min.js +2 -2
  4. package/bundles/bundle.es6.debug.min.js.map +1 -1
  5. package/bundles/bundle.es6.js +748 -586
  6. package/bundles/bundle.es6.js.map +1 -1
  7. package/bundles/bundle.es6.min.js +2 -2
  8. package/bundles/bundle.es6.min.js.map +1 -1
  9. package/bundles/bundle.js +777 -608
  10. package/bundles/bundle.js.map +1 -1
  11. package/bundles/bundle.min.js +2 -2
  12. package/bundles/bundle.min.js.map +1 -1
  13. package/dist/backend.d.ts.map +1 -1
  14. package/dist/backend.js +8 -0
  15. package/dist/backend.js.map +1 -1
  16. package/dist/eventbuilder.js.map +1 -1
  17. package/dist/transports/base.js +1 -1
  18. package/dist/transports/base.js.map +1 -1
  19. package/dist/transports/index.d.ts +2 -0
  20. package/dist/transports/index.d.ts.map +1 -1
  21. package/dist/transports/index.js +4 -0
  22. package/dist/transports/index.js.map +1 -1
  23. package/dist/transports/new-fetch.d.ts +10 -0
  24. package/dist/transports/new-fetch.d.ts.map +1 -0
  25. package/dist/transports/new-fetch.js +27 -0
  26. package/dist/transports/new-fetch.js.map +1 -0
  27. package/dist/transports/new-xhr.d.ts +11 -0
  28. package/dist/transports/new-xhr.d.ts.map +1 -0
  29. package/dist/transports/new-xhr.js +46 -0
  30. package/dist/transports/new-xhr.js.map +1 -0
  31. package/esm/backend.d.ts.map +1 -1
  32. package/esm/backend.js +10 -2
  33. package/esm/backend.js.map +1 -1
  34. package/esm/eventbuilder.js.map +1 -1
  35. package/esm/transports/base.js +1 -1
  36. package/esm/transports/base.js.map +1 -1
  37. package/esm/transports/index.d.ts +2 -0
  38. package/esm/transports/index.d.ts.map +1 -1
  39. package/esm/transports/index.js +2 -0
  40. package/esm/transports/index.js.map +1 -1
  41. package/esm/transports/new-fetch.d.ts +10 -0
  42. package/esm/transports/new-fetch.d.ts.map +1 -0
  43. package/esm/transports/new-fetch.js +25 -0
  44. package/esm/transports/new-fetch.js.map +1 -0
  45. package/esm/transports/new-xhr.d.ts +11 -0
  46. package/esm/transports/new-xhr.d.ts.map +1 -0
  47. package/esm/transports/new-xhr.js +44 -0
  48. package/esm/transports/new-xhr.js.map +1 -0
  49. package/package.json +8 -8
  50. package/types/backend.d.ts.map +1 -1
  51. package/types/transports/index.d.ts +2 -0
  52. package/types/transports/index.d.ts.map +1 -1
  53. package/types/transports/new-fetch.d.ts +10 -0
  54. package/types/transports/new-fetch.d.ts.map +1 -0
  55. package/types/transports/new-xhr.d.ts +11 -0
  56. package/types/transports/new-xhr.d.ts.map +1 -0
@@ -1,4 +1,4 @@
1
- /*! @sentry/browser 6.19.1 (9268185) | https://github.com/getsentry/sentry-javascript */
1
+ /*! @sentry/browser 6.19.4 (261f2e4) | https://github.com/getsentry/sentry-javascript */
2
2
  var Sentry = (function (exports) {
3
3
 
4
4
  /**
@@ -35,22 +35,6 @@ var Sentry = (function (exports) {
35
35
  });
36
36
  }
37
37
 
38
- /**
39
- * This module exists for optimizations in the build process through rollup and terser. We define some global
40
- * constants, which can be overridden during build. By guarding certain pieces of code with functions that return these
41
- * constants, we can control whether or not they appear in the final bundle. (Any code guarded by a false condition will
42
- * never run, and will hence be dropped during treeshaking.) The two primary uses for this are stripping out calls to
43
- * `logger` and preventing node-related code from appearing in browser bundles.
44
- */
45
- /**
46
- * Figures out if we're building with debug functionality.
47
- *
48
- * @returns true if this is a debug build
49
- */
50
- function isDebugBuild() {
51
- return true;
52
- }
53
-
54
38
  /**
55
39
  * NOTE: In order to avoid circular dependencies, if you add a function to this module and it needs to print something,
56
40
  * you must either a) use `console.log` rather than the logger, or b) put your function elsewhere.
@@ -201,6 +185,16 @@ var Sentry = (function (exports) {
201
185
  function isSyntheticEvent(wat) {
202
186
  return isPlainObject(wat) && 'nativeEvent' in wat && 'preventDefault' in wat && 'stopPropagation' in wat;
203
187
  }
188
+ /**
189
+ * Checks whether given value is NaN
190
+ * {@link isNaN}.
191
+ *
192
+ * @param wat A value to be checked.
193
+ * @returns A boolean representing the result.
194
+ */
195
+ function isNaN$1(wat) {
196
+ return typeof wat === 'number' && wat !== wat;
197
+ }
204
198
  /**
205
199
  * Checks whether given value's type is an instance of provided constructor.
206
200
  * {@link isInstanceOf}.
@@ -525,114 +519,6 @@ var Sentry = (function (exports) {
525
519
  global$6.__SENTRY__ = sentryGlobal;
526
520
  }
527
521
 
528
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
529
- /* eslint-disable @typescript-eslint/no-explicit-any */
530
- /**
531
- * Helper to decycle json objects
532
- */
533
- function memoBuilder() {
534
- const hasWeakSet = typeof WeakSet === 'function';
535
- const inner = hasWeakSet ? new WeakSet() : [];
536
- function memoize(obj) {
537
- if (hasWeakSet) {
538
- if (inner.has(obj)) {
539
- return true;
540
- }
541
- inner.add(obj);
542
- return false;
543
- }
544
- // eslint-disable-next-line @typescript-eslint/prefer-for-of
545
- for (let i = 0; i < inner.length; i++) {
546
- const value = inner[i];
547
- if (value === obj) {
548
- return true;
549
- }
550
- }
551
- inner.push(obj);
552
- return false;
553
- }
554
- function unmemoize(obj) {
555
- if (hasWeakSet) {
556
- inner.delete(obj);
557
- }
558
- else {
559
- for (let i = 0; i < inner.length; i++) {
560
- if (inner[i] === obj) {
561
- inner.splice(i, 1);
562
- break;
563
- }
564
- }
565
- }
566
- }
567
- return [memoize, unmemoize];
568
- }
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
- const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
580
- return (stack, skipFirst = 0) => {
581
- const frames = [];
582
- for (const line of stack.split('\n').slice(skipFirst)) {
583
- for (const parser of sortedParsers) {
584
- const frame = parser(line);
585
- if (frame) {
586
- frames.push(frame);
587
- break;
588
- }
589
- }
590
- }
591
- return stripSentryFramesAndReverse(frames);
592
- };
593
- }
594
- /**
595
- * @hidden
596
- */
597
- function stripSentryFramesAndReverse(stack) {
598
- if (!stack.length) {
599
- return [];
600
- }
601
- let localStack = stack;
602
- const firstFrameFunction = localStack[0].function || '';
603
- const lastFrameFunction = localStack[localStack.length - 1].function || '';
604
- // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
605
- if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) {
606
- localStack = localStack.slice(1);
607
- }
608
- // 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)
609
- if (lastFrameFunction.indexOf('sentryWrapped') !== -1) {
610
- localStack = localStack.slice(0, -1);
611
- }
612
- // The frame where the crash happened, should be the last entry in the array
613
- return localStack
614
- .slice(0, STACKTRACE_LIMIT)
615
- .map(frame => (Object.assign(Object.assign({}, frame), { filename: frame.filename || localStack[0].filename, function: frame.function || '?' })))
616
- .reverse();
617
- }
618
- const defaultFunctionName = '<anonymous>';
619
- /**
620
- * Safely extract function name from itself
621
- */
622
- function getFunctionName(fn) {
623
- try {
624
- if (!fn || typeof fn !== 'function') {
625
- return defaultFunctionName;
626
- }
627
- return fn.name || defaultFunctionName;
628
- }
629
- catch (e) {
630
- // Just accessing custom props in some Selenium environments
631
- // can cause a "Permission denied" exception (see raven-js#495).
632
- return defaultFunctionName;
633
- }
634
- }
635
-
636
522
  /**
637
523
  * Truncates given string to the maximum characters count
638
524
  *
@@ -772,235 +658,38 @@ var Sentry = (function (exports) {
772
658
  *
773
659
  * @param value Initial source that we have to transform in order for it to be usable by the serializer
774
660
  */
775
- function getWalkSource(value) {
661
+ function convertToPlainObject(value) {
662
+ let newObj = value;
776
663
  if (isError(value)) {
777
- const error = value;
778
- const err = {
779
- message: error.message,
780
- name: error.name,
781
- stack: error.stack,
782
- };
783
- for (const i in error) {
784
- if (Object.prototype.hasOwnProperty.call(error, i)) {
785
- err[i] = error[i];
786
- }
787
- }
788
- return err;
664
+ newObj = Object.assign({ message: value.message, name: value.name, stack: value.stack }, getOwnProperties(value));
789
665
  }
790
- if (isEvent(value)) {
666
+ else if (isEvent(value)) {
791
667
  const event = value;
792
- const source = {};
793
- // Accessing event attributes can throw (see https://github.com/getsentry/sentry-javascript/issues/768 and
794
- // https://github.com/getsentry/sentry-javascript/issues/838), but accessing `type` hasn't been wrapped in a
795
- // try-catch in at least two years and no one's complained, so that's likely not an issue anymore
796
- source.type = event.type;
797
- try {
798
- source.target = isElement(event.target)
799
- ? htmlTreeAsString(event.target)
800
- : Object.prototype.toString.call(event.target);
801
- }
802
- catch (_oO) {
803
- source.target = '<unknown>';
804
- }
805
- try {
806
- source.currentTarget = isElement(event.currentTarget)
807
- ? htmlTreeAsString(event.currentTarget)
808
- : Object.prototype.toString.call(event.currentTarget);
809
- }
810
- catch (_oO) {
811
- source.currentTarget = '<unknown>';
812
- }
668
+ newObj = Object.assign({ type: event.type, target: serializeEventTarget(event.target), currentTarget: serializeEventTarget(event.currentTarget) }, getOwnProperties(event));
813
669
  if (typeof CustomEvent !== 'undefined' && isInstanceOf(value, CustomEvent)) {
814
- source.detail = event.detail;
815
- }
816
- for (const attr in event) {
817
- if (Object.prototype.hasOwnProperty.call(event, attr)) {
818
- source[attr] = event[attr];
819
- }
670
+ newObj.detail = event.detail;
820
671
  }
821
- return source;
822
- }
823
- return value;
824
- }
825
- /** Calculates bytes size of input string */
826
- function utf8Length(value) {
827
- // eslint-disable-next-line no-bitwise
828
- return ~-encodeURI(value).split(/%..|./).length;
829
- }
830
- /** Calculates bytes size of input object */
831
- function jsonSize(value) {
832
- return utf8Length(JSON.stringify(value));
833
- }
834
- /** JSDoc */
835
- function normalizeToSize(object,
836
- // Default Node.js REPL depth
837
- depth = 3,
838
- // 100kB, as 200kB is max payload size, so half sounds reasonable
839
- maxSize = 100 * 1024) {
840
- const serialized = normalize(object, depth);
841
- if (jsonSize(serialized) > maxSize) {
842
- return normalizeToSize(object, depth - 1, maxSize);
843
672
  }
844
- return serialized;
673
+ return newObj;
845
674
  }
846
- /**
847
- * Transform any non-primitive, BigInt, or Symbol-type value into a string. Acts as a no-op on strings, numbers,
848
- * booleans, null, and undefined.
849
- *
850
- * @param value The value to stringify
851
- * @returns For non-primitive, BigInt, and Symbol-type values, a string denoting the value's type, type and value, or
852
- * type and `description` property, respectively. For non-BigInt, non-Symbol primitives, returns the original value,
853
- * unchanged.
854
- */
855
- function serializeValue(value) {
856
- // Node.js REPL notation
857
- if (typeof value === 'string') {
858
- return value;
859
- }
860
- const type = Object.prototype.toString.call(value);
861
- if (type === '[object Object]') {
862
- return '[Object]';
863
- }
864
- if (type === '[object Array]') {
865
- return '[Array]';
866
- }
867
- // `makeSerializable` provides a string representation of certain non-serializable values. For all others, it's a
868
- // pass-through.
869
- const serializable = makeSerializable(value);
870
- return isPrimitive(serializable) ? serializable : type;
871
- }
872
- /**
873
- * makeSerializable()
874
- *
875
- * Takes unserializable input and make it serializer-friendly.
876
- *
877
- * Handles globals, functions, `undefined`, `NaN`, and other non-serializable values.
878
- */
879
- function makeSerializable(value, key) {
880
- if (key === 'domain' && value && typeof value === 'object' && value._events) {
881
- return '[Domain]';
882
- }
883
- if (key === 'domainEmitter') {
884
- return '[DomainEmitter]';
885
- }
886
- if (typeof global !== 'undefined' && value === global) {
887
- return '[Global]';
888
- }
889
- // It's safe to use `window` and `document` here in this manner, as we are asserting using `typeof` first
890
- // which won't throw if they are not present.
891
- // eslint-disable-next-line no-restricted-globals
892
- if (typeof window !== 'undefined' && value === window) {
893
- return '[Window]';
894
- }
895
- // eslint-disable-next-line no-restricted-globals
896
- if (typeof document !== 'undefined' && value === document) {
897
- return '[Document]';
898
- }
899
- // React's SyntheticEvent thingy
900
- if (isSyntheticEvent(value)) {
901
- return '[SyntheticEvent]';
902
- }
903
- if (typeof value === 'number' && value !== value) {
904
- return '[NaN]';
905
- }
906
- if (value === void 0) {
907
- return '[undefined]';
908
- }
909
- if (typeof value === 'function') {
910
- return `[Function: ${getFunctionName(value)}]`;
911
- }
912
- // symbols and bigints are considered primitives by TS, but aren't natively JSON-serilaizable
913
- if (typeof value === 'symbol') {
914
- return `[${String(value)}]`;
675
+ /** Creates a string representation of the target of an `Event` object */
676
+ function serializeEventTarget(target) {
677
+ try {
678
+ return isElement(target) ? htmlTreeAsString(target) : Object.prototype.toString.call(target);
915
679
  }
916
- if (typeof value === 'bigint') {
917
- return `[BigInt: ${String(value)}]`;
680
+ catch (_oO) {
681
+ return '<unknown>';
918
682
  }
919
- return value;
920
683
  }
921
- /**
922
- * Walks an object to perform a normalization on it
923
- *
924
- * @param key of object that's walked in current iteration
925
- * @param value object to be walked
926
- * @param depth Optional number indicating how deep should walking be performed
927
- * @param maxProperties Optional maximum number of properties/elements included in any single object/array
928
- * @param memo Optional Memo class handling decycling
929
- */
930
- function walk(key, value, depth = +Infinity, maxProperties = +Infinity, memo = memoBuilder()) {
931
- const [memoize, unmemoize] = memo;
932
- // If we reach the maximum depth, serialize whatever is left
933
- if (depth === 0) {
934
- return serializeValue(value);
935
- }
936
- // If value implements `toJSON` method, call it and return early
937
- if (value !== null && value !== undefined && typeof value.toJSON === 'function') {
938
- return value.toJSON();
939
- }
940
- // `makeSerializable` provides a string representation of certain non-serializable values. For all others, it's a
941
- // pass-through. If what comes back is a primitive (either because it's been stringified or because it was primitive
942
- // all along), we're done.
943
- const serializable = makeSerializable(value, key);
944
- if (isPrimitive(serializable)) {
945
- return serializable;
946
- }
947
- // Create source that we will use for the next iteration. It will either be an objectified error object (`Error` type
948
- // with extracted key:value pairs) or the input itself.
949
- const source = getWalkSource(value);
950
- // Create an accumulator that will act as a parent for all future itterations of that branch
951
- const acc = Array.isArray(value) ? [] : {};
952
- // If we already walked that branch, bail out, as it's circular reference
953
- if (memoize(value)) {
954
- return '[Circular ~]';
955
- }
956
- let propertyCount = 0;
957
- // Walk all keys of the source
958
- for (const innerKey in source) {
959
- // Avoid iterating over fields in the prototype if they've somehow been exposed to enumeration.
960
- if (!Object.prototype.hasOwnProperty.call(source, innerKey)) {
961
- continue;
684
+ /** Filters out all but an object's own properties */
685
+ function getOwnProperties(obj) {
686
+ const extractedProps = {};
687
+ for (const property in obj) {
688
+ if (Object.prototype.hasOwnProperty.call(obj, property)) {
689
+ extractedProps[property] = obj[property];
962
690
  }
963
- if (propertyCount >= maxProperties) {
964
- acc[innerKey] = '[MaxProperties ~]';
965
- break;
966
- }
967
- propertyCount += 1;
968
- // Recursively walk through all the child nodes
969
- const innerValue = source[innerKey];
970
- acc[innerKey] = walk(innerKey, innerValue, depth - 1, maxProperties, memo);
971
- }
972
- // Once walked through all the branches, remove the parent from memo storage
973
- unmemoize(value);
974
- // Return accumulated values
975
- return acc;
976
- }
977
- /**
978
- * Recursively normalizes the given object.
979
- *
980
- * - Creates a copy to prevent original input mutation
981
- * - Skips non-enumerable properties
982
- * - When stringifying, calls `toJSON` if implemented
983
- * - Removes circular references
984
- * - Translates non-serializable values (`undefined`/`NaN`/functions) to serializable format
985
- * - Translates known global objects/classes to a string representations
986
- * - Takes care of `Error` object serialization
987
- * - Optionally limits depth of final output
988
- * - Optionally limits number of properties/elements included in any single object/array
989
- *
990
- * @param input The object to be normalized.
991
- * @param depth The max depth to which to normalize the object. (Anything deeper stringified whole.)
992
- * @param maxProperties The max number of elements or properties to be included in any single array or
993
- * object in the normallized output..
994
- * @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
995
- */
996
- function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
997
- try {
998
- // since we're at the outermost level, there is no key
999
- return walk('', input, depth, maxProperties);
1000
- }
1001
- catch (_oO) {
1002
- return '**non-serializable**';
1003
691
  }
692
+ return extractedProps;
1004
693
  }
1005
694
  /**
1006
695
  * Given any captured exception, extract its keys and create a sorted
@@ -1009,7 +698,7 @@ var Sentry = (function (exports) {
1009
698
  */
1010
699
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
1011
700
  function extractExceptionKeysForMessage(exception, maxLength = 40) {
1012
- const keys = Object.keys(getWalkSource(exception));
701
+ const keys = Object.keys(convertToPlainObject(exception));
1013
702
  keys.sort();
1014
703
  if (!keys.length) {
1015
704
  return '[object has no keys]';
@@ -1027,27 +716,92 @@ var Sentry = (function (exports) {
1027
716
  }
1028
717
  return truncate(serialized, maxLength);
1029
718
  }
1030
- return '';
719
+ return '';
720
+ }
721
+ /**
722
+ * Given any object, return the new object with removed keys that value was `undefined`.
723
+ * Works recursively on objects and arrays.
724
+ */
725
+ function dropUndefinedKeys(val) {
726
+ if (isPlainObject(val)) {
727
+ const rv = {};
728
+ for (const key of Object.keys(val)) {
729
+ if (typeof val[key] !== 'undefined') {
730
+ rv[key] = dropUndefinedKeys(val[key]);
731
+ }
732
+ }
733
+ return rv;
734
+ }
735
+ if (Array.isArray(val)) {
736
+ return val.map(dropUndefinedKeys);
737
+ }
738
+ return val;
739
+ }
740
+
741
+ const STACKTRACE_LIMIT = 50;
742
+ /**
743
+ * Creates a stack parser with the supplied line parsers
744
+ *
745
+ * StackFrames are returned in the correct order for Sentry Exception
746
+ * frames and with Sentry SDK internal frames removed from the top and bottom
747
+ *
748
+ */
749
+ function createStackParser(...parsers) {
750
+ const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
751
+ return (stack, skipFirst = 0) => {
752
+ const frames = [];
753
+ for (const line of stack.split('\n').slice(skipFirst)) {
754
+ for (const parser of sortedParsers) {
755
+ const frame = parser(line);
756
+ if (frame) {
757
+ frames.push(frame);
758
+ break;
759
+ }
760
+ }
761
+ }
762
+ return stripSentryFramesAndReverse(frames);
763
+ };
764
+ }
765
+ /**
766
+ * @hidden
767
+ */
768
+ function stripSentryFramesAndReverse(stack) {
769
+ if (!stack.length) {
770
+ return [];
771
+ }
772
+ let localStack = stack;
773
+ const firstFrameFunction = localStack[0].function || '';
774
+ const lastFrameFunction = localStack[localStack.length - 1].function || '';
775
+ // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
776
+ if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) {
777
+ localStack = localStack.slice(1);
778
+ }
779
+ // 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)
780
+ if (lastFrameFunction.indexOf('sentryWrapped') !== -1) {
781
+ localStack = localStack.slice(0, -1);
782
+ }
783
+ // The frame where the crash happened, should be the last entry in the array
784
+ return localStack
785
+ .slice(0, STACKTRACE_LIMIT)
786
+ .map(frame => (Object.assign(Object.assign({}, frame), { filename: frame.filename || localStack[0].filename, function: frame.function || '?' })))
787
+ .reverse();
1031
788
  }
789
+ const defaultFunctionName = '<anonymous>';
1032
790
  /**
1033
- * Given any object, return the new object with removed keys that value was `undefined`.
1034
- * Works recursively on objects and arrays.
791
+ * Safely extract function name from itself
1035
792
  */
1036
- function dropUndefinedKeys(val) {
1037
- if (isPlainObject(val)) {
1038
- const obj = val;
1039
- const rv = {};
1040
- for (const key of Object.keys(obj)) {
1041
- if (typeof obj[key] !== 'undefined') {
1042
- rv[key] = dropUndefinedKeys(obj[key]);
1043
- }
793
+ function getFunctionName(fn) {
794
+ try {
795
+ if (!fn || typeof fn !== 'function') {
796
+ return defaultFunctionName;
1044
797
  }
1045
- return rv;
798
+ return fn.name || defaultFunctionName;
1046
799
  }
1047
- if (Array.isArray(val)) {
1048
- return val.map(dropUndefinedKeys);
800
+ catch (e) {
801
+ // Just accessing custom props in some Selenium environments
802
+ // can cause a "Permission denied" exception (see raven-js#495).
803
+ return defaultFunctionName;
1049
804
  }
1050
- return val;
1051
805
  }
1052
806
 
1053
807
  /**
@@ -1632,6 +1386,48 @@ var Sentry = (function (exports) {
1632
1386
  };
1633
1387
  }
1634
1388
 
1389
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
1390
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1391
+ /**
1392
+ * Helper to decycle json objects
1393
+ */
1394
+ function memoBuilder() {
1395
+ const hasWeakSet = typeof WeakSet === 'function';
1396
+ const inner = hasWeakSet ? new WeakSet() : [];
1397
+ function memoize(obj) {
1398
+ if (hasWeakSet) {
1399
+ if (inner.has(obj)) {
1400
+ return true;
1401
+ }
1402
+ inner.add(obj);
1403
+ return false;
1404
+ }
1405
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
1406
+ for (let i = 0; i < inner.length; i++) {
1407
+ const value = inner[i];
1408
+ if (value === obj) {
1409
+ return true;
1410
+ }
1411
+ }
1412
+ inner.push(obj);
1413
+ return false;
1414
+ }
1415
+ function unmemoize(obj) {
1416
+ if (hasWeakSet) {
1417
+ inner.delete(obj);
1418
+ }
1419
+ else {
1420
+ for (let i = 0; i < inner.length; i++) {
1421
+ if (inner[i] === obj) {
1422
+ inner.splice(i, 1);
1423
+ break;
1424
+ }
1425
+ }
1426
+ }
1427
+ }
1428
+ return [memoize, unmemoize];
1429
+ }
1430
+
1635
1431
  /**
1636
1432
  * UUID4 generator
1637
1433
  *
@@ -1789,6 +1585,187 @@ var Sentry = (function (exports) {
1789
1585
  return false;
1790
1586
  }
1791
1587
 
1588
+ /**
1589
+ * Recursively normalizes the given object.
1590
+ *
1591
+ * - Creates a copy to prevent original input mutation
1592
+ * - Skips non-enumerable properties
1593
+ * - When stringifying, calls `toJSON` if implemented
1594
+ * - Removes circular references
1595
+ * - Translates non-serializable values (`undefined`/`NaN`/functions) to serializable format
1596
+ * - Translates known global objects/classes to a string representations
1597
+ * - Takes care of `Error` object serialization
1598
+ * - Optionally limits depth of final output
1599
+ * - Optionally limits number of properties/elements included in any single object/array
1600
+ *
1601
+ * @param input The object to be normalized.
1602
+ * @param depth The max depth to which to normalize the object. (Anything deeper stringified whole.)
1603
+ * @param maxProperties The max number of elements or properties to be included in any single array or
1604
+ * object in the normallized output..
1605
+ * @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
1606
+ */
1607
+ function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
1608
+ try {
1609
+ // since we're at the outermost level, there is no key
1610
+ return visit('', input, depth, maxProperties);
1611
+ }
1612
+ catch (err) {
1613
+ return { ERROR: `**non-serializable** (${err})` };
1614
+ }
1615
+ }
1616
+ /** JSDoc */
1617
+ function normalizeToSize(object,
1618
+ // Default Node.js REPL depth
1619
+ depth = 3,
1620
+ // 100kB, as 200kB is max payload size, so half sounds reasonable
1621
+ maxSize = 100 * 1024) {
1622
+ const normalized = normalize(object, depth);
1623
+ if (jsonSize(normalized) > maxSize) {
1624
+ return normalizeToSize(object, depth - 1, maxSize);
1625
+ }
1626
+ return normalized;
1627
+ }
1628
+ /**
1629
+ * Visits a node to perform normalization on it
1630
+ *
1631
+ * @param key The key corresponding to the given node
1632
+ * @param value The node to be visited
1633
+ * @param depth Optional number indicating the maximum recursion depth
1634
+ * @param maxProperties Optional maximum number of properties/elements included in any single object/array
1635
+ * @param memo Optional Memo class handling decycling
1636
+ */
1637
+ function visit(key, value, depth = +Infinity, maxProperties = +Infinity, memo = memoBuilder()) {
1638
+ const [memoize, unmemoize] = memo;
1639
+ // If the value has a `toJSON` method, see if we can bail and let it do the work
1640
+ const valueWithToJSON = value;
1641
+ if (valueWithToJSON && typeof valueWithToJSON.toJSON === 'function') {
1642
+ try {
1643
+ return valueWithToJSON.toJSON();
1644
+ }
1645
+ catch (err) {
1646
+ // pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
1647
+ }
1648
+ }
1649
+ // Get the simple cases out of the way first
1650
+ if (value === null || (['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))) {
1651
+ return value;
1652
+ }
1653
+ const stringified = stringifyValue(key, value);
1654
+ // Anything we could potentially dig into more (objects or arrays) will have come back as `"[object XXXX]"`.
1655
+ // Everything else will have already been serialized, so if we don't see that pattern, we're done.
1656
+ if (!stringified.startsWith('[object ')) {
1657
+ return stringified;
1658
+ }
1659
+ // We're also done if we've reached the max depth
1660
+ if (depth === 0) {
1661
+ // At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
1662
+ return stringified.replace('object ', '');
1663
+ }
1664
+ // If we've already visited this branch, bail out, as it's circular reference. If not, note that we're seeing it now.
1665
+ if (memoize(value)) {
1666
+ return '[Circular ~]';
1667
+ }
1668
+ // At this point we know we either have an object or an array, we haven't seen it before, and we're going to recurse
1669
+ // because we haven't yet reached the max depth. Create an accumulator to hold the results of visiting each
1670
+ // property/entry, and keep track of the number of items we add to it.
1671
+ const normalized = (Array.isArray(value) ? [] : {});
1672
+ let numAdded = 0;
1673
+ // Before we begin, convert`Error` and`Event` instances into plain objects, since some of each of their relevant
1674
+ // properties are non-enumerable and otherwise would get missed.
1675
+ const visitable = (isError(value) || isEvent(value) ? convertToPlainObject(value) : value);
1676
+ for (const visitKey in visitable) {
1677
+ // Avoid iterating over fields in the prototype if they've somehow been exposed to enumeration.
1678
+ if (!Object.prototype.hasOwnProperty.call(visitable, visitKey)) {
1679
+ continue;
1680
+ }
1681
+ if (numAdded >= maxProperties) {
1682
+ normalized[visitKey] = '[MaxProperties ~]';
1683
+ break;
1684
+ }
1685
+ // Recursively visit all the child nodes
1686
+ const visitValue = visitable[visitKey];
1687
+ normalized[visitKey] = visit(visitKey, visitValue, depth - 1, maxProperties, memo);
1688
+ numAdded += 1;
1689
+ }
1690
+ // Once we've visited all the branches, remove the parent from memo storage
1691
+ unmemoize(value);
1692
+ // Return accumulated values
1693
+ return normalized;
1694
+ }
1695
+ /**
1696
+ * Stringify the given value. Handles various known special values and types.
1697
+ *
1698
+ * Not meant to be used on simple primitives which already have a string representation, as it will, for example, turn
1699
+ * the number 1231 into "[Object Number]", nor on `null`, as it will throw.
1700
+ *
1701
+ * @param value The value to stringify
1702
+ * @returns A stringified representation of the given value
1703
+ */
1704
+ function stringifyValue(key,
1705
+ // this type is a tiny bit of a cheat, since this function does handle NaN (which is technically a number), but for
1706
+ // our internal use, it'll do
1707
+ value) {
1708
+ try {
1709
+ if (key === 'domain' && value && typeof value === 'object' && value._events) {
1710
+ return '[Domain]';
1711
+ }
1712
+ if (key === 'domainEmitter') {
1713
+ return '[DomainEmitter]';
1714
+ }
1715
+ // It's safe to use `global`, `window`, and `document` here in this manner, as we are asserting using `typeof` first
1716
+ // which won't throw if they are not present.
1717
+ if (typeof global !== 'undefined' && value === global) {
1718
+ return '[Global]';
1719
+ }
1720
+ // eslint-disable-next-line no-restricted-globals
1721
+ if (typeof window !== 'undefined' && value === window) {
1722
+ return '[Window]';
1723
+ }
1724
+ // eslint-disable-next-line no-restricted-globals
1725
+ if (typeof document !== 'undefined' && value === document) {
1726
+ return '[Document]';
1727
+ }
1728
+ // React's SyntheticEvent thingy
1729
+ if (isSyntheticEvent(value)) {
1730
+ return '[SyntheticEvent]';
1731
+ }
1732
+ if (typeof value === 'number' && value !== value) {
1733
+ return '[NaN]';
1734
+ }
1735
+ // this catches `undefined` (but not `null`, which is a primitive and can be serialized on its own)
1736
+ if (value === void 0) {
1737
+ return '[undefined]';
1738
+ }
1739
+ if (typeof value === 'function') {
1740
+ return `[Function: ${getFunctionName(value)}]`;
1741
+ }
1742
+ if (typeof value === 'symbol') {
1743
+ return `[${String(value)}]`;
1744
+ }
1745
+ // stringified BigInts are indistinguishable from regular numbers, so we need to label them to avoid confusion
1746
+ if (typeof value === 'bigint') {
1747
+ return `[BigInt: ${String(value)}]`;
1748
+ }
1749
+ // Now that we've knocked out all the special cases and the primitives, all we have left are objects. Simply casting
1750
+ // them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
1751
+ // `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
1752
+ // we can make sure that only plain objects come out that way.
1753
+ return `[object ${Object.getPrototypeOf(value).constructor.name}]`;
1754
+ }
1755
+ catch (err) {
1756
+ return `**non-serializable** (${err})`;
1757
+ }
1758
+ }
1759
+ /** Calculates bytes size of input string */
1760
+ function utf8Length(value) {
1761
+ // eslint-disable-next-line no-bitwise
1762
+ return ~-encodeURI(value).split(/%..|./).length;
1763
+ }
1764
+ /** Calculates bytes size of input object */
1765
+ function jsonSize(value) {
1766
+ return utf8Length(JSON.stringify(value));
1767
+ }
1768
+
1792
1769
  /* eslint-disable @typescript-eslint/explicit-function-return-type */
1793
1770
  /**
1794
1771
  * Creates a resolved sync promise.
@@ -2189,6 +2166,13 @@ var Sentry = (function (exports) {
2189
2166
  function createEnvelope(headers, items = []) {
2190
2167
  return [headers, items];
2191
2168
  }
2169
+ /**
2170
+ * Get the type of the envelope. Grabs the type from the first envelope item.
2171
+ */
2172
+ function getEnvelopeType(envelope) {
2173
+ const [, [[firstItemHeader]]] = envelope;
2174
+ return firstItemHeader.type;
2175
+ }
2192
2176
  /**
2193
2177
  * Serializes an envelope into a string.
2194
2178
  */
@@ -3931,7 +3915,7 @@ var Sentry = (function (exports) {
3931
3915
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
3932
3916
  normalized.contexts.trace = event.contexts.trace;
3933
3917
  }
3934
- event.sdkProcessingMetadata = Object.assign(Object.assign({}, event.sdkProcessingMetadata), { baseClientNormalized: true });
3918
+ normalized.sdkProcessingMetadata = Object.assign(Object.assign({}, normalized.sdkProcessingMetadata), { baseClientNormalized: true });
3935
3919
  return normalized;
3936
3920
  }
3937
3921
  /**
@@ -4102,85 +4086,6 @@ var Sentry = (function (exports) {
4102
4086
  return rv;
4103
4087
  }
4104
4088
 
4105
- /** Noop transport */
4106
- class NoopTransport {
4107
- /**
4108
- * @inheritDoc
4109
- */
4110
- sendEvent(_) {
4111
- return resolvedSyncPromise({
4112
- reason: 'NoopTransport: Event has been skipped because no Dsn is configured.',
4113
- status: 'skipped',
4114
- });
4115
- }
4116
- /**
4117
- * @inheritDoc
4118
- */
4119
- close(_) {
4120
- return resolvedSyncPromise(true);
4121
- }
4122
- }
4123
-
4124
- /**
4125
- * This is the base implemention of a Backend.
4126
- * @hidden
4127
- */
4128
- class BaseBackend {
4129
- /** Creates a new backend instance. */
4130
- constructor(options) {
4131
- this._options = options;
4132
- if (!this._options.dsn) {
4133
- logger.warn('No DSN provided, backend will not do anything.');
4134
- }
4135
- this._transport = this._setupTransport();
4136
- }
4137
- /**
4138
- * @inheritDoc
4139
- */
4140
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
4141
- eventFromException(_exception, _hint) {
4142
- throw new SentryError('Backend has to implement `eventFromException` method');
4143
- }
4144
- /**
4145
- * @inheritDoc
4146
- */
4147
- eventFromMessage(_message, _level, _hint) {
4148
- throw new SentryError('Backend has to implement `eventFromMessage` method');
4149
- }
4150
- /**
4151
- * @inheritDoc
4152
- */
4153
- sendEvent(event) {
4154
- void this._transport.sendEvent(event).then(null, reason => {
4155
- logger.error('Error while sending event:', reason);
4156
- });
4157
- }
4158
- /**
4159
- * @inheritDoc
4160
- */
4161
- sendSession(session) {
4162
- if (!this._transport.sendSession) {
4163
- logger.warn("Dropping session because custom transport doesn't implement sendSession");
4164
- return;
4165
- }
4166
- void this._transport.sendSession(session).then(null, reason => {
4167
- logger.error('Error while sending session:', reason);
4168
- });
4169
- }
4170
- /**
4171
- * @inheritDoc
4172
- */
4173
- getTransport() {
4174
- return this._transport;
4175
- }
4176
- /**
4177
- * Sets up the transport so it can be used later to send requests.
4178
- */
4179
- _setupTransport() {
4180
- return new NoopTransport();
4181
- }
4182
- }
4183
-
4184
4089
  /** Extract sdk info from from the API metadata */
4185
4090
  function getSdkMetadataForEnvelopeHeader(api) {
4186
4091
  if (!api.metadata || !api.metadata.sdk) {
@@ -4204,8 +4109,8 @@ var Sentry = (function (exports) {
4204
4109
  event.sdk.packages = [...(event.sdk.packages || []), ...(sdkInfo.packages || [])];
4205
4110
  return event;
4206
4111
  }
4207
- /** Creates a SentryRequest from a Session. */
4208
- function sessionToSentryRequest(session, api) {
4112
+ /** Creates an envelope from a Session */
4113
+ function createSessionEnvelope(session, api) {
4209
4114
  const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
4210
4115
  const envelopeHeaders = Object.assign(Object.assign({ sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!api.tunnel && { dsn: dsnToString(api.dsn) }));
4211
4116
  // I know this is hacky but we don't want to add `sessions` to request type since it's never rate limited
@@ -4213,12 +4118,62 @@ var Sentry = (function (exports) {
4213
4118
  // TODO (v7) Have to cast type because envelope items do not accept a `SentryRequestType`
4214
4119
  const envelopeItem = [{ type }, session];
4215
4120
  const envelope = createEnvelope(envelopeHeaders, [envelopeItem]);
4121
+ return [envelope, type];
4122
+ }
4123
+ /** Creates a SentryRequest from a Session. */
4124
+ function sessionToSentryRequest(session, api) {
4125
+ const [envelope, type] = createSessionEnvelope(session, api);
4216
4126
  return {
4217
4127
  body: serializeEnvelope(envelope),
4218
4128
  type,
4219
4129
  url: getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel),
4220
4130
  };
4221
4131
  }
4132
+ /**
4133
+ * Create an Envelope from an event. Note that this is duplicated from below,
4134
+ * but on purpose as this will be refactored in v7.
4135
+ */
4136
+ function createEventEnvelope(event, api) {
4137
+ const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
4138
+ const eventType = event.type || 'event';
4139
+ const { transactionSampling } = event.sdkProcessingMetadata || {};
4140
+ const { method: samplingMethod, rate: sampleRate } = transactionSampling || {};
4141
+ // TODO: Below is a temporary hack in order to debug a serialization error - see
4142
+ // https://github.com/getsentry/sentry-javascript/issues/2809,
4143
+ // https://github.com/getsentry/sentry-javascript/pull/4425, and
4144
+ // https://github.com/getsentry/sentry-javascript/pull/4574.
4145
+ //
4146
+ // TL; DR: even though we normalize all events (which should prevent this), something is causing `JSON.stringify` to
4147
+ // throw a circular reference error.
4148
+ //
4149
+ // When it's time to remove it:
4150
+ // 1. Delete everything between here and where the request object `req` is created, EXCEPT the line deleting
4151
+ // `sdkProcessingMetadata`
4152
+ // 2. Restore the original version of the request body, which is commented out
4153
+ // 3. Search for either of the PR URLs above and pull out the companion hacks in the browser playwright tests and the
4154
+ // baseClient tests in this package
4155
+ enhanceEventWithSdkInfo(event, api.metadata.sdk);
4156
+ event.tags = event.tags || {};
4157
+ event.extra = event.extra || {};
4158
+ // In theory, all events should be marked as having gone through normalization and so
4159
+ // we should never set this tag/extra data
4160
+ if (!(event.sdkProcessingMetadata && event.sdkProcessingMetadata.baseClientNormalized)) {
4161
+ event.tags.skippedNormalization = true;
4162
+ event.extra.normalizeDepth = event.sdkProcessingMetadata ? event.sdkProcessingMetadata.normalizeDepth : 'unset';
4163
+ }
4164
+ // prevent this data from being sent to sentry
4165
+ // TODO: This is NOT part of the hack - DO NOT DELETE
4166
+ delete event.sdkProcessingMetadata;
4167
+ const envelopeHeaders = Object.assign(Object.assign({ event_id: event.event_id, sent_at: new Date().toISOString() }, (sdkInfo && { sdk: sdkInfo })), (!!api.tunnel && { dsn: dsnToString(api.dsn) }));
4168
+ const eventItem = [
4169
+ {
4170
+ type: eventType,
4171
+ sample_rates: [{ id: samplingMethod, rate: sampleRate }],
4172
+ },
4173
+ event,
4174
+ ];
4175
+ return createEnvelope(envelopeHeaders, [eventItem]);
4176
+ }
4222
4177
  /** Creates a SentryRequest from an event. */
4223
4178
  function eventToSentryRequest(event, api) {
4224
4179
  const sdkInfo = getSdkMetadataForEnvelopeHeader(api);
@@ -4306,6 +4261,111 @@ var Sentry = (function (exports) {
4306
4261
  return req;
4307
4262
  }
4308
4263
 
4264
+ /** Noop transport */
4265
+ class NoopTransport {
4266
+ /**
4267
+ * @inheritDoc
4268
+ */
4269
+ sendEvent(_) {
4270
+ return resolvedSyncPromise({
4271
+ reason: 'NoopTransport: Event has been skipped because no Dsn is configured.',
4272
+ status: 'skipped',
4273
+ });
4274
+ }
4275
+ /**
4276
+ * @inheritDoc
4277
+ */
4278
+ close(_) {
4279
+ return resolvedSyncPromise(true);
4280
+ }
4281
+ }
4282
+
4283
+ /**
4284
+ * This is the base implemention of a Backend.
4285
+ * @hidden
4286
+ */
4287
+ class BaseBackend {
4288
+ /** Creates a new backend instance. */
4289
+ constructor(options) {
4290
+ this._options = options;
4291
+ if (!this._options.dsn) {
4292
+ logger.warn('No DSN provided, backend will not do anything.');
4293
+ }
4294
+ this._transport = this._setupTransport();
4295
+ }
4296
+ /**
4297
+ * @inheritDoc
4298
+ */
4299
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
4300
+ eventFromException(_exception, _hint) {
4301
+ throw new SentryError('Backend has to implement `eventFromException` method');
4302
+ }
4303
+ /**
4304
+ * @inheritDoc
4305
+ */
4306
+ eventFromMessage(_message, _level, _hint) {
4307
+ throw new SentryError('Backend has to implement `eventFromMessage` method');
4308
+ }
4309
+ /**
4310
+ * @inheritDoc
4311
+ */
4312
+ sendEvent(event) {
4313
+ // TODO(v7): Remove the if-else
4314
+ if (this._newTransport &&
4315
+ this._options.dsn &&
4316
+ this._options._experiments &&
4317
+ this._options._experiments.newTransport) {
4318
+ const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel);
4319
+ const env = createEventEnvelope(event, api);
4320
+ void this._newTransport.send(env).then(null, reason => {
4321
+ logger.error('Error while sending event:', reason);
4322
+ });
4323
+ }
4324
+ else {
4325
+ void this._transport.sendEvent(event).then(null, reason => {
4326
+ logger.error('Error while sending event:', reason);
4327
+ });
4328
+ }
4329
+ }
4330
+ /**
4331
+ * @inheritDoc
4332
+ */
4333
+ sendSession(session) {
4334
+ if (!this._transport.sendSession) {
4335
+ logger.warn("Dropping session because custom transport doesn't implement sendSession");
4336
+ return;
4337
+ }
4338
+ // TODO(v7): Remove the if-else
4339
+ if (this._newTransport &&
4340
+ this._options.dsn &&
4341
+ this._options._experiments &&
4342
+ this._options._experiments.newTransport) {
4343
+ const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel);
4344
+ const [env] = createSessionEnvelope(session, api);
4345
+ void this._newTransport.send(env).then(null, reason => {
4346
+ logger.error('Error while sending session:', reason);
4347
+ });
4348
+ }
4349
+ else {
4350
+ void this._transport.sendSession(session).then(null, reason => {
4351
+ logger.error('Error while sending session:', reason);
4352
+ });
4353
+ }
4354
+ }
4355
+ /**
4356
+ * @inheritDoc
4357
+ */
4358
+ getTransport() {
4359
+ return this._transport;
4360
+ }
4361
+ /**
4362
+ * Sets up the transport so it can be used later to send requests.
4363
+ */
4364
+ _setupTransport() {
4365
+ return new NoopTransport();
4366
+ }
4367
+ }
4368
+
4309
4369
  /**
4310
4370
  * Internal function to create a new SDK client instance. The client is
4311
4371
  * installed and then bound to the current scope.
@@ -4328,7 +4388,57 @@ var Sentry = (function (exports) {
4328
4388
  hub.bindClient(client);
4329
4389
  }
4330
4390
 
4331
- const SDK_VERSION = '6.19.1';
4391
+ const DEFAULT_TRANSPORT_BUFFER_SIZE = 30;
4392
+ /**
4393
+ * Creates a `NewTransport`
4394
+ *
4395
+ * @param options
4396
+ * @param makeRequest
4397
+ */
4398
+ function createTransport(options, makeRequest, buffer = makePromiseBuffer(options.bufferSize || DEFAULT_TRANSPORT_BUFFER_SIZE)) {
4399
+ let rateLimits = {};
4400
+ const flush = (timeout) => buffer.drain(timeout);
4401
+ function send(envelope) {
4402
+ const envCategory = getEnvelopeType(envelope);
4403
+ const category = envCategory === 'event' ? 'error' : envCategory;
4404
+ const request = {
4405
+ category,
4406
+ body: serializeEnvelope(envelope),
4407
+ };
4408
+ // Don't add to buffer if transport is already rate-limited
4409
+ if (isRateLimited(rateLimits, category)) {
4410
+ return rejectedSyncPromise({
4411
+ status: 'rate_limit',
4412
+ reason: getRateLimitReason(rateLimits, category),
4413
+ });
4414
+ }
4415
+ const requestTask = () => makeRequest(request).then(({ body, headers, reason, statusCode }) => {
4416
+ const status = eventStatusFromHttpCode(statusCode);
4417
+ if (headers) {
4418
+ rateLimits = updateRateLimits(rateLimits, headers);
4419
+ }
4420
+ if (status === 'success') {
4421
+ return resolvedSyncPromise({ status, reason });
4422
+ }
4423
+ return rejectedSyncPromise({
4424
+ status,
4425
+ reason: reason ||
4426
+ body ||
4427
+ (status === 'rate_limit' ? getRateLimitReason(rateLimits, category) : 'Unknown transport error'),
4428
+ });
4429
+ });
4430
+ return buffer.add(requestTask);
4431
+ }
4432
+ return {
4433
+ send,
4434
+ flush,
4435
+ };
4436
+ }
4437
+ function getRateLimitReason(rateLimits, category) {
4438
+ return `Too many ${category} requests, backing off until: ${new Date(disabledUntil(rateLimits, category)).toISOString()}`;
4439
+ }
4440
+
4441
+ const SDK_VERSION = '6.19.4';
4332
4442
 
4333
4443
  let originalFunctionToString;
4334
4444
  /** Patch toString calls to return proper name for wrapped functions */
@@ -4372,172 +4482,151 @@ var Sentry = (function (exports) {
4372
4482
  /**
4373
4483
  * @inheritDoc
4374
4484
  */
4375
- setupOnce() {
4485
+ setupOnce(addGlobalEventProcessor, getCurrentHub) {
4376
4486
  addGlobalEventProcessor((event) => {
4377
4487
  const hub = getCurrentHub();
4378
- if (!hub) {
4379
- return event;
4380
- }
4381
- const self = hub.getIntegration(InboundFilters);
4382
- if (self) {
4383
- const client = hub.getClient();
4384
- const clientOptions = client ? client.getOptions() : {};
4385
- // This checks prevents most of the occurrences of the bug linked below:
4386
- // https://github.com/getsentry/sentry-javascript/issues/2622
4387
- // The bug is caused by multiple SDK instances, where one is minified and one is using non-mangled code.
4388
- // Unfortunatelly we cannot fix it reliably (thus reserved property in rollup's terser config),
4389
- // as we cannot force people using multiple instances in their apps to sync SDK versions.
4390
- const options = typeof self._mergeOptions === 'function' ? self._mergeOptions(clientOptions) : {};
4391
- if (typeof self._shouldDropEvent !== 'function') {
4392
- return event;
4488
+ if (hub) {
4489
+ const self = hub.getIntegration(InboundFilters);
4490
+ if (self) {
4491
+ const client = hub.getClient();
4492
+ const clientOptions = client ? client.getOptions() : {};
4493
+ const options = _mergeOptions(self._options, clientOptions);
4494
+ return _shouldDropEvent$1(event, options) ? null : event;
4393
4495
  }
4394
- return self._shouldDropEvent(event, options) ? null : event;
4395
4496
  }
4396
4497
  return event;
4397
4498
  });
4398
4499
  }
4399
- /** JSDoc */
4400
- _shouldDropEvent(event, options) {
4401
- if (this._isSentryError(event, options)) {
4402
- logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
4403
- return true;
4404
- }
4405
- if (this._isIgnoredError(event, options)) {
4406
- logger.warn(`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`);
4407
- return true;
4408
- }
4409
- if (this._isDeniedUrl(event, options)) {
4410
- logger.warn(`Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${this._getEventFilterUrl(event)}`);
4411
- return true;
4412
- }
4413
- if (!this._isAllowedUrl(event, options)) {
4414
- logger.warn(`Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${this._getEventFilterUrl(event)}`);
4415
- return true;
4416
- }
4500
+ }
4501
+ /**
4502
+ * @inheritDoc
4503
+ */
4504
+ InboundFilters.id = 'InboundFilters';
4505
+ /** JSDoc */
4506
+ function _mergeOptions(internalOptions = {}, clientOptions = {}) {
4507
+ return {
4508
+ allowUrls: [
4509
+ // eslint-disable-next-line deprecation/deprecation
4510
+ ...(internalOptions.whitelistUrls || []),
4511
+ ...(internalOptions.allowUrls || []),
4512
+ // eslint-disable-next-line deprecation/deprecation
4513
+ ...(clientOptions.whitelistUrls || []),
4514
+ ...(clientOptions.allowUrls || []),
4515
+ ],
4516
+ denyUrls: [
4517
+ // eslint-disable-next-line deprecation/deprecation
4518
+ ...(internalOptions.blacklistUrls || []),
4519
+ ...(internalOptions.denyUrls || []),
4520
+ // eslint-disable-next-line deprecation/deprecation
4521
+ ...(clientOptions.blacklistUrls || []),
4522
+ ...(clientOptions.denyUrls || []),
4523
+ ],
4524
+ ignoreErrors: [
4525
+ ...(internalOptions.ignoreErrors || []),
4526
+ ...(clientOptions.ignoreErrors || []),
4527
+ ...DEFAULT_IGNORE_ERRORS,
4528
+ ],
4529
+ ignoreInternal: internalOptions.ignoreInternal !== undefined ? internalOptions.ignoreInternal : true,
4530
+ };
4531
+ }
4532
+ /** JSDoc */
4533
+ function _shouldDropEvent$1(event, options) {
4534
+ if (options.ignoreInternal && _isSentryError(event)) {
4535
+ logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
4536
+ return true;
4537
+ }
4538
+ if (_isIgnoredError(event, options.ignoreErrors)) {
4539
+ logger.warn(`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`);
4540
+ return true;
4541
+ }
4542
+ if (_isDeniedUrl(event, options.denyUrls)) {
4543
+ logger.warn(`Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${_getEventFilterUrl(event)}`);
4544
+ return true;
4545
+ }
4546
+ if (!_isAllowedUrl(event, options.allowUrls)) {
4547
+ logger.warn(`Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription(event)}.\nUrl: ${_getEventFilterUrl(event)}`);
4548
+ return true;
4549
+ }
4550
+ return false;
4551
+ }
4552
+ function _isIgnoredError(event, ignoreErrors) {
4553
+ if (!ignoreErrors || !ignoreErrors.length) {
4417
4554
  return false;
4418
4555
  }
4419
- /** JSDoc */
4420
- _isSentryError(event, options) {
4421
- if (!options.ignoreInternal) {
4422
- return false;
4423
- }
4424
- try {
4425
- // @ts-ignore can't be a sentry error if undefined
4426
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4427
- return event.exception.values[0].type === 'SentryError';
4428
- }
4429
- catch (e) {
4430
- // ignore
4431
- }
4556
+ return _getPossibleEventMessages(event).some(message => ignoreErrors.some(pattern => isMatchingPattern(message, pattern)));
4557
+ }
4558
+ function _isDeniedUrl(event, denyUrls) {
4559
+ // TODO: Use Glob instead?
4560
+ if (!denyUrls || !denyUrls.length) {
4432
4561
  return false;
4433
4562
  }
4434
- /** JSDoc */
4435
- _isIgnoredError(event, options) {
4436
- if (!options.ignoreErrors || !options.ignoreErrors.length) {
4437
- return false;
4438
- }
4439
- return this._getPossibleEventMessages(event).some(message =>
4440
- // Not sure why TypeScript complains here...
4441
- options.ignoreErrors.some(pattern => isMatchingPattern(message, pattern)));
4563
+ const url = _getEventFilterUrl(event);
4564
+ return !url ? false : denyUrls.some(pattern => isMatchingPattern(url, pattern));
4565
+ }
4566
+ function _isAllowedUrl(event, allowUrls) {
4567
+ // TODO: Use Glob instead?
4568
+ if (!allowUrls || !allowUrls.length) {
4569
+ return true;
4442
4570
  }
4443
- /** JSDoc */
4444
- _isDeniedUrl(event, options) {
4445
- // TODO: Use Glob instead?
4446
- if (!options.denyUrls || !options.denyUrls.length) {
4447
- return false;
4448
- }
4449
- const url = this._getEventFilterUrl(event);
4450
- return !url ? false : options.denyUrls.some(pattern => isMatchingPattern(url, pattern));
4571
+ const url = _getEventFilterUrl(event);
4572
+ return !url ? true : allowUrls.some(pattern => isMatchingPattern(url, pattern));
4573
+ }
4574
+ function _getPossibleEventMessages(event) {
4575
+ if (event.message) {
4576
+ return [event.message];
4451
4577
  }
4452
- /** JSDoc */
4453
- _isAllowedUrl(event, options) {
4454
- // TODO: Use Glob instead?
4455
- if (!options.allowUrls || !options.allowUrls.length) {
4456
- return true;
4578
+ if (event.exception) {
4579
+ try {
4580
+ const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
4581
+ return [`${value}`, `${type}: ${value}`];
4582
+ }
4583
+ catch (oO) {
4584
+ logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
4585
+ return [];
4457
4586
  }
4458
- const url = this._getEventFilterUrl(event);
4459
- return !url ? true : options.allowUrls.some(pattern => isMatchingPattern(url, pattern));
4460
4587
  }
4461
- /** JSDoc */
4462
- _mergeOptions(clientOptions = {}) {
4463
- return {
4464
- allowUrls: [
4465
- // eslint-disable-next-line deprecation/deprecation
4466
- ...(this._options.whitelistUrls || []),
4467
- ...(this._options.allowUrls || []),
4468
- // eslint-disable-next-line deprecation/deprecation
4469
- ...(clientOptions.whitelistUrls || []),
4470
- ...(clientOptions.allowUrls || []),
4471
- ],
4472
- denyUrls: [
4473
- // eslint-disable-next-line deprecation/deprecation
4474
- ...(this._options.blacklistUrls || []),
4475
- ...(this._options.denyUrls || []),
4476
- // eslint-disable-next-line deprecation/deprecation
4477
- ...(clientOptions.blacklistUrls || []),
4478
- ...(clientOptions.denyUrls || []),
4479
- ],
4480
- ignoreErrors: [
4481
- ...(this._options.ignoreErrors || []),
4482
- ...(clientOptions.ignoreErrors || []),
4483
- ...DEFAULT_IGNORE_ERRORS,
4484
- ],
4485
- ignoreInternal: typeof this._options.ignoreInternal !== 'undefined' ? this._options.ignoreInternal : true,
4486
- };
4588
+ return [];
4589
+ }
4590
+ function _isSentryError(event) {
4591
+ try {
4592
+ // @ts-ignore can't be a sentry error if undefined
4593
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4594
+ return event.exception.values[0].type === 'SentryError';
4487
4595
  }
4488
- /** JSDoc */
4489
- _getPossibleEventMessages(event) {
4490
- if (event.message) {
4491
- return [event.message];
4492
- }
4493
- if (event.exception) {
4494
- try {
4495
- const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
4496
- return [`${value}`, `${type}: ${value}`];
4497
- }
4498
- catch (oO) {
4499
- logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
4500
- return [];
4501
- }
4502
- }
4503
- return [];
4596
+ catch (e) {
4597
+ // ignore
4504
4598
  }
4505
- /** JSDoc */
4506
- _getLastValidUrl(frames = []) {
4507
- for (let i = frames.length - 1; i >= 0; i--) {
4508
- const frame = frames[i];
4509
- if (frame && frame.filename !== '<anonymous>' && frame.filename !== '[native code]') {
4510
- return frame.filename || null;
4511
- }
4599
+ return false;
4600
+ }
4601
+ function _getLastValidUrl(frames = []) {
4602
+ for (let i = frames.length - 1; i >= 0; i--) {
4603
+ const frame = frames[i];
4604
+ if (frame && frame.filename !== '<anonymous>' && frame.filename !== '[native code]') {
4605
+ return frame.filename || null;
4512
4606
  }
4513
- return null;
4514
4607
  }
4515
- /** JSDoc */
4516
- _getEventFilterUrl(event) {
4608
+ return null;
4609
+ }
4610
+ function _getEventFilterUrl(event) {
4611
+ try {
4612
+ if (event.stacktrace) {
4613
+ return _getLastValidUrl(event.stacktrace.frames);
4614
+ }
4615
+ let frames;
4517
4616
  try {
4518
- if (event.stacktrace) {
4519
- return this._getLastValidUrl(event.stacktrace.frames);
4520
- }
4521
- let frames;
4522
- try {
4523
- // @ts-ignore we only care about frames if the whole thing here is defined
4524
- frames = event.exception.values[0].stacktrace.frames;
4525
- }
4526
- catch (e) {
4527
- // ignore
4528
- }
4529
- return frames ? this._getLastValidUrl(frames) : null;
4617
+ // @ts-ignore we only care about frames if the whole thing here is defined
4618
+ frames = event.exception.values[0].stacktrace.frames;
4530
4619
  }
4531
- catch (oO) {
4532
- logger.error(`Cannot extract url for event ${getEventDescription(event)}`);
4533
- return null;
4620
+ catch (e) {
4621
+ // ignore
4534
4622
  }
4623
+ return frames ? _getLastValidUrl(frames) : null;
4535
4624
  }
4536
- }
4537
- /**
4538
- * @inheritDoc
4539
- */
4540
- InboundFilters.id = 'InboundFilters';
4625
+ catch (oO) {
4626
+ logger.error(`Cannot extract url for event ${getEventDescription(event)}`);
4627
+ return null;
4628
+ }
4629
+ }
4541
4630
 
4542
4631
  var CoreIntegrations = /*#__PURE__*/Object.freeze({
4543
4632
  __proto__: null,
@@ -5069,7 +5158,7 @@ var Sentry = (function (exports) {
5069
5158
  const status = eventStatusFromHttpCode(response.status);
5070
5159
  this._rateLimits = updateRateLimits(this._rateLimits, headers);
5071
5160
  // eslint-disable-next-line deprecation/deprecation
5072
- if (this._isRateLimited(requestType) && isDebugBuild()) {
5161
+ if (this._isRateLimited(requestType)) {
5073
5162
  // eslint-disable-next-line deprecation/deprecation
5074
5163
  logger.warn(`Too many ${requestType} requests, backing off until: ${this._disabledUntil(requestType)}`);
5075
5164
  }
@@ -5218,11 +5307,76 @@ var Sentry = (function (exports) {
5218
5307
  }
5219
5308
  }
5220
5309
 
5310
+ /**
5311
+ * Creates a Transport that uses the Fetch API to send events to Sentry.
5312
+ */
5313
+ function makeNewFetchTransport(options, nativeFetch = getNativeFetchImplementation()) {
5314
+ function makeRequest(request) {
5315
+ const requestOptions = Object.assign({ body: request.body, method: 'POST', referrerPolicy: 'origin' }, options.requestOptions);
5316
+ return nativeFetch(options.url, requestOptions).then(response => {
5317
+ return response.text().then(body => ({
5318
+ body,
5319
+ headers: {
5320
+ 'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'),
5321
+ 'retry-after': response.headers.get('Retry-After'),
5322
+ },
5323
+ reason: response.statusText,
5324
+ statusCode: response.status,
5325
+ }));
5326
+ });
5327
+ }
5328
+ return createTransport({ bufferSize: options.bufferSize }, makeRequest);
5329
+ }
5330
+
5331
+ /**
5332
+ * The DONE ready state for XmlHttpRequest
5333
+ *
5334
+ * Defining it here as a constant b/c XMLHttpRequest.DONE is not always defined
5335
+ * (e.g. during testing, it is `undefined`)
5336
+ *
5337
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState}
5338
+ */
5339
+ const XHR_READYSTATE_DONE = 4;
5340
+ /**
5341
+ * Creates a Transport that uses the XMLHttpRequest API to send events to Sentry.
5342
+ */
5343
+ function makeNewXHRTransport(options) {
5344
+ function makeRequest(request) {
5345
+ return new SyncPromise((resolve, _reject) => {
5346
+ const xhr = new XMLHttpRequest();
5347
+ xhr.onreadystatechange = () => {
5348
+ if (xhr.readyState === XHR_READYSTATE_DONE) {
5349
+ const response = {
5350
+ body: xhr.response,
5351
+ headers: {
5352
+ 'x-sentry-rate-limits': xhr.getResponseHeader('X-Sentry-Rate-Limits'),
5353
+ 'retry-after': xhr.getResponseHeader('Retry-After'),
5354
+ },
5355
+ reason: xhr.statusText,
5356
+ statusCode: xhr.status,
5357
+ };
5358
+ resolve(response);
5359
+ }
5360
+ };
5361
+ xhr.open('POST', options.url);
5362
+ for (const header in options.headers) {
5363
+ if (Object.prototype.hasOwnProperty.call(options.headers, header)) {
5364
+ xhr.setRequestHeader(header, options.headers[header]);
5365
+ }
5366
+ }
5367
+ xhr.send(request.body);
5368
+ });
5369
+ }
5370
+ return createTransport({ bufferSize: options.bufferSize }, makeRequest);
5371
+ }
5372
+
5221
5373
  var index = /*#__PURE__*/Object.freeze({
5222
5374
  __proto__: null,
5223
5375
  BaseTransport: BaseTransport,
5224
5376
  FetchTransport: FetchTransport,
5225
- XHRTransport: XHRTransport
5377
+ XHRTransport: XHRTransport,
5378
+ makeNewFetchTransport: makeNewFetchTransport,
5379
+ makeNewXHRTransport: makeNewXHRTransport
5226
5380
  });
5227
5381
 
5228
5382
  /**
@@ -5251,12 +5405,20 @@ var Sentry = (function (exports) {
5251
5405
  return super._setupTransport();
5252
5406
  }
5253
5407
  const transportOptions = Object.assign(Object.assign({}, this._options.transportOptions), { dsn: this._options.dsn, tunnel: this._options.tunnel, sendClientReports: this._options.sendClientReports, _metadata: this._options._metadata });
5408
+ const api = initAPIDetails(transportOptions.dsn, transportOptions._metadata, transportOptions.tunnel);
5409
+ const url = getEnvelopeEndpointWithUrlEncodedAuth(api.dsn, api.tunnel);
5254
5410
  if (this._options.transport) {
5255
5411
  return new this._options.transport(transportOptions);
5256
5412
  }
5257
5413
  if (supportsFetch()) {
5414
+ const requestOptions = Object.assign({}, transportOptions.fetchParameters);
5415
+ this._newTransport = makeNewFetchTransport({ requestOptions, url });
5258
5416
  return new FetchTransport(transportOptions);
5259
5417
  }
5418
+ this._newTransport = makeNewXHRTransport({
5419
+ url,
5420
+ headers: transportOptions.headers,
5421
+ });
5260
5422
  return new XHRTransport(transportOptions);
5261
5423
  }
5262
5424
  }