Skip to content

Commit

Permalink
feat(eval): support loaderConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Apr 19, 2021
1 parent 8b91a7b commit 5425e52
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 20 deletions.
2 changes: 1 addition & 1 deletion packages/plugin-chat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class SandboxBot extends Bot<'web'> {

const builtinWhitelist = [
'http://gchat.qpic.cn/',
'http://c2cpicdw.qpic.cn',
'http://c2cpicdw.qpic.cn/',
]

const defaultOptions: Config = {
Expand Down
19 changes: 5 additions & 14 deletions packages/plugin-eval/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { resolve } from 'path'
import { load } from 'js-yaml'
import { promises as fs } from 'fs'
import Git, { CheckRepoActions } from 'simple-git'
import { WorkerResponse, Loader } from './worker'
import { WorkerResponse } from './worker'

export * from './main'

Expand Down Expand Up @@ -58,15 +58,14 @@ const defaultConfig: EvalConfig = {
authority: 2,
timeout: 1000,
setupFiles: {},
loaderConfig: {},
moduleLoaders: {},
scriptLoader: 'default',
channelFields: ['id'],
userFields: ['id', 'authority'],
dataKeys: ['inspect', 'moduleLoaders', 'setupFiles'],
dataKeys: ['inspect', 'moduleLoaders', 'setupFiles', 'loaderConfig'],
}

declare const BUILTIN_LOADERS: string[]

const logger = new Logger('eval')

export const name = 'eval'
Expand All @@ -78,14 +77,6 @@ export function apply(ctx: Context, config: Config = {}) {

ctx.worker = new EvalWorker(ctx, config)

// resolve loader filepath
if (BUILTIN_LOADERS.includes(config.scriptLoader)) {
config.scriptLoader = resolve(__dirname, 'loaders', config.scriptLoader)
} else {
config.scriptLoader = resolve(process.cwd(), config.scriptLoader)
}
const loader = require(config.scriptLoader) as Loader

// addons are registered in another plugin
if (config.root) ctx.plugin(addon, config)

Expand Down Expand Up @@ -120,7 +111,7 @@ export function apply(ctx: Context, config: Config = {}) {
if (!expr) return '请输入要执行的脚本。'

try {
expr = await loader.transformScript(segment.unescape(expr))
expr = await ctx.worker.loader.transformScript(segment.unescape(expr))
} catch (err) {
return err.message
}
Expand Down Expand Up @@ -164,7 +155,7 @@ export function apply(ctx: Context, config: Config = {}) {
}

Argv.interpolate('${', '}', (source) => {
const result = loader.extractScript(segment.unescape(source))
const result = ctx.worker.loader.extractScript(segment.unescape(source))
if (!result) {
const index = source.indexOf('}')
if (index >= 0) return { source, rest: source.slice(index + 1), tokens: [] }
Expand Down
18 changes: 17 additions & 1 deletion packages/plugin-eval/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { App, Command, Channel, Argv as IArgv, User, Context } from 'koishi-core'
import { Logger, Observed, pick, union } from 'koishi-utils'
import { Worker, ResourceLimits } from 'worker_threads'
import { WorkerHandle, WorkerConfig, WorkerData, SessionData } from './worker'
import { WorkerHandle, WorkerConfig, WorkerData, SessionData, Loader } from './worker'
import { expose, Remote, wrap } from './transfer'
import { resolve } from 'path'

Expand Down Expand Up @@ -164,27 +164,43 @@ function createRequire(filename: string) {

enum State { closing, close, opening, open }

declare const BUILTIN_LOADERS: string[]

export class EvalWorker {
private prevent = false
private worker: Worker
private promise: Promise<void>

public state = State.close
public local: MainHandle
public loader: Loader
public remote: Remote<WorkerHandle>

static readonly State = State

constructor(public ctx: Context, public config: EvalConfig) {
this.local = new MainHandle(ctx.app)

ctx.before('eval/start', () => this.prepare(config))

// wait for dependents to be executed
process.nextTick(() => {
ctx.on('connect', () => this.start())
ctx.before('disconnect', () => this.stop())
})
}

prepare = async ({ scriptLoader, loaderConfig }: EvalConfig) => {
// resolve loader filepath
if (BUILTIN_LOADERS.includes(scriptLoader)) {
scriptLoader = resolve(__dirname, 'loaders', scriptLoader)
} else {
scriptLoader = resolve(process.cwd(), scriptLoader)
}
this.loader = require(scriptLoader)
return this.loader.prepare?.(loaderConfig)
}

// delegated class methods which use instance properties
// should be written in arrow functions to ensure accessibility
start = async () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-eval/src/worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const config: WorkerData = {
},
}

import prepare, { synthetize, readSerialized, safeWriteFile } from './loader'
import prepare, { synthetize, readSerialized, safeWriteFile, LoaderConfig } from './loader'
import { expose, wrap } from '../transfer'
import { Sandbox } from './sandbox'
import { MainHandle } from '..'
Expand All @@ -34,6 +34,7 @@ export interface WorkerConfig {
cacheFile?: string
storageFile?: string
setupFiles?: Record<string, string>
loaderConfig?: LoaderConfig
}

export interface WorkerData extends WorkerConfig {
Expand Down
11 changes: 8 additions & 3 deletions packages/plugin-eval/src/worker/loader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { config, context, internal, WorkerData } from '.'
import { config, context, internal } from '.'
import { resolve, posix, dirname, extname } from 'path'
import { promises as fs } from 'fs'
import { deserialize, serialize, cachedDataVersionTag } from 'v8'
Expand All @@ -21,12 +21,17 @@ interface Module {
export interface Loader {
name: string
synthetize: boolean
prepare(config: WorkerData): void | Promise<void>
prepare(config: LoaderConfig, root?: string): void | Promise<void>
extractScript(expr: string): string
transformScript(expr: string): string | Promise<string>
transformModule(expr: string, extension: string): string | Promise<string>
}

export interface LoaderConfig {
jsxFactory?: string
jsxFragment?: string
}

export const modules: Record<string, Module> = {}
export const synthetics: Record<string, Module> = {}

Expand Down Expand Up @@ -185,7 +190,7 @@ async function createLoader(extension: string) {
if (!loaderSet.has(loader)) {
loaderSet.add(loader)
logger.debug('creating loader %c', loader.name)
await loader.prepare?.(config)
await loader.prepare?.(config.loaderConfig, config.root)
}
return loader
}
Expand Down

0 comments on commit 5425e52

Please sign in to comment.