UNPKG

cubing

Version:

A collection of JavaScript cubing libraries.

240 lines (235 loc) 8.53 kB
import { PortableWorker, wrap } from "./chunk-SGJ5WPE4.js"; import { exposeAPI } from "./chunk-7GUL3OBQ.js"; import { Alg } from "./chunk-O6HEZXGY.js"; // src/cubing/search/worker-workarounds/index.ts function searchWorkerURLImportMetaResolve() { return import.meta.resolve("./search-worker-entry.js"); } function searchWorkerURLNewURLImportMetaURL() { return new URL("./search-worker-entry.js", import.meta.url); } async function searchWorkerURLEsbuildWorkaround() { exposeAPI.expose = false; return (await import("./search-worker-entry.js")).WORKER_ENTRY_FILE_URL; } // src/cubing/search/instantiator.ts function wrapAPI(worker) { return wrap(worker); } async function instantiateModuleWorker(workerEntryFileURL) { return new Promise(async (resolve, reject) => { try { const worker = new PortableWorker(workerEntryFileURL); const onFirstMessage = (messageData) => { if (messageData === "comlink-exposed") { resolve(wrapAPI(worker)); } else { reject( new Error(`wrong module instantiation message ${messageData}`) ); } }; const onError = (e) => { reject(e); }; if ("once" in worker) { worker.once("message", onFirstMessage); } else { worker.addEventListener("error", onError, { once: true }); worker.addEventListener( "message", (e) => onFirstMessage(e.data), { once: true } ); } } catch (e) { reject(e); } }); } var allWorkerAPIPromises = []; async function instantiateWorkerAPI() { const workerAPIPromise = instantiateWorkerImplementation(); allWorkerAPIPromises.push(workerAPIPromise); const insideAPI = await workerAPIPromise; insideAPI.setDebugMeasurePerf(searchOutsideDebugGlobals.logPerf); insideAPI.setScramblePrefetchLevel( searchOutsideDebugGlobals.scramblePrefetchLevel ); return workerAPIPromise; } async function instantiateWorkerImplementation() { if (globalThis.location?.protocol === "file:") { console.warn( "This current web page is loaded from the local filesystem (a URL that starts with `file://`). In this situation, `cubing.js` may be unable to generate scrambles or perform searches in some browsers. See: https://js.cubing.net/cubing/scramble/#file-server-required" ); } function failed(methodDescription) { return `Module worker instantiation${methodDescription ? ` ${methodDescription}` : ""} failed`; } const importMetaResolveStrategy = [ async () => instantiateModuleWorker(searchWorkerURLImportMetaResolve()), "using `import.meta.resolve(\u2026)", null ]; const esbuildWorkaroundStrategy = [ async () => instantiateModuleWorker(await searchWorkerURLEsbuildWorkaround()), "using the `esbuild` workaround", // TODO: we will hopefully discontinue the `esbuild` workaround at some // point, but `esbuild` has been stuck for 3 years on this issue. Because // `esbuild` and Vite (which uses `esbuild`) are now dominating the // ecosystem, this just causes a warning for a lot of devs/users that they // can't do anything about. As frustrating as the situation is, the // workaround is semantically fine (even if it's convoluted) and is // preserved by `esbuild`-based flows in practice. So we suppress the // warning in the medium-term but maintain long-term hope that we can // remove it (and the other fallbacks as well). null ]; const newURLStrategy = [ async () => instantiateModuleWorker(searchWorkerURLNewURLImportMetaURL()), "using `new URL(\u2026, import.meta.url)`", "will" ]; const fallbackOrder = searchOutsideDebugGlobals.prioritizeEsbuildWorkaroundForWorkerInstantiation ? [esbuildWorkaroundStrategy, importMetaResolveStrategy, newURLStrategy] : [importMetaResolveStrategy, esbuildWorkaroundStrategy, newURLStrategy]; for (const [fn, description, warnOnSuccess] of fallbackOrder) { try { const worker = await fn(); if (warnOnSuccess) { if (searchOutsideDebugGlobals.showWorkerInstantiationWarnings) { console.warn( `Module worker instantiation required ${description}. \`cubing.js\` ${warnOnSuccess} not support this fallback in the future.` ); } } return worker; } catch { } } throw new Error(`${failed()}. There are no more fallbacks available.`); } // src/cubing/search/outside.ts var cachedWorkerInstance; function getCachedWorkerInstance() { return cachedWorkerInstance ??= instantiateWorkerAPI(); } async function mapToAllWorkers(f) { await Promise.all( allWorkerAPIPromises.map(async (worker) => { f(await worker); }) ); } async function randomScrambleForEvent(eventID) { const worker = searchOutsideDebugGlobals.forceNewWorkerForEveryScramble ? await instantiateWorkerAPI() : await getCachedWorkerInstance(); const scrambleString = await worker.randomScrambleStringForEvent(eventID); return Alg.fromString(scrambleString); } async function deriveScrambleForEvent(derivationSeedHex, derivationSaltHierarchy, eventID) { if (!searchOutsideDebugGlobals.allowDerivedScrambles) { throw new Error("Derived scrambles are not allowed."); } const worker = searchOutsideDebugGlobals.forceNewWorkerForEveryScramble ? await instantiateWorkerAPI() : await getCachedWorkerInstance(); const scrambleString = await worker.deriveScrambleStringForEvent( derivationSeedHex, derivationSaltHierarchy, eventID ); return Alg.fromString(scrambleString); } async function experimentalSolve3x3x3IgnoringCenters(pattern) { const cwi = await getCachedWorkerInstance(); return Alg.fromString(await cwi.solve333ToString(pattern.patternData)); } async function experimentalSolve2x2x2(pattern) { const cwi = await getCachedWorkerInstance(); return Alg.fromString(await cwi.solve222ToString(pattern.patternData)); } async function solveSkewb(pattern) { const cwi = await getCachedWorkerInstance(); return Alg.fromString(await cwi.solveSkewbToString(pattern.patternData)); } async function solvePyraminx(pattern) { const cwi = await getCachedWorkerInstance(); return Alg.fromString(await cwi.solvePyraminxToString(pattern.patternData)); } async function solveMegaminx(pattern) { const cwi = await getCachedWorkerInstance(); return Alg.fromString(await cwi.solveMegaminxToString(pattern.patternData)); } async function solveTwips(kpuzzle, pattern, options) { const { targetPattern, ...otherOptions } = options ?? {}; const apiOptions = otherOptions; if (targetPattern) { apiOptions.targetPattern = targetPattern.patternData; } const { ...def } = kpuzzle.definition; delete def.experimentalIsPatternSolved; const dedicatedWorker = await instantiateWorkerAPI(); try { return Alg.fromString( // TODO: unnecessary because we terminate the worker? await dedicatedWorker.solveTwipsToString( def, pattern.patternData, apiOptions ) ); } finally { console.log("Search ended, terminating dedicated `twips` worker."); } } var searchOutsideDebugGlobals = { logPerf: true, scramblePrefetchLevel: "auto", forceNewWorkerForEveryScramble: false, showWorkerInstantiationWarnings: true, prioritizeEsbuildWorkaroundForWorkerInstantiation: false, allowDerivedScrambles: false }; function setSearchDebug(options) { const { logPerf, scramblePrefetchLevel } = options; if (typeof logPerf !== "undefined") { searchOutsideDebugGlobals.logPerf = logPerf; void mapToAllWorkers((worker) => worker.setDebugMeasurePerf(logPerf)); } if (typeof scramblePrefetchLevel !== "undefined") { searchOutsideDebugGlobals.scramblePrefetchLevel = scramblePrefetchLevel; void mapToAllWorkers( (worker) => worker.setScramblePrefetchLevel(scramblePrefetchLevel) ); } for (const booleanField of [ "forceNewWorkerForEveryScramble", "showWorkerInstantiationWarnings", "prioritizeEsbuildWorkaroundForWorkerInstantiation", "allowDerivedScrambles" ]) { if (booleanField in options) { searchOutsideDebugGlobals[booleanField] = options[booleanField] ?? searchOutsideDebugGlobals[booleanField]; } } } export { randomScrambleForEvent, deriveScrambleForEvent, experimentalSolve3x3x3IgnoringCenters, experimentalSolve2x2x2, solveSkewb, solvePyraminx, solveMegaminx, solveTwips, setSearchDebug }; //# sourceMappingURL=chunk-OUM32GEA.js.map