@fable-org/fable-library-js 2.11.0 → 2.12.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/CHANGELOG.md +10 -1
- package/String.js +57 -7
- package/System.js +5 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
last_commit_released:
|
|
2
|
+
last_commit_released: cac5ddd9a99205e0bb5272f1ffd8f0cca937824c
|
|
3
3
|
updaters:
|
|
4
4
|
- package.json:
|
|
5
5
|
file: package.json
|
|
@@ -15,6 +15,15 @@ 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.12.0 - 2026-10-29
|
|
19
|
+
|
|
20
|
+
### 🚀 Features
|
|
21
|
+
|
|
22
|
+
* *(js/ts)* Support the "R" numeric format and choose "G" notation like .NET (#5212) ([24d9c41a](https://github.com/fable-compiler/Fable/commit/24d9c41ad69993f0c4e843558133bcd787a960d4))
|
|
23
|
+
* *(js/ts/python/dart/beam)* Support ArgumentException.ParamName (#5203) ([8ed77788](https://github.com/fable-compiler/Fable/commit/8ed7778893bab48c7dd41d7322d26d2bcaba6d99))
|
|
24
|
+
|
|
25
|
+
<strong><small>[View changes on Github](https://github.com/fable-compiler/Fable/compare/ce886964cb4521dc4c01c8da089b97c9d9742814..cac5ddd9a99205e0bb5272f1ffd8f0cca937824c)</small></strong>
|
|
26
|
+
|
|
18
27
|
## 2.11.0 - 2026-10-29
|
|
19
28
|
|
|
20
29
|
### 🚀 Features
|
package/String.js
CHANGED
|
@@ -344,6 +344,53 @@ function splitIntAndDecimalPart(value) {
|
|
|
344
344
|
function thousandSeparate(value) {
|
|
345
345
|
return value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
346
346
|
}
|
|
347
|
+
function splitExponential(s) {
|
|
348
|
+
const eIdx = s.indexOf("e");
|
|
349
|
+
return [s.slice(0, eIdx).replace(".", ""), Number(s.slice(eIdx + 1))];
|
|
350
|
+
}
|
|
351
|
+
function shortestSingle(x) {
|
|
352
|
+
// 100 digits tell where a float32 lies between two candidates, and 9 digits always round-trip
|
|
353
|
+
const [digits, exponent] = splitExponential(x.toExponential(99));
|
|
354
|
+
for (let p = 1;; p++) {
|
|
355
|
+
const down = Number(digits.slice(0, p));
|
|
356
|
+
const rest = digits.slice(p);
|
|
357
|
+
const half = "5".padEnd(rest.length, "0");
|
|
358
|
+
const roundUp = rest > half || rest === half && down % 2 === 1;
|
|
359
|
+
for (const n of roundUp ? [down + 1, down] : [down, down + 1]) {
|
|
360
|
+
if (Math.fround(Number(n + "e" + (exponent - p + 1))) === x) {
|
|
361
|
+
return [String(n), exponent + String(n).length - p];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// .NET "G" and "R": fixed notation unless the exponent is below -4 or reaches the precision (17 for the shortest digits, 9 for a float32)
|
|
367
|
+
function formatGeneral(x, format, precision, isSingle = false) {
|
|
368
|
+
if (!Number.isFinite(x)) {
|
|
369
|
+
return String(x);
|
|
370
|
+
}
|
|
371
|
+
const sign = x < 0 || Object.is(x, -0) ? "-" : "";
|
|
372
|
+
x = Math.abs(x);
|
|
373
|
+
// R ignores the precision and G0 is G
|
|
374
|
+
const p = format === "r" || format === "R" ? 0 : precision ?? 0;
|
|
375
|
+
const [significand, exponent] = p > 0 ? splitExponential(x.toExponential(p - 1)) : isSingle ? shortestSingle(x) : splitExponential(x.toExponential());
|
|
376
|
+
const digits = trimEnd(significand, "0") || "0";
|
|
377
|
+
if (exponent < -4 || exponent >= (p > 0 ? p : isSingle ? 9 : 17)) {
|
|
378
|
+
const mantissa = digits.length > 1 ? digits[0] + "." + digits.slice(1) : digits;
|
|
379
|
+
const eChar = format === "G" || format === "R" ? "E" : "e";
|
|
380
|
+
return sign + mantissa + eChar + (exponent < 0 ? "-" : "+") + padLeft(String(Math.abs(exponent)), 2, "0");
|
|
381
|
+
}
|
|
382
|
+
else if (exponent < 0) {
|
|
383
|
+
return sign + "0." + "0".repeat(-exponent - 1) + digits;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
const decimals = digits.slice(exponent + 1);
|
|
387
|
+
return sign + digits.slice(0, exponent + 1).padEnd(exponent + 1, "0") + (decimals ? "." + decimals : "");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
export function formatSingle(str, x) {
|
|
391
|
+
const m = /^\{0:([GgRr])(\d{0,2})\}$/.exec(str);
|
|
392
|
+
return m != null ? formatGeneral(Math.fround(x), m[1], m[2] ? parseInt(m[2], 10) : null, true) : format(str, x);
|
|
393
|
+
}
|
|
347
394
|
export function format(str, ...args) {
|
|
348
395
|
let str2;
|
|
349
396
|
if (typeof str === "object") {
|
|
@@ -423,12 +470,18 @@ export function format(str, ...args) {
|
|
|
423
470
|
}
|
|
424
471
|
break;
|
|
425
472
|
case "g":
|
|
426
|
-
case "G":
|
|
427
|
-
|
|
473
|
+
case "G":
|
|
474
|
+
case "r":
|
|
475
|
+
case "R": {
|
|
476
|
+
if (typeof rep === "number") {
|
|
477
|
+
rep = formatGeneral(rep, format, precision);
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
if (precision == null) {
|
|
428
481
|
rep = String(rep);
|
|
429
482
|
break;
|
|
430
483
|
}
|
|
431
|
-
rep =
|
|
484
|
+
rep = toPrecision(rep, precision);
|
|
432
485
|
// Handle exponential notation: only trim trailing zeros from mantissa, not from exponent.
|
|
433
486
|
// .NET G format guarantees an exponent of at least 2 digits with an explicit sign (e.g. "E-07").
|
|
434
487
|
const eIdx = rep.indexOf("e");
|
|
@@ -437,7 +490,7 @@ export function format(str, ...args) {
|
|
|
437
490
|
const expSign = rep[eIdx + 1]; // toPrecision always emits "+" or "-"
|
|
438
491
|
const expDigits = rep.slice(eIdx + 2);
|
|
439
492
|
const paddedExpDigits = expDigits.length < 2 ? "0" + expDigits : expDigits;
|
|
440
|
-
const eChar = format === "G" ? "E" : "e";
|
|
493
|
+
const eChar = format === "G" || format === "R" ? "E" : "e";
|
|
441
494
|
rep = mantissa + eChar + expSign + paddedExpDigits;
|
|
442
495
|
}
|
|
443
496
|
else if (rep.indexOf(".") >= 0) {
|
|
@@ -469,9 +522,6 @@ export function format(str, ...args) {
|
|
|
469
522
|
rep = thousandSeparate(parts.integral) + " %";
|
|
470
523
|
}
|
|
471
524
|
break;
|
|
472
|
-
case "r":
|
|
473
|
-
case "R":
|
|
474
|
-
throw new Exception("The round-trip format is not supported by Fable");
|
|
475
525
|
case "x":
|
|
476
526
|
case "X":
|
|
477
527
|
if (!isIntegral(rep)) {
|
package/System.js
CHANGED
|
@@ -239,16 +239,16 @@ export function ArgumentException_$ctor_Z60A2B367(message, paramName, innerExcep
|
|
|
239
239
|
return new ArgumentException(message, paramName, innerException);
|
|
240
240
|
}
|
|
241
241
|
export function ArgumentException_$ctor() {
|
|
242
|
-
return ArgumentException_$ctor_Z60A2B367(SR_Arg_ArgumentException,
|
|
242
|
+
return ArgumentException_$ctor_Z60A2B367(SR_Arg_ArgumentException, defaultOf(), defaultOf());
|
|
243
243
|
}
|
|
244
244
|
export function ArgumentException_$ctor_Z721C83C5(message) {
|
|
245
|
-
return ArgumentException_$ctor_Z60A2B367(message,
|
|
245
|
+
return ArgumentException_$ctor_Z60A2B367(message, defaultOf(), defaultOf());
|
|
246
246
|
}
|
|
247
247
|
export function ArgumentException_$ctor_Z384F8060(message, paramName) {
|
|
248
248
|
return ArgumentException_$ctor_Z60A2B367(message, paramName, defaultOf());
|
|
249
249
|
}
|
|
250
250
|
export function ArgumentException_$ctor_68CE3CA2(message, innerException) {
|
|
251
|
-
return ArgumentException_$ctor_Z60A2B367(message,
|
|
251
|
+
return ArgumentException_$ctor_Z60A2B367(message, defaultOf(), innerException);
|
|
252
252
|
}
|
|
253
253
|
export function ArgumentException__get_ParamName(_) {
|
|
254
254
|
return _.paramName;
|
|
@@ -268,7 +268,7 @@ export function ArgumentNullException_$ctor_Z721C83C5(paramName) {
|
|
|
268
268
|
return ArgumentNullException_$ctor_Z384F8060(paramName, SR_ArgumentNull_Generic);
|
|
269
269
|
}
|
|
270
270
|
export function ArgumentNullException_$ctor() {
|
|
271
|
-
return ArgumentNullException_$ctor_Z721C83C5(
|
|
271
|
+
return ArgumentNullException_$ctor_Z721C83C5(defaultOf());
|
|
272
272
|
}
|
|
273
273
|
export class ArgumentOutOfRangeException extends ArgumentException {
|
|
274
274
|
constructor(paramName, message) {
|
|
@@ -285,5 +285,5 @@ export function ArgumentOutOfRangeException_$ctor_Z721C83C5(paramName) {
|
|
|
285
285
|
return ArgumentOutOfRangeException_$ctor_Z384F8060(paramName, SR_Arg_ArgumentOutOfRangeException);
|
|
286
286
|
}
|
|
287
287
|
export function ArgumentOutOfRangeException_$ctor() {
|
|
288
|
-
return ArgumentOutOfRangeException_$ctor_Z721C83C5(
|
|
288
|
+
return ArgumentOutOfRangeException_$ctor_Z721C83C5(defaultOf());
|
|
289
289
|
}
|
package/package.json
CHANGED