@percy/core 1.0.0-beta.69 → 1.0.0-beta.72

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/percy.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = exports.Percy = void 0;
7
7
 
8
8
  var _client = _interopRequireDefault(require("@percy/client"));
9
9
 
@@ -21,13 +21,15 @@ var _server = _interopRequireDefault(require("./server"));
21
21
 
22
22
  var _snapshot = require("./snapshot");
23
23
 
24
+ var _utils2 = require("./utils");
25
+
24
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
27
 
26
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
28
+ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
27
29
 
28
- function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
30
+ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
29
31
 
30
- function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
32
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
31
33
 
32
34
  function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
33
35
 
@@ -39,8 +41,6 @@ var _uploads = /*#__PURE__*/new WeakMap();
39
41
 
40
42
  var _snapshots = /*#__PURE__*/new WeakMap();
41
43
 
42
- var _total = /*#__PURE__*/new WeakMap();
43
-
44
44
  // A Percy instance will create a new build when started, handle snapshot
45
45
  // creation, asset discovery, and resource uploads, and will finalize the build
46
46
  // when stopped. Snapshots are processed concurrently and the build is not
@@ -73,40 +73,198 @@ class Percy {
73
73
  port = 5338,
74
74
  // options such as `snapshot` and `discovery` that are valid Percy config
75
75
  // options which will become accessible via the `.config` property
76
- ...options
76
+ ..._options
77
77
  } = {}) {
78
78
  _defineProperty(this, "log", (0, _logger.default)('core'));
79
79
 
80
80
  _defineProperty(this, "readyState", null);
81
81
 
82
- _uploads.set(this, {
82
+ _classPrivateFieldInitSpec(this, _uploads, {
83
83
  writable: true,
84
84
  value: new _queue.default()
85
85
  });
86
86
 
87
- _snapshots.set(this, {
87
+ _classPrivateFieldInitSpec(this, _snapshots, {
88
88
  writable: true,
89
89
  value: new _queue.default()
90
90
  });
91
91
 
92
- _total.set(this, {
93
- writable: true,
94
- value: 0
95
- });
92
+ _defineProperty(this, "idle", () => (0, _utils2.generatePromise)(async function* () {
93
+ yield* _classPrivateFieldGet(this, _snapshots).idle();
94
+ yield* _classPrivateFieldGet(this, _uploads).idle();
95
+ }.bind(this)));
96
+
97
+ _defineProperty(this, "start", options => (0, _utils2.generatePromise)(async function* () {
98
+ // already starting or started
99
+ if (this.readyState != null) return;
100
+ this.readyState = 0; // create a percy build as the first immediately queued task
101
+
102
+ let buildTask = _classPrivateFieldGet(this, _uploads).push('build/create', () => {
103
+ // pause other queued tasks until after the build is created
104
+ _classPrivateFieldGet(this, _uploads).stop();
105
+
106
+ return this.client.createBuild().then(({
107
+ data: {
108
+ id,
109
+ attributes
110
+ }
111
+ }) => {
112
+ this.build = {
113
+ id
114
+ };
115
+ this.build.number = attributes['build-number'];
116
+ this.build.url = attributes['web-url'];
117
+
118
+ _classPrivateFieldGet(this, _uploads).run();
119
+ });
120
+ }, 0); // handle deferred build errors
121
+
122
+
123
+ if (this.deferUploads) {
124
+ buildTask.catch(err => {
125
+ this.log.error('Failed to create build');
126
+ this.log.error(err);
127
+ this.close();
128
+ });
129
+ }
130
+
131
+ try {
132
+ var _this$server;
133
+
134
+ // when not deferred, wait until the build is created first
135
+ if (!this.deferUploads) await buildTask; // maybe launch the discovery browser
136
+
137
+ if (!this.dryRun && (options === null || options === void 0 ? void 0 : options.browser) !== false) {
138
+ yield this.browser.launch();
139
+ } // start the server after everything else is ready
140
+
141
+
142
+ yield (_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.listen(this.port); // mark instance as started
143
+
144
+ this.log.info('Percy has started!');
145
+ this.readyState = 1;
146
+ } catch (error) {
147
+ var _this$server2;
148
+
149
+ // on error, close any running server and browser
150
+ await ((_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close());
151
+ await this.browser.close(); // mark instance as closed
152
+
153
+ this.readyState = 3; // when uploads are deferred, cancel build creation
154
+
155
+ if (error.canceled && this.deferUploads) {
156
+ _classPrivateFieldGet(this, _uploads).cancel('build/create');
157
+
158
+ this.readyState = null;
159
+ } // throw an easier-to-understand error when the port is taken
160
+
161
+
162
+ if (error.code === 'EADDRINUSE') {
163
+ throw new Error('Percy is already running or the port is in use');
164
+ } else {
165
+ throw error;
166
+ }
167
+ }
168
+ }.bind(this)));
169
+
170
+ _defineProperty(this, "flush", close => (0, _utils2.generatePromise)(async function* () {
171
+ // close the snapshot queue and wait for it to empty
172
+ if (_classPrivateFieldGet(this, _snapshots).size) {
173
+ if (close) _classPrivateFieldGet(this, _snapshots).close();
174
+ yield* _classPrivateFieldGet(this, _snapshots).flush(s => {
175
+ // do not log a count when not closing or while dry-running
176
+ if (!close || this.dryRun) return;
177
+ this.log.progress(`Processing ${s} snapshot${s !== 1 ? 's' : ''}...`, !!s);
178
+ });
179
+ } // run, close, and wait for the upload queue to empty
180
+
181
+
182
+ if (!this.skipUploads && _classPrivateFieldGet(this, _uploads).size) {
183
+ if (close) _classPrivateFieldGet(this, _uploads).close();
184
+ yield* _classPrivateFieldGet(this, _uploads).flush(s => {
185
+ // do not log a count when not closing or while creating a build
186
+ if (!close || _classPrivateFieldGet(this, _uploads).has('build/create')) return;
187
+ this.log.progress(`Uploading ${s} snapshot${s !== 1 ? 's' : ''}...`, !!s);
188
+ });
189
+ }
190
+ }.bind(this)).canceled(() => {
191
+ // reopen closed queues when canceled
192
+ _classPrivateFieldGet(this, _snapshots).open();
193
+
194
+ _classPrivateFieldGet(this, _uploads).open();
195
+ }));
196
+
197
+ _defineProperty(this, "stop", force => (0, _utils2.generatePromise)(async function* () {
198
+ var _this$server3, _this$build;
199
+
200
+ // not started, but the browser was launched
201
+ if (!this.readyState && this.browser.isConnected()) {
202
+ await this.browser.close();
203
+ } // not started or already stopped
204
+
205
+
206
+ if (!this.readyState || this.readyState > 2) return; // close queues asap
207
+
208
+ if (force) this.close(); // already stopping
209
+
210
+ if (this.readyState === 2) return;
211
+ this.readyState = 2; // log when force stopping
212
+
213
+ if (force) this.log.info('Stopping percy...'); // process uploads and close queues
214
+
215
+ yield* this.flush(true); // if dry-running, log the total number of snapshots
216
+
217
+ if (this.dryRun && _classPrivateFieldGet(this, _uploads).size) {
218
+ let total = _classPrivateFieldGet(this, _uploads).size - 1; // subtract the build task
219
+
220
+ this.log.info(`Found ${total} snapshot${total !== 1 ? 's' : ''}`);
221
+ } // close any running server and browser
222
+
223
+
224
+ await ((_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close());
225
+ await this.browser.close(); // finalize and log build info
226
+
227
+ let meta = {
228
+ build: this.build
229
+ };
230
+
231
+ if ((_this$build = this.build) !== null && _this$build !== void 0 && _this$build.failed) {
232
+ // do not finalize failed builds
233
+ this.log.warn(`Build #${this.build.number} failed: ${this.build.url}`, meta);
234
+ } else if (this.build) {
235
+ // finalize the build
236
+ await this.client.finalizeBuild(this.build.id);
237
+ this.log.info(`Finalized build #${this.build.number}: ${this.build.url}`, meta);
238
+ } else {
239
+ // no build was ever created (likely failed while deferred)
240
+ this.log.warn('Build not created', meta);
241
+ } // mark instance as stopped
242
+
243
+
244
+ this.readyState = 3;
245
+ }.bind(this)).canceled(() => {
246
+ // reset ready state when canceled
247
+ this.readyState = 1;
248
+ }));
96
249
 
97
250
  if (loglevel) this.loglevel(loglevel);
98
251
  this.dryRun = !!dryRun;
99
252
  this.skipUploads = this.dryRun || !!skipUploads;
100
253
  this.deferUploads = this.skipUploads || !!deferUploads;
254
+ if (this.deferUploads) _classPrivateFieldGet(this, _uploads).stop();
101
255
  this.config = _config.default.load({
102
- overrides: options,
256
+ overrides: _options,
103
257
  path: config
104
258
  });
105
- let {
106
- concurrency
107
- } = this.config.discovery;
108
- if (concurrency) _classPrivateFieldGet(this, _snapshots).concurrency = concurrency;
109
- if (this.deferUploads) _classPrivateFieldGet(this, _uploads).stop();
259
+
260
+ if (this.config.discovery.concurrency) {
261
+ let {
262
+ concurrency
263
+ } = this.config.discovery;
264
+ _classPrivateFieldGet(this, _uploads).concurrency = concurrency;
265
+ _classPrivateFieldGet(this, _snapshots).concurrency = concurrency;
266
+ }
267
+
110
268
  this.client = new _client.default({
111
269
  token,
112
270
  clientInfo,
@@ -158,23 +316,21 @@ class Percy {
158
316
  this.config = (0, _utils.merge)([this.config, config], (path, prev, next) => {
159
317
  // replace arrays instead of merging
160
318
  return Array.isArray(next) && [path, next];
161
- });
319
+ }); // adjust concurrency if necessary
320
+
321
+ if (this.config.discovery.concurrency) {
322
+ let {
323
+ concurrency
324
+ } = this.config.discovery;
325
+ _classPrivateFieldGet(this, _uploads).concurrency = concurrency;
326
+ _classPrivateFieldGet(this, _snapshots).concurrency = concurrency;
327
+ }
328
+
162
329
  return this.config;
163
330
  } // Resolves once snapshot and upload queues are idle
164
331
 
165
332
 
166
- async idle() {
167
- await _classPrivateFieldGet(this, _snapshots).idle();
168
- await _classPrivateFieldGet(this, _uploads).idle();
169
- } // Waits for snapshot idle and flushes the upload queue
170
-
171
-
172
- async dispatch() {
173
- await _classPrivateFieldGet(this, _snapshots).idle();
174
- if (!this.skipUploads) await _classPrivateFieldGet(this, _uploads).flush();
175
- } // Immediately stops all queues, preventing any more tasks from running
176
-
177
-
333
+ // Immediately stops all queues, preventing any more tasks from running
178
334
  close() {
179
335
  _classPrivateFieldGet(this, _snapshots).close(true);
180
336
 
@@ -183,122 +339,7 @@ class Percy {
183
339
  // at a later time when uploads are deferred, or run immediately when not deferred.
184
340
 
185
341
 
186
- async start() {
187
- // already starting or started
188
- if (this.readyState != null) return;
189
- this.readyState = 0; // create a percy build as the first immediately queued task
190
-
191
- let buildTask = _classPrivateFieldGet(this, _uploads).push('build/create', () => {
192
- // pause other queued tasks until after the build is created
193
- _classPrivateFieldGet(this, _uploads).stop();
194
-
195
- return this.client.createBuild().then(({
196
- data: {
197
- id,
198
- attributes
199
- }
200
- }) => {
201
- this.build = {
202
- id
203
- };
204
- this.build.number = attributes['build-number'];
205
- this.build.url = attributes['web-url'];
206
-
207
- _classPrivateFieldGet(this, _uploads).run();
208
- });
209
- }, 0); // handle deferred build errors
210
-
211
-
212
- if (this.deferUploads) {
213
- buildTask.catch(err => {
214
- this.log.error('Failed to create build');
215
- this.log.error(err);
216
- this.close();
217
- });
218
- }
219
-
220
- try {
221
- var _this$server;
222
-
223
- // when not deferred, wait until the build is created first
224
- if (!this.deferUploads) await buildTask; // launch the discovery browser
225
-
226
- if (!this.dryRun) await this.browser.launch(); // if there is a server, start listening
227
-
228
- await ((_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.listen(this.port)); // mark this process as running
229
-
230
- this.log.info('Percy has started!');
231
- this.readyState = 1;
232
- } catch (error) {
233
- var _this$server2;
234
-
235
- // on error, close any running server and browser
236
- await ((_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close());
237
- await this.browser.close();
238
- this.readyState = 3; // throw an easier-to-understand error when the port is taken
239
-
240
- if (error.code === 'EADDRINUSE') {
241
- throw new Error('Percy is already running or the port is in use');
242
- } else {
243
- throw error;
244
- }
245
- }
246
- } // Stops the local API server and browser once snapshots have completed and finalizes the Percy
247
- // build. Does nothing if not running. When `force` is true, any queued tasks are cleared.
248
-
249
-
250
- async stop(force) {
251
- var _this$server3, _this$build;
252
-
253
- // not started or already stopped
254
- if (!this.readyState || this.readyState > 2) return; // close queues asap
255
-
256
- if (force) this.close(); // already stopping
257
-
258
- if (this.readyState === 2) return;
259
- this.readyState = 2; // log when force stopping
260
-
261
- let meta = {
262
- build: this.build
263
- };
264
- if (force) this.log.info('Stopping percy...', meta); // close the snapshot queue and wait for it to empty
265
-
266
- if (_classPrivateFieldGet(this, _snapshots).close().size) {
267
- await _classPrivateFieldGet(this, _snapshots).empty(s => !this.dryRun && this.log.progress(`Processing ${s} snapshot${s !== 1 ? 's' : ''}...`, !!s));
268
- } // run, close, and wait for the upload queue to empty
269
-
270
-
271
- if (!this.skipUploads && _classPrivateFieldGet(this, _uploads).run().close().size) {
272
- await _classPrivateFieldGet(this, _uploads).empty(s => {
273
- this.log.progress(`Uploading ${s} snapshot${s !== 1 ? 's' : ''}...`, !!s);
274
- });
275
- } // if dry-running, print the total number of snapshots at the end
276
-
277
-
278
- if (this.dryRun && _classPrivateFieldGet(this, _total)) {
279
- this.log.info(`Found ${_classPrivateFieldGet(this, _total)} snapshot${_classPrivateFieldGet(this, _total) !== 1 ? 's' : ''}`);
280
- } // close the any running server and browser
281
-
282
-
283
- await ((_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close());
284
- await this.browser.close();
285
-
286
- if ((_this$build = this.build) !== null && _this$build !== void 0 && _this$build.failed) {
287
- // do not finalize failed builds
288
- this.log.warn(`Build #${this.build.number} failed: ${this.build.url}`, meta);
289
- } else if (this.build) {
290
- // finalize the build
291
- await this.client.finalizeBuild(this.build.id);
292
- this.log.info(`Finalized build #${this.build.number}: ${this.build.url}`, meta);
293
- } else {
294
- // no build was ever created (likely failed while deferred)
295
- this.log.warn('Build not created', meta);
296
- }
297
-
298
- this.readyState = 3;
299
- } // Deprecated capture method
300
-
301
-
342
+ // Deprecated capture method
302
343
  capture(options) {
303
344
  this.log.deprecated('The #capture() method will be ' + 'removed in 1.0.0. Use #snapshot() instead.');
304
345
  return this.snapshot(options);
@@ -319,39 +360,46 @@ class Percy {
319
360
  } // get derived snapshot config options
320
361
 
321
362
 
322
- let snapshot = (0, _snapshot.getSnapshotConfig)(this, options); // clear any existing pending upload for the same snapshot (for retries)
323
-
324
- _classPrivateFieldGet(this, _uploads).clear(`upload/${snapshot.name}`); // resolves after asset discovery has finished and the upload has been queued
325
-
326
-
327
- return _classPrivateFieldGet(this, _snapshots).push(`snapshot/${snapshot.name}`, async () => {
328
- var _snapshot$additionalS, _snapshot$additionalS2;
363
+ let snapshot = (0, _snapshot.getSnapshotConfig)(this, options); // clear any existing snapshot uploads of the same name (for retries)
329
364
 
330
- _classPrivateFieldSet(this, _total, _classPrivateFieldGet(this, _total) + (((_snapshot$additionalS = (_snapshot$additionalS2 = snapshot.additionalSnapshots) === null || _snapshot$additionalS2 === void 0 ? void 0 : _snapshot$additionalS2.length) !== null && _snapshot$additionalS !== void 0 ? _snapshot$additionalS : 0) + 1));
365
+ for (let {
366
+ name
367
+ } of [snapshot, ...(snapshot.additionalSnapshots || [])]) {
368
+ _classPrivateFieldGet(this, _uploads).cancel(`upload/${name}`);
369
+ } // resolves after asset discovery has finished and uploads have been queued
331
370
 
332
- (0, _snapshot.debugSnapshotConfig)(snapshot, this.dryRun);
333
- if (this.dryRun) return;
334
371
 
372
+ return _classPrivateFieldGet(this, _snapshots).push(`snapshot/${snapshot.name}`, async function* () {
335
373
  try {
336
- await (0, _snapshot.discoverSnapshotResources)(this, snapshot, (snapshot, resources) => {
337
- this.log.info(`Snapshot taken: ${snapshot.name}`, snapshot.meta);
374
+ yield* (0, _snapshot.discoverSnapshotResources)(this, snapshot, (snap, resources) => {
375
+ if (!this.dryRun) this.log.info(`Snapshot taken: ${snap.name}`, snap.meta);
338
376
 
339
- this._scheduleUpload(snapshot, resources);
377
+ this._scheduleUpload(snap.name, { ...snap,
378
+ resources
379
+ });
340
380
  });
341
381
  } catch (error) {
342
- this.log.error(`Encountered an error taking snapshot: ${snapshot.name}`, snapshot.meta);
343
- this.log.error(error, snapshot.meta);
344
- }
345
- });
346
- } // Queues a snapshot upload with the provided configuration options and resources
382
+ if (error.canceled) {
383
+ this.log.error('Received a duplicate snapshot name, ' + `the previous snapshot was canceled: ${snapshot.name}`);
384
+ } else {
385
+ this.log.error(`Encountered an error taking snapshot: ${snapshot.name}`, snapshot.meta);
386
+ this.log.error(error, snapshot.meta);
387
+ }
388
+ } // fixes an issue in Node 12 where implicit returns do not correctly resolve the async
389
+ // generator objects — https://crbug.com/v8/10238
347
390
 
348
391
 
349
- _scheduleUpload(snapshot, resources) {
350
- _classPrivateFieldGet(this, _uploads).push(`upload/${snapshot.name}`, async () => {
392
+ return; // eslint-disable-line no-useless-return
393
+ }.bind(this));
394
+ } // Queues a snapshot upload with the provided options
395
+
396
+
397
+ _scheduleUpload(name, options) {
398
+ return _classPrivateFieldGet(this, _uploads).push(`upload/${name}`, async () => {
351
399
  try {
352
- await this.client.sendSnapshot(this.build.id, { ...snapshot,
353
- resources
354
- });
400
+ /* istanbul ignore if: useful for other internal packages */
401
+ if (typeof options === 'function') options = await options();
402
+ await this.client.sendSnapshot(this.build.id, options);
355
403
  } catch (error) {
356
404
  var _error$response, _failed$detail;
357
405
 
@@ -360,8 +408,8 @@ class Percy {
360
408
 
361
409
  return ((_e$source = e.source) === null || _e$source === void 0 ? void 0 : _e$source.pointer) === '/data/attributes/build';
362
410
  });
363
- this.log.error(`Encountered an error uploading snapshot: ${snapshot.name}`, snapshot.meta);
364
- this.log.error((_failed$detail = failed === null || failed === void 0 ? void 0 : failed.detail) !== null && _failed$detail !== void 0 ? _failed$detail : error, snapshot.meta); // build failed at some point, stop accepting snapshots
411
+ this.log.error(`Encountered an error uploading snapshot: ${name}`, options.meta);
412
+ this.log.error((_failed$detail = failed === null || failed === void 0 ? void 0 : failed.detail) !== null && _failed$detail !== void 0 ? _failed$detail : error, options.meta); // build failed at some point, stop accepting snapshots
365
413
 
366
414
  if (failed) {
367
415
  this.build.failed = true;
@@ -373,4 +421,6 @@ class Percy {
373
421
 
374
422
  }
375
423
 
376
- exports.default = Percy;
424
+ exports.Percy = Percy;
425
+ var _default = Percy;
426
+ exports.default = _default;
package/dist/queue.js CHANGED
@@ -3,10 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = exports.Queue = void 0;
7
7
 
8
8
  var _utils = require("./utils");
9
9
 
10
+ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
11
+
12
+ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
13
+
10
14
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
15
 
12
16
  function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
@@ -25,12 +29,12 @@ class Queue {
25
29
 
26
30
  _defineProperty(this, "closed", false);
27
31
 
28
- _queued.set(this, {
32
+ _classPrivateFieldInitSpec(this, _queued, {
29
33
  writable: true,
30
34
  value: new Map()
31
35
  });
32
36
 
33
- _pending.set(this, {
37
+ _classPrivateFieldInitSpec(this, _pending, {
34
38
  writable: true,
35
39
  value: new Map()
36
40
  });
@@ -39,7 +43,11 @@ class Queue {
39
43
  }
40
44
 
41
45
  push(id, callback, priority) {
42
- if (this.closed) throw new Error('Closed');
46
+ if (this.closed && !id.startsWith('@@/')) {
47
+ throw new Error('Closed');
48
+ }
49
+
50
+ this.cancel(id);
43
51
  let task = {
44
52
  id,
45
53
  callback,
@@ -51,8 +59,6 @@ class Queue {
51
59
  reject
52
60
  });
53
61
 
54
- _classPrivateFieldGet(this, _queued).delete(id);
55
-
56
62
  _classPrivateFieldGet(this, _queued).set(id, task);
57
63
 
58
64
  this._dequeue();
@@ -60,12 +66,22 @@ class Queue {
60
66
  return task.promise;
61
67
  }
62
68
 
63
- clear(id) {
64
- if (id != null) {
65
- _classPrivateFieldGet(this, _queued).delete(id);
66
- } else {
67
- _classPrivateFieldGet(this, _queued).clear();
68
- }
69
+ cancel(id) {
70
+ var _classPrivateFieldGet2, _classPrivateFieldGet3;
71
+
72
+ (_classPrivateFieldGet2 = _classPrivateFieldGet(this, _pending).get(id)) === null || _classPrivateFieldGet2 === void 0 ? void 0 : (_classPrivateFieldGet3 = _classPrivateFieldGet2.cancel) === null || _classPrivateFieldGet3 === void 0 ? void 0 : _classPrivateFieldGet3.call(_classPrivateFieldGet2);
73
+
74
+ _classPrivateFieldGet(this, _pending).delete(id);
75
+
76
+ _classPrivateFieldGet(this, _queued).delete(id);
77
+ }
78
+
79
+ has(id) {
80
+ return _classPrivateFieldGet(this, _queued).has(id) || _classPrivateFieldGet(this, _pending).has(id);
81
+ }
82
+
83
+ clear() {
84
+ _classPrivateFieldGet(this, _queued).clear();
69
85
 
70
86
  return this.size;
71
87
  }
@@ -87,30 +103,48 @@ class Queue {
87
103
  return this;
88
104
  }
89
105
 
106
+ open() {
107
+ this.closed = false;
108
+ return this;
109
+ }
110
+
90
111
  close(abort) {
91
112
  if (abort) this.stop().clear();
92
113
  this.closed = true;
93
114
  return this;
94
115
  }
95
116
 
96
- async idle() {
97
- await (0, _utils.waitFor)(() => !_classPrivateFieldGet(this, _pending).size, {
117
+ idle(callback) {
118
+ return (0, _utils.waitFor)(() => {
119
+ callback === null || callback === void 0 ? void 0 : callback(_classPrivateFieldGet(this, _pending).size);
120
+ return !_classPrivateFieldGet(this, _pending).size;
121
+ }, {
98
122
  idle: 10
99
123
  });
100
124
  }
101
125
 
102
- async empty(onCheck) {
103
- await (0, _utils.waitFor)(() => {
104
- onCheck === null || onCheck === void 0 ? void 0 : onCheck(this.size);
126
+ empty(callback) {
127
+ return (0, _utils.waitFor)(() => {
128
+ callback === null || callback === void 0 ? void 0 : callback(this.size);
105
129
  return !this.size;
106
130
  }, {
107
131
  idle: 10
108
132
  });
109
133
  }
110
134
 
111
- async flush() {
112
- this.push('@@/flush', () => this.stop());
113
- await this.run().idle();
135
+ flush(callback) {
136
+ let stopped = !this.running;
137
+ this.run().push('@@/flush', () => {
138
+ if (stopped) this.stop();
139
+ });
140
+ return this.idle(pend => {
141
+ let left = [..._classPrivateFieldGet(this, _queued).keys()].indexOf('@@/flush');
142
+ if (!~left && !_classPrivateFieldGet(this, _pending).has('@@/flush')) left = 0;
143
+ callback === null || callback === void 0 ? void 0 : callback(pend + left);
144
+ }).canceled(() => {
145
+ if (stopped) this.stop();
146
+ this.cancel('@@/flush');
147
+ });
114
148
  }
115
149
 
116
150
  next() {
@@ -134,8 +168,12 @@ class Queue {
134
168
 
135
169
  _classPrivateFieldGet(this, _pending).set(task.id, task);
136
170
 
137
- let done = (callback, arg) => {
138
- _classPrivateFieldGet(this, _pending).delete(task.id);
171
+ let done = callback => arg => {
172
+ var _task$cancel;
173
+
174
+ if (!((_task$cancel = task.cancel) !== null && _task$cancel !== void 0 && _task$cancel.triggered)) {
175
+ _classPrivateFieldGet(this, _pending).delete(task.id);
176
+ }
139
177
 
140
178
  callback(arg);
141
179
 
@@ -143,12 +181,16 @@ class Queue {
143
181
  };
144
182
 
145
183
  try {
146
- return Promise.resolve(task.callback()).then(done.bind(null, task.resolve)).catch(done.bind(null, task.reject));
184
+ let gen = (0, _utils.generatePromise)(task.callback);
185
+ task.cancel = gen.cancel;
186
+ return gen.then(done(task.resolve), done(task.reject));
147
187
  } catch (err) {
148
- done(task.reject, err);
188
+ done(task.reject)(err);
149
189
  }
150
190
  }
151
191
 
152
192
  }
153
193
 
154
- exports.default = Queue;
194
+ exports.Queue = Queue;
195
+ var _default = Queue;
196
+ exports.default = _default;