@launchmenu/core
Version:
An environment for visual keyboard controlled applets
132 lines (131 loc) • 8.26 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Command = void 0;
const model_react_1 = require("model-react");
const applicationResource_1 = require("./dependencies/applicationResource");
/**
* A base class for commands
*/
class Command {
constructor() {
this.state = new model_react_1.Field("ready");
this.dependencies = [applicationResource_1.applicationResource];
this.queue = [];
}
/**
* Executes the command
* @returns A promise that resolves once execution finished
*/
async execute() {
return this.addQueue("execute");
}
/**
* Reverts the command
* @returns A promise that resolves once reverting finished
*/
async revert() {
return this.addQueue("revert");
}
/**
* Adds a request to the queue
* @param type The type of request to add
* @returns The promise that resolves once the request is handled
*/
addQueue(type) {
let resolve = () => { };
let reject = () => { };
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
this.queue.push({
type,
promise,
resolve,
reject,
dependencies: this.acquireDependencies(),
});
if (this.queue.length == 1 && ["ready", "executed"].includes(this.getState()))
this.dispatch();
return promise;
}
/**
* Dispatches another execute or revert request if any remain
*/
async dispatch() {
const first = this.queue.shift();
if (!first)
return;
let error;
if (first.type == "execute") {
if (this.getState() != "executed") {
this.state.set("preparingForExecution");
const releasers = await first.dependencies;
this.state.set("executing");
try {
const res = this.onExecute();
if (res instanceof Promise)
await res;
}
catch (e) {
error = e;
}
releasers();
this.state.set("executed");
}
else
first.dependencies.then(releasers => releasers());
}
else {
if (this.getState() != "ready") {
this.state.set("preparingForRevert");
const releasers = await first.dependencies;
this.state.set("reverting");
try {
const res = this.onRevert();
if (res instanceof Promise)
await res;
}
catch (e) {
error = e;
}
releasers();
this.state.set("ready");
}
else
first.dependencies.then(releasers => releasers());
}
if (error)
first.reject(error);
else
first.resolve();
this.dispatch();
}
/**
* Acquires the dependencies
* @returns A function that can be used to release the dependencies
*/
async acquireDependencies() {
/*
Since we are performing a hold and wait operation,
there is a chance of things deadlocking.
We can't wait for all resources to be available at once however,
since the command execution order depends on the dependency claim order.
If a deadlock occurs, this should be solved by claiming the dependencies in the same order everywhere, E.g. always acquire A before B.
There doesn't seem to be a much better solution without making things massively complex.
*/
// Acquire the dependencies
let releasers = await Promise.all(this.dependencies.map(dependency => dependency.acquire()));
return () => releasers.forEach(release => release());
}
/**
* Retrieves the state of the command
* @param hook The hook to subscribe to changes
* @returns The state of the command
*/
getState(hook) {
return this.state.get(hook);
}
}
exports.Command = Command;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tbWFuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91bmRvUmVkby9Db21tYW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLDZDQUE2QztBQUk3Qyw0RUFBdUU7QUFFdkU7O0dBRUc7QUFDSCxNQUFzQixPQUFPO0lBQTdCO1FBR2MsVUFBSyxHQUFHLElBQUksbUJBQUssQ0FBQyxPQUF3QixDQUFDLENBQUM7UUFDbkMsaUJBQVksR0FBRyxDQUFDLHlDQUFtQixDQUFlLENBQUM7UUFDNUQsVUFBSyxHQUFHLEVBTWYsQ0FBQztJQXNIUixDQUFDO0lBcEhHOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxPQUFPO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLE1BQU07UUFDZixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxRQUFRLENBQUMsSUFBMEI7UUFDekMsSUFBSSxPQUFPLEdBQUcsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQ3ZCLElBQUksTUFBTSxHQUFHLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUN0QixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUMzQyxPQUFPLEdBQUcsR0FBRyxDQUFDO1lBQ2QsTUFBTSxHQUFHLEdBQUcsQ0FBQztRQUNqQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO1lBQ1osSUFBSTtZQUNKLE9BQU87WUFDUCxPQUFPO1lBQ1AsTUFBTTtZQUNOLFlBQVksRUFBRSxJQUFJLENBQUMsbUJBQW1CLEVBQUU7U0FDM0MsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFD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
;