import { Worker } from 'node:worker_threads';
import { defineIntegration, debug } from '@sentry/core';
import { isDebuggerEnabled } from '../../utils/debug.js';
import { LOCAL_VARIABLES_KEY, functionNamesMatch } from './common.js';

const base64WorkerScript = "[encoded data, 4236 characters]";
function log(...args) {
  debug.log("[LocalVariables]", ...args);
}
const localVariablesAsyncIntegration = defineIntegration(((integrationOptions = {}) => {
  function addLocalVariablesToException(exception, localVariables) {
    const frames = (exception.stacktrace?.frames || []).filter((frame) => frame.function !== "new Promise");
    for (let i = 0; i < frames.length; i++) {
      const frameIndex = frames.length - i - 1;
      const frameLocalVariables = localVariables[i];
      const frame = frames[frameIndex];
      if (!frame || !frameLocalVariables) {
        break;
      }
      if (
        // We need to have vars to add
        frameLocalVariables.vars === void 0 || // Only skip out-of-app frames if includeOutOfAppFrames is not true
        frame.in_app === false && integrationOptions.includeOutOfAppFrames !== true || // The function names need to match
        !functionNamesMatch(frame.function, frameLocalVariables.function)
      ) {
        continue;
      }
      frame.vars = frameLocalVariables.vars;
    }
  }
  function addLocalVariablesToEvent(event, hint) {
    if (hint.originalException && typeof hint.originalException === "object" && LOCAL_VARIABLES_KEY in hint.originalException && Array.isArray(hint.originalException[LOCAL_VARIABLES_KEY])) {
      for (const exception of event.exception?.values || []) {
        addLocalVariablesToException(exception, hint.originalException[LOCAL_VARIABLES_KEY]);
      }
      hint.originalException[LOCAL_VARIABLES_KEY] = void 0;
    }
    return event;
  }
  async function startInspector() {
    const inspector = await import('node:inspector');
    if (!inspector.url()) {
      inspector.open(0);
    }
  }
  function startWorker(options) {
    const worker = new Worker(new URL(`data:application/javascript;base64,${base64WorkerScript}`), {
      workerData: options,
      // We don't want any Node args to be passed to the worker
      execArgv: [],
      env: { ...process.env, NODE_OPTIONS: void 0 }
    });
    process.on("exit", () => {
      worker.terminate();
    });
    worker.once("error", (err) => {
      log("Worker error", err);
    });
    worker.once("exit", (code) => {
      log("Worker exit", code);
    });
    worker.unref();
  }
  return {
    name: "LocalVariablesAsync",
    async setup(client) {
      const clientOptions = client.getOptions();
      if (!clientOptions.includeLocalVariables) {
        return;
      }
      if (await isDebuggerEnabled()) {
        debug.warn("Local variables capture has been disabled because the debugger was already enabled");
        return;
      }
      const options = {
        ...integrationOptions,
        debug: debug.isEnabled()
      };
      startInspector().then(
        () => {
          try {
            startWorker(options);
          } catch (e) {
            debug.error("Failed to start worker", e);
          }
        },
        (e) => {
          debug.error("Failed to start inspector", e);
        }
      );
    },
    processEvent(event, hint) {
      return addLocalVariablesToEvent(event, hint);
    }
  };
}));

export { base64WorkerScript, localVariablesAsyncIntegration };
//# sourceMappingURL=local-variables-async.js.map
