Skip to content

Commit

Permalink
feat(eval): support yaml loader
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Apr 13, 2021
1 parent cc4e004 commit a3b5297
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 13 deletions.
2 changes: 2 additions & 0 deletions packages/plugin-eval/src/loaders/default.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Script } from 'vm'

export const name = 'default'

export function extractScript(expr: string) {
try {
Reflect.construct(Script, [expr])
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-eval/src/loaders/esbuild.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import esbuild from 'esbuild'

export const name = 'typescript'

export function extractScript(expr: string) {
try {
esbuild.transformSync(expr, {
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-eval/src/loaders/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { Logger } from 'koishi-utils'

export { extractScript } from './default'

export const name = 'typescript'

const compilerOptions: ts.CompilerOptions = {
inlineSourceMap: true,
module: ts.ModuleKind.ES2020,
Expand Down
9 changes: 9 additions & 0 deletions packages/plugin-eval/src/loaders/yaml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { load } from 'js-yaml'

export const name = 'yaml'

export const isTextLoader = false

export function transformModule(source: string) {
return load(source)
}
2 changes: 2 additions & 0 deletions packages/plugin-eval/src/worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export interface WorkerData extends WorkerConfig {
}

export interface Loader {
name: string
isTextLoader: boolean
prepare(config: WorkerData): void | Promise<void>
extractScript(expr: string): string
transformScript(expr: string): string | Promise<string>
Expand Down
38 changes: 25 additions & 13 deletions packages/plugin-eval/src/worker/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function synthetize(identifier: string, namespace: {}, globalName?: strin
modules[identifier] = module
config.addonNames?.unshift(identifier)
if (globalName) synthetics[globalName] = module
return module
}

const suffixes = ['', '.js', '.ts', '/index.js', '/index.ts']
Expand Down Expand Up @@ -102,10 +103,6 @@ export async function safeWriteFile(filename: string, data: any) {
}
}

declare const BUILTIN_LOADERS: string[]

const loaders: Record<string, Loader> = {}

export default async function prepare() {
if (!config.root) return
const cachePath = resolve(config.root, config.cacheFile || '.koishi/cache')
Expand All @@ -132,6 +129,10 @@ function exposeGlobal(name: string, namespace: {}) {
internal.setGlobal(name, outer)
}

declare const BUILTIN_LOADERS: string[]
const fileAssoc: Record<string, Loader> = {}
const loaderSet = new Set<Loader>()

function resolveLoader(extension: string) {
const filename = config.moduleLoaders[extension]
if (BUILTIN_LOADERS.includes(filename)) {
Expand All @@ -140,6 +141,8 @@ function resolveLoader(extension: string) {
return require(resolve(process.cwd(), filename))
} else if (extension === '.js') {
return require('../loaders/default')
} else if (extension === '.yml' || extension === '.yaml') {
return require('../loaders/yaml')
} else if (extension === '.ts') {
for (const filename of ['esbuild', 'typescript']) {
try {
Expand All @@ -148,14 +151,18 @@ function resolveLoader(extension: string) {
}
throw new Error('cannot resolve loader for ".ts", you should install either esbuild or typescript + json5 by yourself')
} else {
throw new Error(`cannot resolve loader for "${extension}", you should specify a custom loader through "config.moduleLoaders"`)
throw new Error(`cannot resolve loader for "${extension}", you should specify a custom loader via "config.moduleLoaders"`)
}
}

async function createLoader(extension: string) {
const loader: Loader = resolveLoader(extension)
logger.debug('creating loader for %c', extension)
await loader.prepare?.(config)
// loader.prepare() should only be called once
if (!loaderSet.has(loader)) {
loaderSet.add(loader)
logger.debug('creating loader %c', loader.name)
await loader.prepare?.(config)
}
return loader
}

Expand All @@ -169,13 +176,18 @@ async function createModule(path: string) {
const { outputText, cachedData } = files[source] = cache
module = new SourceTextModule(outputText, { context, identifier, cachedData })
} else {
type = 'source text'
const extension = extname(identifier)
const loader = loaders[extension] ||= await createLoader(extension)
const outputText = await loader.transformModule(source)
module = new SourceTextModule(outputText, { context, identifier })
const cachedData = module.createCachedData()
files[source] = { outputText, cachedData }
const loader = fileAssoc[extension] ||= await createLoader(extension)
if (loader.isTextLoader !== false) {
type = 'source text'
const outputText = await loader.transformModule(source)
module = new SourceTextModule(outputText, { context, identifier })
const cachedData = module.createCachedData()
files[source] = { outputText, cachedData }
} else {
const exports = await loader.transformModule(source)
module = synthetize(identifier, { default: exports })
}
}
modules[identifier] = module
} else if (module.status !== 'unlinked') {
Expand Down

0 comments on commit a3b5297

Please sign in to comment.