Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Typescript 5.2 Disposable for managing Guards #1

Open
nicoburniske opened this issue Jun 5, 2024 · 0 comments
Open

Use Typescript 5.2 Disposable for managing Guards #1

nicoburniske opened this issue Jun 5, 2024 · 0 comments

Comments

@nicoburniske
Copy link
Contributor

nicoburniske commented Jun 5, 2024

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html

I could not get this to work. It kept throwing TypeError("Object not disposable."). I chose to implement a custom drop function on the guards instead, and have a try/finally helper to manage releasing the resources.

// @ts-ignore
Symbol.dispose ??= Symbol("Symbol.dispose");
// @ts-ignore
Symbol.asyncDispose ??= Symbol("Symbol.asyncDispose");

export class AtomicOperationGuard implements Disposable {
  constructor(private begin: OplogIndex) {}

  [Symbol.dispose]() {
    console.log("Disposing AtomicOperationGuard!!!")
    markEndOperation(this.begin);
  }
}

export function markAtomicOperation(): AtomicOperationGuard {
  const begin = markBeginOperation();
  return new AtomicOperationGuard(begin);
}

export function infallibleTransaction<Out>(f: (tx: InfallibleTransaction) => Out) : Out {
  using _atomic = markAtomicOperation();
  const beginOplogIndex = getOplogIndex();
  const tx = new InfallibleTransaction(beginOplogIndex);
  const result = f(tx);
  return result
}

This is the typescript compiler output

function infallibleTransaction(f) {
    const env_2 = { stack: [], error: void 0, hasError: false };
    try {
        const _atomic = __addDisposableResource(env_2, markAtomicOperation(), false);
        const beginOplogIndex = getOplogIndex();
        const tx = new InfallibleTransaction(beginOplogIndex);
        const result = f(tx);
        return result;
    }
    catch (e_2) {
        env_2.error = e_2;
        env_2.hasError = true;
    }
    finally {
        __disposeResources(env_2);
    }
}
function __addDisposableResource(env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
        var dispose;
        if (async) {
            if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
            dispose = value[Symbol.dispose];
        }
        if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
        env.stack.push({ value: value, dispose: dispose, async: async });
    }
    else if (async) {
        env.stack.push({ async: true });
    }
    return value;
}

var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};

function __disposeResources(env) {
    function fail(e) {
        env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
        env.hasError = true;
    }
    function next() {
        while (env.stack.length) {
            var rec = env.stack.pop();
            try {
                var result = rec.dispose && rec.dispose.call(rec.value);
                if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
            }
            catch (e) {
                fail(e);
            }
        }
        if (env.hasError) throw env.error;
    }
    return next();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant