Files
2026-10-22 17:07:08 +08:00

53 lines
1.8 KiB
TypeScript

import {EventEmitter} from 'node:events';
import {AsyncLocalStorage} from 'node:async_hooks';
import type {Bot} from '@wp2508/mineflayer';
type Cancellation = {generation: number; events: EventEmitter};
const scopes = new AsyncLocalStorage<{bot: Bot; cancellation: Cancellation}>();
const states = new WeakMap<Bot, Cancellation & {scopes: Set<Cancellation>}>();
function state(bot: Bot) {
let value = states.get(bot);
if (!value) states.set(bot, value = {generation: 0, events: new EventEmitter(), scopes: new Set()});
return value;
}
function current(bot: Bot): Cancellation {
const scope = scopes.getStore();
return scope?.bot === bot ? scope.cancellation : state(bot);
}
export function cancellation_generation(bot: Bot): number {
return current(bot).generation;
}
export function on_function_cancel(bot: Bot, listener: () => void): () => void {
const {events} = current(bot);
events.on('cancel', listener);
return () => { events.removeListener('cancel', listener); };
}
/** Existing helpers inherit the call's cancellation scope across awaits. */
export function create_function_cancellation(bot: Bot) {
const value = state(bot);
const cancellation: Cancellation = {generation: 0, events: new EventEmitter()};
value.scopes.add(cancellation);
return {
run<T>(operation: () => T): T { return scopes.run({bot, cancellation}, operation); },
cancel() {
cancellation.generation++;
cancellation.events.emit('cancel');
},
dispose() { value.scopes.delete(cancellation); },
};
}
export function cancel_functions(bot: Bot): void {
const value = state(bot);
value.generation++;
value.events.emit('cancel');
for (const cancellation of value.scopes) {
cancellation.generation++;
cancellation.events.emit('cancel');
}
}