@fable-org/fable-library-js 2.9.0 → 2.11.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/Array.js +272 -167
- package/Async.js +167 -22
- package/BigInt.js +18 -6
- package/CHANGELOG.md +52 -1
- package/Date.js +1 -1
- package/Decimal.js +70 -11
- package/Double.js +25 -10
- package/FSharp.Core.js +7 -1
- package/Global.js +1 -1
- package/Int32.js +10 -1
- package/List.js +226 -156
- package/Long.js +7 -2
- package/Map.js +46 -39
- package/MutableMap.js +76 -96
- package/MutableSet.js +58 -80
- package/NumberStyles.js +56 -0
- package/Numeric.js +10 -4
- package/Random.js +3 -4
- package/Range.js +4 -3
- package/RegExp.js +3 -2
- package/Seq.js +132 -64
- package/Seq2.js +4 -8
- package/Set.js +64 -57
- package/Stopwatch.js +65 -0
- package/String.js +18 -16
- package/System.Collections.Generic.js +3 -2
- package/System.Text.js +2 -2
- package/Task.js +22 -0
- package/TimeOnly.js +1 -1
- package/Types.js +25 -10
- package/Util.js +91 -48
- package/big.d.ts +1 -0
- package/lib/big.js +113 -70
- package/package.json +1 -1
package/Async.js
CHANGED
|
@@ -2,8 +2,8 @@ import { OperationCanceledException, Trampoline } from "./AsyncBuilder.js";
|
|
|
2
2
|
import { CancellationToken } from "./AsyncBuilder.js";
|
|
3
3
|
import { protectedCont, protectedBind, protectedReturn } from "./AsyncBuilder.js";
|
|
4
4
|
import { Choice_makeChoice1Of2, Choice_makeChoice2Of2 } from "./Choice.js";
|
|
5
|
-
import { InvalidOperationException_$ctor_Z721C83C5, TimeoutException_$ctor } from "./System.js";
|
|
6
|
-
import { Exception } from "./Util.js";
|
|
5
|
+
import { ArgumentException_$ctor_Z384F8060, InvalidOperationException_$ctor_Z721C83C5, TimeoutException_$ctor } from "./System.js";
|
|
6
|
+
import { Exception, ensureErrorOrException } from "./Util.js";
|
|
7
7
|
function emptyContinuation(_x) {
|
|
8
8
|
// NOP
|
|
9
9
|
}
|
|
@@ -44,27 +44,43 @@ export function throwIfCancellationRequested(token) {
|
|
|
44
44
|
throw new Exception("Operation is cancelled");
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
// The parent keeps the listener until unlink is called
|
|
48
|
+
function createLinkedToken(parent) {
|
|
49
|
+
const token = new CancellationToken();
|
|
50
|
+
const id = parent.addListener(() => token.cancel());
|
|
51
|
+
return [token, () => { parent.removeListener(id); }];
|
|
52
|
+
}
|
|
47
53
|
export function startChild(computation, ms) {
|
|
48
54
|
return protectedCont((ctx) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
const timeout = ms == null || ms === -1 ? undefined : ms;
|
|
56
|
+
const [childToken, unlink] = timeout === undefined
|
|
57
|
+
? [ctx.cancelToken, () => { }]
|
|
58
|
+
: createLinkedToken(ctx.cancelToken);
|
|
59
|
+
const promise = startAsPromise(computation, childToken);
|
|
60
|
+
let settled = false;
|
|
61
|
+
const onSettled = () => { settled = true; unlink(); };
|
|
62
|
+
// Without a rejection handler an unawaited child's failure is an unhandled rejection
|
|
63
|
+
promise.then(onSettled, onSettled);
|
|
64
|
+
// Like .NET, the timeout only runs while the result is awaited, not from the start of the child
|
|
65
|
+
const awaitResult = () => timeout === undefined || settled ? promise : new Promise((resolve, reject) => {
|
|
66
|
+
const timeoutId = setTimeout(() => {
|
|
67
|
+
// .NET doesn't cancel the child when the timeout is 0
|
|
68
|
+
if (timeout !== 0) {
|
|
69
|
+
try {
|
|
70
|
+
childToken.cancel();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
reject(error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
reject(TimeoutException_$ctor());
|
|
78
|
+
}, timeout);
|
|
79
|
+
promise.then(value => { clearTimeout(timeoutId); resolve(value); }, error => { clearTimeout(timeoutId); reject(error); });
|
|
80
|
+
});
|
|
65
81
|
// JS Promises are hot, computation has already started
|
|
66
82
|
// but we delay returning the result
|
|
67
|
-
protectedReturn(awaitPromise(
|
|
83
|
+
protectedReturn(protectedCont((awaitCtx) => awaitPromise(awaitResult())(awaitCtx)))(ctx);
|
|
68
84
|
});
|
|
69
85
|
}
|
|
70
86
|
export function awaitPromise(p) {
|
|
@@ -154,9 +170,132 @@ export function fromContinuations(f) {
|
|
|
154
170
|
export function ignore(computation) {
|
|
155
171
|
return protectedBind(computation, (_x) => protectedReturn(void 0));
|
|
156
172
|
}
|
|
157
|
-
export function parallel(computations) {
|
|
158
|
-
|
|
159
|
-
|
|
173
|
+
export function parallel(computations, maxDegreeOfParallelism) {
|
|
174
|
+
if (maxDegreeOfParallelism != null && maxDegreeOfParallelism < 1) {
|
|
175
|
+
throw ArgumentException_$ctor_Z384F8060(`maxDegreeOfParallelism must be positive, was ${maxDegreeOfParallelism}`, "maxDegreeOfParallelism");
|
|
176
|
+
}
|
|
177
|
+
return protectedCont((ctx) => awaitPromise(runParallel(Array.from(computations), maxDegreeOfParallelism, ctx.cancelToken))(ctx));
|
|
178
|
+
}
|
|
179
|
+
function runParallel(computations, limit, parentToken) {
|
|
180
|
+
return new Promise((resolve, reject) => {
|
|
181
|
+
const count = computations.length;
|
|
182
|
+
const results = new Array(count);
|
|
183
|
+
const [token, unlink] = createLinkedToken(parentToken);
|
|
184
|
+
let next = 0;
|
|
185
|
+
let running = 0;
|
|
186
|
+
let failed = false;
|
|
187
|
+
let failure;
|
|
188
|
+
const startNext = () => {
|
|
189
|
+
const i = next++;
|
|
190
|
+
running++;
|
|
191
|
+
startAsPromise(computations[i], token)
|
|
192
|
+
.then((x) => { results[i] = x; }, (err) => {
|
|
193
|
+
if (!failed) {
|
|
194
|
+
failed = true;
|
|
195
|
+
failure = err;
|
|
196
|
+
try {
|
|
197
|
+
token.cancel();
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
failure = error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
.then(() => {
|
|
205
|
+
running--;
|
|
206
|
+
if (!failed && next < count) {
|
|
207
|
+
startNext();
|
|
208
|
+
}
|
|
209
|
+
else if (running === 0) {
|
|
210
|
+
unlink();
|
|
211
|
+
if (failed) {
|
|
212
|
+
reject(failure);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
resolve(results);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
if (count === 0) {
|
|
221
|
+
unlink();
|
|
222
|
+
resolve(results);
|
|
223
|
+
}
|
|
224
|
+
const initial = Math.min(limit ?? count, count);
|
|
225
|
+
while (next < initial) {
|
|
226
|
+
startNext();
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
export function choice(computations) {
|
|
231
|
+
return protectedCont((ctx) => {
|
|
232
|
+
const works = Array.from(computations);
|
|
233
|
+
let remaining = works.length;
|
|
234
|
+
if (remaining === 0) {
|
|
235
|
+
ctx.onSuccess(undefined);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const [token, unlink] = createLinkedToken(ctx.cancelToken);
|
|
239
|
+
let done = false;
|
|
240
|
+
const finish = (report) => {
|
|
241
|
+
if (done) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
done = true;
|
|
245
|
+
unlink();
|
|
246
|
+
try {
|
|
247
|
+
token.cancel();
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
ctx.onError(ensureErrorOrException(error));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
report();
|
|
254
|
+
};
|
|
255
|
+
for (const work of works) {
|
|
256
|
+
startWithContinuations(work, (x) => {
|
|
257
|
+
if (x != null) {
|
|
258
|
+
finish(() => ctx.onSuccess(x));
|
|
259
|
+
}
|
|
260
|
+
else if (--remaining === 0) {
|
|
261
|
+
finish(() => ctx.onSuccess(undefined));
|
|
262
|
+
}
|
|
263
|
+
}, (err) => finish(() => ctx.onError(err)), (err) => finish(() => ctx.onCancel(err)), token);
|
|
264
|
+
if (done) {
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
export function onCancel(interruption) {
|
|
271
|
+
return protectedCont((ctx) => {
|
|
272
|
+
const token = ctx.cancelToken;
|
|
273
|
+
let interrupted = false;
|
|
274
|
+
const interrupt = () => {
|
|
275
|
+
if (!interrupted) {
|
|
276
|
+
interrupted = true;
|
|
277
|
+
try {
|
|
278
|
+
interruption();
|
|
279
|
+
}
|
|
280
|
+
catch { /* Ignored, like .NET Async.OnCancel */ }
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const id = token.addListener(interrupt);
|
|
284
|
+
let disposed = false;
|
|
285
|
+
ctx.onSuccess({
|
|
286
|
+
Dispose() {
|
|
287
|
+
if (disposed) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
disposed = true;
|
|
291
|
+
token.removeListener(id);
|
|
292
|
+
// With use! Dispose runs inside cancel() before this listener gets its turn
|
|
293
|
+
if (token.isCancelled) {
|
|
294
|
+
interrupt();
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
});
|
|
160
299
|
}
|
|
161
300
|
export function sequential(computations) {
|
|
162
301
|
function _sequential(computations, cancelToken) {
|
|
@@ -216,3 +355,9 @@ export function startWithContinuations(computation, continuation, exceptionConti
|
|
|
216
355
|
export function startAsPromise(computation, cancellationToken) {
|
|
217
356
|
return new Promise((resolve, reject) => startWithContinuations(computation, resolve, reject, reject, cancellationToken ? cancellationToken : defaultCancellationToken));
|
|
218
357
|
}
|
|
358
|
+
export function startAsTask(computation, _taskCreationOptions, cancellationToken) {
|
|
359
|
+
return startAsPromise(computation, cancellationToken);
|
|
360
|
+
}
|
|
361
|
+
export function startImmediateAsTask(computation, cancellationToken) {
|
|
362
|
+
return startAsPromise(computation, cancellationToken);
|
|
363
|
+
}
|
package/BigInt.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { FSharpRef } from "./Types.js";
|
|
1
2
|
import { fromParts, truncate } from "./Decimal.js";
|
|
2
3
|
import { Exception, bigintHash } from "./Util.js";
|
|
4
|
+
import { ArgumentNullException_$ctor_Z721C83C5, FormatException_$ctor_Z721C83C5 } from "./System.js";
|
|
3
5
|
const isBigEndian = false;
|
|
4
6
|
BigInt.prototype.toJSON = function () {
|
|
5
7
|
return `${this.toString()}`;
|
|
@@ -151,17 +153,27 @@ export function toChar(x) {
|
|
|
151
153
|
return String.fromCharCode(toUInt16(x));
|
|
152
154
|
}
|
|
153
155
|
export function toString(x) { return x.toString(); }
|
|
156
|
+
// .NET's Integer style: white space, a sign and decimal digits, then NULs
|
|
157
|
+
const integerRegex = /^[\t-\r ]*([+-]?\d+)[\t-\r ]*\0*$/;
|
|
154
158
|
export function tryParse(s, res) {
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
const m = s == null ? null : integerRegex.exec(s);
|
|
160
|
+
if (m != null) {
|
|
161
|
+
res.contents = BigInt(m[1]);
|
|
157
162
|
return true;
|
|
158
163
|
}
|
|
159
|
-
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
164
|
+
return false;
|
|
162
165
|
}
|
|
163
166
|
export function parse(s) {
|
|
164
|
-
|
|
167
|
+
const res = new FSharpRef(zero);
|
|
168
|
+
if (tryParse(s, res)) {
|
|
169
|
+
return res.contents;
|
|
170
|
+
}
|
|
171
|
+
else if (s == null) {
|
|
172
|
+
throw ArgumentNullException_$ctor_Z721C83C5("value");
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
throw FormatException_$ctor_Z721C83C5("The value could not be parsed.");
|
|
176
|
+
}
|
|
165
177
|
}
|
|
166
178
|
export function pow(x, n) {
|
|
167
179
|
return x ** BigInt(n);
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
last_commit_released:
|
|
2
|
+
last_commit_released: ce886964cb4521dc4c01c8da089b97c9d9742814
|
|
3
3
|
updaters:
|
|
4
4
|
- package.json:
|
|
5
5
|
file: package.json
|
|
@@ -15,6 +15,57 @@ All notable changes to this project will be documented in this file.
|
|
|
15
15
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
16
16
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
17
17
|
|
|
18
|
+
## 2.11.0 - 2026-10-29
|
|
19
|
+
|
|
20
|
+
### 🚀 Features
|
|
21
|
+
|
|
22
|
+
* *(js/ts/python/dart/beam)* Support System.Array.BinarySearch and ResizeArray.BinarySearch (#5172) ([d332e7d4](https://github.com/fable-compiler/Fable/commit/d332e7d42c889f172bb9501f505292abf519752f))
|
|
23
|
+
|
|
24
|
+
### 🐞 Bug Fixes
|
|
25
|
+
|
|
26
|
+
* *(all)* Accept RegexOptions.NonBacktracking (#5178) ([a61ec8a1](https://github.com/fable-compiler/Fable/commit/a61ec8a1583830599a7ffb2dfb4d093e99902d4f))
|
|
27
|
+
* *(js/ts)* Format DateTimeOffset in its own offset (#5171) ([04ddbd20](https://github.com/fable-compiler/Fable/commit/04ddbd2027e03f4cf7b0b22fe886fdabadf26d93))
|
|
28
|
+
* *(js/ts)* Support %o in sprintf and interpolated strings (#5175) ([e13e7b0f](https://github.com/fable-compiler/Fable/commit/e13e7b0fdc16d26793833c77a11d242ccc61109b))
|
|
29
|
+
* *(js/ts)* Parse numbers like .NET and raise its exception types (#5200) ([82e606e9](https://github.com/fable-compiler/Fable/commit/82e606e9f8567d9bdad743df1b5de6abbdda89b0))
|
|
30
|
+
* *(js/ts)* Honor NumberStyles when parsing floats (#5217) ([82b935f3](https://github.com/fable-compiler/Fable/commit/82b935f3859b36923e5e0eb26771f860eadbe525))
|
|
31
|
+
* *(js/ts/python/dart/beam)* Raise typed exceptions from invalidArg and invalidOp ([60f2f5b9](https://github.com/fable-compiler/Fable/commit/60f2f5b9fa0e6a26af0f3b4f3cddc2496f075ba3))
|
|
32
|
+
* *(js/ts/python/dart/beam)* Align collection exception types with FSharp.Core (#5153) ([7d7ceb33](https://github.com/fable-compiler/Fable/commit/7d7ceb33afd85a25bf06dc703e9d4a471cbc3292))
|
|
33
|
+
* *(js/ts/python/dart/beam)* Add FSharp.Core's argument checks to collection functions (#5154) ([5185e654](https://github.com/fable-compiler/Fable/commit/5185e6547416384fe85fcb0b0c1cf267708879db))
|
|
34
|
+
|
|
35
|
+
### ⚡ Performance Improvements
|
|
36
|
+
|
|
37
|
+
* *(js/ts)* Standard library combine numeric hash from snapshot of object instead of mapping (#5151) ([44495104](https://github.com/fable-compiler/Fable/commit/44495104b5c7ac65bfcea184d1305fd29f1db9b4))
|
|
38
|
+
* *(js/ts)* Standard library remove .map result array from record hash using snapshot (#5150) ([0ceb5e9e](https://github.com/fable-compiler/Fable/commit/0ceb5e9ec5b470d00295a5cea9ead1c621c7858e))
|
|
39
|
+
* *(js/ts)* Standard library one pass List.append builder (#5148) ([2ed9d6dd](https://github.com/fable-compiler/Fable/commit/2ed9d6dd0a372e5bcf53dfe24d786bf9b9256fd3))
|
|
40
|
+
* *(js/ts)* List node as a class with a shared empty node (#5185) ([187f8985](https://github.com/fable-compiler/Fable/commit/187f89852413186b52d4ecdde55e1be7cf736785))
|
|
41
|
+
* *(js/ts)* Check array bounds only on undefined reads (#5188) ([435fc0bb](https://github.com/fable-compiler/Fable/commit/435fc0bb008ff2ab7c14a08c7218be94f4735029))
|
|
42
|
+
* *(js/ts)* Closure-free ref cells and out-arg value cells (#5189) ([91bca925](https://github.com/fable-compiler/Fable/commit/91bca925757356191c7e6e7a71cb3e8a1bc8d52d))
|
|
43
|
+
* *(js/ts)* Keep the curried original on its adapter (#5191) ([bfb4a2a4](https://github.com/fable-compiler/Fable/commit/bfb4a2a4e3bb1b5bd4491955a1e1cb90c14050b6))
|
|
44
|
+
* *(js/ts)* Walk arrays by index when enumerated as seq (#5192) ([d88621c3](https://github.com/fable-compiler/Fable/commit/d88621c3b9d6ce48a72dc09b86a6805f612ac185))
|
|
45
|
+
* *(js/ts)* Hash unions without allocating (#5195) ([2b66a5d2](https://github.com/fable-compiler/Fable/commit/2b66a5d2184f3a35f0d73fb397ab902e300ac4bd))
|
|
46
|
+
* *(js/ts)* Probe dictionary buckets without allocating (#5196) ([9517eafd](https://github.com/fable-compiler/Fable/commit/9517eafd93aa7b84061662a421b7a39a7269318b))
|
|
47
|
+
|
|
48
|
+
<strong><small>[View changes on Github](https://github.com/fable-compiler/Fable/compare/2098f64a25e96385306ef19ed8c289f3b6c84db9..ce886964cb4521dc4c01c8da089b97c9d9742814)</small></strong>
|
|
49
|
+
|
|
50
|
+
## 2.10.0 - 2026-10-22
|
|
51
|
+
|
|
52
|
+
### 🚀 Features
|
|
53
|
+
|
|
54
|
+
* *(js/ts)* Support System.Diagnostics.Stopwatch (#5100) ([eb68225f](https://github.com/fable-compiler/Fable/commit/eb68225ff74d1b455765d99998faa6fd3be32383))
|
|
55
|
+
|
|
56
|
+
### 🐞 Bug Fixes
|
|
57
|
+
|
|
58
|
+
* *(js/ts)* Round decimals below 0.1 correctly ([fca4c408](https://github.com/fable-compiler/Fable/commit/fca4c408a64e33c58293f12869975e5b61bcb96a))
|
|
59
|
+
* *(js/ts)* Keep decimal zero scale without leading zeros ([3076b45a](https://github.com/fable-compiler/Fable/commit/3076b45acacf39b8c99ec57025560ad355ab74db))
|
|
60
|
+
* *(js/ts)* Hash decimals by value in collections ([32a69e0d](https://github.com/fable-compiler/Fable/commit/32a69e0d00f567c9a838307e9ed51b3b1d519473))
|
|
61
|
+
* *(js/ts)* Keep .NET decimal scale through arithmetic (#5126) ([bdf0a6c8](https://github.com/fable-compiler/Fable/commit/bdf0a6c8cb56151a5431b5e3703f7ee165b26dba))
|
|
62
|
+
* *(js/ts)* Accept decimal integers up to 2^96 ([c9feb339](https://github.com/fable-compiler/Fable/commit/c9feb339fb8a4e98bebf17b3facdc42ecd22d628))
|
|
63
|
+
* *(js/ts)* Align decimal conversion, parsing and G format ([6430cdac](https://github.com/fable-compiler/Fable/commit/6430cdacec34e6327434af649eb0c9427d65608c))
|
|
64
|
+
* *(js/ts)* Add missing Async and Task members, cancel timed-out StartChild, bind Async in task { } (#5097) ([d063630d](https://github.com/fable-compiler/Fable/commit/d063630d58d62db21603d45a6bf54b172378c66e))
|
|
65
|
+
* *(js/ts)* Respect maxDegreeOfParallelism and cancel on failure in Async.Parallel (#5098) ([5de3271d](https://github.com/fable-compiler/Fable/commit/5de3271d8b47f1752c4e74c010e4314cf40bbcbe))
|
|
66
|
+
|
|
67
|
+
<strong><small>[View changes on Github](https://github.com/fable-compiler/Fable/compare/e33c57870454fea189a3eb33519f583a5003f8c3..2098f64a25e96385306ef19ed8c289f3b6c84db9)</small></strong>
|
|
68
|
+
|
|
18
69
|
## 2.9.0 - 2026-10-16
|
|
19
70
|
|
|
20
71
|
### 🚀 Features
|
package/Date.js
CHANGED
|
@@ -376,7 +376,7 @@ function dateToISOStringWithOffset(dateWithOffset, offset) {
|
|
|
376
376
|
return str.substring(0, str.length - 1) + dateOffsetToString(offset);
|
|
377
377
|
}
|
|
378
378
|
function dateToStringWithOffset(date, format) {
|
|
379
|
-
const d =
|
|
379
|
+
const d = DateTime(date.getTime() + (date.offset ?? 0), DateTimeKind.Utc);
|
|
380
380
|
if (typeof format !== "string") {
|
|
381
381
|
return d.toISOString().replace(/\.\d+/, "").replace(/[A-Z]|\.\d+/g, " ") + dateOffsetToString((date.offset ?? 0));
|
|
382
382
|
}
|
package/Decimal.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import Decimal from "./lib/big.js";
|
|
2
2
|
import { symbol } from "./Numeric.js";
|
|
3
|
-
import { FSharpRef } from "./Types.js";
|
|
4
3
|
import { Exception, combineHashCodes } from "./Util.js";
|
|
4
|
+
import { NumberStyles, splitNumber } from "./NumberStyles.js";
|
|
5
|
+
import { ArgumentNullException_$ctor_Z721C83C5, FormatException_$ctor_Z721C83C5, OverflowException_$ctor_Z721C83C5 } from "./System.js";
|
|
5
6
|
import { fromDecimal } from "./BigInt.js";
|
|
6
7
|
import * as bigInt from "./BigInt.js";
|
|
7
8
|
Decimal.prototype.GetHashCode = function () {
|
|
8
|
-
|
|
9
|
+
const digits = this.c;
|
|
10
|
+
if (digits[0] === 0) {
|
|
11
|
+
return combineHashCodes([1, 0, 0]);
|
|
12
|
+
}
|
|
13
|
+
let end = digits.length;
|
|
14
|
+
while (digits[end - 1] === 0) {
|
|
15
|
+
end--;
|
|
16
|
+
}
|
|
17
|
+
return combineHashCodes([this.s, this.e].concat(digits.slice(0, end)));
|
|
9
18
|
};
|
|
10
19
|
Decimal.prototype.Equals = function (x) {
|
|
11
20
|
return !this.cmp(x);
|
|
@@ -37,7 +46,7 @@ export function equals(x, y) {
|
|
|
37
46
|
}
|
|
38
47
|
export function abs(x) { return x.abs(); }
|
|
39
48
|
export function sign(x) { return x.lt(get_Zero) ? -1 : x.gt(get_Zero) ? 1 : 0; }
|
|
40
|
-
export function max(x, y) { return x.
|
|
49
|
+
export function max(x, y) { return x.lt(y) ? y : x; }
|
|
41
50
|
export function min(x, y) { return x.lt(y) ? x : y; }
|
|
42
51
|
export function maxMagnitude(x, y) { return abs(x).gt(abs(y)) ? x : y; }
|
|
43
52
|
export function minMagnitude(x, y) { return abs(x).lt(abs(y)) ? x : y; }
|
|
@@ -94,23 +103,47 @@ export const negate = op_UnaryNegation;
|
|
|
94
103
|
export function toString(x) {
|
|
95
104
|
return x.toString();
|
|
96
105
|
}
|
|
97
|
-
|
|
106
|
+
// Returns undefined when the string does not have the format allowed by the style
|
|
107
|
+
function parseWithStyle(str, style) {
|
|
108
|
+
const parts = splitNumber(str, style);
|
|
109
|
+
if (parts === undefined) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
let d;
|
|
113
|
+
try {
|
|
114
|
+
d = new Decimal(parts.digits);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Fable's big.js fork throws for values outside the decimal range
|
|
118
|
+
throw OverflowException_$ctor_Z721C83C5(OVERFLOW);
|
|
119
|
+
}
|
|
120
|
+
if (parts.negative) {
|
|
121
|
+
d.s = -1;
|
|
122
|
+
}
|
|
123
|
+
return d;
|
|
124
|
+
}
|
|
125
|
+
export function tryParse(str, style, defValue) {
|
|
98
126
|
try {
|
|
99
|
-
|
|
127
|
+
const d = parseWithStyle(str, style);
|
|
128
|
+
if (d === undefined) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
defValue.contents = d;
|
|
100
132
|
return true;
|
|
101
133
|
}
|
|
102
134
|
catch {
|
|
103
135
|
return false;
|
|
104
136
|
}
|
|
105
137
|
}
|
|
106
|
-
export function parse(str) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return defValue.contents;
|
|
138
|
+
export function parse(str, style = NumberStyles.Number) {
|
|
139
|
+
if (str == null) {
|
|
140
|
+
throw ArgumentNullException_$ctor_Z721C83C5("s");
|
|
110
141
|
}
|
|
111
|
-
|
|
112
|
-
|
|
142
|
+
const d = parseWithStyle(str, style);
|
|
143
|
+
if (d === undefined) {
|
|
144
|
+
throw FormatException_$ctor_Z721C83C5(`The input string '${str}' was not in a correct format.`);
|
|
113
145
|
}
|
|
146
|
+
return d;
|
|
114
147
|
}
|
|
115
148
|
export function toNumber(x) {
|
|
116
149
|
return +x;
|
|
@@ -182,6 +215,32 @@ function getInt32Bits(hexDigits, offset) {
|
|
|
182
215
|
}
|
|
183
216
|
return bits;
|
|
184
217
|
}
|
|
218
|
+
const OVERFLOW = "Value was either too large or too small for a Decimal.";
|
|
219
|
+
// The first double outside the decimal range
|
|
220
|
+
const MAX_DOUBLE = 2 ** 96;
|
|
221
|
+
function fromFloat(n, significantDigits) {
|
|
222
|
+
if (!isFinite(n) || Math.abs(n) >= MAX_DOUBLE) {
|
|
223
|
+
throw new Exception(OVERFLOW);
|
|
224
|
+
}
|
|
225
|
+
const exact = Math.abs(n) >= 1e21 ? BigInt(n).toString() : n.toFixed(100);
|
|
226
|
+
const d = new Decimal(exact).prec(significantDigits, 2);
|
|
227
|
+
const digits = d.c;
|
|
228
|
+
let end = digits.length;
|
|
229
|
+
while (end > 1 && digits[end - 1] === 0) {
|
|
230
|
+
end--;
|
|
231
|
+
}
|
|
232
|
+
d.c = digits.slice(0, end);
|
|
233
|
+
if (d.c[0] === 0) {
|
|
234
|
+
d.e = 0;
|
|
235
|
+
}
|
|
236
|
+
return d;
|
|
237
|
+
}
|
|
238
|
+
export function fromFloat64(n) {
|
|
239
|
+
return fromFloat(n, 15);
|
|
240
|
+
}
|
|
241
|
+
export function fromFloat32(n) {
|
|
242
|
+
return fromFloat(n, 7);
|
|
243
|
+
}
|
|
185
244
|
export function fromIntArray(bits) {
|
|
186
245
|
return fromInts(bits[0], bits[1], bits[2], bits[3]);
|
|
187
246
|
}
|
package/Double.js
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
import { FSharpRef } from "./Types.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import { ArgumentNullException_$ctor_Z721C83C5, FormatException_$ctor_Z721C83C5 } from "./System.js";
|
|
3
|
+
import { NumberStyles, splitNumber } from "./NumberStyles.js";
|
|
4
|
+
// .NET's NaN and infinity symbols, ignoring case, allowing a sign and trimmed like String.Trim
|
|
5
|
+
const symbolRegex = /^[\t-\r \u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]*(?:[+-]?nan|([+-]?)infinity)[\t-\r \u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]*$/i;
|
|
6
|
+
const defaultStyle = NumberStyles.Float | NumberStyles.AllowThousands;
|
|
7
|
+
export function tryParse(str, style, defValue) {
|
|
8
|
+
if (str != null) {
|
|
9
|
+
const parts = splitNumber(str, style);
|
|
10
|
+
if (parts !== undefined) {
|
|
11
|
+
const value = Number.parseFloat(parts.digits);
|
|
12
|
+
defValue.contents = parts.negative ? -value : value;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
const symbol = symbolRegex.exec(str);
|
|
16
|
+
if (symbol != null) {
|
|
17
|
+
defValue.contents = symbol[1] == null ? NaN : symbol[1] === "-" ? -Infinity : Infinity;
|
|
9
18
|
return true;
|
|
10
19
|
}
|
|
11
20
|
}
|
|
12
21
|
return false;
|
|
13
22
|
}
|
|
14
|
-
export function parse(str) {
|
|
23
|
+
export function parse(str, style = defaultStyle) {
|
|
15
24
|
const defValue = new FSharpRef(0);
|
|
16
|
-
if (tryParse(str, defValue)) {
|
|
25
|
+
if (tryParse(str, style, defValue)) {
|
|
17
26
|
return defValue.contents;
|
|
18
27
|
}
|
|
28
|
+
else if (str == null) {
|
|
29
|
+
throw ArgumentNullException_$ctor_Z721C83C5("s");
|
|
30
|
+
}
|
|
19
31
|
else {
|
|
20
|
-
throw
|
|
32
|
+
throw FormatException_$ctor_Z721C83C5(`The input string '${str}' was not in a correct format.`);
|
|
21
33
|
}
|
|
22
34
|
}
|
|
35
|
+
export function parseIgnoringUnderscores(str) {
|
|
36
|
+
return parse(str == null ? str : str.replace(/_/g, ""), NumberStyles.Float);
|
|
37
|
+
}
|
|
23
38
|
// JS Number.isFinite function evals false for NaN
|
|
24
39
|
export function isPositiveInfinity(x) {
|
|
25
40
|
return x === Number.POSITIVE_INFINITY;
|
package/FSharp.Core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { disposeSafe, defaultOf, Exception, structuralHash, equals } from "./Util.js";
|
|
2
2
|
import { HashIdentity_Structural, ComparisonIdentity_Structural } from "./FSharp.Collections.js";
|
|
3
3
|
import { nonNullValue } from "./Option.js";
|
|
4
|
-
import { NullReferenceException_$ctor, ArgumentNullException_$ctor_Z721C83C5 } from "./System.js";
|
|
4
|
+
import { NullReferenceException_$ctor, InvalidOperationException_$ctor_Z721C83C5, ArgumentException_$ctor_Z384F8060, ArgumentNullException_$ctor_Z721C83C5 } from "./System.js";
|
|
5
5
|
import { FSharpChoice$2_Choice2Of2, FSharpChoice$2_Choice1Of2 } from "./Choice.js";
|
|
6
6
|
import { StringBuilder__Append_Z721C83C5 } from "./System.Text.js";
|
|
7
7
|
export const LanguagePrimitives_GenericEqualityComparer = {
|
|
@@ -41,6 +41,12 @@ export function Operators_FailurePattern(exn) {
|
|
|
41
41
|
export function Operators_NullArg(argumentName) {
|
|
42
42
|
throw ArgumentNullException_$ctor_Z721C83C5(argumentName);
|
|
43
43
|
}
|
|
44
|
+
export function Operators_InvalidArg(argumentName, message) {
|
|
45
|
+
throw ArgumentException_$ctor_Z384F8060(message, argumentName);
|
|
46
|
+
}
|
|
47
|
+
export function Operators_InvalidOp(message) {
|
|
48
|
+
throw InvalidOperationException_$ctor_Z721C83C5(message);
|
|
49
|
+
}
|
|
44
50
|
export function Operators_Using(resource, action) {
|
|
45
51
|
try {
|
|
46
52
|
return action(resource);
|
package/Global.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const SR_indexOutOfBounds = "The index was outside the range of elements in the collection.";
|
|
2
|
-
export const SR_inputWasEmpty = "
|
|
2
|
+
export const SR_inputWasEmpty = "The input list was empty.";
|
|
3
3
|
export const SR_inputMustBeNonNegative = "The input must be non-negative.";
|
|
4
4
|
export const SR_inputSequenceEmpty = "The input sequence was empty.";
|
|
5
5
|
export const SR_inputSequenceTooLong = "The input sequence contains more than one element.";
|
package/Int32.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Exception } from "./Util.js";
|
|
2
|
+
import { ArgumentNullException_$ctor_Z721C83C5, FormatException_$ctor_Z721C83C5, OverflowException_$ctor_Z721C83C5 } from "./System.js";
|
|
2
3
|
export const NumberStyles = {
|
|
3
4
|
// None: 0x00000000,
|
|
4
5
|
// AllowLeadingWhite: 0x00000001,
|
|
@@ -87,7 +88,14 @@ export function isValid(str, style, radix) {
|
|
|
87
88
|
}
|
|
88
89
|
return null;
|
|
89
90
|
}
|
|
91
|
+
export function parseOverflow(unsigned, bitsize) {
|
|
92
|
+
const type = bitsize === 8 ? (unsigned ? "an unsigned byte" : "a signed byte") : (unsigned ? "a UInt" : "an Int") + bitsize;
|
|
93
|
+
return OverflowException_$ctor_Z721C83C5(`Value was either too large or too small for ${type}.`);
|
|
94
|
+
}
|
|
90
95
|
export function parse(str, style, unsigned, bitsize, radix) {
|
|
96
|
+
if (str == null) {
|
|
97
|
+
throw ArgumentNullException_$ctor_Z721C83C5("s");
|
|
98
|
+
}
|
|
91
99
|
const res = isValid(str, style, radix);
|
|
92
100
|
if (res != null) {
|
|
93
101
|
let v = Number.parseInt(res.sign + res.digits, res.radix);
|
|
@@ -100,9 +108,10 @@ export function parse(str, style, unsigned, bitsize, radix) {
|
|
|
100
108
|
if (v >= min && v <= max) {
|
|
101
109
|
return v;
|
|
102
110
|
}
|
|
111
|
+
throw parseOverflow(unsigned, bitsize);
|
|
103
112
|
}
|
|
104
113
|
}
|
|
105
|
-
throw
|
|
114
|
+
throw FormatException_$ctor_Z721C83C5(`The input string '${str}' was not in a correct format.`);
|
|
106
115
|
}
|
|
107
116
|
export function tryParse(str, style, unsigned, bitsize, defValue) {
|
|
108
117
|
try {
|