|
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