@itwin/core-bentley 5.7.0-dev.13 → 5.7.0-dev.15

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.
@@ -12,6 +12,10 @@ export declare class ObservableSet<T> extends Set<T> {
12
12
  readonly onDeleted: BeEvent<(item: T) => void>;
13
13
  /** Emitted after this set's contents are cleared. */
14
14
  readonly onCleared: BeEvent<() => void>;
15
+ /** Emitted after multiple items are added to this set via [[addAll]]. */
16
+ readonly onBatchAdded: BeEvent<() => void>;
17
+ /** Emitted after multiple items are deleted from this set via [[deleteAll]]. */
18
+ readonly onBatchDeleted: BeEvent<() => void>;
15
19
  /** Construct a new ObservableSet.
16
20
  * @param elements Optional elements with which to populate the new set.
17
21
  */
@@ -24,5 +28,17 @@ export declare class ObservableSet<T> extends Set<T> {
24
28
  * and raises the [[onCleared]] event.
25
29
  */
26
30
  clear(): void;
31
+ /** Add multiple items to the set, raising [[onBatchAdded]] only once after all items are added.
32
+ * This is more efficient than calling [[add]] in a loop when listeners need not be notified of each individual addition.
33
+ * @param items The items to add.
34
+ * @returns The number of items that were actually added (i.e., were not already present).
35
+ */
36
+ addAll(items: Iterable<T>): number;
37
+ /** Delete multiple items from the set, raising [[onBatchDeleted]] only once after all items are deleted.
38
+ * This is more efficient than calling [[delete]] in a loop when listeners need not be notified of each individual deletion.
39
+ * @param items The items to delete.
40
+ * @returns The number of items that were actually deleted (i.e., were present in the set).
41
+ */
42
+ deleteAll(items: Iterable<T>): number;
27
43
  }
28
44
  //# sourceMappingURL=ObservableSet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableSet.d.ts","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IAC1C,iDAAiD;IACjD,SAAgB,OAAO,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC3D,qDAAqD;IACrD,SAAgB,SAAS,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC7D,qDAAqD;IACrD,SAAgB,SAAS,gBAAqB,IAAI,EAAI;IAEtD;;OAEG;gBACgB,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS;IAcrD;;OAEG;IACa,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAQxC;;OAEG;IACa,KAAK,IAAI,IAAI;CAM9B"}
1
+ {"version":3,"file":"ObservableSet.d.ts","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IAC1C,iDAAiD;IACjD,SAAgB,OAAO,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC3D,qDAAqD;IACrD,SAAgB,SAAS,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC7D,qDAAqD;IACrD,SAAgB,SAAS,gBAAqB,IAAI,EAAI;IACtD,yEAAyE;IACzE,SAAgB,YAAY,gBAAqB,IAAI,EAAI;IACzD,gFAAgF;IAChF,SAAgB,cAAc,gBAAqB,IAAI,EAAI;IAE3D;;OAEG;gBACgB,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS;IAcrD;;OAEG;IACa,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAQxC;;OAEG;IACa,KAAK,IAAI,IAAI;IAO7B;;;;OAIG;IACI,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM;IAWzC;;;;OAIG;IACI,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM;CAU7C"}
@@ -19,6 +19,10 @@ class ObservableSet extends Set {
19
19
  onDeleted = new BeEvent_1.BeEvent();
20
20
  /** Emitted after this set's contents are cleared. */
21
21
  onCleared = new BeEvent_1.BeEvent();
22
+ /** Emitted after multiple items are added to this set via [[addAll]]. */
23
+ onBatchAdded = new BeEvent_1.BeEvent();
24
+ /** Emitted after multiple items are deleted from this set via [[deleteAll]]. */
25
+ onBatchDeleted = new BeEvent_1.BeEvent();
22
26
  /** Construct a new ObservableSet.
23
27
  * @param elements Optional elements with which to populate the new set.
24
28
  */
@@ -51,6 +55,32 @@ class ObservableSet extends Set {
51
55
  this.onCleared.raiseEvent();
52
56
  }
53
57
  }
58
+ /** Add multiple items to the set, raising [[onBatchAdded]] only once after all items are added.
59
+ * This is more efficient than calling [[add]] in a loop when listeners need not be notified of each individual addition.
60
+ * @param items The items to add.
61
+ * @returns The number of items that were actually added (i.e., were not already present).
62
+ */
63
+ addAll(items) {
64
+ const prevSize = this.size;
65
+ for (const item of items)
66
+ super.add(item);
67
+ if (this.size !== prevSize)
68
+ this.onBatchAdded.raiseEvent();
69
+ return this.size - prevSize;
70
+ }
71
+ /** Delete multiple items from the set, raising [[onBatchDeleted]] only once after all items are deleted.
72
+ * This is more efficient than calling [[delete]] in a loop when listeners need not be notified of each individual deletion.
73
+ * @param items The items to delete.
74
+ * @returns The number of items that were actually deleted (i.e., were present in the set).
75
+ */
76
+ deleteAll(items) {
77
+ const prevSize = this.size;
78
+ for (const item of items)
79
+ super.delete(item);
80
+ if (this.size !== prevSize)
81
+ this.onBatchDeleted.raiseEvent();
82
+ return prevSize - this.size;
83
+ }
54
84
  }
55
85
  exports.ObservableSet = ObservableSet;
