|
4 | 4 | // in https://github.com/mysticatea/abort-controller (MIT license)
|
5 | 5 |
|
6 | 6 | const {
|
| 7 | + ArrayPrototypePush, |
7 | 8 | ObjectAssign,
|
8 | 9 | ObjectDefineProperties,
|
9 | 10 | ObjectDefineProperty,
|
10 | 11 | PromiseResolve,
|
11 | 12 | SafeFinalizationRegistry,
|
12 | 13 | SafeSet,
|
13 | 14 | SafeWeakRef,
|
| 15 | + SafeWeakSet, |
14 | 16 | Symbol,
|
15 | 17 | SymbolToStringTag,
|
| 18 | + WeakRefPrototypeDeref, |
| 19 | + WeakSetPrototypeAdd, |
| 20 | + WeakSetPrototypeHas, |
16 | 21 | } = primordials;
|
17 | 22 |
|
18 | 23 | const {
|
@@ -100,6 +105,33 @@ const kComposite = Symbol('kComposite');
|
100 | 105 | const kSourceSignals = Symbol('kSourceSignals');
|
101 | 106 | const kDependantSignals = Symbol('kDependantSignals');
|
102 | 107 |
|
| 108 | +// Since WeakSet is not iterable, we must use another iterable |
| 109 | +// data structure to make it "iterable". |
| 110 | +class IterableWeakSet { |
| 111 | + #weakSet = new SafeWeakSet(); |
| 112 | + #weakRefs = []; |
| 113 | + |
| 114 | + add(value) { |
| 115 | + if (!this.has(value)) { |
| 116 | + WeakSetPrototypeAdd(this.#weakSet, value); |
| 117 | + ArrayPrototypePush(this.#weakRefs, new SafeWeakRef(value)); |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + has(value) { |
| 122 | + return WeakSetPrototypeHas(this.#weakSet, value); |
| 123 | + } |
| 124 | + |
| 125 | + getIterable() { |
| 126 | + const iterable = []; |
| 127 | + for (let i = 0; i < this.#weakRefs.length; i++) { |
| 128 | + const item = WeakRefPrototypeDeref(this.#weakRefs[i]); |
| 129 | + ArrayPrototypePush(iterable, item); |
| 130 | + } |
| 131 | + return iterable; |
| 132 | + } |
| 133 | +} |
| 134 | + |
103 | 135 | function customInspect(self, obj, depth, options) {
|
104 | 136 | if (depth < 0)
|
105 | 137 | return self;
|
@@ -238,34 +270,32 @@ class AbortSignal extends EventTarget {
|
238 | 270 | if (!signalsArray.length) {
|
239 | 271 | return resultSignal;
|
240 | 272 | }
|
241 |
| - const resultSignalWeakRef = new SafeWeakRef(resultSignal); |
242 |
| - resultSignal[kSourceSignals] = new SafeSet(); |
| 273 | + resultSignal[kSourceSignals] = new IterableWeakSet(); |
243 | 274 | for (let i = 0; i < signalsArray.length; i++) {
|
244 | 275 | const signal = signalsArray[i];
|
245 | 276 | if (signal.aborted) {
|
246 | 277 | abortSignal(resultSignal, signal.reason);
|
247 | 278 | return resultSignal;
|
248 | 279 | }
|
249 |
| - signal[kDependantSignals] ??= new SafeSet(); |
| 280 | + signal[kDependantSignals] ??= new IterableWeakSet(); |
250 | 281 | if (!signal[kComposite]) {
|
251 |
| - resultSignal[kSourceSignals].add(new SafeWeakRef(signal)); |
252 |
| - signal[kDependantSignals].add(resultSignalWeakRef); |
| 282 | + resultSignal[kSourceSignals].add(signal); |
| 283 | + signal[kDependantSignals].add(resultSignal); |
253 | 284 | } else if (!signal[kSourceSignals]) {
|
254 | 285 | continue;
|
255 | 286 | } else {
|
256 |
| - for (const sourceSignal of signal[kSourceSignals]) { |
257 |
| - const sourceSignalRef = sourceSignal.deref(); |
258 |
| - if (!sourceSignalRef) { |
| 287 | + for (const sourceSignal of signal[kSourceSignals].getIterable()) { |
| 288 | + if (!sourceSignal) { |
259 | 289 | continue;
|
260 | 290 | }
|
261 |
| - assert(!sourceSignalRef.aborted); |
262 |
| - assert(!sourceSignalRef[kComposite]); |
| 291 | + assert(!sourceSignal.aborted); |
| 292 | + assert(!sourceSignal[kComposite]); |
263 | 293 |
|
264 | 294 | if (resultSignal[kSourceSignals].has(sourceSignal)) {
|
265 | 295 | continue;
|
266 | 296 | }
|
267 | 297 | resultSignal[kSourceSignals].add(sourceSignal);
|
268 |
| - sourceSignalRef[kDependantSignals].add(resultSignalWeakRef); |
| 298 | + sourceSignal[kDependantSignals].add(resultSignal); |
269 | 299 | }
|
270 | 300 | }
|
271 | 301 | }
|
@@ -380,9 +410,8 @@ function abortSignal(signal, reason) {
|
380 | 410 | [kTrustEvent]: true,
|
381 | 411 | });
|
382 | 412 | signal.dispatchEvent(event);
|
383 |
| - signal[kDependantSignals]?.forEach((s) => { |
384 |
| - const signalRef = s.deref(); |
385 |
| - if (signalRef) abortSignal(signalRef, reason); |
| 413 | + signal[kDependantSignals]?.getIterable()?.forEach((s) => { |
| 414 | + if (s) abortSignal(s, reason); |
386 | 415 | });
|
387 | 416 | }
|
388 | 417 |
|
|
0 commit comments