@lvce-editor/file-search-worker
Version:
Web worker for file search backends in LVCE Editor.
1,271 lines (1,225 loc) • 32.1 kB
JavaScript
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;
}
}
}
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);
}
}
};
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$2 = 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$2(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$2(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$2(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;
if (stack) {
Object.defineProperty(cause, 'stack', {
configurable: true,
enumerable: false,
value: stack,
writable: true
});
}
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 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
};
class CommandNotFoundError extends Error {
constructor(command) {
super(`Command not found ${command}`);
this.name = 'CommandNotFoundError';
}
}
const commands = Object.create(null);
const register$1 = 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$1 = '2.0';
const callbacks = Object.create(null);
const get$1 = id => {
return callbacks[id];
};
const remove$1 = 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 ReferenceError$1:
return ReferenceError;
case SyntaxError$1:
return SyntaxError;
case TypeError$1:
return TypeError;
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') {
Object.defineProperty(error, 'name', {
configurable: true,
value: name
});
}
return error;
}
return new ErrorConstructor(message);
};
const joinLines = lines => {
return lines.join(NewLine);
};
const splitLines$1 = lines => {
return lines.split(NewLine);
};
const getCurrentStack = () => {
const stackLinesToSkip = 3;
const currentStack = joinLines(splitLines$1(new Error().stack || '').slice(stackLinesToSkip));
return currentStack;
};
const getNewLineIndex = (string, startIndex) => {
{
return string.indexOf(NewLine);
}
};
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 setStack = (error, stack) => {
const descriptor = Object.getOwnPropertyDescriptor(error, 'stack');
if (descriptor) {
if (!descriptor.configurable && !descriptor.writable) {
return;
}
if (!descriptor.configurable && descriptor.writable) {
error.stack = stack;
return;
}
}
Object.defineProperty(error, 'stack', {
configurable: true,
value: stack,
writable: true
});
};
const restoreExistingError = (error, currentStack) => {
if (typeof error.stack === 'string') {
setStack(error, `${error.stack}${NewLine}${currentStack}`);
}
return error;
};
const restoreMethodNotFoundError = (error, currentStack) => {
const restoredError = new JsonRpcError(error.message);
const parentStack = getParentStack(error);
setStack(restoredError, `${parentStack}${NewLine}${currentStack}`);
return restoredError;
};
const restoreStackFromData = (restoredError, error, currentStack) => {
if (error.data.stack && error.data.type && error.message) {
setStack(restoredError, `${error.data.type}: ${error.message}${NewLine}${error.data.stack}${NewLine}${currentStack}`);
return;
}
if (error.data.stack) {
setStack(restoredError, error.data.stack);
}
};
const applyDataProperties = (restoredError, error) => {
restoreStackFromData(restoredError, error, getCurrentStack());
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;
}
};
const applyDirectProperties = (restoredError, error) => {
if (error.stack) {
const lowerStack = restoredError.stack || '';
const indexNewLine = getNewLineIndex(lowerStack);
const parentStack = getParentStack(error);
// @ts-ignore
setStack(restoredError, `${parentStack}${lowerStack.slice(indexNewLine)}`);
}
if (error.codeFrame) {
// @ts-ignore
restoredError.codeFrame = error.codeFrame;
}
};
const restoreMessageError = (error, _currentStack) => {
const restoredError = constructError(error.message, error.type, error.name);
if (error.data) {
applyDataProperties(restoredError, error);
} else {
applyDirectProperties(restoredError, error);
}
return restoredError;
};
const restoreJsonRpcError = error => {
const currentStack = getCurrentStack();
if (error && error instanceof Error) {
return restoreExistingError(error, currentStack);
}
if (error && error.code && error.code === MethodNotFound) {
return restoreMethodNotFoundError(error, currentStack);
}
if (error && error.message) {
return restoreMessageError(error);
}
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$1(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,
data: error.stack,
message: error.message
};
}
return {
code: Custom,
data: {
code: prettyError.code,
codeFrame: prettyError.codeFrame,
name: prettyError.name,
stack: getStack(prettyError),
type: getErrorType(prettyError)
},
message: prettyError.message
};
};
const create$1$1 = (id, error) => {
return {
error,
id,
jsonrpc: Two$1
};
};
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$8 = (message, result) => {
return {
id: message.id,
jsonrpc: Two$1,
result: result ?? null
};
};
const getSuccessResponse = (message, result) => {
const resultProperty = result ?? null;
return create$8(message, resultProperty);
};
const getErrorResponseSimple = (id, error) => {
return {
error: {
code: Custom,
data: error,
// @ts-ignore
message: error.message
},
id,
jsonrpc: Two$1
};
};
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 {
execute: options.execute,
ipc: options.ipc,
logError: options.logError || defaultLogError,
message: options.message,
preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
requiresSocket: options.requiresSocket || defaultRequiresSocket,
resolve: options.resolve || defaultResolve
};
}
return {
execute: args[2],
ipc: args[0],
logError: args[5],
message: args[1],
preparePrettyError: args[4],
requiresSocket: args[6],
resolve: args[3]
};
};
const handleJsonRpcMessage = async (...args) => {
const options = normalizeParams(args);
const {
execute,
ipc,
logError,
message,
preparePrettyError,
requiresSocket,
resolve
} = 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 Two = '2.0';
const create$7 = (method, params) => {
return {
jsonrpc: Two,
method,
params
};
};
const create$6 = (id, method, params) => {
const message = {
id,
jsonrpc: Two,
method,
params
};
return message;
};
let id = 0;
const create$5 = () => {
return ++id;
};
const registerPromise = map => {
const id = create$5();
const {
promise,
resolve
} = Promise.withResolvers();
map[id] = resolve;
return {
id,
promise
};
};
const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => {
const {
id,
promise
} = registerPromise(callbacks);
const message = create$6(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$7(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;
};
const create$4 = async ({
commandMap,
isMessagePortOpen = true,
messagePort
}) => {
// TODO create a commandMap per rpc instance
register$1(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$3 = async ({
commandMap,
isMessagePortOpen,
send
}) => {
const {
port1,
port2
} = new MessageChannel();
await send(port1);
return create$4({
commandMap,
isMessagePortOpen,
messagePort: port2
});
};
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$2 = async ({
commandMap,
isMessagePortOpen,
send
}) => {
return createSharedLazyRpc(() => {
return create$3({
commandMap,
isMessagePortOpen,
send
});
});
};
const create$1 = async ({
commandMap
}) => {
// TODO create a commandMap per rpc instance
register$1(commandMap);
const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
handleIpc(ipc);
const rpc = createRpc(ipc);
return rpc;
};
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 commandMapRef = {};
const handleMessagePort = async port => {
await create$4({
commandMap: commandMapRef,
isMessagePortOpen: true,
messagePort: port
});
};
const RE_PROTOCOL = /^([a-z-]+):\/\//;
const getProtocol = uri => {
const protocolMatch = uri.match(RE_PROTOCOL);
if (protocolMatch) {
return protocolMatch[1];
}
return '';
};
const state = Object.create(null);
const register = modules => {
Object.assign(state, modules);
};
const getFn = protocol => {
return state[protocol];
};
const searchFile$4 = async (path, value, prepare, assetDir) => {
const protocol = getProtocol(path);
const fn = getFn(protocol);
if (!fn) {
throw new Error(`No search handler registered for protocol: ${protocol}`);
}
const result = await fn(path, value, prepare, assetDir);
return result;
};
const commandMap = {
'FileSearch.handleMessagePort': handleMessagePort,
'FileSearch.searchFile': searchFile$4,
'SearchFile.searchFile': searchFile$4
};
const rpcs = Object.create(null);
const set$2 = (id, rpc) => {
rpcs[id] = rpc;
};
const get = id => {
return rpcs[id];
};
const remove = id => {
delete rpcs[id];
};
/* eslint-disable @typescript-eslint/explicit-function-return-type */
const create = rpcId => {
return {
async dispose() {
const rpc = get(rpcId);
await rpc.dispose();
},
// @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);
},
registerMockRpc(commandMap) {
const mockRpc = createMockRpc({
commandMap
});
set$2(rpcId, mockRpc);
// @ts-ignore
mockRpc[Symbol.dispose] = () => {
remove(rpcId);
};
// @ts-ignore
return mockRpc;
},
set(rpc) {
set$2(rpcId, rpc);
}
};
};
const EditorWorker = 99;
const RendererWorker = 1;
const {
set: set$1
} = create(EditorWorker);
const {
invoke: invoke$1,
invokeAndTransfer,
set
} = create(RendererWorker);
const sendMessagePortToEditorWorker = async (port, rpcId) => {
const command = 'HandleMessagePort.handleMessagePort';
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToEditorWorker', port, command, rpcId);
};
const initializeEditorWorker = async () => {
const rpc = await create$2({
commandMap: {},
async send(port) {
await sendMessagePortToEditorWorker(port, 0);
}
});
set$1(rpc);
};
const initializeRendererWorker = async () => {
const rpc = await create$1({
commandMap: commandMap
});
set(rpc);
};
const Memfs = 'memfs';
const Html = 'html';
const Fetch = 'fetch';
const File = 'file';
const Default = '';
const searchFile$3 = async uri => {
return invoke$1('ExtensionHost.searchFileWithMemory', uri);
};
// TODO simplify code
// 1. don't have playground prefix in fileMap json
// 2. remove code here that removes the prefix
const searchFile$2 = async path => {
return invoke$1('ExtensionHost.searchFileWithFetch', path);
};
const searchFile$1 = async uri => {
return invoke$1('ExtensionHost.searchFileWithHtml', uri);
};
const getFileSearchRipGrepArgs = () => {
const ripGrepArgs = ['--files', '--sort-files', '--hidden', '--glob', '!.git', '--glob', '!elm-stuff'];
return ripGrepArgs;
};
const invoke = (method, ...params) => {
return invoke$1('SearchProcess.invoke', method, ...params);
};
const splitLines = lines => {
if (!lines) {
return [];
}
return lines.split('\n');
};
// TODO create direct connection from electron to file search worker using message ports
const searchFile = async (path, value, prepare) => {
const ripGrepArgs = getFileSearchRipGrepArgs();
const options = {
limit: 9_999_999,
ripGrepArgs,
searchPath: path
};
const stdout = await invoke('SearchFile.searchFile', options);
const lines = splitLines(stdout);
return lines;
};
const searchModules = {
[Default]: searchFile,
[Fetch]: searchFile$2,
[File]: searchFile,
[Html]: searchFile$1,
[Memfs]: searchFile$3
};
const listen = async () => {
Object.assign(commandMapRef, commandMap);
register(searchModules);
await Promise.all([initializeRendererWorker(), initializeEditorWorker()]);
};
const main = async () => {
await listen();
};
main();