56
86
  //# sourceMappingURL=ObservableSet.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableSet.js","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,uCAAoC;AAEpC;;GAEG;AACH,MAAa,aAAiB,SAAQ,GAAM;IAC1C,iDAAiD;IACjC,OAAO,GAAG,IAAI,iBAAO,EAAqB,CAAC;IAC3D,qDAAqD;IACrC,SAAS,GAAG,IAAI,iBAAO,EAAqB,CAAC;IAC7D,qDAAqD;IACrC,SAAS,GAAG,IAAI,iBAAO,EAAc,CAAC;IAEtD;;OAEG;IACH,YAAmB,QAAkC;QACnD,4EAA4E;QAC5E,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEhB,IAAI,CAAC,GAAG,GAAG,CAAC,IAAO,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;YAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;gBACxB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAEhC,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACa,MAAM,CAAC,IAAO;QAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,GAAG;YACL,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAElC,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACa,KAAK;QACnB,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;CACF;AA7CD,sCA6CC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Collections\r\n */\r\n\r\nimport { BeEvent } from \"./BeEvent\";\r\n\r\n/** A standard [Set<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) that emits events when its contents change.\r\n * @public\r\n */\r\nexport class ObservableSet<T> extends Set<T> {\r\n /** Emitted after `item` is added to this set. */\r\n public readonly onAdded = new BeEvent<(item: T) => void>();\r\n /** Emitted after `item` is deleted from this set. */\r\n public readonly onDeleted = new BeEvent<(item: T) => void>();\r\n /** Emitted after this set's contents are cleared. */\r\n public readonly onCleared = new BeEvent<() => void>();\r\n\r\n /** Construct a new ObservableSet.\r\n * @param elements Optional elements with which to populate the new set.\r\n */\r\n public constructor(elements?: Iterable<T> | undefined) {\r\n // NB: Set constructor will invoke add(). Do not override until initialized.\r\n super(elements);\r\n\r\n this.add = (item: T) => {\r\n const prevSize = this.size;\r\n const ret = super.add(item);\r\n if (this.size !== prevSize)\r\n this.onAdded.raiseEvent(item);\r\n\r\n return ret;\r\n };\r\n }\r\n\r\n /** Invokes [Set.delete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete), raising\r\n * the [[onDeleted]] event if the item was removed from the set.\r\n */\r\n public override delete(item: T): boolean {\r\n const ret = super.delete(item);\r\n if (ret)\r\n this.onDeleted.raiseEvent(item);\r\n\r\n return ret;\r\n }\r\n\r\n /** If this set is not already empty, invokes [Set.clear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear)\r\n * and raises the [[onCleared]] event.\r\n */\r\n public override clear(): void {\r\n if (0 !== this.size) {\r\n super.clear();\r\n this.onCleared.raiseEvent();\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"ObservableSet.js","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,uCAAoC;AAEpC;;GAEG;AACH,MAAa,aAAiB,SAAQ,GAAM;IAC1C,iDAAiD;IACjC,OAAO,GAAG,IAAI,iBAAO,EAAqB,CAAC;IAC3D,qDAAqD;IACrC,SAAS,GAAG,IAAI,iBAAO,EAAqB,CAAC;IAC7D,qDAAqD;IACrC,SAAS,GAAG,IAAI,iBAAO,EAAc,CAAC;IACtD,yEAAyE;IACzD,YAAY,GAAG,IAAI,iBAAO,EAAc,CAAC;IACzD,gFAAgF;IAChE,cAAc,GAAG,IAAI,iBAAO,EAAc,CAAC;IAE3D;;OAEG;IACH,YAAmB,QAAkC;QACnD,4EAA4E;QAC5E,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEhB,IAAI,CAAC,GAAG,GAAG,CAAC,IAAO,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;YAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;gBACxB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAEhC,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACa,MAAM,CAAC,IAAO;QAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,GAAG;YACL,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAElC,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACa,KAAK;QACnB,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,KAAkB;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK;YACtB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAElB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YACxB,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;QAEjC,OAAO,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACI,SAAS,CAAC,KAAkB;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK;YACtB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAErB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YACxB,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QAEnC,OAAO,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AAjFD,sCAiFC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Collections\r\n */\r\n\r\nimport { BeEvent } from \"./BeEvent\";\r\n\r\n/** A standard [Set<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) that emits events when its contents change.\r\n * @public\r\n */\r\nexport class ObservableSet<T> extends Set<T> {\r\n /** Emitted after `item` is added to this set. */\r\n public readonly onAdded = new BeEvent<(item: T) => void>();\r\n /** Emitted after `item` is deleted from this set. */\r\n public readonly onDeleted = new BeEvent<(item: T) => void>();\r\n /** Emitted after this set's contents are cleared. */\r\n public readonly onCleared = new BeEvent<() => void>();\r\n /** Emitted after multiple items are added to this set via [[addAll]]. */\r\n public readonly onBatchAdded = new BeEvent<() => void>();\r\n /** Emitted after multiple items are deleted from this set via [[deleteAll]]. */\r\n public readonly onBatchDeleted = new BeEvent<() => void>();\r\n\r\n /** Construct a new ObservableSet.\r\n * @param elements Optional elements with which to populate the new set.\r\n */\r\n public constructor(elements?: Iterable<T> | undefined) {\r\n // NB: Set constructor will invoke add(). Do not override until initialized.\r\n super(elements);\r\n\r\n this.add = (item: T) => {\r\n const prevSize = this.size;\r\n const ret = super.add(item);\r\n if (this.size !== prevSize)\r\n this.onAdded.raiseEvent(item);\r\n\r\n return ret;\r\n };\r\n }\r\n\r\n /** Invokes [Set.delete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete), raising\r\n * the [[onDeleted]] event if the item was removed from the set.\r\n */\r\n public override delete(item: T): boolean {\r\n const ret = super.delete(item);\r\n if (ret)\r\n this.onDeleted.raiseEvent(item);\r\n\r\n return ret;\r\n }\r\n\r\n /** If this set is not already empty, invokes [Set.clear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear)\r\n * and raises the [[onCleared]] event.\r\n */\r\n public override clear(): void {\r\n if (0 !== this.size) {\r\n super.clear();\r\n this.onCleared.raiseEvent();\r\n }\r\n }\r\n\r\n /** Add multiple items to the set, raising [[onBatchAdded]] only once after all items are added.\r\n * This is more efficient than calling [[add]] in a loop when listeners need not be notified of each individual addition.\r\n * @param items The items to add.\r\n * @returns The number of items that were actually added (i.e., were not already present).\r\n */\r\n public addAll(items: Iterable<T>): number {\r\n const prevSize = this.size;\r\n for (const item of items)\r\n super.add(item);\r\n\r\n if (this.size !== prevSize)\r\n this.onBatchAdded.raiseEvent();\r\n\r\n return this.size - prevSize;\r\n }\r\n\r\n /** Delete multiple items from the set, raising [[onBatchDeleted]] only once after all items are deleted.\r\n * This is more efficient than calling [[delete]] in a loop when listeners need not be notified of each individual deletion.\r\n * @param items The items to delete.\r\n * @returns The number of items that were actually deleted (i.e., were present in the set).\r\n */\r\n public deleteAll(items: Iterable<T>): number {\r\n const prevSize = this.size;\r\n for (const item of items)\r\n super.delete(item);\r\n\r\n if (this.size !== prevSize)\r\n this.onBatchDeleted.raiseEvent();\r\n\r\n return prevSize - this.size;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"OneAtATimeAction.d.ts","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,YAAY;AACZ,qBAAa,cAAe,SAAQ,KAAK;CAAI;AAqC7C;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB,CAAC,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAwB;IACxC,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,IAAI,CAAiC;IACtC,GAAG,EAAE,MAAM,CAAC;IAEnB;;OAEG;gBACS,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,SAAc;IAKlE;;OAEG;IACU,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;CAuBjD"}
1
+ {"version":3,"file":"OneAtATimeAction.d.ts","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,YAAY;AACZ,qBAAa,cAAe,SAAQ,KAAK;CAAI;AAqC7C;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB,CAAC,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAwB;IACxC,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,IAAI,CAAiC;IACtC,GAAG,EAAE,MAAM,CAAC;IAEnB;;OAEG;gBACS,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,SAAc;IAKlE;;OAEG;IACU,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;CA2BjD"}
@@ -92,11 +92,15 @@ class OneAtATimeAction {
92
92
  return await promise;
93
93
  }
