reactor-core-ts 3.2.2 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/core/demand.d.ts +4 -0
- package/dist/core/demand.d.ts.map +1 -1
- package/dist/core/demand.js +12 -4
- package/dist/core/demand.js.map +1 -1
- package/dist/internal/deep-value.d.ts +9 -0
- package/dist/internal/deep-value.d.ts.map +1 -0
- package/dist/internal/deep-value.js +159 -0
- package/dist/internal/deep-value.js.map +1 -0
- package/dist/internal/iterable-transform.d.ts +8 -1
- package/dist/internal/iterable-transform.d.ts.map +1 -1
- package/dist/internal/iterable-transform.js +7 -5
- package/dist/internal/iterable-transform.js.map +1 -1
- package/dist/internal/iteration-demand.d.ts +18 -0
- package/dist/internal/iteration-demand.d.ts.map +1 -0
- package/dist/internal/iteration-demand.js +34 -0
- package/dist/internal/iteration-demand.js.map +1 -0
- package/dist/internal/publisher-terminal.d.ts +25 -0
- package/dist/internal/publisher-terminal.d.ts.map +1 -0
- package/dist/internal/publisher-terminal.js +128 -0
- package/dist/internal/publisher-terminal.js.map +1 -0
- package/dist/publisher/flux.d.ts.map +1 -1
- package/dist/publisher/flux.js +22 -12
- package/dist/publisher/flux.js.map +1 -1
- package/dist/publisher/mono.d.ts.map +1 -1
- package/dist/publisher/mono.js +2 -1
- package/dist/publisher/mono.js.map +1 -1
- package/dist/publisher/operators/aggregate.d.ts.map +1 -1
- package/dist/publisher/operators/aggregate.js +136 -143
- package/dist/publisher/operators/aggregate.js.map +1 -1
- package/dist/publisher/operators/buffer-lift.d.ts +5 -0
- package/dist/publisher/operators/buffer-lift.d.ts.map +1 -0
- package/dist/publisher/operators/buffer-lift.js +197 -0
- package/dist/publisher/operators/buffer-lift.js.map +1 -0
- package/dist/publisher/operators/compat/flux.d.ts.map +1 -1
- package/dist/publisher/operators/compat/flux.js +86 -35
- package/dist/publisher/operators/compat/flux.js.map +1 -1
- package/dist/publisher/operators/coordination.d.ts.map +1 -1
- package/dist/publisher/operators/coordination.js +3 -4
- package/dist/publisher/operators/coordination.js.map +1 -1
- package/dist/publisher/operators/lifecycle.d.ts.map +1 -1
- package/dist/publisher/operators/lifecycle.js +64 -21
- package/dist/publisher/operators/lifecycle.js.map +1 -1
- package/dist/publisher/operators/lift.d.ts +2 -0
- package/dist/publisher/operators/lift.d.ts.map +1 -1
- package/dist/publisher/operators/lift.js +173 -3
- package/dist/publisher/operators/lift.js.map +1 -1
- package/dist/publisher/operators/selection.d.ts +5 -0
- package/dist/publisher/operators/selection.d.ts.map +1 -1
- package/dist/publisher/operators/selection.js +11 -2
- package/dist/publisher/operators/selection.js.map +1 -1
- package/dist/publisher/operators/terminal-mono.d.ts +12 -0
- package/dist/publisher/operators/terminal-mono.d.ts.map +1 -0
- package/dist/publisher/operators/terminal-mono.js +244 -0
- package/dist/publisher/operators/terminal-mono.js.map +1 -0
- package/dist/publisher/operators/terminal.d.ts.map +1 -1
- package/dist/publisher/operators/terminal.js +12 -25
- package/dist/publisher/operators/terminal.js.map +1 -1
- package/dist/publisher/operators/time.d.ts.map +1 -1
- package/dist/publisher/operators/time.js +2 -0
- package/dist/publisher/operators/time.js.map +1 -1
- package/dist/subscription/iterable-subscription.d.ts.map +1 -1
- package/dist/subscription/iterable-subscription.js +5 -2
- package/dist/subscription/iterable-subscription.js.map +1 -1
- package/package.json +1 -1
- package/dist/internal/iterable-terminal.d.ts +0 -12
- package/dist/internal/iterable-terminal.d.ts.map +0 -1
- package/dist/internal/iterable-terminal.js +0 -49
- package/dist/internal/iterable-terminal.js.map +0 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import _defineProperty from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/defineProperty.js";
|
|
2
|
+
import { Context } from "../../context/context.js";
|
|
3
|
+
import { UNBOUNDED_DEMAND, normalizeRequest } from "../../core/demand.js";
|
|
4
|
+
import { ITERATION_DEMAND_HINT, iterationDemandHint } from "../../internal/iteration-demand.js";
|
|
5
|
+
import { consumePublisher } from "../../internal/publisher-terminal.js";
|
|
6
|
+
import { Mono } from "../mono.js";
|
|
7
|
+
//#region src/publisher/operators/terminal-mono.ts
|
|
8
|
+
/**
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
* Direct terminal Mono implementation shared by aggregating operators.
|
|
11
|
+
*/
|
|
12
|
+
/** Sentinel returned by a terminal collector when its Mono must complete empty. */
|
|
13
|
+
var NO_TERMINAL_VALUE = Symbol("no-terminal-value");
|
|
14
|
+
/** Creates a Mono that reduces Publisher signals on the native demand path. */
|
|
15
|
+
function terminalMono(source, upstreamRequest, collectorFactory) {
|
|
16
|
+
return new DirectTerminalMono(source, upstreamRequest, collectorFactory);
|
|
17
|
+
}
|
|
18
|
+
/** Mono whose subscribe and iteration paths both consume the source directly. */
|
|
19
|
+
var DirectTerminalMono = class extends Mono {
|
|
20
|
+
/** Creates a direct terminal Mono around one source. */
|
|
21
|
+
constructor(source, upstreamRequest, collectorFactory) {
|
|
22
|
+
super(async function* (signal, context) {
|
|
23
|
+
if (signal.aborted) return;
|
|
24
|
+
const result = await consumePublisher(source, signal, context, upstreamRequest, collectorFactory());
|
|
25
|
+
if (result !== NO_TERMINAL_VALUE) yield result;
|
|
26
|
+
});
|
|
27
|
+
_defineProperty(this, "source", void 0);
|
|
28
|
+
_defineProperty(this, "upstreamRequest", void 0);
|
|
29
|
+
_defineProperty(this, "collectorFactory", void 0);
|
|
30
|
+
this.source = source;
|
|
31
|
+
this.upstreamRequest = upstreamRequest;
|
|
32
|
+
this.collectorFactory = collectorFactory;
|
|
33
|
+
}
|
|
34
|
+
/** Installs a subscriber that waits for downstream demand before requesting upstream. */
|
|
35
|
+
subscribeActual(subscriber) {
|
|
36
|
+
new TerminalMonoSubscriber(subscriber, this.upstreamRequest, this.collectorFactory).start(this.source);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
/** Subscriber/subscription pair that reduces a Flux to at most one value. */
|
|
40
|
+
var TerminalMonoSubscriber = class {
|
|
41
|
+
/** Creates a terminal subscriber for one downstream subscriber. */
|
|
42
|
+
constructor(actual, upstreamRequest, collectorFactory) {
|
|
43
|
+
_defineProperty(this, "actual", void 0);
|
|
44
|
+
_defineProperty(this, "upstreamRequest", void 0);
|
|
45
|
+
_defineProperty(this, "collectorFactory", void 0);
|
|
46
|
+
_defineProperty(
|
|
47
|
+
this,
|
|
48
|
+
/** Active upstream subscription. */
|
|
49
|
+
"upstream",
|
|
50
|
+
void 0
|
|
51
|
+
);
|
|
52
|
+
_defineProperty(
|
|
53
|
+
this,
|
|
54
|
+
/** Collector created lazily on the first valid downstream request. */
|
|
55
|
+
"collector",
|
|
56
|
+
void 0
|
|
57
|
+
);
|
|
58
|
+
_defineProperty(
|
|
59
|
+
this,
|
|
60
|
+
/** Tracks the upstream Reactive Streams handshake. */
|
|
61
|
+
"subscribed",
|
|
62
|
+
false
|
|
63
|
+
);
|
|
64
|
+
_defineProperty(
|
|
65
|
+
this,
|
|
66
|
+
/** Ensures upstream is requested at most once. */
|
|
67
|
+
"requested",
|
|
68
|
+
false
|
|
69
|
+
);
|
|
70
|
+
_defineProperty(
|
|
71
|
+
this,
|
|
72
|
+
/** Records completion that arrived before downstream demand. */
|
|
73
|
+
"completedBeforeRequest",
|
|
74
|
+
false
|
|
75
|
+
);
|
|
76
|
+
_defineProperty(
|
|
77
|
+
this,
|
|
78
|
+
/** Guards the downstream result callback against reentrant upstream signals. */
|
|
79
|
+
"emitting",
|
|
80
|
+
false
|
|
81
|
+
);
|
|
82
|
+
_defineProperty(
|
|
83
|
+
this,
|
|
84
|
+
/** Ensures the active upstream is cancelled at most once. */
|
|
85
|
+
"upstreamCancelled",
|
|
86
|
+
false
|
|
87
|
+
);
|
|
88
|
+
_defineProperty(
|
|
89
|
+
this,
|
|
90
|
+
/** Suppresses signals after cancellation or termination. */
|
|
91
|
+
"terminated",
|
|
92
|
+
false
|
|
93
|
+
);
|
|
94
|
+
this.actual = actual;
|
|
95
|
+
this.upstreamRequest = upstreamRequest;
|
|
96
|
+
this.collectorFactory = collectorFactory;
|
|
97
|
+
}
|
|
98
|
+
/** Subscribes this terminal reducer to its source with handshake error recovery. */
|
|
99
|
+
start(source) {
|
|
100
|
+
try {
|
|
101
|
+
source.subscribe(this);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
if (this.terminated) throw error;
|
|
104
|
+
if (!this.subscribed && !this.terminated) {
|
|
105
|
+
this.subscribed = true;
|
|
106
|
+
this.actual.onSubscribe(this);
|
|
107
|
+
}
|
|
108
|
+
this.onError(error);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Stores the upstream and exposes this demand-gating subscription downstream. */
|
|
112
|
+
onSubscribe(subscription) {
|
|
113
|
+
if (this.subscribed || this.terminated) {
|
|
114
|
+
cancelSilently(subscription);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.subscribed = true;
|
|
118
|
+
this.upstream = subscription;
|
|
119
|
+
try {
|
|
120
|
+
this.actual.onSubscribe(this);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
this.terminated = true;
|
|
123
|
+
this.cancelUpstream();
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** Reduces a value and emits the result immediately when it becomes final. */
|
|
128
|
+
onNext(value) {
|
|
129
|
+
if (this.terminated || this.emitting || !this.requested || !this.collector) return;
|
|
130
|
+
try {
|
|
131
|
+
if (this.collector.onNext(value)) this.emitResult(true);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.fail(error, true);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Forwards the first upstream failure without waiting for demand. */
|
|
137
|
+
onError(error) {
|
|
138
|
+
if (this.emitting) return;
|
|
139
|
+
this.fail(error, false);
|
|
140
|
+
}
|
|
141
|
+
/** Emits the reduced result, or remembers completion until demand arrives. */
|
|
142
|
+
onComplete() {
|
|
143
|
+
if (this.terminated || this.emitting) return;
|
|
144
|
+
if (!this.requested) {
|
|
145
|
+
this.completedBeforeRequest = true;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
this.emitResult(false);
|
|
149
|
+
}
|
|
150
|
+
/** Starts the single upstream terminal batch on the first valid request. */
|
|
151
|
+
request(n) {
|
|
152
|
+
if (this.terminated) return;
|
|
153
|
+
try {
|
|
154
|
+
normalizeRequest(n);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
this.fail(error, true);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (this.requested) return;
|
|
160
|
+
this.requested = true;
|
|
161
|
+
try {
|
|
162
|
+
this.collector = this.collectorFactory();
|
|
163
|
+
} catch (error) {
|
|
164
|
+
this.fail(error, true);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (this.completedBeforeRequest) {
|
|
168
|
+
this.emitResult(false);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
this.upstream?.request(this.upstreamRequest);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
this.fail(error, true);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Cancels the source and releases the collector state. */
|
|
178
|
+
cancel() {
|
|
179
|
+
if (this.terminated) return;
|
|
180
|
+
this.terminated = true;
|
|
181
|
+
this.collector = void 0;
|
|
182
|
+
this.cancelUpstream();
|
|
183
|
+
}
|
|
184
|
+
/** Exposes the downstream Reactor context to the source. */
|
|
185
|
+
currentContext() {
|
|
186
|
+
return this.actual.currentContext?.() ?? Context.empty();
|
|
187
|
+
}
|
|
188
|
+
/** Propagates a guaranteed downstream batch to eagerly assembled iterable sources. */
|
|
189
|
+
[ITERATION_DEMAND_HINT]() {
|
|
190
|
+
return iterationDemandHint(this.actual) === UNBOUNDED_DEMAND ? this.upstreamRequest : void 0;
|
|
191
|
+
}
|
|
192
|
+
/** Produces and emits the terminal result, cancelling upstream for early results. */
|
|
193
|
+
emitResult(cancelUpstream) {
|
|
194
|
+
if (this.terminated || !this.collector) return;
|
|
195
|
+
let result;
|
|
196
|
+
try {
|
|
197
|
+
result = this.collector.result();
|
|
198
|
+
} catch (error) {
|
|
199
|
+
this.fail(error, cancelUpstream);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this.collector = void 0;
|
|
203
|
+
this.emitting = true;
|
|
204
|
+
if (cancelUpstream) this.cancelUpstream();
|
|
205
|
+
if (result !== NO_TERMINAL_VALUE) try {
|
|
206
|
+
this.actual.onNext(result);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.emitting = false;
|
|
209
|
+
if (this.terminated) return;
|
|
210
|
+
this.terminated = true;
|
|
211
|
+
this.cancelUpstream();
|
|
212
|
+
this.actual.onError(error);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
this.emitting = false;
|
|
216
|
+
if (this.terminated) return;
|
|
217
|
+
this.terminated = true;
|
|
218
|
+
this.actual.onComplete();
|
|
219
|
+
}
|
|
220
|
+
/** Cancels when requested and forwards one terminal failure. */
|
|
221
|
+
fail(error, cancelUpstream) {
|
|
222
|
+
if (this.terminated) return;
|
|
223
|
+
this.terminated = true;
|
|
224
|
+
this.collector = void 0;
|
|
225
|
+
if (cancelUpstream) this.cancelUpstream();
|
|
226
|
+
this.actual.onError(error);
|
|
227
|
+
}
|
|
228
|
+
/** Cancels the active upstream at most once. */
|
|
229
|
+
cancelUpstream() {
|
|
230
|
+
if (this.upstreamCancelled) return;
|
|
231
|
+
this.upstreamCancelled = true;
|
|
232
|
+
if (this.upstream) cancelSilently(this.upstream);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
/** Cancels a subscription without replacing the active terminal signal. */
|
|
236
|
+
function cancelSilently(subscription) {
|
|
237
|
+
try {
|
|
238
|
+
subscription.cancel();
|
|
239
|
+
} catch {}
|
|
240
|
+
}
|
|
241
|
+
//#endregion
|
|
242
|
+
export { NO_TERMINAL_VALUE, terminalMono };
|
|
243
|
+
|
|
244
|
+
//# sourceMappingURL=terminal-mono.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-mono.js","names":[],"sources":["../../../src/publisher/operators/terminal-mono.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Direct terminal Mono implementation shared by aggregating operators.\n */\nimport {Context} from \"@/context/context.js\";\nimport {normalizeRequest, UNBOUNDED_DEMAND} from \"@/core/demand.js\";\nimport {ITERATION_DEMAND_HINT, iterationDemandHint} from \"@/internal/iteration-demand.js\";\nimport {consumePublisher, type TerminalCollector} from \"@/internal/publisher-terminal.js\";\nimport {Flux} from \"@/publisher/flux.js\";\nimport {Mono} from \"@/publisher/mono.js\";\nimport type {CoreSubscriber} from \"@/subscription/core-subscriber.js\";\nimport type {Subscriber} from \"@/subscription/subscriber.js\";\nimport type {Subscription} from \"@/subscription/subscription.js\";\n\n/** Sentinel returned by a terminal collector when its Mono must complete empty. */\nexport const NO_TERMINAL_VALUE = Symbol(\"no-terminal-value\");\n\n/** Result produced by a terminal collector, including empty Mono completion. */\nexport type TerminalValue<T> = T | typeof NO_TERMINAL_VALUE;\n\n/** Creates fresh terminal reduction state for each subscription. */\nexport type TerminalCollectorFactory<T, R> = () => TerminalCollector<T, TerminalValue<R>>;\n\n/** Creates a Mono that reduces Publisher signals on the native demand path. */\nexport function terminalMono<T, R>(\n source: Flux<T>,\n upstreamRequest: number,\n collectorFactory: TerminalCollectorFactory<T, R>\n): Mono<R> {\n return new DirectTerminalMono(source, upstreamRequest, collectorFactory);\n}\n\n/** Mono whose subscribe and iteration paths both consume the source directly. */\nclass DirectTerminalMono<T, R> extends Mono<R> {\n /** Creates a direct terminal Mono around one source. */\n public constructor(\n private readonly source: Flux<T>,\n private readonly upstreamRequest: number,\n private readonly collectorFactory: TerminalCollectorFactory<T, R>\n ) {\n super(async function* (signal, context) {\n if (signal.aborted) {\n return;\n }\n const result = await consumePublisher(source, signal, context, upstreamRequest, collectorFactory());\n if (result !== NO_TERMINAL_VALUE) {\n yield result as R;\n }\n });\n }\n\n /** Installs a subscriber that waits for downstream demand before requesting upstream. */\n protected override subscribeActual(subscriber: Subscriber<R>): void {\n new TerminalMonoSubscriber(subscriber, this.upstreamRequest, this.collectorFactory).start(this.source);\n }\n}\n\n/** Subscriber/subscription pair that reduces a Flux to at most one value. */\nclass TerminalMonoSubscriber<T, R> implements CoreSubscriber<T>, Subscription {\n /** Active upstream subscription. */\n private upstream: Subscription | undefined;\n /** Collector created lazily on the first valid downstream request. */\n private collector: TerminalCollector<T, TerminalValue<R>> | undefined;\n /** Tracks the upstream Reactive Streams handshake. */\n private subscribed = false;\n /** Ensures upstream is requested at most once. */\n private requested = false;\n /** Records completion that arrived before downstream demand. */\n private completedBeforeRequest = false;\n /** Guards the downstream result callback against reentrant upstream signals. */\n private emitting = false;\n /** Ensures the active upstream is cancelled at most once. */\n private upstreamCancelled = false;\n /** Suppresses signals after cancellation or termination. */\n private terminated = false;\n\n /** Creates a terminal subscriber for one downstream subscriber. */\n public constructor(\n private readonly actual: Subscriber<R>,\n private readonly upstreamRequest: number,\n private readonly collectorFactory: TerminalCollectorFactory<T, R>\n ) {\n }\n\n /** Subscribes this terminal reducer to its source with handshake error recovery. */\n public start(source: Flux<T>): void {\n try {\n source.subscribe(this);\n } catch (error) {\n if (this.terminated) {\n throw error;\n }\n if (!this.subscribed && !this.terminated) {\n this.subscribed = true;\n this.actual.onSubscribe(this);\n }\n this.onError(error);\n }\n }\n\n /** Stores the upstream and exposes this demand-gating subscription downstream. */\n public onSubscribe(subscription: Subscription): void {\n if (this.subscribed || this.terminated) {\n cancelSilently(subscription);\n return;\n }\n this.subscribed = true;\n this.upstream = subscription;\n try {\n this.actual.onSubscribe(this);\n } catch (error) {\n this.terminated = true;\n this.cancelUpstream();\n throw error;\n }\n }\n\n /** Reduces a value and emits the result immediately when it becomes final. */\n public onNext(value: T): void {\n if (this.terminated || this.emitting || !this.requested || !this.collector) {\n return;\n }\n try {\n if (this.collector.onNext(value)) {\n this.emitResult(true);\n }\n } catch (error) {\n this.fail(error, true);\n }\n }\n\n /** Forwards the first upstream failure without waiting for demand. */\n public onError(error: unknown): void {\n if (this.emitting) {\n return;\n }\n this.fail(error, false);\n }\n\n /** Emits the reduced result, or remembers completion until demand arrives. */\n public onComplete(): void {\n if (this.terminated || this.emitting) {\n return;\n }\n if (!this.requested) {\n this.completedBeforeRequest = true;\n return;\n }\n this.emitResult(false);\n }\n\n /** Starts the single upstream terminal batch on the first valid request. */\n public request(n: number): void {\n if (this.terminated) {\n return;\n }\n try {\n normalizeRequest(n);\n } catch (error) {\n this.fail(error, true);\n return;\n }\n if (this.requested) {\n return;\n }\n this.requested = true;\n try {\n this.collector = this.collectorFactory();\n } catch (error) {\n this.fail(error, true);\n return;\n }\n if (this.completedBeforeRequest) {\n this.emitResult(false);\n return;\n }\n try {\n this.upstream?.request(this.upstreamRequest);\n } catch (error) {\n this.fail(error, true);\n }\n }\n\n /** Cancels the source and releases the collector state. */\n public cancel(): void {\n if (this.terminated) {\n return;\n }\n this.terminated = true;\n this.collector = undefined;\n this.cancelUpstream();\n }\n\n /** Exposes the downstream Reactor context to the source. */\n public currentContext(): Context {\n return (this.actual as CoreSubscriber<R>).currentContext?.() ?? Context.empty();\n }\n\n /** Propagates a guaranteed downstream batch to eagerly assembled iterable sources. */\n public [ITERATION_DEMAND_HINT](): number | undefined {\n return iterationDemandHint(this.actual) === UNBOUNDED_DEMAND\n ? this.upstreamRequest\n : undefined;\n }\n\n /** Produces and emits the terminal result, cancelling upstream for early results. */\n private emitResult(cancelUpstream: boolean): void {\n if (this.terminated || !this.collector) {\n return;\n }\n let result: TerminalValue<R>;\n try {\n result = this.collector.result();\n } catch (error) {\n this.fail(error, cancelUpstream);\n return;\n }\n this.collector = undefined;\n this.emitting = true;\n if (cancelUpstream) {\n this.cancelUpstream();\n }\n if (result !== NO_TERMINAL_VALUE) {\n try {\n this.actual.onNext(result as R);\n } catch (error) {\n this.emitting = false;\n if (this.terminated) {\n return;\n }\n this.terminated = true;\n this.cancelUpstream();\n this.actual.onError(error);\n return;\n }\n }\n this.emitting = false;\n if (this.terminated) {\n return;\n }\n this.terminated = true;\n this.actual.onComplete();\n }\n\n /** Cancels when requested and forwards one terminal failure. */\n private fail(error: unknown, cancelUpstream: boolean): void {\n if (this.terminated) {\n return;\n }\n this.terminated = true;\n this.collector = undefined;\n if (cancelUpstream) {\n this.cancelUpstream();\n }\n this.actual.onError(error);\n }\n\n /** Cancels the active upstream at most once. */\n private cancelUpstream(): void {\n if (this.upstreamCancelled) {\n return;\n }\n this.upstreamCancelled = true;\n if (this.upstream) {\n cancelSilently(this.upstream);\n }\n }\n}\n\n/** Cancels a subscription without replacing the active terminal signal. */\nfunction cancelSilently(subscription: Subscription): void {\n try {\n subscription.cancel();\n } catch {\n // Terminal state has already been selected.\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/publisher/operators/terminal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/publisher/operators/terminal.ts"],"names":[],"mappings":"AAOA,OAAO,EAAC,IAAI,EAAC,MAAM,qBAAqB,CAAC;AAEzC,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEzD,OAAO,QAAQ,qBAAqB,CAAC;IACjC,6DAA6D;IAC7D,UAAU,IAAI,CAAC,CAAC;QACZ,+EAA+E;QAC/E,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnB,4EAA4E;QAC5E,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAE/C,wEAAwE;QACxE,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEjC,wEAAwE;QACxE,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;KAC7G;CACJ"}
|
|
@@ -1,44 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UNBOUNDED_DEMAND } from "../../core/demand.js";
|
|
2
|
+
import { drainPublisher } from "../../internal/publisher-terminal.js";
|
|
2
3
|
import { Flux } from "../flux.js";
|
|
3
|
-
import {
|
|
4
|
+
import { NO_TERMINAL_VALUE, terminalMono } from "./terminal-mono.js";
|
|
4
5
|
//#region src/publisher/operators/terminal.ts
|
|
5
6
|
/**
|
|
6
7
|
* @packageDocumentation
|
|
7
8
|
* Flux, Mono and operator implementation modules.
|
|
8
9
|
*/
|
|
9
10
|
Flux.prototype.then = function then() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
});
|
|
11
|
+
return terminalMono(this, UNBOUNDED_DEMAND, () => ({
|
|
12
|
+
onNext: () => false,
|
|
13
|
+
result: () => NO_TERMINAL_VALUE
|
|
14
|
+
}));
|
|
15
15
|
};
|
|
16
16
|
Flux.prototype.thenMany = function thenMany(other) {
|
|
17
17
|
const source = this;
|
|
18
18
|
return new Flux(async function* (signal, context) {
|
|
19
|
-
|
|
19
|
+
await drainPublisher(source, signal, context);
|
|
20
20
|
for await (const value of Flux.from(other).iterate(signal, context)) yield value;
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
23
|
Flux.prototype.thenReturn = function thenReturn(value) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
24
|
+
return terminalMono(this, UNBOUNDED_DEMAND, () => ({
|
|
25
|
+
onNext: () => false,
|
|
26
|
+
result: () => value
|
|
27
|
+
}));
|
|
29
28
|
};
|
|
30
|
-
/** Drains a synchronous source and then emits one completion value. */
|
|
31
|
-
function drainThenEmitSync(values, value) {
|
|
32
|
-
return (function* () {
|
|
33
|
-
for (const _ of values);
|
|
34
|
-
yield value;
|
|
35
|
-
})();
|
|
36
|
-
}
|
|
37
|
-
/** Drains an asynchronous source and then emits one completion value. */
|
|
38
|
-
async function* drainThenEmitAsync(values, value) {
|
|
39
|
-
for await (const _ of values);
|
|
40
|
-
yield value;
|
|
41
|
-
}
|
|
42
29
|
Flux.prototype.zipWith = function zipWith(other, combinator) {
|
|
43
30
|
return Flux.zip([this, other], (values) => combinator ? combinator(values[0], values[1]) : [values[0], values[1]]);
|
|
44
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.js","names":[],"sources":["../../../src/publisher/operators/terminal.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Flux, Mono and operator implementation modules.\n */\nimport {Flux} from \"@/publisher/flux.js\";\nimport {Mono} from \"@/publisher/mono.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"terminal.js","names":[],"sources":["../../../src/publisher/operators/terminal.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Flux, Mono and operator implementation modules.\n */\nimport {UNBOUNDED_DEMAND} from \"@/core/demand.js\";\nimport {drainPublisher} from \"@/internal/publisher-terminal.js\";\nimport {Flux} from \"@/publisher/flux.js\";\nimport {Mono} from \"@/publisher/mono.js\";\nimport {NO_TERMINAL_VALUE, terminalMono} from \"@/publisher/operators/terminal-mono.js\";\nimport type {PublisherInput} from \"@/publisher/types.js\";\n\ndeclare module \"@/publisher/flux.js\" {\n /** Terminal continuation and zip operators added to Flux. */\n interface Flux<T> {\n /** Ignores all values and completes when the source completes successfully. */\n then(): Mono<void>;\n\n /** Waits for this source to complete and then emits values from `other`. */\n thenMany<R>(other: PublisherInput<R>): Flux<R>;\n\n /** Ignores all values and emits `value` after successful completion. */\n thenReturn<R>(value: R): Mono<R>;\n\n /** Zips this Flux with another publisher and combines paired values. */\n zipWith<U, R = readonly [T, U]>(other: PublisherInput<U>, combinator?: (left: T, right: U) => R): Flux<R>;\n }\n}\n\nFlux.prototype.then = function then<T>(this: Flux<T>): Mono<void> {\n return terminalMono<T, void>(this, UNBOUNDED_DEMAND, () => ({\n onNext: () => false,\n result: () => NO_TERMINAL_VALUE\n }));\n};\n\nFlux.prototype.thenMany = function thenMany<T, R>(this: Flux<T>, other: PublisherInput<R>): Flux<R> {\n const source = this;\n return new Flux(async function* (signal, context) {\n await drainPublisher(source, signal, context);\n for await (const value of Flux.from(other).iterate(signal, context)) {\n yield value;\n }\n });\n};\n\nFlux.prototype.thenReturn = function thenReturn<T, R>(this: Flux<T>, value: R): Mono<R> {\n return terminalMono(this, UNBOUNDED_DEMAND, () => ({\n onNext: () => false,\n result: () => value\n }));\n};\n\nFlux.prototype.zipWith = function zipWith<T, U, R = readonly [T, U]>(\n this: Flux<T>,\n other: PublisherInput<U>,\n combinator?: (left: T, right: U) => R\n): Flux<R> {\n return Flux.zip<[T, U], R>([this, other], values =>\n combinator ? combinator(values[0], values[1]) : ([values[0], values[1]] as const as R)\n );\n};\n"],"mappings":";;;;;;;;;AA4BA,KAAK,UAAU,OAAO,SAAS,OAAmC;CAC9D,OAAO,aAAsB,MAAM,yBAAyB;EACxD,cAAc;EACd,cAAc;CAClB,EAAE;AACN;AAEA,KAAK,UAAU,WAAW,SAAS,SAA8B,OAAmC;CAChG,MAAM,SAAS;CACf,OAAO,IAAI,KAAK,iBAAiB,QAAQ,SAAS;EAC9C,MAAM,eAAe,QAAQ,QAAQ,OAAO;EAC5C,WAAW,MAAM,SAAS,KAAK,KAAK,KAAK,CAAC,CAAC,QAAQ,QAAQ,OAAO,GAC9D,MAAM;CAEd,CAAC;AACL;AAEA,KAAK,UAAU,aAAa,SAAS,WAAgC,OAAmB;CACpF,OAAO,aAAa,MAAM,yBAAyB;EAC/C,cAAc;EACd,cAAc;CAClB,EAAE;AACN;AAEA,KAAK,UAAU,UAAU,SAAS,QAE9B,OACA,YACO;CACP,OAAO,KAAK,IAAe,CAAC,MAAM,KAAK,IAAG,WACtC,aAAa,WAAW,OAAO,IAAI,OAAO,EAAE,IAAK,CAAC,OAAO,IAAI,OAAO,EAAE,CAC1E;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../../src/publisher/operators/time.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../../src/publisher/operators/time.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAC,aAAa,EAAE,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEpE,OAAO,QAAQ,qBAAqB,CAAC;IACjC,4DAA4D;IAC5D,UAAU,IAAI,CAAC,CAAC;QACZ,6EAA6E;QAC7E,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpE,+EAA+E;QAC/E,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAE9F,4DAA4D;QAC5D,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzC,6DAA6D;QAC7D,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAE3C,8DAA8D;QAC9D,SAAS,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7D,sFAAsF;QACtF,OAAO,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;KAC9D;CACJ"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { toAsyncIterator } from "../../internal/iterable.js";
|
|
2
2
|
import { TimeoutError } from "../../errors/classes.js";
|
|
3
3
|
import { AsyncQueue } from "../../internal/async-queue.js";
|
|
4
|
+
import { inheritIterationDemand } from "../../internal/iteration-demand.js";
|
|
4
5
|
import { Schedulers } from "../../schedulers/schedulers.js";
|
|
5
6
|
import { TIMEOUT, raceIteratorWithTimeout, scheduleDelay } from "../helpers.js";
|
|
6
7
|
import { Flux } from "../flux.js";
|
|
@@ -22,6 +23,7 @@ Flux.prototype.timeout = function timeout(timeout, fallback, scheduler = Schedul
|
|
|
22
23
|
const source = this;
|
|
23
24
|
return new Flux(async function* (signal, context) {
|
|
24
25
|
const controller = new AbortController();
|
|
26
|
+
inheritIterationDemand(signal, controller.signal);
|
|
25
27
|
const abort = () => controller.abort();
|
|
26
28
|
signal.addEventListener("abort", abort, { once: true });
|
|
27
29
|
const iterator = toAsyncIterator(source.iterate(controller.signal, context));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.js","names":[],"sources":["../../../src/publisher/operators/time.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Flux, Mono and operator implementation modules.\n */\nimport {TimeoutError} from \"@/errors/classes.js\";\nimport {AsyncQueue} from \"@/internal/async-queue.js\";\nimport {toAsyncIterator} from \"@/internal/iterable.js\";\nimport {Flux} from \"@/publisher/flux.js\";\nimport {raceIteratorWithTimeout, scheduleDelay, TIMEOUT} from \"@/publisher/helpers.js\";\nimport type {PublisherInput} from \"@/publisher/types.js\";\nimport {Schedulers} from \"@/schedulers/schedulers.js\";\nimport type {DurationInput, Scheduler} from \"@/schedulers/types.js\";\n\ndeclare module \"@/publisher/flux.js\" {\n /** Time, scheduling and timeout operators added to Flux. */\n interface Flux<T> {\n /** Delays each source value on the provided scheduler before emitting it. */\n delayElements(delay: DurationInput, scheduler?: Scheduler): Flux<T>;\n\n /** Fails or switches to a fallback when the source does not signal in time. */\n timeout(timeout: DurationInput, fallback?: PublisherInput<T>, scheduler?: Scheduler): Flux<T>;\n\n /** Reschedules value delivery on the provided scheduler. */\n publishOn(scheduler: Scheduler): Flux<T>;\n\n /** Schedules subscription work on the provided scheduler. */\n subscribeOn(scheduler: Scheduler): Flux<T>;\n\n /** Emits each value together with the scheduler timestamp. */\n timestamp(scheduler?: Scheduler): Flux<readonly [number, T]>;\n\n /** Emits each value together with elapsed scheduler time since the previous value. */\n elapsed(scheduler?: Scheduler): Flux<readonly [number, T]>;\n }\n}\n\nFlux.prototype.delayElements = function delayElements<T>(\n this: Flux<T>,\n delay: DurationInput,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n for await (const value of source.iterate(signal, context)) {\n await scheduleDelay(scheduler, delay, signal);\n yield value;\n }\n });\n};\n\nFlux.prototype.timeout = function timeout<T>(\n this: Flux<T>,\n timeout: DurationInput,\n fallback?: PublisherInput<T>,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n const controller = new AbortController();\n const abort = () => controller.abort();\n signal.addEventListener(\"abort\", abort, {once: true});\n const iterator = toAsyncIterator(source.iterate(controller.signal, context));\n try {\n while (!signal.aborted) {\n const result = await raceIteratorWithTimeout(iterator, timeout, scheduler, signal);\n if (result === TIMEOUT) {\n controller.abort();\n if (fallback) {\n for await (const value of Flux.from(fallback).iterate(signal, context)) {\n yield value;\n }\n return;\n }\n throw new TimeoutError();\n }\n if (result.done) {\n return;\n }\n yield result.value;\n }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n controller.abort();\n void iterator.return?.();\n }\n });\n};\n\nFlux.prototype.publishOn = function publishOn<T>(this: Flux<T>, scheduler: Scheduler): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n for await (const value of source.iterate(signal, context)) {\n await scheduleDelay(scheduler, 0, signal);\n yield value;\n }\n });\n};\n\nFlux.prototype.subscribeOn = function subscribeOn<T>(this: Flux<T>, scheduler: Scheduler): Flux<T> {\n const source = this;\n return new Flux((signal, context) => {\n const queue = new AsyncQueue<T>(signal);\n const disposable = scheduler.schedule(() => {\n void (async () => {\n try {\n for await (const value of source.iterate(signal, context)) {\n queue.push(value);\n }\n queue.complete();\n } catch (error) {\n queue.error(error);\n }\n })();\n });\n signal.addEventListener(\"abort\", () => disposable.dispose(), {once: true});\n return queue;\n });\n};\n\nFlux.prototype.timestamp = function timestamp<T>(\n this: Flux<T>,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<readonly [number, T]> {\n return this.map(value => [scheduler.now(), value] as const);\n};\n\nFlux.prototype.elapsed = function elapsed<T>(\n this: Flux<T>,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<readonly [number, T]> {\n const source = this;\n return new Flux(async function* (signal, context) {\n let last = scheduler.now();\n for await (const value of source.iterate(signal, context)) {\n const now = scheduler.now();\n yield [now - last, value] as const;\n last = now;\n }\n });\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"time.js","names":[],"sources":["../../../src/publisher/operators/time.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Flux, Mono and operator implementation modules.\n */\nimport {TimeoutError} from \"@/errors/classes.js\";\nimport {AsyncQueue} from \"@/internal/async-queue.js\";\nimport {toAsyncIterator} from \"@/internal/iterable.js\";\nimport {inheritIterationDemand} from \"@/internal/iteration-demand.js\";\nimport {Flux} from \"@/publisher/flux.js\";\nimport {raceIteratorWithTimeout, scheduleDelay, TIMEOUT} from \"@/publisher/helpers.js\";\nimport type {PublisherInput} from \"@/publisher/types.js\";\nimport {Schedulers} from \"@/schedulers/schedulers.js\";\nimport type {DurationInput, Scheduler} from \"@/schedulers/types.js\";\n\ndeclare module \"@/publisher/flux.js\" {\n /** Time, scheduling and timeout operators added to Flux. */\n interface Flux<T> {\n /** Delays each source value on the provided scheduler before emitting it. */\n delayElements(delay: DurationInput, scheduler?: Scheduler): Flux<T>;\n\n /** Fails or switches to a fallback when the source does not signal in time. */\n timeout(timeout: DurationInput, fallback?: PublisherInput<T>, scheduler?: Scheduler): Flux<T>;\n\n /** Reschedules value delivery on the provided scheduler. */\n publishOn(scheduler: Scheduler): Flux<T>;\n\n /** Schedules subscription work on the provided scheduler. */\n subscribeOn(scheduler: Scheduler): Flux<T>;\n\n /** Emits each value together with the scheduler timestamp. */\n timestamp(scheduler?: Scheduler): Flux<readonly [number, T]>;\n\n /** Emits each value together with elapsed scheduler time since the previous value. */\n elapsed(scheduler?: Scheduler): Flux<readonly [number, T]>;\n }\n}\n\nFlux.prototype.delayElements = function delayElements<T>(\n this: Flux<T>,\n delay: DurationInput,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n for await (const value of source.iterate(signal, context)) {\n await scheduleDelay(scheduler, delay, signal);\n yield value;\n }\n });\n};\n\nFlux.prototype.timeout = function timeout<T>(\n this: Flux<T>,\n timeout: DurationInput,\n fallback?: PublisherInput<T>,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n const controller = new AbortController();\n inheritIterationDemand(signal, controller.signal);\n const abort = () => controller.abort();\n signal.addEventListener(\"abort\", abort, {once: true});\n const iterator = toAsyncIterator(source.iterate(controller.signal, context));\n try {\n while (!signal.aborted) {\n const result = await raceIteratorWithTimeout(iterator, timeout, scheduler, signal);\n if (result === TIMEOUT) {\n controller.abort();\n if (fallback) {\n for await (const value of Flux.from(fallback).iterate(signal, context)) {\n yield value;\n }\n return;\n }\n throw new TimeoutError();\n }\n if (result.done) {\n return;\n }\n yield result.value;\n }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n controller.abort();\n void iterator.return?.();\n }\n });\n};\n\nFlux.prototype.publishOn = function publishOn<T>(this: Flux<T>, scheduler: Scheduler): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n for await (const value of source.iterate(signal, context)) {\n await scheduleDelay(scheduler, 0, signal);\n yield value;\n }\n });\n};\n\nFlux.prototype.subscribeOn = function subscribeOn<T>(this: Flux<T>, scheduler: Scheduler): Flux<T> {\n const source = this;\n return new Flux((signal, context) => {\n const queue = new AsyncQueue<T>(signal);\n const disposable = scheduler.schedule(() => {\n void (async () => {\n try {\n for await (const value of source.iterate(signal, context)) {\n queue.push(value);\n }\n queue.complete();\n } catch (error) {\n queue.error(error);\n }\n })();\n });\n signal.addEventListener(\"abort\", () => disposable.dispose(), {once: true});\n return queue;\n });\n};\n\nFlux.prototype.timestamp = function timestamp<T>(\n this: Flux<T>,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<readonly [number, T]> {\n return this.map(value => [scheduler.now(), value] as const);\n};\n\nFlux.prototype.elapsed = function elapsed<T>(\n this: Flux<T>,\n scheduler: Scheduler = Schedulers.timeout()\n): Flux<readonly [number, T]> {\n const source = this;\n return new Flux(async function* (signal, context) {\n let last = scheduler.now();\n for await (const value of source.iterate(signal, context)) {\n const now = scheduler.now();\n yield [now - last, value] as const;\n last = now;\n }\n });\n};\n"],"mappings":";;;;;;;;;;;;AAqCA,KAAK,UAAU,gBAAgB,SAAS,cAEpC,OACA,YAAuB,WAAW,QAAQ,GACnC;CACP,MAAM,SAAS;CACf,OAAO,IAAI,KAAK,iBAAiB,QAAQ,SAAS;EAC9C,WAAW,MAAM,SAAS,OAAO,QAAQ,QAAQ,OAAO,GAAG;GACvD,MAAM,cAAc,WAAW,OAAO,MAAM;GAC5C,MAAM;EACV;CACJ,CAAC;AACL;AAEA,KAAK,UAAU,UAAU,SAAS,QAE9B,SACA,UACA,YAAuB,WAAW,QAAQ,GACnC;CACP,MAAM,SAAS;CACf,OAAO,IAAI,KAAK,iBAAiB,QAAQ,SAAS;EAC9C,MAAM,aAAa,IAAI,gBAAgB;EACvC,uBAAuB,QAAQ,WAAW,MAAM;EAChD,MAAM,cAAc,WAAW,MAAM;EACrC,OAAO,iBAAiB,SAAS,OAAO,EAAC,MAAM,KAAI,CAAC;EACpD,MAAM,WAAW,gBAAgB,OAAO,QAAQ,WAAW,QAAQ,OAAO,CAAC;EAC3E,IAAI;GACA,OAAO,CAAC,OAAO,SAAS;IACpB,MAAM,SAAS,MAAM,wBAAwB,UAAU,SAAS,WAAW,MAAM;IACjF,IAAI,WAAW,SAAS;KACpB,WAAW,MAAM;KACjB,IAAI,UAAU;MACV,WAAW,MAAM,SAAS,KAAK,KAAK,QAAQ,CAAC,CAAC,QAAQ,QAAQ,OAAO,GACjE,MAAM;MAEV;KACJ;KACA,MAAM,IAAI,aAAa;IAC3B;IACA,IAAI,OAAO,MACP;IAEJ,MAAM,OAAO;GACjB;EACJ,UAAU;GACN,OAAO,oBAAoB,SAAS,KAAK;GACzC,WAAW,MAAM;GACjB,AAAK,SAAS,SAAS;EAC3B;CACJ,CAAC;AACL;AAEA,KAAK,UAAU,YAAY,SAAS,UAA4B,WAA+B;CAC3F,MAAM,SAAS;CACf,OAAO,IAAI,KAAK,iBAAiB,QAAQ,SAAS;EAC9C,WAAW,MAAM,SAAS,OAAO,QAAQ,QAAQ,OAAO,GAAG;GACvD,MAAM,cAAc,WAAW,GAAG,MAAM;GACxC,MAAM;EACV;CACJ,CAAC;AACL;AAEA,KAAK,UAAU,cAAc,SAAS,YAA8B,WAA+B;CAC/F,MAAM,SAAS;CACf,OAAO,IAAI,MAAM,QAAQ,YAAY;EACjC,MAAM,QAAQ,IAAI,WAAc,MAAM;EACtC,MAAM,aAAa,UAAU,eAAe;GACxC,CAAM,YAAY;IACd,IAAI;KACA,WAAW,MAAM,SAAS,OAAO,QAAQ,QAAQ,OAAO,GACpD,MAAM,KAAK,KAAK;KAEpB,MAAM,SAAS;IACnB,SAAS,OAAO;KACZ,MAAM,MAAM,KAAK;IACrB;GACJ,EAAA,CAAG;EACP,CAAC;EACD,OAAO,iBAAiB,eAAe,WAAW,QAAQ,GAAG,EAAC,MAAM,KAAI,CAAC;EACzE,OAAO;CACX,CAAC;AACL;AAEA,KAAK,UAAU,YAAY,SAAS,UAEhC,YAAuB,WAAW,QAAQ,GAChB;CAC1B,OAAO,KAAK,KAAI,UAAS,CAAC,UAAU,IAAI,GAAG,KAAK,CAAU;AAC9D;AAEA,KAAK,UAAU,UAAU,SAAS,QAE9B,YAAuB,WAAW,QAAQ,GAChB;CAC1B,MAAM,SAAS;CACf,OAAO,IAAI,KAAK,iBAAiB,QAAQ,SAAS;EAC9C,IAAI,OAAO,UAAU,IAAI;EACzB,WAAW,MAAM,SAAS,OAAO,QAAQ,QAAQ,OAAO,GAAG;GACvD,MAAM,MAAM,UAAU,IAAI;GAC1B,MAAM,CAAC,MAAM,MAAM,KAAK;GACxB,OAAO;EACX;CACJ,CAAC;AACL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-subscription.d.ts","sourceRoot":"","sources":["../../src/subscription/iterable-subscription.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"iterable-subscription.d.ts","sourceRoot":"","sources":["../../src/subscription/iterable-subscription.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,sBAAsB,CAAC;AAIlD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAEjE,oFAAoF;AACpF,qBAAa,oBAAoB,CAAC,CAAC,CAAE,YAAW,YAAY;IACxD,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,2DAA2D;IAC3D,OAAO,CAAC,aAAa,CAA+B;IACpD,iEAAiE;IACjE,OAAO,CAAC,YAAY,CAA0B;IAC9C,6DAA6D;IAC7D,OAAO,CAAC,OAAO,CAAS;IACxB,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAAU;IAC9B,2DAA2D;IAC3D,OAAO,CAAC,eAAe,CAAS;IAChC,0EAA0E;IAC1E,OAAO,CAAC,gBAAgB,CAAyC;IACjE,yEAAyE;IACzE,OAAO,CAAC,eAAe,CAAgC;IACvD,qCAAqC;IACrC,OAAO,CAAC,SAAS,CAAK;IACtB,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAS;IACzB,sCAAsC;IACtC,OAAO,CAAC,SAAS,CAAS;IAC1B,sDAAsD;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,gDAAgD;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,+CAA+C;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,mEAAmE;IACnE,YAAmB,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAK5E;IAED,iEAAiE;IAC1D,KAAK,IAAI,IAAI,CAgBnB;IAED,0EAA0E;IACnE,mBAAmB,IAAI,IAAI,CAOjC;IAED,sDAAsD;IAC/C,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAqB9B;IAED,uDAAuD;IAChD,MAAM,IAAI,IAAI,CAOpB;IAED,2DAA2D;YAC7C,KAAK;IAyCnB,uEAAuE;IACvE,OAAO,CAAC,SAAS;IAYjB,uDAAuD;IACvD,OAAO,CAAC,aAAa;IAmBrB,gGAAgG;IAChG,OAAO,CAAC,eAAe;IASvB,8FAA8F;IAC9F,OAAO,CAAC,cAAc;IAStB,gFAAgF;IAChF,OAAO,CAAC,uBAAuB;IAgC/B,4FAA4F;IAC5F,OAAO,CAAC,2BAA2B;IAuBnC,+EAA+E;IAC/E,OAAO,CAAC,cAAc;CAYzB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _defineProperty from "../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/defineProperty.js";
|
|
2
2
|
import { doneResult, isAsyncIterable, resolvedDoneResult } from "../internal/iterable.js";
|
|
3
|
-
import { addCap, normalizeRequest } from "../core/demand.js";
|
|
3
|
+
import { UNBOUNDED_DEMAND, addCap, normalizeRequest } from "../core/demand.js";
|
|
4
|
+
import { applyIterationDemandHint, markUnboundedIteration } from "../internal/iteration-demand.js";
|
|
4
5
|
import { scheduleMicrotask } from "../internal/microtask.js";
|
|
5
6
|
//#region src/subscription/iterable-subscription.ts
|
|
6
7
|
/**
|
|
@@ -104,6 +105,7 @@ var IterableSubscription = class {
|
|
|
104
105
|
this.flux = flux;
|
|
105
106
|
this.subscriber = subscriber;
|
|
106
107
|
this.context = context;
|
|
108
|
+
applyIterationDemandHint(this.controller.signal, subscriber);
|
|
107
109
|
}
|
|
108
110
|
/** Starts source assembly without pulling any values from it. */
|
|
109
111
|
start() {
|
|
@@ -136,6 +138,7 @@ var IterableSubscription = class {
|
|
|
136
138
|
this.subscriber.onError(error);
|
|
137
139
|
return;
|
|
138
140
|
}
|
|
141
|
+
if (request === UNBOUNDED_DEMAND) markUnboundedIteration(this.controller.signal);
|
|
139
142
|
this.requested = addCap(this.requested, request);
|
|
140
143
|
if (this.hasStartFailure) {
|
|
141
144
|
this.deliverStartFailure();
|
|
@@ -197,7 +200,7 @@ var IterableSubscription = class {
|
|
|
197
200
|
this.subscriber.onComplete();
|
|
198
201
|
return true;
|
|
199
202
|
}
|
|
200
|
-
if (this.requested !==
|
|
203
|
+
if (this.requested !== UNBOUNDED_DEMAND) this.requested -= 1;
|
|
201
204
|
try {
|
|
202
205
|
this.subscriber.onNext(result.value);
|
|
203
206
|
} catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-subscription.js","names":[],"sources":["../../src/subscription/iterable-subscription.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Reactive Streams subscription and subscriber contracts.\n */\nimport {addCap, normalizeRequest} from \"@/core/demand.js\";\nimport type {Context} from \"@/context/context.js\";\nimport {doneResult, isAsyncIterable, resolvedDoneResult} from \"@/internal/iterable.js\";\nimport {scheduleMicrotask} from \"@/internal/microtask.js\";\nimport type {Flux} from \"@/publisher/flux.js\";\nimport type {Subscriber} from \"@/subscription/subscriber.js\";\nimport type {Subscription} from \"@/subscription/subscription.js\";\n\n/** Subscription implementation that drains a Flux only when demand is requested. */\nexport class IterableSubscription<T> implements Subscription {\n /** Abort controller used to cancel the active source iterator. */\n private readonly controller = new AbortController();\n /** Lazily created async iterator over the backing Flux. */\n private asyncIterator: AsyncIterator<T> | undefined;\n /** Lazily created synchronous iterator over the backing Flux. */\n private syncIterator: Iterator<T> | undefined;\n /** Tracks whether the source iterator has been assembled. */\n private started = false;\n /** Stores a synchronous source assembly failure until it can be signalled. */\n private startFailure: unknown;\n /** Tracks whether source assembly failed synchronously. */\n private hasStartFailure = false;\n /** Prefetched async result used to detect completion with zero demand. */\n private pendingAsyncNext: Promise<IteratorResult<T>> | undefined;\n /** Prefetched sync result used to detect completion with zero demand. */\n private pendingSyncNext: IteratorResult<T> | undefined;\n /** Outstanding downstream demand. */\n private requested = 0;\n /** Guards against concurrent drain loops. */\n private draining = false;\n /** Tracks downstream cancellation. */\n private cancelled = false;\n /** Tracks terminal completion or failure delivery. */\n private terminated = false;\n /** Source Flux drained by this subscription. */\n private readonly flux: Flux<T>;\n /** Downstream subscriber receiving signals. */\n private readonly subscriber: Subscriber<T>;\n /** Context used for the source iteration. */\n private readonly context: Context;\n\n /** Creates a subscription for the provided Flux and subscriber. */\n public constructor(flux: Flux<T>, subscriber: Subscriber<T>, context: Context) {\n this.flux = flux;\n this.subscriber = subscriber;\n this.context = context;\n }\n\n /** Starts source assembly without pulling any values from it. */\n public start(): void {\n if (this.started || this.cancelled || this.terminated) {\n return;\n }\n this.started = true;\n try {\n const source = this.flux.iterate(this.controller.signal, this.context);\n if (isAsyncIterable<T>(source)) {\n this.asyncIterator = source[Symbol.asyncIterator]();\n } else {\n this.syncIterator = source[Symbol.iterator]();\n }\n } catch (error) {\n this.startFailure = error;\n this.hasStartFailure = true;\n }\n }\n\n /** Delivers a synchronous source assembly failure after `onSubscribe`. */\n public deliverStartFailure(): void {\n if (!this.hasStartFailure || this.cancelled || this.terminated) {\n return;\n }\n this.hasStartFailure = false;\n this.terminated = true;\n this.subscriber.onError(this.startFailure);\n }\n\n /** Requests more values from the backing iterator. */\n public request(n: number): void {\n if (this.cancelled || this.terminated) {\n return;\n }\n let request: number;\n try {\n request = normalizeRequest(n);\n } catch (error) {\n this.cancel();\n this.subscriber.onError(error);\n return;\n }\n this.requested = addCap(this.requested, request);\n if (this.hasStartFailure) {\n this.deliverStartFailure();\n return;\n }\n void this.drain();\n }\n\n /** Cancels iteration and closes upstream resources. */\n public cancel(): void {\n if (this.cancelled || this.terminated) {\n return;\n }\n this.cancelled = true;\n this.controller.abort();\n this.closeIterators();\n }\n\n /** Drains the source while there is outstanding demand. */\n private async drain(): Promise<void> {\n if (this.draining) {\n return;\n }\n this.draining = true;\n try {\n this.start();\n if (this.hasStartFailure) {\n this.deliverStartFailure();\n return;\n }\n if (this.syncIterator) {\n this.drainSync();\n return;\n }\n while (!this.cancelled && !this.terminated && this.requested > 0) {\n const result = await this.nextAsyncResult();\n if (this.cancelled || this.terminated) {\n return;\n }\n if (this.deliverResult(result)) {\n return;\n }\n }\n } catch (error) {\n if (!this.cancelled && !this.terminated) {\n this.terminated = true;\n this.subscriber.onError(error);\n }\n } finally {\n this.draining = false;\n if (!this.cancelled && !this.terminated && this.requested > 0) {\n scheduleMicrotask(() => {\n void this.drain();\n });\n } else if (!this.cancelled && !this.terminated && this.requested === 0) {\n this.lookAheadForTermination();\n }\n }\n }\n\n /** Drains a synchronous source without per-item promise allocation. */\n private drainSync(): void {\n while (!this.cancelled && !this.terminated && this.requested > 0) {\n const result = this.nextSyncResult();\n if (this.cancelled || this.terminated) {\n return;\n }\n if (this.deliverResult(result)) {\n return;\n }\n }\n }\n\n /** Returns true after delivering a terminal result. */\n private deliverResult(result: IteratorResult<T>): boolean {\n if (result.done) {\n this.terminated = true;\n this.subscriber.onComplete();\n return true;\n }\n if (this.requested !== Number.POSITIVE_INFINITY) {\n this.requested -= 1;\n }\n try {\n this.subscriber.onNext(result.value);\n } catch (error) {\n this.cancel();\n this.subscriber.onError(error);\n return true;\n }\n return false;\n }\n\n /** Returns the pending prefetched async result or asks the async iterator for the next item. */\n private nextAsyncResult(): Promise<IteratorResult<T>> {\n if (this.pendingAsyncNext) {\n const pending = this.pendingAsyncNext;\n this.pendingAsyncNext = undefined;\n return pending;\n }\n return this.asyncIterator?.next() ?? resolvedDoneResult<T>();\n }\n\n /** Returns the pending prefetched sync result or asks the sync iterator for the next item. */\n private nextSyncResult(): IteratorResult<T> {\n if (this.pendingSyncNext) {\n const pending = this.pendingSyncNext;\n this.pendingSyncNext = undefined;\n return pending;\n }\n return this.syncIterator?.next() ?? doneResult<T>();\n }\n\n /** Prefetches one item to discover terminal completion without extra demand. */\n private lookAheadForTermination(): void {\n if (this.syncIterator) {\n this.lookAheadForSyncTermination();\n return;\n }\n if (!this.asyncIterator || this.pendingAsyncNext) {\n return;\n }\n const pending = this.asyncIterator.next();\n this.pendingAsyncNext = pending;\n pending.then(\n result => {\n if (this.pendingAsyncNext !== pending || this.cancelled || this.terminated) {\n return;\n }\n if (result.done) {\n this.pendingAsyncNext = undefined;\n this.terminated = true;\n this.subscriber.onComplete();\n }\n },\n error => {\n if (this.pendingAsyncNext !== pending || this.cancelled || this.terminated) {\n return;\n }\n this.pendingAsyncNext = undefined;\n this.terminated = true;\n this.subscriber.onError(error);\n }\n );\n }\n\n /** Prefetches one synchronous item to discover terminal completion without extra demand. */\n private lookAheadForSyncTermination(): void {\n if (!this.syncIterator || this.pendingSyncNext) {\n return;\n }\n try {\n const result = this.syncIterator.next();\n if (this.cancelled || this.terminated) {\n return;\n }\n if (result.done) {\n this.terminated = true;\n this.subscriber.onComplete();\n } else {\n this.pendingSyncNext = result;\n }\n } catch (error) {\n if (!this.cancelled && !this.terminated) {\n this.terminated = true;\n this.subscriber.onError(error);\n }\n }\n }\n\n /** Closes active iterators and ignores cleanup failures after cancellation. */\n private closeIterators(): void {\n try {\n void this.asyncIterator?.return?.();\n } catch {\n // cancellation best-effort cleanup\n }\n try {\n this.syncIterator?.return?.();\n } catch {\n // cancellation best-effort cleanup\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"iterable-subscription.js","names":[],"sources":["../../src/subscription/iterable-subscription.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Reactive Streams subscription and subscriber contracts.\n */\nimport {addCap, normalizeRequest, UNBOUNDED_DEMAND} from \"@/core/demand.js\";\nimport type {Context} from \"@/context/context.js\";\nimport {doneResult, isAsyncIterable, resolvedDoneResult} from \"@/internal/iterable.js\";\nimport {applyIterationDemandHint, markUnboundedIteration} from \"@/internal/iteration-demand.js\";\nimport {scheduleMicrotask} from \"@/internal/microtask.js\";\nimport type {Flux} from \"@/publisher/flux.js\";\nimport type {Subscriber} from \"@/subscription/subscriber.js\";\nimport type {Subscription} from \"@/subscription/subscription.js\";\n\n/** Subscription implementation that drains a Flux only when demand is requested. */\nexport class IterableSubscription<T> implements Subscription {\n /** Abort controller used to cancel the active source iterator. */\n private readonly controller = new AbortController();\n /** Lazily created async iterator over the backing Flux. */\n private asyncIterator: AsyncIterator<T> | undefined;\n /** Lazily created synchronous iterator over the backing Flux. */\n private syncIterator: Iterator<T> | undefined;\n /** Tracks whether the source iterator has been assembled. */\n private started = false;\n /** Stores a synchronous source assembly failure until it can be signalled. */\n private startFailure: unknown;\n /** Tracks whether source assembly failed synchronously. */\n private hasStartFailure = false;\n /** Prefetched async result used to detect completion with zero demand. */\n private pendingAsyncNext: Promise<IteratorResult<T>> | undefined;\n /** Prefetched sync result used to detect completion with zero demand. */\n private pendingSyncNext: IteratorResult<T> | undefined;\n /** Outstanding downstream demand. */\n private requested = 0;\n /** Guards against concurrent drain loops. */\n private draining = false;\n /** Tracks downstream cancellation. */\n private cancelled = false;\n /** Tracks terminal completion or failure delivery. */\n private terminated = false;\n /** Source Flux drained by this subscription. */\n private readonly flux: Flux<T>;\n /** Downstream subscriber receiving signals. */\n private readonly subscriber: Subscriber<T>;\n /** Context used for the source iteration. */\n private readonly context: Context;\n\n /** Creates a subscription for the provided Flux and subscriber. */\n public constructor(flux: Flux<T>, subscriber: Subscriber<T>, context: Context) {\n this.flux = flux;\n this.subscriber = subscriber;\n this.context = context;\n applyIterationDemandHint(this.controller.signal, subscriber);\n }\n\n /** Starts source assembly without pulling any values from it. */\n public start(): void {\n if (this.started || this.cancelled || this.terminated) {\n return;\n }\n this.started = true;\n try {\n const source = this.flux.iterate(this.controller.signal, this.context);\n if (isAsyncIterable<T>(source)) {\n this.asyncIterator = source[Symbol.asyncIterator]();\n } else {\n this.syncIterator = source[Symbol.iterator]();\n }\n } catch (error) {\n this.startFailure = error;\n this.hasStartFailure = true;\n }\n }\n\n /** Delivers a synchronous source assembly failure after `onSubscribe`. */\n public deliverStartFailure(): void {\n if (!this.hasStartFailure || this.cancelled || this.terminated) {\n return;\n }\n this.hasStartFailure = false;\n this.terminated = true;\n this.subscriber.onError(this.startFailure);\n }\n\n /** Requests more values from the backing iterator. */\n public request(n: number): void {\n if (this.cancelled || this.terminated) {\n return;\n }\n let request: number;\n try {\n request = normalizeRequest(n);\n } catch (error) {\n this.cancel();\n this.subscriber.onError(error);\n return;\n }\n if (request === UNBOUNDED_DEMAND) {\n markUnboundedIteration(this.controller.signal);\n }\n this.requested = addCap(this.requested, request);\n if (this.hasStartFailure) {\n this.deliverStartFailure();\n return;\n }\n void this.drain();\n }\n\n /** Cancels iteration and closes upstream resources. */\n public cancel(): void {\n if (this.cancelled || this.terminated) {\n return;\n }\n this.cancelled = true;\n this.controller.abort();\n this.closeIterators();\n }\n\n /** Drains the source while there is outstanding demand. */\n private async drain(): Promise<void> {\n if (this.draining) {\n return;\n }\n this.draining = true;\n try {\n this.start();\n if (this.hasStartFailure) {\n this.deliverStartFailure();\n return;\n }\n if (this.syncIterator) {\n this.drainSync();\n return;\n }\n while (!this.cancelled && !this.terminated && this.requested > 0) {\n const result = await this.nextAsyncResult();\n if (this.cancelled || this.terminated) {\n return;\n }\n if (this.deliverResult(result)) {\n return;\n }\n }\n } catch (error) {\n if (!this.cancelled && !this.terminated) {\n this.terminated = true;\n this.subscriber.onError(error);\n }\n } finally {\n this.draining = false;\n if (!this.cancelled && !this.terminated && this.requested > 0) {\n scheduleMicrotask(() => {\n void this.drain();\n });\n } else if (!this.cancelled && !this.terminated && this.requested === 0) {\n this.lookAheadForTermination();\n }\n }\n }\n\n /** Drains a synchronous source without per-item promise allocation. */\n private drainSync(): void {\n while (!this.cancelled && !this.terminated && this.requested > 0) {\n const result = this.nextSyncResult();\n if (this.cancelled || this.terminated) {\n return;\n }\n if (this.deliverResult(result)) {\n return;\n }\n }\n }\n\n /** Returns true after delivering a terminal result. */\n private deliverResult(result: IteratorResult<T>): boolean {\n if (result.done) {\n this.terminated = true;\n this.subscriber.onComplete();\n return true;\n }\n if (this.requested !== UNBOUNDED_DEMAND) {\n this.requested -= 1;\n }\n try {\n this.subscriber.onNext(result.value);\n } catch (error) {\n this.cancel();\n this.subscriber.onError(error);\n return true;\n }\n return false;\n }\n\n /** Returns the pending prefetched async result or asks the async iterator for the next item. */\n private nextAsyncResult(): Promise<IteratorResult<T>> {\n if (this.pendingAsyncNext) {\n const pending = this.pendingAsyncNext;\n this.pendingAsyncNext = undefined;\n return pending;\n }\n return this.asyncIterator?.next() ?? resolvedDoneResult<T>();\n }\n\n /** Returns the pending prefetched sync result or asks the sync iterator for the next item. */\n private nextSyncResult(): IteratorResult<T> {\n if (this.pendingSyncNext) {\n const pending = this.pendingSyncNext;\n this.pendingSyncNext = undefined;\n return pending;\n }\n return this.syncIterator?.next() ?? doneResult<T>();\n }\n\n /** Prefetches one item to discover terminal completion without extra demand. */\n private lookAheadForTermination(): void {\n if (this.syncIterator) {\n this.lookAheadForSyncTermination();\n return;\n }\n if (!this.asyncIterator || this.pendingAsyncNext) {\n return;\n }\n const pending = this.asyncIterator.next();\n this.pendingAsyncNext = pending;\n pending.then(\n result => {\n if (this.pendingAsyncNext !== pending || this.cancelled || this.terminated) {\n return;\n }\n if (result.done) {\n this.pendingAsyncNext = undefined;\n this.terminated = true;\n this.subscriber.onComplete();\n }\n },\n error => {\n if (this.pendingAsyncNext !== pending || this.cancelled || this.terminated) {\n return;\n }\n this.pendingAsyncNext = undefined;\n this.terminated = true;\n this.subscriber.onError(error);\n }\n );\n }\n\n /** Prefetches one synchronous item to discover terminal completion without extra demand. */\n private lookAheadForSyncTermination(): void {\n if (!this.syncIterator || this.pendingSyncNext) {\n return;\n }\n try {\n const result = this.syncIterator.next();\n if (this.cancelled || this.terminated) {\n return;\n }\n if (result.done) {\n this.terminated = true;\n this.subscriber.onComplete();\n } else {\n this.pendingSyncNext = result;\n }\n } catch (error) {\n if (!this.cancelled && !this.terminated) {\n this.terminated = true;\n this.subscriber.onError(error);\n }\n }\n }\n\n /** Closes active iterators and ignores cleanup failures after cancellation. */\n private closeIterators(): void {\n try {\n void this.asyncIterator?.return?.();\n } catch {\n // cancellation best-effort cleanup\n }\n try {\n this.syncIterator?.return?.();\n } catch {\n // cancellation best-effort cleanup\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @packageDocumentation
|
|
3
|
-
* Internal iterable terminal helpers.
|
|
4
|
-
*/
|
|
5
|
-
import { type AnyIterable } from "./iterable.js";
|
|
6
|
-
/** Collects an iterable into an array, using a synchronous loop when possible. */
|
|
7
|
-
export declare function collectIterable<T>(source: AnyIterable<T>): T[] | Promise<T[]>;
|
|
8
|
-
/** Returns the last value from an iterable, or undefined when it is empty. */
|
|
9
|
-
export declare function lastIterableValue<T>(source: AnyIterable<T>): T | undefined | Promise<T | undefined>;
|
|
10
|
-
/** Counts iterable values, using a synchronous loop when possible. */
|
|
11
|
-
export declare function countIterable<T>(source: AnyIterable<T>): number | Promise<number>;
|
|
12
|
-
//# sourceMappingURL=iterable-terminal.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-terminal.d.ts","sourceRoot":"","sources":["../../src/internal/iterable-terminal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAC,KAAK,WAAW,EAAkB,MAAM,wBAAwB,CAAC;AAEzE,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAS7E;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CASnG;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASjF"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { isAsyncIterable } from "./iterable.js";
|
|
2
|
-
//#region src/internal/iterable-terminal.ts
|
|
3
|
-
/**
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
* Internal iterable terminal helpers.
|
|
6
|
-
*/
|
|
7
|
-
/** Collects an iterable into an array, using a synchronous loop when possible. */
|
|
8
|
-
function collectIterable(source) {
|
|
9
|
-
if (isAsyncIterable(source)) return collectAsync(source);
|
|
10
|
-
const values = [];
|
|
11
|
-
for (const value of source) values.push(value);
|
|
12
|
-
return values;
|
|
13
|
-
}
|
|
14
|
-
/** Returns the last value from an iterable, or undefined when it is empty. */
|
|
15
|
-
function lastIterableValue(source) {
|
|
16
|
-
if (isAsyncIterable(source)) return lastAsync(source);
|
|
17
|
-
let last;
|
|
18
|
-
for (const value of source) last = value;
|
|
19
|
-
return last;
|
|
20
|
-
}
|
|
21
|
-
/** Counts iterable values, using a synchronous loop when possible. */
|
|
22
|
-
function countIterable(source) {
|
|
23
|
-
if (isAsyncIterable(source)) return countAsync(source);
|
|
24
|
-
let count = 0;
|
|
25
|
-
for (const _ of source) count += 1;
|
|
26
|
-
return count;
|
|
27
|
-
}
|
|
28
|
-
/** Collects an async iterable into an array. */
|
|
29
|
-
async function collectAsync(source) {
|
|
30
|
-
const values = [];
|
|
31
|
-
for await (const value of source) values.push(value);
|
|
32
|
-
return values;
|
|
33
|
-
}
|
|
34
|
-
/** Returns the last async iterable value, or undefined when empty. */
|
|
35
|
-
async function lastAsync(source) {
|
|
36
|
-
let last;
|
|
37
|
-
for await (const value of source) last = value;
|
|
38
|
-
return last;
|
|
39
|
-
}
|
|
40
|
-
/** Counts async iterable values. */
|
|
41
|
-
async function countAsync(source) {
|
|
42
|
-
let count = 0;
|
|
43
|
-
for await (const _ of source) count += 1;
|
|
44
|
-
return count;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
|
-
export { collectIterable, countIterable, lastIterableValue };
|
|
48
|
-
|
|
49
|
-
//# sourceMappingURL=iterable-terminal.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-terminal.js","names":[],"sources":["../../src/internal/iterable-terminal.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Internal iterable terminal helpers.\n */\nimport {type AnyIterable, isAsyncIterable} from \"@/internal/iterable.js\";\n\n/** Collects an iterable into an array, using a synchronous loop when possible. */\nexport function collectIterable<T>(source: AnyIterable<T>): T[] | Promise<T[]> {\n if (isAsyncIterable<T>(source)) {\n return collectAsync(source);\n }\n const values: T[] = [];\n for (const value of source) {\n values.push(value);\n }\n return values;\n}\n\n/** Returns the last value from an iterable, or undefined when it is empty. */\nexport function lastIterableValue<T>(source: AnyIterable<T>): T | undefined | Promise<T | undefined> {\n if (isAsyncIterable<T>(source)) {\n return lastAsync(source);\n }\n let last: T | undefined;\n for (const value of source) {\n last = value;\n }\n return last;\n}\n\n/** Counts iterable values, using a synchronous loop when possible. */\nexport function countIterable<T>(source: AnyIterable<T>): number | Promise<number> {\n if (isAsyncIterable<T>(source)) {\n return countAsync(source);\n }\n let count = 0;\n for (const _ of source) {\n count += 1;\n }\n return count;\n}\n\n/** Collects an async iterable into an array. */\nasync function collectAsync<T>(source: AsyncIterable<T>): Promise<T[]> {\n const values: T[] = [];\n for await (const value of source) {\n values.push(value);\n }\n return values;\n}\n\n/** Returns the last async iterable value, or undefined when empty. */\nasync function lastAsync<T>(source: AsyncIterable<T>): Promise<T | undefined> {\n let last: T | undefined;\n for await (const value of source) {\n last = value;\n }\n return last;\n}\n\n/** Counts async iterable values. */\nasync function countAsync<T>(source: AsyncIterable<T>): Promise<number> {\n let count = 0;\n for await (const _ of source) {\n count += 1;\n }\n return count;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,gBAAmB,QAA4C;CAC3E,IAAI,gBAAmB,MAAM,GACzB,OAAO,aAAa,MAAM;CAE9B,MAAM,SAAc,CAAC;CACrB,KAAK,MAAM,SAAS,QAChB,OAAO,KAAK,KAAK;CAErB,OAAO;AACX;;AAGA,SAAgB,kBAAqB,QAAgE;CACjG,IAAI,gBAAmB,MAAM,GACzB,OAAO,UAAU,MAAM;CAE3B,IAAI;CACJ,KAAK,MAAM,SAAS,QAChB,OAAO;CAEX,OAAO;AACX;;AAGA,SAAgB,cAAiB,QAAkD;CAC/E,IAAI,gBAAmB,MAAM,GACzB,OAAO,WAAW,MAAM;CAE5B,IAAI,QAAQ;CACZ,KAAK,MAAM,KAAK,QACZ,SAAS;CAEb,OAAO;AACX;;AAGA,eAAe,aAAgB,QAAwC;CACnE,MAAM,SAAc,CAAC;CACrB,WAAW,MAAM,SAAS,QACtB,OAAO,KAAK,KAAK;CAErB,OAAO;AACX;;AAGA,eAAe,UAAa,QAAkD;CAC1E,IAAI;CACJ,WAAW,MAAM,SAAS,QACtB,OAAO;CAEX,OAAO;AACX;;AAGA,eAAe,WAAc,QAA2C;CACpE,IAAI,QAAQ;CACZ,WAAW,MAAM,KAAK,QAClB,SAAS;CAEb,OAAO;AACX"}
|