@qwik.dev/core
Version:
An open source framework for building instant loading web apps at any scale, without the extra effort.
319 lines (318 loc) • 9.88 kB
JavaScript
import { inlinedQrl, _captures, implicit$FirstArg } from "@qwik.dev/core";
import workerUrl from "./worker.js?worker&url";
import { _serialize } from "@qwik.dev/core/internal";
import nodeWorkerAssetUrl from "./worker.node.js?worker&url";
const browserGlobals$1 = globalThis;
const sanitizeWorkerArgs = (args) => {
const SubmitEventConstructor = browserGlobals$1.SubmitEvent;
const HTMLFormElementConstructor = browserGlobals$1.HTMLFormElement;
const EventConstructor = browserGlobals$1.Event;
const NodeConstructor = browserGlobals$1.Node;
const sanitizedArgs = new Array(args.length);
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (SubmitEventConstructor && HTMLFormElementConstructor && arg instanceof SubmitEventConstructor && arg.target instanceof HTMLFormElementConstructor) {
sanitizedArgs[i] = new FormData(arg.target);
} else if (EventConstructor && arg instanceof EventConstructor) {
sanitizedArgs[i] = null;
} else if (NodeConstructor && arg instanceof NodeConstructor) {
sanitizedArgs[i] = null;
} else {
sanitizedArgs[i] = arg;
}
}
return sanitizedArgs;
};
const qwikWorkers = /* @__PURE__ */ new Map();
const pendingWorkers = /* @__PURE__ */ new Map();
let nextWorkerRequestId = 0;
const getWorkerRequestId = () => ++nextWorkerRequestId;
const getWorkerHash = (qrl) => qrl.getHash();
const getWorkerName = (qrl) => `worker$(${qrl.getSymbol()})`;
const getOrCreateWorker = (qrl, createWorker) => {
const workerHash = getWorkerHash(qrl);
const cachedWorker = qwikWorkers.get(workerHash);
if (cachedWorker) {
return Promise.resolve(cachedWorker);
}
const pendingWorker = pendingWorkers.get(workerHash);
if (pendingWorker) {
return pendingWorker;
}
const workerPromise = Promise.resolve(createWorker()).then((worker) => {
if (worker) {
qwikWorkers.set(workerHash, worker);
}
return worker;
}).finally(() => {
pendingWorkers.delete(workerHash);
});
pendingWorkers.set(workerHash, workerPromise);
return workerPromise;
};
const isWorkerResponseMessage = (messageData, requestId) => Array.isArray(messageData) && messageData.length === 3 && messageData[0] === requestId;
const invokeWorker = async (worker, qrl, args) => {
const requestId = getWorkerRequestId();
const data = await _serialize([
qrl,
...args
]);
return new Promise((resolve, reject) => {
const cleanup = () => {
worker.offError(errorHandler);
worker.offMessage(messageHandler);
};
const errorHandler = (error) => {
cleanup();
reject(error);
};
const messageHandler = (messageData) => {
if (isWorkerResponseMessage(messageData, requestId)) {
cleanup();
if (messageData[1]) {
resolve(messageData[2]);
} else {
reject(messageData[2]);
}
}
};
worker.onError(errorHandler);
worker.onMessage(messageHandler);
worker.postMessage([
requestId,
data
]);
});
};
const browserGlobals = globalThis;
const createBrowserWorkerTransport = (worker) => {
const errorListenerMap = /* @__PURE__ */ new Map();
const listenerMap = /* @__PURE__ */ new Map();
return {
offError(handler) {
const listener = errorListenerMap.get(handler);
if (listener) {
errorListenerMap.delete(handler);
worker.removeEventListener("error", listener);
}
},
offMessage(handler) {
const listener = listenerMap.get(handler);
if (listener) {
listenerMap.delete(handler);
worker.removeEventListener("message", listener);
}
},
onError(handler) {
const listener = (event) => handler(event.error ?? event);
errorListenerMap.set(handler, listener);
worker.addEventListener("error", listener);
},
onMessage(handler) {
const listener = (event) => handler(event.data);
listenerMap.set(handler, listener);
worker.addEventListener("message", listener);
},
postMessage(data) {
worker.postMessage(data);
}
};
};
const getBrowserWorker = (qrl) => {
const WorkerConstructor = browserGlobals.Worker;
if (!WorkerConstructor) {
return Promise.resolve(null);
}
return getOrCreateWorker(qrl, () => createBrowserWorkerTransport(new WorkerConstructor(workerUrl, {
name: getWorkerName(qrl),
type: "module"
})));
};
const tryParseUrl = (value) => {
try {
return new URL(value);
} catch {
return null;
}
};
const getImportMetaDirUrl = (metaUrl) => {
const moduleUrl = tryParseUrl(metaUrl);
if (!moduleUrl || moduleUrl.protocol !== "file:") {
return null;
}
moduleUrl.pathname = moduleUrl.pathname.slice(0, moduleUrl.pathname.lastIndexOf("/") + 1);
return moduleUrl;
};
const getPublicBuildPath = (assetUrl) => {
const assetsIndex = assetUrl.lastIndexOf("/assets/");
if (assetsIndex === -1) {
return null;
}
return `${assetUrl.slice(0, assetsIndex)}/build/`;
};
const getNodeDistUrl$1 = (metaUrl, fsModule) => {
if (!fsModule?.existsSync) {
return null;
}
let currentDirUrl = getImportMetaDirUrl(metaUrl);
if (!currentDirUrl) {
return null;
}
for (let i = 0; i < 8; i++) {
const distUrl = new URL("dist/", currentDirUrl);
if (fsModule.existsSync(distUrl)) {
return distUrl;
}
const parentDirUrl = new URL("../", currentDirUrl);
if (parentDirUrl.href === currentDirUrl.href) {
break;
}
currentDirUrl = parentDirUrl;
}
return null;
};
const getNodeWorkerUrlFromDist = (assetUrl, distUrl) => {
return new URL(`.${assetUrl}`, distUrl);
};
const getNodeWorkerQrlBaseUrlFromDist = (assetUrl, distUrl) => {
const publicBuildPath = getPublicBuildPath(assetUrl);
if (!publicBuildPath) {
return null;
}
return new URL(`.${publicBuildPath}`, distUrl);
};
const runtimeGlobals$1 = globalThis;
const runtimeImportMeta = import.meta;
const nodeWorkerThreadsModuleId = "node:worker_threads";
const nodeFsModuleId = "node:fs";
let resolvedNodeWorkerUrl = void 0;
let resolvedNodeDistUrl = void 0;
const getNodeWorkerConstructor = () => {
const workerThreadsModule = runtimeGlobals$1.process?.getBuiltinModule?.(nodeWorkerThreadsModuleId);
return workerThreadsModule?.Worker;
};
const getNodeFsModule = () => {
return runtimeGlobals$1.process?.getBuiltinModule?.(nodeFsModuleId);
};
const getResolvedNodeWorkerModuleUrl = () => {
const resolvedUrl = runtimeImportMeta.resolve?.("./worker.node.js");
if (!resolvedUrl) {
return null;
}
const workerUrl2 = tryParseUrl(resolvedUrl);
if (!workerUrl2) {
return null;
}
const fsModule = getNodeFsModule();
if (!fsModule?.existsSync?.(workerUrl2)) {
return null;
}
return workerUrl2;
};
const getNodeDistUrl = () => {
if (resolvedNodeDistUrl !== void 0) {
return resolvedNodeDistUrl;
}
resolvedNodeDistUrl = getNodeDistUrl$1(import.meta.url, getNodeFsModule());
return resolvedNodeDistUrl;
};
const getNodeWorkerUrl = () => {
if (resolvedNodeWorkerUrl != void 0) {
return resolvedNodeWorkerUrl;
}
const resolvedModuleUrl = getResolvedNodeWorkerModuleUrl();
if (resolvedModuleUrl) {
resolvedNodeWorkerUrl = resolvedModuleUrl;
return resolvedNodeWorkerUrl;
}
if (nodeWorkerAssetUrl.startsWith("/")) {
const distUrl = getNodeDistUrl();
if (distUrl) {
resolvedNodeWorkerUrl = getNodeWorkerUrlFromDist(nodeWorkerAssetUrl, distUrl);
return resolvedNodeWorkerUrl;
}
}
resolvedNodeWorkerUrl = new URL(nodeWorkerAssetUrl, import.meta.url);
return resolvedNodeWorkerUrl;
};
const getNodeWorkerQrlBaseUrl = () => {
const resolvedModuleUrl = getResolvedNodeWorkerModuleUrl();
if (resolvedModuleUrl) {
return new URL("../build/", resolvedModuleUrl);
}
if (nodeWorkerAssetUrl.startsWith("/")) {
const distUrl = getNodeDistUrl();
const qrlBaseUrl = distUrl && getNodeWorkerQrlBaseUrlFromDist(nodeWorkerAssetUrl, distUrl);
if (qrlBaseUrl) {
return qrlBaseUrl;
}
}
return new URL("../build/", getNodeWorkerUrl());
};
const createNodeWorkerTransport = (worker) => {
return {
offError(handler) {
worker.off("error", handler);
},
offMessage(handler) {
worker.off("message", handler);
},
onError(handler) {
worker.on("error", handler);
},
onMessage(handler) {
worker.on("message", handler);
},
postMessage(data) {
worker.postMessage(data);
}
};
};
const getNodeWorker = (qrl) => {
return getOrCreateWorker(qrl, () => {
const WorkerConstructor = getNodeWorkerConstructor();
if (!WorkerConstructor) {
return null;
}
const worker = new WorkerConstructor(getNodeWorkerUrl(), {
name: getWorkerName(qrl),
workerData: {
qrlBaseUrl: getNodeWorkerQrlBaseUrl().href
}
});
worker.unref();
return createNodeWorkerTransport(worker);
});
};
const runtimeGlobals = globalThis;
const isBrowserRuntime = () => !!runtimeGlobals.document;
const isBunRuntime = () => !!runtimeGlobals.process?.versions?.bun;
const isDenoRuntime = () => !!runtimeGlobals.Deno?.version?.deno;
const isNodeRuntime = () => !!runtimeGlobals.process?.versions?.node && !isBunRuntime() && !isDenoRuntime();
const getWorkerTransport = async (qrl) => {
if (isNodeRuntime()) {
return getNodeWorker(qrl);
}
if (isBrowserRuntime()) {
return getBrowserWorker(qrl);
}
return null;
};
const workerQrl = (qrl) => {
return /* @__PURE__ */ inlinedQrl(async (...args) => {
const qrl2 = _captures[0];
const filtered = sanitizeWorkerArgs(args);
const worker = await getWorkerTransport(qrl2);
if (!worker) {
return qrl2(...filtered);
}
return invokeWorker(worker, qrl2, filtered);
}, "workerQrl_lGZKoP3eM7I", [
qrl
]);
};
const worker$ = implicit$FirstArg(workerQrl);
export {
worker$,
workerQrl
};