const normalizeLine = line => {
  if (line.startsWith('Error: ')) {
    return line.slice('Error: '.length);
  }
  if (line.startsWith('VError: ')) {
    return line.slice('VError: '.length);
  }
  return line;
};
const getCombinedMessage = (error, message) => {
  const stringifiedError = normalizeLine(`${error}`);
  if (message) {
    return `${message}: ${stringifiedError}`;
  }
  return stringifiedError;
};
const NewLine$3 = '\n';
const getNewLineIndex$2 = (string, startIndex = undefined) => {
  return string.indexOf(NewLine$3, startIndex);
};
const mergeStacks = (parent, child) => {
  if (!child) {
    return parent;
  }
  const parentNewLineIndex = getNewLineIndex$2(parent);
  const childNewLineIndex = getNewLineIndex$2(child);
  if (childNewLineIndex === -1) {
    return parent;
  }
  const parentFirstLine = parent.slice(0, parentNewLineIndex);
  const childRest = child.slice(childNewLineIndex);
  const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
  if (parentFirstLine.includes(childFirstLine)) {
    return parentFirstLine + childRest;
  }
  return child;
};
class VError extends Error {
  constructor(error, message) {
    const combinedMessage = getCombinedMessage(error, message);
    super(combinedMessage);
    this.name = 'VError';
    if (error instanceof Error) {
      this.stack = mergeStacks(this.stack, error.stack);
    }
    if (error.codeFrame) {
      // @ts-ignore
      this.codeFrame = error.codeFrame;
    }
    if (error.code) {
      // @ts-ignore
      this.code = error.code;
    }
  }
}

class AssertionError extends Error {
  constructor(message) {
    super(message);
    this.name = 'AssertionError';
  }
}
const Object$1 = 1;
const Number$1 = 2;
const Array$1 = 3;
const String = 4;
const Boolean = 5;
const Function = 6;
const Null = 7;
const Unknown = 8;
const getType = value => {
  switch (typeof value) {
    case 'number':
      return Number$1;
    case 'function':
      return Function;
    case 'string':
      return String;
    case 'object':
      if (value === null) {
        return Null;
      }
      if (Array.isArray(value)) {
        return Array$1;
      }
      return Object$1;
    case 'boolean':
      return Boolean;
    default:
      return Unknown;
  }
};
const number = value => {
  const type = getType(value);
  if (type !== Number$1) {
    throw new AssertionError('expected value to be of type number');
  }
};
const array = value => {
  const type = getType(value);
  if (type !== Array$1) {
    throw new AssertionError('expected value to be of type array');
  }
};
const string = value => {
  const type = getType(value);
  if (type !== String) {
    throw new AssertionError('expected value to be of type string');
  }
};

const isMessagePort = value => {
  return value && value instanceof MessagePort;
};
const isMessagePortMain = value => {
  return value && value.constructor && value.constructor.name === 'MessagePortMain';
};
const isOffscreenCanvas = value => {
  return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
};
const isInstanceOf = (value, constructorName) => {
  return value?.constructor?.name === constructorName;
};
const isSocket = value => {
  return isInstanceOf(value, 'Socket');
};
const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
const isTransferrable = value => {
  for (const fn of transferrables) {
    if (fn(value)) {
      return true;
    }
  }
  return false;
};
const walkValue = (value, transferrables, isTransferrable) => {
  if (!value) {
    return;
  }
  if (isTransferrable(value)) {
    transferrables.push(value);
    return;
  }
  if (Array.isArray(value)) {
    for (const item of value) {
      walkValue(item, transferrables, isTransferrable);
    }
    return;
  }
  if (typeof value === 'object') {
    for (const property of Object.values(value)) {
      walkValue(property, transferrables, isTransferrable);
    }
    return;
  }
};
const getTransferrables = value => {
  const transferrables = [];
  walkValue(value, transferrables, isTransferrable);
  return transferrables;
};
const attachEvents = that => {
  const handleMessage = (...args) => {
    const data = that.getData(...args);
    that.dispatchEvent(new MessageEvent('message', {
      data
    }));
  };
  that.onMessage(handleMessage);
  const handleClose = event => {
    that.dispatchEvent(new Event('close'));
  };
  that.onClose(handleClose);
};
class Ipc extends EventTarget {
  constructor(rawIpc) {
    super();
    this._rawIpc = rawIpc;
    attachEvents(this);
  }
}
const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
const NewLine$2 = '\n';
const joinLines$1 = lines => {
  return lines.join(NewLine$2);
};
const RE_AT = /^\s+at/;
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
const isNormalStackLine = line => {
  return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
};
const getDetails = lines => {
  const index = lines.findIndex(isNormalStackLine);
  if (index === -1) {
    return {
      actualMessage: joinLines$1(lines),
      rest: []
    };
  }
  let lastIndex = index - 1;
  while (++lastIndex < lines.length) {
    if (!isNormalStackLine(lines[lastIndex])) {
      break;
    }
  }
  return {
    actualMessage: lines[index - 1],
    rest: lines.slice(index, lastIndex)
  };
};
const splitLines$1 = lines => {
  return lines.split(NewLine$2);
};
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
const isMessageCodeBlockStartIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_START.test(line);
};
const isMessageCodeBlockEndIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_END.test(line);
};
const getMessageCodeBlock = stderr => {
  const lines = splitLines$1(stderr);
  const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
  const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
  const relevantLines = lines.slice(startIndex, endIndex);
  const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
  return relevantMessage;
};
const isModuleNotFoundMessage = line => {
  return line.includes('[ERR_MODULE_NOT_FOUND]');
};
const getModuleNotFoundError = stderr => {
  const lines = splitLines$1(stderr);
  const messageIndex = lines.findIndex(isModuleNotFoundMessage);
  const message = lines[messageIndex];
  return {
    message,
    code: ERR_MODULE_NOT_FOUND
  };
};
const isModuleNotFoundError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('ERR_MODULE_NOT_FOUND');
};
const isModulesSyntaxError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('SyntaxError: Cannot use import statement outside a module');
};
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
const isUnhelpfulNativeModuleError = stderr => {
  return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
};
const getNativeModuleErrorMessage = stderr => {
  const message = getMessageCodeBlock(stderr);
  return {
    message: `Incompatible native node module: ${message}`,
    code: E_INCOMPATIBLE_NATIVE_MODULE
  };
};
const getModuleSyntaxError = () => {
  return {
    message: `ES Modules are not supported in electron`,
    code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
  };
};
const getHelpfulChildProcessError = (stdout, stderr) => {
  if (isUnhelpfulNativeModuleError(stderr)) {
    return getNativeModuleErrorMessage(stderr);
  }
  if (isModulesSyntaxError(stderr)) {
    return getModuleSyntaxError();
  }
  if (isModuleNotFoundError(stderr)) {
    return getModuleNotFoundError(stderr);
  }
  const lines = splitLines$1(stderr);
  const {
    actualMessage,
    rest
  } = getDetails(lines);
  return {
    message: actualMessage,
    code: '',
    stack: rest
  };
};
class IpcError extends VError {
  // @ts-ignore
  constructor(betterMessage, stdout = '', stderr = '') {
    if (stdout || stderr) {
      // @ts-ignore
      const {
        message,
        code,
        stack
      } = getHelpfulChildProcessError(stdout, stderr);
      const cause = new Error(message);
      // @ts-ignore
      cause.code = code;
      cause.stack = stack;
      super(cause, betterMessage);
    } else {
      super(betterMessage);
    }
    // @ts-ignore
    this.name = 'IpcError';
    // @ts-ignore
    this.stdout = stdout;
    // @ts-ignore
    this.stderr = stderr;
  }
}
const readyMessage = 'ready';
const getData$2 = event => {
  return event.data;
};
const listen$7 = () => {
  // @ts-ignore
  if (typeof WorkerGlobalScope === 'undefined') {
    throw new TypeError('module is not in web worker scope');
  }
  return globalThis;
};
const signal$8 = global => {
  global.postMessage(readyMessage);
};
class IpcChildWithModuleWorker extends Ipc {
  getData(event) {
    return getData$2(event);
  }
  send(message) {
    // @ts-ignore
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    // @ts-ignore
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    // ignore
  }
  onClose(callback) {
    // ignore
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
  }
}
const wrap$f = global => {
  return new IpcChildWithModuleWorker(global);
};
const waitForFirstMessage = async port => {
  const {
    resolve,
    promise
  } = Promise.withResolvers();
  port.addEventListener('message', resolve, {
    once: true
  });
  const event = await promise;
  // @ts-ignore
  return event.data;
};
const listen$6 = async () => {
  const parentIpcRaw = listen$7();
  signal$8(parentIpcRaw);
  const parentIpc = wrap$f(parentIpcRaw);
  const firstMessage = await waitForFirstMessage(parentIpc);
  if (firstMessage.method !== 'initialize') {
    throw new IpcError('unexpected first message');
  }
  const type = firstMessage.params[0];
  if (type === 'message-port') {
    parentIpc.send({
      jsonrpc: '2.0',
      id: firstMessage.id,
      result: null
    });
    parentIpc.dispose();
    const port = firstMessage.params[1];
    return port;
  }
  return globalThis;
};
class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
  getData(event) {
    return getData$2(event);
  }
  send(message) {
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    if (this._rawIpc.close) {
      this._rawIpc.close();
    }
  }
  onClose(callback) {
    // ignore
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
    this._rawIpc.start();
  }
}
const wrap$e = port => {
  return new IpcChildWithModuleWorkerAndMessagePort(port);
};
const IpcChildWithModuleWorkerAndMessagePort$1 = {
  __proto__: null,
  listen: listen$6,
  wrap: wrap$e
};
const addListener = (emitter, type, callback) => {
  if ('addEventListener' in emitter) {
    emitter.addEventListener(type, callback);
  } else {
    emitter.on(type, callback);
  }
};
const removeListener = (emitter, type, callback) => {
  if ('removeEventListener' in emitter) {
    emitter.removeEventListener(type, callback);
  } else {
    emitter.off(type, callback);
  }
};
const getFirstEvent = (eventEmitter, eventMap) => {
  const {
    resolve,
    promise
  } = Promise.withResolvers();
  const listenerMap = Object.create(null);
  const cleanup = value => {
    for (const event of Object.keys(eventMap)) {
      removeListener(eventEmitter, event, listenerMap[event]);
    }
    resolve(value);
  };
  for (const [event, type] of Object.entries(eventMap)) {
    const listener = event => {
      cleanup({
        type,
        event
      });
    };
    addListener(eventEmitter, event, listener);
    listenerMap[event] = listener;
  }
  return promise;
};
const Message$1 = 3;
const create$5$1 = async ({
  messagePort,
  isMessagePortOpen
}) => {
  if (!isMessagePort(messagePort)) {
    throw new IpcError('port must be of type MessagePort');
  }
  if (isMessagePortOpen) {
    return messagePort;
  }
  const eventPromise = getFirstEvent(messagePort, {
    message: Message$1
  });
  messagePort.start();
  const {
    type,
    event
  } = await eventPromise;
  if (type !== Message$1) {
    throw new IpcError('Failed to wait for ipc message');
  }
  if (event.data !== readyMessage) {
    throw new IpcError('unexpected first message');
  }
  return messagePort;
};
const signal$1 = messagePort => {
  messagePort.start();
};
class IpcParentWithMessagePort extends Ipc {
  getData = getData$2;
  send(message) {
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    this._rawIpc.close();
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
  }
  onClose(callback) {}
}
const wrap$5 = messagePort => {
  return new IpcParentWithMessagePort(messagePort);
};
const IpcParentWithMessagePort$1 = {
  __proto__: null,
  create: create$5$1,
  signal: signal$1,
  wrap: wrap$5
};

