Skip to content

Commit

Permalink
feat(cordis): cancel with invalid config
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Aug 15, 2024
1 parent aa4f973 commit 5589bca
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 21 deletions.
17 changes: 9 additions & 8 deletions packages/core/src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,19 +161,20 @@ class Registry<C extends Context = Context> {
return this.plugin({ inject, apply: callback, name: callback.name })
}

plugin(plugin: Plugin<C>, config?: any) {
plugin(plugin: Plugin<C>, config?: any, error?: any) {
// check if it's a valid plugin
this.resolve(plugin, true)
this.ctx.scope.assertActive()

// resolve plugin config
let error: any
try {
config = resolveConfig(plugin, config)
} catch (reason) {
this.context.emit(this.ctx, 'internal/error', reason)
error = reason
config = null
if (!error) {
try {
config = resolveConfig(plugin, config)
} catch (reason) {
this.context.emit(this.ctx, 'internal/error', reason)
error = reason
config = null
}
}

// check duplication
Expand Down
16 changes: 14 additions & 2 deletions packages/core/src/scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,13 @@ export class ForkScope<C extends Context = Context> extends EffectScope<C> {
const oldConfig = this.config
const state: EffectScope<C> = this.runtime.isForkable ? this : this.runtime
if (state.config !== oldConfig) return
const resolved = resolveConfig(this.runtime.plugin, config)
let resolved: any
try {
resolved = resolveConfig(this.runtime.plugin, config)
} catch (error) {
this.context.emit('internal/error', error)
return this.cancel(error)
}
const [hasUpdate, shouldRestart] = state.checkUpdate(resolved, forced)
this.context.emit('internal/before-update', this, config)
this.config = resolved
Expand Down Expand Up @@ -393,7 +399,13 @@ export class MainScope<C extends Context = Context> extends EffectScope<C> {
this.context.emit(this.ctx, 'internal/warning', warning)
}
const oldConfig = this.config
const resolved = resolveConfig(this.runtime.plugin || this.context.constructor, config)
let resolved: any
try {
resolved = resolveConfig(this.runtime.plugin || this.context.constructor, config)
} catch (error) {
this.context.emit('internal/error', error)
return this.cancel(error)
}
const [hasUpdate, shouldRestart] = this.checkUpdate(resolved, forced)
const state = this.children.find(fork => fork.config === oldConfig)
this.config = resolved
Expand Down
27 changes: 21 additions & 6 deletions packages/loader/src/config/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isNullable } from 'cosmokit'
import { Loader } from '../loader.ts'
import { EntryGroup } from './group.ts'
import { EntryTree } from './tree.ts'
import { interpolate } from './utils.ts'
import { evaluate, interpolate } from './utils.ts'

export interface EntryOptions {
id: string
Expand Down Expand Up @@ -76,9 +76,18 @@ export class Entry<C extends Context = Context> {
return !this.parent.ctx.bail('loader/entry-check', this)
}

_resolveConfig(plugin: any) {
if (!plugin[EntryGroup.key]) return this.options.config
return interpolate({}, this.options.config) // FIXME
evaluate(expr: string) {
return evaluate(this.ctx, expr)
}

_resolveConfig(plugin: any): [any, any?] {
if (plugin[EntryGroup.key]) return [this.options.config]
try {
return [interpolate(this.ctx, this.options.config)]
} catch (error) {
this.context.emit(this.ctx, 'internal/error', error)
return [null, error]
}
}

patch(options: Partial<EntryOptions> = {}) {
Expand All @@ -92,7 +101,12 @@ export class Entry<C extends Context = Context> {
if (this.fork && 'config' in options) {
// step 2: update fork (when options.config is updated)
this.suspend = true
this.fork.update(this._resolveConfig(this.fork.runtime.plugin))
const [config, error] = this._resolveConfig(this.fork.runtime.plugin)
if (error) {
this.fork.cancel(error)
} else {
this.fork.update(config)
}
} else if (this.subgroup && 'disabled' in options) {
// step 3: check children (when options.disabled is updated)
const tree = this.subtree ?? this.parent.tree
Expand Down Expand Up @@ -152,7 +166,8 @@ export class Entry<C extends Context = Context> {
const plugin = this.loader.unwrapExports(exports)
this.patch()
this.ctx[Entry.key] = this
this.fork = this.ctx.plugin(plugin, this._resolveConfig(plugin))
const [config, error] = this._resolveConfig(plugin)
this.fork = this.ctx.registry.plugin(plugin, config, error)
this.context.emit('loader/entry-fork', this, 'apply')
}

Expand Down
8 changes: 3 additions & 5 deletions packages/loader/src/config/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ import * as yaml from 'js-yaml'

// eslint-disable-next-line no-new-func
export const evaluate = new Function('ctx', 'expr', `
try {
with (ctx) {
return eval(expr)
}
} catch {}
with (ctx) {
return eval(expr)
}
`) as ((ctx: object, expr: string) => any)

export function interpolate(ctx: object, value: any) {
Expand Down

0 comments on commit 5589bca

Please sign in to comment.