94
94
  finally {
95
- // do all of this whether promise was fulfilled or rejected
96
- this._active = this._pending; // see if there's a pending request waiting
97
- this._pending = undefined; // clear pending
98
- if (this._active)
99
- this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises
95
+ // A replaced pending request can be abandoned before it ever becomes active.
96
+ // Only the currently active entry is allowed to promote/start the next pending request.
97
+ if (this._active === entry) {
98
+ // do all of this whether promise was fulfilled or rejected
99
+ this._active = this._pending; // see if there's a pending request waiting
100
+ this._pending = undefined; // clear pending
101
+ if (this._active)
102
+ this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises
103
+ }
100
104
  }
101
105
  }
102
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OneAtATimeAction.js","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,iDAA8C;AAE9C,YAAY;AACZ,MAAa,cAAe,SAAQ,KAAK;CAAI;AAA7C,wCAA6C;AAE7C;;;;;GAKG;AACH,MAAM,kBAAkB;IASF;IAA8C;IARlE,+GAA+G;IACxG,OAAO,CAA0B;IAChC,QAAQ,CAAsB;IAEtC;;;OAGG;IACH,YAAoB,IAAoC,EAAU,KAAY;QAA1D,SAAI,GAAJ,IAAI,CAAgC;QAAU,UAAK,GAAL,KAAK,CAAO;IAAI,CAAC;IAEnF,0GAA0G;IACnG,KAAK,CAAC,IAAI,CAAC,GAAW;QAC3B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,OAAO,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC;YAChF,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,oFAAoF;IAC7E,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,2BAAY,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,6EAA6E;QAChI,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAa,gBAAgB;IACnB,OAAO,CAAyB;IAChC,QAAQ,CAAyB;IACjC,IAAI,CAAiC;IACtC,GAAG,CAAS;IAEnB;;OAEG;IACH,YAAY,GAAmC,EAAE,GAAG,GAAG,WAAW;QAChE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO,CAAC,GAAG,IAAW;QACjC,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,0CAA0C;QACpG,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,8FAA8F;QAEpI,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC,CAAC,8BAA8B;YAC9D,IAAI,IAAI,CAAC,QAAQ,EAAE,8FAA8F;gBAC/G,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,iEAAiE;YAC5F,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,uCAAuC;YAC7D,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;QAC/E,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,2DAA2D;YAC3D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,2CAA2C;YACzE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,gBAAgB;YAC3C,IAAI,IAAI,CAAC,OAAO;gBACd,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;QACxF,CAAC;IACH,CAAC;CACF;AAxCD,4CAwCC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Utils\r\n */\r\n\r\nimport { BentleyError } from \"./BentleyError\";\r\n\r\n/** @beta */\r\nexport class AbandonedError extends Error { }\r\n\r\n/**\r\n * An object that returns a Promise when you call [[init]], but supplies a way to abandon the promise if it is no longer relevant.\r\n * When you call abandon, the promise will be rejected. You must supply a [[run]] method to the constructor that\r\n * creates the real Promise for the underlying action. Notice that to use this class there are really two\r\n * Promises involved that are chained together. That makes this class less efficient than just using a Promise directly.\r\n */\r\nclass PromiseWithAbandon<T> {\r\n /** Method to abandon the Promise created by [[init]] while it is outstanding. The promise will be rejected. */\r\n public abandon!: (msg?: string) => void;\r\n private _resolve!: (val: any) => void;\r\n\r\n /** Create a PromiseWithAbandon. After this call you must call [[init]] to create the underlying Promise.\r\n * @param _run The method that creates the underlying Promise.\r\n * @param _args An array of args to be passed to run when [[start]] is called.\r\n */\r\n constructor(private _run: (...args: any[]) => Promise<T>, private _args: any[]) { }\r\n\r\n /** Create a Promise that is chained to the underlying Promise, but is connected to the abandon method. */\r\n public async init(msg: string): Promise<T> {\r\n return new Promise<T>((resolve, reject) => {\r\n this.abandon = (message?: string) => reject(new AbandonedError(message ?? msg));\r\n this._resolve = resolve;\r\n });\r\n }\r\n\r\n /** Call the [[run]] method supplied to the ctor to start the underlying Promise. */\r\n public async start() {\r\n try {\r\n this._resolve(await this._run(...this._args));\r\n } catch (err) {\r\n this.abandon(BentleyError.getErrorMessage(err)); // turn all errors from execution into abandoned errors, but keep the message\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Orchestrator of a one-at-a-time activity. This concept is useful only for *replaceable* operations (that is, operations where subsequent requests replace and obviate\r\n * the need for previous requests. E.g. over slow HTTP connections, without this class, the stream of requests can overwhelm the connection, and cause the HTTP\r\n * request queue to grow such that the delay to service new requests is unbounded.\r\n *\r\n * With this class, we issue the initial request immediately. When the second request arrives before the first one completes, it becomes *pending*. If subsequent\r\n * requests arrive with a pending request, the current pending request is *abandoned* (its Promise is rejected) and the new request becomes pending.\r\n * When the active request completes, the pending request (if present) is started. In this manner there will only ever be one outstanding HTTP request for this type\r\n * of operation, but the first and last request will always eventually complete.\r\n * @beta\r\n */\r\nexport class OneAtATimeAction<T> {\r\n private _active?: PromiseWithAbandon<T>;\r\n private _pending?: PromiseWithAbandon<T>;\r\n private _run: (...args: any[]) => Promise<T>;\r\n public msg: string;\r\n\r\n /** Ctor for OneAtATimePromise.\r\n * @param run The method that performs an action that creates the Promise.\r\n */\r\n constructor(run: (...args: any[]) => Promise<T>, msg = \"abandoned\") {\r\n this._run = run;\r\n this.msg = msg;\r\n }\r\n\r\n /** Add a new request to this OneAtATimePromise. The request will only run when no other outstanding requests are active.\r\n * @note Callers of this method *must* handle AbandonedError rejections.\r\n */\r\n public async request(...args: any[]): Promise<T> {\r\n const entry = new PromiseWithAbandon<T>(this._run, args); // create an \"abandon-able promise\" object\r\n const promise = entry.init(this.msg); // create the Promise from PromiseWithAbandon. Note: this must be called before we call start.\r\n\r\n if (this._active !== undefined) { // is there an active request?\r\n if (this._pending) // yes. If there is also a pending request, this one replaces it and previous one is abandoned\r\n this._pending.abandon(); // rejects previous call to this method, throwing AbandonedError.\r\n this._pending = entry;\r\n } else {\r\n this._active = entry; // this is the first request, start it.\r\n entry.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n\r\n try {\r\n return await promise;\r\n } finally {\r\n // do all of this whether promise was fulfilled or rejected\r\n this._active = this._pending; // see if there's a pending request waiting\r\n this._pending = undefined; // clear pending\r\n if (this._active)\r\n this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"OneAtATimeAction.js","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,iDAA8C;AAE9C,YAAY;AACZ,MAAa,cAAe,SAAQ,KAAK;CAAI;AAA7C,wCAA6C;AAE7C;;;;;GAKG;AACH,MAAM,kBAAkB;IASF;IAA8C;IARlE,+GAA+G;IACxG,OAAO,CAA0B;IAChC,QAAQ,CAAsB;IAEtC;;;OAGG;IACH,YAAoB,IAAoC,EAAU,KAAY;QAA1D,SAAI,GAAJ,IAAI,CAAgC;QAAU,UAAK,GAAL,KAAK,CAAO;IAAI,CAAC;IAEnF,0GAA0G;IACnG,KAAK,CAAC,IAAI,CAAC,GAAW;QAC3B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,OAAO,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC;YAChF,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,oFAAoF;IAC7E,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,2BAAY,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,6EAA6E;QAChI,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAa,gBAAgB;IACnB,OAAO,CAAyB;IAChC,QAAQ,CAAyB;IACjC,IAAI,CAAiC;IACtC,GAAG,CAAS;IAEnB;;OAEG;IACH,YAAY,GAAmC,EAAE,GAAG,GAAG,WAAW;QAChE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO,CAAC,GAAG,IAAW;QACjC,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,0CAA0C;QACpG,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,8FAA8F;QAEpI,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC,CAAC,8BAA8B;YAC9D,IAAI,IAAI,CAAC,QAAQ,EAAE,8FAA8F;gBAC/G,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,iEAAiE;YAC5F,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,uCAAuC;YAC7D,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;QAC/E,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,6EAA6E;YAC7E,wFAAwF;YACxF,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC3B,2DAA2D;gBAC3D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,2CAA2C;gBACzE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,gBAAgB;gBAC3C,IAAI,IAAI,CAAC,OAAO;oBACd,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;YACxF,CAAC;QACH,CAAC;IACH,CAAC;CACF;AA5CD,4CA4CC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Utils\r\n */\r\n\r\nimport { BentleyError } from \"./BentleyError\";\r\n\r\n/** @beta */\r\nexport class AbandonedError extends Error { }\r\n\r\n/**\r\n * An object that returns a Promise when you call [[init]], but supplies a way to abandon the promise if it is no longer relevant.\r\n * When you call abandon, the promise will be rejected. You must supply a [[run]] method to the constructor that\r\n * creates the real Promise for the underlying action. Notice that to use this class there are really two\r\n * Promises involved that are chained together. That makes this class less efficient than just using a Promise directly.\r\n */\r\nclass PromiseWithAbandon<T> {\r\n /** Method to abandon the Promise created by [[init]] while it is outstanding. The promise will be rejected. */\r\n public abandon!: (msg?: string) => void;\r\n private _resolve!: (val: any) => void;\r\n\r\n /** Create a PromiseWithAbandon. After this call you must call [[init]] to create the underlying Promise.\r\n * @param _run The method that creates the underlying Promise.\r\n * @param _args An array of args to be passed to run when [[start]] is called.\r\n */\r\n constructor(private _run: (...args: any[]) => Promise<T>, private _args: any[]) { }\r\n\r\n /** Create a Promise that is chained to the underlying Promise, but is connected to the abandon method. */\r\n public async init(msg: string): Promise<T> {\r\n return new Promise<T>((resolve, reject) => {\r\n this.abandon = (message?: string) => reject(new AbandonedError(message ?? msg));\r\n this._resolve = resolve;\r\n });\r\n }\r\n\r\n /** Call the [[run]] method supplied to the ctor to start the underlying Promise. */\r\n public async start() {\r\n try {\r\n this._resolve(await this._run(...this._args));\r\n } catch (err) {\r\n this.abandon(BentleyError.getErrorMessage(err)); // turn all errors from execution into abandoned errors, but keep the message\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Orchestrator of a one-at-a-time activity. This concept is useful only for *replaceable* operations (that is, operations where subsequent requests replace and obviate\r\n * the need for previous requests. E.g. over slow HTTP connections, without this class, the stream of requests can overwhelm the connection, and cause the HTTP\r\n * request queue to grow such that the delay to service new requests is unbounded.\r\n *\r\n * With this class, we issue the initial request immediately. When the second request arrives before the first one completes, it becomes *pending*. If subsequent\r\n * requests arrive with a pending request, the current pending request is *abandoned* (its Promise is rejected) and the new request becomes pending.\r\n * When the active request completes, the pending request (if present) is started. In this manner there will only ever be one outstanding HTTP request for this type\r\n * of operation, but the first and last request will always eventually complete.\r\n * @beta\r\n */\r\nexport class OneAtATimeAction<T> {\r\n private _active?: PromiseWithAbandon<T>;\r\n private _pending?: PromiseWithAbandon<T>;\r\n private _run: (...args: any[]) => Promise<T>;\r\n public msg: string;\r\n\r\n /** Ctor for OneAtATimePromise.\r\n * @param run The method that performs an action that creates the Promise.\r\n */\r\n constructor(run: (...args: any[]) => Promise<T>, msg = \"abandoned\") {\r\n this._run = run;\r\n this.msg = msg;\r\n }\r\n\r\n /** Add a new request to this OneAtATimePromise. The request will only run when no other outstanding requests are active.\r\n * @note Callers of this method *must* handle AbandonedError rejections.\r\n */\r\n public async request(...args: any[]): Promise<T> {\r\n const entry = new PromiseWithAbandon<T>(this._run, args); // create an \"abandon-able promise\" object\r\n const promise = entry.init(this.msg); // create the Promise from PromiseWithAbandon. Note: this must be called before we call start.\r\n\r\n if (this._active !== undefined) { // is there an active request?\r\n if (this._pending) // yes. If there is also a pending request, this one replaces it and previous one is abandoned\r\n this._pending.abandon(); // rejects previous call to this method, throwing AbandonedError.\r\n this._pending = entry;\r\n } else {\r\n this._active = entry; // this is the first request, start it.\r\n entry.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n\r\n try {\r\n return await promise;\r\n } finally {\r\n // A replaced pending request can be abandoned before it ever becomes active.\r\n // Only the currently active entry is allowed to promote/start the next pending request.\r\n if (this._active === entry) {\r\n // do all of this whether promise was fulfilled or rejected\r\n this._active = this._pending; // see if there's a pending request waiting\r\n this._pending = undefined; // clear pending\r\n if (this._active)\r\n this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n }\r\n}\r\n"]}
@@ -12,6 +12,10 @@ export declare class ObservableSet<T> extends Set<T> {
12
12
  readonly onDeleted: BeEvent<(item: T) => void>;
13
13
  /** Emitted after this set's contents are cleared. */
14
14
  readonly onCleared: BeEvent<() => void>;
15
+ /** Emitted after multiple items are added to this set via [[addAll]]. */
16
+ readonly onBatchAdded: BeEvent<() => void>;
17
+ /** Emitted after multiple items are deleted from this set via [[deleteAll]]. */
18
+ readonly onBatchDeleted: BeEvent<() => void>;
15
19
  /** Construct a new ObservableSet.
16
20
  * @param elements Optional elements with which to populate the new set.
17
21
  */
@@ -24,5 +28,17 @@ export declare class ObservableSet<T> extends Set<T> {
24
28
  * and raises the [[onCleared]] event.
25
29
  */
26
30
  clear(): void;
31
+ /** Add multiple items to the set, raising [[onBatchAdded]] only once after all items are added.
32
+ * This is more efficient than calling [[add]] in a loop when listeners need not be notified of each individual addition.
33
+ * @param items The items to add.
34
+ * @returns The number of items that were actually added (i.e., were not already present).
35
+ */
36
+ addAll(items: Iterable<T>): number;
37
+ /** Delete multiple items from the set, raising [[onBatchDeleted]] only once after all items are deleted.
38
+ * This is more efficient than calling [[delete]] in a loop when listeners need not be notified of each individual deletion.
39
+ * @param items The items to delete.
40
+ * @returns The number of items that were actually deleted (i.e., were present in the set).
41
+ */
42
+ deleteAll(items: Iterable<T>): number;
27
43
  }
28
44
  //# sourceMappingURL=ObservableSet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableSet.d.ts","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IAC1C,iDAAiD;IACjD,SAAgB,OAAO,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC3D,qDAAqD;IACrD,SAAgB,SAAS,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC7D,qDAAqD;IACrD,SAAgB,SAAS,gBAAqB,IAAI,EAAI;IAEtD;;OAEG;gBACgB,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS;IAcrD;;OAEG;IACa,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAQxC;;OAEG;IACa,KAAK,IAAI,IAAI;CAM9B"}
1
+ {"version":3,"file":"ObservableSet.d.ts","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,qBAAa,aAAa,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,CAAC,CAAC;IAC1C,iDAAiD;IACjD,SAAgB,OAAO,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC3D,qDAAqD;IACrD,SAAgB,SAAS,iBAAsB,CAAC,KAAK,IAAI,EAAI;IAC7D,qDAAqD;IACrD,SAAgB,SAAS,gBAAqB,IAAI,EAAI;IACtD,yEAAyE;IACzE,SAAgB,YAAY,gBAAqB,IAAI,EAAI;IACzD,gFAAgF;IAChF,SAAgB,cAAc,gBAAqB,IAAI,EAAI;IAE3D;;OAEG;gBACgB,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS;IAcrD;;OAEG;IACa,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO;IAQxC;;OAEG;IACa,KAAK,IAAI,IAAI;IAO7B;;;;OAIG;IACI,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM;IAWzC;;;;OAIG;IACI,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM;CAU7C"}
@@ -16,6 +16,10 @@ export class ObservableSet extends Set {
16
16
  onDeleted = new BeEvent();
17
17
  /** Emitted after this set's contents are cleared. */
18
18
  onCleared = new BeEvent();
19
+ /** Emitted after multiple items are added to this set via [[addAll]]. */
20
+ onBatchAdded = new BeEvent();
21
+ /** Emitted after multiple items are deleted from this set via [[deleteAll]]. */
22
+ onBatchDeleted = new BeEvent();
19
23
  /** Construct a new ObservableSet.
20
24
  * @param elements Optional elements with which to populate the new set.
21
25
  */
@@ -48,5 +52,31 @@ export class ObservableSet extends Set {
48
52
  this.onCleared.raiseEvent();
49
53
  }
50
54
  }
55
+ /** Add multiple items to the set, raising [[onBatchAdded]] only once after all items are added.
56
+ * This is more efficient than calling [[add]] in a loop when listeners need not be notified of each individual addition.
57
+ * @param items The items to add.
58
+ * @returns The number of items that were actually added (i.e., were not already present).
59
+ */
60
+ addAll(items) {
61
+ const prevSize = this.size;
62
+ for (const item of items)
63
+ super.add(item);
64
+ if (this.size !== prevSize)
65
+ this.onBatchAdded.raiseEvent();
66
+ return this.size - prevSize;
67
+ }
68
+ /** Delete multiple items from the set, raising [[onBatchDeleted]] only once after all items are deleted.
69
+ * This is more efficient than calling [[delete]] in a loop when listeners need not be notified of each individual deletion.
70
+ * @param items The items to delete.
71
+ * @returns The number of items that were actually deleted (i.e., were present in the set).
72
+ */
73
+ deleteAll(items) {
74
+ const prevSize = this.size;
75
+ for (const item of items)
76
+ super.delete(item);
77
+ if (this.size !== prevSize)
78
+ this.onBatchDeleted.raiseEvent();
79
+ return prevSize - this.size;
80
+ }
51
81
  }