const Two = '2.0';
const create$4$1 = (method, params) => {
  return {
    jsonrpc: Two,
    method,
    params
  };
};
const callbacks = Object.create(null);
const set$8 = (id, fn) => {
  callbacks[id] = fn;
};
const get$2 = id => {
  return callbacks[id];
};
const remove = id => {
  delete callbacks[id];
};
let id = 0;
const create$3$1 = () => {
  return ++id;
};
const registerPromise = () => {
  const id = create$3$1();
  const {
    resolve,
    promise
  } = Promise.withResolvers();
  set$8(id, resolve);
  return {
    id,
    promise
  };
};
const create$2$1 = (method, params) => {
  const {
    id,
    promise
  } = registerPromise();
  const message = {
    jsonrpc: Two,
    method,
    params,
    id
  };
  return {
    message,
    promise
  };
};
class JsonRpcError extends Error {
  constructor(message) {
    super(message);
    this.name = 'JsonRpcError';
  }
}
const NewLine$1 = '\n';
const DomException = 'DOMException';
const ReferenceError$1 = 'ReferenceError';
const SyntaxError$1 = 'SyntaxError';
const TypeError$1 = 'TypeError';
const getErrorConstructor = (message, type) => {
  if (type) {
    switch (type) {
      case DomException:
        return DOMException;
      case TypeError$1:
        return TypeError;
      case SyntaxError$1:
        return SyntaxError;
      case ReferenceError$1:
        return ReferenceError;
      default:
        return Error;
    }
  }
  if (message.startsWith('TypeError: ')) {
    return TypeError;
  }
  if (message.startsWith('SyntaxError: ')) {
    return SyntaxError;
  }
  if (message.startsWith('ReferenceError: ')) {
    return ReferenceError;
  }
  return Error;
};
const constructError = (message, type, name) => {
  const ErrorConstructor = getErrorConstructor(message, type);
  if (ErrorConstructor === DOMException && name) {
    return new ErrorConstructor(message, name);
  }
  if (ErrorConstructor === Error) {
    const error = new Error(message);
    if (name && name !== 'VError') {
      error.name = name;
    }
    return error;
  }
  return new ErrorConstructor(message);
};
const joinLines = lines => {
  return lines.join(NewLine$1);
};
const splitLines = lines => {
  return lines.split(NewLine$1);
};
const getCurrentStack = () => {
  const stackLinesToSkip = 3;
  const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip));
  return currentStack;
};
const getNewLineIndex$1 = (string, startIndex = undefined) => {
  return string.indexOf(NewLine$1, startIndex);
};
const getParentStack = error => {
  let parentStack = error.stack || error.data || error.message || '';
  if (parentStack.startsWith('    at')) {
    parentStack = error.message + NewLine$1 + parentStack;
  }
  return parentStack;
};
const MethodNotFound = -32601;
const Custom = -32001;
const restoreJsonRpcError = error => {
  const currentStack = getCurrentStack();
  if (error && error instanceof Error) {
    if (typeof error.stack === 'string') {
      error.stack = error.stack + NewLine$1 + currentStack;
    }
    return error;
  }
  if (error && error.code && error.code === MethodNotFound) {
    const restoredError = new JsonRpcError(error.message);
    const parentStack = getParentStack(error);
    restoredError.stack = parentStack + NewLine$1 + currentStack;
    return restoredError;
  }
  if (error && error.message) {
    const restoredError = constructError(error.message, error.type, error.name);
    if (error.data) {
      if (error.data.stack && error.data.type && error.message) {
        restoredError.stack = error.data.type + ': ' + error.message + NewLine$1 + error.data.stack + NewLine$1 + currentStack;
      } else if (error.data.stack) {
        restoredError.stack = error.data.stack;
      }
      if (error.data.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.data.codeFrame;
      }
      if (error.data.code) {
        // @ts-ignore
        restoredError.code = error.data.code;
      }
      if (error.data.type) {
        // @ts-ignore
        restoredError.name = error.data.type;
      }
    } else {
      if (error.stack) {
        const lowerStack = restoredError.stack || '';
        // @ts-ignore
        const indexNewLine = getNewLineIndex$1(lowerStack);
        const parentStack = getParentStack(error);
        // @ts-ignore
        restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
      }
      if (error.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.codeFrame;
      }
    }
    return restoredError;
  }
  if (typeof error === 'string') {
    return new Error(`JsonRpc Error: ${error}`);
  }
  return new Error(`JsonRpc Error: ${error}`);
};
const unwrapJsonRpcResult = responseMessage => {
  if ('error' in responseMessage) {
    const restoredError = restoreJsonRpcError(responseMessage.error);
    throw restoredError;
  }
  if ('result' in responseMessage) {
    return responseMessage.result;
  }
  throw new JsonRpcError('unexpected response message');
};
const warn = (...args) => {
  console.warn(...args);
};
const resolve = (id, response) => {
  const fn = get$2(id);
  if (!fn) {
    console.log(response);
    warn(`callback ${id} may already be disposed`);
    return;
  }
  fn(response);
  remove(id);
};
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
const getErrorType = prettyError => {
  if (prettyError && prettyError.type) {
    return prettyError.type;
  }
  if (prettyError && prettyError.constructor && prettyError.constructor.name) {
    return prettyError.constructor.name;
  }
  return undefined;
};
const isAlreadyStack = line => {
  return line.trim().startsWith('at ');
};
const getStack = prettyError => {
  const stackString = prettyError.stack || '';
  const newLineIndex = stackString.indexOf('\n');
  if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
    return stackString.slice(newLineIndex + 1);
  }
  return stackString;
};
const getErrorProperty = (error, prettyError) => {
  if (error && error.code === E_COMMAND_NOT_FOUND) {
    return {
      code: MethodNotFound,
      message: error.message,
      data: error.stack
    };
  }
  return {
    code: Custom,
    message: prettyError.message,
    data: {
      stack: getStack(prettyError),
      codeFrame: prettyError.codeFrame,
      type: getErrorType(prettyError),
      code: prettyError.code,
      name: prettyError.name
    }
  };
};
const create$1$1 = (id, error) => {
  return {
    jsonrpc: Two,
    id,
    error
  };
};
const getErrorResponse = (id, error, preparePrettyError, logError) => {
  const prettyError = preparePrettyError(error);
  logError(error, prettyError);
  const errorProperty = getErrorProperty(error, prettyError);
  return create$1$1(id, errorProperty);
};
const create$6 = (message, result) => {
  return {
    jsonrpc: Two,
    id: message.id,
    result: result ?? null
  };
};
const getSuccessResponse = (message, result) => {
  const resultProperty = result ?? null;
  return create$6(message, resultProperty);
};
const getErrorResponseSimple = (id, error) => {
  return {
    jsonrpc: Two,
    id,
    error: {
      code: Custom,
      // @ts-ignore
      message: error.message,
      data: error
    }
  };
};
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
  try {
    const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
    return getSuccessResponse(message, result);
  } catch (error) {
    if (ipc.canUseSimpleErrorResponse) {
      return getErrorResponseSimple(message.id, error);
    }
    return getErrorResponse(message.id, error, preparePrettyError, logError);
  }
};
const defaultPreparePrettyError = error => {
  return error;
};
const defaultLogError = () => {
  // ignore
};
const defaultRequiresSocket = () => {
  return false;
};
const defaultResolve = resolve;

// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
const normalizeParams = args => {
  if (args.length === 1) {
    const options = args[0];
    return {
      ipc: options.ipc,
      message: options.message,
      execute: options.execute,
      resolve: options.resolve || defaultResolve,
      preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
      logError: options.logError || defaultLogError,
      requiresSocket: options.requiresSocket || defaultRequiresSocket
    };
  }
  return {
    ipc: args[0],
    message: args[1],
    execute: args[2],
    resolve: args[3],
    preparePrettyError: args[4],
    logError: args[5],
    requiresSocket: args[6]
  };
};
const handleJsonRpcMessage = async (...args) => {
  const options = normalizeParams(args);
  const {
    message,
    ipc,
    execute,
    resolve,
    preparePrettyError,
    logError,
    requiresSocket
  } = options;
  if ('id' in message) {
    if ('method' in message) {
      const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
      try {
        ipc.send(response);
      } catch (error) {
        const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
        ipc.send(errorResponse);
      }
      return;
    }
    resolve(message.id, message);
    return;
  }
  if ('method' in message) {
    await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
    return;
  }
  throw new JsonRpcError('unexpected message');
};
const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
  const {
    message,
    promise
  } = create$2$1(method, params);
  if (useSendAndTransfer && ipc.sendAndTransfer) {
    ipc.sendAndTransfer(message);
  } else {
    ipc.send(message);
  }
  const responseMessage = await promise;
  return unwrapJsonRpcResult(responseMessage);
};
const send = (transport, method, ...params) => {
  const message = create$4$1(method, params);
  transport.send(message);
};
const invoke$4 = (ipc, method, ...params) => {
  return invokeHelper(ipc, method, params, false);
};
const invokeAndTransfer$3 = (ipc, method, ...params) => {
  return invokeHelper(ipc, method, params, true);
};

class CommandNotFoundError extends Error {
  constructor(command) {
    super(`Command not found ${command}`);
    this.name = 'CommandNotFoundError';
  }
}
const commands = Object.create(null);
const register = commandMap => {
  Object.assign(commands, commandMap);
};
const getCommand = key => {
  return commands[key];
};
const execute = (command, ...args) => {
  const fn = getCommand(command);
  if (!fn) {
    throw new CommandNotFoundError(command);
  }
  return fn(...args);
};

const createRpc = ipc => {
  const rpc = {
    // @ts-ignore
    ipc,
    /**
     * @deprecated
     */
    send(method, ...params) {
      send(ipc, method, ...params);
    },
    invoke(method, ...params) {
      return invoke$4(ipc, method, ...params);
    },
    invokeAndTransfer(method, ...params) {
      return invokeAndTransfer$3(ipc, method, ...params);
    },
    async dispose() {
      await ipc?.dispose();
    }
  };
  return rpc;
};
const requiresSocket = () => {
  return false;
};
const preparePrettyError = error => {
  return error;
};
const logError = () => {
  // handled by renderer worker
};
const handleMessage = event => {
  const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
  const actualExecute = event?.target?.execute || execute;
  return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
};
const handleIpc = ipc => {
  if ('addEventListener' in ipc) {
    ipc.addEventListener('message', handleMessage);
  } else if ('on' in ipc) {
    // deprecated
    ipc.on('message', handleMessage);
  }
};
const listen$1 = async (module, options) => {
  const rawIpc = await module.listen(options);
  if (module.signal) {
    module.signal(rawIpc);
  }
  const ipc = module.wrap(rawIpc);
  return ipc;
};
const create$5 = async ({
  commandMap,
  messagePort
}) => {
  // TODO create a commandMap per rpc instance
  register(commandMap);
  const rawIpc = await IpcParentWithMessagePort$1.create({
    messagePort,
    isMessagePortOpen: true
  });
  const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
  handleIpc(ipc);
  const rpc = createRpc(ipc);
  messagePort.start();
  return rpc;
};
const create$3 = async ({
  commandMap,
  send
}) => {
  const {
    port1,
    port2
  } = new MessageChannel();
  await send(port1);
  return create$5({
    commandMap,
    messagePort: port2
  });
};
const TransferMessagePortRpcParent = {
  __proto__: null,
  create: create$3
};
const create$4 = async ({
  commandMap
}) => {
  // TODO create a commandMap per rpc instance
  register(commandMap);
  const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
  handleIpc(ipc);
  const rpc = createRpc(ipc);
  return rpc;
};
const WebWorkerRpcClient = {
  __proto__: null,
  create: create$4
};
const createMockRpc = ({
  commandMap
}) => {
  const invocations = [];
  const invoke = (method, ...params) => {
    invocations.push([method, ...params]);
    const command = commandMap[method];
    return command(...params);
  };
  const mockRpc = {
    invoke,
    invokeAndTransfer: invoke,
    invocations
  };
  return mockRpc;
};

