Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

const core = require('@sentry/core');
const debugBuild = require('../debug-build.js');
const eventbuilder = require('../eventbuilder.js');
const helpers = require('../helpers.js');

const INTEGRATION_NAME = 'GlobalHandlers';

const _globalHandlersIntegration = ((options = {}) => {
  const _options = {
    onerror: true,
    onunhandledrejection: true,
    ...options,
  };

  return {
    name: INTEGRATION_NAME,
    setupOnce() {
      Error.stackTraceLimit = 50;
    },
    setup(client) {
      if (_options.onerror) {
        _installGlobalOnErrorHandler(client);
        globalHandlerLog('onerror');
      }
      if (_options.onunhandledrejection) {
        _installGlobalOnUnhandledRejectionHandler(client);
        globalHandlerLog('onunhandledrejection');
      }
    },
  };
}) ;

const globalHandlersIntegration = core.defineIntegration(_globalHandlersIntegration);

function _installGlobalOnErrorHandler(client) {
  core.addGlobalErrorInstrumentationHandler(data => {
    const { stackParser, attachStacktrace } = getOptions();

    if (core.getClient() !== client || helpers.shouldIgnoreOnError()) {
      return;
    }

    const { msg, url, line, column, error } = data;

    const event = _enhanceEventWithInitialFrame(
      eventbuilder.eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),
      url,
      line,
      column,
    );

    event.level = 'error';

    core.captureEvent(event, {
      originalException: error,
      mechanism: {
        handled: false,
        type: 'auto.browser.global_handlers.onerror',
      },
    });
  });
}

function _installGlobalOnUnhandledRejectionHandler(client) {
  core.addGlobalUnhandledRejectionInstrumentationHandler(e => {
    const { stackParser, attachStacktrace } = getOptions();

    if (core.getClient() !== client || helpers.shouldIgnoreOnError()) {
      return;
    }

    const error = _getUnhandledRejectionError(e);

    const event = core.isPrimitive(error)
      ? _eventFromRejectionWithPrimitive(error)
      : eventbuilder.eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);

    event.level = 'error';

    core.captureEvent(event, {
      originalException: error,
      mechanism: {
        handled: false,
        type: 'auto.browser.global_handlers.onunhandledrejection',
      },
    });
  });
}

/**
 *
 */
function _getUnhandledRejectionError(error) {
  if (core.isPrimitive(error)) {
    return error;
  }

  // dig the object of the rejection out of known event types
  try {

    // PromiseRejectionEvents store the object of the rejection under 'reason'
    // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent
    if ('reason' in (error )) {
      return (error ).reason;
    }

    // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents
    // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into
    // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec
    // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and
    // https://github.com/getsentry/sentry-javascript/issues/2380
    if ('detail' in (error ) && 'reason' in (error ).detail) {
      return (error ).detail.reason;
    }
  } catch {} // eslint-disable-line no-empty

  return error;
}

/**
 * Create an event from a promise rejection where the `reason` is a primitive.
 *
 * @param reason: The `reason` property of the promise rejection
 * @returns An Event object with an appropriate `exception` value
 */
function _eventFromRejectionWithPrimitive(reason) {
  return {
    exception: {
      values: [
        {
          type: 'UnhandledRejection',
          // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)
          value: `Non-Error promise rejection captured with value: ${String(reason)}`,
        },
      ],
    },
  };
}

function _enhanceEventWithInitialFrame(
  event,
  url,
  line,
  column,
) {
  // event.exception
  const e = (event.exception = event.exception || {});
  // event.exception.values
  const ev = (e.values = e.values || []);
  // event.exception.values[0]
  const ev0 = (ev[0] = ev[0] || {});
  // event.exception.values[0].stacktrace
  const ev0s = (ev0.stacktrace = ev0.stacktrace || {});
  // event.exception.values[0].stacktrace.frames
  const ev0sf = (ev0s.frames = ev0s.frames || []);

  const colno = column;
  const lineno = line;
  const filename = getFilenameFromUrl(url) ?? core.getLocationHref();

  // event.exception.values[0].stacktrace.frames
  if (ev0sf.length === 0) {
    ev0sf.push({
      colno,
      filename,
      function: core.UNKNOWN_FUNCTION,
      in_app: true,
      lineno,
    });
  }

  return event;
}

function globalHandlerLog(type) {
  debugBuild.DEBUG_BUILD && core.debug.log(`Global Handler attached: ${type}`);
}

function getOptions() {
  const client = core.getClient();
  const options = client?.getOptions() || {
    stackParser: () => [],
    attachStacktrace: false,
  };
  return options;
}

function getFilenameFromUrl(url) {
  if (!core.isString(url) || url.length === 0) {
    return undefined;
  }

  // stack frame urls can be data urls, for example when initializing a Worker with a base64 encoded script
  // in this case we just show the data prefix and mime type to avoid too long raw data urls
  if (url.startsWith('data:')) {
    const match = url.match(/^data:([^;]+)/);
    const mimeType = match ? match[1] : 'text/javascript';
    const isBase64 = url.includes('base64,');
    return `<data:${mimeType}${isBase64 ? ',base64' : ''}>`;
  }

  return url; // it's fine to not truncate it as it's not put in a regex (https://codeql.github.com/codeql-query-help/javascript/js-polynomial-redos)
}

exports._eventFromRejectionWithPrimitive = _eventFromRejectionWithPrimitive;
exports._getUnhandledRejectionError = _getUnhandledRejectionError;
exports.globalHandlersIntegration = globalHandlersIntegration;//# sourceMappingURL=http://go/sourcemap/sourcemaps/cd1c87ff9b66021918fb9731605f8d1d5fd2f0b0/node_modules/@sentry/browser/build/npm/cjs/prod/integrations/globalhandlers.js.map
