refactor: engine loading method

This commit is contained in:
impart我的impart 2024-03-08 23:30:41 +08:00
parent c612db09fd
commit 7ea06d1ef8
No known key found for this signature in database
GPG Key ID: 68ED75B1D060D166
4 changed files with 73 additions and 135 deletions

View File

@ -1,3 +1,19 @@
import { chronocat } from '@chronocat/shell' 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
})
})

View File

@ -19286,6 +19286,7 @@ interface Document {
declare namespace NodeJS { declare namespace NodeJS {
interface Process extends NodeJS.EventEmitter { interface Process extends NodeJS.EventEmitter {
domain: any;
// Docs: https://electronjs.org/docs/api/process // Docs: https://electronjs.org/docs/api/process
@ -19304,7 +19305,7 @@ declare namespace NodeJS {
/** /**
* * `allocated` Integer - Size of all allocated objects in Kilobytes. * * `allocated` Integer - Size of all allocated objects in Kilobytes.
* * `total` Integer - Total allocated space in Kilobytes. * * `total` Integer - Total allocated space in Kilobytes.
* *
* Returns an object with Blink memory information. It can be useful for debugging * 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 * rendering / DOM related memory issues. Note that all values are reported in
* Kilobytes. * Kilobytes.
@ -19314,7 +19315,7 @@ declare namespace NodeJS {
/** /**
* The number of milliseconds since epoch, or `null` if the information is * The number of milliseconds since epoch, or `null` if the information is
* unavailable * unavailable
* *
* Indicates the creation time of the application. The time is represented as * 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 * number of milliseconds since epoch. It returns null if it is unable to get the
* process creation time. * process creation time.
@ -19330,7 +19331,7 @@ declare namespace NodeJS {
* * `mallocedMemory` Integer * * `mallocedMemory` Integer
* * `peakMallocedMemory` Integer * * `peakMallocedMemory` Integer
* * `doesZapGarbage` boolean * * `doesZapGarbage` boolean
* *
* Returns an object with V8 heap statistics. Note that all statistics are reported * Returns an object with V8 heap statistics. Note that all statistics are reported
* in Kilobytes. * in Kilobytes.
*/ */
@ -19341,11 +19342,11 @@ declare namespace NodeJS {
getIOCounters(): Electron.IOCounters; getIOCounters(): Electron.IOCounters;
/** /**
* Resolves with a ProcessMemoryInfo * Resolves with a ProcessMemoryInfo
* *
* Returns an object giving memory usage statistics about the current process. Note * 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 * that all statistics are reported in Kilobytes. This api should be called after
* app ready. * app ready.
* *
* Chromium does not provide `residentSet` value for macOS. This is because macOS * 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 * 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` * 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. * Kilobytes available to the system.
* * `swapFree` Integer _Windows_ _Linux_ - The free amount of swap memory in * * `swapFree` Integer _Windows_ _Linux_ - The free amount of swap memory in
* Kilobytes available to the system. * Kilobytes available to the system.
* *
* Returns an object giving memory usage statistics about the entire system. Note * Returns an object giving memory usage statistics about the entire system. Note
* that all statistics are reported in Kilobytes. * that all statistics are reported in Kilobytes.
*/ */
getSystemMemoryInfo(): Electron.SystemMemoryInfo; getSystemMemoryInfo(): Electron.SystemMemoryInfo;
/** /**
* The version of the host operating system. * The version of the host operating system.
* *
* Example: * Example:
* *
* **Note:** It returns the actual operating system version instead of kernel * **Note:** It returns the actual operating system version instead of kernel
* version on macOS unlike `os.release()`. * version on macOS unlike `os.release()`.
*/ */
@ -19389,7 +19390,7 @@ declare namespace NodeJS {
setFdLimit(maxDescriptors: number): void; setFdLimit(maxDescriptors: number): void;
/** /**
* Indicates whether the snapshot has been created successfully. * Indicates whether the snapshot has been created successfully.
* *
* Takes a V8 heap snapshot and saves it to `filePath`. * Takes a V8 heap snapshot and saves it to `filePath`.
*/ */
takeHeapSnapshot(filePath: string): boolean; takeHeapSnapshot(filePath: string): boolean;
@ -19488,7 +19489,7 @@ declare namespace NodeJS {
traceProcessWarnings: boolean; traceProcessWarnings: boolean;
/** /**
* A `string` representing the current process's type, can be: * A `string` representing the current process's type, can be:
* *
* * `browser` - The main process * * `browser` - The main process
* * `renderer` - A renderer process * * `renderer` - A renderer process
* * `worker` - In a web worker * * `worker` - In a web worker
@ -19507,4 +19508,4 @@ declare namespace NodeJS {
readonly electron: string; readonly electron: string;
readonly chrome: string; readonly chrome: string;
} }
} }

View File

@ -1,7 +1,5 @@
import h from '@satorijs/element' import h from '@satorijs/element'
import styles from 'ansi-styles' import styles from 'ansi-styles'
import { mkdirSync, readdirSync } from 'node:fs'
import { join } from 'node:path'
import { initServers } from './server' import { initServers } from './server'
import { api } from './services/api' import { api } from './services/api'
import { getAuthData } from './services/authData' import { getAuthData } from './services/authData'
@ -24,14 +22,6 @@ export * from './types'
declare const __DEFINE_CHRONO_VERSION__: string declare const __DEFINE_CHRONO_VERSION__: string
interface EngineInfo {
name: string
filename: string
type: string
path: string
hidden: boolean
}
export const chronocat = async () => { export const chronocat = async () => {
l.info(`Chronocat v${__DEFINE_CHRONO_VERSION__}`) 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) emitter.register(setSelfProfile)
// getConfig() 包含用户配置,因此会先等待登录 // getConfig() 包含用户配置,因此会先等待登录
@ -173,7 +59,7 @@ export const chronocat = async () => {
l.debug('等待登录') l.debug('等待登录')
const config = await getConfig() const config = await getConfig()
if (!config.enable) { if (!config.enable) {
l.info('根据配置文件要求,退出 Chronocat') l.info('根据配置文件要求,Chronocat 不会启用。')
return return
} }
@ -187,7 +73,7 @@ export const chronocat = async () => {
// Log satori message // Log satori message
emitter.register(async (m) => { emitter.register(async (m) => {
if (m.type !== 'satori') return 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) emitter.register((await initServers(ctx)).emit)
@ -195,4 +81,39 @@ export const chronocat = async () => {
l.info('中身はあんまりないよ~ (v0.x)', { code: 560 }) l.info('中身はあんまりないよ~ (v0.x)', { code: 560 })
ready!() 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
} }

View File

@ -17,12 +17,12 @@ void Promise.all(
await cp(srcPath, distPath) await cp(srcPath, distPath)
await cp( // await cp(
distPath, // distPath,
resolve( // resolve(
__dirname, // __dirname,
`../build/dist/llqqnt/LiteLoaderQQNT-Plugin-Chronocat/src/${filename}`, // `../build/dist/llqqnt/LiteLoaderQQNT-Plugin-Chronocat/src/${filename}`,
), // ),
) // )
}), }),
) )