const toCommandId = key => {
  const dotIndex = key.indexOf('.');
  return key.slice(dotIndex + 1);
};
const create$2 = () => {
  const states = Object.create(null);
  const commandMapRef = {};
  return {
    get(uid) {
      return states[uid];
    },
    set(uid, oldState, newState) {
      states[uid] = {
        oldState,
        newState
      };
    },
    dispose(uid) {
      delete states[uid];
    },
    getKeys() {
      return Object.keys(states).map(key => {
        return Number.parseInt(key);
      });
    },
    clear() {
      for (const key of Object.keys(states)) {
        delete states[key];
      }
    },
    wrapCommand(fn) {
      const wrapped = async (uid, ...args) => {
        const {
          newState
        } = states[uid];
        const newerState = await fn(newState, ...args);
        if (newState === newerState) {
          return;
        }
        const latest = states[uid];
        states[uid] = {
          oldState: latest.oldState,
          newState: newerState
        };
      };
      return wrapped;
    },
    wrapGetter(fn) {
      const wrapped = (uid, ...args) => {
        const {
          newState
        } = states[uid];
        return fn(newState, ...args);
      };
      return wrapped;
    },
    diff(uid, modules, numbers) {
      const {
        oldState,
        newState
      } = states[uid];
      const diffResult = [];
      for (let i = 0; i < modules.length; i++) {
        const fn = modules[i];
        if (!fn(oldState, newState)) {
          diffResult.push(numbers[i]);
        }
      }
      return diffResult;
    },
    getCommandIds() {
      const keys = Object.keys(commandMapRef);
      const ids = keys.map(toCommandId);
      return ids;
    },
    registerCommands(commandMap) {
      Object.assign(commandMapRef, commandMap);
    }
  };
};
const terminate = () => {
  globalThis.close();
};

const clear$1 = state => {
  return {
    ...state,
    references: [],
    displayReferences: [],
    message: 'No Results'
  };
};

const getBaseName = uri => {
  if (!uri) {
    return '';
  }
  return uri.slice(uri.lastIndexOf('/') + 1);
};

const Leaf = 1;
const Expanded = 2;
const Collapsed = 3;

const getDisplayReferences = (references, icons, collapsedUris) => {
  const displayReferences = [];
  let currentUri = '';
  let outerPosInSet = 1;
  let innerPosInSet = 1;
  let index = 0;
  for (const reference of references) {
    if (reference.uri === currentUri) {
      displayReferences.push({
        depth: 2,
        posInSet: innerPosInSet++,
        setSize: 1,
        type: Leaf,
        uri: '',
        name: '',
        lineText: reference.lineText || '',
        icon: '',
        index: index++,
        startOffset: reference.startColumnIndex || reference.startOffset,
        endOffset: reference.endColumnIndex || reference.endOffset
      });
    } else {
      currentUri = reference.uri;
      innerPosInSet = 1;
      const name = getBaseName(reference.uri);
      const relativeIndex = references.indexOf(reference);
      const icon = icons[relativeIndex];
      displayReferences.push({
        depth: 1,
        posInSet: outerPosInSet++,
        setSize: 1,
        type: Expanded,
        uri: reference.uri,
        name,
        lineText: '',
        icon,
        index: index++,
        startOffset: 0,
        endOffset: 0
      });
      if (!collapsedUris.includes(reference.uri)) {
        displayReferences.push({
          depth: 2,
          posInSet: innerPosInSet++,
          setSize: 1,
          type: Leaf,
          uri: '',
          name: '',
          lineText: reference.lineText || '',
          icon: '',
          index: index++,
          startOffset: reference.startColumnIndex || reference.startOffset,
          endOffset: reference.endColumnIndex || reference.endOffset
        });
      }
    }
  }
  return displayReferences;
};

const getUri$3 = reference => {
  return reference.uri;
};
const collapseAll$1 = async state => {
  const {
    references
  } = state;
  const uris = references.map(getUri$3);
  const displayReferences = getDisplayReferences(references, [], uris);
  return {
    ...state,
    collapsedUris: uris,
    displayReferences
  };
};

const {
  get: get$1,
  set: set$7,
  wrapCommand,
  dispose: dispose$4,
  registerCommands,
  getCommandIds
} = create$2();

const create$1 = (id, uri, x, y, width, height) => {
  const state = {
    id,
    message: '',
    references: [],
    displayReferences: [],
    focusedIndex: -1,
    fileIconCache: {},
    offset: -1,
    uri: '',
    languageId: '',
    collapsedUris: []
  };
  set$7(id, state, state);
};

const RenderItems = 1;

const diffType = RenderItems;
const isEqual = (oldState, newState) => {
  return oldState.references === newState.references && oldState.displayReferences === newState.displayReferences && oldState.message === newState.message;
};

const modules = [isEqual];
const numbers = [diffType];

const diff = (oldState, newState) => {
  const diffResult = [];
  for (let i = 0; i < modules.length; i++) {
    const fn = modules[i];
    if (!fn(oldState, newState)) {
      diffResult.push(numbers[i]);
    }
  }
  return diffResult;
};

const diff2 = uid => {
  const {
    oldState,
    newState
  } = get$1(uid);
  const diffResult = diff(oldState, newState);
  return diffResult;
};

const dispose$3 = async uid => {
  dispose$4(uid);
};

const focusIndex = (state, index) => {
  if (index < -1 || index >= state.displayReferences.length) {
    return state;
  }
  return {
    ...state,
    focusedIndex: index
  };
};

const focusFirst = state => {
  if (state.displayReferences.length === 0) {
    return focusIndex(state, -1);
  }
  return focusIndex(state, 0);
};

const focusLast = state => {
  if (state.displayReferences.length === 0) {
    return focusIndex(state, -1);
  }
  return focusIndex(state, state.displayReferences.length - 1);
};

const focusNext = state => {
  if (state.displayReferences.length === 0) {
    return state;
  }
  const nextIndex = state.focusedIndex + 1;
  if (nextIndex >= state.displayReferences.length) {
    return focusIndex(state, 0);
  }
  return focusIndex(state, nextIndex);
};

const focusPrevious = state => {
  if (state.displayReferences.length === 0) {
    return state;
  }
  const prevIndex = state.focusedIndex - 1;
  if (prevIndex < 0) {
    return focusIndex(state, state.displayReferences.length - 1);
  }
  return focusIndex(state, prevIndex);
};

const None = 'none';
const Status = 'status';
const Tree = 'tree';

const Button$1 = 1;
const Div = 4;
const Span = 8;
const Text = 12;
const Img = 17;

const Enter = 3;
const End = 255;
const Home = 12;
const UpArrow = 14;
const DownArrow = 16;

const DebugWorker = 55;
const EditorWorker$1 = 99;
const ExtensionHostWorker = 44;
const RendererWorker$1 = 1;

const text = data => {
  return {
    type: Text,
    text: data,
    childCount: 0
  };
};

const FocusLocationList = 17;

const getKeyBindings$1 = () => {
  return [{
    key: DownArrow,
    command: 'References.focusNext',
    when: FocusLocationList
  }, {
    key: UpArrow,
    command: 'References.focusPrevious',
    when: FocusLocationList
  }, {
    key: Home,
    command: 'References.focusFirst',
    when: FocusLocationList
  }, {
    key: End,
    command: 'References.focusLast',
    when: FocusLocationList
  }, {
    key: Enter,
    command: 'References.selectCurrent',
    when: FocusLocationList
  }];
};

const selectIndexCollapsed = (state, index) => {
  // TODO collapse

  return {
    ...state,
    focusedIndex: index
  };
};

const selectIndexExpanded = (state, index) => {
  // TODO expand

  return {
    ...state,
    focusedIndex: index
  };
};

const getUri$2 = (state, index) => {
  return state.displayReferences[index]?.uri || '';
};

const rpcs = Object.create(null);
const set$6 = (id, rpc) => {
  rpcs[id] = rpc;
};
const get = id => {
  return rpcs[id];
};

const create = rpcId => {
  return {
    // @ts-ignore
    invoke(method, ...params) {
      const rpc = get(rpcId);
      // @ts-ignore
      return rpc.invoke(method, ...params);
    },
    // @ts-ignore
    invokeAndTransfer(method, ...params) {
      const rpc = get(rpcId);
      // @ts-ignore
      return rpc.invokeAndTransfer(method, ...params);
    },
    set(rpc) {
      set$6(rpcId, rpc);
    },
    async dispose() {
      const rpc = get(rpcId);
      await rpc.dispose();
    }
  };
};

