@fable-org/fable-library-ts 1.4.3 → 1.6.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.
- package/Async.ts +20 -29
- package/AsyncBuilder.ts +13 -13
- package/CHANGELOG.md +23 -0
- package/MailboxProcessor.ts +2 -2
- package/String.ts +20 -7
- package/Uri.ts +21 -1
- package/Util.ts +2 -2
- package/package.json +1 -1
package/Async.ts
CHANGED
|
@@ -1,40 +1,33 @@
|
|
|
1
1
|
import { OperationCanceledError, Trampoline } from "./AsyncBuilder.js";
|
|
2
2
|
import { Continuation, Continuations } from "./AsyncBuilder.js";
|
|
3
|
-
import { CancellationToken } from "./AsyncBuilder.js";
|
|
4
|
-
import {
|
|
5
|
-
import { IAsyncContext } from "./AsyncBuilder.js";
|
|
6
|
-
import { protectedCont } from "./AsyncBuilder.js";
|
|
7
|
-
import { protectedBind } from "./AsyncBuilder.js";
|
|
8
|
-
import { protectedReturn } from "./AsyncBuilder.js";
|
|
3
|
+
import { Async, IAsyncContext, CancellationToken } from "./AsyncBuilder.js";
|
|
4
|
+
import { protectedCont, protectedBind, protectedReturn } from "./AsyncBuilder.js";
|
|
9
5
|
import { FSharpChoice$2_$union, Choice_makeChoice1Of2, Choice_makeChoice2Of2 } from "./Choice.js";
|
|
10
6
|
import { TimeoutException } from "./SystemException.js";
|
|
11
7
|
|
|
12
|
-
// Implemented just for type references
|
|
13
|
-
export class Async<_T> { }
|
|
14
|
-
|
|
15
8
|
function emptyContinuation<T>(_x: T) {
|
|
16
9
|
// NOP
|
|
17
10
|
}
|
|
18
11
|
|
|
19
12
|
// see AsyncBuilder.Delay
|
|
20
|
-
function delay<T>(generator: () =>
|
|
13
|
+
function delay<T>(generator: () => Async<T>) {
|
|
21
14
|
return protectedCont((ctx: IAsyncContext<T>) => generator()(ctx));
|
|
22
15
|
}
|
|
23
16
|
|
|
24
17
|
// MakeAsync: body:(AsyncActivation<'T> -> AsyncReturn) -> Async<'T>
|
|
25
|
-
export function makeAsync<T>(body:
|
|
18
|
+
export function makeAsync<T>(body: Async<T>) {
|
|
26
19
|
return body;
|
|
27
20
|
}
|
|
28
21
|
// Invoke: computation: Async<'T> -> ctxt:AsyncActivation<'T> -> AsyncReturn
|
|
29
|
-
export function invoke<T>(computation:
|
|
22
|
+
export function invoke<T>(computation: Async<T>, ctx: IAsyncContext<T>) {
|
|
30
23
|
return computation(ctx);
|
|
31
24
|
}
|
|
32
25
|
// CallThenInvoke: ctxt:AsyncActivation<'T> -> result1:'U -> part2:('U -> Async<'T>) -> AsyncReturn
|
|
33
|
-
export function callThenInvoke<T, U>(ctx: IAsyncContext<T>, result1: U, part2: (x: U) =>
|
|
26
|
+
export function callThenInvoke<T, U>(ctx: IAsyncContext<T>, result1: U, part2: (x: U) => Async<T>) {
|
|
34
27
|
return part2(result1)(ctx);
|
|
35
28
|
}
|
|
36
29
|
// Bind: ctxt:AsyncActivation<'T> -> part1:Async<'U> -> part2:('U -> Async<'T>) -> AsyncReturn
|
|
37
|
-
export function bind<T, U>(ctx: IAsyncContext<T>, part1:
|
|
30
|
+
export function bind<T, U>(ctx: IAsyncContext<T>, part1: Async<U>, part2: (x: U) => Async<T>) {
|
|
38
31
|
return protectedBind(part1, part2)(ctx);
|
|
39
32
|
}
|
|
40
33
|
|
|
@@ -64,7 +57,7 @@ export function throwIfCancellationRequested(token: CancellationToken) {
|
|
|
64
57
|
}
|
|
65
58
|
}
|
|
66
59
|
|
|
67
|
-
function throwAfter(millisecondsDueTime: number)
|
|
60
|
+
function throwAfter(millisecondsDueTime: number): Async<void> {
|
|
68
61
|
return protectedCont((ctx: IAsyncContext<void>) => {
|
|
69
62
|
let tokenId: number;
|
|
70
63
|
const timeoutId = setTimeout(() => {
|
|
@@ -78,7 +71,7 @@ function throwAfter(millisecondsDueTime: number) : IAsync<void> {
|
|
|
78
71
|
});
|
|
79
72
|
}
|
|
80
73
|
|
|
81
|
-
export function startChild<T>(computation:
|
|
74
|
+
export function startChild<T>(computation: Async<T>, ms?: number): Async<Async<T>> {
|
|
82
75
|
if (ms) {
|
|
83
76
|
const computationWithTimeout = protectedBind(
|
|
84
77
|
parallel2(
|
|
@@ -110,7 +103,7 @@ export function cancellationToken() {
|
|
|
110
103
|
|
|
111
104
|
export const defaultCancellationToken = new CancellationToken();
|
|
112
105
|
|
|
113
|
-
export function catchAsync<T>(work:
|
|
106
|
+
export function catchAsync<T>(work: Async<T>) {
|
|
114
107
|
return protectedCont((ctx: IAsyncContext<FSharpChoice$2_$union<T, Error>>) => {
|
|
115
108
|
work({
|
|
116
109
|
onSuccess: (x) => ctx.onSuccess(Choice_makeChoice1Of2(x)),
|
|
@@ -127,21 +120,21 @@ export function fromContinuations<T>(f: (conts: Continuations<T>) => void) {
|
|
|
127
120
|
f([ctx.onSuccess, ctx.onError, ctx.onCancel]));
|
|
128
121
|
}
|
|
129
122
|
|
|
130
|
-
export function ignore<T>(computation:
|
|
123
|
+
export function ignore<T>(computation: Async<T>) {
|
|
131
124
|
return protectedBind(computation, (_x) => protectedReturn(void 0));
|
|
132
125
|
}
|
|
133
126
|
|
|
134
|
-
export function parallel<T>(computations: Iterable<
|
|
127
|
+
export function parallel<T>(computations: Iterable<Async<T>>) {
|
|
135
128
|
return delay(() => awaitPromise(Promise.all(Array.from(computations, (w) => startAsPromise(w)))));
|
|
136
129
|
}
|
|
137
130
|
|
|
138
|
-
function parallel2<T, U>(a:
|
|
139
|
-
return delay(() => awaitPromise(Promise.all([
|
|
131
|
+
function parallel2<T, U>(a: Async<T>, b: Async<U>): Async<[T, U]> {
|
|
132
|
+
return delay(() => awaitPromise(Promise.all([startAsPromise(a), startAsPromise(b)])));
|
|
140
133
|
}
|
|
141
134
|
|
|
142
|
-
export function sequential<T>(computations: Iterable<
|
|
135
|
+
export function sequential<T>(computations: Iterable<Async<T>>) {
|
|
143
136
|
|
|
144
|
-
function _sequential<T>(computations: Iterable<
|
|
137
|
+
function _sequential<T>(computations: Iterable<Async<T>>): Promise<T[]> {
|
|
145
138
|
let pr: Promise<T[]> = Promise.resolve([]);
|
|
146
139
|
for (const c of computations) {
|
|
147
140
|
pr = pr.then(results => startAsPromise(c).then(r => results.concat([r])))
|
|
@@ -170,16 +163,16 @@ export function runSynchronously(): never {
|
|
|
170
163
|
throw new Error("Asynchronous code cannot be run synchronously in JS");
|
|
171
164
|
}
|
|
172
165
|
|
|
173
|
-
export function start<T>(computation:
|
|
166
|
+
export function start<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
|
|
174
167
|
return startWithContinuations(computation, cancellationToken);
|
|
175
168
|
}
|
|
176
169
|
|
|
177
|
-
export function startImmediate<T>(computation:
|
|
170
|
+
export function startImmediate<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
|
|
178
171
|
return start(computation, cancellationToken);
|
|
179
172
|
}
|
|
180
173
|
|
|
181
174
|
export function startWithContinuations<T>(
|
|
182
|
-
computation:
|
|
175
|
+
computation: Async<T>,
|
|
183
176
|
continuation?: Continuation<T> | CancellationToken,
|
|
184
177
|
exceptionContinuation?: Continuation<any>,
|
|
185
178
|
cancellationContinuation?: Continuation<any>,
|
|
@@ -198,10 +191,8 @@ export function startWithContinuations<T>(
|
|
|
198
191
|
});
|
|
199
192
|
}
|
|
200
193
|
|
|
201
|
-
export function startAsPromise<T>(computation:
|
|
194
|
+
export function startAsPromise<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
|
|
202
195
|
return new Promise((resolve: Continuation<T>, reject: Continuation<any>) =>
|
|
203
196
|
startWithContinuations(computation, resolve, reject, reject,
|
|
204
197
|
cancellationToken ? cancellationToken : defaultCancellationToken));
|
|
205
198
|
}
|
|
206
|
-
|
|
207
|
-
export default Async;
|
package/AsyncBuilder.ts
CHANGED
|
@@ -86,9 +86,9 @@ export interface IAsyncContext<T> {
|
|
|
86
86
|
trampoline: Trampoline;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
export type
|
|
89
|
+
export type Async<T> = (x: IAsyncContext<T>) => void;
|
|
90
90
|
|
|
91
|
-
export function protectedCont<T>(f:
|
|
91
|
+
export function protectedCont<T>(f: Async<T>) {
|
|
92
92
|
return (ctx: IAsyncContext<T>) => {
|
|
93
93
|
if (ctx.cancelToken.isCancelled) {
|
|
94
94
|
ctx.onCancel(new OperationCanceledError());
|
|
@@ -110,7 +110,7 @@ export function protectedCont<T>(f: IAsync<T>) {
|
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
export function protectedBind<T, U>(computation:
|
|
113
|
+
export function protectedBind<T, U>(computation: Async<T>, binder: (x: T) => Async<U>) {
|
|
114
114
|
return protectedCont((ctx: IAsyncContext<U>) => {
|
|
115
115
|
computation({
|
|
116
116
|
onSuccess: (x: T) => {
|
|
@@ -133,19 +133,19 @@ export function protectedReturn<T>(value: T) {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
export class AsyncBuilder {
|
|
136
|
-
public Bind<T, U>(computation:
|
|
136
|
+
public Bind<T, U>(computation: Async<T>, binder: (x: T) => Async<U>) {
|
|
137
137
|
return protectedBind(computation, binder);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
public Combine<T>(computation1:
|
|
140
|
+
public Combine<T>(computation1: Async<void>, computation2: Async<T>) {
|
|
141
141
|
return this.Bind(computation1, () => computation2);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
public Delay<T>(generator: () =>
|
|
144
|
+
public Delay<T>(generator: () => Async<T>) {
|
|
145
145
|
return protectedCont((ctx: IAsyncContext<T>) => generator()(ctx));
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
public For<T>(sequence: Iterable<T>, body: (x: T) =>
|
|
148
|
+
public For<T>(sequence: Iterable<T>, body: (x: T) => Async<void>) {
|
|
149
149
|
const iter = sequence[Symbol.iterator]();
|
|
150
150
|
let cur = iter.next();
|
|
151
151
|
return this.While(() => !cur.done, this.Delay(() => {
|
|
@@ -155,15 +155,15 @@ export class AsyncBuilder {
|
|
|
155
155
|
}));
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
public Return<T>(value
|
|
158
|
+
public Return<T>(value: T) {
|
|
159
159
|
return protectedReturn(value);
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
public ReturnFrom<T>(computation:
|
|
162
|
+
public ReturnFrom<T>(computation: Async<T>) {
|
|
163
163
|
return computation;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
public TryFinally<T>(computation:
|
|
166
|
+
public TryFinally<T>(computation: Async<T>, compensation: () => void) {
|
|
167
167
|
return protectedCont((ctx: IAsyncContext<T>) => {
|
|
168
168
|
computation({
|
|
169
169
|
onSuccess: (x: T) => {
|
|
@@ -184,7 +184,7 @@ export class AsyncBuilder {
|
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
public TryWith<T>(computation:
|
|
187
|
+
public TryWith<T>(computation: Async<T>, catchHandler: (e: any) => Async<T>) {
|
|
188
188
|
return protectedCont((ctx: IAsyncContext<T>) => {
|
|
189
189
|
computation({
|
|
190
190
|
onSuccess: ctx.onSuccess,
|
|
@@ -202,11 +202,11 @@ export class AsyncBuilder {
|
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
public Using<T extends IDisposable, U>(resource: T, binder: (x: T) =>
|
|
205
|
+
public Using<T extends IDisposable, U>(resource: T, binder: (x: T) => Async<U>) {
|
|
206
206
|
return this.TryFinally(binder(resource), () => resource.Dispose());
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
public While(guard: () => boolean, computation:
|
|
209
|
+
public While(guard: () => boolean, computation: Async<void>): Async<void> {
|
|
210
210
|
if (guard()) {
|
|
211
211
|
return this.Bind(computation, () => this.While(guard, computation));
|
|
212
212
|
} else {
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 1.6.0 - 2024-10-02
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
|
|
14
|
+
* Remove `Async` (from `Async.ts`) class (by @MangelMaxime)
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
* Renamed `IAsync` to `Async` in `AsyncBuilder.ts` (#3906) (by @ncave)
|
|
19
|
+
|
|
20
|
+
## 1.5.0 - 2024-09-19
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
* [JS/TS] Add support for `OrdinalIgnoreCase` overload for `String.EndsWith` (#3892) (by @goswinr)
|
|
25
|
+
* [JS/TS] Add `uri.Port`, `uri.IsDefaultPort` (by @MangelMaxime)
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
* [JS/TS] Fix escaping of `{` and `}` in FormattableString (#3890) (by @roboz0r)
|
|
30
|
+
* [JS/TS] Fix `uri.Host` to return the host name without the port (by @MangelMaxime)
|
|
31
|
+
* [JS/TS] Fix TypeScript compilation by resolving type of `jsOptions` (#3894) (by @ManngelMaxime)
|
|
32
|
+
|
|
10
33
|
## 1.4.3 - 2024-09-04
|
|
11
34
|
|
|
12
35
|
* [JS/TS] Fixed Decimal comparisons (#3884) (by @ncave)
|
package/MailboxProcessor.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defaultCancellationToken } from "./Async.js";
|
|
2
2
|
import { fromContinuations } from "./Async.js";
|
|
3
3
|
import { startImmediate } from "./Async.js";
|
|
4
|
-
import {
|
|
4
|
+
import { Async } from "./AsyncBuilder.js";
|
|
5
5
|
import { Continuation, Continuations } from "./AsyncBuilder.js";
|
|
6
6
|
import { CancellationToken } from "./AsyncBuilder.js";
|
|
7
7
|
|
|
@@ -41,7 +41,7 @@ class MailboxQueue<Msg> {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export type MailboxBody<Msg> = (m: MailboxProcessor<Msg>) =>
|
|
44
|
+
export type MailboxBody<Msg> = (m: MailboxProcessor<Msg>) => Async<void>;
|
|
45
45
|
|
|
46
46
|
export interface AsyncReplyChannel<Reply> {
|
|
47
47
|
reply: (r: Reply) => void;
|
package/String.ts
CHANGED
|
@@ -64,12 +64,25 @@ export function compareTo(x: string, y: string) {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export function startsWith(str: string, pattern: string, ic: number) {
|
|
67
|
+
if (ic === StringComparison.Ordinal) { // to avoid substring allocation
|
|
68
|
+
return str.startsWith(pattern);
|
|
69
|
+
}
|
|
67
70
|
if (str.length >= pattern.length) {
|
|
68
71
|
return cmp(str.substr(0, pattern.length), pattern, ic) === 0;
|
|
69
72
|
}
|
|
70
73
|
return false;
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
export function endsWith(str: string, pattern: string, ic: number) {
|
|
77
|
+
if (ic === StringComparison.Ordinal) { // to avoid substring allocation
|
|
78
|
+
return str.endsWith(pattern);
|
|
79
|
+
}
|
|
80
|
+
if (str.length >= pattern.length) {
|
|
81
|
+
return cmp(str.substr(str.length - pattern.length, pattern.length), pattern, ic) === 0;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
73
86
|
export function indexOfAny(str: string, anyOf: string[], ...args: number[]) {
|
|
74
87
|
if (str == null || str === "") {
|
|
75
88
|
return -1;
|
|
@@ -87,7 +100,7 @@ export function indexOfAny(str: string, anyOf: string[], ...args: number[]) {
|
|
|
87
100
|
}
|
|
88
101
|
const endIndex = startIndex + length
|
|
89
102
|
const anyOfAsStr = "".concat.apply("", anyOf);
|
|
90
|
-
for (let i=startIndex; i<endIndex; i++) {
|
|
103
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
91
104
|
if (anyOfAsStr.indexOf(str[i]) > -1) {
|
|
92
105
|
return i;
|
|
93
106
|
}
|
|
@@ -374,10 +387,6 @@ export function format(str: string | object, ...args: any[]) {
|
|
|
374
387
|
});
|
|
375
388
|
}
|
|
376
389
|
|
|
377
|
-
export function endsWith(str: string, search: string) {
|
|
378
|
-
const idx = str.lastIndexOf(search);
|
|
379
|
-
return idx >= 0 && idx === str.length - search.length;
|
|
380
|
-
}
|
|
381
390
|
|
|
382
391
|
export function initialize(n: number, f: (i: number) => string) {
|
|
383
392
|
if (n < 0) {
|
|
@@ -587,7 +596,11 @@ export function fmtWith(fmts: string[]) {
|
|
|
587
596
|
}
|
|
588
597
|
|
|
589
598
|
export function getFormat(s: FormattableString) {
|
|
599
|
+
const strs = s.strs.map((value) => value.replace(/{/g, '{{').replace(/}/g, '}}'));
|
|
600
|
+
|
|
590
601
|
return s.fmts
|
|
591
|
-
?
|
|
592
|
-
|
|
602
|
+
? strs
|
|
603
|
+
.reduce((acc, newPart, index) => acc + `{${String(index - 1) + s.fmts![index - 1]}}` + newPart)
|
|
604
|
+
: strs
|
|
605
|
+
.reduce((acc, newPart, index) => acc + `{${index - 1}}` + newPart);
|
|
593
606
|
}
|
package/Uri.ts
CHANGED
|
@@ -177,7 +177,13 @@ export class Uri {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
get host() {
|
|
180
|
-
|
|
180
|
+
const host = this.asUrl().host;
|
|
181
|
+
|
|
182
|
+
if (host.includes(":")) {
|
|
183
|
+
return host.split(":")[0];
|
|
184
|
+
} else {
|
|
185
|
+
return host;
|
|
186
|
+
}
|
|
181
187
|
}
|
|
182
188
|
|
|
183
189
|
get absolutePath() {
|
|
@@ -188,6 +194,20 @@ export class Uri {
|
|
|
188
194
|
return this.asUrl().search;
|
|
189
195
|
}
|
|
190
196
|
|
|
197
|
+
get isDefaultPort() {
|
|
198
|
+
return this.port === 80;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
get port() {
|
|
202
|
+
const port = this.asUrl().port;
|
|
203
|
+
|
|
204
|
+
if (port === "") {
|
|
205
|
+
return 80;
|
|
206
|
+
} else {
|
|
207
|
+
return parseInt(port);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
191
211
|
get pathAndQuery() {
|
|
192
212
|
const url = this.asUrl();
|
|
193
213
|
return url.pathname + url.search;
|
package/Util.ts
CHANGED
|
@@ -588,8 +588,8 @@ export function createObj(fields: Iterable<[string, any]>) {
|
|
|
588
588
|
return obj;
|
|
589
589
|
}
|
|
590
590
|
|
|
591
|
-
export function jsOptions(mutator: (x:
|
|
592
|
-
const opts = {};
|
|
591
|
+
export function jsOptions<T>(mutator: (x: T) => void): T {
|
|
592
|
+
const opts = {} as T;
|
|
593
593
|
mutator(opts);
|
|
594
594
|
return opts;
|
|
595
595
|
}
|
package/package.json
CHANGED