@fable-org/fable-library-js 2.10.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/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
- try {
156
- res.contents = BigInt(s);
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
- catch (err) {
160
- return false;
161
- }
164
+ return false;
162
165
  }
163
166
  export function parse(s) {
164
- return BigInt(s);
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: 2098f64a25e96385306ef19ed8c289f3b6c84db9
2
+ last_commit_released: ce886964cb4521dc4c01c8da089b97c9d9742814
3
3
  updaters:
4
4
  - package.json:
5
5
  file: package.json
@@ -15,6 +15,38 @@ 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
+
18
50
  ## 2.10.0 - 2026-10-22
19
51
 
20
52
  ### 🚀 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 = new Date(date.getTime() + (date.offset ?? 0));
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,6 +1,8 @@
1
1
  import Decimal from "./lib/big.js";
2
2
  import { symbol } from "./Numeric.js";
3
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";
4
6
  import { fromDecimal } from "./BigInt.js";
5
7
  import * as bigInt from "./BigInt.js";
6
8
  Decimal.prototype.GetHashCode = function () {
@@ -101,56 +103,21 @@ export const negate = op_UnaryNegation;
101
103
  export function toString(x) {
102
104
  return x.toString();
103
105
  }
104
- const NumberStyles = {
105
- AllowLeadingWhite: 1,
106
- AllowTrailingWhite: 2,
107
- AllowLeadingSign: 4,
108
- AllowTrailingSign: 8,
109
- AllowParentheses: 16,
110
- AllowDecimalPoint: 32,
111
- AllowThousands: 64,
112
- AllowExponent: 128,
113
- AllowHexSpecifier: 512,
114
- Number: 111,
115
- };
116
- // The digits of a decimal string once whitespace, sign and parentheses are stripped
117
- function digitsPattern(style) {
118
- const integral = style & NumberStyles.AllowThousands ? "\\d+(?:,\\d+)*" : "\\d+";
119
- const point = style & NumberStyles.AllowDecimalPoint ? "(?:\\.\\d*)?" : "";
120
- const leadingPoint = style & NumberStyles.AllowDecimalPoint ? "|\\.\\d+" : "";
121
- const exponent = style & NumberStyles.AllowExponent ? "(?:[eE][+-]?\\d+)?" : "";
122
- return new RegExp(`^(?:${integral}${point}${leadingPoint})${exponent}$`);
123
- }
124
106
  // Returns undefined when the string does not have the format allowed by the style
125
107
  function parseWithStyle(str, style) {
126
- if (style & NumberStyles.AllowHexSpecifier) {
127
- throw new Exception("The number style AllowHexSpecifier is not supported on floating point data types.");
128
- }
129
- let s = str;
130
- if (style & NumberStyles.AllowLeadingWhite) {
131
- s = s.replace(/^\s+/, "");
132
- }
133
- if (style & NumberStyles.AllowTrailingWhite) {
134
- s = s.replace(/\s+$/, "");
135
- }
136
- let negative = false;
137
- if (style & NumberStyles.AllowParentheses && s.startsWith("(") && s.endsWith(")")) {
138
- s = s.slice(1, -1);
139
- negative = true;
140
- }
141
- if (style & NumberStyles.AllowLeadingSign && /^[+-]/.test(s)) {
142
- negative = s[0] === "-" ? !negative : negative;
143
- s = s.slice(1);
108
+ const parts = splitNumber(str, style);
109
+ if (parts === undefined) {
110
+ return undefined;
144
111
  }
145
- else if (style & NumberStyles.AllowTrailingSign && /[+-]$/.test(s)) {
146
- negative = s[s.length - 1] === "-" ? !negative : negative;
147
- s = s.slice(0, -1);
112
+ let d;
113
+ try {
114
+ d = new Decimal(parts.digits);
148
115
  }
149
- if (!digitsPattern(style).test(s)) {
150
- return undefined;
116
+ catch {
117
+ // Fable's big.js fork throws for values outside the decimal range
118
+ throw OverflowException_$ctor_Z721C83C5(OVERFLOW);
151
119
  }
152
- const d = new Decimal(s.replace(/,/g, ""));
153
- if (negative) {
120
+ if (parts.negative) {
154
121
  d.s = -1;
155
122
  }
156
123
  return d;
@@ -169,9 +136,12 @@ export function tryParse(str, style, defValue) {
169
136
  }
170
137
  }
171
138
  export function parse(str, style = NumberStyles.Number) {
139
+ if (str == null) {
140
+ throw ArgumentNullException_$ctor_Z721C83C5("s");
141
+ }
172
142
  const d = parseWithStyle(str, style);
173
143
  if (d === undefined) {
174
- throw new Exception(`The input string ${str} was not in a correct format.`);
144
+ throw FormatException_$ctor_Z721C83C5(`The input string '${str}' was not in a correct format.`);
175
145
  }
176
146
  return d;
177
147
  }
package/Double.js CHANGED
@@ -1,25 +1,40 @@
1
1
  import { FSharpRef } from "./Types.js";
2
- import { Exception } from "./Util.js";
3
- export function tryParse(str, defValue) {
4
- // TODO: test if value is valid and in range
5
- if (str != null && /\S/.test(str)) {
6
- const v = +str.replace("_", "");
7
- if (!Number.isNaN(v)) {
8
- defValue.contents = v;
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 new Exception(`The input string ${str} was not in a correct format.`);
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 = "Collection was empty.";
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 new Exception(`The input string ${str} was not in a correct format.`);
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 {