From 7ea06d1ef8c7a3bf8fb2794f46bec71279ac4004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?impart=E6=88=91=E7=9A=84impart?= Date: Fri, 8 Mar 2024 23:30:41 +0800 Subject: [PATCH] refactor: engine loading method --- packages/llqqnt/src/index.ts | 18 +++- packages/shell/src/electron.d.ts | 23 ++--- packages/shell/src/index.ts | 153 ++++++++----------------------- scripts/packengine.cts | 14 +-- 4 files changed, 73 insertions(+), 135 deletions(-) diff --git a/packages/llqqnt/src/index.ts b/packages/llqqnt/src/index.ts index f603751..7f247dd 100644 --- a/packages/llqqnt/src/index.ts +++ b/packages/llqqnt/src/index.ts @@ -1,3 +1,19 @@ import { chronocat } from '@chronocat/shell' +import { apply as ccApi } from '@chronocat/engine-chronocat-api' +import { version as ccApiVersion } from '@chronocat/engine-chronocat-api/package.json' +import { version as ccEventVersion } from '@chronocat/engine-chronocat-event/package.json' +import { apply as ccEvent } from '@chronocat/engine-chronocat-event' -void chronocat() +void chronocat().then(x => { + x?.load({ + name: 'engine-chronocat-api', + version: ccApiVersion, + apply: ccApi + }) + + x?.load({ + name: 'engine-chronocat-event', + version: ccEventVersion, + apply: ccEvent + }) +}) diff --git a/packages/shell/src/electron.d.ts b/packages/shell/src/electron.d.ts index 360d080..36ec112 100644 --- a/packages/shell/src/electron.d.ts +++ b/packages/shell/src/electron.d.ts @@ -19286,6 +19286,7 @@ interface Document { declare namespace NodeJS { interface Process extends NodeJS.EventEmitter { + domain: any; // Docs: https://electronjs.org/docs/api/process @@ -19304,7 +19305,7 @@ declare namespace NodeJS { /** * * `allocated` Integer - Size of all allocated objects in Kilobytes. * * `total` Integer - Total allocated space in Kilobytes. - * + * * Returns an object with Blink memory information. It can be useful for debugging * rendering / DOM related memory issues. Note that all values are reported in * Kilobytes. @@ -19314,7 +19315,7 @@ declare namespace NodeJS { /** * The number of milliseconds since epoch, or `null` if the information is * unavailable - * + * * Indicates the creation time of the application. The time is represented as * number of milliseconds since epoch. It returns null if it is unable to get the * process creation time. @@ -19330,7 +19331,7 @@ declare namespace NodeJS { * * `mallocedMemory` Integer * * `peakMallocedMemory` Integer * * `doesZapGarbage` boolean - * + * * Returns an object with V8 heap statistics. Note that all statistics are reported * in Kilobytes. */ @@ -19341,11 +19342,11 @@ declare namespace NodeJS { getIOCounters(): Electron.IOCounters; /** * Resolves with a ProcessMemoryInfo - * + * * Returns an object giving memory usage statistics about the current process. Note * that all statistics are reported in Kilobytes. This api should be called after * app ready. - * + * * Chromium does not provide `residentSet` value for macOS. This is because macOS * performs in-memory compression of pages that haven't been recently used. As a * result the resident set size value is not what one would expect. `private` @@ -19362,16 +19363,16 @@ declare namespace NodeJS { * Kilobytes available to the system. * * `swapFree` Integer _Windows_ _Linux_ - The free amount of swap memory in * Kilobytes available to the system. - * + * * Returns an object giving memory usage statistics about the entire system. Note * that all statistics are reported in Kilobytes. */ getSystemMemoryInfo(): Electron.SystemMemoryInfo; /** * The version of the host operating system. - * + * * Example: - * + * * **Note:** It returns the actual operating system version instead of kernel * version on macOS unlike `os.release()`. */ @@ -19389,7 +19390,7 @@ declare namespace NodeJS { setFdLimit(maxDescriptors: number): void; /** * Indicates whether the snapshot has been created successfully. - * + * * Takes a V8 heap snapshot and saves it to `filePath`. */ takeHeapSnapshot(filePath: string): boolean; @@ -19488,7 +19489,7 @@ declare namespace NodeJS { traceProcessWarnings: boolean; /** * A `string` representing the current process's type, can be: - * + * * * `browser` - The main process * * `renderer` - A renderer process * * `worker` - In a web worker @@ -19507,4 +19508,4 @@ declare namespace NodeJS { readonly electron: string; readonly chrome: string; } -} \ No newline at end of file +} diff --git a/packages/shell/src/index.ts b/packages/shell/src/index.ts index 7fb93c8..e8970bd 100644 --- a/packages/shell/src/index.ts +++ b/packages/shell/src/index.ts @@ -1,7 +1,5 @@ import h from '@satorijs/element' import styles from 'ansi-styles' -import { mkdirSync, readdirSync } from 'node:fs' -import { join } from 'node:path' import { initServers } from './server' import { api } from './services/api' import { getAuthData } from './services/authData' @@ -24,14 +22,6 @@ export * from './types' declare const __DEFINE_CHRONO_VERSION__: string -interface EngineInfo { - name: string - filename: string - type: string - path: string - hidden: boolean -} - export const chronocat = async () => { l.info(`Chronocat v${__DEFINE_CHRONO_VERSION__}`) @@ -61,110 +51,6 @@ export const chronocat = async () => { }, } - const engines: EngineInfo[] = [] - - const externalEnginesPath = join(baseDir, 'engines') - - mkdirSync(externalEnginesPath, { - recursive: true, - }) - - readdirSync(externalEnginesPath) - .map((filename) => { - let valid = false - let name = filename - let type = 'js' - - if (name.endsWith('.engine.jsc')) { - valid = true - name = name.slice(0, name.length - 11) - type = 'jsc' - } - - if (name.endsWith('.engine.js')) { - valid = true - name = name.slice(0, name.length - 10) - } - - if (!valid) return undefined - - return { - name, - filename, - type, - path: join(externalEnginesPath, filename), - hidden: false, - } - }) - .filter( - Boolean as unknown as (x: EngineInfo | undefined) => x is EngineInfo, - ) - .forEach((x) => engines.push(x)) - - // if (!engines.length) - readdirSync(__dirname) - .map((filename) => { - let valid = false - let name = filename - let type = 'js' - - if (name.endsWith('.engine.jsc')) { - valid = true - name = name.slice(0, name.length - 11) - type = 'jsc' - } - - if (name.endsWith('.engine.js')) { - valid = true - name = name.slice(0, name.length - 10) - } - - if (!valid) return undefined - - return { - name, - filename, - type, - path: join(__dirname, filename), - hidden: true, - } - }) - .filter( - Boolean as unknown as (x: EngineInfo | undefined) => x is EngineInfo, - ) - .forEach((x) => engines.push(x)) - - if (!engines.length) - l.warn('没有找到任何引擎。Chronocat 服务仍将启动。', { code: 2156 }) - - for (const engineInfo of engines) { - try { - l.debug( - `加载引擎:${styles.green.open}${engineInfo.filename}${styles.green.close}`, - ) - - if (engineInfo.type === 'jsc') require('bytenode') - - // eslint-disable-next-line @typescript-eslint/no-var-requires - const engine = require(engineInfo.path) as unknown as Engine - l.info( - `使用引擎 ${styles.green.open}${engine.name}${styles.green.close} v${engine.version}${engineInfo.hidden ? '' : `${styles.grey.open},来自 ${engineInfo.filename}${styles.grey.close}`}`, - ) - engine.apply(ctx) - } catch (e) { - setTimeout(() => process.exit(1), 2000) - l.error( - new Error(`加载引擎 ${engineInfo.filename} 失败`, { - cause: e, - }), - { - code: 2155, - throw: true, - }, - ) - } - } - emitter.register(setSelfProfile) // getConfig() 包含用户配置,因此会先等待登录 @@ -173,7 +59,7 @@ export const chronocat = async () => { l.debug('等待登录') const config = await getConfig() if (!config.enable) { - l.info('根据配置文件要求,退出 Chronocat') + l.info('根据配置文件要求,Chronocat 不会启用。') return } @@ -187,7 +73,7 @@ export const chronocat = async () => { // Log satori message emitter.register(async (m) => { if (m.type !== 'satori') return - ;(await m.toSatori(ctx, log)).forEach((e) => l.parse(e)) + ; (await m.toSatori(ctx, log)).forEach((e) => l.parse(e)) }) emitter.register((await initServers(ctx)).emit) @@ -195,4 +81,39 @@ export const chronocat = async () => { l.info('中身はあんまりないよ~ (v0.x)', { code: 560 }) ready!() + + const outerContext = { + load: (x: Engine) => x.apply(ctx), + } + + // 将 outerContext 挂载至 process.domain + if (!process || !process.domain) { + l.warn('process.domain 不存在,无法挂载 outerContext,一些 Engine 可能加载失败。') + } else { + // 如何通过 process.domain 获取 outerContext: + // ```ts + // process.domain = '__chronocat__' + // const outerContext = process.domain + // ``` + + const origDomain = process.domain + + let signalHack = false + // @ts-ignore + process.__defineSetter__('domain', (x) => { + if (x === '__chronocat__') + signalHack = true + }) + + // @ts-ignore + process.__defineGetter__('domain', () => { + if (signalHack) { + signalHack = false + return outerContext + } + return origDomain + }) + } + + return outerContext } diff --git a/scripts/packengine.cts b/scripts/packengine.cts index 703b6df..0beab2e 100644 --- a/scripts/packengine.cts +++ b/scripts/packengine.cts @@ -17,12 +17,12 @@ void Promise.all( await cp(srcPath, distPath) - await cp( - distPath, - resolve( - __dirname, - `../build/dist/llqqnt/LiteLoaderQQNT-Plugin-Chronocat/src/${filename}`, - ), - ) + // await cp( + // distPath, + // resolve( + // __dirname, + // `../build/dist/llqqnt/LiteLoaderQQNT-Plugin-Chronocat/src/${filename}`, + // ), + // ) }), )