X Tutup
// The following is a translation of the TypeScript async awaiter which uses generators and yields. // For Lua we use coroutines instead. // // Source: // // var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { // function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } // return new (P || (P = Promise))(function (resolve, reject) { // function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } // function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } // function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } // step((generator = generator.apply(thisArg, _arguments || [])).next()); // }); // }; // import { __TS__Promise } from "./Promise"; const coroutine = _G.coroutine ?? {}; const cocreate = coroutine.create; const coresume = coroutine.resume; const costatus = coroutine.status; const coyield = coroutine.yield; // Be extremely careful editing this function. A single non-tail function call may ruin chained awaits performance // eslint-disable-next-line @typescript-eslint/promise-function-async export function __TS__AsyncAwaiter(this: void, generator: (this: void) => void) { return new Promise((resolve, reject) => { let resolved = false; const asyncCoroutine = cocreate(generator); function fulfilled(value: unknown): void { const [success, resultOrError] = coresume(asyncCoroutine, value); if (success) { // `step` never throws. Tail call return is important! return step(resultOrError); } // `reject` should never throw. Tail call return is important! return reject(resultOrError); } function step(this: void, result: unknown): void { if (resolved) { return; } if (costatus(asyncCoroutine) === "dead") { // `resolve` never throws. Tail call return is important! return resolve(result); } // We cannot use `then` because we need to avoid calling `coroutine.resume` from inside `pcall` // `fulfilled` and `reject` should never throw. Tail call return is important! return __TS__Promise.resolve(result).addCallbacks(fulfilled, reject); } const [success, resultOrError] = coresume(asyncCoroutine, (v: unknown) => { resolved = true; return __TS__Promise.resolve(v).addCallbacks(resolve, reject); }); if (success) { return step(resultOrError); } else { return reject(resultOrError); } }); } export function __TS__Await(this: void, thing: unknown) { return coyield(thing); }
X Tutup