dommy-js-quickjs 0.1.0

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.
@@ -0,0 +1,728 @@
1
+ // Observable / Subscriber polyfill (WICG Observable) + EventTarget.prototype.when.
2
+ //
3
+ // QuickJS is a real JS engine, so the reactive primitive is implemented in JS
4
+ // and evaluated into the VM after the DOM interface prototypes are seeded (so
5
+ // `EventTarget.prototype` exists). The only host integration points are
6
+ // EventTarget (addEventListener/removeEventListener), AbortController/AbortSignal,
7
+ // and reporting an unhandled exception to the global error handler.
8
+ (function () {
9
+ "use strict";
10
+ if (typeof globalThis.Observable === "function") return;
11
+
12
+ const kInternal = Symbol("observable-internal");
13
+
14
+ // "Report the exception" — dispatch an `error` ErrorEvent on the global so
15
+ // `self.addEventListener("error", …)` sees unhandled Observable errors.
16
+ function reportException(error) {
17
+ // A thrown value with no stack (e.g. a string) reports lineno/colno 0;
18
+ // a real Error carries a stack we parse for a positive position.
19
+ let lineno = 0, colno = 0, filename = "";
20
+ const stack = error && typeof error === "object" ? error.stack : undefined;
21
+ if (typeof stack === "string") {
22
+ const m = stack.match(/\(?([^()\s]*):(\d+):(\d+)\)?/);
23
+ if (m) {
24
+ filename = m[1] || "";
25
+ lineno = parseInt(m[2], 10) || 0;
26
+ colno = parseInt(m[3], 10) || 0;
27
+ }
28
+ }
29
+ const message = (error && typeof error === "object" && "message" in error)
30
+ ? String(error.message) : String(error);
31
+ const g = globalThis.window || globalThis;
32
+ let event;
33
+ try {
34
+ if (typeof globalThis.ErrorEvent === "function") {
35
+ event = new ErrorEvent("error", { error, message, lineno, colno, filename, cancelable: true });
36
+ } else {
37
+ event = new Event("error", { cancelable: true });
38
+ event.error = error;
39
+ event.message = message;
40
+ event.lineno = lineno;
41
+ event.colno = colno;
42
+ event.filename = filename;
43
+ }
44
+ if (g && typeof g.dispatchEvent === "function") g.dispatchEvent(event);
45
+ } catch (_e) {
46
+ // Best effort: swallow — reporting must never throw into the caller.
47
+ }
48
+ }
49
+
50
+ function isCallable(v) { return typeof v === "function"; }
51
+
52
+ // take()/drop() counts are WebIDL `unsigned long long`: a negative value
53
+ // wraps to the maximum (effectively unlimited), as does a non-finite value.
54
+ function toUnsignedCount(amount) {
55
+ const n = Math.trunc(Number(amount));
56
+ if (!isFinite(n) || n < 0) return Infinity;
57
+ return n;
58
+ }
59
+
60
+ // TC39 GetMethod(value, key): undefined for an absent (null/undefined)
61
+ // property, the function if callable, and a TypeError if present but not
62
+ // callable. The property read may itself throw (a getter) — that propagates.
63
+ function getMethod(value, key) {
64
+ const method = value[key];
65
+ if (method === undefined || method === null) return undefined;
66
+ if (!isCallable(method)) throw new TypeError(String(key) + " is not a function");
67
+ return method;
68
+ }
69
+
70
+ // The Subscriber handed to an Observable's initializer. Not constructible from
71
+ // script. Uses #private fields so a detached `next`/`error`/`complete`
72
+ // (called with no receiver) throws TypeError — matching the WebIDL receiver
73
+ // check the spec mandates.
74
+ class Subscriber {
75
+ #token;
76
+ #ac;
77
+ #signal;
78
+ #next;
79
+ #error;
80
+ #complete;
81
+ #teardowns = [];
82
+ #closed = false;
83
+
84
+ constructor(token, observer) {
85
+ if (token !== kInternal) throw new TypeError("Illegal constructor");
86
+ this.#token = token;
87
+ this.#ac = new AbortController();
88
+ this.#signal = this.#ac.signal;
89
+ this.#next = isCallable(observer && observer.next) ? observer.next : null;
90
+ this.#error = isCallable(observer && observer.error) ? observer.error : null;
91
+ this.#complete = isCallable(observer && observer.complete) ? observer.complete : null;
92
+ }
93
+
94
+ get active() { return !this.#signal.aborted; }
95
+ get signal() { return this.#signal; }
96
+
97
+ next(value) {
98
+ // Touch a private field first so a receiver-less call throws TypeError.
99
+ void this.#token;
100
+ if (arguments.length < 1) throw new TypeError("Subscriber.next requires 1 argument");
101
+ if (this.#signal.aborted) return;
102
+ if (this.#next) {
103
+ try { this.#next.call(undefined, value); }
104
+ catch (e) { reportException(e); }
105
+ }
106
+ }
107
+
108
+ error(err) {
109
+ void this.#token;
110
+ if (arguments.length < 1) throw new TypeError("Subscriber.error requires 1 argument");
111
+ if (this.#signal.aborted) { reportException(err); return; }
112
+ const cb = this.#error;
113
+ this.#close(err);
114
+ if (cb) {
115
+ try { cb.call(undefined, err); }
116
+ catch (e) { reportException(e); }
117
+ } else {
118
+ reportException(err);
119
+ }
120
+ }
121
+
122
+ complete() {
123
+ void this.#token;
124
+ if (this.#signal.aborted) return;
125
+ const cb = this.#complete;
126
+ this.#close(undefined);
127
+ if (cb) {
128
+ try { cb.call(undefined); }
129
+ catch (e) { reportException(e); }
130
+ }
131
+ }
132
+
133
+ addTeardown(teardown) {
134
+ void this.#token;
135
+ if (!isCallable(teardown)) return;
136
+ if (this.#signal.aborted) {
137
+ try { teardown.call(undefined); } catch (e) { reportException(e); }
138
+ } else {
139
+ this.#teardowns.push(teardown);
140
+ }
141
+ }
142
+
143
+ // Abort the subscriber's signal (reason for error()), then run teardowns
144
+ // LIFO. After this, active is false and the signal is aborted — before any
145
+ // observer complete()/error() callback is invoked.
146
+ #close(reason) {
147
+ if (this.#closed) return;
148
+ this.#closed = true;
149
+ try { this.#ac.abort(reason); } catch (_e) {}
150
+ const teardowns = this.#teardowns;
151
+ this.#teardowns = [];
152
+ for (let i = teardowns.length - 1; i >= 0; i--) {
153
+ try { teardowns[i].call(undefined); } catch (e) { reportException(e); }
154
+ }
155
+ }
156
+
157
+ // Internal: abort because the consumer's signal aborted (unsubscribe).
158
+ _abortConsumer(reason) { this.#close(reason); }
159
+ }
160
+
161
+ Object.defineProperty(Subscriber.prototype, Symbol.toStringTag, {
162
+ value: "Subscriber", configurable: true,
163
+ });
164
+
165
+ function normalizeObserver(observer) {
166
+ if (isCallable(observer)) return { next: observer };
167
+ if (observer && typeof observer === "object") return observer;
168
+ return {};
169
+ }
170
+
171
+ class Observable {
172
+ #subscribeCallback;
173
+
174
+ constructor(subscribeCallback) {
175
+ if (!isCallable(subscribeCallback)) {
176
+ throw new TypeError("Observable constructor requires a callback function");
177
+ }
178
+ this.#subscribeCallback = subscribeCallback;
179
+ }
180
+
181
+ // Public subscribe(). observer may be a next-callback, an observer object,
182
+ // or omitted. options may carry an AbortSignal.
183
+ subscribe(observer, options) {
184
+ this._subscribeWith(normalizeObserver(observer), options || {});
185
+ }
186
+
187
+ // Internal subscribe used by subscribe() and by operators. internalObserver
188
+ // is a plain {next?, error?, complete?}.
189
+ _subscribeWith(internalObserver, options) {
190
+ const subscriber = new Subscriber(kInternal, internalObserver);
191
+ const outer = options && options.signal;
192
+ if (outer) {
193
+ if (outer.aborted) {
194
+ subscriber._abortConsumer(outer.reason);
195
+ } else {
196
+ outer.addEventListener("abort", () => subscriber._abortConsumer(outer.reason),
197
+ { once: true });
198
+ }
199
+ }
200
+ try {
201
+ this.#subscribeCallback.call(undefined, subscriber);
202
+ } catch (e) {
203
+ subscriber.error(e);
204
+ }
205
+ return subscriber;
206
+ }
207
+
208
+ static from(value) {
209
+ if (value instanceof Observable) return value;
210
+ if (value === null || (typeof value !== "object" && typeof value !== "function")) {
211
+ throw new TypeError("Observable.from: value is not convertible to an Observable");
212
+ }
213
+
214
+ // Commit to a conversion by probing the protocol method (TC39 GetMethod:
215
+ // a present-but-not-callable @@asyncIterator/@@iterator is a TypeError,
216
+ // not a silent fall-through to the next branch). The method is re-read at
217
+ // subscribe time too — it is never cached.
218
+ if (getMethod(value, Symbol.asyncIterator) !== undefined) {
219
+ return new Observable((subscriber) => {
220
+ const method = getMethod(value, Symbol.asyncIterator);
221
+ if (method === undefined) { subscriber.error(new TypeError("@@asyncIterator was removed")); return; }
222
+ let iterator;
223
+ try { iterator = method.call(value); }
224
+ catch (e) { subscriber.error(e); return; }
225
+ subscriber.addTeardown(() => {
226
+ if (iterator && isCallable(iterator.return)) {
227
+ try { Promise.resolve(iterator.return()).then(undefined, () => {}); } catch (_e) {}
228
+ }
229
+ });
230
+ const pump = () => {
231
+ if (subscriber.signal.aborted) return;
232
+ let p;
233
+ try { p = iterator.next(); }
234
+ catch (e) { subscriber.error(e); return; }
235
+ Promise.resolve(p).then(
236
+ (result) => {
237
+ if (subscriber.signal.aborted) return;
238
+ if (result === null || typeof result !== "object") {
239
+ subscriber.error(new TypeError("Iterator result is not an object"));
240
+ return;
241
+ }
242
+ if (result.done) { subscriber.complete(); return; }
243
+ subscriber.next(result.value);
244
+ pump();
245
+ },
246
+ (e) => subscriber.error(e),
247
+ );
248
+ };
249
+ pump();
250
+ });
251
+ }
252
+
253
+ if (getMethod(value, Symbol.iterator) !== undefined) {
254
+ return new Observable((subscriber) => {
255
+ let method;
256
+ try { method = getMethod(value, Symbol.iterator); }
257
+ catch (e) { subscriber.error(e); return; }
258
+ if (method === undefined) { subscriber.error(new TypeError("@@iterator was removed")); return; }
259
+ let iterator;
260
+ try { iterator = method.call(value); }
261
+ catch (e) { subscriber.error(e); return; }
262
+ subscriber.addTeardown(() => {
263
+ if (iterator && isCallable(iterator.return)) {
264
+ try { iterator.return(); } catch (_e) {}
265
+ }
266
+ });
267
+ while (true) {
268
+ if (subscriber.signal.aborted) return;
269
+ let result;
270
+ try { result = iterator.next(); }
271
+ catch (e) { subscriber.error(e); return; }
272
+ if (result === null || typeof result !== "object") {
273
+ subscriber.error(new TypeError("Iterator result is not an object"));
274
+ return;
275
+ }
276
+ if (result.done) { subscriber.complete(); return; }
277
+ subscriber.next(result.value);
278
+ }
279
+ });
280
+ }
281
+
282
+ if (isCallable(value.then)) {
283
+ return new Observable((subscriber) => {
284
+ Promise.resolve(value).then(
285
+ (v) => { subscriber.next(v); subscriber.complete(); },
286
+ (e) => subscriber.error(e),
287
+ );
288
+ });
289
+ }
290
+
291
+ throw new TypeError("Observable.from: value is not convertible to an Observable");
292
+ }
293
+
294
+ // ---- transform operators (return an Observable) ----
295
+
296
+ map(mapper) {
297
+ if (!isCallable(mapper)) throw new TypeError("map: mapper must be a function");
298
+ const source = this;
299
+ return new Observable((subscriber) => {
300
+ let index = 0;
301
+ source._subscribeWith({
302
+ next: (value) => {
303
+ let mapped;
304
+ try { mapped = mapper(value, index++); }
305
+ catch (e) { subscriber.error(e); return; }
306
+ subscriber.next(mapped);
307
+ },
308
+ error: (e) => subscriber.error(e),
309
+ complete: () => subscriber.complete(),
310
+ }, { signal: subscriber.signal });
311
+ });
312
+ }
313
+
314
+ filter(predicate) {
315
+ if (!isCallable(predicate)) throw new TypeError("filter: predicate must be a function");
316
+ const source = this;
317
+ return new Observable((subscriber) => {
318
+ let index = 0;
319
+ source._subscribeWith({
320
+ next: (value) => {
321
+ let keep;
322
+ try { keep = predicate(value, index++); }
323
+ catch (e) { subscriber.error(e); return; }
324
+ if (keep) subscriber.next(value);
325
+ },
326
+ error: (e) => subscriber.error(e),
327
+ complete: () => subscriber.complete(),
328
+ }, { signal: subscriber.signal });
329
+ });
330
+ }
331
+
332
+ take(amount) {
333
+ amount = toUnsignedCount(amount);
334
+ const source = this;
335
+ return new Observable((subscriber) => {
336
+ if (amount === 0) { subscriber.complete(); return; }
337
+ let remaining = amount;
338
+ source._subscribeWith({
339
+ next: (value) => {
340
+ subscriber.next(value);
341
+ if (--remaining === 0) subscriber.complete();
342
+ },
343
+ error: (e) => subscriber.error(e),
344
+ complete: () => subscriber.complete(),
345
+ }, { signal: subscriber.signal });
346
+ });
347
+ }
348
+
349
+ drop(amount) {
350
+ amount = toUnsignedCount(amount);
351
+ const source = this;
352
+ return new Observable((subscriber) => {
353
+ let remaining = amount;
354
+ source._subscribeWith({
355
+ next: (value) => {
356
+ if (remaining > 0) { remaining--; return; }
357
+ subscriber.next(value);
358
+ },
359
+ error: (e) => subscriber.error(e),
360
+ complete: () => subscriber.complete(),
361
+ }, { signal: subscriber.signal });
362
+ });
363
+ }
364
+
365
+ flatMap(mapper) {
366
+ if (!isCallable(mapper)) throw new TypeError("flatMap: mapper must be a function");
367
+ const source = this;
368
+ return new Observable((subscriber) => {
369
+ let index = 0;
370
+ let outerComplete = false;
371
+ let active = 0;
372
+ const queue = [];
373
+ let subscribing = false;
374
+
375
+ const subscribeToInner = (value) => {
376
+ active++;
377
+ let inner;
378
+ try { inner = Observable.from(mapper(value, index++)); }
379
+ catch (e) { subscriber.error(e); return; }
380
+ inner._subscribeWith({
381
+ next: (v) => subscriber.next(v),
382
+ error: (e) => subscriber.error(e),
383
+ complete: () => {
384
+ active--;
385
+ if (queue.length > 0) {
386
+ subscribeToInner(queue.shift());
387
+ } else if (outerComplete && active === 0) {
388
+ subscriber.complete();
389
+ }
390
+ },
391
+ }, { signal: subscriber.signal });
392
+ };
393
+
394
+ source._subscribeWith({
395
+ next: (value) => {
396
+ if (active > 0) queue.push(value);
397
+ else subscribeToInner(value);
398
+ },
399
+ error: (e) => subscriber.error(e),
400
+ complete: () => {
401
+ outerComplete = true;
402
+ if (active === 0 && queue.length === 0) subscriber.complete();
403
+ },
404
+ }, { signal: subscriber.signal });
405
+ });
406
+ }
407
+
408
+ switchMap(mapper) {
409
+ if (!isCallable(mapper)) throw new TypeError("switchMap: mapper must be a function");
410
+ const source = this;
411
+ return new Observable((subscriber) => {
412
+ let index = 0;
413
+ let outerComplete = false;
414
+ let innerController = null;
415
+ let innerActive = false;
416
+
417
+ const startInner = (value) => {
418
+ if (innerController) innerController.abort();
419
+ innerController = new AbortController();
420
+ innerActive = true;
421
+ let inner;
422
+ try { inner = Observable.from(mapper(value, index++)); }
423
+ catch (e) { subscriber.error(e); return; }
424
+ inner._subscribeWith({
425
+ next: (v) => subscriber.next(v),
426
+ error: (e) => subscriber.error(e),
427
+ complete: () => {
428
+ innerActive = false;
429
+ if (outerComplete) subscriber.complete();
430
+ },
431
+ }, { signal: AbortSignal.any([subscriber.signal, innerController.signal]) });
432
+ };
433
+
434
+ source._subscribeWith({
435
+ next: (value) => startInner(value),
436
+ error: (e) => subscriber.error(e),
437
+ complete: () => {
438
+ outerComplete = true;
439
+ if (!innerActive) subscriber.complete();
440
+ },
441
+ }, { signal: subscriber.signal });
442
+ });
443
+ }
444
+
445
+ takeUntil(notifier) {
446
+ const source = this;
447
+ return new Observable((subscriber) => {
448
+ const notifierObs = Observable.from(notifier);
449
+ // The notifier's first next() OR error() completes the subscriber (the
450
+ // error is NOT mirrored); the notifier completing is a no-op.
451
+ notifierObs._subscribeWith({
452
+ next: () => subscriber.complete(),
453
+ error: () => subscriber.complete(),
454
+ complete: () => {},
455
+ }, { signal: subscriber.signal });
456
+ if (subscriber.signal.aborted) return;
457
+ source._subscribeWith({
458
+ next: (v) => subscriber.next(v),
459
+ error: (e) => subscriber.error(e),
460
+ complete: () => subscriber.complete(),
461
+ }, { signal: subscriber.signal });
462
+ });
463
+ }
464
+
465
+ catch(handler) {
466
+ if (!isCallable(handler)) throw new TypeError("catch: handler must be a function");
467
+ const source = this;
468
+ return new Observable((subscriber) => {
469
+ source._subscribeWith({
470
+ next: (v) => subscriber.next(v),
471
+ error: (err) => {
472
+ let next;
473
+ try { next = Observable.from(handler(err)); }
474
+ catch (e) { subscriber.error(e); return; }
475
+ next._subscribeWith({
476
+ next: (v) => subscriber.next(v),
477
+ error: (e) => subscriber.error(e),
478
+ complete: () => subscriber.complete(),
479
+ }, { signal: subscriber.signal });
480
+ },
481
+ complete: () => subscriber.complete(),
482
+ }, { signal: subscriber.signal });
483
+ });
484
+ }
485
+
486
+ finally(callback) {
487
+ if (!isCallable(callback)) throw new TypeError("finally: callback must be a function");
488
+ const source = this;
489
+ return new Observable((subscriber) => {
490
+ subscriber.addTeardown(() => callback());
491
+ source._subscribeWith({
492
+ next: (v) => subscriber.next(v),
493
+ error: (e) => subscriber.error(e),
494
+ complete: () => subscriber.complete(),
495
+ }, { signal: subscriber.signal });
496
+ });
497
+ }
498
+
499
+ inspect(inspector) {
500
+ const source = this;
501
+ const cfg = isCallable(inspector) ? { next: inspector } : (inspector || {});
502
+ return new Observable((subscriber) => {
503
+ try { if (isCallable(cfg.subscribe)) cfg.subscribe(); }
504
+ catch (e) { subscriber.error(e); return; }
505
+ if (isCallable(cfg.abort)) {
506
+ subscriber.signal.addEventListener("abort", () => {
507
+ try { cfg.abort(subscriber.signal.reason); } catch (_e) {}
508
+ }, { once: true });
509
+ }
510
+ source._subscribeWith({
511
+ next: (v) => {
512
+ try { if (isCallable(cfg.next)) cfg.next(v); }
513
+ catch (e) { subscriber.error(e); return; }
514
+ subscriber.next(v);
515
+ },
516
+ error: (e) => {
517
+ try { if (isCallable(cfg.error)) cfg.error(e); } catch (_e) {}
518
+ subscriber.error(e);
519
+ },
520
+ complete: () => {
521
+ try { if (isCallable(cfg.complete)) cfg.complete(); }
522
+ catch (e) { subscriber.error(e); return; }
523
+ subscriber.complete();
524
+ },
525
+ }, { signal: subscriber.signal });
526
+ });
527
+ }
528
+
529
+ // ---- promise-returning operators ----
530
+
531
+ toArray(options) {
532
+ const source = this;
533
+ return new Promise((resolve, reject) => {
534
+ const controller = new AbortController();
535
+ const signal = consumerSignal(options, controller);
536
+ if (signal.aborted) { reject(signal.reason); return; }
537
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
538
+ const values = [];
539
+ source._subscribeWith({
540
+ next: (v) => values.push(v),
541
+ error: (e) => reject(e),
542
+ complete: () => resolve(values),
543
+ }, { signal });
544
+ });
545
+ }
546
+
547
+ forEach(callback, options) {
548
+ const source = this;
549
+ return new Promise((resolve, reject) => {
550
+ if (!isCallable(callback)) { reject(new TypeError("forEach: callback must be a function")); return; }
551
+ const controller = new AbortController();
552
+ const signal = consumerSignal(options, controller);
553
+ if (signal.aborted) { reject(signal.reason); return; }
554
+ // Per spec the returned promise rejects when the (consumer) signal is
555
+ // aborted; the reject is queued before the subscriber's own teardown
556
+ // abort fires, giving the documented microtask ordering.
557
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
558
+ let index = 0;
559
+ source._subscribeWith({
560
+ next: (v) => {
561
+ try { callback(v, index++); }
562
+ catch (e) { reject(e); controller.abort(e); }
563
+ },
564
+ error: (e) => reject(e),
565
+ complete: () => resolve(undefined),
566
+ }, { signal });
567
+ });
568
+ }
569
+
570
+ first(options) {
571
+ const source = this;
572
+ return new Promise((resolve, reject) => {
573
+ const controller = new AbortController();
574
+ const signal = consumerSignal(options, controller);
575
+ if (signal.aborted) { reject(signal.reason); return; }
576
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
577
+ source._subscribeWith({
578
+ next: (v) => { resolve(v); controller.abort(); },
579
+ error: (e) => reject(e),
580
+ complete: () => reject(new RangeError("first(): source completed without emitting a value")),
581
+ }, { signal });
582
+ });
583
+ }
584
+
585
+ last(options) {
586
+ const source = this;
587
+ return new Promise((resolve, reject) => {
588
+ const controller = new AbortController();
589
+ const signal = consumerSignal(options, controller);
590
+ if (signal.aborted) { reject(signal.reason); return; }
591
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
592
+ let has = false; let lastValue;
593
+ source._subscribeWith({
594
+ next: (v) => { has = true; lastValue = v; },
595
+ error: (e) => reject(e),
596
+ complete: () => {
597
+ if (has) resolve(lastValue);
598
+ else reject(new RangeError("last(): source completed without emitting a value"));
599
+ },
600
+ }, { signal });
601
+ });
602
+ }
603
+
604
+ find(predicate, options) {
605
+ const source = this;
606
+ return new Promise((resolve, reject) => {
607
+ if (!isCallable(predicate)) { reject(new TypeError("find: predicate must be a function")); return; }
608
+ const controller = new AbortController();
609
+ const signal = consumerSignal(options, controller);
610
+ if (signal.aborted) { reject(signal.reason); return; }
611
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
612
+ let index = 0;
613
+ source._subscribeWith({
614
+ next: (v) => {
615
+ let matched;
616
+ try { matched = predicate(v, index++); }
617
+ catch (e) { reject(e); controller.abort(); return; }
618
+ if (matched) { resolve(v); controller.abort(); }
619
+ },
620
+ error: (e) => reject(e),
621
+ complete: () => resolve(undefined),
622
+ }, { signal });
623
+ });
624
+ }
625
+
626
+ some(predicate, options) {
627
+ const source = this;
628
+ return new Promise((resolve, reject) => {
629
+ if (!isCallable(predicate)) { reject(new TypeError("some: predicate must be a function")); return; }
630
+ const controller = new AbortController();
631
+ const signal = consumerSignal(options, controller);
632
+ if (signal.aborted) { reject(signal.reason); return; }
633
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
634
+ let index = 0;
635
+ source._subscribeWith({
636
+ next: (v) => {
637
+ let matched;
638
+ try { matched = predicate(v, index++); }
639
+ catch (e) { reject(e); controller.abort(); return; }
640
+ if (matched) { resolve(true); controller.abort(); }
641
+ },
642
+ error: (e) => reject(e),
643
+ complete: () => resolve(false),
644
+ }, { signal });
645
+ });
646
+ }
647
+
648
+ every(predicate, options) {
649
+ const source = this;
650
+ return new Promise((resolve, reject) => {
651
+ if (!isCallable(predicate)) { reject(new TypeError("every: predicate must be a function")); return; }
652
+ const controller = new AbortController();
653
+ const signal = consumerSignal(options, controller);
654
+ if (signal.aborted) { reject(signal.reason); return; }
655
+ signal.addEventListener("abort", () => reject(signal.reason), { once: true });
656
+ let index = 0;
657
+ source._subscribeWith({
658
+ next: (v) => {
659
+ let matched;
660
+ try { matched = predicate(v, index++); }
661
+ catch (e) { reject(e); controller.abort(); return; }
662
+ if (!matched) { resolve(false); controller.abort(); }
663
+ },
664
+ error: (e) => reject(e),
665
+ complete: () => resolve(true),
666
+ }, { signal });
667
+ });
668
+ }
669
+
670
+ reduce(reducer, initialValue) {
671
+ const source = this;
672
+ const hasInitial = arguments.length >= 2;
673
+ // The options bag is not part of reduce(reducer, initialValue); signal
674
+ // support is omitted to keep the 2-arg contract.
675
+ return new Promise((resolve, reject) => {
676
+ if (!isCallable(reducer)) { reject(new TypeError("reduce: reducer must be a function")); return; }
677
+ let acc = initialValue;
678
+ let hasAcc = hasInitial;
679
+ let index = 0;
680
+ source._subscribeWith({
681
+ next: (v) => {
682
+ if (!hasAcc) { acc = v; hasAcc = true; index++; return; }
683
+ try { acc = reducer(acc, v, index++); }
684
+ catch (e) { reject(e); }
685
+ },
686
+ error: (e) => reject(e),
687
+ complete: () => {
688
+ if (!hasAcc) reject(new TypeError("reduce: no values and no initial value"));
689
+ else resolve(acc);
690
+ },
691
+ }, {});
692
+ });
693
+ }
694
+ }
695
+
696
+ // The signal a promise-returning operator subscribes with: a fresh controller
697
+ // (so the operator can unsubscribe on resolve) merged with the caller's signal.
698
+ function consumerSignal(options, controller) {
699
+ const outer = options && options.signal;
700
+ return outer ? AbortSignal.any([outer, controller.signal]) : controller.signal;
701
+ }
702
+
703
+ Object.defineProperty(Observable.prototype, Symbol.toStringTag, {
704
+ value: "Observable", configurable: true,
705
+ });
706
+
707
+ globalThis.Observable = Observable;
708
+ globalThis.Subscriber = Subscriber;
709
+
710
+ // EventTarget.prototype.when(type, options) → Observable of events.
711
+ if (typeof globalThis.EventTarget === "function") {
712
+ Object.defineProperty(EventTarget.prototype, "when", {
713
+ configurable: true, writable: true,
714
+ value: function when(type, options) {
715
+ const target = this;
716
+ const opts = options || {};
717
+ return new Observable((subscriber) => {
718
+ const handler = (event) => subscriber.next(event);
719
+ target.addEventListener(type, handler, {
720
+ signal: subscriber.signal,
721
+ capture: !!opts.capture,
722
+ passive: opts.passive,
723
+ });
724
+ });
725
+ },
726
+ });
727
+ }
728
+ })();