abort-controller.mjs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. * @author Toru Nagashima <https://github.com/mysticatea>
  3. * See LICENSE file in root directory for full license.
  4. */
  5. import { EventTarget, defineEventAttribute } from 'event-target-shim';
  6. /**
  7. * The signal class.
  8. * @see https://dom.spec.whatwg.org/#abortsignal
  9. */
  10. class AbortSignal extends EventTarget {
  11. /**
  12. * AbortSignal cannot be constructed directly.
  13. */
  14. constructor() {
  15. super();
  16. throw new TypeError("AbortSignal cannot be constructed directly");
  17. }
  18. /**
  19. * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise.
  20. */
  21. get aborted() {
  22. const aborted = abortedFlags.get(this);
  23. if (typeof aborted !== "boolean") {
  24. throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`);
  25. }
  26. return aborted;
  27. }
  28. }
  29. defineEventAttribute(AbortSignal.prototype, "abort");
  30. /**
  31. * Create an AbortSignal object.
  32. */
  33. function createAbortSignal() {
  34. const signal = Object.create(AbortSignal.prototype);
  35. EventTarget.call(signal);
  36. abortedFlags.set(signal, false);
  37. return signal;
  38. }
  39. /**
  40. * Abort a given signal.
  41. */
  42. function abortSignal(signal) {
  43. if (abortedFlags.get(signal) !== false) {
  44. return;
  45. }
  46. abortedFlags.set(signal, true);
  47. signal.dispatchEvent({ type: "abort" });
  48. }
  49. /**
  50. * Aborted flag for each instances.
  51. */
  52. const abortedFlags = new WeakMap();
  53. // Properties should be enumerable.
  54. Object.defineProperties(AbortSignal.prototype, {
  55. aborted: { enumerable: true },
  56. });
  57. // `toString()` should return `"[object AbortSignal]"`
  58. if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
  59. Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {
  60. configurable: true,
  61. value: "AbortSignal",
  62. });
  63. }
  64. /**
  65. * The AbortController.
  66. * @see https://dom.spec.whatwg.org/#abortcontroller
  67. */
  68. class AbortController {
  69. /**
  70. * Initialize this controller.
  71. */
  72. constructor() {
  73. signals.set(this, createAbortSignal());
  74. }
  75. /**
  76. * Returns the `AbortSignal` object associated with this object.
  77. */
  78. get signal() {
  79. return getSignal(this);
  80. }
  81. /**
  82. * Abort and signal to any observers that the associated activity is to be aborted.
  83. */
  84. abort() {
  85. abortSignal(getSignal(this));
  86. }
  87. }
  88. /**
  89. * Associated signals.
  90. */
  91. const signals = new WeakMap();
  92. /**
  93. * Get the associated signal of a given controller.
  94. */
  95. function getSignal(controller) {
  96. const signal = signals.get(controller);
  97. if (signal == null) {
  98. throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`);
  99. }
  100. return signal;
  101. }
  102. // Properties should be enumerable.
  103. Object.defineProperties(AbortController.prototype, {
  104. signal: { enumerable: true },
  105. abort: { enumerable: true },
  106. });
  107. if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
  108. Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {
  109. configurable: true,
  110. value: "AbortController",
  111. });
  112. }
  113. export default AbortController;
  114. export { AbortController, AbortSignal };
  115. //# sourceMappingURL=abort-controller.mjs.map