supports.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { DEBUG_BUILD } from './debug-build.js';
  2. import { logger } from './logger.js';
  3. import { getGlobalObject } from './worldwide.js';
  4. // eslint-disable-next-line deprecation/deprecation
  5. const WINDOW = getGlobalObject();
  6. /**
  7. * Tells whether current environment supports ErrorEvent objects
  8. * {@link supportsErrorEvent}.
  9. *
  10. * @returns Answer to the given question.
  11. */
  12. function supportsErrorEvent() {
  13. try {
  14. new ErrorEvent('');
  15. return true;
  16. } catch (e) {
  17. return false;
  18. }
  19. }
  20. /**
  21. * Tells whether current environment supports DOMError objects
  22. * {@link supportsDOMError}.
  23. *
  24. * @returns Answer to the given question.
  25. */
  26. function supportsDOMError() {
  27. try {
  28. // Chrome: VM89:1 Uncaught TypeError: Failed to construct 'DOMError':
  29. // 1 argument required, but only 0 present.
  30. // @ts-expect-error It really needs 1 argument, not 0.
  31. new DOMError('');
  32. return true;
  33. } catch (e) {
  34. return false;
  35. }
  36. }
  37. /**
  38. * Tells whether current environment supports DOMException objects
  39. * {@link supportsDOMException}.
  40. *
  41. * @returns Answer to the given question.
  42. */
  43. function supportsDOMException() {
  44. try {
  45. new DOMException('');
  46. return true;
  47. } catch (e) {
  48. return false;
  49. }
  50. }
  51. /**
  52. * Tells whether current environment supports Fetch API
  53. * {@link supportsFetch}.
  54. *
  55. * @returns Answer to the given question.
  56. */
  57. function supportsFetch() {
  58. if (!('fetch' in WINDOW)) {
  59. return false;
  60. }
  61. try {
  62. new Headers();
  63. new Request('http://www.example.com');
  64. new Response();
  65. return true;
  66. } catch (e) {
  67. return false;
  68. }
  69. }
  70. /**
  71. * isNativeFetch checks if the given function is a native implementation of fetch()
  72. */
  73. // eslint-disable-next-line @typescript-eslint/ban-types
  74. function isNativeFetch(func) {
  75. return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString());
  76. }
  77. /**
  78. * Tells whether current environment supports Fetch API natively
  79. * {@link supportsNativeFetch}.
  80. *
  81. * @returns true if `window.fetch` is natively implemented, false otherwise
  82. */
  83. function supportsNativeFetch() {
  84. if (typeof EdgeRuntime === 'string') {
  85. return true;
  86. }
  87. if (!supportsFetch()) {
  88. return false;
  89. }
  90. // Fast path to avoid DOM I/O
  91. // eslint-disable-next-line @typescript-eslint/unbound-method
  92. if (isNativeFetch(WINDOW.fetch)) {
  93. return true;
  94. }
  95. // window.fetch is implemented, but is polyfilled or already wrapped (e.g: by a chrome extension)
  96. // so create a "pure" iframe to see if that has native fetch
  97. let result = false;
  98. const doc = WINDOW.document;
  99. // eslint-disable-next-line deprecation/deprecation
  100. if (doc && typeof (doc.createElement ) === 'function') {
  101. try {
  102. const sandbox = doc.createElement('iframe');
  103. sandbox.hidden = true;
  104. doc.head.appendChild(sandbox);
  105. if (sandbox.contentWindow && sandbox.contentWindow.fetch) {
  106. // eslint-disable-next-line @typescript-eslint/unbound-method
  107. result = isNativeFetch(sandbox.contentWindow.fetch);
  108. }
  109. doc.head.removeChild(sandbox);
  110. } catch (err) {
  111. DEBUG_BUILD &&
  112. logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
  113. }
  114. }
  115. return result;
  116. }
  117. /**
  118. * Tells whether current environment supports ReportingObserver API
  119. * {@link supportsReportingObserver}.
  120. *
  121. * @returns Answer to the given question.
  122. */
  123. function supportsReportingObserver() {
  124. return 'ReportingObserver' in WINDOW;
  125. }
  126. /**
  127. * Tells whether current environment supports Referrer Policy API
  128. * {@link supportsReferrerPolicy}.
  129. *
  130. * @returns Answer to the given question.
  131. */
  132. function supportsReferrerPolicy() {
  133. // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default'
  134. // (see https://caniuse.com/#feat=referrer-policy),
  135. // it doesn't. And it throws an exception instead of ignoring this parameter...
  136. // REF: https://github.com/getsentry/raven-js/issues/1233
  137. if (!supportsFetch()) {
  138. return false;
  139. }
  140. try {
  141. new Request('_', {
  142. referrerPolicy: 'origin' ,
  143. });
  144. return true;
  145. } catch (e) {
  146. return false;
  147. }
  148. }
  149. export { isNativeFetch, supportsDOMError, supportsDOMException, supportsErrorEvent, supportsFetch, supportsNativeFetch, supportsReferrerPolicy, supportsReportingObserver };
  150. //# sourceMappingURL=supports.js.map