{"version":3,"sources":["../../src/thenable.ts"],"sourcesContent":["/**\n * Thenable types which matches React's types for promises\n *\n * React seemingly uses `.status`, `.value` and `.reason` properties on a promises to optimistically unwrap data from promises\n *\n * @see https://github.com/facebook/react/blob/main/packages/shared/ReactTypes.js#L112-L138\n * @see https://github.com/facebook/react/blob/4f604941569d2e8947ce1460a0b2997e835f37b9/packages/react-debug-tools/src/ReactDebugHooks.js#L224-L227\n */\n\nimport { noop } from './utils'\n\ninterface Fulfilled<T> {\n  status: 'fulfilled'\n  value: T\n}\ninterface Rejected {\n  status: 'rejected'\n  reason: unknown\n}\ninterface Pending<T> {\n  status: 'pending'\n\n  /**\n   * Resolve the promise with a value.\n   * Will remove the `resolve` and `reject` properties from the promise.\n   */\n  resolve: (value: T) => void\n  /**\n   * Reject the promise with a reason.\n   * Will remove the `resolve` and `reject` properties from the promise.\n   */\n  reject: (reason: unknown) => void\n}\n\nexport type FulfilledThenable<T> = Promise<T> & Fulfilled<T>\nexport type RejectedThenable<T> = Promise<T> & Rejected\nexport type PendingThenable<T> = Promise<T> & Pending<T>\n\nexport type Thenable<T> =\n  | FulfilledThenable<T>\n  | RejectedThenable<T>\n  | PendingThenable<T>\n\nexport function pendingThenable<T>(): PendingThenable<T> {\n  let resolve: Pending<T>['resolve']\n  let reject: Pending<T>['reject']\n  // this could use `Promise.withResolvers()` in the future\n  const thenable = new Promise((_resolve, _reject) => {\n    resolve = _resolve\n    reject = _reject\n  }) as PendingThenable<T>\n\n  thenable.status = 'pending'\n  thenable.catch(() => {\n    // prevent unhandled rejection errors\n  })\n\n  function finalize(data: Fulfilled<T> | Rejected) {\n    Object.assign(thenable, data)\n\n    // clear pending props to avoid calling them twice\n    delete (thenable as Partial<PendingThenable<T>>).resolve\n    delete (thenable as Partial<PendingThenable<T>>).reject\n  }\n\n  thenable.resolve = (value) => {\n    finalize({\n      status: 'fulfilled',\n      value,\n    })\n\n    resolve(value)\n  }\n  thenable.reject = (reason) => {\n    finalize({\n      status: 'rejected',\n      reason,\n    })\n\n    reject(reason)\n  }\n\n  return thenable\n}\n\n/**\n * This function takes a Promise-like input and detects whether the data\n * is synchronously available or not.\n *\n * It does not inspect .status, .value or .reason properties of the promise,\n * as those are not always available, and the .status of React's promises\n * should not be considered part of the public API.\n */\nexport function tryResolveSync(promise: Promise<unknown> | Thenable<unknown>) {\n  let data: unknown\n\n  promise\n    .then((result) => {\n      data = result\n      return result\n    }, noop)\n    // .catch can be unavailable on certain kinds of thenable's\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    ?.catch(noop)\n\n  if (data !== undefined) {\n    return { data }\n  }\n\n  return undefined\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,mBAAqB;AAkCd,SAAS,kBAAyC;AACvD,MAAI;AACJ,MAAI;AAEJ,QAAM,WAAW,IAAI,QAAQ,CAAC,UAAU,YAAY;AAClD,cAAU;AACV,aAAS;AAAA,EACX,CAAC;AAED,WAAS,SAAS;AAClB,WAAS,MAAM,MAAM;AAAA,EAErB,CAAC;AAED,WAAS,SAAS,MAA+B;AAC/C,WAAO,OAAO,UAAU,IAAI;AAG5B,WAAQ,SAAyC;AACjD,WAAQ,SAAyC;AAAA,EACnD;AAEA,WAAS,UAAU,CAAC,UAAU;AAC5B,aAAS;AAAA,MACP,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAED,YAAQ,KAAK;AAAA,EACf;AACA,WAAS,SAAS,CAAC,WAAW;AAC5B,aAAS;AAAA,MACP,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAA,EACf;AAEA,SAAO;AACT;AAUO,SAAS,eAAe,SAA+C;AA7F9E;AA8FE,MAAI;AAEJ,gBACG,KAAK,CAAC,WAAW;AAChB,WAAO;AACP,WAAO;AAAA,EACT,GAAG,iBAAI,MAJT,mBAOI,MAAM;AAEV,MAAI,SAAS,QAAW;AACtB,WAAO,EAAE,KAAK;AAAA,EAChB;AAEA,SAAO;AACT;","names":[]}