UNPKG

@launchmenu/core

Version:

An environment for visual keyboard controlled applets

132 lines (131 loc) 8.26 kB
"use strict"; 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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