UNPKG

ts-raii-scope

Version:
80 lines (79 loc) 2.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const disposableResource_1 = require("./disposableResource"); const utils_1 = require("./utils"); class RaiiScope { constructor(...args) { this._stack = []; this._isDisposed = false; for (const arg of args) { this.push(arg); } } // noinspection JSUnusedGlobalSymbols static doInside(resources, action) { const scope = new RaiiScope(...resources); try { return action(...resources); } finally { scope.dispose(); } } // noinspection JSUnusedGlobalSymbols static async doInsideAsync(resources, action) { const scope = new RaiiScope(...resources); return action(...resources).then(async (result) => { await scope.dispose(); return result; }, async (reason) => { await scope.dispose(); throw reason; }); } push(resource, disposeCallback) { if (utils_1.isDisposable(resource)) { if (disposeCallback) { throw new Error('Disposable resource passed with extra disposeCallback'); } return this.pushUnique(resource); } if (disposeCallback) { this.pushUnique(new disposableResource_1.DisposableResource(resource, disposeCallback)); return resource; } throw new Error('Passed not disposable resource without disposeCallback'); } dispose() { if (this._isDisposed === false) { const disposeResult = this.disposeImpl(); if (utils_1.isPromise(disposeResult)) { return disposeResult.then(() => { this._isDisposed = true; }); } this._isDisposed = true; } } disposeImpl() { const resource = this._stack.pop(); if (resource) { const disposing = utils_1.safeDisposeResource(resource); return utils_1.isPromise(disposing) ? disposing.then(() => this.disposeImpl()) : this.disposeImpl(); } } pushUnique(resource) { if (this._isDisposed === true) { throw new Error('Already disposed'); } if (this._isDisposed === undefined) { throw new Error('Disposing in progress'); } if (this._stack.indexOf(resource) !== -1) { throw new Error('Resource already pushed'); } this._stack.push(resource); return resource; } } exports.RaiiScope = RaiiScope;