waiter.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  4. var __getOwnPropNames = Object.getOwnPropertyNames;
  5. var __hasOwnProp = Object.prototype.hasOwnProperty;
  6. var __export = (target, all) => {
  7. for (var name in all)
  8. __defProp(target, name, { get: all[name], enumerable: true });
  9. };
  10. var __copyProps = (to, from, except, desc) => {
  11. if (from && typeof from === "object" || typeof from === "function") {
  12. for (let key of __getOwnPropNames(from))
  13. if (!__hasOwnProp.call(to, key) && key !== except)
  14. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15. }
  16. return to;
  17. };
  18. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  19. var waiter_exports = {};
  20. __export(waiter_exports, {
  21. Waiter: () => Waiter
  22. });
  23. module.exports = __toCommonJS(waiter_exports);
  24. var import_errors = require("./errors");
  25. var import_stackTrace = require("../utils/isomorphic/stackTrace");
  26. class Waiter {
  27. constructor(channelOwner, event) {
  28. this._failures = [];
  29. this._logs = [];
  30. this._waitId = channelOwner._platform.createGuid();
  31. this._channelOwner = channelOwner;
  32. this._savedZone = channelOwner._platform.zones.current().pop();
  33. this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: "before", event } }).catch(() => {
  34. });
  35. this._dispose = [
  36. () => this._channelOwner._wrapApiCall(async () => {
  37. await this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: "after", error: this._error } });
  38. }, { internal: true }).catch(() => {
  39. })
  40. ];
  41. }
  42. static createForEvent(channelOwner, event) {
  43. return new Waiter(channelOwner, event);
  44. }
  45. async waitForEvent(emitter, event, predicate) {
  46. const { promise, dispose } = waitForEvent(emitter, event, this._savedZone, predicate);
  47. return await this.waitForPromise(promise, dispose);
  48. }
  49. rejectOnEvent(emitter, event, error, predicate) {
  50. const { promise, dispose } = waitForEvent(emitter, event, this._savedZone, predicate);
  51. this._rejectOn(promise.then(() => {
  52. throw typeof error === "function" ? error() : error;
  53. }), dispose);
  54. }
  55. rejectOnTimeout(timeout, message) {
  56. if (!timeout)
  57. return;
  58. const { promise, dispose } = waitForTimeout(timeout);
  59. this._rejectOn(promise.then(() => {
  60. throw new import_errors.TimeoutError(message);
  61. }), dispose);
  62. }
  63. rejectImmediately(error) {
  64. this._immediateError = error;
  65. }
  66. dispose() {
  67. for (const dispose of this._dispose)
  68. dispose();
  69. }
  70. async waitForPromise(promise, dispose) {
  71. try {
  72. if (this._immediateError)
  73. throw this._immediateError;
  74. const result = await Promise.race([promise, ...this._failures]);
  75. if (dispose)
  76. dispose();
  77. return result;
  78. } catch (e) {
  79. if (dispose)
  80. dispose();
  81. this._error = e.message;
  82. this.dispose();
  83. (0, import_stackTrace.rewriteErrorMessage)(e, e.message + formatLogRecording(this._logs));
  84. throw e;
  85. }
  86. }
  87. log(s) {
  88. this._logs.push(s);
  89. this._channelOwner._wrapApiCall(async () => {
  90. await this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: "log", message: s } });
  91. }, { internal: true }).catch(() => {
  92. });
  93. }
  94. _rejectOn(promise, dispose) {
  95. this._failures.push(promise);
  96. if (dispose)
  97. this._dispose.push(dispose);
  98. }
  99. }
  100. function waitForEvent(emitter, event, savedZone, predicate) {
  101. let listener;
  102. const promise = new Promise((resolve, reject) => {
  103. listener = async (eventArg) => {
  104. await savedZone.run(async () => {
  105. try {
  106. if (predicate && !await predicate(eventArg))
  107. return;
  108. emitter.removeListener(event, listener);
  109. resolve(eventArg);
  110. } catch (e) {
  111. emitter.removeListener(event, listener);
  112. reject(e);
  113. }
  114. });
  115. };
  116. emitter.addListener(event, listener);
  117. });
  118. const dispose = () => emitter.removeListener(event, listener);
  119. return { promise, dispose };
  120. }
  121. function waitForTimeout(timeout) {
  122. let timeoutId;
  123. const promise = new Promise((resolve) => timeoutId = setTimeout(resolve, timeout));
  124. const dispose = () => clearTimeout(timeoutId);
  125. return { promise, dispose };
  126. }
  127. function formatLogRecording(log) {
  128. if (!log.length)
  129. return "";
  130. const header = ` logs `;
  131. const headerLength = 60;
  132. const leftLength = (headerLength - header.length) / 2;
  133. const rightLength = headerLength - header.length - leftLength;
  134. return `
  135. ${"=".repeat(leftLength)}${header}${"=".repeat(rightLength)}
  136. ${log.join("\n")}
  137. ${"=".repeat(headerLength)}`;
  138. }
  139. // Annotate the CommonJS export names for ESM import in node:
  140. 0 && (module.exports = {
  141. Waiter
  142. });