{"version":3,"file":"deferred-promise.js","sourceRoot":"","sources":["../ts/deferred-promise.ts"],"names":[],"mappings":";;;AAMA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,sBAAsB;IAoBjC;;;;OAIG;IACH,YAAY,IAKX;QAWD;;;;;;;WAOG;QACH,YAAO,GAAG,CAAC,KAAqB,EAAE,EAAE;YAClC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;gBAC7B,OAAM;aACP;YAED,IAAI,CAAC,OAAO;iBACT,YAAY,CACX,IAAI,CAAC,OAAO,CAAC,YAAY,CACvB,IAAI,CAAC,aAAa,EAClB,IAAI,CAAC,OAAO,CAAC,SAAS,EACtB,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAChC,CACF;iBACA,OAAO,EAAE,CAAA;YAEZ,IAAI,CAAC,gBAAgB,EAAE,CAAA;YACvB,IAAI,CAAC,SAAS,EAAE,CAAA;QAClB,CAAC,CAAA;QAED;;;;;;;WAOG;QACH,WAAM,GAAG,CAAC,KAAqB,EAAE,EAAE;YACjC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;gBAC5B,OAAM;aACP;YAED,IAAI,CAAC,OAAO;iBACT,YAAY,CACX,IAAI,CAAC,OAAO,CAAC,YAAY,CACvB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,OAAO,CAAC,SAAS,EACtB,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAChC,CACF;iBACA,OAAO,EAAE,CAAA;YAEZ,IAAI,CAAC,gBAAgB,EAAE,CAAA;YACvB,IAAI,CAAC,SAAS,EAAE,CAAA;QAClB,CAAC,CAAA;QAMD,YAAO,GAAG,GAAG,EAAE;YACb,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;gBACrB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;aACtB;YACD,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACzB,CAAC,CAAA;QAzEC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAA;QACjC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAA;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAA;QAC1B,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACvC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAA;IACvC,CAAC;IAwDD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAA;IACjF,CAAC;IASO,gBAAgB;QACtB,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;YAC5B,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAA;SAC7B;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE;YAC3B,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAA;SAC5B;IACH,CAAC;CACF;AAnHD,wDAmHC","sourcesContent":["import type { Disposable } from \"./lifetime\"\nimport type { QuickJSHandle } from \"./types\"\nimport type { QuickJSRuntime } from \"./runtime\"\nimport type { QuickJSContext } from \"./context\"\nexport type { PromiseExecutor } from \"./types\"\n\n/**\n * QuickJSDeferredPromise wraps a QuickJS promise [[handle]] and allows\n * [[resolve]]ing or [[reject]]ing that promise. Use it to bridge asynchronous\n * code on the host to APIs inside a QuickJSContext.\n *\n * Managing the lifetime of promises is tricky. There are three\n * [[QuickJSHandle]]s inside of each deferred promise object: (1) the promise\n * itself, (2) the `resolve` callback, and (3) the `reject` callback.\n *\n * - If the promise will be fulfilled before the end of it's [[owner]]'s lifetime,\n * the only cleanup necessary is `deferred.handle.dispose()`, because\n * calling [[resolve]] or [[reject]] will dispose of both callbacks automatically.\n *\n * - As the return value of a [[VmFunctionImplementation]], return [[handle]],\n * and ensure that either [[resolve]] or [[reject]] will be called. No other\n * clean-up is necessary.\n *\n * - In other cases, call [[dispose]], which will dispose [[handle]] as well as the\n * QuickJS handles that back [[resolve]] and [[reject]]. For this object,\n * [[dispose]] is idempotent.\n */\nexport class QuickJSDeferredPromise implements Disposable {\n public owner: QuickJSRuntime\n public context: QuickJSContext\n\n /**\n * A handle of the Promise instance inside the QuickJSContext.\n * You must dispose [[handle]] or the entire QuickJSDeferredPromise once you\n * are finished with it.\n */\n public handle: QuickJSHandle\n\n /**\n * A native promise that will resolve once this deferred is settled.\n */\n public settled: Promise<void>\n\n private resolveHandle: QuickJSHandle\n private rejectHandle: QuickJSHandle\n private onSettled!: () => void\n\n /**\n * Use [[QuickJSContext.newPromise]] to create a new promise instead of calling\n * this constructor directly.\n * @unstable\n */\n constructor(args: {\n context: QuickJSContext\n promiseHandle: QuickJSHandle\n resolveHandle: QuickJSHandle\n rejectHandle: QuickJSHandle\n }) {\n this.context = args.context\n this.owner = args.context.runtime\n this.handle = args.promiseHandle\n this.settled = new Promise((resolve) => {\n this.onSettled = resolve\n })\n this.resolveHandle = args.resolveHandle\n this.rejectHandle = args.rejectHandle\n }\n\n /**\n * Resolve [[handle]] with the given value, if any.\n * Calling this method after calling [[dispose]] is a no-op.\n *\n * Note that after resolving a promise, you may need to call\n * [[QuickJSContext.executePendingJobs]] to propagate the result to the promise's\n * callbacks.\n */\n resolve = (value?: QuickJSHandle) => {\n if (!this.resolveHandle.alive) {\n return\n }\n\n this.context\n .unwrapResult(\n this.context.callFunction(\n this.resolveHandle,\n this.context.undefined,\n value || this.context.undefined\n )\n )\n .dispose()\n\n this.disposeResolvers()\n this.onSettled()\n }\n\n /**\n * Reject [[handle]] with the given value, if any.\n * Calling this method after calling [[dispose]] is a no-op.\n *\n * Note that after rejecting a promise, you may need to call\n * [[QuickJSContext.executePendingJobs]] to propagate the result to the promise's\n * callbacks.\n */\n reject = (value?: QuickJSHandle) => {\n if (!this.rejectHandle.alive) {\n return\n }\n\n this.context\n .unwrapResult(\n this.context.callFunction(\n this.rejectHandle,\n this.context.undefined,\n value || this.context.undefined\n )\n )\n .dispose()\n\n this.disposeResolvers()\n this.onSettled()\n }\n\n get alive() {\n return this.handle.alive || this.resolveHandle.alive || this.rejectHandle.alive\n }\n\n dispose = () => {\n if (this.handle.alive) {\n this.handle.dispose()\n }\n this.disposeResolvers()\n }\n\n private disposeResolvers() {\n if (this.resolveHandle.alive) {\n this.resolveHandle.dispose()\n }\n\n if (this.rejectHandle.alive) {\n this.rejectHandle.dispose()\n }\n }\n}\n"]}