UNPKG

@lvce-editor/text-search-worker

Version:
1,922 lines (1,877 loc) 137 kB
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$2 = '\n'; const getNewLineIndex$1 = (string, startIndex = undefined) => { return string.indexOf(NewLine$2, startIndex); }; const mergeStacks = (parent, child) => { if (!child) { return parent; } const parentNewLineIndex = getNewLineIndex$1(parent); const childNewLineIndex = getNewLineIndex$1(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$1 = 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$1; default: return Unknown; } }; const object = value => { const type = getType(value); if (type !== Object$1) { throw new AssertionError('expected value to be of type object'); } }; 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$1 = '\n'; const joinLines$1 = lines => { return lines.join(NewLine$1); }; 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$1); }; 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 Error$3 = 1; const Open = 2; const Close = 3; 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 stringifyCompact = value => { return JSON.stringify(value); }; const parse = content => { if (content === 'undefined') { return null; } try { return JSON.parse(content); } catch (error) { throw new VError(error, 'failed to parse json'); } }; const waitForWebSocketToBeOpen = webSocket => { return getFirstEvent(webSocket, { open: Open, close: Close, error: Error$3 }); }; const create$7 = async ({ webSocket }) => { const firstWebSocketEvent = await waitForWebSocketToBeOpen(webSocket); if (firstWebSocketEvent.type === Error$3) { throw new IpcError(`WebSocket connection error`); } if (firstWebSocketEvent.type === Close) { throw new IpcError('Websocket connection was immediately closed'); } return webSocket; }; class IpcParentWithWebSocket extends Ipc { getData(event) { return parse(event.data); } send(message) { this._rawIpc.send(stringifyCompact(message)); } sendAndTransfer(message) { throw new Error('sendAndTransfer not supported'); } dispose() { this._rawIpc.close(); } onClose(callback) { this._rawIpc.addEventListener('close', callback); } onMessage(callback) { this._rawIpc.addEventListener('message', callback); } } const wrap = webSocket => { return new IpcParentWithWebSocket(webSocket); }; const IpcParentWithWebSocket$1 = { __proto__: null, create: create$7, wrap }; const Two = '2.0'; const create$4$1 = (method, params) => { return { jsonrpc: Two, method, params }; }; const callbacks = Object.create(null); const set$2 = (id, fn) => { callbacks[id] = fn; }; const get$3 = id => { return callbacks[id]; }; const remove$1 = id => { delete callbacks[id]; }; let id = 0; const create$3$2 = () => { return ++id; }; const registerPromise = () => { const id = create$3$2(); const { resolve, promise } = Promise.withResolvers(); set$2(id, resolve); return { id, promise }; }; const create$2$2 = (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 = '\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); }; const splitLines = lines => { return lines.split(NewLine); }; const getCurrentStack = () => { const currentStack = joinLines(splitLines(new Error().stack || '').slice(2)); return currentStack; }; const getNewLineIndex = (string, startIndex = undefined) => { return string.indexOf(NewLine, startIndex); }; const getParentStack = error => { let parentStack = error.stack || error.data || error.message || ''; if (parentStack.startsWith(' at')) { parentStack = error.message + NewLine + 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 + currentStack; } return error; } if (error && error.code && error.code === MethodNotFound) { const restoredError = new JsonRpcError(error.message); const parentStack = getParentStack(error); restoredError.stack = parentStack + NewLine + 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 + error.data.stack + NewLine + 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(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$3(id); if (!fn) { console.log(response); warn(`callback ${id} may already be disposed`); return; } fn(response); remove$1(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$2 = (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$2(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$2(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$2 = (ipc, method, ...params) => { return invokeHelper(ipc, method, params, false); }; const invokeAndTransfer = (ipc, method, ...params) => { return invokeHelper(ipc, method, params, true); }; 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 Error(`command not found ${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$2(ipc, method, ...params); }, invokeAndTransfer(method, ...params) { return invokeAndTransfer(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$1 = async ({ commandMap, send }) => { const { port1, port2 } = new MessageChannel(); await send(port1); return create$5({ commandMap, messagePort: port2 }); }; const TransferMessagePortRpcParent = { __proto__: null, create: create$3$1 }; const create$2$1 = async ({ commandMap, webSocket }) => { // TODO create a commandMap per rpc instance register(commandMap); const rawIpc = await IpcParentWithWebSocket$1.create({ webSocket }); const ipc = IpcParentWithWebSocket$1.wrap(rawIpc); handleIpc(ipc); const rpc = createRpc(ipc); return rpc; }; const Https = 'https:'; const Ws = 'ws:'; const Wss = 'wss:'; const getWebSocketProtocol = locationProtocol => { return locationProtocol === Https ? Wss : Ws; }; const getWebSocketUrl = (type, host, locationProtocol) => { const wsProtocol = getWebSocketProtocol(locationProtocol); return `${wsProtocol}//${host}/websocket/${type}`; }; const getHost = () => { return location.host; }; const getProtocol$1 = () => { return location.protocol; }; const create$1$1 = async ({ commandMap, type }) => { const host = getHost(); const protocol = getProtocol$1(); const wsUrl = getWebSocketUrl(type, host, protocol); const webSocket = new WebSocket(wsUrl); const rpc = await create$2$1({ webSocket, commandMap }); return rpc; }; const WebSocketRpcParent2 = { __proto__: null, create: create$1$1 }; 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 toCommandId = key => { const dotIndex = key.indexOf('.'); return key.slice(dotIndex + 1); }; const create$3 = () => { 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 User = 1; const Script = 2; const Empty$1 = 0; const FocusIgnoreFiles = 1012; const FocusSearch = 1013; const FocusSearchExcludeInput = 1008; const FocusSearchIncludeInput = 1007; const FocusSearchInput = 21; const FocusSearchMatchCase = 32; const FocusSearchOpenEditors = 1011; const FocusSearchPreserveCase = 36; const FocusSearchRegex = 33; const FocusSearchReplaceAll = 35; const FocusSearchReplaceInput = 31; const FocusSearchResults = 22; const FocusSearchWholeWord = 34; const FocusToggleDetails = 1010; const FocusToggleReplace = 1020; const clearSearchResults$1 = state => { return { ...state, value: '', items: [], minLineY: 0, maxLineY: 0, message: '', focus: FocusSearchInput, focusSource: Script, inputSource: Script }; }; const collapseAll$1 = async state => { return state; }; const PreserveCase$2 = 1 << 0; // 1 const UseRegularExpression$2 = 1 << 1; // 2 const ReplaceExpanded = 1 << 2; // 4 const MatchWholeWord$2 = 1 << 3; // 8 const MatchCase$2 = 1 << 4; // 16 const DetailsExpanded = 1 << 5; // 32 const OpenEditors = 1 << 6; // 64 const UseIgnoreFiles = 1 << 7; // 128 const hasDetailsExpanded = flags => { return (flags & DetailsExpanded) === DetailsExpanded; }; const collapseDetails = state => { const { flags } = state; return { ...state, flags: flags & -33, focus: FocusSearchInput, focusSource: Script }; }; const rpcs = Object.create(null); const set$g = (id, rpc) => { rpcs[id] = rpc; }; const get$2 = id => { return rpcs[id]; }; /* eslint-disable @typescript-eslint/explicit-function-return-type */ const create$2 = rpcId => { return { // @ts-ignore invoke(method, ...params) { const rpc = get$2(rpcId); // @ts-ignore return rpc.invoke(method, ...params); }, // @ts-ignore invokeAndTransfer(method, ...params) { const rpc = get$2(rpcId); // @ts-ignore return rpc.invokeAndTransfer(method, ...params); }, set(rpc) { set$g(rpcId, rpc); }, async dispose() { const rpc = get$2(rpcId); await rpc.dispose(); } }; }; const RendererWorker$1 = 1; const SearchProcess$1 = 77; const RpcId = { __proto__: null, SearchProcess: SearchProcess$1}; const { invoke: invoke$3, invokeAndTransfer: invokeAndTransfer$3, set: set$3} = create$2(RendererWorker$1); const showContextMenu$1 = async (x, y, id, ...args) => { return invoke$3('ContextMenu.show', x, y, id, ...args); }; const getFileIcon$2 = async options => { return invoke$3('IconTheme.getFileIcon', options); }; const sendMessagePortToSearchProcess$1 = async port => { await invokeAndTransfer$3('SendMessagePortToElectron.sendMessagePortToElectron', port, 'HandleMessagePortForSearchProcess.handleMessagePortForSearchProcess'); }; const writeClipBoardText$1 = async text => { await invoke$3('ClipBoard.writeText', /* text */text); }; const openUri$2 = async (uri, focus, options) => { await invoke$3('Main.openUri', uri, focus, options); }; const RendererWorker = { __proto__: null, getFileIcon: getFileIcon$2, invoke: invoke$3, openUri: openUri$2, sendMessagePortToSearchProcess: sendMessagePortToSearchProcess$1, set: set$3, showContextMenu: showContextMenu$1, writeClipBoardText: writeClipBoardText$1 }; const createLazyRpc = rpcId => { let rpcPromise; let factory; const createRpc = async () => { const rpc = await factory(); set$g(rpcId, rpc); }; const ensureRpc = async () => { if (!rpcPromise) { rpcPromise = createRpc(); } await rpcPromise; }; return { setFactory(value) { factory = value; }, async invoke(method, ...params) { await ensureRpc(); const rpc = get$2(rpcId); return rpc.invoke(method, ...params); } }; }; const { getFileIcon: getFileIcon$1, invoke: invoke$1, openUri: openUri$1, sendMessagePortToSearchProcess, set: set$1, showContextMenu, writeClipBoardText } = RendererWorker; const copy = async state => { const { items, listFocusedIndex } = state; if (listFocusedIndex === -1) { return state; } const item = items[listFocusedIndex]; await writeClipBoardText(item.text); return state; }; const minimumSliderSize = 20; const { get: get$1, set, wrapCommand } = create$3(); const List$1 = 1; const create$1 = ({ itemHeight, headerHeight = 0, minimumSliderSize = 20 }) => { return { deltaY: 0, minLineY: 0, maxLineY: 0, finalDeltaY: 0, itemHeight, headerHeight, items: [], listItems: [], minimumSliderSize, focusedIndex: -1, touchOffsetY: 0, touchTimeStamp: 0, touchDifference: 0, scrollBarHeight: 0, scrollBarActive: false }; }; const create = (uid, x, y, width, height, workspacePath, assetDir, itemHeight, value = '', replacement = '', platform) => { const state = { uid, searchResults: [], stats: {}, value, disposed: false, fileCount: 0, x, y, width, height, ...create$1({ itemHeight: itemHeight || 22, minimumSliderSize: minimumSliderSize, headerHeight: 61 // TODO }), threads: 0, replacement, matchCount: 0, listFocused: false, listFocusedIndex: -1, inputSource: User, workspacePath: workspacePath, includeValue: '', excludeValue: '', focus: Empty$1, loaded: false, message: '', collapsedPaths: [], icons: [], assetDir, deltaY: 0, finalDeltaY: 0, focused: false, focusedIndex: -1, handleOffset: 0, focusSource: User, flags: 0, platform, searchInputErrorMessage: '', history: [], historyIndex: -1, viewMode: List$1, incrementalSearch: false, searchId: '', useChevrons: true, useFileIcons: true }; set(uid, state, state); return state; }; const RenderItems = 1; const RenderFocus = 2; const RenderValue = 3; const RenderReplaceValue = 4; const RenderIncludeValue = 5; const RenderExcludeValue = 6; const RenderFocusContext = 7; const diffType$5 = RenderExcludeValue; const isEqual$6 = (oldState, newState) => { return oldState.excludeValue === newState.excludeValue || newState.inputSource === User; }; const diffType$4 = RenderFocus; const isEqual$5 = (oldState, newState) => { return oldState.focus === newState.focus || newState.focusSource === User; }; const isEqual$4 = (oldState, newState) => { return oldState.focus === newState.focus; }; const diffType$3 = RenderIncludeValue; const isEqual$3 = (oldState, newState) => { return oldState.includeValue === newState.includeValue || newState.inputSource === User; }; const diffType$2 = RenderItems; const isEqual$2 = (oldState, newState) => { return oldState.collapsedPaths === newState.collapsedPaths && oldState.deltaY === newState.deltaY && oldState.flags === newState.flags && oldState.focus === newState.focus && oldState.icons === newState.icons && oldState.items === newState.items && oldState.listFocused === newState.listFocused && oldState.listFocusedIndex === newState.listFocusedIndex && oldState.loaded === newState.loaded && oldState.maxLineY === newState.maxLineY && oldState.message === newState.message && oldState.minLineY === newState.minLineY && oldState.replacement === newState.replacement && oldState.searchInputErrorMessage === newState.searchInputErrorMessage; }; const diffType$1 = RenderReplaceValue; const isEqual$1 = (oldState, newState) => { return oldState.replacement === newState.replacement || newState.inputSource === User; }; const diffType = RenderValue; const isEqual = (oldState, newState) => { return oldState.value === newState.value || newState.inputSource === User; }; const modules = [isEqual$2, isEqual$5, isEqual$3, isEqual$6, isEqual$1, isEqual, isEqual$4]; const numbers = [diffType$2, diffType$4, diffType$3, diffType$5, diffType$1, diffType, RenderFocusContext]; const diff$1 = (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$1(oldState, newState); return diffResult; }; // based on https://github.com/microsoft/vscode/blob/c0769274fa136b45799edeccc0d0a2f645b75caf/src/vs/base/common/arrays.ts#L625 (License MIT) const remove = (array, index, deleteCount) => { return array.toSpliced(index, deleteCount); }; 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 ClearSearchResults = 'Clear Search Results'; const CollapseAll$1 = 'Collapse All'; const ConfirmReplaceManyOccurrencesInManyFiles = "Replace {PH1} occurrences across {PH2} files with '{PH3}'"; const ConfirmReplaceManyOccurrencesInManyFilesNoValue = 'Replace {PH1} occurrences across {PH2} files'; const ConfirmReplaceManyOccurrencesInOneFile = "Replace {PH1} occurrences across 1 file with '{PH2}'"; const ConfirmReplaceManyOccurrencesInOneFileNoValue = 'Replace {PH1} occurrences across 1 file'; const ConfirmReplaceOneOccurrenceInOneFile = "Replace 1 occurrence across 1 file with '{PH1}'"; const ConfirmReplaceOneOccurrenceInOneFileNoValue = 'Replace 1 occurrence across 1 file'; const Exclude = 'Exclude'; const FilesToExclude$1 = 'Files to Exclude'; const FilesToInclude$1 = 'Files to Include'; const Include = 'Include'; const ManyResultsInManyFiles = '{PH1} results in {PH2} files'; const ManyResultsInOneFile = '{PH1} results in 1 file'; const MatchCase$1 = 'Match Case'; const MatchWholeWord$1 = 'Match Whole Word'; const NoResults = 'No results found'; const Oneresult = '1 result in 1 file'; const OpenNewSearchEditor = 'Open New Search Editor'; const PreserveCase$1 = 'Preserve Case'; const Refresh$1 = 'Refresh'; const Replace = 'Replace'; const ReplaceAll$1 = 'Replace All'; const ReplacedManyOccurrencesInManyFiles = "Replaced {PH1} occurrences across {PH2} files with '{PH3}'"; const ReplacedOneOccurrenceInOneFile = "Replaced 1 occurrence across 1 file with '{PH1}'"; const ReplaceForHistory = 'Replace (⇅ for history)'; const Search$2 = 'Search'; const SearchForHistory = 'Search (⇅ for history)'; const SearchOnlyOpenEditors$1 = 'Search Only Open Editors'; const ToggleReplace$1 = 'Toggle Replace'; const ToggleSearchDetails$1 = 'Toggle Search Details'; const UseExcludeSettings$1 = 'Use Exclude Settings'; const UseRegularExpression$1 = 'Use Regular Expression'; const ViewAsTree = 'View as Tree'; const noResults = () => { return i18nString(NoResults); }; const oneResult = () => { return i18nString(Oneresult); }; const toggleReplace$1 = () => { return i18nString(ToggleReplace$1); }; const matchCase = () => { return i18nString(MatchCase$1); }; const preserveCase = () => { return i18nString(PreserveCase$1); }; const matchWholeWord = () => { return i18nString(MatchWholeWord$1); }; const toggleSearchDetails = () => { return i18nString(ToggleSearchDetails$1); }; const useRegularExpression = () => { return i18nString(UseRegularExpression$1); }; const manyResultsInOneFile = resultCount => { return i18nString(ManyResultsInOneFile, { PH1: resultCount }); }; const manyResultsInManyFiles = (resultCount, fileResultCount) => { return i18nString(ManyResultsInManyFiles, { PH1: resultCount, PH2: fileResultCount }); }; const confirmReplaceOneOccurrenceInOneFile = replacement => { return i18nString(ConfirmReplaceOneOccurrenceInOneFile, { PH1: replacement }); }; const confirmReplaceOneOccurrenceInOneFileNoValue = () => { return i18nString(ConfirmReplaceOneOccurrenceInOneFileNoValue); }; const confirmReplaceManyOccurrencesInOneFile = (matchCount, replacement) => { return i18nString(ConfirmReplaceManyOccurrencesInOneFile, { PH1: matchCount, PH2: replacement }); }; const confirmReplaceManyOccurrencesInOneFileNoValue = matchCount => { return i18nString(ConfirmReplaceManyOccurrencesInOneFileNoValue, { PH1: matchCount }); }; const confirmReplaceManyOccurrencesInManyFiles = (matchCount, fileCount, replacement) => { return i18nString(ConfirmReplaceManyOccurrencesInManyFiles, { PH1: matchCount, PH2: fileCount, PH3: replacement }); }; const confirmReplaceManyOccurrencesInManyFilesNoValue = (matchCount, fileCount) => { return i18nString(ConfirmReplaceManyOccurrencesInManyFilesNoValue, { PH1: matchCount, PH2: fileCount }); }; const replacedOneOccurrenceInOneFile = replacement => { return i18nString(ReplacedOneOccurrenceInOneFile, { PH1: replacement }); }; const replacedManyOccurrencesInOneFile = (matchCount, replacement) => { return i18nString(ReplacedOneOccurrenceInOneFile, { PH1: matchCount, PH2: replacement }); }; const replacedManyOccurrencesInManyFiles = (matchCount, fileCount, replacement) => { return i18nString(ReplacedManyOccurrencesInManyFiles, { PH1: matchCount, PH2: fileCount, PH3: replacement }); }; const replaceAll$1 = () => { return i18nString(ReplaceAll$1); }; const replace = () => { return i18nString(Replace); }; const refresh$1 = () => { return i18nString(Refresh$1); }; const clearSearchResults = () => { return i18nString(ClearSearchResults); }; const openNewSearchEditor = () => { return i18nString(OpenNewSearchEditor); }; const viewAsTree$1 = () => { return i18nString(ViewAsTree); }; const collapseAll = () => { return i18nString(CollapseAll$1); }; const filesToInclude = () => { return i18nString(FilesToInclude$1); }; const include = () => { return i18nString(Include); }; const exclude = () => { return i18nString(Exclude); }; const filesToExclude = () => { return i18nString(FilesToExclude$1); }; const searchOnlyOpenEditors = () => { return i18nString(SearchOnlyOpenEditors$1); }; const useExcludeSettings = () => { return i18nString(UseExcludeSettings$1); }; const searchForHistory = () => { return i18nString(SearchForHistory); }; const search = () => { return i18nString(Search$2); }; const replaceForHistory = () => { return i18nString(ReplaceForHistory); }; const getStatusMessage = (resultCount, fileResultCount) => { if (resultCount === 0) { return noResults(); } if (resultCount === 1) { return oneResult(); } if (fileResultCount === 1) { return manyResultsInOneFile(resultCount); } return manyResultsInManyFiles(resultCount, fileResultCount); }; const File = 1; const Match = 2; const getSetSize = (items, index) => { let setSize = 0; for (let i = index + 1; i < items.length; i++) { if (items[i].type === File) { break; } setSize++; } return setSize; }; const getRemoveIndicesFile = (items, item, index, matchCount, fileCount) => { const setSize = getSetSize(items, index); return { startIndex: index, removeCount: setSize + 1, newFocusedIndex: index + setSize + 1 < items.length ? index : index - 1, newFileCount: fileCount - 1, newMatchCount: matchCount - setSize }; }; const getRemoveIndicesMatch = (items, index, matchCount, fileCount) => { for (let i = index; i >= 0; i--) { if (items[i].type === File) { const setSize = getSetSize(items, i); if (setSize === 1) { return { startIndex: i, removeCount: 2, newFocusedIndex: i - 1, newFileCount: fileCount - 1, newMatchCount: matchCount - 1 }; } return { startIndex: index, removeCount: 1, newFocusedIndex: index, newFileCount: fileCount, newMatchCount: matchCount - 1 }; } } throw new Error('could not compute indices to remove'); }; const getRemoveIndices = (items, index, matchCount, fileCount) => { const item = items[index]; switch (item.type) { case File: return getRemoveIndicesFile(items, item, index, matchCount, fileCount); case Match: return getRemoveIndicesMatch(items, index, matchCount, fileCount); default: throw new Error('unknown search result type'); } }; const removeItemFromItems = (items, index, matchCount, fileCount) => { const { startIndex, removeCount, newFocusedIndex, newFileCount, newMatchCount } = getRemoveIndices(items, index, matchCount, fileCount); const newItems = remove(items, startIndex, removeCount); return { newItems, newFocusedIndex, newFileCount, newMatchCount }; }; const getNewMinMax = (newItemsLength, minLineY, maxLineY, deltaY, itemHeight) => { if (maxLineY > newItemsLength) { const diff = maxLineY - minLineY; const newMinLineY = Math.max(newItemsLength - diff, 0); const newDeltaY = newMinLineY * itemHeight; return { newDeltaY, newMinLineY, newMaxLineY: newItemsLength }; } return { newDeltaY: deltaY, newMinLineY: minLineY, newMaxLineY: maxLineY }; }; const dismissItem = state => { const { items, listFocusedIndex, fileCount, matchCount, minLineY, maxLineY, deltaY, itemHeight } = state; if (listFocusedIndex === -1) { return state; } const { newItems, newFocusedIndex, newMatchCount, newFileCount } = removeItemFromItems(items, listFocusedIndex, matchCount, fileCount); const message = getStatusMessage(newMatchCount, newFileCount); const { newMinLineY, newMaxLineY, newDeltaY } = getNewMinMax(newItems.length, minLineY, maxLineY, deltaY, itemHeight); return { ...state, items: newItems, listFocusedIndex: newFocusedIndex, message, matchCount: newMatchCount, fileCount: newFileCount, minLineY: newMinLineY, maxLineY: newMaxLineY, deltaY: newDeltaY }; }; const expandDetails = state => { const { flags } = state; return { ...state, flags: flags | DetailsExpanded, focus: FocusSearchIncludeInput, focusSource: Script }; }; const focusMatchCase$1 = state => { return { ...state, focus: FocusSearchMatchCase }; }; const getNextFocus = (focus, flags) => { switch (focus) { case FocusToggleReplace: return FocusSearchInput; case FocusSearchInput: if (flags & ReplaceExpanded) { return FocusSearchReplaceInput; } return FocusSearchMatchCase; case FocusSearchMatchCase: return FocusSearchWholeWord; case FocusSearchWholeWord: return FocusSearchRegex; case FocusSearchRegex: if (flags & ReplaceExpanded) { return FocusSearchPreserveCase; } return FocusToggleDetails; case FocusSearchReplaceInput: return FocusSearchMatchCase; case FocusSearchPreserveCase: return FocusSearchReplaceAll; case FocusSearchReplaceAll: return FocusToggleDetails; case FocusSearchIncludeInput: return FocusSearchOpenEditors; case FocusSearchOpenEditors: ret