@azure/abort-controller 1.0.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,253 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var tslib_1 = require('tslib');
6
+
7
+ var listenersMap = new WeakMap();
8
+ var abortedMap = new WeakMap();
9
+ /**
10
+ * An aborter instance implements AbortSignal interface, can abort HTTP requests.
11
+ *
12
+ * - Call AbortSignal.none to create a new AbortSignal instance that cannot be cancelled.
13
+ * Use `AbortSignal.none` when you are required to pass a cancellation token but the operation
14
+ * cannot or will not ever be cancelled.
15
+ *
16
+ * @example
17
+ * // Abort without timeout
18
+ * await doAsyncWork(AbortSignal.none);
19
+ *
20
+ * @export
21
+ * @class AbortSignal
22
+ * @implements {AbortSignalLike}
23
+ */
24
+ var AbortSignal = /** @class */ (function () {
25
+ function AbortSignal() {
26
+ listenersMap.set(this, []);
27
+ abortedMap.set(this, false);
28
+ }
29
+ Object.defineProperty(AbortSignal.prototype, "aborted", {
30
+ /**
31
+ * Status of whether aborted or not.
32
+ *
33
+ * @readonly
34
+ * @type {boolean}
35
+ * @memberof AbortSignal
36
+ */
37
+ get: function () {
38
+ if (!abortedMap.has(this)) {
39
+ throw new TypeError("Expected `this` to be an instance of AbortSignal.");
40
+ }
41
+ return abortedMap.get(this);
42
+ },
43
+ enumerable: true,
44
+ configurable: true
45
+ });
46
+ Object.defineProperty(AbortSignal, "none", {
47
+ /**
48
+ * Creates a new AbortSignal instance that will never be aborted.
49
+ *
50
+ * @readonly
51
+ * @static
52
+ * @type {AbortSignal}
53
+ * @memberof AbortSignal
54
+ */
55
+ get: function () {
56
+ return new AbortSignal();
57
+ },
58
+ enumerable: true,
59
+ configurable: true
60
+ });
61
+ /**
62
+ * Added new "abort" event listener, only support "abort" event.
63
+ *
64
+ * @param {"abort"} _type Only support "abort" event
65
+ * @param {(this: AbortSignalLike, ev: any) => any} listener
66
+ * @memberof AbortSignal
67
+ */
68
+ AbortSignal.prototype.addEventListener = function (
69
+ // tslint:disable-next-line:variable-name
70
+ _type, listener) {
71
+ if (!listenersMap.has(this)) {
72
+ throw new TypeError("Expected `this` to be an instance of AbortSignal.");
73
+ }
74
+ var listeners = listenersMap.get(this);
75
+ listeners.push(listener);
76
+ };
77
+ /**
78
+ * Remove "abort" event listener, only support "abort" event.
79
+ *
80
+ * @param {"abort"} _type Only support "abort" event
81
+ * @param {(this: AbortSignalLike, ev: any) => any} listener
82
+ * @memberof AbortSignal
83
+ */
84
+ AbortSignal.prototype.removeEventListener = function (
85
+ // tslint:disable-next-line:variable-name
86
+ _type, listener) {
87
+ if (!listenersMap.has(this)) {
88
+ throw new TypeError("Expected `this` to be an instance of AbortSignal.");
89
+ }
90
+ var listeners = listenersMap.get(this);
91
+ var index = listeners.indexOf(listener);
92
+ if (index > -1) {
93
+ listeners.splice(index, 1);
94
+ }
95
+ };
96
+ return AbortSignal;
97
+ }());
98
+ /**
99
+ * Helper to trigger an abort event immediately, the onabort and all abort event listeners will be triggered.
100
+ * Will try to trigger abort event for all linked AbortSignal nodes.
101
+ *
102
+ * - If there is a timeout, the timer will be cancelled.
103
+ * - If aborted is true, nothing will happen.
104
+ *
105
+ * @returns
106
+ * @internal
107
+ */
108
+ function abortSignal(signal) {
109
+ if (signal.aborted) {
110
+ return;
111
+ }
112
+ if (signal.onabort) {
113
+ signal.onabort.call(signal);
114
+ }
115
+ var listeners = listenersMap.get(signal);
116
+ listeners.forEach(function (listener) {
117
+ listener.call(signal);
118
+ });
119
+ abortedMap.set(signal, true);
120
+ }
121
+
122
+ /**
123
+ * This error is thrown when an asynchronous operation has been aborted.
124
+ * Check for this error by testing the `name` that the name property of the
125
+ * error matches `"AbortError"`.
126
+ *
127
+ * @example
128
+ * const controller = new AbortController();
129
+ * controller.abort();
130
+ * try {
131
+ * doAsyncWork(controller.signal)
132
+ * } catch (e) {
133
+ * if (e.name === 'AbortError') {
134
+ * // handle abort error here.
135
+ * }
136
+ * }
137
+ */
138
+ var AbortError = /** @class */ (function (_super) {
139
+ tslib_1.__extends(AbortError, _super);
140
+ function AbortError(message) {
141
+ var _this = _super.call(this, message) || this;
142
+ _this.name = "AbortError";
143
+ return _this;
144
+ }
145
+ return AbortError;
146
+ }(Error));
147
+ /**
148
+ * An AbortController provides an AbortSignal and the associated controls to signal
149
+ * that an asynchronous operation should be aborted.
150
+ *
151
+ * @example
152
+ * // Abort an operation when another event fires
153
+ * const controller = new AbortController();
154
+ * const signal = controller.signal;
155
+ * doAsyncWork(signal);
156
+ * button.addEventListener('click', () => controller.abort());
157
+ *
158
+ * @example
159
+ * // Share aborter cross multiple operations in 30s
160
+ * // Upload the same data to 2 different data centers at the same time,
161
+ * // abort another when any of them is finished
162
+ * const controller = AbortController.withTimeout(30 * 1000);
163
+ * doAsyncWork(controller.signal).then(controller.abort);
164
+ * doAsyncWork(controller.signal).then(controller.abort);
165
+ *
166
+ * @example
167
+ * // Cascaded aborting
168
+ * // All operations can't take more than 30 seconds
169
+ * const aborter = Aborter.timeout(30 * 1000);
170
+ *
171
+ * // Following 2 operations can't take more than 25 seconds
172
+ * await doAsyncWork(aborter.withTimeout(25 * 1000));
173
+ * await doAsyncWork(aborter.withTimeout(25 * 1000));
174
+ *
175
+ * @export
176
+ * @class AbortController
177
+ * @implements {AbortSignalLike}
178
+ */
179
+ var AbortController = /** @class */ (function () {
180
+ function AbortController(parentSignals) {
181
+ var _this = this;
182
+ this._signal = new AbortSignal();
183
+ if (!parentSignals) {
184
+ return;
185
+ }
186
+ // coerce parentSignals into an array
187
+ if (!Array.isArray(parentSignals)) {
188
+ parentSignals = arguments;
189
+ }
190
+ for (var _i = 0, parentSignals_1 = parentSignals; _i < parentSignals_1.length; _i++) {
191
+ var parentSignal = parentSignals_1[_i];
192
+ // if the parent signal has already had abort() called,
193
+ // then call abort on this signal as well.
194
+ if (parentSignal.aborted) {
195
+ this.abort();
196
+ }
197
+ else {
198
+ // when the parent signal aborts, this signal should as well.
199
+ parentSignal.addEventListener("abort", function () {
200
+ _this.abort();
201
+ });
202
+ }
203
+ }
204
+ }
205
+ Object.defineProperty(AbortController.prototype, "signal", {
206
+ /**
207
+ * The AbortSignal associated with this controller that will signal aborted
208
+ * when the abort method is called on this controller.
209
+ *
210
+ * @readonly
211
+ * @type {AbortSignal}
212
+ * @memberof AbortController
213
+ */
214
+ get: function () {
215
+ return this._signal;
216
+ },
217
+ enumerable: true,
218
+ configurable: true
219
+ });
220
+ /**
221
+ * Signal that any operations passed this controller's associated abort signal
222
+ * to cancel any remaining work and throw an `AbortError`.
223
+ *
224
+ * @memberof AbortController
225
+ */
226
+ AbortController.prototype.abort = function () {
227
+ abortSignal(this._signal);
228
+ };
229
+ /**
230
+ * Creates a new AbortSignal instance that will abort after the provided ms.
231
+ *
232
+ * @static
233
+ * @params {number} ms Elapsed time in milliseconds to trigger an abort.
234
+ * @returns {AbortSignal}
235
+ */
236
+ AbortController.timeout = function (ms) {
237
+ var signal = new AbortSignal();
238
+ var timer = setTimeout(abortSignal, ms, signal);
239
+ // Prevent the active Timer from keeping the Node.js event loop active.
240
+ if (typeof timer.unref === "function") {
241
+ timer.unref();
242
+ }
243
+ return signal;
244
+ };
245
+ return AbortController;
246
+ }());
247
+
248
+ /// <reference lib="es5" />
249
+
250
+ exports.AbortController = AbortController;
251
+ exports.AbortError = AbortError;
252
+ exports.AbortSignal = AbortSignal;
253
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/AbortSignal.ts","../src/AbortController.ts","../src/aborter.ts"],"sourcesContent":["/// <reference path=\"./shims-public.d.ts\" />\ntype AbortEventListener = (this: AbortSignalLike, ev?: any) => any;\n\nconst listenersMap = new WeakMap<AbortSignal, AbortEventListener[]>();\nconst abortedMap = new WeakMap<AbortSignal, boolean>();\n\n/**\n * Allows the request to be aborted upon firing of the \"abort\" event.\n * Compatible with the browser built-in AbortSignal and common polyfills.\n */\nexport interface AbortSignalLike {\n /**\n * Indicates if the signal has already been aborted.\n */\n readonly aborted: boolean;\n /**\n * Add new \"abort\" event listener, only support \"abort\" event.\n */\n addEventListener(\n type: \"abort\",\n listener: (this: AbortSignalLike, ev: any) => any,\n options?: any\n ): void;\n /**\n * Remove \"abort\" event listener, only support \"abort\" event.\n */\n removeEventListener(\n type: \"abort\",\n listener: (this: AbortSignalLike, ev: any) => any,\n options?: any\n ): void;\n}\n\n/**\n * An aborter instance implements AbortSignal interface, can abort HTTP requests.\n *\n * - Call AbortSignal.none to create a new AbortSignal instance that cannot be cancelled.\n * Use `AbortSignal.none` when you are required to pass a cancellation token but the operation\n * cannot or will not ever be cancelled.\n *\n * @example\n * // Abort without timeout\n * await doAsyncWork(AbortSignal.none);\n *\n * @export\n * @class AbortSignal\n * @implements {AbortSignalLike}\n */\nexport class AbortSignal implements AbortSignalLike {\n constructor() {\n listenersMap.set(this, []);\n abortedMap.set(this, false);\n }\n\n /**\n * Status of whether aborted or not.\n *\n * @readonly\n * @type {boolean}\n * @memberof AbortSignal\n */\n public get aborted(): boolean {\n if (!abortedMap.has(this)) {\n throw new TypeError(\"Expected `this` to be an instance of AbortSignal.\");\n }\n\n return abortedMap.get(this)!;\n }\n\n /**\n * Creates a new AbortSignal instance that will never be aborted.\n *\n * @readonly\n * @static\n * @type {AbortSignal}\n * @memberof AbortSignal\n */\n public static get none(): AbortSignal {\n return new AbortSignal();\n }\n\n /**\n * onabort event listener.\n *\n * @memberof AbortSignal\n */\n public onabort?: (ev?: Event) => any;\n\n /**\n * Added new \"abort\" event listener, only support \"abort\" event.\n *\n * @param {\"abort\"} _type Only support \"abort\" event\n * @param {(this: AbortSignalLike, ev: any) => any} listener\n * @memberof AbortSignal\n */\n public addEventListener(\n // tslint:disable-next-line:variable-name\n _type: \"abort\",\n listener: (this: AbortSignalLike, ev: any) => any\n ): void {\n if (!listenersMap.has(this)) {\n throw new TypeError(\"Expected `this` to be an instance of AbortSignal.\");\n }\n\n const listeners = listenersMap.get(this)!;\n listeners.push(listener);\n }\n\n /**\n * Remove \"abort\" event listener, only support \"abort\" event.\n *\n * @param {\"abort\"} _type Only support \"abort\" event\n * @param {(this: AbortSignalLike, ev: any) => any} listener\n * @memberof AbortSignal\n */\n public removeEventListener(\n // tslint:disable-next-line:variable-name\n _type: \"abort\",\n listener: (this: AbortSignalLike, ev: any) => any\n ): void {\n if (!listenersMap.has(this)) {\n throw new TypeError(\"Expected `this` to be an instance of AbortSignal.\");\n }\n\n const listeners = listenersMap.get(this)!;\n\n const index = listeners.indexOf(listener);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n }\n}\n\n/**\n * Helper to trigger an abort event immediately, the onabort and all abort event listeners will be triggered.\n * Will try to trigger abort event for all linked AbortSignal nodes.\n *\n * - If there is a timeout, the timer will be cancelled.\n * - If aborted is true, nothing will happen.\n *\n * @returns\n * @internal\n */\nexport function abortSignal(signal: AbortSignal) {\n if (signal.aborted) {\n return;\n }\n\n if (signal.onabort) {\n signal.onabort.call(signal);\n }\n\n const listeners = listenersMap.get(signal)!;\n listeners.forEach((listener) => {\n listener.call(signal);\n });\n\n abortedMap.set(signal, true);\n}\n","import { AbortSignal, abortSignal, AbortSignalLike } from \"./AbortSignal\";\n\n/**\n * This error is thrown when an asynchronous operation has been aborted.\n * Check for this error by testing the `name` that the name property of the\n * error matches `\"AbortError\"`.\n *\n * @example\n * const controller = new AbortController();\n * controller.abort();\n * try {\n * doAsyncWork(controller.signal)\n * } catch (e) {\n * if (e.name === 'AbortError') {\n * // handle abort error here.\n * }\n * }\n */\nexport class AbortError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"AbortError\";\n }\n}\n\n/**\n * An AbortController provides an AbortSignal and the associated controls to signal\n * that an asynchronous operation should be aborted.\n *\n * @example\n * // Abort an operation when another event fires\n * const controller = new AbortController();\n * const signal = controller.signal;\n * doAsyncWork(signal);\n * button.addEventListener('click', () => controller.abort());\n *\n * @example\n * // Share aborter cross multiple operations in 30s\n * // Upload the same data to 2 different data centers at the same time,\n * // abort another when any of them is finished\n * const controller = AbortController.withTimeout(30 * 1000);\n * doAsyncWork(controller.signal).then(controller.abort);\n * doAsyncWork(controller.signal).then(controller.abort);\n *\n * @example\n * // Cascaded aborting\n * // All operations can't take more than 30 seconds\n * const aborter = Aborter.timeout(30 * 1000);\n *\n * // Following 2 operations can't take more than 25 seconds\n * await doAsyncWork(aborter.withTimeout(25 * 1000));\n * await doAsyncWork(aborter.withTimeout(25 * 1000));\n *\n * @export\n * @class AbortController\n * @implements {AbortSignalLike}\n */\nexport class AbortController {\n private _signal: AbortSignal;\n\n /**\n * @param {AbortSignalLike[]} [parentSignals] The AbortSignals that will signal aborted on the AbortSignal associated with this controller.\n * @constructor\n */\n constructor(parentSignals?: AbortSignalLike[]);\n /**\n * @param {...AbortSignalLike} parentSignals The AbortSignals that will signal aborted on the AbortSignal associated with this controller.\n * @constructor\n */\n constructor(...parentSignals: AbortSignalLike[]);\n constructor(parentSignals?: any) {\n this._signal = new AbortSignal();\n\n if (!parentSignals) {\n return;\n }\n // coerce parentSignals into an array\n if (!Array.isArray(parentSignals)) {\n parentSignals = arguments;\n }\n for (const parentSignal of parentSignals) {\n // if the parent signal has already had abort() called,\n // then call abort on this signal as well.\n if (parentSignal.aborted) {\n this.abort();\n } else {\n // when the parent signal aborts, this signal should as well.\n parentSignal.addEventListener(\"abort\", () => {\n this.abort();\n });\n }\n }\n }\n\n /**\n * The AbortSignal associated with this controller that will signal aborted\n * when the abort method is called on this controller.\n *\n * @readonly\n * @type {AbortSignal}\n * @memberof AbortController\n */\n public get signal() {\n return this._signal;\n }\n\n /**\n * Signal that any operations passed this controller's associated abort signal\n * to cancel any remaining work and throw an `AbortError`.\n *\n * @memberof AbortController\n */\n abort() {\n abortSignal(this._signal);\n }\n\n /**\n * Creates a new AbortSignal instance that will abort after the provided ms.\n *\n * @static\n * @params {number} ms Elapsed time in milliseconds to trigger an abort.\n * @returns {AbortSignal}\n */\n public static timeout(ms: number): AbortSignal {\n const signal = new AbortSignal();\n const timer = setTimeout(abortSignal, ms, signal);\n // Prevent the active Timer from keeping the Node.js event loop active.\n if (typeof timer.unref === \"function\") {\n timer.unref();\n }\n return signal;\n }\n}\n","/// <reference lib=\"es5\" />\n\n// Changes to Aborter\n// * Rename Aborter to AbortSignal\n// * Remove withValue and getValue - async context should be solved differently/wholistically, not tied to cancellation\n// * Remove withTimeout, it's moved to the controller\n// * AbortSignal constructor no longer takes a parent. Cancellation graphs are created from the controller.\n\n// Potential changes to align with DOM Spec\n// * dispatchEvent on Signal\n\nexport { AbortController, AbortError } from \"./AbortController\";\nexport { AbortSignal, AbortSignalLike } from \"./AbortSignal\";\n"],"names":["tslib_1.__extends"],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ import * as tslib_1 from "tslib";
2
+ import { AbortSignal, abortSignal } from "./AbortSignal";
3
+ /**
4
+ * This error is thrown when an asynchronous operation has been aborted.
5
+ * Check for this error by testing the `name` that the name property of the
6
+ * error matches `"AbortError"`.
7
+ *
8
+ * @example
9
+ * const controller = new AbortController();
10
+ * controller.abort();
11
+ * try {
12
+ * doAsyncWork(controller.signal)
13
+ * } catch (e) {
14
+ * if (e.name === 'AbortError') {
15
+ * // handle abort error here.
16
+ * }
17
+ * }
18
+ */
19
+ var AbortError = /** @class */ (function (_super) {
20
+ tslib_1.__extends(AbortError, _super);
21
+ function AbortError(message) {
22
+ var _this = _super.call(this, message) || this;
23
+ _this.name = "AbortError";
24
+ return _this;
25
+ }
26
+ return AbortError;
27
+ }(Error));
28
+ export { AbortError };
29
+ /**
30
+ * An AbortController provides an AbortSignal and the associated controls to signal
31
+ * that an asynchronous operation should be aborted.
32
+ *
33
+ * @example
34
+ * // Abort an operation when another event fires
35
+ * const controller = new AbortController();
36
+ * const signal = controller.signal;
37
+ * doAsyncWork(signal);
38
+ * button.addEventListener('click', () => controller.abort());
39
+ *
40
+ * @example
41
+ * // Share aborter cross multiple operations in 30s
42
+ * // Upload the same data to 2 different data centers at the same time,
43
+ * // abort another when any of them is finished
44
+ * const controller = AbortController.withTimeout(30 * 1000);
45
+ * doAsyncWork(controller.signal).then(controller.abort);
46
+ * doAsyncWork(controller.signal).then(controller.abort);
47
+ *
48
+ * @example
49
+ * // Cascaded aborting
50
+ * // All operations can't take more than 30 seconds
51
+ * const aborter = Aborter.timeout(30 * 1000);
52
+ *
53
+ * // Following 2 operations can't take more than 25 seconds
54
+ * await doAsyncWork(aborter.withTimeout(25 * 1000));
55
+ * await doAsyncWork(aborter.withTimeout(25 * 1000));
56
+ *
57
+ * @export
58
+ * @class AbortController
59
+ * @implements {AbortSignalLike}
60
+ */
61
+ var AbortController = /** @class */ (function () {
62
+ function AbortController(parentSignals) {
63
+ var _this = this;
64
+ this._signal = new AbortSignal();
65
+ if (!parentSignals) {
66
+ return;
67
+ }
68
+ // coerce parentSignals into an array
69
+ if (!Array.isArray(parentSignals)) {
70
+ parentSignals = arguments;
71
+ }
72
+ for (var _i = 0, parentSignals_1 = parentSignals; _i < parentSignals_1.length; _i++) {
73
+ var parentSignal = parentSignals_1[_i];
74
+ // if the parent signal has already had abort() called,
75
+ // then call abort on this signal as well.
76
+ if (parentSignal.aborted) {
77
+ this.abort();
78
+ }
79
+ else {
80
+ // when the parent signal aborts, this signal should as well.
81
+ parentSignal.addEventListener("abort", function () {
82
+ _this.abort();
83
+ });
84
+ }
85
+ }
86
+ }
87
+ Object.defineProperty(AbortController.prototype, "signal", {
88
+ /**
89
+ * The AbortSignal associated with this controller that will signal aborted
90
+ * when the abort method is called on this controller.
91
+ *
92
+ * @readonly
93
+ * @type {AbortSignal}
94
+ * @memberof AbortController
95
+ */
96
+ get: function () {
97
+ return this._signal;
98
+ },
99
+ enumerable: true,
100
+ configurable: true
101
+ });
102
+ /**
103
+ * Signal that any operations passed this controller's associated abort signal
104
+ * to cancel any remaining work and throw an `AbortError`.
105
+ *
106
+ * @memberof AbortController
107
+ */
108
+ AbortController.prototype.abort = function () {
109
+ abortSignal(this._signal);
110
+ };
111
+ /**
112
+ * Creates a new AbortSignal instance that will abort after the provided ms.
113
+ *
114
+ * @static
115
+ * @params {number} ms Elapsed time in milliseconds to trigger an abort.
116
+ * @returns {AbortSignal}
117
+ */
118
+ AbortController.timeout = function (ms) {
119
+ var signal = new AbortSignal();
120
+ var timer = setTimeout(abortSignal, ms, signal);
121
+ // Prevent the active Timer from keeping the Node.js event loop active.
122
+ if (typeof timer.unref === "function") {
123
+ timer.unref();
124
+ }
125
+ return signal;
126
+ };
127
+ return AbortController;
128
+ }());
129
+ export { AbortController };
130
+ //# sourceMappingURL=AbortController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbortController.js","sourceRoot":"","sources":["../../src/AbortController.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAmB,MAAM,eAAe,CAAC;AAE1E;;;;;;;;;;;;;;;GAeG;AACH;IAAgC,sCAAK;IACnC,oBAAY,OAAgB;QAA5B,YACE,kBAAM,OAAO,CAAC,SAEf;QADC,KAAI,CAAC,IAAI,GAAG,YAAY,CAAC;;IAC3B,CAAC;IACH,iBAAC;AAAD,CAAC,AALD,CAAgC,KAAK,GAKpC;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH;IAaE,yBAAY,aAAmB;QAA/B,iBAsBC;QArBC,IAAI,CAAC,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAEjC,IAAI,CAAC,aAAa,EAAE;YAClB,OAAO;SACR;QACD,qCAAqC;QACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;YACjC,aAAa,GAAG,SAAS,CAAC;SAC3B;QACD,KAA2B,UAAa,EAAb,+BAAa,EAAb,2BAAa,EAAb,IAAa,EAAE;YAArC,IAAM,YAAY,sBAAA;YACrB,uDAAuD;YACvD,0CAA0C;YAC1C,IAAI,YAAY,CAAC,OAAO,EAAE;gBACxB,IAAI,CAAC,KAAK,EAAE,CAAC;aACd;iBAAM;gBACL,6DAA6D;gBAC7D,YAAY,CAAC,gBAAgB,CAAC,OAAO,EAAE;oBACrC,KAAI,CAAC,KAAK,EAAE,CAAC;gBACf,CAAC,CAAC,CAAC;aACJ;SACF;IACH,CAAC;IAUD,sBAAW,mCAAM;QARjB;;;;;;;WAOG;aACH;YACE,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;;;OAAA;IAED;;;;;OAKG;IACH,+BAAK,GAAL;QACE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;;OAMG;IACW,uBAAO,GAArB,UAAsB,EAAU;QAC9B,IAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAClD,uEAAuE;QACvE,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE;YACrC,KAAK,CAAC,KAAK,EAAE,CAAC;SACf;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACH,sBAAC;AAAD,CAAC,AA3ED,IA2EC"}
@@ -0,0 +1,116 @@
1
+ var listenersMap = new WeakMap();
2
+ var abortedMap = new WeakMap();
3
+ /**
4
+ * An aborter instance implements AbortSignal interface, can abort HTTP requests.
5
+ *
6
+ * - Call AbortSignal.none to create a new AbortSignal instance that cannot be cancelled.
7
+ * Use `AbortSignal.none` when you are required to pass a cancellation token but the operation
8
+ * cannot or will not ever be cancelled.
9
+ *
10
+ * @example
11
+ * // Abort without timeout
12
+ * await doAsyncWork(AbortSignal.none);
13
+ *
14
+ * @export
15
+ * @class AbortSignal
16
+ * @implements {AbortSignalLike}
17
+ */
18
+ var AbortSignal = /** @class */ (function () {
19
+ function AbortSignal() {
20
+ listenersMap.set(this, []);
21
+ abortedMap.set(this, false);
22
+ }
23
+ Object.defineProperty(AbortSignal.prototype, "aborted", {
24
+ /**
25
+ * Status of whether aborted or not.
26
+ *
27
+ * @readonly
28
+ * @type {boolean}
29
+ * @memberof AbortSignal
30
+ */
31
+ get: function () {
32
+ if (!abortedMap.has(this)) {
33
+ throw new TypeError("Expected `this` to be an instance of AbortSignal.");
34
+ }
35
+ return abortedMap.get(this);
36
+ },
37
+ enumerable: true,
38
+ configurable: true
39
+ });
40
+ Object.defineProperty(AbortSignal, "none", {
41
+ /**
42
+ * Creates a new AbortSignal instance that will never be aborted.
43
+ *
44
+ * @readonly
45
+ * @static
46
+ * @type {AbortSignal}
47
+ * @memberof AbortSignal
48
+ */
49
+ get: function () {
50
+ return new AbortSignal();
51
+ },
52
+ enumerable: true,
53
+ configurable: true
54
+ });
55
+ /**
56
+ * Added new "abort" event listener, only support "abort" event.
57
+ *
58
+ * @param {"abort"} _type Only support "abort" event
59
+ * @param {(this: AbortSignalLike, ev: any) => any} listener
60
+ * @memberof AbortSignal
61
+ */
62
+ AbortSignal.prototype.addEventListener = function (
63
+ // tslint:disable-next-line:variable-name
64
+ _type, listener) {
65
+ if (!listenersMap.has(this)) {
66
+ throw new TypeError("Expected `this` to be an instance of AbortSignal.");
67
+ }
68
+ var listeners = listenersMap.get(this);
69
+ listeners.push(listener);
70
+ };
71
+ /**
72
+ * Remove "abort" event listener, only support "abort" event.
73
+ *
74
+ * @param {"abort"} _type Only support "abort" event
75
+ * @param {(this: AbortSignalLike, ev: any) => any} listener
76
+ * @memberof AbortSignal
77
+ */
78
+ AbortSignal.prototype.removeEventListener = function (
79
+ // tslint:disable-next-line:variable-name
80
+ _type, listener) {
81
+ if (!listenersMap.has(this)) {
82
+ throw new TypeError("Expected `this` to be an instance of AbortSignal.");
83
+ }
84
+ var listeners = listenersMap.get(this);
85
+ var index = listeners.indexOf(listener);
86
+ if (index > -1) {
87
+ listeners.splice(index, 1);
88
+ }
89
+ };
90
+ return AbortSignal;
91
+ }());
92
+ export { AbortSignal };
93
+ /**
94
+ * Helper to trigger an abort event immediately, the onabort and all abort event listeners will be triggered.
95
+ * Will try to trigger abort event for all linked AbortSignal nodes.
96
+ *
97
+ * - If there is a timeout, the timer will be cancelled.
98
+ * - If aborted is true, nothing will happen.
99
+ *
100
+ * @returns
101
+ * @internal
102
+ */
103
+ export function abortSignal(signal) {
104
+ if (signal.aborted) {
105
+ return;
106
+ }
107
+ if (signal.onabort) {
108
+ signal.onabort.call(signal);
109
+ }
110
+ var listeners = listenersMap.get(signal);
111
+ listeners.forEach(function (listener) {
112
+ listener.call(signal);
113
+ });
114
+ abortedMap.set(signal, true);
115
+ }
116
+ //# sourceMappingURL=AbortSignal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbortSignal.js","sourceRoot":"","sources":["../../src/AbortSignal.ts"],"names":[],"mappings":"AAGA,IAAM,YAAY,GAAG,IAAI,OAAO,EAAqC,CAAC;AACtE,IAAM,UAAU,GAAG,IAAI,OAAO,EAAwB,CAAC;AA6BvD;;;;;;;;;;;;;;GAcG;AACH;IACE;QACE,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3B,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IASD,sBAAW,gCAAO;QAPlB;;;;;;WAMG;aACH;YACE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBACzB,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;aAC1E;YAED,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAC/B,CAAC;;;OAAA;IAUD,sBAAkB,mBAAI;QARtB;;;;;;;WAOG;aACH;YACE,OAAO,IAAI,WAAW,EAAE,CAAC;QAC3B,CAAC;;;OAAA;IASD;;;;;;OAMG;IACI,sCAAgB,GAAvB;IACE,yCAAyC;IACzC,KAAc,EACd,QAAiD;QAEjD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC3B,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;SAC1E;QAED,IAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAC1C,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACI,yCAAmB,GAA1B;IACE,yCAAyC;IACzC,KAAc,EACd,QAAiD;QAEjD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC3B,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;SAC1E;QAED,IAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAE1C,IAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;YACd,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;SAC5B;IACH,CAAC;IACH,kBAAC;AAAD,CAAC,AAnFD,IAmFC;;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,IAAI,MAAM,CAAC,OAAO,EAAE;QAClB,OAAO;KACR;IAED,IAAI,MAAM,CAAC,OAAO,EAAE;QAClB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KAC7B;IAED,IAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;IAC5C,SAAS,CAAC,OAAO,CAAC,UAAC,QAAQ;QACzB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /// <reference lib="es5" />
2
+ // Changes to Aborter
3
+ // * Rename Aborter to AbortSignal
4
+ // * Remove withValue and getValue - async context should be solved differently/wholistically, not tied to cancellation
5
+ // * Remove withTimeout, it's moved to the controller
6
+ // * AbortSignal constructor no longer takes a parent. Cancellation graphs are created from the controller.
7
+ // Potential changes to align with DOM Spec
8
+ // * dispatchEvent on Signal
9
+ export { AbortController, AbortError } from "./AbortController";
10
+ export { AbortSignal } from "./AbortSignal";
11
+ //# sourceMappingURL=aborter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aborter.js","sourceRoot":"","sources":["../../src/aborter.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,qBAAqB;AACrB,kCAAkC;AAClC,uHAAuH;AACvH,qDAAqD;AACrD,2GAA2G;AAE3G,2CAA2C;AAC3C,4BAA4B;AAE5B,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAmB,MAAM,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "@azure/abort-controller",
3
+ "sdk-type": "client",
4
+ "version": "1.0.0-preview.1",
5
+ "description": "Microsoft Azure SDK for JavaScript - Aborter",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist-esm/src/aborter.js",
8
+ "browser": {
9
+ "./dist/index.js": "./browser/index.js"
10
+ },
11
+ "scripts": {
12
+ "audit": "node ../../../common/scripts/rush-audit.js && rimraf node_modules package-lock.json && npm i --package-lock-only 2>&1 && npm audit",
13
+ "build:es6": "tsc -p tsconfig.json",
14
+ "build:nodebrowser": "rollup -c 2>&1",
15
+ "build:test": "rollup -c rollup.test.config.js 2>&1",
16
+ "build": "npm run build:es6 && npm run build:nodebrowser",
17
+ "check-format": "prettier --list-different --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
18
+ "clean": "rimraf dist dist-esm dist-test types temp browser/*.js* browser/*.zip statistics.html coverage coverage-browser .nyc_output *.tgz *.log test*.xml TEST*.xml",
19
+ "extract-api": "tsc -p . && api-extractor run --local",
20
+ "format": "prettier --write --config ../../.prettierrc.json \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
21
+ "integration-test:browser": "echo skipped",
22
+ "integration-test:node": "echo skipped",
23
+ "integration-test": "npm run integration-test:node && npm run integration-test:browser",
24
+ "lint:fix": "echo skipped",
25
+ "lint": "echo skipped",
26
+ "pack": "npm pack 2>&1",
27
+ "prebuild": "npm run clean",
28
+ "pretest": "npm run build:test",
29
+ "test:browser": "npm run build:test && npm run unit-test:browser && npm run integration-test:browser",
30
+ "test:node": "npm run build:test && npm run unit-test:node && npm run integration-test:node",
31
+ "test": "npm run build:test && npm run unit-test && npm run integration-test",
32
+ "unit-test:browser": "karma start --single-run",
33
+ "unit-test:node": "cross-env TS_NODE_FILES=true TS_NODE_COMPILER_OPTIONS=\"{\\\"module\\\": \\\"commonjs\\\"}\" mocha --require ts-node/register --require source-map-support/register --reporter mocha-multi-reporters --reporter-options configFile=mocha.reporter.config.json --full-trace --no-timeouts test/*.spec.ts",
34
+ "unit-test": "npm run unit-test:node && npm run unit-test:browser"
35
+ },
36
+ "types": "./types/src/aborter.d.ts",
37
+ "engine": {
38
+ "node": ">=6.0.0"
39
+ },
40
+ "files": [
41
+ "browser/*.js*",
42
+ "dist/",
43
+ "dist-esm/src/",
44
+ "src/",
45
+ "types/src",
46
+ "tsconfig.json"
47
+ ],
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/Azure/azure-sdk-for-js.git"
51
+ },
52
+ "keywords": [
53
+ "Azure",
54
+ "Aborter",
55
+ "AbortSignal",
56
+ "Cancellation",
57
+ "Node.js",
58
+ "TypeScript",
59
+ "JavaScript",
60
+ "Browser"
61
+ ],
62
+ "author": "Microsoft Corporation",
63
+ "license": "MIT",
64
+ "bugs": {
65
+ "url": "https://github.com/Azure/azure-sdk-for-js/issues"
66
+ },
67
+ "homepage": "https://github.com/Azure/azure-sdk-for-js#readme",
68
+ "sideEffects": false,
69
+ "dependencies": {
70
+ "tslib": "^1.9.3"
71
+ },
72
+ "devDependencies": {
73
+ "@microsoft/api-extractor": "^7.1.5",
74
+ "@types/mocha": "^5.2.5",
75
+ "@types/node": "^8.0.0",
76
+ "assert": "^1.4.1",
77
+ "cross-env": "^5.2.0",
78
+ "delay": "^4.2.0",
79
+ "karma": "^4.0.1",
80
+ "karma-chrome-launcher": "^2.2.0",
81
+ "karma-coverage": "^1.1.2",
82
+ "karma-edge-launcher": "^0.4.2",
83
+ "karma-env-preprocessor": "^0.1.1",
84
+ "karma-firefox-launcher": "^1.1.0",
85
+ "karma-ie-launcher": "^1.0.0",
86
+ "karma-junit-reporter": "^1.2.0",
87
+ "karma-mocha": "^1.3.0",
88
+ "karma-mocha-reporter": "^2.2.5",
89
+ "karma-remap-coverage": "^0.1.5",
90
+ "mocha": "^5.2.0",
91
+ "mocha-junit-reporter": "^1.18.0",
92
+ "mocha-multi-reporters": "^1.1.7",
93
+ "nyc": "^14.0.0",
94
+ "prettier": "^1.16.4",
95
+ "rimraf": "^2.6.2",
96
+ "rollup": "~1.13.1",
97
+ "rollup-plugin-commonjs": "^10.0.0",
98
+ "rollup-plugin-multi-entry": "^2.1.0",
99
+ "rollup-plugin-node-resolve": "^5.0.2",
100
+ "rollup-plugin-replace": "^2.1.0",
101
+ "rollup-plugin-sourcemaps": "^0.4.2",
102
+ "rollup-plugin-uglify": "^6.0.0",
103
+ "typescript": "^3.2.2"
104
+ }
105
+ }