const {
  invoke: invoke$3,
  invokeAndTransfer: invokeAndTransfer$2,
  set: set$5,
  dispose: dispose$2
} = create(EditorWorker$1);
const sendMessagePortToExtensionHostWorker$3 = async port => {
  const command = 'HandleMessagePort.handleMessagePort2';
  await invokeAndTransfer$2(
  // @ts-ignore
  'SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, 0);
};
// TODO add tests for this
const activateByEvent$2 = async event => {
  // @ts-ignore
  await invoke$3('ActivateByEvent.activateByEvent', event);
};
const applyEdit = async (editorUid, changes) => {
  // @ts-ignore
  await invoke$3('Editor.applyEdit2', editorUid, changes);
};
const applyWorkspaceEdit = async (editorUid, changes) => {
  // @ts-ignore
  await invoke$3('Editor.applyWorkspaceEdit', editorUid, changes);
};
const closeWidget$1 = async (editorUid, widgetId, widgetName, focusId) => {
  // @ts-ignore
  await invoke$3('Editor.closeWidget2', editorUid, widgetId, widgetName, focusId);
};
const getWordAt = async (uid, rowIndex, columnIndex) => {
  // @ts-ignore
  const word = await invoke$3('Editor.getWordAt2', uid, rowIndex, columnIndex);
  return word;
};
const getLines = async editorUid => {
  const lines = await invoke$3('Editor.getLines2', editorUid);
  return lines;
};
const getPositionAtCursor$1 = async parentUid => {
  const position = await invoke$3('Editor.getPositionAtCursor', parentUid);
  return position;
};
const getOffsetAtCursor$1 = async editorId => {
  // @ts-ignore
  return await invoke$3('Editor.getOffsetAtCursor', editorId);
};
const getSelections = async editorUid => {
  const selections = await invoke$3('Editor.getSelections2', editorUid);
  return selections;
};
const getWordAtOffset2 = async editorUid => {
  return invoke$3('Editor.getWordAtOffset2', editorUid);
};
const getWordBefore = async (editorUid, rowIndex, columnIndex) => {
  return invoke$3('Editor.getWordBefore2', editorUid, rowIndex, columnIndex);
};
const updateDebugInfo = async info => {
  await invoke$3('Editor.updateDebugInfo', info);
};
const getUri$1 = async editorUid => {
  // @ts-ignore
  return invoke$3('Editor.getUri', editorUid);
};
const getLanguageId$1 = async editorUid => {
  // @ts-ignore
  return invoke$3('Editor.getLanguageId', editorUid);
};
const getProblems = async () => {
  // @ts-ignore
  return invoke$3('Editor.getProblems');
};
const registerMockRpc$2 = commandMap => {
  const mockRpc = createMockRpc({
    commandMap
  });
  set$5(mockRpc);
  return mockRpc;
};

const EditorWorker = {
  __proto__: null,
  activateByEvent: activateByEvent$2,
  applyEdit,
  applyWorkspaceEdit,
  closeWidget: closeWidget$1,
  dispose: dispose$2,
  getLanguageId: getLanguageId$1,
  getLines,
  getOffsetAtCursor: getOffsetAtCursor$1,
  getPositionAtCursor: getPositionAtCursor$1,
  getProblems,
  getSelections,
  getUri: getUri$1,
  getWordAt,
  getWordAtOffset2,
  getWordBefore,
  invoke: invoke$3,
  invokeAndTransfer: invokeAndTransfer$2,
  registerMockRpc: registerMockRpc$2,
  sendMessagePortToExtensionHostWorker: sendMessagePortToExtensionHostWorker$3,
  set: set$5,
  updateDebugInfo
};

const {
  invoke: invoke$2,
  invokeAndTransfer: invokeAndTransfer$1,
  set: set$4,
  dispose: dispose$1
} = create(ExtensionHostWorker);
const executeReferenceProvider = async (id, offset) => {
  // @ts-ignore
  return invoke$2('ExtensionHostReference.executeReferenceProvider', id, offset);
};
const executeFileReferenceProvider = async id => {
  // @ts-ignore
  return invoke$2('ExtensionHostReference.executeFileReferenceProvider', id);
};
const getRuntimeStatus = async extensionId => {
  // @ts-ignore
  return invoke$2('ExtensionHost.getRuntimeStatus', extensionId);
};
const registerMockRpc$1 = commandMap => {
  const mockRpc = createMockRpc({
    commandMap
  });
  set$4(mockRpc);
  return mockRpc;
};

const ExtensionHost = {
  __proto__: null,
  dispose: dispose$1,
  executeFileReferenceProvider,
  executeReferenceProvider,
  getRuntimeStatus,
  invoke: invoke$2,
  invokeAndTransfer: invokeAndTransfer$1,
  registerMockRpc: registerMockRpc$1,
  set: set$4
};

const {
  invoke: invoke$1,
  invokeAndTransfer,
  set: set$3,
  dispose
} = create(RendererWorker$1);
const searchFileHtml = async uri => {
  return invoke$1('ExtensionHost.searchFileWithHtml', uri);
};
const getFilePathElectron = async file => {
  return invoke$1('FileSystemHandle.getFilePathElectron', file);
};
const showContextMenu = async (x, y, id, ...args) => {
  return invoke$1('ContextMenu.show', x, y, id, ...args);
};
const getElectronVersion = async () => {
  return invoke$1('Process.getElectronVersion');
};
const applyBulkReplacement = async bulkEdits => {
  await invoke$1('BulkReplacement.applyBulkReplacement', bulkEdits);
};
const setColorTheme = async id => {
  // @ts-ignore
  return invoke$1(/* ColorTheme.setColorTheme */'ColorTheme.setColorTheme', /* colorThemeId */id);
};
const getNodeVersion = async () => {
  return invoke$1('Process.getNodeVersion');
};
const getChromeVersion = async () => {
  return invoke$1('Process.getChromeVersion');
};
const getV8Version = async () => {
  return invoke$1('Process.getV8Version');
};
const getFileHandles = async fileIds => {
  const files = await invoke$1('FileSystemHandle.getFileHandles', fileIds);
  return files;
};
const setWorkspacePath = async path => {
  await invoke$1('Workspace.setPath', path);
};
const registerWebViewInterceptor = async (id, port) => {
  await invokeAndTransfer('WebView.registerInterceptor', id, port);
};
const unregisterWebViewInterceptor = async id => {
  await invoke$1('WebView.unregisterInterceptor', id);
};
const sendMessagePortToEditorWorker$2 = async (port, rpcId) => {
  const command = 'HandleMessagePort.handleMessagePort';
  // @ts-ignore
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToEditorWorker', port, command, rpcId);
};
const sendMessagePortToErrorWorker = async (port, rpcId) => {
  const command = 'Errors.handleMessagePort';
  // @ts-ignore
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToErrorWorker', port, command, rpcId);
};
const sendMessagePortToMarkdownWorker = async (port, rpcId) => {
  const command = 'Markdown.handleMessagePort';
  // @ts-ignore
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToMarkdownWorker', port, command, rpcId);
};
const sendMessagePortToFileSystemWorker = async (port, rpcId) => {
  const command = 'FileSystem.handleMessagePort';
  // @ts-ignore
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToFileSystemWorker', port, command, rpcId);
};
const readFile$2 = async uri => {
  return invoke$1('FileSystem.readFile', uri);
};
const getWebViewSecret = async key => {
  // @ts-ignore
  return invoke$1('WebView.getSecret', key);
};
const setWebViewPort = async (uid, port, origin, portType) => {
  return invokeAndTransfer('WebView.setPort', uid, port, origin, portType);
};
const setFocus = key => {
  return invoke$1('Focus.setFocus', key);
};
const getFileIcon = async options => {
  return invoke$1('IconTheme.getFileIcon', options);
};
const getColorThemeNames = async () => {
  return invoke$1('ColorTheme.getColorThemeNames');
};
const disableExtension = async id => {
  // @ts-ignore
  return invoke$1('ExtensionManagement.disable', id);
};
const enableExtension = async id => {
  // @ts-ignore
  return invoke$1('ExtensionManagement.enable', id);
};
const handleDebugChange = async params => {
  // @ts-ignore
  return invoke$1('Run And Debug.handleChange', params);
};
const getFolderIcon = async options => {
  return invoke$1('IconTheme.getFolderIcon', options);
};
const closeWidget = async widgetId => {
  return invoke$1('Viewlet.closeWidget', widgetId);
};
const sendMessagePortToExtensionHostWorker$2 = async (port, rpcId = 0) => {
  const command = 'HandleMessagePort.handleMessagePort2';
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
};
const sendMessagePortToSearchProcess = async port => {
  await invokeAndTransfer('SendMessagePortToElectron.sendMessagePortToElectron', port, 'HandleMessagePortForSearchProcess.handleMessagePortForSearchProcess');
};
const confirm = async (message, options) => {
  // @ts-ignore
  const result = await invoke$1('ConfirmPrompt.prompt', message, options);
  return result;
};
const getRecentlyOpened = async () => {
  return invoke$1(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
};
const getKeyBindings = async () => {
  return invoke$1('KeyBindingsInitial.getKeyBindings');
};
const writeClipBoardText = async text => {
  await invoke$1('ClipBoard.writeText', /* text */text);
};
const writeClipBoardImage = async blob => {
  // @ts-ignore
  await invoke$1('ClipBoard.writeImage', /* text */blob);
};
const searchFileMemory = async uri => {
  // @ts-ignore
  return invoke$1('ExtensionHost.searchFileWithMemory', uri);
};
const searchFileFetch = async uri => {
  return invoke$1('ExtensionHost.searchFileWithFetch', uri);
};
const showMessageBox = async options => {
  return invoke$1('ElectronDialog.showMessageBox', options);
};
const handleDebugResumed = async params => {
  await invoke$1('Run And Debug.handleResumed', params);
};
const openWidget = async name => {
  await invoke$1('Viewlet.openWidget', name);
};
const getIcons$1 = async requests => {
  const icons = await invoke$1('IconTheme.getIcons', requests);
  return icons;
};
const activateByEvent$1 = event => {
  return invoke$1('ExtensionHostManagement.activateByEvent', event);
};
const setAdditionalFocus = focusKey => {
  // @ts-ignore
  return invoke$1('Focus.setAdditionalFocus', focusKey);
};
const getActiveEditorId$1 = () => {
  // @ts-ignore
  return invoke$1('GetActiveEditor.getActiveEditorId');
};
const getWorkspacePath = () => {
  return invoke$1('Workspace.getPath');
};
const sendMessagePortToRendererProcess = async port => {
  const command = 'HandleMessagePort.handleMessagePort';
  // @ts-ignore
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToRendererProcess', port, command, DebugWorker);
};
const getPreference = async key => {
  return await invoke$1('Preferences.get', key);
};
const getAllExtensions = async () => {
  return invoke$1('ExtensionManagement.getAllExtensions');
};
const rerenderEditor = async key => {
  // @ts-ignore
  return invoke$1('Editor.rerender', key);
};
const handleDebugPaused = async params => {
  await invoke$1('Run And Debug.handlePaused', params);
};
const openUri$1 = async (uri, focus, options) => {
  await invoke$1('Main.openUri', uri, focus, options);
};
const sendMessagePortToSyntaxHighlightingWorker = async port => {
  await invokeAndTransfer(
  // @ts-ignore
  'SendMessagePortToSyntaxHighlightingWorker.sendMessagePortToSyntaxHighlightingWorker', port, 'HandleMessagePort.handleMessagePort2');
};
const handleDebugScriptParsed = async script => {
  await invoke$1('Run And Debug.handleScriptParsed', script);
};
const getWindowId = async () => {
  return invoke$1('GetWindowId.getWindowId');
};
const getBlob = async uri => {
  // @ts-ignore
  return invoke$1('FileSystem.getBlob', uri);
};
const getExtensionCommands = async () => {
  return invoke$1('ExtensionHost.getCommands');
};
const showErrorDialog = async errorInfo => {
  // @ts-ignore
  await invoke$1('ErrorHandling.showErrorDialog', errorInfo);
};
const getFolderSize = async uri => {
  // @ts-ignore
  return await invoke$1('FileSystem.getFolderSize', uri);
};
const getExtension = async id => {
  // @ts-ignore
  return invoke$1('ExtensionManagement.getExtension', id);
};
const getMarkdownDom = async html => {
  // @ts-ignore
  return invoke$1('Markdown.getVirtualDom', html);
};
const renderMarkdown = async (markdown, options) => {
  // @ts-ignore
  return invoke$1('Markdown.renderMarkdown', markdown, options);
};
const openNativeFolder = async uri => {
  // @ts-ignore
  await invoke$1('OpenNativeFolder.openNativeFolder', uri);
};
const uninstallExtension = async id => {
  return invoke$1('ExtensionManagement.uninstall', id);
};
const installExtension = async id => {
  // @ts-ignore
  return invoke$1('ExtensionManagement.install', id);
};
const openExtensionSearch = async () => {
  // @ts-ignore
  return invoke$1('SideBar.openViewlet', 'Extensions');
};
const setExtensionsSearchValue = async searchValue => {
  // @ts-ignore
  return invoke$1('Extensions.handleInput', searchValue);
};
const openExternal = async uri => {
  // @ts-ignore
  await invoke$1('Open.openExternal', uri);
};
const openUrl = async uri => {
  // @ts-ignore
  await invoke$1('Open.openUrl', uri);
};
const getAllPreferences = async () => {
  // @ts-ignore
  return invoke$1('Preferences.getAll');
};
const showSaveFilePicker = async () => {
  // @ts-ignore
  return invoke$1('FilePicker.showSaveFilePicker');
};
const getLogsDir = async () => {
  // @ts-ignore
  return invoke$1('PlatformPaths.getLogsDir');
};
const registerMockRpc = commandMap => {
  const mockRpc = createMockRpc({
    commandMap
  });
  set$3(mockRpc);
  return mockRpc;
};

const RendererWorker = {
  __proto__: null,
  activateByEvent: activateByEvent$1,
  applyBulkReplacement,
  closeWidget,
  confirm,
  disableExtension,
  dispose,
  enableExtension,
  getActiveEditorId: getActiveEditorId$1,
  getAllExtensions,
  getAllPreferences,
  getBlob,
  getChromeVersion,
  getColorThemeNames,
  getElectronVersion,
  getExtension,
  getExtensionCommands,
  getFileHandles,
  getFileIcon,
  getFilePathElectron,
  getFolderIcon,
  getFolderSize,
  getIcons: getIcons$1,
  getKeyBindings,
  getLogsDir,
  getMarkdownDom,
  getNodeVersion,
  getPreference,
  getRecentlyOpened,
  getV8Version,
  getWebViewSecret,
  getWindowId,
  getWorkspacePath,
  handleDebugChange,
  handleDebugPaused,
  handleDebugResumed,
  handleDebugScriptParsed,
  installExtension,
  invoke: invoke$1,
  invokeAndTransfer,
  openExtensionSearch,
  openExternal,
  openNativeFolder,
  openUri: openUri$1,
  openUrl,
  openWidget,
  readFile: readFile$2,
  registerMockRpc,
  registerWebViewInterceptor,
  renderMarkdown,
  rerenderEditor,
  searchFileFetch,
  searchFileHtml,
  searchFileMemory,
  sendMessagePortToEditorWorker: sendMessagePortToEditorWorker$2,
  sendMessagePortToErrorWorker,
  sendMessagePortToExtensionHostWorker: sendMessagePortToExtensionHostWorker$2,
  sendMessagePortToFileSystemWorker,
  sendMessagePortToMarkdownWorker,
  sendMessagePortToRendererProcess,
  sendMessagePortToSearchProcess,
  sendMessagePortToSyntaxHighlightingWorker,
  set: set$3,
  setAdditionalFocus,
  setColorTheme,
  setExtensionsSearchValue,
  setFocus,
  setWebViewPort,
  setWorkspacePath,
  showContextMenu,
  showErrorDialog,
  showMessageBox,
  showSaveFilePicker,
  uninstallExtension,
  unregisterWebViewInterceptor,
  writeClipBoardImage,
  writeClipBoardText
};

const {
  set: set$2,
  activateByEvent,
  sendMessagePortToEditorWorker: sendMessagePortToEditorWorker$1,
  getIcons,
  getActiveEditorId,
  sendMessagePortToExtensionHostWorker: sendMessagePortToExtensionHostWorker$1,
  readFile: readFile$1,
  openUri
} = RendererWorker;

const selectIndexLead = async (state, index) => {
  const uri = getUri$2(state, index);
  // TODO open file and jump to line
  await openUri(uri);
  return {
    ...state,
    focusedIndex: index
  };
};

const selectIndex = async (state, index) => {
  if (index < 0 || index >= state.displayReferences.length) {
    return state;
  }
  const displayReference = state.displayReferences[index];
  switch (displayReference.type) {
    case Leaf:
      return await selectIndexLead(state, index);
    case Expanded:
      return selectIndexExpanded(state, index);
    case Collapsed:
      return selectIndexCollapsed(state, index);
    default:
      return state;
  }
};

const handleClickReference = async (state, dataIndex) => {
  const index = Number.parseInt(dataIndex, 10);
  if (Number.isNaN(index)) {
    return state;
  }
  return await selectIndex(state, index);
};

const sendMessagePortToEditorWorker = sendMessagePortToEditorWorker$1;

const createEditorWorkerRpc = async () => {
  try {
    const rpc = await TransferMessagePortRpcParent.create({
      commandMap: {},
      send: port => sendMessagePortToEditorWorker(port, 0)
    });
    return rpc;
  } catch (error) {
    throw new VError(error, `Failed to create editor worker rpc`);
  }
};

const {
  set: set$1,
  getOffsetAtCursor,
  getPositionAtCursor,
  getLanguageId,
  getUri
} = EditorWorker;

const initializeEditorWorker = async () => {
  try {
    const rpc = await createEditorWorkerRpc();
    set$1(rpc);
  } catch {
    // ignore
  }
};

const sendMessagePortToExtensionHostWorker = sendMessagePortToExtensionHostWorker$1;

const createExtensionHostRpc = async () => {
  try {
    const rpc = await TransferMessagePortRpcParent.create({
      commandMap: {},
      send: sendMessagePortToExtensionHostWorker
    });
    return rpc;
  } catch (error) {
    throw new VError(error, `Failed to create extension host rpc`);
  }
};

const {
  invoke,
  set} = ExtensionHost;

const initializeExtensionHost = async () => {
  const rpc = await createExtensionHostRpc();
  set(rpc);
};

const initialize = async () => {
  await Promise.all([initializeExtensionHost(), initializeEditorWorker()]);
};

const restoreFocusedIndex = state => {
  if (state && typeof state === 'object' && 'focusedIndex' in state && typeof state.focusedIndex === 'number') {
    return state.focusedIndex;
  }
  return -1;
};
const restoreOffset = state => {
  if (state && typeof state === 'object' && 'offset' in state && typeof state.offset === 'number') {
    return state.offset;
  }
  return -1;
};
const restoreUri = state => {
  if (state && typeof state === 'object' && 'uri' in state && typeof state.uri === 'string') {
    return state.uri;
  }
  return '';
};
const restoreLanguageId = state => {
  if (state && typeof state === 'object' && 'language' in state && typeof state.language === 'string') {
    return state.language;
  }
  return '';
};
const restorePosition = state => {
  if (state && typeof state === 'object' && 'position' in state && typeof state.position === 'object') {
    return state.position;
  }
  return {};
};
const restoreState = input => {
  const focusedIndex = restoreFocusedIndex(input);
  const offset = restoreOffset(input);
  const uri = restoreUri(input);
  const languageId = restoreLanguageId(input);
  const position = restorePosition(input);
  return {
    focusedIndex,
    offset,
    uri,
    languageId,
    position
  };
};

const getUniqueObjectCount = (objects, key) => {
  array(objects);
  string(key);
  const seen = [];
  for (const object of objects) {
    const value = object[key];
    if (!seen.includes(value)) {
      seen.push(value);
    }
  }
  return seen.length;
};

const getFileCount = references => {
  return getUniqueObjectCount(references, 'uri');
};

const emptyObject = {};
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
const i18nString = (key, placeholders = emptyObject) => {
  if (placeholders === emptyObject) {
    return key;
  }
  const replacer = (match, rest) => {
    return placeholders[rest];
  };
  return key.replaceAll(RE_PLACEHOLDER, replacer);
};

const NoResults = 'No Results';
const OneResultInOneFile = '1 result in 1 file';
const ManyResultsInOneFile = '{PH1} results in 1 file';
const ManyResultsInManyFiles = '{PH1} results in {PH2} files';
const Locations = 'Locations';
const Refresh$1 = 'Refresh';
const Clear = 'Clear';
const CollapseAll$1 = 'Collapse All';

const noResults = () => {
  return i18nString(NoResults);
};
const oneResultInOneFile = () => {
  return i18nString(OneResultInOneFile);
};
const locations = () => {
  return i18nString(Locations);
};
const manyResultsInOneFile = resultCount => {
  return i18nString(ManyResultsInOneFile, {
    PH1: resultCount
  });
};
const manyResultsInManyFiles = (resultCount, fileCount) => {
  return i18nString(ManyResultsInManyFiles, {
    PH1: resultCount,
    PH2: fileCount
  });
};
const refresh$1 = () => {
  return i18nString(Refresh$1);
};
const clear = () => {
  return i18nString(Clear);
};
const collapseAll = () => {
  return i18nString(CollapseAll$1);
};

const getMessage = (resultCount, fileCount) => {
  number(resultCount);
  number(fileCount);
  if (resultCount === 0) {
    return noResults();
  }
  if (resultCount === 1 && fileCount === 1) {
    return oneResultInOneFile();
  }
  if (fileCount === 1) {
    return manyResultsInOneFile(resultCount);
  }
  return manyResultsInManyFiles(resultCount, fileCount);
};

const executeProvider = async ({
  event,
  method,
  params
}) => {
  await activateByEvent(event);
  // @ts-ignore
  const result = await invoke(method, ...params);
  return result;
};

const OnReferences = 'onReferences';

const ReferenceExecuteReferenceProvider2 = 'ExtensionHostReference.executeReferenceProvider2';

const executeReferenceProvider2 = async (uri, languageId, offset, position) => {
  const result = await executeProvider({
    event: OnReferences,
    method: ReferenceExecuteReferenceProvider2,
    params: [uri, languageId, offset, position]
  });
  array(result);
  return result;
};

const readFile = readFile$1;

const NewLine = '\n';

const getNewLineIndex = (string, startIndex = undefined) => {
  return string.indexOf(NewLine, startIndex);
};

const getLineText = (content, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex) => {
  let newLineIndex = 0;
  let rowIndex = 0;
  while (newLineIndex !== -1) {
    if (rowIndex++ >= startRowIndex) {
      break;
    }
    newLineIndex = getNewLineIndex(content, newLineIndex + 1);
  }
  if (content[newLineIndex] === NewLine) {
    newLineIndex++;
  }
  let nextIndex = getNewLineIndex(content, newLineIndex);
  if (nextIndex === -1) {
    nextIndex = content.length;
  }
  const lineText = content.slice(newLineIndex, nextIndex).trim();
  return lineText;
};

const getReferenceWithPreview = async reference => {
  const content = await readFile(reference.uri);
  const lineText = getLineText(content, reference.startRowIndex);
  return {
    ...reference,
    lineText
  };
};

const getReferencesWithPreview = async references => {
  const withPreview = await Promise.all(references.map(getReferenceWithPreview));
  return withPreview;
};

const getReferences2 = async (uri, languageId, offset, position) => {
  const references = await executeReferenceProvider2(uri, languageId, offset, position);
  const withPreview = await getReferencesWithPreview(references);
  return withPreview;
};

const getSimpleIconRequestType = direntType => {
  return 1;
};

const toSimpleIconRequest = request => {
  const {
    uri
  } = request;
  const name = getBaseName(uri);
  return {
    name: name,
    type: getSimpleIconRequestType()
  };
};

// TODO add more exact types
const requestFileIcons = async references => {
  if (references.length === 0) {
    return [];
  }
  const simpleRequests = references.map(toSimpleIconRequest);
  const icons = await getIcons(simpleRequests);
  return icons;
};

const updateReferences = async (state, uri, languageId, offset, position) => {
  const references = await getReferences2(uri, languageId, offset, position);
  const icons = await requestFileIcons(references);
  const collapseduris = [];
  const displayReferences = getDisplayReferences(references, icons, collapseduris);
  const fileCount = getFileCount(references);
  const message = getMessage(references.length, fileCount);
  return {
    ...state,
    references,
    displayReferences,
    message,
    offset,
    uri,
    languageId
  };
};
const getAndUpdateReferences = async state => {
  // TODO need to wait for editor
  const editorId = await getActiveEditorId();
  if (editorId === -1) {
    return {
      ...state,
      message: 'No Editor found'
    };
  }
  const uri = await getUri(editorId);
  const languageId = await getLanguageId(editorId);
  const offset = await getOffsetAtCursor(editorId);
  const position = await getPositionAtCursor(editorId);
  return updateReferences(state, uri, languageId, offset, position);
};

const isMemory = uri => {
  return uri.startsWith('memfs://');
};
const loadContent = async (state, savedState) => {
  try {
    const {
      uri,
      offset,
      languageId,
      position
    } = restoreState(savedState);
    if (uri && !isMemory(uri)) {
      return updateReferences(state, uri, languageId, offset, position);
    }
    return getAndUpdateReferences(state);
  } catch (error) {
    // TODO send error to error worker
    return {
      ...state,
      message: `${error}`
    };
  }
};

const refresh = async state => {
  return state;
};

const FileIcon = 'FileIcon';
const Highlight = 'Highlight';
const Label = 'Label';
const LocationList = 'LocationList';
const LocationsMessage = 'LocationsMessage';
const TreeItem = 'TreeItem';
const IconButton = 'IconButton';

const HandleClickReference = 'handleClickReference';

const getCollapsedVirtualDom = location => {
  const {
    index,
    name
  } = location;
  return [{
    type: Div,
    className: TreeItem,
    ariaExpanded: false,
    id: `Reference-${index}`,
    'data-index': index,
    role: 'treeitem',
    childCount: 1
  }, text(name)];
};

const getExpandedVirtualDom = location => {
  const {
    index,
    name,
    icon
  } = location;
  return [{
    type: Div,
    className: TreeItem,
    ariaExpanded: true,
    id: `Reference-${index}`,
    'data-index': index,
    role: 'treeitem',
    childCount: 2,
    paddingLeft: '1rem'
  }, {
    type: Img,
    className: FileIcon,
    src: icon
  }, text(name)];
};

const getLabelDomHighlight = (lineText, startOffset, endOffset) => {
  const before = lineText.slice(0, startOffset);
  const middle = lineText.slice(startOffset, endOffset);
  const end = lineText.slice(endOffset);
  return [{
    type: Div,
    className: Label,
    childCount: 3
  }, text(before), {
    type: Span,
    className: Highlight,
    childCount: 1
  }, text(middle), text(end)];
};

const getLabelDomNoHighlight = lineText => {
  return [{
    type: Div,
    className: Label,
    childCount: 1
  }, text(lineText || '(empty line)')];
};

const getLabelDom = location => {
  const {
    lineText,
    startOffset,
    endOffset
  } = location;
  if (startOffset === endOffset) {
    return getLabelDomNoHighlight(lineText);
  }
  return getLabelDomHighlight(lineText, startOffset ?? 0, endOffset ?? 0);
};

const getLeafVirtualDom = location => {
  const {
    index
  } = location;
  return [{
    type: Div,
    className: TreeItem,
    id: `Reference-${index}`,
    'data-index': index,
    role: 'treeitem',
    childCount: 1,
    paddingLeft: '2rem'
  }, ...getLabelDom(location)];
};

const getLocationVirtualDom = location => {
  const {
    type
  } = location;
  switch (type) {
    case Leaf:
      return getLeafVirtualDom(location);
    case Collapsed:
      return getCollapsedVirtualDom(location);
    case Expanded:
      return getExpandedVirtualDom(location);
    default:
      return [];
  }
};

const getLocationsVirtualDom = (locations$1, message) => {
  return [{
    type: Div,
    className: 'Viewlet Locations',
    onMouseDown: HandleClickReference,
    childCount: 2
  }, {
    type: Div,
    className: LocationsMessage,
    id: 'LocationsMessage',
    role: Status,
    childCount: 1
  }, text(message), {
    type: Div,
    className: LocationList,
    role: Tree,
    ariaLabel: locations(),
    tabIndex: 0,
    ariaDescribedBy: 'LocationsMessage',
    childCount: locations$1.length
  }, ...locations$1.flatMap(getLocationVirtualDom)];
};

const renderItems = (oldState, newState) => {
  const dom = getLocationsVirtualDom(newState.displayReferences, newState.message);
  return ['Viewlet.setDom2', newState.id, dom];
};

const getRenderer = diffType => {
  switch (diffType) {
    case RenderItems:
      return renderItems;
    default:
      throw new Error('unknown renderer');
  }
};

const applyRender = (oldState, newState, diffResult) => {
  const commands = [];
  for (const item of diffResult) {
    const fn = getRenderer(item);
    commands.push(fn(oldState, newState));
  }
  return commands;
};

const render2 = (uid, diffResult) => {
  const {
    oldState,
    newState
  } = get$1(uid);
  set$7(uid, newState, newState);
  const commands = applyRender(oldState, newState, diffResult);
  return commands;
};

const Button = 1;

const getIconVirtualDom = (icon, type = Div) => {
  return {
    type,
    className: `MaskIcon MaskIcon${icon}`,
    role: None,
    childCount: 0
  };
};

const getActionButtonVirtualDom = action => {
  const {
    id,
    icon,
    command
  } = action;
  return [{
    type: Button$1,
    className: IconButton,
    title: id,
    'data-command': command,
    childCount: 1
  }, getIconVirtualDom(icon || '')];
};

const ClearAll = 'ClearAll';
const CollapseAll = 'CollapseAll';
const Refresh = 'Refresh';

const getActionButtons = () => {
  return [{
    type: Button,
    id: refresh$1(),
    icon: Refresh,
    command: 'refresh'
  }, {
    type: Button,
    id: clear(),
    icon: ClearAll,
    command: 'clear'
  }, {
    type: Button,
    id: collapseAll(),
    icon: CollapseAll,
    command: 'collapseAll'
  }];
};
const renderActions = () => {
  const buttons = getActionButtons();
  return [{
    type: Div,
    className: 'Actions',
    childCount: buttons.length
  }, ...buttons.flatMap(getActionButtonVirtualDom)];
};

const renderEventListeners = () => {
  return [{
    name: HandleClickReference,
    params: ['handleClickReference', 'event.target.dataset.index']
  }];
};

const saveState = id => {
  const {
    newState
  } = get$1(id);
  const {
    message,
    focusedIndex,
    offset,
    uri,
    languageId
  } = newState;
  return {
    message,
    focusedIndex,
    offset,
    uri,
    languageId
  };
};

const commandMap = {
  'References.clear': wrapCommand(clear$1),
  'References.create': create$1,
  'References.diff2': diff2,
  'References.dispose': dispose$3,
  'References.focusFirst': wrapCommand(focusFirst),
  'References.focusIndex': wrapCommand(focusIndex),
  'References.focusLast': wrapCommand(focusLast),
  'References.focusNext': wrapCommand(focusNext),
  'References.focusPrevious': wrapCommand(focusPrevious),
  'References.getCommandIds': getCommandIds,
  'References.getKeyBindings': getKeyBindings$1,
  'References.handleClickReference': wrapCommand(handleClickReference),
  'References.initialize': initialize,
  'References.loadContent': wrapCommand(loadContent),
  'References.refresh': wrapCommand(refresh),
  'References.render2': render2,
  'References.collapseAll': wrapCommand(collapseAll$1),
  'References.renderActions': renderActions,
  'References.renderEventListeners': renderEventListeners,
  'References.restoreState': restoreState,
  'References.saveState': saveState,
  'References.selectIndex': wrapCommand(selectIndex),
  'References.terminate': terminate
};

const listen = async () => {
  registerCommands(commandMap);
  const rpc = await WebWorkerRpcClient.create({
    commandMap: commandMap
  });
  set$2(rpc);
};

const main = async () => {
  await listen();
};

main();
