@rackbops/ac-agent 2.0.0-alpha.42 → 2.0.0-alpha.44
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/README.md +5 -4
- package/dist/ac-agent.mjs +706 -517
- package/package.json +2 -2
package/dist/ac-agent.mjs
CHANGED
|
@@ -47,7 +47,7 @@ function _mergeNamespaces(n, m) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
var name = "@rackbops/ac-agent";
|
|
50
|
-
var version = "2.0.0-alpha.
|
|
50
|
+
var version = "2.0.0-alpha.44";
|
|
51
51
|
var type = "module";
|
|
52
52
|
var description = "The per-machine host agent (installed with npx @rackbops/ac-agent): an HTTPS health server plus install/status/uninstall for a Windows logon task or a systemd user unit.";
|
|
53
53
|
var bin = {
|
|
@@ -73,7 +73,7 @@ var dependencies = {
|
|
|
73
73
|
"@hono/node-server": "^2.1.3",
|
|
74
74
|
hono: "^4.13.11",
|
|
75
75
|
selfsigned: "^5.0.0",
|
|
76
|
-
"smol-toml": "^1.
|
|
76
|
+
"smol-toml": "^1.9.0",
|
|
77
77
|
yaml: "^2.9.1"
|
|
78
78
|
};
|
|
79
79
|
var devDependencies = {
|
|
@@ -447,134 +447,6 @@ function createClaudeDesktopWatch(deps, hooks = {}, opts = {}) {
|
|
|
447
447
|
return { current: () => held, refresh, start };
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
-
/*!
|
|
451
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
452
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
453
|
-
*
|
|
454
|
-
* Redistribution and use in source and binary forms, with or without
|
|
455
|
-
* modification, are permitted provided that the following conditions are met:
|
|
456
|
-
*
|
|
457
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
458
|
-
* list of conditions and the following disclaimer.
|
|
459
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
460
|
-
* this list of conditions and the following disclaimer in the
|
|
461
|
-
* documentation and/or other materials provided with the distribution.
|
|
462
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
463
|
-
* may be used to endorse or promote products derived from this software without
|
|
464
|
-
* specific prior written permission.
|
|
465
|
-
*
|
|
466
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
467
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
468
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
469
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
470
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
471
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
472
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
473
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
474
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
475
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
476
|
-
*/
|
|
477
|
-
let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
478
|
-
class TomlDate extends Date {
|
|
479
|
-
#hasDate = false;
|
|
480
|
-
#hasTime = false;
|
|
481
|
-
#offset = null;
|
|
482
|
-
constructor(date) {
|
|
483
|
-
let hasDate = true;
|
|
484
|
-
let hasTime = true;
|
|
485
|
-
let offset = 'Z';
|
|
486
|
-
if (typeof date === 'string') {
|
|
487
|
-
let match = date.match(DATE_TIME_RE);
|
|
488
|
-
if (match) {
|
|
489
|
-
if (!match[1]) {
|
|
490
|
-
hasDate = false;
|
|
491
|
-
date = `0000-01-01T${date}`;
|
|
492
|
-
}
|
|
493
|
-
hasTime = !!match[2];
|
|
494
|
-
// Make sure to use T instead of a space. Breaks in case of extreme values otherwise.
|
|
495
|
-
hasTime && date[10] === ' ' && (date = date.replace(' ', 'T'));
|
|
496
|
-
// Do not allow rollover hours.
|
|
497
|
-
if (match[2] && +match[2] > 23) {
|
|
498
|
-
date = '';
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
offset = match[3] || null;
|
|
502
|
-
date = date.toUpperCase();
|
|
503
|
-
if (!offset && hasTime)
|
|
504
|
-
date += 'Z';
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
else {
|
|
508
|
-
date = '';
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
super(date);
|
|
512
|
-
if (!isNaN(this.getTime())) {
|
|
513
|
-
this.#hasDate = hasDate;
|
|
514
|
-
this.#hasTime = hasTime;
|
|
515
|
-
this.#offset = offset;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
isDateTime() {
|
|
519
|
-
return this.#hasDate && this.#hasTime;
|
|
520
|
-
}
|
|
521
|
-
isLocal() {
|
|
522
|
-
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
523
|
-
}
|
|
524
|
-
isDate() {
|
|
525
|
-
return this.#hasDate && !this.#hasTime;
|
|
526
|
-
}
|
|
527
|
-
isTime() {
|
|
528
|
-
return this.#hasTime && !this.#hasDate;
|
|
529
|
-
}
|
|
530
|
-
isValid() {
|
|
531
|
-
return this.#hasDate || this.#hasTime;
|
|
532
|
-
}
|
|
533
|
-
toISOString() {
|
|
534
|
-
let iso = super.toISOString();
|
|
535
|
-
// Local Date
|
|
536
|
-
if (this.isDate())
|
|
537
|
-
return iso.slice(0, 10);
|
|
538
|
-
// Local Time
|
|
539
|
-
if (this.isTime())
|
|
540
|
-
return iso.slice(11, 23);
|
|
541
|
-
// Local DateTime
|
|
542
|
-
if (this.#offset === null)
|
|
543
|
-
return iso.slice(0, -1);
|
|
544
|
-
// Offset DateTime
|
|
545
|
-
if (this.#offset === 'Z')
|
|
546
|
-
return iso;
|
|
547
|
-
// This part is quite annoying: JS strips the original timezone from the ISO string representation
|
|
548
|
-
// Instead of using a "modified" date and "Z", we restore the representation "as authored"
|
|
549
|
-
let offset = (+(this.#offset.slice(1, 3)) * 60) + +(this.#offset.slice(4, 6));
|
|
550
|
-
offset = this.#offset[0] === '-' ? offset : -offset;
|
|
551
|
-
let offsetDate = new Date(this.getTime() - (offset * 60e3));
|
|
552
|
-
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
553
|
-
}
|
|
554
|
-
static wrapAsOffsetDateTime(jsDate, offset = 'Z') {
|
|
555
|
-
let date = new TomlDate(jsDate);
|
|
556
|
-
date.#offset = offset;
|
|
557
|
-
return date;
|
|
558
|
-
}
|
|
559
|
-
static wrapAsLocalDateTime(jsDate) {
|
|
560
|
-
let date = new TomlDate(jsDate);
|
|
561
|
-
date.#offset = null;
|
|
562
|
-
return date;
|
|
563
|
-
}
|
|
564
|
-
static wrapAsLocalDate(jsDate) {
|
|
565
|
-
let date = new TomlDate(jsDate);
|
|
566
|
-
date.#hasTime = false;
|
|
567
|
-
date.#offset = null;
|
|
568
|
-
return date;
|
|
569
|
-
}
|
|
570
|
-
static wrapAsLocalTime(jsDate) {
|
|
571
|
-
let date = new TomlDate(jsDate);
|
|
572
|
-
date.#hasDate = false;
|
|
573
|
-
date.#offset = null;
|
|
574
|
-
return date;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
450
|
/*!
|
|
579
451
|
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
580
452
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
@@ -603,11 +475,11 @@ class TomlDate extends Date {
|
|
|
603
475
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
604
476
|
*/
|
|
605
477
|
function getLineColFromPtr(string, ptr) {
|
|
606
|
-
let lines = string.slice(0, ptr).split(/\r
|
|
478
|
+
let lines = string.slice(0, ptr).split(/\r?\n/);
|
|
607
479
|
return [lines.length, lines.pop().length + 1];
|
|
608
480
|
}
|
|
609
481
|
function makeCodeBlock(string, line, column) {
|
|
610
|
-
let lines = string.split(/\r
|
|
482
|
+
let lines = string.split(/\r?\n/);
|
|
611
483
|
let codeblock = '';
|
|
612
484
|
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
613
485
|
for (let i = line - 1; i <= line + 1; i++) {
|
|
@@ -637,95 +509,10 @@ class TomlError extends Error {
|
|
|
637
509
|
this.column = column;
|
|
638
510
|
this.codeblock = codeblock;
|
|
639
511
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
644
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
645
|
-
*
|
|
646
|
-
* Redistribution and use in source and binary forms, with or without
|
|
647
|
-
* modification, are permitted provided that the following conditions are met:
|
|
648
|
-
*
|
|
649
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
650
|
-
* list of conditions and the following disclaimer.
|
|
651
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
652
|
-
* this list of conditions and the following disclaimer in the
|
|
653
|
-
* documentation and/or other materials provided with the distribution.
|
|
654
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
655
|
-
* may be used to endorse or promote products derived from this software without
|
|
656
|
-
* specific prior written permission.
|
|
657
|
-
*
|
|
658
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
659
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
660
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
661
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
662
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
663
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
664
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
665
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
666
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
667
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
668
|
-
*/
|
|
669
|
-
/** @internal */
|
|
670
|
-
function indexOfNewline(str, start = 0) {
|
|
671
|
-
let idx = str.indexOf('\n', start);
|
|
672
|
-
if (str.charCodeAt(idx - 1) === 0xd /* \r */)
|
|
673
|
-
idx--;
|
|
674
|
-
return idx;
|
|
675
|
-
}
|
|
676
|
-
/** @internal */
|
|
677
|
-
function skipComment$1(ctx) {
|
|
678
|
-
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
679
|
-
let c = ctx.s.charCodeAt(ctx.p);
|
|
680
|
-
if (c === 0xa /* \n */)
|
|
681
|
-
break;
|
|
682
|
-
if (c === 0xd /* \r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \n */) {
|
|
683
|
-
ctx.p++;
|
|
684
|
-
break;
|
|
685
|
-
}
|
|
686
|
-
if ((c < 0x20 && c !== 0x9 /* \t */) || c === 0x7f) {
|
|
687
|
-
throw new TomlError('control characters are not allowed in comments', {
|
|
688
|
-
toml: ctx.s,
|
|
689
|
-
ptr: ctx.p,
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
/** @internal */
|
|
695
|
-
function skipVoid(ctx, banNewLines, banComments) {
|
|
696
|
-
let c;
|
|
697
|
-
while (1) {
|
|
698
|
-
while ((c = ctx.s.charCodeAt(ctx.p)) === 0x20 ||
|
|
699
|
-
c === 0x9 /* \t */ ||
|
|
700
|
-
(!banNewLines &&
|
|
701
|
-
(c === 0xa /* \n */ || (c === 0xd /* \r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \n */))))
|
|
702
|
-
ctx.p++;
|
|
703
|
-
if (banComments || c !== 0x23 /* # */)
|
|
704
|
-
break;
|
|
705
|
-
skipComment$1(ctx);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
/** @internal */
|
|
709
|
-
function skipUntil(ctx, sep, end) {
|
|
710
|
-
let ptr = ctx.p;
|
|
711
|
-
if (!end) {
|
|
712
|
-
ptr = indexOfNewline(ctx.s, ptr);
|
|
713
|
-
ctx.p = ptr < 0 ? ctx.s.length : ptr;
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
717
|
-
let c = ctx.s.charCodeAt(ctx.p);
|
|
718
|
-
if (c === 0x23 /* # */) {
|
|
719
|
-
skipComment$1(ctx);
|
|
720
|
-
}
|
|
721
|
-
else if (c === end || c === sep) {
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
512
|
+
/** @internal */
|
|
513
|
+
static x(message, ctx, ptr) {
|
|
514
|
+
throw new TomlError(message, { toml: ctx.s, ptr: ptr ?? ctx.p });
|
|
724
515
|
}
|
|
725
|
-
throw new TomlError('cannot find end of structure', {
|
|
726
|
-
toml: ctx.s,
|
|
727
|
-
ptr,
|
|
728
|
-
});
|
|
729
516
|
}
|
|
730
517
|
|
|
731
518
|
/*!
|
|
@@ -755,13 +542,9 @@ function skipUntil(ctx, sep, end) {
|
|
|
755
542
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
756
543
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
757
544
|
*/
|
|
758
|
-
// let CTRL_REGEX = /[\x00-\x08\x0f-\x1f\x7f]/
|
|
759
|
-
let INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
|
760
|
-
let FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
|
761
|
-
let LEADING_ZERO = /^[+-]?0[0-9_]/;
|
|
762
545
|
/** @internal */
|
|
763
546
|
function parseString(ctx) {
|
|
764
|
-
let
|
|
547
|
+
let startPtr = ctx.p;
|
|
765
548
|
let c = ctx.s.charCodeAt(ctx.p++);
|
|
766
549
|
let first = c;
|
|
767
550
|
let isLiteral = c === 0x27; /* ' */
|
|
@@ -773,37 +556,8 @@ function parseString(ctx) {
|
|
|
773
556
|
else if (c === 0xd /* \r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \n */)
|
|
774
557
|
ctx.p += 2;
|
|
775
558
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
Kept for reference and/or future fafoing.
|
|
779
|
-
|
|
780
|
-
Without: spec 5.08 µs/iter 3.88 ipc (99.44% cache) 23.90 branch misses 28.61k cycles 111.01k instructions
|
|
781
|
-
5MB 115.73 ms/iter 2.51 ipc (98.36% cache) 3.12M branch misses 619.30M cycles 1.56G instructions
|
|
782
|
-
|
|
783
|
-
With: spec 5.09 µs/iter 3.90 ipc (99.46% cache) 24.42 branch misses 28.57k cycles 111.49k instructions
|
|
784
|
-
5MB 113.89 ms/iter 2.47 ipc (98.38% cache) 3.12M branch misses 611.94M cycles 1.51G instructions
|
|
785
|
-
|
|
786
|
-
if (c === "'") {
|
|
787
|
-
// Literal strings fast path - no transform needs to occur; just grab the str and that's it
|
|
788
|
-
let endPtr = str.indexOf(isMultiline ? "'''" : "'", ptr)
|
|
789
|
-
if (endPtr < 0) {
|
|
790
|
-
throw new TomlError("unfinished string literal", { toml: str, ptr })
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
if (isMultiline) {
|
|
794
|
-
// If the string ends with 4-5 quotes, then the first 1-2 are part of the string
|
|
795
|
-
if (str[endPtr + 3] === "'") endPtr++
|
|
796
|
-
if (str[endPtr + 3] === "'") endPtr++
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
let string = str.slice(ptr, endPtr)
|
|
800
|
-
if (CTRL_REGEX.test(string)) {
|
|
801
|
-
let match = string.match(CTRL_REGEX)!
|
|
802
|
-
throw new TomlError('control characters are not allowed in strings', { toml: str, ptr: ptr + (match.index ?? 0) })
|
|
803
|
-
}
|
|
804
|
-
return [string, endPtr + (isMultiline ? 3 : 1)]
|
|
805
|
-
}
|
|
806
|
-
*/
|
|
559
|
+
// For the record: it is not worth it to use a fast-path for literal strings using `indexOf`.
|
|
560
|
+
// Doing a char-by-char iteration ends up dispatching less instructions, for the same wall-clock runtime.
|
|
807
561
|
let parsed = '';
|
|
808
562
|
let sliceStart = ctx.p;
|
|
809
563
|
// states:
|
|
@@ -820,10 +574,7 @@ function parseString(ctx) {
|
|
|
820
574
|
}
|
|
821
575
|
// Control characters are banned in TOML, so we throw an error if we encounter them
|
|
822
576
|
else if ((c < 0x20 && c !== 0x9 /* \t */) || c === 0x7f) {
|
|
823
|
-
|
|
824
|
-
toml: ctx.s,
|
|
825
|
-
ptr: ctx.p,
|
|
826
|
-
});
|
|
577
|
+
TomlError.x('control characters are not allowed in strings', ctx);
|
|
827
578
|
}
|
|
828
579
|
// The string might terminate while we're parsing through a newline escape.
|
|
829
580
|
// It must have encountered a newline; otherwise, it'll simply fail in another branch.
|
|
@@ -836,11 +587,15 @@ function parseString(ctx) {
|
|
|
836
587
|
ctx.p++;
|
|
837
588
|
}
|
|
838
589
|
// If we're in a newline escape still, then there's nothing to add.
|
|
839
|
-
if (!state)
|
|
840
|
-
|
|
590
|
+
if (!state) {
|
|
591
|
+
// Avoid a useless concat operation if the string can be used as-is.
|
|
592
|
+
let s = ctx.s.slice(sliceStart, ctx.p);
|
|
593
|
+
parsed = parsed ? parsed + s : s;
|
|
594
|
+
}
|
|
841
595
|
ctx.p += isMultiline ? 3 : 1;
|
|
842
596
|
return parsed;
|
|
843
597
|
}
|
|
598
|
+
// Baseline state; keep moving forward unless an escape sequence starts
|
|
844
599
|
else if (!state) {
|
|
845
600
|
if (!isLiteral && c === 0x5c /* \ */) {
|
|
846
601
|
parsed += ctx.s.slice(sliceStart, (sliceStart = ctx.p));
|
|
@@ -849,29 +604,32 @@ function parseString(ctx) {
|
|
|
849
604
|
}
|
|
850
605
|
else if (state === 1) {
|
|
851
606
|
if (c === 0x78 /* x */ || c === 0x75 /* u */ || c === 0x55 /* U */) { // Unicode escape
|
|
607
|
+
let errPtr = ctx.p++ - 1;
|
|
852
608
|
let value = 0;
|
|
853
609
|
let len = c === 0x78 /* x */ ? 2 : c === 0x75 /* u */ ? 4 : 8;
|
|
854
610
|
for (let j = 0; j < len; j++, ctx.p++) {
|
|
855
|
-
let hex = ctx.s.charCodeAt(ctx.p
|
|
611
|
+
let hex = ctx.s.charCodeAt(ctx.p);
|
|
856
612
|
let digit =
|
|
857
613
|
/* 0-9 */ hex >= 0x30 && hex <= 0x39 ? hex - 0x30 :
|
|
858
614
|
/* A-F */ hex >= 0x41 && hex <= 0x46 ? hex - 0x41 + 10 :
|
|
859
615
|
/* a-f */ hex >= 0x61 && hex <= 0x66 ? hex - 0x61 + 10 : -1;
|
|
860
616
|
if (digit < 0)
|
|
861
|
-
|
|
617
|
+
TomlError.x('invalid non-hex character in unicode escape', ctx);
|
|
862
618
|
value = (value << 4) | digit;
|
|
863
619
|
}
|
|
864
620
|
// Because JS does bitwise on signed 32bit integers, all 0xfzzzzzzz values are actually seen as negative
|
|
865
621
|
if (value < 0 || value > 0x10ffff || (value >= 0xd800 && value <= 0xdfff)) {
|
|
866
|
-
|
|
622
|
+
TomlError.x('invalid unicode escape', ctx, errPtr);
|
|
867
623
|
}
|
|
868
624
|
parsed += String.fromCodePoint(value);
|
|
869
|
-
sliceStart = ctx.p
|
|
625
|
+
sliceStart = ctx.p--;
|
|
870
626
|
state = 0;
|
|
871
627
|
}
|
|
872
|
-
|
|
628
|
+
// Newline escape sequence. We only need to care about spaces and tabs; newlines are dealt with earlier
|
|
629
|
+
else if (isMultiline && (c === 0x20 || c === 0x9 /* \t */)) {
|
|
873
630
|
state = 2;
|
|
874
631
|
}
|
|
632
|
+
// Basic escape sequence
|
|
875
633
|
else {
|
|
876
634
|
if (c === 0x62 /* b */)
|
|
877
635
|
parsed += '\b';
|
|
@@ -890,78 +648,179 @@ function parseString(ctx) {
|
|
|
890
648
|
else if (c === 0x5c /* \ */)
|
|
891
649
|
parsed += '\\';
|
|
892
650
|
else
|
|
893
|
-
|
|
651
|
+
TomlError.x('unrecognised escape sequence', ctx);
|
|
894
652
|
sliceStart = ctx.p + 1;
|
|
895
653
|
state = 0;
|
|
896
654
|
}
|
|
897
655
|
}
|
|
656
|
+
// Newline escape continuation: keep moving forward until the first non-whitespace char
|
|
898
657
|
else if (c !== 0x20 && c !== 0x9 /* \t */) {
|
|
899
|
-
if (state === 2)
|
|
900
|
-
|
|
901
|
-
toml: ctx.s,
|
|
902
|
-
ptr: sliceStart,
|
|
903
|
-
});
|
|
904
|
-
}
|
|
658
|
+
if (state === 2)
|
|
659
|
+
TomlError.x('invalid escape: only line-ending whitespace may be escaped', ctx, sliceStart);
|
|
905
660
|
// State cannot be zero, or we'd have branched earlier already.
|
|
906
661
|
// If it's a backslash, immediately transition to the escape state so it can be processed.
|
|
907
662
|
state = !isLiteral && c === 0x5c /* \ */ ? 1 : 0;
|
|
908
663
|
sliceStart = ctx.p;
|
|
909
664
|
}
|
|
910
665
|
}
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
function sliceAndTrimEndOf(ctx, start, end) {
|
|
914
|
-
let value = ctx.s.slice(start, end);
|
|
915
|
-
let commentIdx = value.indexOf('#');
|
|
916
|
-
if (commentIdx > 0) {
|
|
917
|
-
// The call to skipComment allows to "validate" the comment
|
|
918
|
-
// (absence of control characters)
|
|
919
|
-
skipComment$1({ s: value, p: commentIdx});
|
|
920
|
-
value = value.slice(0, commentIdx);
|
|
921
|
-
}
|
|
922
|
-
return value.trimEnd();
|
|
666
|
+
TomlError.x('unfinished string', ctx, startPtr);
|
|
923
667
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
668
|
+
|
|
669
|
+
/*!
|
|
670
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
671
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
672
|
+
*
|
|
673
|
+
* Redistribution and use in source and binary forms, with or without
|
|
674
|
+
* modification, are permitted provided that the following conditions are met:
|
|
675
|
+
*
|
|
676
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
677
|
+
* list of conditions and the following disclaimer.
|
|
678
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
679
|
+
* this list of conditions and the following disclaimer in the
|
|
680
|
+
* documentation and/or other materials provided with the distribution.
|
|
681
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
682
|
+
* may be used to endorse or promote products derived from this software without
|
|
683
|
+
* specific prior written permission.
|
|
684
|
+
*
|
|
685
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
686
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
687
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
688
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
689
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
690
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
691
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
692
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
693
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
694
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
695
|
+
*/
|
|
696
|
+
let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i;
|
|
697
|
+
class TomlDate extends Date {
|
|
698
|
+
#hasDate = false;
|
|
699
|
+
#hasTime = false;
|
|
700
|
+
#offset = null;
|
|
701
|
+
constructor(date, fasttype, unsafeDelim) {
|
|
702
|
+
let hasDate = true;
|
|
703
|
+
let hasTime = true;
|
|
704
|
+
let offset = 'Z';
|
|
705
|
+
let c;
|
|
706
|
+
if (typeof date === 'string') {
|
|
707
|
+
if (fasttype)
|
|
708
|
+
prep: {
|
|
709
|
+
// Date-time
|
|
710
|
+
if (fasttype < 3) {
|
|
711
|
+
if (+date.slice(11, 13) > 23) {
|
|
712
|
+
date = '';
|
|
713
|
+
break prep;
|
|
714
|
+
}
|
|
715
|
+
// Local
|
|
716
|
+
if (fasttype === 2) {
|
|
717
|
+
offset = null;
|
|
718
|
+
date += 'Z';
|
|
719
|
+
}
|
|
720
|
+
// Offset; keep track of offset if not Z
|
|
721
|
+
else if ((c = date.charCodeAt(date.length - 1)) !== 0x5a /* Z */ && c !== 0x7a /* z */) {
|
|
722
|
+
offset = date.slice(date.length - 6);
|
|
723
|
+
}
|
|
724
|
+
if (unsafeDelim)
|
|
725
|
+
date = date.slice(0, 10) + 'T' + date.slice(11);
|
|
726
|
+
}
|
|
727
|
+
// Time
|
|
728
|
+
else if (fasttype === 4) {
|
|
729
|
+
date = +date.slice(0, 2) > 23 ? '' : `0000-01-01T${date}Z`;
|
|
730
|
+
}
|
|
731
|
+
hasDate = fasttype !== 4;
|
|
732
|
+
hasTime = fasttype !== 3;
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
let match = date.match(DATE_TIME_RE);
|
|
736
|
+
if (match) {
|
|
737
|
+
if (!match[1]) {
|
|
738
|
+
hasDate = false;
|
|
739
|
+
date = `0000-01-01T${date}`;
|
|
740
|
+
}
|
|
741
|
+
hasTime = !!match[2];
|
|
742
|
+
// Make sure to use T instead of a space. Breaks in case of extreme values otherwise.
|
|
743
|
+
hasTime && date[10] === ' ' && (date = date.replace(' ', 'T'));
|
|
744
|
+
// Do not allow rollover hours.
|
|
745
|
+
if (match[2] && +match[2] > 23) {
|
|
746
|
+
date = '';
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
offset = match[3] || null;
|
|
750
|
+
if (!offset && hasTime)
|
|
751
|
+
date += 'Z';
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
date = '';
|
|
756
|
+
}
|
|
955
757
|
}
|
|
956
|
-
if (isInt || integersAsBigInt === true)
|
|
957
|
-
numeric = BigInt(value);
|
|
958
758
|
}
|
|
959
|
-
|
|
759
|
+
super(date);
|
|
760
|
+
if (!isNaN(this.getTime())) {
|
|
761
|
+
this.#hasDate = hasDate;
|
|
762
|
+
this.#hasTime = hasTime;
|
|
763
|
+
this.#offset = offset;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
isDateTime() {
|
|
767
|
+
return this.#hasDate && this.#hasTime;
|
|
768
|
+
}
|
|
769
|
+
isLocal() {
|
|
770
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
771
|
+
}
|
|
772
|
+
isDate() {
|
|
773
|
+
return this.#hasDate && !this.#hasTime;
|
|
774
|
+
}
|
|
775
|
+
isTime() {
|
|
776
|
+
return this.#hasTime && !this.#hasDate;
|
|
777
|
+
}
|
|
778
|
+
isValid() {
|
|
779
|
+
return this.#hasDate || this.#hasTime;
|
|
780
|
+
}
|
|
781
|
+
toISOString() {
|
|
782
|
+
let iso = super.toISOString();
|
|
783
|
+
// Local Date
|
|
784
|
+
if (this.isDate())
|
|
785
|
+
return iso.slice(0, 10);
|
|
786
|
+
// Local Time
|
|
787
|
+
if (this.isTime())
|
|
788
|
+
return iso.slice(11, 23);
|
|
789
|
+
// Local DateTime
|
|
790
|
+
if (this.#offset === null)
|
|
791
|
+
return iso.slice(0, -1);
|
|
792
|
+
// Offset DateTime
|
|
793
|
+
if (this.#offset === 'Z' || this.#offset === 'z')
|
|
794
|
+
return iso;
|
|
795
|
+
// This part is quite annoying: JS strips the original timezone from the ISO string representation
|
|
796
|
+
// Instead of using a "modified" date and "Z", we restore the representation "as authored"
|
|
797
|
+
let offset = (+(this.#offset.slice(1, 3)) * 60) + +(this.#offset.slice(4, 6));
|
|
798
|
+
offset = this.#offset[0] === '-' ? offset : -offset;
|
|
799
|
+
let offsetDate = new Date(this.getTime() - (offset * 60e3));
|
|
800
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
801
|
+
}
|
|
802
|
+
static wrapAsOffsetDateTime(jsDate, offset = 'Z') {
|
|
803
|
+
let date = new TomlDate(jsDate);
|
|
804
|
+
date.#offset = offset;
|
|
805
|
+
return date;
|
|
806
|
+
}
|
|
807
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
808
|
+
let date = new TomlDate(jsDate);
|
|
809
|
+
date.#offset = null;
|
|
810
|
+
return date;
|
|
811
|
+
}
|
|
812
|
+
static wrapAsLocalDate(jsDate) {
|
|
813
|
+
let date = new TomlDate(jsDate);
|
|
814
|
+
date.#hasTime = false;
|
|
815
|
+
date.#offset = null;
|
|
816
|
+
return date;
|
|
817
|
+
}
|
|
818
|
+
static wrapAsLocalTime(jsDate) {
|
|
819
|
+
let date = new TomlDate(jsDate);
|
|
820
|
+
date.#hasDate = false;
|
|
821
|
+
date.#offset = null;
|
|
822
|
+
return date;
|
|
960
823
|
}
|
|
961
|
-
const date = new TomlDate(value);
|
|
962
|
-
if (!date.isValid())
|
|
963
|
-
throw new TomlError('invalid value', err);
|
|
964
|
-
return date;
|
|
965
824
|
}
|
|
966
825
|
|
|
967
826
|
/*!
|
|
@@ -991,21 +850,29 @@ function parseValue(ctx, integersAsBigInt, end) {
|
|
|
991
850
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
992
851
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
993
852
|
*/
|
|
853
|
+
function isDigit(char, base = 10) {
|
|
854
|
+
return base === 16
|
|
855
|
+
? (char > 0x2f && char < 0x3a) || (char > 0x40 && char < 0x47) || (char > 0x60 && char < 0x67)
|
|
856
|
+
: (char > 0x2f && char < 0x30 + base);
|
|
857
|
+
}
|
|
858
|
+
function isEndOfValue(char, delim) {
|
|
859
|
+
// Whitespace -- we're permissive on `\r` for performance; it'll be dealt with later anyway
|
|
860
|
+
return char === 0x20 || char === 0x9 /* \t */ || char === 0xa /* \n */ || char === 0xd /* \r */ ||
|
|
861
|
+
// Structure end or next value delimiter
|
|
862
|
+
(delim && (char === delim || char === 0x2c /* , */)) ||
|
|
863
|
+
// Comment
|
|
864
|
+
char === 0x23; /* # */
|
|
865
|
+
}
|
|
994
866
|
/** @internal */
|
|
995
|
-
function extractValue(ctx, end
|
|
996
|
-
let
|
|
997
|
-
let c = ctx.s.charCodeAt(
|
|
867
|
+
function extractValue(ctx, end) {
|
|
868
|
+
let errPtr = ctx.p;
|
|
869
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
998
870
|
// Structs
|
|
999
871
|
if (c === 0x5b /* [ */ || c === 0x7b /* { */) {
|
|
1000
|
-
|
|
1001
|
-
throw new TomlError('document contains excessively nested structures. aborting.', {
|
|
1002
|
-
toml: ctx.s,
|
|
1003
|
-
ptr,
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
872
|
+
ctx.d-- || TomlError.x('document contains excessively nested structures. aborting.', ctx);
|
|
1006
873
|
let value = c === 0x5b /* [ */
|
|
1007
|
-
? parseArray(ctx
|
|
1008
|
-
: parseInlineTable(ctx
|
|
874
|
+
? parseArray(ctx)
|
|
875
|
+
: parseInlineTable(ctx);
|
|
1009
876
|
ctx.d++;
|
|
1010
877
|
return value;
|
|
1011
878
|
}
|
|
@@ -1017,18 +884,229 @@ function extractValue(ctx, end, integersAsBigInt) {
|
|
|
1017
884
|
// We can fast-path because the first character is enough to know the only possible value
|
|
1018
885
|
if (c === 0x74 /* t */) { // Only possible valid value is `true`
|
|
1019
886
|
if (ctx.s.charCodeAt(++ctx.p) !== 0x72 || ctx.s.charCodeAt(++ctx.p) !== 0x75 || ctx.s.charCodeAt(++ctx.p) !== 0x65)
|
|
1020
|
-
|
|
1021
|
-
ctx.p
|
|
1022
|
-
return true;
|
|
887
|
+
TomlError.x('invalid value', ctx, errPtr);
|
|
888
|
+
return ctx.p++, true;
|
|
1023
889
|
}
|
|
1024
890
|
if (c === 0x66 /* f */) { // Only possible valid value is `false`
|
|
1025
891
|
if (ctx.s.charCodeAt(++ctx.p) !== 0x61 || ctx.s.charCodeAt(++ctx.p) !== 0x6c || ctx.s.charCodeAt(++ctx.p) !== 0x73 || ctx.s.charCodeAt(++ctx.p) !== 0x65)
|
|
1026
|
-
|
|
1027
|
-
ctx.p
|
|
1028
|
-
|
|
892
|
+
TomlError.x('invalid value', ctx, errPtr);
|
|
893
|
+
return ctx.p++, false;
|
|
894
|
+
}
|
|
895
|
+
if (c === 0x2b /* + */ || c === 0x2d /* - */) {
|
|
896
|
+
return parseNumber(ctx, ctx.p, ctx.s.charCodeAt(++ctx.p), 0x2c - c, end);
|
|
897
|
+
}
|
|
898
|
+
// Rough heuristic, but `parseDate` falls back to number parsing if it's a false positive.
|
|
899
|
+
// e.g.: `a = 1\n-------------- = 1` would match this heuristic, but gracefully fallback to numbers.
|
|
900
|
+
if (ctx.s.charCodeAt(ctx.p + 4) === 0x2d /* - */ && ctx.s.charCodeAt(ctx.p + 7) === 0x2d /* - */) {
|
|
901
|
+
return parseDate(ctx, c, end);
|
|
902
|
+
}
|
|
903
|
+
// Same logic as above; `parseTime` falls back to number parsing if it's a false positive.
|
|
904
|
+
if (ctx.s.charCodeAt(ctx.p + 2) === 0x3a /* : */) {
|
|
905
|
+
return parseTime(ctx, c, end);
|
|
906
|
+
}
|
|
907
|
+
return parseNumber(ctx, ctx.p, c, 0, end);
|
|
908
|
+
}
|
|
909
|
+
// State:
|
|
910
|
+
// 0: init
|
|
911
|
+
// 1: integer
|
|
912
|
+
// 2: fractional dot
|
|
913
|
+
// 3: fractional
|
|
914
|
+
// 4: exponent letter
|
|
915
|
+
// 5: exponent
|
|
916
|
+
// >9: underscore; see below
|
|
917
|
+
// -> 12: was integer
|
|
918
|
+
// -> 14: was fractional
|
|
919
|
+
// -> 16: was exponent
|
|
920
|
+
// states 2-5, 14, 16 are ONLY permitted iif base === 10
|
|
921
|
+
function parseNumber(ctx, startPtr, startChr, sign, endChr) {
|
|
922
|
+
let c = startChr;
|
|
923
|
+
let state = 0;
|
|
924
|
+
let hasUnderscores = false;
|
|
925
|
+
// (+/-)inf
|
|
926
|
+
if (c === 0x69 /* i */) {
|
|
927
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 0x6e || ctx.s.charCodeAt(++ctx.p) !== 0x66)
|
|
928
|
+
TomlError.x('invalid value', ctx, startPtr);
|
|
929
|
+
return ctx.p++, (sign || 1) / 0;
|
|
930
|
+
}
|
|
931
|
+
// (+/-)nan
|
|
932
|
+
if (c === 0x6e /* n */) {
|
|
933
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 0x61 || ctx.s.charCodeAt(++ctx.p) !== 0x6e)
|
|
934
|
+
TomlError.x('invalid value', ctx, startPtr);
|
|
935
|
+
return ctx.p++, NaN;
|
|
936
|
+
}
|
|
937
|
+
// Leading zero
|
|
938
|
+
// Only allowed cases: `0<EOV>`, `0.(...)`, `0e(...)`, `0x(...)`, `0b(...)`, `0o(...)`
|
|
939
|
+
// FWIW, `0e(...)` is a stupid case, but it's not banned per-se so we have to parse it
|
|
940
|
+
if (c === 0x30 /* 0 */) {
|
|
941
|
+
if (++ctx.p >= ctx.s.length || isEndOfValue(c = ctx.s.charCodeAt(ctx.p), endChr))
|
|
942
|
+
return ctx.bi === true ? 0n : 0; // note: conveniently deals with `-0`
|
|
943
|
+
if (!sign) {
|
|
944
|
+
if (c === 0x78 /* x */)
|
|
945
|
+
return parseIntegerBaseN(ctx, startPtr, 16, endChr);
|
|
946
|
+
else if (c === 0x62 /* b */)
|
|
947
|
+
return parseIntegerBaseN(ctx, startPtr, 2, endChr);
|
|
948
|
+
else if (c === 0x6f /* o */)
|
|
949
|
+
return parseIntegerBaseN(ctx, startPtr, 8, endChr);
|
|
950
|
+
}
|
|
951
|
+
if (c === 0x2e /* . */)
|
|
952
|
+
state = 2;
|
|
953
|
+
else if (c === 0x65 /* e */ || c === 0x45 /* E */)
|
|
954
|
+
state = 4;
|
|
955
|
+
else
|
|
956
|
+
TomlError.x('illegal leading zero', ctx, startPtr);
|
|
957
|
+
}
|
|
958
|
+
// If the 1st char is not a digit by now, then it's not a valid TOML value at all
|
|
959
|
+
else if (!isDigit(c))
|
|
960
|
+
TomlError.x('invalid value', ctx, startPtr);
|
|
961
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
962
|
+
if (!state)
|
|
963
|
+
state = 1; // Detects single-digit numbers we can use a fast parse path for
|
|
964
|
+
// The way the states are numbered is not random: underscores are always permitted in odd-numbered states and
|
|
965
|
+
// never permitted in even-numbered ones.
|
|
966
|
+
if (c === 0x5f /* _ */) {
|
|
967
|
+
if (!(state & 1))
|
|
968
|
+
TomlError.x('illegal underscore', ctx);
|
|
969
|
+
state += 11; // 11 is a marker that makes the state even and greater than 9; see the numbering + rationale above
|
|
970
|
+
hasUnderscores = true;
|
|
971
|
+
}
|
|
972
|
+
// Transition to fractional part.
|
|
973
|
+
else if (state === 1 && c === 0x2e /* . */)
|
|
974
|
+
state = 2;
|
|
975
|
+
// Transition to exponent part.
|
|
976
|
+
else if ((state === 1 || state === 3) && (c === 0x65 /* e */ || c === 0x45 /* E */))
|
|
977
|
+
state = 4;
|
|
978
|
+
// + and - are permitted in state 4 only (handled before entering the function for state 0)
|
|
979
|
+
else if (state === 4 && (c === 0x2b /* + */ || c === 0x2d /* - */)) ;
|
|
980
|
+
// All special cases have been handled; only digits are allowed here
|
|
981
|
+
else if (!isDigit(c))
|
|
982
|
+
TomlError.x(`illegal character in numeric literal`, ctx);
|
|
983
|
+
// Clear state flags
|
|
984
|
+
else if (state > 9)
|
|
985
|
+
state -= 11;
|
|
986
|
+
else if (!(state & 1))
|
|
987
|
+
state++;
|
|
988
|
+
}
|
|
989
|
+
// Single-char number; we can fast-path these very easily.
|
|
990
|
+
if (!state) {
|
|
991
|
+
let val = (startChr - 0x30 /* 0 */) * (sign || 1);
|
|
992
|
+
return ctx.bi === true ? BigInt(val) : val;
|
|
993
|
+
}
|
|
994
|
+
// Even-numbered states absolutely require a digit next; not even end of value is permitted
|
|
995
|
+
if (!(state & 1))
|
|
996
|
+
TomlError.x('unfinished numeric value', ctx, startPtr);
|
|
997
|
+
let str = ctx.s.slice(startPtr, ctx.p);
|
|
998
|
+
if (hasUnderscores)
|
|
999
|
+
str = str.replaceAll('_', ''); // perf: replaceAll 1.25x faster than replace with a regex
|
|
1000
|
+
return state > 1
|
|
1001
|
+
? parseFloat(str)
|
|
1002
|
+
: parseInteger(ctx, str, 10, startPtr);
|
|
1003
|
+
}
|
|
1004
|
+
function parseIntegerBaseN(ctx, startPtr, base, endChr) {
|
|
1005
|
+
let c, underscore = 1;
|
|
1006
|
+
while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
|
|
1007
|
+
if (c === 0x5f /* _ */) {
|
|
1008
|
+
if (underscore & 1)
|
|
1009
|
+
TomlError.x('illegal underscore', ctx);
|
|
1010
|
+
underscore = 3;
|
|
1011
|
+
}
|
|
1012
|
+
// We only need to check if the number is a valid digit, nothing else is permitted
|
|
1013
|
+
else if (!isDigit(c, base))
|
|
1014
|
+
TomlError.x(`illegal character in numeric literal`, ctx);
|
|
1015
|
+
// Clear underscore flag
|
|
1016
|
+
else if (underscore & 1)
|
|
1017
|
+
underscore--;
|
|
1018
|
+
}
|
|
1019
|
+
// Trailing underscore is not allowed
|
|
1020
|
+
if (underscore & 1)
|
|
1021
|
+
TomlError.x('unfinished numeric value', ctx);
|
|
1022
|
+
let str = ctx.s.slice(startPtr + 2, ctx.p);
|
|
1023
|
+
if (underscore)
|
|
1024
|
+
str = str.replaceAll('_', ''); // perf: replaceAll 1.25x faster than replace with a regex
|
|
1025
|
+
return parseInteger(ctx, str, base, startPtr);
|
|
1026
|
+
}
|
|
1027
|
+
function parseInteger(ctx, str, base, startPtr) {
|
|
1028
|
+
if (ctx.bi !== true)
|
|
1029
|
+
int: {
|
|
1030
|
+
let val = parseInt(str, base);
|
|
1031
|
+
if (!Number.isSafeInteger(val)) {
|
|
1032
|
+
if (ctx.bi)
|
|
1033
|
+
break int;
|
|
1034
|
+
TomlError.x('integer value cannot be represented losslessly', ctx, startPtr);
|
|
1035
|
+
}
|
|
1036
|
+
return val;
|
|
1037
|
+
}
|
|
1038
|
+
return base === 10 ? BigInt(str) : BigInt((base === 2 ? '0b' : base === 8 ? '0o' : '0x') + str);
|
|
1039
|
+
}
|
|
1040
|
+
function parseDate(ctx, c, endChr) {
|
|
1041
|
+
let startPtr = ctx.p++, unsafeSeparator;
|
|
1042
|
+
if (!isDigit(c) ||
|
|
1043
|
+
!isDigit(ctx.s.charCodeAt(ctx.p++)) ||
|
|
1044
|
+
!isDigit(ctx.s.charCodeAt(ctx.p++)) ||
|
|
1045
|
+
!isDigit(ctx.s.charCodeAt(ctx.p++))) {
|
|
1046
|
+
return parseNumber(ctx, ctx.p = startPtr, c, 0, endChr);
|
|
1047
|
+
}
|
|
1048
|
+
ctx.p += 5;
|
|
1049
|
+
if (!isDigit(ctx.s.charCodeAt(ctx.p++)))
|
|
1050
|
+
TomlError.x('invalid date-time: date part is malformed', ctx, startPtr);
|
|
1051
|
+
if (ctx.p >= ctx.s.length || (((c = ctx.s.charCodeAt(ctx.p)) !== 0x20 || (unsafeSeparator = true, !isDigit(ctx.s.charCodeAt(ctx.p + 1)))) && c !== 0x54 /* T */ && c !== 0x74 /* t */)) {
|
|
1052
|
+
let t = ctx.s.slice(startPtr, ctx.p);
|
|
1053
|
+
return readDate(ctx, t, 3, false, startPtr);
|
|
1054
|
+
}
|
|
1055
|
+
if (ctx.s.charCodeAt(ctx.p += 3) !== 0x3a /* : */)
|
|
1056
|
+
TomlError.x('invalid date-time: time part is malformed', ctx, startPtr);
|
|
1057
|
+
if (ctx.s.charCodeAt(ctx.p += 3) === 0x3a /* : */)
|
|
1058
|
+
ctx.p += 3;
|
|
1059
|
+
if (ctx.s.charCodeAt(ctx.p) === 0x2e /* . */)
|
|
1060
|
+
while (isDigit(ctx.s.charCodeAt(++ctx.p)))
|
|
1061
|
+
;
|
|
1062
|
+
if (c = ctx.s.charCodeAt(ctx.p)) {
|
|
1063
|
+
if (c === 0x5a /* Z */ || c === 0x7a /* z */) {
|
|
1064
|
+
let t = ctx.s.slice(startPtr, ++ctx.p);
|
|
1065
|
+
return readDate(ctx, t, 1, unsafeSeparator, startPtr, '[+00:00]');
|
|
1066
|
+
}
|
|
1067
|
+
if (c === 0x2b /* + */ || c === 0x2d /* - */) {
|
|
1068
|
+
// Temporal's ZonedDateTime is weird asf when it comes to dealing with traditional offsets...
|
|
1069
|
+
// It's 1.2x faster to allocate a new string to pass to ZDT than use Instant.toZonedDateTimeISO
|
|
1070
|
+
let t = ctx.s.slice(startPtr, ctx.p += 6);
|
|
1071
|
+
return readDate(ctx, t, 1, unsafeSeparator, startPtr, !ctx.ld && ('[' + ctx.s.slice(ctx.p - 6, ctx.p) + ']'));
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
let t = ctx.s.slice(startPtr, ctx.p);
|
|
1075
|
+
return readDate(ctx, t, 2, unsafeSeparator, startPtr);
|
|
1076
|
+
}
|
|
1077
|
+
function parseTime(ctx, c, endChr) {
|
|
1078
|
+
let start = ctx.p;
|
|
1079
|
+
if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(++ctx.p))) {
|
|
1080
|
+
return parseNumber(ctx, --ctx.p, c, 0, endChr);
|
|
1081
|
+
}
|
|
1082
|
+
if (ctx.s.charCodeAt(ctx.p += 4) === 0x3a /* : */)
|
|
1083
|
+
ctx.p += 3;
|
|
1084
|
+
if (ctx.s.charCodeAt(ctx.p) === 0x2e /* . */)
|
|
1085
|
+
while (isDigit(ctx.s.charCodeAt(++ctx.p)))
|
|
1086
|
+
;
|
|
1087
|
+
let t = ctx.s.slice(start, ctx.p);
|
|
1088
|
+
return readDate(ctx, t, 4, false, start);
|
|
1089
|
+
}
|
|
1090
|
+
function readDate(ctx, str, type, unsafeDelim, errPtr, temporalSuffix) {
|
|
1091
|
+
if (ctx.ld) {
|
|
1092
|
+
let date = new TomlDate(str, type, unsafeDelim);
|
|
1093
|
+
if (!date.isValid())
|
|
1094
|
+
TomlError.x('invalid date', ctx, errPtr);
|
|
1095
|
+
return date;
|
|
1096
|
+
}
|
|
1097
|
+
try {
|
|
1098
|
+
if (temporalSuffix)
|
|
1099
|
+
str += temporalSuffix;
|
|
1100
|
+
switch (type) {
|
|
1101
|
+
case 1: return Temporal.ZonedDateTime.from(str);
|
|
1102
|
+
case 2: return Temporal.PlainDateTime.from(str);
|
|
1103
|
+
case 3: return Temporal.PlainDate.from(str);
|
|
1104
|
+
case 4: return Temporal.PlainTime.from(str);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
catch (e) {
|
|
1108
|
+
TomlError.x(e instanceof Error ? e.message : '' + e, ctx, errPtr);
|
|
1029
1109
|
}
|
|
1030
|
-
// Legacy logic for numbers and dates. Slow and needs to be rewritten.
|
|
1031
|
-
return parseValue(ctx, integersAsBigInt, end);
|
|
1032
1110
|
}
|
|
1033
1111
|
|
|
1034
1112
|
/*!
|
|
@@ -1058,83 +1136,124 @@ function extractValue(ctx, end, integersAsBigInt) {
|
|
|
1058
1136
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1059
1137
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1060
1138
|
*/
|
|
1061
|
-
let KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
1062
1139
|
/** @internal */
|
|
1063
|
-
function
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1140
|
+
function skipComment$1(ctx) {
|
|
1141
|
+
for (; ctx.p < ctx.s.length; ctx.p++) {
|
|
1142
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
1143
|
+
if (c === 0xa /* \n */)
|
|
1144
|
+
break;
|
|
1145
|
+
if (c === 0xd /* \r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \n */) {
|
|
1146
|
+
ctx.p++;
|
|
1147
|
+
break;
|
|
1148
|
+
}
|
|
1149
|
+
if ((c < 0x20 && c !== 0x9 /* \t */) || c === 0x7f) {
|
|
1150
|
+
TomlError.x('control characters are not allowed in comments', ctx);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
/** @internal */
|
|
1155
|
+
function skipVoid(ctx, banNewLines, banComments) {
|
|
1156
|
+
let c;
|
|
1157
|
+
while (ctx.p < ctx.s.length) {
|
|
1158
|
+
while (ctx.p < ctx.s.length && ((c = ctx.s.charCodeAt(ctx.p)) === 0x20 ||
|
|
1159
|
+
c === 0x9 /* \t */ ||
|
|
1160
|
+
(!banNewLines &&
|
|
1161
|
+
(c === 0xa /* \n */ || (c === 0xd /* \r */ && ctx.s.charCodeAt(ctx.p + 1) === 0xa /* \n */)))))
|
|
1162
|
+
ctx.p++;
|
|
1163
|
+
if (banComments || c !== 0x23 /* # */)
|
|
1164
|
+
break;
|
|
1165
|
+
skipComment$1(ctx);
|
|
1073
1166
|
}
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/*!
|
|
1170
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1171
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
1172
|
+
*
|
|
1173
|
+
* Redistribution and use in source and binary forms, with or without
|
|
1174
|
+
* modification, are permitted provided that the following conditions are met:
|
|
1175
|
+
*
|
|
1176
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1177
|
+
* list of conditions and the following disclaimer.
|
|
1178
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1179
|
+
* this list of conditions and the following disclaimer in the
|
|
1180
|
+
* documentation and/or other materials provided with the distribution.
|
|
1181
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1182
|
+
* may be used to endorse or promote products derived from this software without
|
|
1183
|
+
* specific prior written permission.
|
|
1184
|
+
*
|
|
1185
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1186
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1187
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1188
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1189
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1190
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1191
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1192
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1193
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1194
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1195
|
+
*/
|
|
1196
|
+
/** @internal */
|
|
1197
|
+
function parseKey(ctx, end = 0x3d /* = */) {
|
|
1198
|
+
// States:
|
|
1199
|
+
// 0: before first char
|
|
1200
|
+
// 1: parsing bare key
|
|
1201
|
+
// 2: after key component
|
|
1202
|
+
let startPtr;
|
|
1203
|
+
let state = 0;
|
|
1204
|
+
let parsed = [];
|
|
1205
|
+
let sliceStart;
|
|
1206
|
+
let c = ctx.s.charCodeAt(startPtr = ctx.p);
|
|
1074
1207
|
do {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
if (
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if (endPtr < 0) {
|
|
1105
|
-
throw new TomlError('incomplete key-value: cannot find end of key', {
|
|
1106
|
-
toml: ctx.s,
|
|
1107
|
-
ptr: start,
|
|
1108
|
-
});
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
parsed.push(part);
|
|
1112
|
-
}
|
|
1113
|
-
else {
|
|
1114
|
-
// Normal raw key part consumption and validation
|
|
1115
|
-
dot = ctx.s.indexOf('.', ctx.p);
|
|
1116
|
-
let part = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
1117
|
-
if (!KEY_PART_RE.test(part)) {
|
|
1118
|
-
throw new TomlError('only letter, numbers, dashes and underscores are allowed in keys', {
|
|
1119
|
-
toml: ctx.s,
|
|
1120
|
-
ptr: ctx.p,
|
|
1121
|
-
});
|
|
1122
|
-
}
|
|
1123
|
-
parsed.push(part.trimEnd());
|
|
1208
|
+
// End of key
|
|
1209
|
+
if (c === end) {
|
|
1210
|
+
if (!state)
|
|
1211
|
+
TomlError.x('unexpected end of key', ctx);
|
|
1212
|
+
if (state === 1)
|
|
1213
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
1214
|
+
return ctx.p++, parsed;
|
|
1215
|
+
}
|
|
1216
|
+
// Dotted key separator
|
|
1217
|
+
else if (c === 0x2e /* . */) {
|
|
1218
|
+
if (!state)
|
|
1219
|
+
TomlError.x('illegal empty bare key', ctx);
|
|
1220
|
+
if (state === 1)
|
|
1221
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
1222
|
+
state = 0;
|
|
1223
|
+
}
|
|
1224
|
+
// Quoted key
|
|
1225
|
+
else if (!state && (c === 0x22 /* " */ || c === 0x27 /* ' */)) {
|
|
1226
|
+
if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2))
|
|
1227
|
+
TomlError.x('illegal quoted key: multiline strings are not allowed', ctx);
|
|
1228
|
+
parsed.push(parseString(ctx));
|
|
1229
|
+
state = 2;
|
|
1230
|
+
ctx.p--;
|
|
1231
|
+
}
|
|
1232
|
+
// Whitespace; no-op in state 0 and 2, end of bare key in state 1
|
|
1233
|
+
else if (c === 0x20 || c === 0x9 /* \t */) {
|
|
1234
|
+
if (state === 1) {
|
|
1235
|
+
parsed.push(ctx.s.slice(sliceStart, ctx.p));
|
|
1236
|
+
state = 2;
|
|
1124
1237
|
}
|
|
1125
1238
|
}
|
|
1126
|
-
//
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1239
|
+
// If state is post-key, no character is allowed; otherwise ensure it's a bare-key component
|
|
1240
|
+
else if (state === 2 || (c < 0x30 && c !== 0x2d /* - */) || (c > 0x39 && c < 0x41) || (c > 0x5a && c < 0x61 && c !== 0x5f /* _ */) || c > 0x7a) {
|
|
1241
|
+
TomlError.x('illegal character in key', ctx);
|
|
1242
|
+
}
|
|
1243
|
+
// Illegal character
|
|
1244
|
+
else if (!state) {
|
|
1245
|
+
state = 1;
|
|
1246
|
+
sliceStart = ctx.p;
|
|
1247
|
+
}
|
|
1248
|
+
} while (c = ctx.s.charCodeAt(++ctx.p));
|
|
1249
|
+
TomlError.x('incomplete key-value: cannot find end of key', ctx, startPtr);
|
|
1131
1250
|
}
|
|
1132
1251
|
/** @internal */
|
|
1133
|
-
function parseInlineTable(ctx
|
|
1134
|
-
let
|
|
1252
|
+
function parseInlineTable(ctx) {
|
|
1253
|
+
let startPtr = ctx.p++;
|
|
1254
|
+
let res = Object.create(null);
|
|
1135
1255
|
let seen = new Set();
|
|
1136
1256
|
let c;
|
|
1137
|
-
ctx.p++;
|
|
1138
1257
|
while (ctx.p < ctx.s.length) {
|
|
1139
1258
|
skipVoid(ctx);
|
|
1140
1259
|
if ((c = ctx.s.charCodeAt(ctx.p)) === 0x7d /* } */) {
|
|
@@ -1144,67 +1263,60 @@ function parseInlineTable(ctx, integersAsBigInt) {
|
|
|
1144
1263
|
let k;
|
|
1145
1264
|
let t = res;
|
|
1146
1265
|
let hasOwn = false;
|
|
1147
|
-
let
|
|
1266
|
+
let errPtr = ctx.p;
|
|
1148
1267
|
let key = parseKey(ctx);
|
|
1149
1268
|
for (let i = 0; i < key.length; i++) {
|
|
1150
1269
|
if (i)
|
|
1151
|
-
t = hasOwn ? t[k] : (t[k] =
|
|
1270
|
+
t = hasOwn ? t[k] : (t[k] = Object.create(null));
|
|
1152
1271
|
k = key[i];
|
|
1153
1272
|
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== 'object' || seen.has(t[k]))) {
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1273
|
+
TomlError.x('trying to redefine an already defined value', ctx, errPtr);
|
|
1274
|
+
}
|
|
1275
|
+
let unsafe = k === '__proto__';
|
|
1276
|
+
if (ctx.uk && (unsafe || k === 'constructor')) {
|
|
1277
|
+
t = ctx.uk !== 1 && TomlError.x('document contains an unsafe property', ctx, errPtr);
|
|
1278
|
+
break;
|
|
1158
1279
|
}
|
|
1159
|
-
if (!hasOwn &&
|
|
1280
|
+
if (!hasOwn && unsafe) {
|
|
1160
1281
|
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
1161
1282
|
}
|
|
1162
1283
|
}
|
|
1163
1284
|
if (hasOwn) {
|
|
1164
|
-
|
|
1165
|
-
toml: ctx.s,
|
|
1166
|
-
ptr: ctx.p,
|
|
1167
|
-
});
|
|
1285
|
+
TomlError.x('trying to redefine an already defined value', ctx, errPtr);
|
|
1168
1286
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1287
|
+
skipVoid(ctx, true, true);
|
|
1288
|
+
let value = extractValue(ctx, 0x7d /* } */);
|
|
1289
|
+
if (t && typeof (t[k] = value) === 'object')
|
|
1290
|
+
seen.add(value);
|
|
1171
1291
|
skipVoid(ctx);
|
|
1172
1292
|
if ((c = ctx.s.charCodeAt(ctx.p++)) === 0x7d /* } */) {
|
|
1173
1293
|
return res;
|
|
1174
1294
|
}
|
|
1175
|
-
if (c !== 0x2c /* , */)
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1295
|
+
if (c !== 0x2c /* , */)
|
|
1296
|
+
TomlError.x('expected comma or end of structure', ctx, ctx.p - 1);
|
|
1178
1297
|
}
|
|
1179
|
-
|
|
1180
|
-
toml: ctx.s,
|
|
1181
|
-
ptr: ctx.p,
|
|
1182
|
-
});
|
|
1298
|
+
TomlError.x('unfinished table', ctx, startPtr);
|
|
1183
1299
|
}
|
|
1184
1300
|
/** @internal */
|
|
1185
|
-
function parseArray(ctx
|
|
1301
|
+
function parseArray(ctx) {
|
|
1302
|
+
let startPtr = ctx.p++;
|
|
1186
1303
|
let res = [];
|
|
1187
1304
|
let c;
|
|
1188
|
-
ctx.p++;
|
|
1189
1305
|
while (ctx.p < ctx.s.length) {
|
|
1190
1306
|
skipVoid(ctx);
|
|
1191
1307
|
if ((c = ctx.s.charCodeAt(ctx.p)) === 0x5d /* ] */) {
|
|
1192
1308
|
ctx.p++;
|
|
1193
1309
|
return res;
|
|
1194
1310
|
}
|
|
1195
|
-
res.push(extractValue(ctx, 0x5d /* ]
|
|
1311
|
+
res.push(extractValue(ctx, 0x5d /* ] */));
|
|
1196
1312
|
skipVoid(ctx);
|
|
1197
1313
|
if ((c = ctx.s.charCodeAt(ctx.p++)) === 0x5d /* ] */) {
|
|
1198
1314
|
return res;
|
|
1199
1315
|
}
|
|
1200
|
-
if (c !== 0x2c /* , */)
|
|
1201
|
-
|
|
1202
|
-
}
|
|
1316
|
+
if (c !== 0x2c /* , */)
|
|
1317
|
+
TomlError.x('expected comma or end of structure', ctx, ctx.p - 1);
|
|
1203
1318
|
}
|
|
1204
|
-
|
|
1205
|
-
toml: ctx.s,
|
|
1206
|
-
ptr: ctx.p,
|
|
1207
|
-
});
|
|
1319
|
+
TomlError.x('unfinished array', ctx, startPtr);
|
|
1208
1320
|
}
|
|
1209
1321
|
|
|
1210
1322
|
/*!
|
|
@@ -1234,7 +1346,7 @@ function parseArray(ctx, integersAsBigInt) {
|
|
|
1234
1346
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1235
1347
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1236
1348
|
*/
|
|
1237
|
-
function peekTable(key, table, meta, type) {
|
|
1349
|
+
function peekTable(ctx, key, table, meta, type) {
|
|
1238
1350
|
let t = table;
|
|
1239
1351
|
let m = meta;
|
|
1240
1352
|
let k;
|
|
@@ -1242,7 +1354,7 @@ function peekTable(key, table, meta, type) {
|
|
|
1242
1354
|
let state;
|
|
1243
1355
|
for (let i = 0; i < key.length; i++) {
|
|
1244
1356
|
if (i) {
|
|
1245
|
-
t = hasOwn ? t[k] : (t[k] =
|
|
1357
|
+
t = hasOwn ? t[k] : (t[k] = Object.create(null));
|
|
1246
1358
|
m = (state = m[k]).c;
|
|
1247
1359
|
if (type === 0 /* Type.DOTTED */ && (state.t === 1 /* Type.EXPLICIT */ || state.t === 2 /* Type.ARRAY */)) {
|
|
1248
1360
|
return null;
|
|
@@ -1258,7 +1370,10 @@ function peekTable(key, table, meta, type) {
|
|
|
1258
1370
|
return null;
|
|
1259
1371
|
}
|
|
1260
1372
|
if (!hasOwn) {
|
|
1261
|
-
|
|
1373
|
+
let unsafe = k === '__proto__';
|
|
1374
|
+
if (ctx.uk && (unsafe || k === 'constructor'))
|
|
1375
|
+
return false;
|
|
1376
|
+
if (unsafe) {
|
|
1262
1377
|
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
1263
1378
|
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
1264
1379
|
}
|
|
@@ -1267,7 +1382,7 @@ function peekTable(key, table, meta, type) {
|
|
|
1267
1382
|
? 3 /* Type.ARRAY_DOTTED */ : type,
|
|
1268
1383
|
d: false,
|
|
1269
1384
|
i: 0,
|
|
1270
|
-
c:
|
|
1385
|
+
c: Object.create(null),
|
|
1271
1386
|
};
|
|
1272
1387
|
}
|
|
1273
1388
|
}
|
|
@@ -1281,8 +1396,8 @@ function peekTable(key, table, meta, type) {
|
|
|
1281
1396
|
state.d = true;
|
|
1282
1397
|
t[k] = [];
|
|
1283
1398
|
}
|
|
1284
|
-
t[k].push(t =
|
|
1285
|
-
state.c[state.i++] = (state = { t: 1 /* Type.EXPLICIT */, d: false, i: 0, c:
|
|
1399
|
+
t[k].push(t = Object.create(null));
|
|
1400
|
+
state.c[state.i++] = (state = { t: 1 /* Type.EXPLICIT */, d: false, i: 0, c: Object.create(null) });
|
|
1286
1401
|
}
|
|
1287
1402
|
if (state.d) {
|
|
1288
1403
|
// Redefining a table!
|
|
@@ -1290,63 +1405,75 @@ function peekTable(key, table, meta, type) {
|
|
|
1290
1405
|
}
|
|
1291
1406
|
state.d = true;
|
|
1292
1407
|
if (type === 1 /* Type.EXPLICIT */) {
|
|
1293
|
-
t = hasOwn ? t[k] : (t[k] =
|
|
1408
|
+
t = hasOwn ? t[k] : (t[k] = Object.create(null));
|
|
1294
1409
|
}
|
|
1295
1410
|
else if (type === 0 /* Type.DOTTED */ && hasOwn) {
|
|
1296
1411
|
return null;
|
|
1297
1412
|
}
|
|
1298
1413
|
return [k, t, state.c];
|
|
1299
1414
|
}
|
|
1300
|
-
function
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1415
|
+
function validateTablePeek(ctx, peek, ptr) {
|
|
1416
|
+
if (peek === null || ctx.uk === 2)
|
|
1417
|
+
TomlError.x(peek === null
|
|
1418
|
+
? 'trying to redefine an already defined table or value'
|
|
1419
|
+
: 'document contains an unsafe property', ctx, ptr);
|
|
1420
|
+
}
|
|
1421
|
+
function parse$4(toml, options = {}) {
|
|
1422
|
+
let ctx = {
|
|
1423
|
+
s: toml,
|
|
1424
|
+
p: 0,
|
|
1425
|
+
d: options.maxDepth ?? 1000,
|
|
1426
|
+
bi: options.integersAsBigInt ?? false,
|
|
1427
|
+
ld: options.useLegacyDate ?? true,
|
|
1428
|
+
uk: options.unsafeKeyBehaviour === 'throw' ? 2 : options.unsafeKeyBehaviour === 'drop' ? 1 : 0,
|
|
1429
|
+
};
|
|
1430
|
+
let res = Object.create(null);
|
|
1431
|
+
let meta = Object.create(null);
|
|
1304
1432
|
let tmp;
|
|
1433
|
+
let skipping = false;
|
|
1305
1434
|
let tbl = res;
|
|
1306
1435
|
let m = meta;
|
|
1436
|
+
// BOM is allowed, skip.
|
|
1437
|
+
// JS is UTF-16, so we have to check for the UTF-16 BOM instead of the UTF-8 BOM sequence!
|
|
1438
|
+
if (toml.charCodeAt(0) === 0xfeff)
|
|
1439
|
+
ctx.p++;
|
|
1307
1440
|
skipVoid(ctx);
|
|
1308
1441
|
while (ctx.p < toml.length) {
|
|
1309
1442
|
if (toml.charCodeAt(ctx.p) === 0x5b /* [ */) {
|
|
1310
1443
|
let isTableArray = toml.charCodeAt(++ctx.p) === 0x5b; /* [ */
|
|
1311
1444
|
tmp = ctx.p += +isTableArray;
|
|
1312
|
-
|
|
1445
|
+
skipping = false;
|
|
1446
|
+
let k = parseKey(ctx, 0x5d /* ] */);
|
|
1313
1447
|
if (isTableArray) {
|
|
1314
|
-
if (toml.charCodeAt(ctx.p
|
|
1315
|
-
|
|
1316
|
-
toml: toml,
|
|
1317
|
-
ptr: ctx.p - 1,
|
|
1318
|
-
});
|
|
1448
|
+
if (toml.charCodeAt(ctx.p) !== 0x5d /* ] */) {
|
|
1449
|
+
TomlError.x('expected end of table array declaration', ctx);
|
|
1319
1450
|
}
|
|
1320
1451
|
ctx.p++;
|
|
1321
1452
|
}
|
|
1322
|
-
let p = peekTable(k, res, meta, isTableArray ? 2 /* Type.ARRAY */ : 1 /* Type.EXPLICIT */);
|
|
1453
|
+
let p = peekTable(ctx, k, res, meta, isTableArray ? 2 /* Type.ARRAY */ : 1 /* Type.EXPLICIT */);
|
|
1323
1454
|
if (!p) {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1455
|
+
validateTablePeek(ctx, p, tmp);
|
|
1456
|
+
skipping = true;
|
|
1457
|
+
}
|
|
1458
|
+
else {
|
|
1459
|
+
m = p[2];
|
|
1460
|
+
tbl = p[1];
|
|
1328
1461
|
}
|
|
1329
|
-
m = p[2];
|
|
1330
|
-
tbl = p[1];
|
|
1331
1462
|
}
|
|
1332
1463
|
else {
|
|
1333
1464
|
tmp = ctx.p;
|
|
1334
1465
|
let k = parseKey(ctx);
|
|
1335
|
-
let p = peekTable(k, tbl, m, 0 /* Type.DOTTED */);
|
|
1336
|
-
if (!p)
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
p[1][p[0]] = extractValue(ctx, void 0, integersAsBigInt);
|
|
1466
|
+
let p = peekTable(ctx, k, tbl, m, 0 /* Type.DOTTED */);
|
|
1467
|
+
if (!p && !skipping)
|
|
1468
|
+
validateTablePeek(ctx, p, tmp);
|
|
1469
|
+
skipVoid(ctx, true, true);
|
|
1470
|
+
let v = extractValue(ctx, void 0);
|
|
1471
|
+
if (p && !skipping)
|
|
1472
|
+
p[1][p[0]] = v;
|
|
1343
1473
|
}
|
|
1344
1474
|
skipVoid(ctx, true);
|
|
1345
|
-
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 0xa /* \n */ && tmp !== 0xd /* \r */) {
|
|
1346
|
-
|
|
1347
|
-
toml: toml,
|
|
1348
|
-
ptr: ctx.p,
|
|
1349
|
-
});
|
|
1475
|
+
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 0xa /* \n */ && (tmp !== 0xd /* \r */ || toml.charCodeAt(ctx.p + 1) !== 0xa /* \n */)) {
|
|
1476
|
+
TomlError.x('each key-value declaration must be followed by an end-of-line', ctx);
|
|
1350
1477
|
}
|
|
1351
1478
|
skipVoid(ctx);
|
|
1352
1479
|
}
|
|
@@ -1381,22 +1508,29 @@ function parse$4(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
|
1381
1508
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1382
1509
|
*/
|
|
1383
1510
|
let BARE_KEY = /^[a-z0-9-_]+$/i;
|
|
1511
|
+
let HAS_WELLFORMED = !!(''.isWellFormed);
|
|
1384
1512
|
function extendedTypeOf(obj) {
|
|
1385
1513
|
let type = typeof obj;
|
|
1386
1514
|
if (type === 'object') {
|
|
1387
1515
|
if (Array.isArray(obj))
|
|
1388
1516
|
return 'array';
|
|
1389
|
-
if (typeof obj
|
|
1517
|
+
if (typeof obj.getUTCDate === 'function' && obj instanceof Date)
|
|
1390
1518
|
return 'date';
|
|
1391
|
-
if (globalThis.Temporal
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
obj instanceof Temporal.
|
|
1396
|
-
|
|
1397
|
-
obj instanceof Temporal.PlainTime ||
|
|
1398
|
-
|
|
1399
|
-
|
|
1519
|
+
if (globalThis.Temporal) {
|
|
1520
|
+
if (obj.until) {
|
|
1521
|
+
if (obj instanceof Temporal.ZonedDateTime)
|
|
1522
|
+
return 'temporal/tz+uc';
|
|
1523
|
+
if (obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainDate)
|
|
1524
|
+
return 'temporal/uc';
|
|
1525
|
+
if (obj instanceof Temporal.PlainTime || obj instanceof Temporal.Instant)
|
|
1526
|
+
return 'temporal';
|
|
1527
|
+
if (obj instanceof Temporal.PlainYearMonth)
|
|
1528
|
+
return 'temporal/x';
|
|
1529
|
+
}
|
|
1530
|
+
else if ((obj.toPlainDate && obj instanceof Temporal.PlainMonthDay) ||
|
|
1531
|
+
(obj.negated && obj instanceof Temporal.Duration)) {
|
|
1532
|
+
return 'temporal/x';
|
|
1533
|
+
}
|
|
1400
1534
|
}
|
|
1401
1535
|
}
|
|
1402
1536
|
return type;
|
|
@@ -1408,16 +1542,20 @@ function isArrayOfTables(obj) {
|
|
|
1408
1542
|
}
|
|
1409
1543
|
return obj.length != 0;
|
|
1410
1544
|
}
|
|
1545
|
+
function formatWellFormedStringUnchecked(s) {
|
|
1546
|
+
return JSON.stringify(s).replaceAll('\x7f', '\\u007f');
|
|
1547
|
+
}
|
|
1411
1548
|
function formatString(s) {
|
|
1412
|
-
return
|
|
1549
|
+
return formatWellFormedStringUnchecked(HAS_WELLFORMED ? s.toWellFormed() : s);
|
|
1413
1550
|
}
|
|
1414
|
-
function
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1551
|
+
function formatKey(s) {
|
|
1552
|
+
if (BARE_KEY.test(s))
|
|
1553
|
+
return s;
|
|
1554
|
+
if (HAS_WELLFORMED && !s.isWellFormed())
|
|
1555
|
+
throw new RangeError('key contains illegal lone surrogates');
|
|
1556
|
+
return formatWellFormedStringUnchecked(s);
|
|
1419
1557
|
}
|
|
1420
|
-
function stringifyValue(val, type, depth, numberAsFloat) {
|
|
1558
|
+
function stringifyValue(val, type, depth, numberAsFloat, strictTemporal) {
|
|
1421
1559
|
if (depth === 0) {
|
|
1422
1560
|
throw new Error('Could not stringify the object: maximum object depth exceeded');
|
|
1423
1561
|
}
|
|
@@ -1434,6 +1572,7 @@ function stringifyValue(val, type, depth, numberAsFloat) {
|
|
|
1434
1572
|
return val.toFixed(1);
|
|
1435
1573
|
case 'bigint':
|
|
1436
1574
|
case 'boolean':
|
|
1575
|
+
case 'temporal':
|
|
1437
1576
|
return val.toString();
|
|
1438
1577
|
case 'string':
|
|
1439
1578
|
return formatString(val);
|
|
@@ -1442,14 +1581,42 @@ function stringifyValue(val, type, depth, numberAsFloat) {
|
|
|
1442
1581
|
throw new TypeError('cannot serialize invalid date');
|
|
1443
1582
|
return val.toISOString();
|
|
1444
1583
|
case 'object':
|
|
1445
|
-
return stringifyInlineTable(val, depth, numberAsFloat);
|
|
1584
|
+
return stringifyInlineTable(val, depth, numberAsFloat, strictTemporal);
|
|
1446
1585
|
case 'array':
|
|
1447
|
-
return stringifyArray(val, depth, numberAsFloat);
|
|
1448
|
-
case
|
|
1449
|
-
|
|
1586
|
+
return stringifyArray(val, depth, numberAsFloat, strictTemporal);
|
|
1587
|
+
// @ts-expect-error -- intentional fallthrough case
|
|
1588
|
+
case 'temporal/tz+uc':
|
|
1589
|
+
if (strictTemporal) {
|
|
1590
|
+
let tz = val.timeZoneId;
|
|
1591
|
+
let tzc = tz.charCodeAt(0);
|
|
1592
|
+
if (
|
|
1593
|
+
// Classic offset
|
|
1594
|
+
tzc !== 0x2b /* + */ && tzc !== 0x2d /* - */ &&
|
|
1595
|
+
(
|
|
1596
|
+
// Fast pre-check pass; see below for the actually accepted values
|
|
1597
|
+
(tzc !== 0x55 /* U */ && tzc !== 0x47 /* G */ && tzc !== 0x5a /* Z */ && tzc !== 0x45 /* E */) ||
|
|
1598
|
+
(
|
|
1599
|
+
// UTC and its aliases; Temporal implementations don't all canonicalise unfortunately
|
|
1600
|
+
tz !== 'UTC' && tz !== 'UCT' && tz !== 'Universal' && tz !== 'Zulu' &&
|
|
1601
|
+
// GMT is a TZ but it's for all intents and purposes equivalent to UTC. Safe to downgrade.
|
|
1602
|
+
!tz.startsWith('GMT') && tz !== 'Greenwich' &&
|
|
1603
|
+
// Etc/* are all safe to downgrade to offset (either UTC, GMT, or offset)
|
|
1604
|
+
!tz.startsWith('Etc/')))) {
|
|
1605
|
+
throw new TypeError('Temporal objects with an IANA timezone are not allowed in Temporal strict mode');
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
case 'temporal/uc':
|
|
1609
|
+
if (strictTemporal && val.calendarId !== 'iso8601')
|
|
1610
|
+
throw new TypeError('Temporal objects with a non-default calendar are not allowed in Temporal strict mode');
|
|
1611
|
+
return val.toString({
|
|
1612
|
+
calendarName: 'never',
|
|
1613
|
+
timeZoneName: 'never',
|
|
1614
|
+
});
|
|
1615
|
+
case 'temporal/x':
|
|
1616
|
+
throw new TypeError('Unsupported ' + val[Symbol.toStringTag]);
|
|
1450
1617
|
}
|
|
1451
1618
|
}
|
|
1452
|
-
function stringifyInlineTable(obj, depth, numberAsFloat) {
|
|
1619
|
+
function stringifyInlineTable(obj, depth, numberAsFloat, strictTemporal) {
|
|
1453
1620
|
let keys = Object.keys(obj);
|
|
1454
1621
|
if (keys.length === 0)
|
|
1455
1622
|
return '{}';
|
|
@@ -1458,13 +1625,11 @@ function stringifyInlineTable(obj, depth, numberAsFloat) {
|
|
|
1458
1625
|
let k = keys[i];
|
|
1459
1626
|
if (i)
|
|
1460
1627
|
res += ', ';
|
|
1461
|
-
res +=
|
|
1462
|
-
res += ' = ';
|
|
1463
|
-
res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
|
|
1628
|
+
res += formatKey(k) + ' = ' + stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat, strictTemporal);
|
|
1464
1629
|
}
|
|
1465
1630
|
return res + ' }';
|
|
1466
1631
|
}
|
|
1467
|
-
function stringifyArray(array, depth, numberAsFloat) {
|
|
1632
|
+
function stringifyArray(array, depth, numberAsFloat, strictTemporal) {
|
|
1468
1633
|
if (array.length === 0)
|
|
1469
1634
|
return '[]';
|
|
1470
1635
|
let res = '[ ';
|
|
@@ -1474,22 +1639,22 @@ function stringifyArray(array, depth, numberAsFloat) {
|
|
|
1474
1639
|
if (array[i] === null || array[i] === void 0) {
|
|
1475
1640
|
throw new TypeError('arrays cannot contain null or undefined values');
|
|
1476
1641
|
}
|
|
1477
|
-
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
|
|
1642
|
+
res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat, strictTemporal);
|
|
1478
1643
|
}
|
|
1479
1644
|
return res + ' ]';
|
|
1480
1645
|
}
|
|
1481
|
-
function stringifyArrayTable(array, key, depth, numberAsFloat) {
|
|
1646
|
+
function stringifyArrayTable(array, key, depth, numberAsFloat, strictTemporal) {
|
|
1482
1647
|
if (depth === 0) {
|
|
1483
1648
|
throw new Error('Could not stringify the object: maximum object depth exceeded');
|
|
1484
1649
|
}
|
|
1485
1650
|
let res = '';
|
|
1486
1651
|
for (let i = 0; i < array.length; i++) {
|
|
1487
1652
|
res += `${res && '\n'}[[${key}]]\n`;
|
|
1488
|
-
res += stringifyTable(0, array[i], key, depth, numberAsFloat);
|
|
1653
|
+
res += stringifyTable(0, array[i], key, depth, numberAsFloat, strictTemporal);
|
|
1489
1654
|
}
|
|
1490
1655
|
return res;
|
|
1491
1656
|
}
|
|
1492
|
-
function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
|
|
1657
|
+
function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat, strictTemporal) {
|
|
1493
1658
|
if (depth === 0) {
|
|
1494
1659
|
throw new Error('Could not stringify the object: maximum object depth exceeded');
|
|
1495
1660
|
}
|
|
@@ -1503,18 +1668,18 @@ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
|
|
|
1503
1668
|
if (type === 'symbol' || type === 'function') {
|
|
1504
1669
|
throw new TypeError(`cannot serialize values of type '${type}'`);
|
|
1505
1670
|
}
|
|
1506
|
-
let key =
|
|
1671
|
+
let key = formatKey(k);
|
|
1507
1672
|
if (type === 'array' && isArrayOfTables(obj[k])) {
|
|
1508
|
-
tables += (tables && '\n') + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
|
|
1673
|
+
tables += (tables && '\n') + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat, strictTemporal);
|
|
1509
1674
|
}
|
|
1510
1675
|
else if (type === 'object') {
|
|
1511
1676
|
let tblKey = prefix ? `${prefix}.${key}` : key;
|
|
1512
|
-
tables += (tables && '\n') + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat);
|
|
1677
|
+
tables += (tables && '\n') + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat, strictTemporal);
|
|
1513
1678
|
}
|
|
1514
1679
|
else {
|
|
1515
1680
|
preamble += key;
|
|
1516
1681
|
preamble += ' = ';
|
|
1517
|
-
preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
|
|
1682
|
+
preamble += stringifyValue(obj[k], type, depth, numberAsFloat, strictTemporal);
|
|
1518
1683
|
preamble += '\n';
|
|
1519
1684
|
}
|
|
1520
1685
|
}
|
|
@@ -1525,11 +1690,11 @@ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat) {
|
|
|
1525
1690
|
? `${preamble}\n${tables}`
|
|
1526
1691
|
: preamble || tables;
|
|
1527
1692
|
}
|
|
1528
|
-
function stringify$1(obj, { maxDepth = 1000, numbersAsFloat = false } = {}) {
|
|
1693
|
+
function stringify$1(obj, { maxDepth = 1000, numbersAsFloat = false, strictTemporal = false } = {}) {
|
|
1529
1694
|
if (extendedTypeOf(obj) !== 'object') {
|
|
1530
1695
|
throw new TypeError('stringify can only be called with an object');
|
|
1531
1696
|
}
|
|
1532
|
-
let str = stringifyTable(0, obj, '', maxDepth, numbersAsFloat);
|
|
1697
|
+
let str = stringifyTable(0, obj, '', maxDepth, numbersAsFloat, strictTemporal);
|
|
1533
1698
|
if (str[str.length - 1] !== '\n')
|
|
1534
1699
|
return str + '\n';
|
|
1535
1700
|
return str;
|
|
@@ -21231,6 +21396,30 @@ function locateRootValue(source) {
|
|
|
21231
21396
|
}
|
|
21232
21397
|
return null;
|
|
21233
21398
|
}
|
|
21399
|
+
/**
|
|
21400
|
+
* A parsed TOML value with every table rebuilt as a plain object, so a deep comparison is about the
|
|
21401
|
+
* values and not about which prototype a table carries. smol-toml >= 1.9 parses every table, the document
|
|
21402
|
+
* root included (and inline tables), to a null-prototype object, and `isDeepStrictEqual` treats a null
|
|
21403
|
+
* prototype as different from `Object.prototype`, while the spread `{ ...original, repos_root }` that
|
|
21404
|
+
* `editReposRoot` compares against is plain at its top level: on 1.9 every edit that reached the
|
|
21405
|
+
* comparison failed it, whatever the document held. An array maps each element; an object whose prototype
|
|
21406
|
+
* is `null` or `Object.prototype` becomes a fresh plain object with each value mapped the same way;
|
|
21407
|
+
* anything else (a string, number, boolean, `null`, a `Date` or smol-toml's `TomlDate`, an object of any
|
|
21408
|
+
* other class) is returned as it is. So the comparison ignores prototypes and compares everything else as
|
|
21409
|
+
* before, except that a rebuilt table keeps only its own enumerable string keys (a TOML document has no
|
|
21410
|
+
* others). The input is not mutated.
|
|
21411
|
+
*/
|
|
21412
|
+
function withPlainPrototypes(value) {
|
|
21413
|
+
if (Array.isArray(value))
|
|
21414
|
+
return value.map((element) => withPlainPrototypes(element));
|
|
21415
|
+
if (typeof value === "object" && value !== null) {
|
|
21416
|
+
const prototype = Object.getPrototypeOf(value);
|
|
21417
|
+
if (prototype === null || prototype === Object.prototype) {
|
|
21418
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, withPlainPrototypes(entry)]));
|
|
21419
|
+
}
|
|
21420
|
+
}
|
|
21421
|
+
return value;
|
|
21422
|
+
}
|
|
21234
21423
|
/**
|
|
21235
21424
|
* Edit only the top-level string `repos_root` assignment while preserving every unrelated byte.
|
|
21236
21425
|
* `missingValue` is the unoverlaid value a missing key means to `loadConfig`; when it already equals
|
|
@@ -21262,7 +21451,7 @@ function editReposRoot(source, next, missingValue, locateValue = locateRootValue
|
|
|
21262
21451
|
}
|
|
21263
21452
|
const reparsed = parseDocument$1(proposed);
|
|
21264
21453
|
const expected = { ...original, repos_root: next };
|
|
21265
|
-
if (!isDeepStrictEqual(reparsed, expected)) {
|
|
21454
|
+
if (!isDeepStrictEqual(withPlainPrototypes(reparsed), withPlainPrototypes(expected))) {
|
|
21266
21455
|
fail$1("proposed edit changed more than the requested value");
|
|
21267
21456
|
}
|
|
21268
21457
|
return proposed;
|
|
@@ -74285,8 +74474,8 @@ function parse(src, reviver, options) {
|
|
|
74285
74474
|
* tunnel, capability `agent.tunnel.lint`. The design decision (recorded in the registry): the lint runs
|
|
74286
74475
|
* as an agent verb, because the console is a container that cannot read the tunnel host's config (the
|
|
74287
74476
|
* issue's own finding) and has no Tooling clone (roshne, 2026-09-16, recorded at
|
|
74288
|
-
* `admin-cards.test.ts`); the console
|
|
74289
|
-
*
|
|
74477
|
+
* `admin-cards.test.ts`); the console asks each paired machine through `host.agent.call` (#416 PR 2,
|
|
74478
|
+
* `plugins/admin/src/tunnel-audit.ts`).
|
|
74290
74479
|
*
|
|
74291
74480
|
* The verb takes NO request input: which file is read and which script is run come only from
|
|
74292
74481
|
* `agent.toml` / the `AC_AGENT_TUNNEL_*` env (`config.ts`), set by the machine's own operator. Two
|