mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-28 06:22:45 -08:00
refactor: extract yomitan runtime wiring from main
This commit is contained in:
96
src/main/runtime/yomitan-extension-runtime.test.ts
Normal file
96
src/main/runtime/yomitan-extension-runtime.test.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import type { Extension } from 'electron';
|
||||
import { createYomitanExtensionRuntime } from './yomitan-extension-runtime';
|
||||
|
||||
test('yomitan extension runtime reuses in-flight ensure load and clears it after resolve', async () => {
|
||||
let extension: Extension | null = null;
|
||||
let inFlight: Promise<Extension | null> | null = null;
|
||||
let parserWindow: unknown = null;
|
||||
let readyPromise: Promise<void> | null = null;
|
||||
let initPromise: Promise<boolean> | null = null;
|
||||
let loadCalls = 0;
|
||||
const releaseLoadState: { releaseLoad: ((value: Extension | null) => void) | null } = {
|
||||
releaseLoad: null,
|
||||
};
|
||||
|
||||
const runtime = createYomitanExtensionRuntime({
|
||||
loadYomitanExtensionCore: async (options) => {
|
||||
loadCalls += 1;
|
||||
options.setYomitanParserWindow(null);
|
||||
options.setYomitanParserReadyPromise(Promise.resolve());
|
||||
options.setYomitanParserInitPromise(Promise.resolve(true));
|
||||
return await new Promise<Extension | null>((resolve) => {
|
||||
releaseLoadState.releaseLoad = (value) => {
|
||||
options.setYomitanExtension(value);
|
||||
resolve(value);
|
||||
};
|
||||
});
|
||||
},
|
||||
userDataPath: '/tmp',
|
||||
getYomitanParserWindow: () => parserWindow as never,
|
||||
setYomitanParserWindow: (window) => {
|
||||
parserWindow = window;
|
||||
},
|
||||
setYomitanParserReadyPromise: (promise) => {
|
||||
readyPromise = promise as Promise<void> | null;
|
||||
},
|
||||
setYomitanParserInitPromise: (promise) => {
|
||||
initPromise = promise as Promise<boolean> | null;
|
||||
},
|
||||
setYomitanExtension: (next) => {
|
||||
extension = next;
|
||||
},
|
||||
getYomitanExtension: () => extension,
|
||||
getLoadInFlight: () => inFlight,
|
||||
setLoadInFlight: (promise) => {
|
||||
inFlight = promise;
|
||||
},
|
||||
});
|
||||
|
||||
const first = runtime.ensureYomitanExtensionLoaded();
|
||||
const second = runtime.ensureYomitanExtensionLoaded();
|
||||
assert.equal(loadCalls, 1);
|
||||
assert.ok(inFlight);
|
||||
assert.equal(parserWindow, null);
|
||||
assert.ok(readyPromise);
|
||||
assert.ok(initPromise);
|
||||
|
||||
const fakeExtension = { id: 'yomitan' } as Extension;
|
||||
const releaseLoad = releaseLoadState.releaseLoad;
|
||||
if (!releaseLoad) {
|
||||
throw new Error('expected in-flight yomitan load resolver');
|
||||
}
|
||||
releaseLoad(fakeExtension);
|
||||
assert.equal(await first, fakeExtension);
|
||||
assert.equal(await second, fakeExtension);
|
||||
assert.equal(extension, fakeExtension);
|
||||
assert.equal(inFlight, null);
|
||||
|
||||
const third = await runtime.ensureYomitanExtensionLoaded();
|
||||
assert.equal(third, fakeExtension);
|
||||
assert.equal(loadCalls, 1);
|
||||
});
|
||||
|
||||
test('yomitan extension runtime direct load delegates to core', async () => {
|
||||
let loadCalls = 0;
|
||||
|
||||
const runtime = createYomitanExtensionRuntime({
|
||||
loadYomitanExtensionCore: async () => {
|
||||
loadCalls += 1;
|
||||
return null;
|
||||
},
|
||||
userDataPath: '/tmp',
|
||||
getYomitanParserWindow: () => null,
|
||||
setYomitanParserWindow: () => {},
|
||||
setYomitanParserReadyPromise: () => {},
|
||||
setYomitanParserInitPromise: () => {},
|
||||
setYomitanExtension: () => {},
|
||||
getYomitanExtension: () => null,
|
||||
getLoadInFlight: () => null,
|
||||
setLoadInFlight: () => {},
|
||||
});
|
||||
|
||||
assert.equal(await runtime.loadYomitanExtension(), null);
|
||||
assert.equal(loadCalls, 1);
|
||||
});
|
||||
50
src/main/runtime/yomitan-extension-runtime.ts
Normal file
50
src/main/runtime/yomitan-extension-runtime.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { createEnsureYomitanExtensionLoadedHandler, createLoadYomitanExtensionHandler } from './yomitan-extension-loader';
|
||||
import {
|
||||
createBuildEnsureYomitanExtensionLoadedMainDepsHandler,
|
||||
createBuildLoadYomitanExtensionMainDepsHandler,
|
||||
} from './yomitan-extension-loader-main-deps';
|
||||
|
||||
type LoadYomitanExtensionMainDeps = Parameters<
|
||||
typeof createBuildLoadYomitanExtensionMainDepsHandler
|
||||
>[0];
|
||||
|
||||
type EnsureYomitanExtensionLoadedMainDeps = Omit<
|
||||
Parameters<typeof createBuildEnsureYomitanExtensionLoadedMainDepsHandler>[0],
|
||||
'loadYomitanExtension'
|
||||
>;
|
||||
|
||||
export type YomitanExtensionRuntimeDeps = LoadYomitanExtensionMainDeps &
|
||||
EnsureYomitanExtensionLoadedMainDeps;
|
||||
|
||||
export function createYomitanExtensionRuntime(deps: YomitanExtensionRuntimeDeps) {
|
||||
const buildLoadYomitanExtensionMainDepsHandler = createBuildLoadYomitanExtensionMainDepsHandler({
|
||||
loadYomitanExtensionCore: deps.loadYomitanExtensionCore,
|
||||
userDataPath: deps.userDataPath,
|
||||
getYomitanParserWindow: deps.getYomitanParserWindow,
|
||||
setYomitanParserWindow: deps.setYomitanParserWindow,
|
||||
setYomitanParserReadyPromise: deps.setYomitanParserReadyPromise,
|
||||
setYomitanParserInitPromise: deps.setYomitanParserInitPromise,
|
||||
setYomitanExtension: deps.setYomitanExtension,
|
||||
});
|
||||
const loadYomitanExtensionHandler = createLoadYomitanExtensionHandler(
|
||||
buildLoadYomitanExtensionMainDepsHandler(),
|
||||
);
|
||||
|
||||
const buildEnsureYomitanExtensionLoadedMainDepsHandler =
|
||||
createBuildEnsureYomitanExtensionLoadedMainDepsHandler({
|
||||
getYomitanExtension: deps.getYomitanExtension,
|
||||
getLoadInFlight: deps.getLoadInFlight,
|
||||
setLoadInFlight: deps.setLoadInFlight,
|
||||
loadYomitanExtension: () => loadYomitanExtensionHandler(),
|
||||
});
|
||||
const ensureYomitanExtensionLoadedHandler = createEnsureYomitanExtensionLoadedHandler(
|
||||
buildEnsureYomitanExtensionLoadedMainDepsHandler(),
|
||||
);
|
||||
|
||||
return {
|
||||
loadYomitanExtension: (): Promise<ReturnType<typeof deps.getYomitanExtension>> =>
|
||||
loadYomitanExtensionHandler(),
|
||||
ensureYomitanExtensionLoaded: (): Promise<ReturnType<typeof deps.getYomitanExtension>> =>
|
||||
ensureYomitanExtensionLoadedHandler(),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user