@fable-org/fable-library-ts 1.5.0 → 1.7.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 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 { IAsync } from "./AsyncBuilder.js";
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: () => IAsync<T>) {
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: IAsync<T>) {
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: IAsync<T>, ctx: IAsyncContext<T>) {
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) => IAsync<T>) {
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: IAsync<U>, part2: (x: U) => IAsync<T>) {
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) : IAsync<void> {
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: IAsync<T>, ms?: number): IAsync<IAsync<T>> {
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: IAsync<T>) {
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: IAsync<T>) {
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<IAsync<T>>) {
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: IAsync<T>, b: IAsync<U>): IAsync<[T, U]> {
139
- return delay(() => awaitPromise(Promise.all([ startAsPromise(a), startAsPromise(b) ])));
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<IAsync<T>>) {
135
+ export function sequential<T>(computations: Iterable<Async<T>>) {
143
136
 
144
- function _sequential<T>(computations: Iterable<IAsync<T>>): Promise<T[]> {
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: IAsync<T>, cancellationToken?: CancellationToken) {
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: IAsync<T>, cancellationToken?: CancellationToken) {
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: IAsync<T>,
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: IAsync<T>, cancellationToken?: CancellationToken) {
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 IAsync<T> = (x: IAsyncContext<T>) => void;
89
+ export type Async<T> = (x: IAsyncContext<T>) => void;
90
90
 
91
- export function protectedCont<T>(f: IAsync<T>) {
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: IAsync<T>, binder: (x: T) => IAsync<U>) {
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: IAsync<T>, binder: (x: T) => IAsync<U>) {
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: IAsync<void>, computation2: IAsync<T>) {
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: () => IAsync<T>) {
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) => IAsync<void>) {
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?: T) {
158
+ public Return<T>(value: T) {
159
159
  return protectedReturn(value);
160
160
  }
161
161
 
162
- public ReturnFrom<T>(computation: IAsync<T>) {
162
+ public ReturnFrom<T>(computation: Async<T>) {
163
163
  return computation;
164
164
  }
165
165
 
166
- public TryFinally<T>(computation: IAsync<T>, compensation: () => void) {
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: IAsync<T>, catchHandler: (e: any) => IAsync<T>) {
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) => IAsync<U>) {
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: IAsync<void>): IAsync<void> {
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,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 1.7.0 - 2024-11-19
11
+
12
+ ### Fixed
13
+
14
+ * [JS/TS] Added missing IReadOnlyCollection helpers (#3953)
15
+
16
+ ## 1.6.0 - 2024-10-02
17
+
18
+ ### Removed
19
+
20
+ * Remove `Async` (from `Async.ts`) class (by @MangelMaxime)
21
+
22
+ ### Changed
23
+
24
+ * Renamed `IAsync` to `Async` in `AsyncBuilder.ts` (#3906) (by @ncave)
25
+
10
26
  ## 1.5.0 - 2024-09-19
11
27
 
12
28
  ### Added
@@ -0,0 +1,161 @@
1
+ import { equals, isArrayLike } from "./Util.js";
2
+
3
+ export function count<T>(col: Iterable<T>): number {
4
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.get_Count"] === "function") {
5
+ return (col as any)["System.Collections.Generic.ICollection`1.get_Count"](); // collection
6
+ } else {
7
+ if (typeof (col as any)["System.Collections.Generic.IReadOnlyCollection`1.get_Count"] === "function") {
8
+ return (col as any)["System.Collections.Generic.IReadOnlyCollection`1.get_Count"](); // collection
9
+ } else {
10
+ if (isArrayLike(col)) {
11
+ return col.length; // array, resize array
12
+ } else {
13
+ if (typeof (col as any).size === "number") {
14
+ return (col as any).size; // map, set
15
+ } else {
16
+ let count = 0;
17
+ for (const _ of col) {
18
+ count++;
19
+ }
20
+ return count; // other collections
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ export function isReadOnly<T>(col: Iterable<T>): boolean {
28
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.get_IsReadOnly"] === "function") {
29
+ return (col as any)["System.Collections.Generic.ICollection`1.get_IsReadOnly"](); // collection
30
+ } else {
31
+ if (isArrayLike(col)) {
32
+ return ArrayBuffer.isView(col); // true for typed arrays, false for other arrays
33
+ } else {
34
+ if (typeof (col as any).size === "number") {
35
+ return false; // map, set
36
+ } else {
37
+ return true; // other collections
38
+ }
39
+ }
40
+
41
+ }
42
+ }
43
+
44
+ export function copyTo<T>(col: Iterable<T>, array: T[], arrayIndex: number) {
45
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.CopyToZ3B4C077E"] === "function") {
46
+ (col as any)["System.Collections.Generic.ICollection`1.CopyToZ3B4C077E"](array, arrayIndex); // collection
47
+ } else {
48
+ let i = arrayIndex;
49
+ for (const v of col) {
50
+ array[i] = v;
51
+ i++;
52
+ }
53
+ }
54
+ }
55
+
56
+ export function contains<T>(col: Iterable<T>, item: T): boolean {
57
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.Contains2B595"] === "function") {
58
+ return (col as any)["System.Collections.Generic.ICollection`1.Contains2B595"](item); // collection
59
+ } else {
60
+ if (isArrayLike(col)) {
61
+ let i = col.findIndex(x => equals(x, item)); // array, resize array
62
+ return i >= 0;
63
+ } else {
64
+ if (typeof (col as any).has === "function") {
65
+ if (typeof (col as any).set === "function" && isArrayLike(item)) {
66
+ return (col as any).has(item[0]) && equals((col as any).get(item[0]), item[1]); // map
67
+ } else {
68
+ return (col as any).has(item); // set
69
+ }
70
+ } else {
71
+ return false; // other collections
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ export function add<T>(col: Iterable<T>, item: T): void {
78
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.Add2B595"] === "function") {
79
+ return (col as any)["System.Collections.Generic.ICollection`1.Add2B595"](item); // collection
80
+ } else {
81
+ if (isArrayLike(col)) {
82
+ if (ArrayBuffer.isView(col)) {
83
+ // TODO: throw for typed arrays?
84
+ } else {
85
+ col.push(item); // array, resize array
86
+ }
87
+ } else {
88
+ if (typeof (col as any).add === "function") {
89
+ return (col as any).add(item); // set
90
+ } else {
91
+ if (typeof (col as any).has === "function"
92
+ && typeof (col as any).set === "function"
93
+ && isArrayLike(item)) {
94
+ if ((col as any).has(item[0]) === false) {
95
+ (col as any).set(item[0], item[1]); // map
96
+ } else {
97
+ throw new Error("An item with the same key has already been added. Key: " + item[0]);
98
+ }
99
+ } else {
100
+ // TODO: throw for other collections?
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ export function remove<T>(col: Iterable<T>, item: T): boolean {
108
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.Remove2B595"] === "function") {
109
+ return (col as any)["System.Collections.Generic.ICollection`1.Remove2B595"](item); // collection
110
+ } else {
111
+ if (isArrayLike(col)) {
112
+ if (ArrayBuffer.isView(col)) {
113
+ // TODO: throw for typed arrays
114
+ return false;
115
+ } else {
116
+ let i = col.findIndex(x => equals(x, item));
117
+ if (i >= 0) {
118
+ col.splice(i, 1); // array, resize array
119
+ return true;
120
+ } else {
121
+ return false;
122
+ }
123
+ }
124
+ } else {
125
+ if (typeof (col as any).delete === "function") {
126
+ if (typeof (col as any).set === "function" && isArrayLike(item)) {
127
+ if ((col as any).has(item[0]) && equals((col as any).get(item[0]), item[1])) {
128
+ return (col as any).delete(item[0]); // map
129
+ } else {
130
+ return false;
131
+ }
132
+ } else {
133
+ return (col as any).delete(item); // set
134
+ }
135
+ } else {
136
+ // TODO: throw for other collections?
137
+ return false; // other collections
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ export function clear<T>(col: Iterable<T>): void {
144
+ if (typeof (col as any)["System.Collections.Generic.ICollection`1.Clear"] === "function") {
145
+ return (col as any)["System.Collections.Generic.ICollection`1.Clear"](); // collection
146
+ } else {
147
+ if (isArrayLike(col)) {
148
+ if (ArrayBuffer.isView(col)) {
149
+ // TODO: throw for typed arrays?
150
+ } else {
151
+ col.splice(0); // array, resize array
152
+ }
153
+ } else {
154
+ if (typeof (col as any).clear === "function") {
155
+ (col as any).clear(); // map, set
156
+ } else {
157
+ // TODO: throw for other collections?
158
+ }
159
+ }
160
+ }
161
+ }
@@ -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 { IAsync } from "./AsyncBuilder.js";
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>) => IAsync<void>;
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
@@ -63,7 +63,7 @@ export function compareTo(x: string, y: string) {
63
63
  return cmp(x, y, StringComparison.CurrentCulture);
64
64
  }
65
65
 
66
- export function startsWith(str: string, pattern: string, ic: number) {
66
+ export function startsWith(str: string, pattern: string, ic: boolean | StringComparison) {
67
67
  if (ic === StringComparison.Ordinal) { // to avoid substring allocation
68
68
  return str.startsWith(pattern);
69
69
  }
@@ -73,7 +73,7 @@ export function startsWith(str: string, pattern: string, ic: number) {
73
73
  return false;
74
74
  }
75
75
 
76
- export function endsWith(str: string, pattern: string, ic: number) {
76
+ export function endsWith(str: string, pattern: string, ic: boolean | StringComparison) {
77
77
  if (ic === StringComparison.Ordinal) { // to avoid substring allocation
78
78
  return str.endsWith(pattern);
79
79
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "private": false,
4
4
  "type": "module",
5
5
  "name": "@fable-org/fable-library-ts",
6
- "version": "1.5.0",
6
+ "version": "1.7.0",
7
7
  "description": "Core library used by F# projects compiled with fable.io",
8
8
  "author": "Fable Contributors",
9
9
  "license": "MIT",