52
82
  //# sourceMappingURL=ObservableSet.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableSet.js","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,OAAO,aAAiB,SAAQ,GAAM;IAC1C,iDAAiD;IACjC,OAAO,GAAG,IAAI,OAAO,EAAqB,CAAC;IAC3D,qDAAqD;IACrC,SAAS,GAAG,IAAI,OAAO,EAAqB,CAAC;IAC7D,qDAAqD;IACrC,SAAS,GAAG,IAAI,OAAO,EAAc,CAAC;IAEtD;;OAEG;IACH,YAAmB,QAAkC;QACnD,4EAA4E;QAC5E,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEhB,IAAI,CAAC,GAAG,GAAG,CAAC,IAAO,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;YAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;gBACxB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAEhC,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACa,MAAM,CAAC,IAAO;QAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,GAAG;YACL,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAElC,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACa,KAAK;QACnB,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Collections\r\n */\r\n\r\nimport { BeEvent } from \"./BeEvent\";\r\n\r\n/** A standard [Set<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) that emits events when its contents change.\r\n * @public\r\n */\r\nexport class ObservableSet<T> extends Set<T> {\r\n /** Emitted after `item` is added to this set. */\r\n public readonly onAdded = new BeEvent<(item: T) => void>();\r\n /** Emitted after `item` is deleted from this set. */\r\n public readonly onDeleted = new BeEvent<(item: T) => void>();\r\n /** Emitted after this set's contents are cleared. */\r\n public readonly onCleared = new BeEvent<() => void>();\r\n\r\n /** Construct a new ObservableSet.\r\n * @param elements Optional elements with which to populate the new set.\r\n */\r\n public constructor(elements?: Iterable<T> | undefined) {\r\n // NB: Set constructor will invoke add(). Do not override until initialized.\r\n super(elements);\r\n\r\n this.add = (item: T) => {\r\n const prevSize = this.size;\r\n const ret = super.add(item);\r\n if (this.size !== prevSize)\r\n this.onAdded.raiseEvent(item);\r\n\r\n return ret;\r\n };\r\n }\r\n\r\n /** Invokes [Set.delete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete), raising\r\n * the [[onDeleted]] event if the item was removed from the set.\r\n */\r\n public override delete(item: T): boolean {\r\n const ret = super.delete(item);\r\n if (ret)\r\n this.onDeleted.raiseEvent(item);\r\n\r\n return ret;\r\n }\r\n\r\n /** If this set is not already empty, invokes [Set.clear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear)\r\n * and raises the [[onCleared]] event.\r\n */\r\n public override clear(): void {\r\n if (0 !== this.size) {\r\n super.clear();\r\n this.onCleared.raiseEvent();\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"ObservableSet.js","sourceRoot":"","sources":["../../src/ObservableSet.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,OAAO,aAAiB,SAAQ,GAAM;IAC1C,iDAAiD;IACjC,OAAO,GAAG,IAAI,OAAO,EAAqB,CAAC;IAC3D,qDAAqD;IACrC,SAAS,GAAG,IAAI,OAAO,EAAqB,CAAC;IAC7D,qDAAqD;IACrC,SAAS,GAAG,IAAI,OAAO,EAAc,CAAC;IACtD,yEAAyE;IACzD,YAAY,GAAG,IAAI,OAAO,EAAc,CAAC;IACzD,gFAAgF;IAChE,cAAc,GAAG,IAAI,OAAO,EAAc,CAAC;IAE3D;;OAEG;IACH,YAAmB,QAAkC;QACnD,4EAA4E;QAC5E,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEhB,IAAI,CAAC,GAAG,GAAG,CAAC,IAAO,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;YAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;gBACxB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAEhC,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACa,MAAM,CAAC,IAAO;QAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,GAAG;YACL,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAElC,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACa,KAAK;QACnB,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,KAAkB;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK;YACtB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAElB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YACxB,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;QAEjC,OAAO,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACI,SAAS,CAAC,KAAkB;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK;YACtB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAErB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;YACxB,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QAEnC,OAAO,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Collections\r\n */\r\n\r\nimport { BeEvent } from \"./BeEvent\";\r\n\r\n/** A standard [Set<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) that emits events when its contents change.\r\n * @public\r\n */\r\nexport class ObservableSet<T> extends Set<T> {\r\n /** Emitted after `item` is added to this set. */\r\n public readonly onAdded = new BeEvent<(item: T) => void>();\r\n /** Emitted after `item` is deleted from this set. */\r\n public readonly onDeleted = new BeEvent<(item: T) => void>();\r\n /** Emitted after this set's contents are cleared. */\r\n public readonly onCleared = new BeEvent<() => void>();\r\n /** Emitted after multiple items are added to this set via [[addAll]]. */\r\n public readonly onBatchAdded = new BeEvent<() => void>();\r\n /** Emitted after multiple items are deleted from this set via [[deleteAll]]. */\r\n public readonly onBatchDeleted = new BeEvent<() => void>();\r\n\r\n /** Construct a new ObservableSet.\r\n * @param elements Optional elements with which to populate the new set.\r\n */\r\n public constructor(elements?: Iterable<T> | undefined) {\r\n // NB: Set constructor will invoke add(). Do not override until initialized.\r\n super(elements);\r\n\r\n this.add = (item: T) => {\r\n const prevSize = this.size;\r\n const ret = super.add(item);\r\n if (this.size !== prevSize)\r\n this.onAdded.raiseEvent(item);\r\n\r\n return ret;\r\n };\r\n }\r\n\r\n /** Invokes [Set.delete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete), raising\r\n * the [[onDeleted]] event if the item was removed from the set.\r\n */\r\n public override delete(item: T): boolean {\r\n const ret = super.delete(item);\r\n if (ret)\r\n this.onDeleted.raiseEvent(item);\r\n\r\n return ret;\r\n }\r\n\r\n /** If this set is not already empty, invokes [Set.clear](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear)\r\n * and raises the [[onCleared]] event.\r\n */\r\n public override clear(): void {\r\n if (0 !== this.size) {\r\n super.clear();\r\n this.onCleared.raiseEvent();\r\n }\r\n }\r\n\r\n /** Add multiple items to the set, raising [[onBatchAdded]] only once after all items are added.\r\n * This is more efficient than calling [[add]] in a loop when listeners need not be notified of each individual addition.\r\n * @param items The items to add.\r\n * @returns The number of items that were actually added (i.e., were not already present).\r\n */\r\n public addAll(items: Iterable<T>): number {\r\n const prevSize = this.size;\r\n for (const item of items)\r\n super.add(item);\r\n\r\n if (this.size !== prevSize)\r\n this.onBatchAdded.raiseEvent();\r\n\r\n return this.size - prevSize;\r\n }\r\n\r\n /** Delete multiple items from the set, raising [[onBatchDeleted]] only once after all items are deleted.\r\n * This is more efficient than calling [[delete]] in a loop when listeners need not be notified of each individual deletion.\r\n * @param items The items to delete.\r\n * @returns The number of items that were actually deleted (i.e., were present in the set).\r\n */\r\n public deleteAll(items: Iterable<T>): number {\r\n const prevSize = this.size;\r\n for (const item of items)\r\n super.delete(item);\r\n\r\n if (this.size !== prevSize)\r\n this.onBatchDeleted.raiseEvent();\r\n\r\n return prevSize - this.size;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"OneAtATimeAction.d.ts","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,YAAY;AACZ,qBAAa,cAAe,SAAQ,KAAK;CAAI;AAqC7C;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB,CAAC,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAwB;IACxC,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,IAAI,CAAiC;IACtC,GAAG,EAAE,MAAM,CAAC;IAEnB;;OAEG;gBACS,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,SAAc;IAKlE;;OAEG;IACU,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;CAuBjD"}
