UNPKG

@lvce-editor/text-search-worker

Version:
1,920 lines (1,866 loc) 159 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 { code: ERR_MODULE_NOT_FOUND, message }; }; 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 { code: E_INCOMPATIBLE_NATIVE_MODULE, message: `Incompatible native node module: ${message}` }; }; const getModuleSyntaxError = () => { return { code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON, message: `ES Modules are 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 { code: '', message: actualMessage, stack: rest }; }; class IpcError extends VError { // @ts-ignore constructor(betterMessage, stdout = '', stderr = '') { if (stdout || stderr) { // @ts-ignore const { code, message, 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 { promise, resolve } = 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({ id: firstMessage.id, jsonrpc: '2.0', 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 { promise, resolve } = 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({ event, type }); }; addListener(eventEmitter, event, listener); listenerMap[event] = listener; } return promise; }; const Message$1 = 3; const create$5$1 = async ({ isMessagePortOpen, messagePort }) => { 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 { event, type } = 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, { close: Close, error: Error$3, open: Open }); }; const create$6 = 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$6, wrap }; const Two$1 = '2.0'; const callbacks = Object.create(null); const get$3 = id => { return callbacks[id]; }; const remove$3 = id => { delete callbacks[id]; }; 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 stackLinesToSkip = 3; const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip)); 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$3(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$1, 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$5 = (message, result) => { return { jsonrpc: Two$1, id: message.id, result: result ?? null }; }; const getSuccessResponse = (message, result) => { const resultProperty = result ?? null; return create$5(message, resultProperty); }; const getErrorResponseSimple = (id, error) => { return { jsonrpc: Two$1, 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'); }; 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 Two = '2.0'; const create$s = (method, params) => { return { jsonrpc: Two, method, params }; }; const create$r = (id, method, params) => { const message = { id, jsonrpc: Two, method, params }; return message; }; let id = 0; const create$q = () => { return ++id; }; /* eslint-disable n/no-unsupported-features/es-syntax */ const registerPromise = map => { const id = create$q(); const { promise, resolve } = Promise.withResolvers(); map[id] = resolve; return { id, promise }; }; // @ts-ignore const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => { const { id, promise } = registerPromise(callbacks); const message = create$r(id, method, params); if (useSendAndTransfer && ipc.sendAndTransfer) { ipc.sendAndTransfer(message); } else { ipc.send(message); } const responseMessage = await promise; return unwrapJsonRpcResult(responseMessage); }; const createRpc = ipc => { const callbacks = Object.create(null); ipc._resolve = (id, response) => { const fn = callbacks[id]; if (!fn) { console.warn(`callback ${id} may already be disposed`); return; } fn(response); delete callbacks[id]; }; const rpc = { async dispose() { await ipc?.dispose(); }, invoke(method, ...params) { return invokeHelper(callbacks, ipc, method, params, false); }, invokeAndTransfer(method, ...params) { return invokeHelper(callbacks, ipc, method, params, true); }, // @ts-ignore ipc, /** * @deprecated */ send(method, ...params) { const message = create$s(method, params); ipc.send(message); } }; 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, event.target._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; }; /* eslint-disable @typescript-eslint/no-misused-promises */ const createSharedLazyRpc = factory => { let rpcPromise; const getOrCreate = () => { if (!rpcPromise) { rpcPromise = factory(); } return rpcPromise; }; return { async dispose() { const rpc = await getOrCreate(); await rpc.dispose(); }, async invoke(method, ...params) { const rpc = await getOrCreate(); return rpc.invoke(method, ...params); }, async invokeAndTransfer(method, ...params) { const rpc = await getOrCreate(); return rpc.invokeAndTransfer(method, ...params); }, async send(method, ...params) { const rpc = await getOrCreate(); rpc.send(method, ...params); } }; }; const create$i = async ({ commandMap, isMessagePortOpen, send }) => { return createSharedLazyRpc(() => { return create$2$1({ commandMap, isMessagePortOpen, send }); }); }; const LazyTransferMessagePortRpcParent = { __proto__: null, create: create$i }; 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$h = 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 create$g = 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$h({ commandMap, webSocket }); return rpc; }; const create$f = async ({ commandMap, type }) => { return createSharedLazyRpc(() => { return create$g({ commandMap, type }); }); }; const LazyWebSocketRpcParent2 = { __proto__: null, create: create$f }; const create$4 = async ({ commandMap, isMessagePortOpen = true, messagePort }) => { // TODO create a commandMap per rpc instance register(commandMap); const rawIpc = await IpcParentWithMessagePort$1.create({ isMessagePortOpen, messagePort }); const ipc = IpcParentWithMessagePort$1.wrap(rawIpc); handleIpc(ipc); const rpc = createRpc(ipc); messagePort.start(); return rpc; }; const create$2$1 = async ({ commandMap, isMessagePortOpen, send }) => { const { port1, port2 } = new MessageChannel(); await send(port1); return create$4({ commandMap, isMessagePortOpen, messagePort: port2 }); }; const TransferMessagePortRpcParent = { __proto__: null, create: create$2$1 }; const create$1$1 = 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$1$1 }; const createMockRpc = ({ commandMap }) => { const invocations = []; const invoke = (method, ...params) => { invocations.push([method, ...params]); const command = commandMap[method]; if (!command) { throw new Error(`command ${method} not found`); } return command(...params); }; const mockRpc = { invocations, invoke, invokeAndTransfer: invoke }; return mockRpc; }; const Alert = 'alert'; const Button$3 = 'button'; const CheckBox = 'checkbox'; const None$2 = 'none'; const ScrollBar$1 = 'scrollbar'; const Status = 'status'; const ToolBar = 'toolbar'; const Tree$1 = 'tree'; const TreeItem$1 = 'treeitem'; const Actions = 'Actions'; const Badge = 'Badge'; const Chevron = 'Chevron'; const CloseMaskIcon = 'MaskIcon MaskIconClose'; const Empty$1 = ''; const FileIcon = 'FileIcon'; const FocusOutline = 'FocusOutline'; const Grow = 'Grow'; const Highlight = 'Highlight'; const HighlightDeleted = 'HighlightDeleted'; const HighlightInserted = 'HighlightInserted'; const IconButton = 'IconButton'; const IconButtonDisabled = 'IconButtonDisabled'; const Label = 'Label'; const List$1 = 'List'; const MaskIcon = 'MaskIcon'; const MaskIconBook = 'MaskIconBook'; const MaskIconCaseSensitive = 'MaskIconCaseSensitive'; const MaskIconChevronDown = 'MaskIconChevronDown'; const MaskIconChevronRight = 'MaskIconChevronRight'; const MaskIconEllipsis = 'MaskIconEllipsis'; const MaskIconExclude = 'MaskIconExclude'; const MaskIconPreserveCase = 'MaskIconPreserveCase'; const MaskIconRegex = 'MaskIconRegex'; const MaskIconReplaceAll = 'MaskIconReplaceAll'; const MaskIconWholeWord = 'MaskIconWholeWord'; const MultilineInputBox = 'MultilineInputBox'; const ScrollBar = 'ScrollBar'; const ScrollBarThumb = 'ScrollBarThumb'; const ScrollBarVertical = 'ScrollBarVertical'; const Search$2 = 'Search'; const SearchField = 'SearchField'; const SearchFieldButton = 'SearchFieldButton'; const SearchFieldButtonChecked = 'SearchFieldButtonChecked'; const SearchFieldButtonDisabled = 'SearchFieldButtonDisabled'; const SearchFieldButtons = 'SearchFieldButtons'; const SearchFieldContainer = 'SearchFieldContainer'; const SearchFieldError = 'SearchFieldError'; const SearchHeader = 'SearchHeader'; const SearchHeaderDetails = 'SearchHeaderDetails'; const SearchHeaderDetailsExpanded = 'SearchHeaderDetailsExpanded'; const SearchHeaderDetailsExpandedTop = 'SearchHeaderDetailsExpandedTop'; const SearchHeaderDetailsHeading = 'SearchHeaderDetailsHeading'; const SearchHeaderTop = 'SearchHeaderTop'; const SearchHeaderTopRight = 'SearchHeaderTopRight'; const SearchInputError = 'SearchInputError'; const SearchRemove = 'SearchRemove'; const SearchToggleButton = 'SearchToggleButton'; const SearchToggleButtonExpanded = 'SearchToggleButtonExpanded'; const SourceControlBadge = 'SourceControlBadge'; const ToggleDetails = 'ToggleDetails'; const Tree = 'Tree'; const TreeItem = 'TreeItem'; const TreeItemActive = 'TreeItemActive'; const TreeItems$1 = 'TreeItems'; const Viewlet = 'Viewlet'; const ViewletSearchMessage = 'ViewletSearchMessage'; const ViewletSearchMessageIndented = 'ViewletSearchMessageIndented'; const File$2 = 7; const Button$2 = 1; const Div = 4; const Span = 8; const Text = 12; const Img = 17; const Ins = 20; const Del = 21; const H4 = 24; const TextArea = 62; const Button$1 = 'event.button'; const ClientX = 'event.clientX'; const ClientY = 'event.clientY'; const DeltaMode = 'event.deltaMode'; const DeltaY = 'event.deltaY'; const TargetName = 'event.target.name'; const TargetSelectionEnd = 'event.target.selectionEnd'; const TargetSelectionStart = 'event.target.selectionStart'; const TargetValue = 'event.target.value'; const Script$1 = 2; const Search$1 = 18; const InputContextMenu = 91; const Separator = 1; const None$1 = 0; const LeftClick = 0; const Electron = 2; const Remote = 3; const IconThemeWorker = 7009; const RendererWorker = 1; const SearchProcess = 77; const File$1 = 1; const Match$1 = 2; const FocusElementByName = 'Viewlet.focusElementByName'; const SetDom2 = 'Viewlet.setDom2'; const SetFocusContext = 'Viewlet.setFocusContext'; const SetValueByName = 'Viewlet.setValueByName'; const Empty = 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 rpcs = Object.create(null); const set$4 = (id, rpc) => { rpcs[id] = rpc; }; const get$2 = id => { return rpcs[id]; }; const remove$2 = id => { delete rpcs[id]; }; /* eslint-disable @typescript-eslint/explicit-function-return-type */ const create$3 = rpcId => { return { async dispose() { const rpc = get$2(rpcId); await rpc.dispose(); }, // @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); }, registerMockRpc(commandMap) { const mockRpc = createMockRpc({ commandMap }); set$4(rpcId, mockRpc); // @ts-ignore mockRpc[Symbol.dispose] = () => { remove$2(rpcId); }; // @ts-ignore return mockRpc; }, set(rpc) { set$4(rpcId, rpc); } }; }; const { invoke: invoke$2, set: set$3 } = create$3(IconThemeWorker); const getIcons = async iconRequests => { // @ts-ignore return invoke$2('IconTheme.getIcons', iconRequests); }; const { invoke: invoke$1, invokeAndTransfer, set: set$2 } = create$3(RendererWorker); const showContextMenu2 = async (uid, menuId, x, y, args) => { number(uid); number(menuId); number(x); number(y); // @ts-ignore await invoke$1('ContextMenu.show2', uid, menuId, x, y, args); }; const sendMessagePortToIconThemeWorker = async (port, rpcId) => { const command = 'IconTheme.handleMessagePort'; // @ts-ignore await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToIconThemeWorker', port, command, rpcId); }; const handleWorkspaceRefresh = async () => { return invoke$1('Layout.handleWorkspaceRefresh'); }; const sendMessagePortToSearchProcess = async port => { await invokeAndTransfer('SendMessagePortToElectron.sendMessagePortToElectron', port, 'HandleMessagePortForSearchProcess.handleMessagePortForSearchProcess'); }; const writeClipBoardText = async text => { await invoke$1('ClipBoard.writeText', /* text */text); }; const openUri$1 = async (uri, focus, options) => { await invoke$1('Main.openUri', uri, focus, options); }; const { invoke, set: set$1 } = create$3(SearchProcess); 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 { oldState, newState } = states[uid]; const newerState = await fn(newState, ...args); if (oldState === newerState || 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 mergeClassNames = (...classNames) => { return classNames.filter(Boolean).join(' '); }; const text = data => { return { childCount: 0, text: data, type: Text }; }; const SetText = 1; const Replace$1 = 2; const SetAttribute = 3; const RemoveAttribute = 4; const Add = 6; const NavigateChild = 7; const NavigateParent = 8; const RemoveChild = 9; const NavigateSibling = 10; const isKey = key => { return key !== 'type' && key !== 'childCount'; }; const getKeys = node => { const keys = Object.keys(node).filter(isKey); return keys; }; const arrayToTree = nodes => { const result = []; let i = 0; while (i < nodes.length) { const node = nodes[i]; const { children, nodesConsumed } = getChildrenWithCount(nodes, i + 1, node.childCount || 0); result.push({ node, children }); i += 1 + nodesConsumed; } return result; }; const getChildrenWithCount = (nodes, startIndex, childCount) => { if (childCount === 0) { return { children: [], nodesConsumed: 0 }; } const children = []; let i = startIndex; let remaining = childCount; let totalConsumed = 0; while (remaining > 0 && i < nodes.length) { const node = nodes[i]; const nodeChildCount = node.childCount || 0; const { children: nodeChildren, nodesConsumed } = getChildrenWithCount(nodes, i + 1, nodeChildCount); children.push({ node, children: nodeChildren }); const nodeSize = 1 + nodesConsumed; i += nodeSize; totalConsumed += nodeSize; remaining--; } return { children, nodesConsumed: totalConsumed }; }; const compareNodes = (oldNode, newNode) => { const patches = []; // Check if node type changed - return null to signal incompatible nodes // (caller should handle this with a Replace operation) if (oldNode.type !== newNode.type) { return null; } // Handle text nodes if (oldNode.type === Text && newNode.type === Text) { if (oldNode.text !== newNode.text) { patches.push({ type: SetText, value: newNode.text }); } return patches; } // Compare attributes const oldKeys = getKeys(oldNode); const newKeys = getKeys(newNode); // Check for attribute changes for (const key of newKeys) { if (oldNode[key] !== newNode[key]) { patches.push({ type: SetAttribute, key, value: newNode[key] }); } } // Check for removed attributes for (const key of oldKeys) { if (!(key in newNode)) { patches.push({ type: RemoveAttribute, key }); } } return patches; }; const treeToArray = node => { const result = [node.node]; for (const child of node.children) { result.push(...treeToArray(child)); } return result; }; const diffChildren = (oldChildren, newChildren, patches) => { const maxLength = Math.max(oldChildren.length, newChildren.length); // Track where we are: -1 means at parent, >= 0 means at child index let currentChildIndex = -1; // Collect indices of children to remove (we'll add these patches at the end in reverse order) const indicesToRemove = []; for (let i = 0; i < maxLength; i++) { const oldNode = oldChildren[i]; const newNode = newChildren[i]; if (!oldNode && !newNode) { continue; } if (!oldNode) { // Add new node - we should be at the parent if (currentChildIndex >= 0) { // Navigate back to parent patches.push({ type: NavigateParent }); currentChildIndex = -1; } // Flatten the entire subtree so renderInternal can handle it const flatNodes = treeToArray(newNode); patches.push({ type: Add, nodes: flatNodes }); } else if (newNode) { // Compare nodes to see if we need any patches const nodePatches = compareNodes(oldNode.node, newNode.node); // If nodePatches is null, the node types are incompatible - need to replace if (nodePatches === null) { // Navigate to this child if (currentChildIndex === -1) { patches.push({ type: NavigateChild, index: i }); currentChildIndex = i; } else if (currentChildIndex !== i) { patches.push({ type: NavigateSibling, index: i }); currentChildIndex = i; } // Replace the entire subtree const flatNodes = treeToArray(newNode); patches.push({ type: Replace$1, nodes: flatNodes }); // After replace, we're at the new element (same position) continue; } // Check if we need to recurse into children const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0; // Only navigate to this element if we need to do something if (nodePatches.length > 0 || hasChildrenToCompare) { // Navigate to this child if not already there if (currentChildIndex === -1) { patches.push({ type: NavigateChild, index: i }); currentChildIndex = i; } else if (currentChildIndex !== i) { patches.push({ type: NavigateSibling, index: i }); currentChildIndex = i; } // Apply node patches (these apply to the current element, not children) if (nodePatches.length > 0) { patches.push(...nodePatches); } // Compare children recursively if (hasChildrenToCompare) { diffChildren(oldNode.children, newNode.children, patches); } } } else { // Remove old node - collect the index for later removal indicesToRemove.push(i); } } // Navigate back to parent if we ended at a child if (currentChildIndex >= 0) { patches.push({ type: NavigateParent }); currentChildIndex = -1; } // Add remove patches in reverse order (highest index first) // This ensures indices remain valid as we remove for (let j = indicesToRemove.length - 1; j >= 0; j--) { patches.push({ type: RemoveChild, index: indicesToRemove[j] }); } }; const diffTrees = (oldTree, newTree, patches, path) => { // At the root level (path.length === 0), we're already AT the element // So we compare the root node directly, then compare its children if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) { const oldNode = oldTree[0]; const newNode = newTree[0]; // Compare root nodes const nodePatches = compareNodes(oldNode.node, newNode.node); // If nodePatches is null, the root node types are incompatible - need to replace if (nodePatches === null) { const flatNodes = treeToArray(newNode); patches.push({ type: Replace$1, nodes: flatNodes }); return; } if (nodePatches.length > 0) { patches.push(...nodePatches); } // Compare children if (oldNode.children.length > 0 || newNode.children.length > 0) { diffChildren(oldNode.children, newNode.children, patches); } } else { // Non-root level or multiple root elements - use the regular comparison diffChildren(oldTree, newTree, patches); } }; const removeTrailingNavigationPatches = patches => { // Find the last non-navigation patch let lastNonNavigationIndex = -1; for (let i = patches.length - 1; i >= 0; i--) { const patch = patches[i]; if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) { lastNonNavigationIndex = i; break; } } // Return patches up to and including the last non-navigation patch return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1); }; const diffTree = (oldNodes, newNodes) => { // Step 1: Convert flat arrays to tree structures const oldTree = arrayToTree(oldNodes); const newTree = arrayToTree(newNodes); // Step 3: Compare the trees const patches = []; diffTrees(oldTree, newTree, patches, []); // Remove trailing navigation patches since they serve no purpose return removeTrailingNavigationPatches(patches); }; const User = 1; const Script = 2; const clearSearchResults$1 = state => { return { ...state, focus: FocusSearchInput, focusSource: Script, inputSource: Script, items: [], limitHit: false, limitHitWarning: '', maxLineY: 0, message: '', minLineY: 0, replacement: '', searchInputErrorMessage: '', value: '' }; }; const getFilePath = text => { // TODO make api stricter so that results always have the same shape if (text.startsWith('./')) { return text.slice(2); } return text; }; const getIconsCached = (dirents, fileIconCache) => { return dirents.map(dirent => { if (dirent.type === Match$1) { return ''; } const path = getFilePath(dirent.text); return fileIconCache[path]; }); }; const getFileName = path => { const slashIndex = path.lastIndexOf('/'); if (slashIndex === -1) { return path; } return path.slice(slashIndex + 1); }; const File = 1; const Match = 2; const isFile = match => { return match.type === File; }; const getMissingDirents = (searchResults, fileIconCache) => { const missingDirents = []; const files = searchResults.filter(isFile); for (const file of files) { const uri = getFilePath(file.text); if (!(uri in fileIconCache)) { missingDirents.push(file); } } return missingDirents; }; const toIconRequest = item => { const filePath = getFilePath(item.text); const fileName = getFileName(filePath); return { name: fileName, path: filePath, type: File$2 }; }; const getMissingIconRequests = (dirents, fileIconCache) => { const missingRequests = getMissingDirents(dirents, fileIconCache); const iconRequests = missingRequests.map(toIconRequest); return iconRequests; }; const Directory = 3; const DirectoryExpanded = 4; const getSimpleIconRequestType = direntType => { if (direntType === Directory || direntType === DirectoryExpanded) { return 2; } return 1; }; const toSimpleIconRequest = request => { return { name: request.name, type: getSimpleIconRequestType(request.type) }; }; const requestFileIcons = async requests => { if (requests.length === 0) { return []; } const simpleRequests = requests.map(toSimpleIconRequest); const icons = await get