1
+ {"version":3,"file":"OneAtATimeAction.d.ts","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,YAAY;AACZ,qBAAa,cAAe,SAAQ,KAAK;CAAI;AAqC7C;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB,CAAC,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAwB;IACxC,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,IAAI,CAAiC;IACtC,GAAG,EAAE,MAAM,CAAC;IAEnB;;OAEG;gBACS,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,SAAc;IAKlE;;OAEG;IACU,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;CA2BjD"}
@@ -88,11 +88,15 @@ export class OneAtATimeAction {
88
88
  return await promise;
89
89
  }
90
90
  finally {
91
- // do all of this whether promise was fulfilled or rejected
92
- this._active = this._pending; // see if there's a pending request waiting
93
- this._pending = undefined; // clear pending
94
- if (this._active)
95
- this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises
91
+ // A replaced pending request can be abandoned before it ever becomes active.
92
+ // Only the currently active entry is allowed to promote/start the next pending request.
93
+ if (this._active === entry) {
94
+ // do all of this whether promise was fulfilled or rejected
95
+ this._active = this._pending; // see if there's a pending request waiting
96
+ this._pending = undefined; // clear pending
97
+ if (this._active)
98
+ this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises
99
+ }
96
100
  }
97
101
  }
98
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OneAtATimeAction.js","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,YAAY;AACZ,MAAM,OAAO,cAAe,SAAQ,KAAK;CAAI;AAE7C;;;;;GAKG;AACH,MAAM,kBAAkB;IASF;IAA8C;IARlE,+GAA+G;IACxG,OAAO,CAA0B;IAChC,QAAQ,CAAsB;IAEtC;;;OAGG;IACH,YAAoB,IAAoC,EAAU,KAAY;QAA1D,SAAI,GAAJ,IAAI,CAAgC;QAAU,UAAK,GAAL,KAAK,CAAO;IAAI,CAAC;IAEnF,0GAA0G;IACnG,KAAK,CAAC,IAAI,CAAC,GAAW;QAC3B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,OAAO,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC;YAChF,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,oFAAoF;IAC7E,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,6EAA6E;QAChI,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,gBAAgB;IACnB,OAAO,CAAyB;IAChC,QAAQ,CAAyB;IACjC,IAAI,CAAiC;IACtC,GAAG,CAAS;IAEnB;;OAEG;IACH,YAAY,GAAmC,EAAE,GAAG,GAAG,WAAW;QAChE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO,CAAC,GAAG,IAAW;QACjC,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,0CAA0C;QACpG,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,8FAA8F;QAEpI,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC,CAAC,8BAA8B;YAC9D,IAAI,IAAI,CAAC,QAAQ,EAAE,8FAA8F;gBAC/G,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,iEAAiE;YAC5F,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,uCAAuC;YAC7D,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;QAC/E,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,2DAA2D;YAC3D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,2CAA2C;YACzE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,gBAAgB;YAC3C,IAAI,IAAI,CAAC,OAAO;gBACd,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;QACxF,CAAC;IACH,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Utils\r\n */\r\n\r\nimport { BentleyError } from \"./BentleyError\";\r\n\r\n/** @beta */\r\nexport class AbandonedError extends Error { }\r\n\r\n/**\r\n * An object that returns a Promise when you call [[init]], but supplies a way to abandon the promise if it is no longer relevant.\r\n * When you call abandon, the promise will be rejected. You must supply a [[run]] method to the constructor that\r\n * creates the real Promise for the underlying action. Notice that to use this class there are really two\r\n * Promises involved that are chained together. That makes this class less efficient than just using a Promise directly.\r\n */\r\nclass PromiseWithAbandon<T> {\r\n /** Method to abandon the Promise created by [[init]] while it is outstanding. The promise will be rejected. */\r\n public abandon!: (msg?: string) => void;\r\n private _resolve!: (val: any) => void;\r\n\r\n /** Create a PromiseWithAbandon. After this call you must call [[init]] to create the underlying Promise.\r\n * @param _run The method that creates the underlying Promise.\r\n * @param _args An array of args to be passed to run when [[start]] is called.\r\n */\r\n constructor(private _run: (...args: any[]) => Promise<T>, private _args: any[]) { }\r\n\r\n /** Create a Promise that is chained to the underlying Promise, but is connected to the abandon method. */\r\n public async init(msg: string): Promise<T> {\r\n return new Promise<T>((resolve, reject) => {\r\n this.abandon = (message?: string) => reject(new AbandonedError(message ?? msg));\r\n this._resolve = resolve;\r\n });\r\n }\r\n\r\n /** Call the [[run]] method supplied to the ctor to start the underlying Promise. */\r\n public async start() {\r\n try {\r\n this._resolve(await this._run(...this._args));\r\n } catch (err) {\r\n this.abandon(BentleyError.getErrorMessage(err)); // turn all errors from execution into abandoned errors, but keep the message\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Orchestrator of a one-at-a-time activity. This concept is useful only for *replaceable* operations (that is, operations where subsequent requests replace and obviate\r\n * the need for previous requests. E.g. over slow HTTP connections, without this class, the stream of requests can overwhelm the connection, and cause the HTTP\r\n * request queue to grow such that the delay to service new requests is unbounded.\r\n *\r\n * With this class, we issue the initial request immediately. When the second request arrives before the first one completes, it becomes *pending*. If subsequent\r\n * requests arrive with a pending request, the current pending request is *abandoned* (its Promise is rejected) and the new request becomes pending.\r\n * When the active request completes, the pending request (if present) is started. In this manner there will only ever be one outstanding HTTP request for this type\r\n * of operation, but the first and last request will always eventually complete.\r\n * @beta\r\n */\r\nexport class OneAtATimeAction<T> {\r\n private _active?: PromiseWithAbandon<T>;\r\n private _pending?: PromiseWithAbandon<T>;\r\n private _run: (...args: any[]) => Promise<T>;\r\n public msg: string;\r\n\r\n /** Ctor for OneAtATimePromise.\r\n * @param run The method that performs an action that creates the Promise.\r\n */\r\n constructor(run: (...args: any[]) => Promise<T>, msg = \"abandoned\") {\r\n this._run = run;\r\n this.msg = msg;\r\n }\r\n\r\n /** Add a new request to this OneAtATimePromise. The request will only run when no other outstanding requests are active.\r\n * @note Callers of this method *must* handle AbandonedError rejections.\r\n */\r\n public async request(...args: any[]): Promise<T> {\r\n const entry = new PromiseWithAbandon<T>(this._run, args); // create an \"abandon-able promise\" object\r\n const promise = entry.init(this.msg); // create the Promise from PromiseWithAbandon. Note: this must be called before we call start.\r\n\r\n if (this._active !== undefined) { // is there an active request?\r\n if (this._pending) // yes. If there is also a pending request, this one replaces it and previous one is abandoned\r\n this._pending.abandon(); // rejects previous call to this method, throwing AbandonedError.\r\n this._pending = entry;\r\n } else {\r\n this._active = entry; // this is the first request, start it.\r\n entry.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n\r\n try {\r\n return await promise;\r\n } finally {\r\n // do all of this whether promise was fulfilled or rejected\r\n this._active = this._pending; // see if there's a pending request waiting\r\n this._pending = undefined; // clear pending\r\n if (this._active)\r\n this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"OneAtATimeAction.js","sourceRoot":"","sources":["../../src/OneAtATimeAction.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,YAAY;AACZ,MAAM,OAAO,cAAe,SAAQ,KAAK;CAAI;AAE7C;;;;;GAKG;AACH,MAAM,kBAAkB;IASF;IAA8C;IARlE,+GAA+G;IACxG,OAAO,CAA0B;IAChC,QAAQ,CAAsB;IAEtC;;;OAGG;IACH,YAAoB,IAAoC,EAAU,KAAY;QAA1D,SAAI,GAAJ,IAAI,CAAgC;QAAU,UAAK,GAAL,KAAK,CAAO;IAAI,CAAC;IAEnF,0GAA0G;IACnG,KAAK,CAAC,IAAI,CAAC,GAAW;QAC3B,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,OAAO,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC;YAChF,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,oFAAoF;IAC7E,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,6EAA6E;QAChI,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,gBAAgB;IACnB,OAAO,CAAyB;IAChC,QAAQ,CAAyB;IACjC,IAAI,CAAiC;IACtC,GAAG,CAAS;IAEnB;;OAEG;IACH,YAAY,GAAmC,EAAE,GAAG,GAAG,WAAW;QAChE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO,CAAC,GAAG,IAAW;QACjC,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,0CAA0C;QACpG,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,8FAA8F;QAEpI,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC,CAAC,8BAA8B;YAC9D,IAAI,IAAI,CAAC,QAAQ,EAAE,8FAA8F;gBAC/G,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,iEAAiE;YAC5F,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,uCAAuC;YAC7D,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;QAC/E,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,6EAA6E;YAC7E,wFAAwF;YACxF,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC3B,2DAA2D;gBAC3D,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,2CAA2C;gBACzE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,gBAAgB;gBAC3C,IAAI,IAAI,CAAC,OAAO;oBACd,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,8DAA8D;YACxF,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Utils\r\n */\r\n\r\nimport { BentleyError } from \"./BentleyError\";\r\n\r\n/** @beta */\r\nexport class AbandonedError extends Error { }\r\n\r\n/**\r\n * An object that returns a Promise when you call [[init]], but supplies a way to abandon the promise if it is no longer relevant.\r\n * When you call abandon, the promise will be rejected. You must supply a [[run]] method to the constructor that\r\n * creates the real Promise for the underlying action. Notice that to use this class there are really two\r\n * Promises involved that are chained together. That makes this class less efficient than just using a Promise directly.\r\n */\r\nclass PromiseWithAbandon<T> {\r\n /** Method to abandon the Promise created by [[init]] while it is outstanding. The promise will be rejected. */\r\n public abandon!: (msg?: string) => void;\r\n private _resolve!: (val: any) => void;\r\n\r\n /** Create a PromiseWithAbandon. After this call you must call [[init]] to create the underlying Promise.\r\n * @param _run The method that creates the underlying Promise.\r\n * @param _args An array of args to be passed to run when [[start]] is called.\r\n */\r\n constructor(private _run: (...args: any[]) => Promise<T>, private _args: any[]) { }\r\n\r\n /** Create a Promise that is chained to the underlying Promise, but is connected to the abandon method. */\r\n public async init(msg: string): Promise<T> {\r\n return new Promise<T>((resolve, reject) => {\r\n this.abandon = (message?: string) => reject(new AbandonedError(message ?? msg));\r\n this._resolve = resolve;\r\n });\r\n }\r\n\r\n /** Call the [[run]] method supplied to the ctor to start the underlying Promise. */\r\n public async start() {\r\n try {\r\n this._resolve(await this._run(...this._args));\r\n } catch (err) {\r\n this.abandon(BentleyError.getErrorMessage(err)); // turn all errors from execution into abandoned errors, but keep the message\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Orchestrator of a one-at-a-time activity. This concept is useful only for *replaceable* operations (that is, operations where subsequent requests replace and obviate\r\n * the need for previous requests. E.g. over slow HTTP connections, without this class, the stream of requests can overwhelm the connection, and cause the HTTP\r\n * request queue to grow such that the delay to service new requests is unbounded.\r\n *\r\n * With this class, we issue the initial request immediately. When the second request arrives before the first one completes, it becomes *pending*. If subsequent\r\n * requests arrive with a pending request, the current pending request is *abandoned* (its Promise is rejected) and the new request becomes pending.\r\n * When the active request completes, the pending request (if present) is started. In this manner there will only ever be one outstanding HTTP request for this type\r\n * of operation, but the first and last request will always eventually complete.\r\n * @beta\r\n */\r\nexport class OneAtATimeAction<T> {\r\n private _active?: PromiseWithAbandon<T>;\r\n private _pending?: PromiseWithAbandon<T>;\r\n private _run: (...args: any[]) => Promise<T>;\r\n public msg: string;\r\n\r\n /** Ctor for OneAtATimePromise.\r\n * @param run The method that performs an action that creates the Promise.\r\n */\r\n constructor(run: (...args: any[]) => Promise<T>, msg = \"abandoned\") {\r\n this._run = run;\r\n this.msg = msg;\r\n }\r\n\r\n /** Add a new request to this OneAtATimePromise. The request will only run when no other outstanding requests are active.\r\n * @note Callers of this method *must* handle AbandonedError rejections.\r\n */\r\n public async request(...args: any[]): Promise<T> {\r\n const entry = new PromiseWithAbandon<T>(this._run, args); // create an \"abandon-able promise\" object\r\n const promise = entry.init(this.msg); // create the Promise from PromiseWithAbandon. Note: this must be called before we call start.\r\n\r\n if (this._active !== undefined) { // is there an active request?\r\n if (this._pending) // yes. If there is also a pending request, this one replaces it and previous one is abandoned\r\n this._pending.abandon(); // rejects previous call to this method, throwing AbandonedError.\r\n this._pending = entry;\r\n } else {\r\n this._active = entry; // this is the first request, start it.\r\n entry.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n\r\n try {\r\n return await promise;\r\n } finally {\r\n // A replaced pending request can be abandoned before it ever becomes active.\r\n // Only the currently active entry is allowed to promote/start the next pending request.\r\n if (this._active === entry) {\r\n // do all of this whether promise was fulfilled or rejected\r\n this._active = this._pending; // see if there's a pending request waiting\r\n this._pending = undefined; // clear pending\r\n if (this._active)\r\n this._active.start(); // eslint-disable-line @typescript-eslint/no-floating-promises\r\n }\r\n }\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/core-bentley",
3
- "version": "5.7.0-dev.13",
3
+ "version": "5.7.0-dev.15",
4
4
  "description": "Bentley JavaScript core components",
5
5
  "main": "lib/cjs/core-bentley.js",
6
6
  "module": "lib/esm/core-bentley.js",
@@ -30,7 +30,7 @@
30
30
  "rimraf": "^6.0.1",
31
31
  "typescript": "~5.6.2",
32
32
  "vitest": "^3.0.6",
33
- "@itwin/build-tools": "5.7.0-dev.13"
33
+ "@itwin/build-tools": "5.7.0-dev.15"
34
34
  },
35
35
  "nyc": {
36
36
  "extends": "./node_modules/@itwin/build-tools/.nycrc"