@optionfactory/fml 9.0.0-rc3 → 9.0.0-rc30
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 +16 -88
- package/dist/client-errors.iife.js +40 -49
- package/dist/client-errors.iife.js.map +1 -1
- package/dist/client-errors.iife.min.js +1 -1
- package/dist/client-errors.iife.min.js.map +1 -1
- package/dist/custom-elements.json +483 -50
- package/dist/fml.css +25 -20
- package/dist/fml.css.map +1 -1
- package/dist/fml.iife.js +5688 -2542
- package/dist/fml.iife.js.map +1 -1
- package/dist/fml.iife.min.js +1 -1
- package/dist/fml.iife.min.js.map +1 -1
- package/dist/ftl.d.mts +398 -227
- package/dist/ftl.iife.js +682 -1016
- package/dist/ftl.iife.js.map +1 -1
- package/dist/ftl.iife.min.js +1 -1
- package/dist/ftl.iife.min.js.map +1 -1
- package/dist/ftl.min.mjs +1 -1
- package/dist/ftl.min.mjs.map +1 -1
- package/dist/ftl.mjs +682 -1016
- package/dist/ftl.mjs.map +1 -1
- package/dist/ful.css +25 -20
- package/dist/ful.css.map +1 -1
- package/dist/ful.d.mts +3043 -546
- package/dist/ful.iife.js +4875 -1387
- package/dist/ful.iife.js.map +1 -1
- package/dist/ful.iife.min.js +1 -1
- package/dist/ful.iife.min.js.map +1 -1
- package/dist/ful.min.mjs +1 -1
- package/dist/ful.min.mjs.map +1 -1
- package/dist/ful.mjs +4873 -1389
- package/dist/ful.mjs.map +1 -1
- package/dist/httpc.d.mts +143 -123
- package/dist/httpc.iife.js +163 -175
- package/dist/httpc.iife.js.map +1 -1
- package/dist/httpc.iife.min.js +1 -1
- package/dist/httpc.iife.min.js.map +1 -1
- package/dist/httpc.min.mjs +1 -1
- package/dist/httpc.min.mjs.map +1 -1
- package/dist/httpc.mjs +163 -175
- package/dist/httpc.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +234 -38
- package/dist/web-types.json +489 -50
- package/package.json +2 -2
package/dist/ftl.mjs
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A Map bounded by entry count, evicting
|
|
3
|
-
*
|
|
4
|
-
* expressions, compiled masks, formatter instances) from growing forever. The
|
|
5
|
-
* capacity is sized so eviction never happens on a sane page: hitting it means
|
|
6
|
-
* dynamically generated keys, where FIFO's worst case (evicting a hot entry)
|
|
7
|
-
* costs one recomputation.
|
|
2
|
+
* A Map bounded by entry count, evicting the oldest entry when full. A hit does
|
|
3
|
+
* not refresh an entry: eviction follows insertion order, not use.
|
|
8
4
|
*/
|
|
9
5
|
class BoundedCache {
|
|
10
6
|
#max;
|
|
@@ -33,6 +29,7 @@ class BoundedCache {
|
|
|
33
29
|
this.#entries.set(key, value);
|
|
34
30
|
return value;
|
|
35
31
|
}
|
|
32
|
+
/** @returns {number} the number of entries held */
|
|
36
33
|
get size() {
|
|
37
34
|
return this.#entries.size;
|
|
38
35
|
}
|
|
@@ -71,14 +68,10 @@ const nodes = {
|
|
|
71
68
|
},
|
|
72
69
|
};
|
|
73
70
|
|
|
74
|
-
// @generated by Peggy 5.1.
|
|
71
|
+
// @generated by Peggy 5.1.1.
|
|
75
72
|
//
|
|
76
73
|
// https://peggyjs.org/
|
|
77
74
|
|
|
78
|
-
//keyword classification lives here, not in the grammar's ordered choice: the
|
|
79
|
-
//identifier rule consumes the whole word and the action decides, so no keyword
|
|
80
|
-
//can grab a longer identifier's prefix. A Map, not a plain object: `in` on the
|
|
81
|
-
//latter would classify inherited names such as `constructor` as keywords
|
|
82
75
|
const keywords = new Map([
|
|
83
76
|
['true', true],
|
|
84
77
|
['false', false],
|
|
@@ -141,10 +134,9 @@ class peg$SyntaxError extends SyntaxError {
|
|
|
141
134
|
return s;
|
|
142
135
|
}
|
|
143
136
|
|
|
144
|
-
function
|
|
137
|
+
function escape(s, special) {
|
|
145
138
|
return unicodeEscape(s
|
|
146
|
-
.replace(
|
|
147
|
-
.replace(/"/g, "\\\"")
|
|
139
|
+
.replace(special, "\\$&")
|
|
148
140
|
.replace(/\0/g, "\\0")
|
|
149
141
|
.replace(/\t/g, "\\t")
|
|
150
142
|
.replace(/\n/g, "\\n")
|
|
@@ -153,18 +145,12 @@ class peg$SyntaxError extends SyntaxError {
|
|
|
153
145
|
.replace(/[\x10-\x1F\x7F-\x9F]/g, ch => "\\x" + hex(ch)));
|
|
154
146
|
}
|
|
155
147
|
|
|
148
|
+
function literalEscape(s) {
|
|
149
|
+
return escape(s, /[\\"]/g);
|
|
150
|
+
}
|
|
151
|
+
|
|
156
152
|
function classEscape(s) {
|
|
157
|
-
return
|
|
158
|
-
.replace(/\\/g, "\\\\")
|
|
159
|
-
.replace(/\]/g, "\\]")
|
|
160
|
-
.replace(/\^/g, "\\^")
|
|
161
|
-
.replace(/-/g, "\\-")
|
|
162
|
-
.replace(/\0/g, "\\0")
|
|
163
|
-
.replace(/\t/g, "\\t")
|
|
164
|
-
.replace(/\n/g, "\\n")
|
|
165
|
-
.replace(/\r/g, "\\r")
|
|
166
|
-
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
|
167
|
-
.replace(/[\x10-\x1F\x7F-\x9F]/g, ch => "\\x" + hex(ch)));
|
|
153
|
+
return escape(s, /[\\\]^-]/g);
|
|
168
154
|
}
|
|
169
155
|
|
|
170
156
|
const DESCRIBE_EXPECTATION_FNS = {
|
|
@@ -282,14 +268,6 @@ function peg$parse(input, options) {
|
|
|
282
268
|
const peg$c53 = "<=";
|
|
283
269
|
const peg$c54 = "<";
|
|
284
270
|
|
|
285
|
-
const peg$r0 = /^[^\\{]/;
|
|
286
|
-
const peg$r1 = /^[0-9]/;
|
|
287
|
-
const peg$r2 = /^[^']/;
|
|
288
|
-
const peg$r3 = /^[^"]/;
|
|
289
|
-
const peg$r4 = /^[^\\`{]/;
|
|
290
|
-
const peg$r5 = /^[a-zA-Z$_]/;
|
|
291
|
-
const peg$r6 = /^[a-zA-Z$_0-9]/;
|
|
292
|
-
const peg$r7 = /^[ \t\n\r]/;
|
|
293
271
|
|
|
294
272
|
const peg$e0 = peg$literalExpectation("{{{{", false);
|
|
295
273
|
const peg$e1 = peg$literalExpectation("}}}}", false);
|
|
@@ -447,9 +425,10 @@ function peg$parse(input, options) {
|
|
|
447
425
|
let peg$maxFailExpected = options.peg$maxFailExpected || [];
|
|
448
426
|
let peg$silentFails = options.peg$silentFails | 0;
|
|
449
427
|
|
|
450
|
-
let peg$resultsCache =
|
|
428
|
+
let peg$resultsCache = new Map();
|
|
451
429
|
|
|
452
430
|
let peg$result;
|
|
431
|
+
let peg$charCode;
|
|
453
432
|
|
|
454
433
|
if (options.startRule) {
|
|
455
434
|
if (!(options.startRule in peg$startRuleFunctions)) {
|
|
@@ -568,7 +547,7 @@ function peg$parse(input, options) {
|
|
|
568
547
|
let s0, s1;
|
|
569
548
|
|
|
570
549
|
const key = peg$currPos * 38 + 0;
|
|
571
|
-
const cached = peg$resultsCache
|
|
550
|
+
const cached = peg$resultsCache.get(key);
|
|
572
551
|
|
|
573
552
|
if (cached) {
|
|
574
553
|
peg$currPos = cached.nextPos;
|
|
@@ -577,13 +556,13 @@ function peg$parse(input, options) {
|
|
|
577
556
|
}
|
|
578
557
|
|
|
579
558
|
s0 = [];
|
|
580
|
-
|
|
581
|
-
while (s1 !== peg$FAILED) {
|
|
582
|
-
s0.push(s1);
|
|
559
|
+
for (;;) {
|
|
583
560
|
s1 = peg$parseTemplatedExpression();
|
|
561
|
+
if (s1 === peg$FAILED) { break; }
|
|
562
|
+
s0.push(s1);
|
|
584
563
|
}
|
|
585
564
|
|
|
586
|
-
peg$resultsCache
|
|
565
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
587
566
|
|
|
588
567
|
return s0;
|
|
589
568
|
}
|
|
@@ -592,7 +571,7 @@ function peg$parse(input, options) {
|
|
|
592
571
|
let s0, s1, s2, s3, s4;
|
|
593
572
|
|
|
594
573
|
const key = peg$currPos * 38 + 1;
|
|
595
|
-
const cached = peg$resultsCache
|
|
574
|
+
const cached = peg$resultsCache.get(key);
|
|
596
575
|
|
|
597
576
|
if (cached) {
|
|
598
577
|
peg$currPos = cached.nextPos;
|
|
@@ -688,7 +667,7 @@ function peg$parse(input, options) {
|
|
|
688
667
|
}
|
|
689
668
|
}
|
|
690
669
|
|
|
691
|
-
peg$resultsCache
|
|
670
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
692
671
|
|
|
693
672
|
return s0;
|
|
694
673
|
}
|
|
@@ -697,7 +676,7 @@ function peg$parse(input, options) {
|
|
|
697
676
|
let s0;
|
|
698
677
|
|
|
699
678
|
const key = peg$currPos * 38 + 2;
|
|
700
|
-
const cached = peg$resultsCache
|
|
679
|
+
const cached = peg$resultsCache.get(key);
|
|
701
680
|
|
|
702
681
|
if (cached) {
|
|
703
682
|
peg$currPos = cached.nextPos;
|
|
@@ -713,7 +692,7 @@ function peg$parse(input, options) {
|
|
|
713
692
|
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
|
714
693
|
}
|
|
715
694
|
|
|
716
|
-
peg$resultsCache
|
|
695
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
717
696
|
|
|
718
697
|
return s0;
|
|
719
698
|
}
|
|
@@ -722,7 +701,7 @@ function peg$parse(input, options) {
|
|
|
722
701
|
let s0;
|
|
723
702
|
|
|
724
703
|
const key = peg$currPos * 38 + 3;
|
|
725
|
-
const cached = peg$resultsCache
|
|
704
|
+
const cached = peg$resultsCache.get(key);
|
|
726
705
|
|
|
727
706
|
if (cached) {
|
|
728
707
|
peg$currPos = cached.nextPos;
|
|
@@ -738,7 +717,7 @@ function peg$parse(input, options) {
|
|
|
738
717
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
|
739
718
|
}
|
|
740
719
|
|
|
741
|
-
peg$resultsCache
|
|
720
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
742
721
|
|
|
743
722
|
return s0;
|
|
744
723
|
}
|
|
@@ -747,7 +726,7 @@ function peg$parse(input, options) {
|
|
|
747
726
|
let s0;
|
|
748
727
|
|
|
749
728
|
const key = peg$currPos * 38 + 4;
|
|
750
|
-
const cached = peg$resultsCache
|
|
729
|
+
const cached = peg$resultsCache.get(key);
|
|
751
730
|
|
|
752
731
|
if (cached) {
|
|
753
732
|
peg$currPos = cached.nextPos;
|
|
@@ -763,7 +742,7 @@ function peg$parse(input, options) {
|
|
|
763
742
|
if (peg$silentFails === 0) { peg$fail(peg$e2); }
|
|
764
743
|
}
|
|
765
744
|
|
|
766
|
-
peg$resultsCache
|
|
745
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
767
746
|
|
|
768
747
|
return s0;
|
|
769
748
|
}
|
|
@@ -772,7 +751,7 @@ function peg$parse(input, options) {
|
|
|
772
751
|
let s0;
|
|
773
752
|
|
|
774
753
|
const key = peg$currPos * 38 + 5;
|
|
775
|
-
const cached = peg$resultsCache
|
|
754
|
+
const cached = peg$resultsCache.get(key);
|
|
776
755
|
|
|
777
756
|
if (cached) {
|
|
778
757
|
peg$currPos = cached.nextPos;
|
|
@@ -788,7 +767,7 @@ function peg$parse(input, options) {
|
|
|
788
767
|
if (peg$silentFails === 0) { peg$fail(peg$e3); }
|
|
789
768
|
}
|
|
790
769
|
|
|
791
|
-
peg$resultsCache
|
|
770
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
792
771
|
|
|
793
772
|
return s0;
|
|
794
773
|
}
|
|
@@ -797,7 +776,7 @@ function peg$parse(input, options) {
|
|
|
797
776
|
let s0;
|
|
798
777
|
|
|
799
778
|
const key = peg$currPos * 38 + 6;
|
|
800
|
-
const cached = peg$resultsCache
|
|
779
|
+
const cached = peg$resultsCache.get(key);
|
|
801
780
|
|
|
802
781
|
if (cached) {
|
|
803
782
|
peg$currPos = cached.nextPos;
|
|
@@ -813,7 +792,7 @@ function peg$parse(input, options) {
|
|
|
813
792
|
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
|
814
793
|
}
|
|
815
794
|
|
|
816
|
-
peg$resultsCache
|
|
795
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
817
796
|
|
|
818
797
|
return s0;
|
|
819
798
|
}
|
|
@@ -822,7 +801,7 @@ function peg$parse(input, options) {
|
|
|
822
801
|
let s0;
|
|
823
802
|
|
|
824
803
|
const key = peg$currPos * 38 + 7;
|
|
825
|
-
const cached = peg$resultsCache
|
|
804
|
+
const cached = peg$resultsCache.get(key);
|
|
826
805
|
|
|
827
806
|
if (cached) {
|
|
828
807
|
peg$currPos = cached.nextPos;
|
|
@@ -838,7 +817,7 @@ function peg$parse(input, options) {
|
|
|
838
817
|
if (peg$silentFails === 0) { peg$fail(peg$e5); }
|
|
839
818
|
}
|
|
840
819
|
|
|
841
|
-
peg$resultsCache
|
|
820
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
842
821
|
|
|
843
822
|
return s0;
|
|
844
823
|
}
|
|
@@ -847,7 +826,7 @@ function peg$parse(input, options) {
|
|
|
847
826
|
let s0, s1, s2, s3, s4, s5, s6;
|
|
848
827
|
|
|
849
828
|
const key = peg$currPos * 38 + 8;
|
|
850
|
-
const cached = peg$resultsCache
|
|
829
|
+
const cached = peg$resultsCache.get(key);
|
|
851
830
|
|
|
852
831
|
if (cached) {
|
|
853
832
|
peg$currPos = cached.nextPos;
|
|
@@ -857,211 +836,104 @@ function peg$parse(input, options) {
|
|
|
857
836
|
|
|
858
837
|
s0 = peg$currPos;
|
|
859
838
|
s1 = [];
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
peg$currPos++;
|
|
865
|
-
} else {
|
|
866
|
-
s4 = peg$FAILED;
|
|
867
|
-
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
868
|
-
}
|
|
869
|
-
if (s4 !== peg$FAILED) {
|
|
870
|
-
while (s4 !== peg$FAILED) {
|
|
871
|
-
s3.push(s4);
|
|
839
|
+
for (;;) {
|
|
840
|
+
s2 = peg$currPos;
|
|
841
|
+
s3 = [];
|
|
842
|
+
for (;;) {
|
|
872
843
|
s4 = input.charAt(peg$currPos);
|
|
873
|
-
if (peg$
|
|
844
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 92 || peg$charCode === 123)) {
|
|
874
845
|
peg$currPos++;
|
|
875
846
|
} else {
|
|
876
847
|
s4 = peg$FAILED;
|
|
877
848
|
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
878
849
|
}
|
|
850
|
+
if (s4 === peg$FAILED) { break; }
|
|
851
|
+
s3.push(s4);
|
|
879
852
|
}
|
|
880
|
-
|
|
881
|
-
s3 = peg$FAILED;
|
|
882
|
-
}
|
|
883
|
-
if (s3 !== peg$FAILED) {
|
|
884
|
-
s2 = input.substring(s2, peg$currPos);
|
|
885
|
-
} else {
|
|
886
|
-
s2 = s3;
|
|
887
|
-
}
|
|
888
|
-
if (s2 === peg$FAILED) {
|
|
889
|
-
s2 = peg$currPos;
|
|
890
|
-
if (input.charCodeAt(peg$currPos) === 92) {
|
|
891
|
-
s3 = peg$c7;
|
|
892
|
-
peg$currPos++;
|
|
893
|
-
} else {
|
|
853
|
+
if (s3.length < 1) {
|
|
894
854
|
s3 = peg$FAILED;
|
|
895
|
-
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
896
855
|
}
|
|
897
856
|
if (s3 !== peg$FAILED) {
|
|
898
|
-
|
|
899
|
-
s4 = input.charAt(peg$currPos);
|
|
900
|
-
peg$currPos++;
|
|
901
|
-
} else {
|
|
902
|
-
s4 = peg$FAILED;
|
|
903
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
904
|
-
}
|
|
905
|
-
if (s4 !== peg$FAILED) {
|
|
906
|
-
s2 = peg$f4(s4);
|
|
907
|
-
} else {
|
|
908
|
-
peg$currPos = s2;
|
|
909
|
-
s2 = peg$FAILED;
|
|
910
|
-
}
|
|
857
|
+
s2 = input.substring(s2, peg$currPos);
|
|
911
858
|
} else {
|
|
912
|
-
|
|
913
|
-
s2 = peg$FAILED;
|
|
859
|
+
s2 = s3;
|
|
914
860
|
}
|
|
915
861
|
if (s2 === peg$FAILED) {
|
|
916
862
|
s2 = peg$currPos;
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
s4 = peg$c9;
|
|
863
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
864
|
+
s3 = peg$c7;
|
|
920
865
|
peg$currPos++;
|
|
921
866
|
} else {
|
|
922
|
-
|
|
923
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
867
|
+
s3 = peg$FAILED;
|
|
868
|
+
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
924
869
|
}
|
|
925
|
-
if (
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
if (input.charCodeAt(peg$currPos) === 123) {
|
|
929
|
-
s6 = peg$c9;
|
|
870
|
+
if (s3 !== peg$FAILED) {
|
|
871
|
+
if (input.length > peg$currPos) {
|
|
872
|
+
s4 = input.charAt(peg$currPos);
|
|
930
873
|
peg$currPos++;
|
|
931
874
|
} else {
|
|
932
|
-
|
|
933
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
934
|
-
}
|
|
935
|
-
peg$silentFails--;
|
|
936
|
-
if (s6 === peg$FAILED) {
|
|
937
|
-
s5 = undefined;
|
|
938
|
-
} else {
|
|
939
|
-
peg$currPos = s5;
|
|
940
|
-
s5 = peg$FAILED;
|
|
875
|
+
s4 = peg$FAILED;
|
|
876
|
+
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
941
877
|
}
|
|
942
|
-
if (
|
|
943
|
-
|
|
944
|
-
s3 = s4;
|
|
878
|
+
if (s4 !== peg$FAILED) {
|
|
879
|
+
s2 = peg$f4(s4);
|
|
945
880
|
} else {
|
|
946
|
-
peg$currPos =
|
|
947
|
-
|
|
948
|
-
}
|
|
949
|
-
} else {
|
|
950
|
-
peg$currPos = s3;
|
|
951
|
-
s3 = peg$FAILED;
|
|
952
|
-
}
|
|
953
|
-
if (s3 !== peg$FAILED) {
|
|
954
|
-
s2 = input.substring(s2, peg$currPos);
|
|
955
|
-
} else {
|
|
956
|
-
s2 = s3;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
if (s2 !== peg$FAILED) {
|
|
961
|
-
while (s2 !== peg$FAILED) {
|
|
962
|
-
s1.push(s2);
|
|
963
|
-
s2 = peg$currPos;
|
|
964
|
-
s3 = [];
|
|
965
|
-
s4 = input.charAt(peg$currPos);
|
|
966
|
-
if (peg$r0.test(s4)) {
|
|
967
|
-
peg$currPos++;
|
|
968
|
-
} else {
|
|
969
|
-
s4 = peg$FAILED;
|
|
970
|
-
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
971
|
-
}
|
|
972
|
-
if (s4 !== peg$FAILED) {
|
|
973
|
-
while (s4 !== peg$FAILED) {
|
|
974
|
-
s3.push(s4);
|
|
975
|
-
s4 = input.charAt(peg$currPos);
|
|
976
|
-
if (peg$r0.test(s4)) {
|
|
977
|
-
peg$currPos++;
|
|
978
|
-
} else {
|
|
979
|
-
s4 = peg$FAILED;
|
|
980
|
-
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
981
|
-
}
|
|
881
|
+
peg$currPos = s2;
|
|
882
|
+
s2 = peg$FAILED;
|
|
982
883
|
}
|
|
983
884
|
} else {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
if (s3 !== peg$FAILED) {
|
|
987
|
-
s2 = input.substring(s2, peg$currPos);
|
|
988
|
-
} else {
|
|
989
|
-
s2 = s3;
|
|
885
|
+
peg$currPos = s2;
|
|
886
|
+
s2 = peg$FAILED;
|
|
990
887
|
}
|
|
991
888
|
if (s2 === peg$FAILED) {
|
|
992
889
|
s2 = peg$currPos;
|
|
993
|
-
|
|
994
|
-
|
|
890
|
+
s3 = peg$currPos;
|
|
891
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
892
|
+
s4 = peg$c9;
|
|
995
893
|
peg$currPos++;
|
|
996
894
|
} else {
|
|
997
|
-
|
|
998
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
999
|
-
}
|
|
1000
|
-
if (s3 !== peg$FAILED) {
|
|
1001
|
-
if (input.length > peg$currPos) {
|
|
1002
|
-
s4 = input.charAt(peg$currPos);
|
|
1003
|
-
peg$currPos++;
|
|
1004
|
-
} else {
|
|
1005
|
-
s4 = peg$FAILED;
|
|
1006
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
1007
|
-
}
|
|
1008
|
-
if (s4 !== peg$FAILED) {
|
|
1009
|
-
s2 = peg$f4(s4);
|
|
1010
|
-
} else {
|
|
1011
|
-
peg$currPos = s2;
|
|
1012
|
-
s2 = peg$FAILED;
|
|
1013
|
-
}
|
|
1014
|
-
} else {
|
|
1015
|
-
peg$currPos = s2;
|
|
1016
|
-
s2 = peg$FAILED;
|
|
895
|
+
s4 = peg$FAILED;
|
|
896
|
+
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
1017
897
|
}
|
|
1018
|
-
if (
|
|
1019
|
-
|
|
1020
|
-
|
|
898
|
+
if (s4 !== peg$FAILED) {
|
|
899
|
+
s5 = peg$currPos;
|
|
900
|
+
peg$silentFails++;
|
|
1021
901
|
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1022
|
-
|
|
902
|
+
s6 = peg$c9;
|
|
1023
903
|
peg$currPos++;
|
|
1024
904
|
} else {
|
|
1025
|
-
|
|
905
|
+
s6 = peg$FAILED;
|
|
1026
906
|
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
1027
907
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1032
|
-
s6 = peg$c9;
|
|
1033
|
-
peg$currPos++;
|
|
1034
|
-
} else {
|
|
1035
|
-
s6 = peg$FAILED;
|
|
1036
|
-
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
1037
|
-
}
|
|
1038
|
-
peg$silentFails--;
|
|
1039
|
-
if (s6 === peg$FAILED) {
|
|
1040
|
-
s5 = undefined;
|
|
1041
|
-
} else {
|
|
1042
|
-
peg$currPos = s5;
|
|
1043
|
-
s5 = peg$FAILED;
|
|
1044
|
-
}
|
|
1045
|
-
if (s5 !== peg$FAILED) {
|
|
1046
|
-
s4 = [s4, s5];
|
|
1047
|
-
s3 = s4;
|
|
1048
|
-
} else {
|
|
1049
|
-
peg$currPos = s3;
|
|
1050
|
-
s3 = peg$FAILED;
|
|
1051
|
-
}
|
|
908
|
+
peg$silentFails--;
|
|
909
|
+
if (s6 === peg$FAILED) {
|
|
910
|
+
s5 = undefined;
|
|
1052
911
|
} else {
|
|
1053
|
-
peg$currPos =
|
|
1054
|
-
|
|
912
|
+
peg$currPos = s5;
|
|
913
|
+
s5 = peg$FAILED;
|
|
1055
914
|
}
|
|
1056
|
-
if (
|
|
1057
|
-
|
|
915
|
+
if (s5 !== peg$FAILED) {
|
|
916
|
+
s4 = [s4, s5];
|
|
917
|
+
s3 = s4;
|
|
1058
918
|
} else {
|
|
1059
|
-
|
|
919
|
+
peg$currPos = s3;
|
|
920
|
+
s3 = peg$FAILED;
|
|
1060
921
|
}
|
|
922
|
+
} else {
|
|
923
|
+
peg$currPos = s3;
|
|
924
|
+
s3 = peg$FAILED;
|
|
925
|
+
}
|
|
926
|
+
if (s3 !== peg$FAILED) {
|
|
927
|
+
s2 = input.substring(s2, peg$currPos);
|
|
928
|
+
} else {
|
|
929
|
+
s2 = s3;
|
|
1061
930
|
}
|
|
1062
931
|
}
|
|
1063
932
|
}
|
|
1064
|
-
|
|
933
|
+
if (s2 === peg$FAILED) { break; }
|
|
934
|
+
s1.push(s2);
|
|
935
|
+
}
|
|
936
|
+
if (s1.length < 1) {
|
|
1065
937
|
s1 = peg$FAILED;
|
|
1066
938
|
}
|
|
1067
939
|
if (s1 !== peg$FAILED) {
|
|
@@ -1069,7 +941,7 @@ function peg$parse(input, options) {
|
|
|
1069
941
|
}
|
|
1070
942
|
s0 = s1;
|
|
1071
943
|
|
|
1072
|
-
peg$resultsCache
|
|
944
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1073
945
|
|
|
1074
946
|
return s0;
|
|
1075
947
|
}
|
|
@@ -1078,7 +950,7 @@ function peg$parse(input, options) {
|
|
|
1078
950
|
let s0, s2;
|
|
1079
951
|
|
|
1080
952
|
const key = peg$currPos * 38 + 9;
|
|
1081
|
-
const cached = peg$resultsCache
|
|
953
|
+
const cached = peg$resultsCache.get(key);
|
|
1082
954
|
|
|
1083
955
|
if (cached) {
|
|
1084
956
|
peg$currPos = cached.nextPos;
|
|
@@ -1097,7 +969,7 @@ function peg$parse(input, options) {
|
|
|
1097
969
|
s0 = peg$FAILED;
|
|
1098
970
|
}
|
|
1099
971
|
|
|
1100
|
-
peg$resultsCache
|
|
972
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1101
973
|
|
|
1102
974
|
return s0;
|
|
1103
975
|
}
|
|
@@ -1106,7 +978,7 @@ function peg$parse(input, options) {
|
|
|
1106
978
|
let s0, s1, s3, s5, s7, s9;
|
|
1107
979
|
|
|
1108
980
|
const key = peg$currPos * 38 + 10;
|
|
1109
|
-
const cached = peg$resultsCache
|
|
981
|
+
const cached = peg$resultsCache.get(key);
|
|
1110
982
|
|
|
1111
983
|
if (cached) {
|
|
1112
984
|
peg$currPos = cached.nextPos;
|
|
@@ -1166,7 +1038,7 @@ function peg$parse(input, options) {
|
|
|
1166
1038
|
s0 = peg$parseElvisExpression();
|
|
1167
1039
|
}
|
|
1168
1040
|
|
|
1169
|
-
peg$resultsCache
|
|
1041
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1170
1042
|
|
|
1171
1043
|
return s0;
|
|
1172
1044
|
}
|
|
@@ -1175,7 +1047,7 @@ function peg$parse(input, options) {
|
|
|
1175
1047
|
let s0, s1, s3, s5;
|
|
1176
1048
|
|
|
1177
1049
|
const key = peg$currPos * 38 + 11;
|
|
1178
|
-
const cached = peg$resultsCache
|
|
1050
|
+
const cached = peg$resultsCache.get(key);
|
|
1179
1051
|
|
|
1180
1052
|
if (cached) {
|
|
1181
1053
|
peg$currPos = cached.nextPos;
|
|
@@ -1215,7 +1087,7 @@ function peg$parse(input, options) {
|
|
|
1215
1087
|
s0 = peg$parseNullCoalescingExpression();
|
|
1216
1088
|
}
|
|
1217
1089
|
|
|
1218
|
-
peg$resultsCache
|
|
1090
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1219
1091
|
|
|
1220
1092
|
return s0;
|
|
1221
1093
|
}
|
|
@@ -1224,7 +1096,7 @@ function peg$parse(input, options) {
|
|
|
1224
1096
|
let s0, s1, s3, s5;
|
|
1225
1097
|
|
|
1226
1098
|
const key = peg$currPos * 38 + 12;
|
|
1227
|
-
const cached = peg$resultsCache
|
|
1099
|
+
const cached = peg$resultsCache.get(key);
|
|
1228
1100
|
|
|
1229
1101
|
if (cached) {
|
|
1230
1102
|
peg$currPos = cached.nextPos;
|
|
@@ -1264,7 +1136,7 @@ function peg$parse(input, options) {
|
|
|
1264
1136
|
s0 = peg$parseOrExpression();
|
|
1265
1137
|
}
|
|
1266
1138
|
|
|
1267
|
-
peg$resultsCache
|
|
1139
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1268
1140
|
|
|
1269
1141
|
return s0;
|
|
1270
1142
|
}
|
|
@@ -1273,7 +1145,7 @@ function peg$parse(input, options) {
|
|
|
1273
1145
|
let s0, s1, s2, s3, s5, s7;
|
|
1274
1146
|
|
|
1275
1147
|
const key = peg$currPos * 38 + 13;
|
|
1276
|
-
const cached = peg$resultsCache
|
|
1148
|
+
const cached = peg$resultsCache.get(key);
|
|
1277
1149
|
|
|
1278
1150
|
if (cached) {
|
|
1279
1151
|
peg$currPos = cached.nextPos;
|
|
@@ -1285,30 +1157,7 @@ function peg$parse(input, options) {
|
|
|
1285
1157
|
s1 = peg$parseAndExpression();
|
|
1286
1158
|
if (s1 !== peg$FAILED) {
|
|
1287
1159
|
s2 = [];
|
|
1288
|
-
|
|
1289
|
-
peg$parse_();
|
|
1290
|
-
if (input.substr(peg$currPos, 2) === peg$c22) {
|
|
1291
|
-
s5 = peg$c22;
|
|
1292
|
-
peg$currPos += 2;
|
|
1293
|
-
} else {
|
|
1294
|
-
s5 = peg$FAILED;
|
|
1295
|
-
if (peg$silentFails === 0) { peg$fail(peg$e14); }
|
|
1296
|
-
}
|
|
1297
|
-
if (s5 !== peg$FAILED) {
|
|
1298
|
-
peg$parse_();
|
|
1299
|
-
s7 = peg$parseAndExpression();
|
|
1300
|
-
if (s7 !== peg$FAILED) {
|
|
1301
|
-
s3 = s7;
|
|
1302
|
-
} else {
|
|
1303
|
-
peg$currPos = s3;
|
|
1304
|
-
s3 = peg$FAILED;
|
|
1305
|
-
}
|
|
1306
|
-
} else {
|
|
1307
|
-
peg$currPos = s3;
|
|
1308
|
-
s3 = peg$FAILED;
|
|
1309
|
-
}
|
|
1310
|
-
while (s3 !== peg$FAILED) {
|
|
1311
|
-
s2.push(s3);
|
|
1160
|
+
for (;;) {
|
|
1312
1161
|
s3 = peg$currPos;
|
|
1313
1162
|
peg$parse_();
|
|
1314
1163
|
if (input.substr(peg$currPos, 2) === peg$c22) {
|
|
@@ -1331,6 +1180,8 @@ function peg$parse(input, options) {
|
|
|
1331
1180
|
peg$currPos = s3;
|
|
1332
1181
|
s3 = peg$FAILED;
|
|
1333
1182
|
}
|
|
1183
|
+
if (s3 === peg$FAILED) { break; }
|
|
1184
|
+
s2.push(s3);
|
|
1334
1185
|
}
|
|
1335
1186
|
s0 = peg$f10(s1, s2);
|
|
1336
1187
|
} else {
|
|
@@ -1338,7 +1189,7 @@ function peg$parse(input, options) {
|
|
|
1338
1189
|
s0 = peg$FAILED;
|
|
1339
1190
|
}
|
|
1340
1191
|
|
|
1341
|
-
peg$resultsCache
|
|
1192
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1342
1193
|
|
|
1343
1194
|
return s0;
|
|
1344
1195
|
}
|
|
@@ -1347,7 +1198,7 @@ function peg$parse(input, options) {
|
|
|
1347
1198
|
let s0, s1, s2, s3, s5, s7;
|
|
1348
1199
|
|
|
1349
1200
|
const key = peg$currPos * 38 + 14;
|
|
1350
|
-
const cached = peg$resultsCache
|
|
1201
|
+
const cached = peg$resultsCache.get(key);
|
|
1351
1202
|
|
|
1352
1203
|
if (cached) {
|
|
1353
1204
|
peg$currPos = cached.nextPos;
|
|
@@ -1359,30 +1210,7 @@ function peg$parse(input, options) {
|
|
|
1359
1210
|
s1 = peg$parseEqExpression();
|
|
1360
1211
|
if (s1 !== peg$FAILED) {
|
|
1361
1212
|
s2 = [];
|
|
1362
|
-
|
|
1363
|
-
peg$parse_();
|
|
1364
|
-
if (input.substr(peg$currPos, 2) === peg$c24) {
|
|
1365
|
-
s5 = peg$c24;
|
|
1366
|
-
peg$currPos += 2;
|
|
1367
|
-
} else {
|
|
1368
|
-
s5 = peg$FAILED;
|
|
1369
|
-
if (peg$silentFails === 0) { peg$fail(peg$e15); }
|
|
1370
|
-
}
|
|
1371
|
-
if (s5 !== peg$FAILED) {
|
|
1372
|
-
peg$parse_();
|
|
1373
|
-
s7 = peg$parseEqExpression();
|
|
1374
|
-
if (s7 !== peg$FAILED) {
|
|
1375
|
-
s3 = s7;
|
|
1376
|
-
} else {
|
|
1377
|
-
peg$currPos = s3;
|
|
1378
|
-
s3 = peg$FAILED;
|
|
1379
|
-
}
|
|
1380
|
-
} else {
|
|
1381
|
-
peg$currPos = s3;
|
|
1382
|
-
s3 = peg$FAILED;
|
|
1383
|
-
}
|
|
1384
|
-
while (s3 !== peg$FAILED) {
|
|
1385
|
-
s2.push(s3);
|
|
1213
|
+
for (;;) {
|
|
1386
1214
|
s3 = peg$currPos;
|
|
1387
1215
|
peg$parse_();
|
|
1388
1216
|
if (input.substr(peg$currPos, 2) === peg$c24) {
|
|
@@ -1405,6 +1233,8 @@ function peg$parse(input, options) {
|
|
|
1405
1233
|
peg$currPos = s3;
|
|
1406
1234
|
s3 = peg$FAILED;
|
|
1407
1235
|
}
|
|
1236
|
+
if (s3 === peg$FAILED) { break; }
|
|
1237
|
+
s2.push(s3);
|
|
1408
1238
|
}
|
|
1409
1239
|
s0 = peg$f11(s1, s2);
|
|
1410
1240
|
} else {
|
|
@@ -1412,7 +1242,7 @@ function peg$parse(input, options) {
|
|
|
1412
1242
|
s0 = peg$FAILED;
|
|
1413
1243
|
}
|
|
1414
1244
|
|
|
1415
|
-
peg$resultsCache
|
|
1245
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1416
1246
|
|
|
1417
1247
|
return s0;
|
|
1418
1248
|
}
|
|
@@ -1421,7 +1251,7 @@ function peg$parse(input, options) {
|
|
|
1421
1251
|
let s0, s1, s2, s3, s5, s7;
|
|
1422
1252
|
|
|
1423
1253
|
const key = peg$currPos * 38 + 15;
|
|
1424
|
-
const cached = peg$resultsCache
|
|
1254
|
+
const cached = peg$resultsCache.get(key);
|
|
1425
1255
|
|
|
1426
1256
|
if (cached) {
|
|
1427
1257
|
peg$currPos = cached.nextPos;
|
|
@@ -1433,24 +1263,7 @@ function peg$parse(input, options) {
|
|
|
1433
1263
|
s1 = peg$parseRelExpression();
|
|
1434
1264
|
if (s1 !== peg$FAILED) {
|
|
1435
1265
|
s2 = [];
|
|
1436
|
-
|
|
1437
|
-
peg$parse_();
|
|
1438
|
-
s5 = peg$parseEqualityOp();
|
|
1439
|
-
if (s5 !== peg$FAILED) {
|
|
1440
|
-
peg$parse_();
|
|
1441
|
-
s7 = peg$parseRelExpression();
|
|
1442
|
-
if (s7 !== peg$FAILED) {
|
|
1443
|
-
s3 = peg$f12(s1, s5, s7);
|
|
1444
|
-
} else {
|
|
1445
|
-
peg$currPos = s3;
|
|
1446
|
-
s3 = peg$FAILED;
|
|
1447
|
-
}
|
|
1448
|
-
} else {
|
|
1449
|
-
peg$currPos = s3;
|
|
1450
|
-
s3 = peg$FAILED;
|
|
1451
|
-
}
|
|
1452
|
-
while (s3 !== peg$FAILED) {
|
|
1453
|
-
s2.push(s3);
|
|
1266
|
+
for (;;) {
|
|
1454
1267
|
s3 = peg$currPos;
|
|
1455
1268
|
peg$parse_();
|
|
1456
1269
|
s5 = peg$parseEqualityOp();
|
|
@@ -1467,6 +1280,8 @@ function peg$parse(input, options) {
|
|
|
1467
1280
|
peg$currPos = s3;
|
|
1468
1281
|
s3 = peg$FAILED;
|
|
1469
1282
|
}
|
|
1283
|
+
if (s3 === peg$FAILED) { break; }
|
|
1284
|
+
s2.push(s3);
|
|
1470
1285
|
}
|
|
1471
1286
|
s0 = peg$f13(s1, s2);
|
|
1472
1287
|
} else {
|
|
@@ -1474,7 +1289,7 @@ function peg$parse(input, options) {
|
|
|
1474
1289
|
s0 = peg$FAILED;
|
|
1475
1290
|
}
|
|
1476
1291
|
|
|
1477
|
-
peg$resultsCache
|
|
1292
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1478
1293
|
|
|
1479
1294
|
return s0;
|
|
1480
1295
|
}
|
|
@@ -1483,7 +1298,7 @@ function peg$parse(input, options) {
|
|
|
1483
1298
|
let s0, s1, s2, s3, s5, s7;
|
|
1484
1299
|
|
|
1485
1300
|
const key = peg$currPos * 38 + 16;
|
|
1486
|
-
const cached = peg$resultsCache
|
|
1301
|
+
const cached = peg$resultsCache.get(key);
|
|
1487
1302
|
|
|
1488
1303
|
if (cached) {
|
|
1489
1304
|
peg$currPos = cached.nextPos;
|
|
@@ -1495,24 +1310,7 @@ function peg$parse(input, options) {
|
|
|
1495
1310
|
s1 = peg$parseNotExpression();
|
|
1496
1311
|
if (s1 !== peg$FAILED) {
|
|
1497
1312
|
s2 = [];
|
|
1498
|
-
|
|
1499
|
-
peg$parse_();
|
|
1500
|
-
s5 = peg$parseRelationalOp();
|
|
1501
|
-
if (s5 !== peg$FAILED) {
|
|
1502
|
-
peg$parse_();
|
|
1503
|
-
s7 = peg$parseNotExpression();
|
|
1504
|
-
if (s7 !== peg$FAILED) {
|
|
1505
|
-
s3 = peg$f14(s1, s5, s7);
|
|
1506
|
-
} else {
|
|
1507
|
-
peg$currPos = s3;
|
|
1508
|
-
s3 = peg$FAILED;
|
|
1509
|
-
}
|
|
1510
|
-
} else {
|
|
1511
|
-
peg$currPos = s3;
|
|
1512
|
-
s3 = peg$FAILED;
|
|
1513
|
-
}
|
|
1514
|
-
while (s3 !== peg$FAILED) {
|
|
1515
|
-
s2.push(s3);
|
|
1313
|
+
for (;;) {
|
|
1516
1314
|
s3 = peg$currPos;
|
|
1517
1315
|
peg$parse_();
|
|
1518
1316
|
s5 = peg$parseRelationalOp();
|
|
@@ -1529,6 +1327,8 @@ function peg$parse(input, options) {
|
|
|
1529
1327
|
peg$currPos = s3;
|
|
1530
1328
|
s3 = peg$FAILED;
|
|
1531
1329
|
}
|
|
1330
|
+
if (s3 === peg$FAILED) { break; }
|
|
1331
|
+
s2.push(s3);
|
|
1532
1332
|
}
|
|
1533
1333
|
s0 = peg$f15(s1, s2);
|
|
1534
1334
|
} else {
|
|
@@ -1536,7 +1336,7 @@ function peg$parse(input, options) {
|
|
|
1536
1336
|
s0 = peg$FAILED;
|
|
1537
1337
|
}
|
|
1538
1338
|
|
|
1539
|
-
peg$resultsCache
|
|
1339
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1540
1340
|
|
|
1541
1341
|
return s0;
|
|
1542
1342
|
}
|
|
@@ -1545,7 +1345,7 @@ function peg$parse(input, options) {
|
|
|
1545
1345
|
let s0, s1, s3;
|
|
1546
1346
|
|
|
1547
1347
|
const key = peg$currPos * 38 + 17;
|
|
1548
|
-
const cached = peg$resultsCache
|
|
1348
|
+
const cached = peg$resultsCache.get(key);
|
|
1549
1349
|
|
|
1550
1350
|
if (cached) {
|
|
1551
1351
|
peg$currPos = cached.nextPos;
|
|
@@ -1578,7 +1378,7 @@ function peg$parse(input, options) {
|
|
|
1578
1378
|
s0 = peg$parseAccess();
|
|
1579
1379
|
}
|
|
1580
1380
|
|
|
1581
|
-
peg$resultsCache
|
|
1381
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1582
1382
|
|
|
1583
1383
|
return s0;
|
|
1584
1384
|
}
|
|
@@ -1587,7 +1387,7 @@ function peg$parse(input, options) {
|
|
|
1587
1387
|
let s0, s1, s3, s4, s5;
|
|
1588
1388
|
|
|
1589
1389
|
const key = peg$currPos * 38 + 18;
|
|
1590
|
-
const cached = peg$resultsCache
|
|
1390
|
+
const cached = peg$resultsCache.get(key);
|
|
1591
1391
|
|
|
1592
1392
|
if (cached) {
|
|
1593
1393
|
peg$currPos = cached.nextPos;
|
|
@@ -1600,29 +1400,20 @@ function peg$parse(input, options) {
|
|
|
1600
1400
|
if (s1 !== peg$FAILED) {
|
|
1601
1401
|
peg$parse_();
|
|
1602
1402
|
s3 = [];
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
peg$
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
if (s4 !== peg$FAILED) {
|
|
1613
|
-
while (s4 !== peg$FAILED) {
|
|
1614
|
-
s3.push(s4);
|
|
1615
|
-
s4 = peg$currPos;
|
|
1616
|
-
s5 = peg$parseAccessExpression();
|
|
1617
|
-
if (s5 !== peg$FAILED) {
|
|
1618
|
-
peg$parse_();
|
|
1619
|
-
s4 = s5;
|
|
1620
|
-
} else {
|
|
1621
|
-
peg$currPos = s4;
|
|
1622
|
-
s4 = peg$FAILED;
|
|
1623
|
-
}
|
|
1403
|
+
for (;;) {
|
|
1404
|
+
s4 = peg$currPos;
|
|
1405
|
+
s5 = peg$parseAccessExpression();
|
|
1406
|
+
if (s5 !== peg$FAILED) {
|
|
1407
|
+
peg$parse_();
|
|
1408
|
+
s4 = s5;
|
|
1409
|
+
} else {
|
|
1410
|
+
peg$currPos = s4;
|
|
1411
|
+
s4 = peg$FAILED;
|
|
1624
1412
|
}
|
|
1625
|
-
|
|
1413
|
+
if (s4 === peg$FAILED) { break; }
|
|
1414
|
+
s3.push(s4);
|
|
1415
|
+
}
|
|
1416
|
+
if (s3.length < 1) {
|
|
1626
1417
|
s3 = peg$FAILED;
|
|
1627
1418
|
}
|
|
1628
1419
|
if (s3 !== peg$FAILED) {
|
|
@@ -1639,7 +1430,7 @@ function peg$parse(input, options) {
|
|
|
1639
1430
|
s0 = peg$parseGroupingExpression();
|
|
1640
1431
|
}
|
|
1641
1432
|
|
|
1642
|
-
peg$resultsCache
|
|
1433
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1643
1434
|
|
|
1644
1435
|
return s0;
|
|
1645
1436
|
}
|
|
@@ -1648,7 +1439,7 @@ function peg$parse(input, options) {
|
|
|
1648
1439
|
let s0;
|
|
1649
1440
|
|
|
1650
1441
|
const key = peg$currPos * 38 + 19;
|
|
1651
|
-
const cached = peg$resultsCache
|
|
1442
|
+
const cached = peg$resultsCache.get(key);
|
|
1652
1443
|
|
|
1653
1444
|
if (cached) {
|
|
1654
1445
|
peg$currPos = cached.nextPos;
|
|
@@ -1664,7 +1455,7 @@ function peg$parse(input, options) {
|
|
|
1664
1455
|
}
|
|
1665
1456
|
}
|
|
1666
1457
|
|
|
1667
|
-
peg$resultsCache
|
|
1458
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1668
1459
|
|
|
1669
1460
|
return s0;
|
|
1670
1461
|
}
|
|
@@ -1673,7 +1464,7 @@ function peg$parse(input, options) {
|
|
|
1673
1464
|
let s0, s1, s3;
|
|
1674
1465
|
|
|
1675
1466
|
const key = peg$currPos * 38 + 20;
|
|
1676
|
-
const cached = peg$resultsCache
|
|
1467
|
+
const cached = peg$resultsCache.get(key);
|
|
1677
1468
|
|
|
1678
1469
|
if (cached) {
|
|
1679
1470
|
peg$currPos = cached.nextPos;
|
|
@@ -1718,7 +1509,7 @@ function peg$parse(input, options) {
|
|
|
1718
1509
|
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
|
1719
1510
|
}
|
|
1720
1511
|
|
|
1721
|
-
peg$resultsCache
|
|
1512
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1722
1513
|
|
|
1723
1514
|
return s0;
|
|
1724
1515
|
}
|
|
@@ -1727,7 +1518,7 @@ function peg$parse(input, options) {
|
|
|
1727
1518
|
let s0, s1, s2, s4, s6;
|
|
1728
1519
|
|
|
1729
1520
|
const key = peg$currPos * 38 + 21;
|
|
1730
|
-
const cached = peg$resultsCache
|
|
1521
|
+
const cached = peg$resultsCache.get(key);
|
|
1731
1522
|
|
|
1732
1523
|
if (cached) {
|
|
1733
1524
|
peg$currPos = cached.nextPos;
|
|
@@ -1786,7 +1577,7 @@ function peg$parse(input, options) {
|
|
|
1786
1577
|
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
|
1787
1578
|
}
|
|
1788
1579
|
|
|
1789
|
-
peg$resultsCache
|
|
1580
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1790
1581
|
|
|
1791
1582
|
return s0;
|
|
1792
1583
|
}
|
|
@@ -1795,7 +1586,7 @@ function peg$parse(input, options) {
|
|
|
1795
1586
|
let s0, s1, s2, s4, s5, s6, s7, s9;
|
|
1796
1587
|
|
|
1797
1588
|
const key = peg$currPos * 38 + 22;
|
|
1798
|
-
const cached = peg$resultsCache
|
|
1589
|
+
const cached = peg$resultsCache.get(key);
|
|
1799
1590
|
|
|
1800
1591
|
if (cached) {
|
|
1801
1592
|
peg$currPos = cached.nextPos;
|
|
@@ -1837,30 +1628,7 @@ function peg$parse(input, options) {
|
|
|
1837
1628
|
s4 = null;
|
|
1838
1629
|
}
|
|
1839
1630
|
s5 = [];
|
|
1840
|
-
|
|
1841
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
1842
|
-
s7 = peg$c34;
|
|
1843
|
-
peg$currPos++;
|
|
1844
|
-
} else {
|
|
1845
|
-
s7 = peg$FAILED;
|
|
1846
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
1847
|
-
}
|
|
1848
|
-
if (s7 !== peg$FAILED) {
|
|
1849
|
-
peg$parse_();
|
|
1850
|
-
s9 = peg$parseTernaryExpression();
|
|
1851
|
-
if (s9 !== peg$FAILED) {
|
|
1852
|
-
peg$parse_();
|
|
1853
|
-
s6 = s9;
|
|
1854
|
-
} else {
|
|
1855
|
-
peg$currPos = s6;
|
|
1856
|
-
s6 = peg$FAILED;
|
|
1857
|
-
}
|
|
1858
|
-
} else {
|
|
1859
|
-
peg$currPos = s6;
|
|
1860
|
-
s6 = peg$FAILED;
|
|
1861
|
-
}
|
|
1862
|
-
while (s6 !== peg$FAILED) {
|
|
1863
|
-
s5.push(s6);
|
|
1631
|
+
for (;;) {
|
|
1864
1632
|
s6 = peg$currPos;
|
|
1865
1633
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
1866
1634
|
s7 = peg$c34;
|
|
@@ -1883,6 +1651,8 @@ function peg$parse(input, options) {
|
|
|
1883
1651
|
peg$currPos = s6;
|
|
1884
1652
|
s6 = peg$FAILED;
|
|
1885
1653
|
}
|
|
1654
|
+
if (s6 === peg$FAILED) { break; }
|
|
1655
|
+
s5.push(s6);
|
|
1886
1656
|
}
|
|
1887
1657
|
if (input.charCodeAt(peg$currPos) === 41) {
|
|
1888
1658
|
s6 = peg$c36;
|
|
@@ -1907,7 +1677,7 @@ function peg$parse(input, options) {
|
|
|
1907
1677
|
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
|
1908
1678
|
}
|
|
1909
1679
|
|
|
1910
|
-
peg$resultsCache
|
|
1680
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1911
1681
|
|
|
1912
1682
|
return s0;
|
|
1913
1683
|
}
|
|
@@ -1916,7 +1686,7 @@ function peg$parse(input, options) {
|
|
|
1916
1686
|
let s0, s1, s3, s5;
|
|
1917
1687
|
|
|
1918
1688
|
const key = peg$currPos * 38 + 23;
|
|
1919
|
-
const cached = peg$resultsCache
|
|
1689
|
+
const cached = peg$resultsCache.get(key);
|
|
1920
1690
|
|
|
1921
1691
|
if (cached) {
|
|
1922
1692
|
peg$currPos = cached.nextPos;
|
|
@@ -1968,7 +1738,7 @@ function peg$parse(input, options) {
|
|
|
1968
1738
|
}
|
|
1969
1739
|
}
|
|
1970
1740
|
|
|
1971
|
-
peg$resultsCache
|
|
1741
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1972
1742
|
|
|
1973
1743
|
return s0;
|
|
1974
1744
|
}
|
|
@@ -1977,7 +1747,7 @@ function peg$parse(input, options) {
|
|
|
1977
1747
|
let s0, s1, s2, s4, s5, s6, s7, s9;
|
|
1978
1748
|
|
|
1979
1749
|
const key = peg$currPos * 38 + 24;
|
|
1980
|
-
const cached = peg$resultsCache
|
|
1750
|
+
const cached = peg$resultsCache.get(key);
|
|
1981
1751
|
|
|
1982
1752
|
if (cached) {
|
|
1983
1753
|
peg$currPos = cached.nextPos;
|
|
@@ -2011,30 +1781,7 @@ function peg$parse(input, options) {
|
|
|
2011
1781
|
s4 = null;
|
|
2012
1782
|
}
|
|
2013
1783
|
s5 = [];
|
|
2014
|
-
|
|
2015
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2016
|
-
s7 = peg$c34;
|
|
2017
|
-
peg$currPos++;
|
|
2018
|
-
} else {
|
|
2019
|
-
s7 = peg$FAILED;
|
|
2020
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
2021
|
-
}
|
|
2022
|
-
if (s7 !== peg$FAILED) {
|
|
2023
|
-
peg$parse_();
|
|
2024
|
-
s9 = peg$parseTernaryExpression();
|
|
2025
|
-
if (s9 !== peg$FAILED) {
|
|
2026
|
-
peg$parse_();
|
|
2027
|
-
s6 = s9;
|
|
2028
|
-
} else {
|
|
2029
|
-
peg$currPos = s6;
|
|
2030
|
-
s6 = peg$FAILED;
|
|
2031
|
-
}
|
|
2032
|
-
} else {
|
|
2033
|
-
peg$currPos = s6;
|
|
2034
|
-
s6 = peg$FAILED;
|
|
2035
|
-
}
|
|
2036
|
-
while (s6 !== peg$FAILED) {
|
|
2037
|
-
s5.push(s6);
|
|
1784
|
+
for (;;) {
|
|
2038
1785
|
s6 = peg$currPos;
|
|
2039
1786
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2040
1787
|
s7 = peg$c34;
|
|
@@ -2057,6 +1804,8 @@ function peg$parse(input, options) {
|
|
|
2057
1804
|
peg$currPos = s6;
|
|
2058
1805
|
s6 = peg$FAILED;
|
|
2059
1806
|
}
|
|
1807
|
+
if (s6 === peg$FAILED) { break; }
|
|
1808
|
+
s5.push(s6);
|
|
2060
1809
|
}
|
|
2061
1810
|
if (input.charCodeAt(peg$currPos) === 41) {
|
|
2062
1811
|
s6 = peg$c36;
|
|
@@ -2085,7 +1834,7 @@ function peg$parse(input, options) {
|
|
|
2085
1834
|
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
|
2086
1835
|
}
|
|
2087
1836
|
|
|
2088
|
-
peg$resultsCache
|
|
1837
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2089
1838
|
|
|
2090
1839
|
return s0;
|
|
2091
1840
|
}
|
|
@@ -2094,7 +1843,7 @@ function peg$parse(input, options) {
|
|
|
2094
1843
|
let s0;
|
|
2095
1844
|
|
|
2096
1845
|
const key = peg$currPos * 38 + 25;
|
|
2097
|
-
const cached = peg$resultsCache
|
|
1846
|
+
const cached = peg$resultsCache.get(key);
|
|
2098
1847
|
|
|
2099
1848
|
if (cached) {
|
|
2100
1849
|
peg$currPos = cached.nextPos;
|
|
@@ -2113,7 +1862,7 @@ function peg$parse(input, options) {
|
|
|
2113
1862
|
}
|
|
2114
1863
|
}
|
|
2115
1864
|
|
|
2116
|
-
peg$resultsCache
|
|
1865
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2117
1866
|
|
|
2118
1867
|
return s0;
|
|
2119
1868
|
}
|
|
@@ -2122,7 +1871,7 @@ function peg$parse(input, options) {
|
|
|
2122
1871
|
let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
|
|
2123
1872
|
|
|
2124
1873
|
const key = peg$currPos * 38 + 26;
|
|
2125
|
-
const cached = peg$resultsCache
|
|
1874
|
+
const cached = peg$resultsCache.get(key);
|
|
2126
1875
|
|
|
2127
1876
|
if (cached) {
|
|
2128
1877
|
peg$currPos = cached.nextPos;
|
|
@@ -2146,25 +1895,18 @@ function peg$parse(input, options) {
|
|
|
2146
1895
|
}
|
|
2147
1896
|
s4 = peg$currPos;
|
|
2148
1897
|
s5 = [];
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
peg$
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
if (s6 !== peg$FAILED) {
|
|
2157
|
-
while (s6 !== peg$FAILED) {
|
|
2158
|
-
s5.push(s6);
|
|
2159
|
-
s6 = input.charAt(peg$currPos);
|
|
2160
|
-
if (peg$r1.test(s6)) {
|
|
2161
|
-
peg$currPos++;
|
|
2162
|
-
} else {
|
|
2163
|
-
s6 = peg$FAILED;
|
|
2164
|
-
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2165
|
-
}
|
|
1898
|
+
for (;;) {
|
|
1899
|
+
s6 = input.charAt(peg$currPos);
|
|
1900
|
+
if ((peg$charCode = s6.charCodeAt(0), (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
1901
|
+
peg$currPos++;
|
|
1902
|
+
} else {
|
|
1903
|
+
s6 = peg$FAILED;
|
|
1904
|
+
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2166
1905
|
}
|
|
2167
|
-
|
|
1906
|
+
if (s6 === peg$FAILED) { break; }
|
|
1907
|
+
s5.push(s6);
|
|
1908
|
+
}
|
|
1909
|
+
if (s5.length < 1) {
|
|
2168
1910
|
s5 = peg$FAILED;
|
|
2169
1911
|
}
|
|
2170
1912
|
if (s5 !== peg$FAILED) {
|
|
@@ -2178,22 +1920,16 @@ function peg$parse(input, options) {
|
|
|
2178
1920
|
}
|
|
2179
1921
|
if (s7 !== peg$FAILED) {
|
|
2180
1922
|
s8 = [];
|
|
2181
|
-
|
|
2182
|
-
if (peg$r1.test(s9)) {
|
|
2183
|
-
peg$currPos++;
|
|
2184
|
-
} else {
|
|
2185
|
-
s9 = peg$FAILED;
|
|
2186
|
-
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2187
|
-
}
|
|
2188
|
-
while (s9 !== peg$FAILED) {
|
|
2189
|
-
s8.push(s9);
|
|
1923
|
+
for (;;) {
|
|
2190
1924
|
s9 = input.charAt(peg$currPos);
|
|
2191
|
-
if (peg$
|
|
1925
|
+
if ((peg$charCode = s9.charCodeAt(0), (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
2192
1926
|
peg$currPos++;
|
|
2193
1927
|
} else {
|
|
2194
1928
|
s9 = peg$FAILED;
|
|
2195
1929
|
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2196
1930
|
}
|
|
1931
|
+
if (s9 === peg$FAILED) { break; }
|
|
1932
|
+
s8.push(s9);
|
|
2197
1933
|
}
|
|
2198
1934
|
s7 = [s7, s8];
|
|
2199
1935
|
s6 = s7;
|
|
@@ -2221,25 +1957,18 @@ function peg$parse(input, options) {
|
|
|
2221
1957
|
}
|
|
2222
1958
|
if (s5 !== peg$FAILED) {
|
|
2223
1959
|
s6 = [];
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
peg$
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
if (s7 !== peg$FAILED) {
|
|
2232
|
-
while (s7 !== peg$FAILED) {
|
|
2233
|
-
s6.push(s7);
|
|
2234
|
-
s7 = input.charAt(peg$currPos);
|
|
2235
|
-
if (peg$r1.test(s7)) {
|
|
2236
|
-
peg$currPos++;
|
|
2237
|
-
} else {
|
|
2238
|
-
s7 = peg$FAILED;
|
|
2239
|
-
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2240
|
-
}
|
|
1960
|
+
for (;;) {
|
|
1961
|
+
s7 = input.charAt(peg$currPos);
|
|
1962
|
+
if ((peg$charCode = s7.charCodeAt(0), (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
1963
|
+
peg$currPos++;
|
|
1964
|
+
} else {
|
|
1965
|
+
s7 = peg$FAILED;
|
|
1966
|
+
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2241
1967
|
}
|
|
2242
|
-
|
|
1968
|
+
if (s7 === peg$FAILED) { break; }
|
|
1969
|
+
s6.push(s7);
|
|
1970
|
+
}
|
|
1971
|
+
if (s6.length < 1) {
|
|
2243
1972
|
s6 = peg$FAILED;
|
|
2244
1973
|
}
|
|
2245
1974
|
if (s6 !== peg$FAILED) {
|
|
@@ -2276,7 +2005,7 @@ function peg$parse(input, options) {
|
|
|
2276
2005
|
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
|
2277
2006
|
}
|
|
2278
2007
|
|
|
2279
|
-
peg$resultsCache
|
|
2008
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2280
2009
|
|
|
2281
2010
|
return s0;
|
|
2282
2011
|
}
|
|
@@ -2285,7 +2014,7 @@ function peg$parse(input, options) {
|
|
|
2285
2014
|
let s0, s1, s2, s3, s4;
|
|
2286
2015
|
|
|
2287
2016
|
const key = peg$currPos * 38 + 27;
|
|
2288
|
-
const cached = peg$resultsCache
|
|
2017
|
+
const cached = peg$resultsCache.get(key);
|
|
2289
2018
|
|
|
2290
2019
|
if (cached) {
|
|
2291
2020
|
peg$currPos = cached.nextPos;
|
|
@@ -2305,22 +2034,16 @@ function peg$parse(input, options) {
|
|
|
2305
2034
|
if (s1 !== peg$FAILED) {
|
|
2306
2035
|
s2 = peg$currPos;
|
|
2307
2036
|
s3 = [];
|
|
2308
|
-
|
|
2309
|
-
if (peg$r2.test(s4)) {
|
|
2310
|
-
peg$currPos++;
|
|
2311
|
-
} else {
|
|
2312
|
-
s4 = peg$FAILED;
|
|
2313
|
-
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
|
2314
|
-
}
|
|
2315
|
-
while (s4 !== peg$FAILED) {
|
|
2316
|
-
s3.push(s4);
|
|
2037
|
+
for (;;) {
|
|
2317
2038
|
s4 = input.charAt(peg$currPos);
|
|
2318
|
-
if (peg$
|
|
2039
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 39)) {
|
|
2319
2040
|
peg$currPos++;
|
|
2320
2041
|
} else {
|
|
2321
2042
|
s4 = peg$FAILED;
|
|
2322
2043
|
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
|
2323
2044
|
}
|
|
2045
|
+
if (s4 === peg$FAILED) { break; }
|
|
2046
|
+
s3.push(s4);
|
|
2324
2047
|
}
|
|
2325
2048
|
s2 = input.substring(s2, peg$currPos);
|
|
2326
2049
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
@@ -2352,22 +2075,16 @@ function peg$parse(input, options) {
|
|
|
2352
2075
|
if (s1 !== peg$FAILED) {
|
|
2353
2076
|
s2 = peg$currPos;
|
|
2354
2077
|
s3 = [];
|
|
2355
|
-
|
|
2356
|
-
if (peg$r3.test(s4)) {
|
|
2357
|
-
peg$currPos++;
|
|
2358
|
-
} else {
|
|
2359
|
-
s4 = peg$FAILED;
|
|
2360
|
-
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
2361
|
-
}
|
|
2362
|
-
while (s4 !== peg$FAILED) {
|
|
2363
|
-
s3.push(s4);
|
|
2078
|
+
for (;;) {
|
|
2364
2079
|
s4 = input.charAt(peg$currPos);
|
|
2365
|
-
if (peg$
|
|
2080
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 34)) {
|
|
2366
2081
|
peg$currPos++;
|
|
2367
2082
|
} else {
|
|
2368
2083
|
s4 = peg$FAILED;
|
|
2369
2084
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
2370
2085
|
}
|
|
2086
|
+
if (s4 === peg$FAILED) { break; }
|
|
2087
|
+
s3.push(s4);
|
|
2371
2088
|
}
|
|
2372
2089
|
s2 = input.substring(s2, peg$currPos);
|
|
2373
2090
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
@@ -2398,16 +2115,13 @@ function peg$parse(input, options) {
|
|
|
2398
2115
|
}
|
|
2399
2116
|
if (s1 !== peg$FAILED) {
|
|
2400
2117
|
s2 = [];
|
|
2401
|
-
|
|
2402
|
-
if (s3 === peg$FAILED) {
|
|
2403
|
-
s3 = peg$parseTemplateStringLiteral();
|
|
2404
|
-
}
|
|
2405
|
-
while (s3 !== peg$FAILED) {
|
|
2406
|
-
s2.push(s3);
|
|
2118
|
+
for (;;) {
|
|
2407
2119
|
s3 = peg$parseTemplateStringExpression();
|
|
2408
2120
|
if (s3 === peg$FAILED) {
|
|
2409
2121
|
s3 = peg$parseTemplateStringLiteral();
|
|
2410
2122
|
}
|
|
2123
|
+
if (s3 === peg$FAILED) { break; }
|
|
2124
|
+
s2.push(s3);
|
|
2411
2125
|
}
|
|
2412
2126
|
if (input.charCodeAt(peg$currPos) === 96) {
|
|
2413
2127
|
s3 = peg$c42;
|
|
@@ -2434,7 +2148,7 @@ function peg$parse(input, options) {
|
|
|
2434
2148
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
2435
2149
|
}
|
|
2436
2150
|
|
|
2437
|
-
peg$resultsCache
|
|
2151
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2438
2152
|
|
|
2439
2153
|
return s0;
|
|
2440
2154
|
}
|
|
@@ -2443,7 +2157,7 @@ function peg$parse(input, options) {
|
|
|
2443
2157
|
let s0, s1, s3, s5;
|
|
2444
2158
|
|
|
2445
2159
|
const key = peg$currPos * 38 + 28;
|
|
2446
|
-
const cached = peg$resultsCache
|
|
2160
|
+
const cached = peg$resultsCache.get(key);
|
|
2447
2161
|
|
|
2448
2162
|
if (cached) {
|
|
2449
2163
|
peg$currPos = cached.nextPos;
|
|
@@ -2492,7 +2206,7 @@ function peg$parse(input, options) {
|
|
|
2492
2206
|
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
|
2493
2207
|
}
|
|
2494
2208
|
|
|
2495
|
-
peg$resultsCache
|
|
2209
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2496
2210
|
|
|
2497
2211
|
return s0;
|
|
2498
2212
|
}
|
|
@@ -2501,7 +2215,7 @@ function peg$parse(input, options) {
|
|
|
2501
2215
|
let s0, s1, s2, s3, s4;
|
|
2502
2216
|
|
|
2503
2217
|
const key = peg$currPos * 38 + 29;
|
|
2504
|
-
const cached = peg$resultsCache
|
|
2218
|
+
const cached = peg$resultsCache.get(key);
|
|
2505
2219
|
|
|
2506
2220
|
if (cached) {
|
|
2507
2221
|
peg$currPos = cached.nextPos;
|
|
@@ -2512,123 +2226,60 @@ function peg$parse(input, options) {
|
|
|
2512
2226
|
peg$silentFails++;
|
|
2513
2227
|
s0 = peg$currPos;
|
|
2514
2228
|
s1 = [];
|
|
2515
|
-
|
|
2516
|
-
s3 = [];
|
|
2517
|
-
s4 = input.charAt(peg$currPos);
|
|
2518
|
-
if (peg$r4.test(s4)) {
|
|
2519
|
-
peg$currPos++;
|
|
2520
|
-
} else {
|
|
2521
|
-
s4 = peg$FAILED;
|
|
2522
|
-
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2523
|
-
}
|
|
2524
|
-
if (s4 !== peg$FAILED) {
|
|
2525
|
-
while (s4 !== peg$FAILED) {
|
|
2526
|
-
s3.push(s4);
|
|
2527
|
-
s4 = input.charAt(peg$currPos);
|
|
2528
|
-
if (peg$r4.test(s4)) {
|
|
2529
|
-
peg$currPos++;
|
|
2530
|
-
} else {
|
|
2531
|
-
s4 = peg$FAILED;
|
|
2532
|
-
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2533
|
-
}
|
|
2534
|
-
}
|
|
2535
|
-
} else {
|
|
2536
|
-
s3 = peg$FAILED;
|
|
2537
|
-
}
|
|
2538
|
-
if (s3 !== peg$FAILED) {
|
|
2539
|
-
s2 = input.substring(s2, peg$currPos);
|
|
2540
|
-
} else {
|
|
2541
|
-
s2 = s3;
|
|
2542
|
-
}
|
|
2543
|
-
if (s2 === peg$FAILED) {
|
|
2229
|
+
for (;;) {
|
|
2544
2230
|
s2 = peg$currPos;
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
peg$currPos
|
|
2548
|
-
|
|
2549
|
-
s3 = peg$FAILED;
|
|
2550
|
-
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
2551
|
-
}
|
|
2552
|
-
if (s3 !== peg$FAILED) {
|
|
2553
|
-
if (input.length > peg$currPos) {
|
|
2554
|
-
s4 = input.charAt(peg$currPos);
|
|
2231
|
+
s3 = [];
|
|
2232
|
+
for (;;) {
|
|
2233
|
+
s4 = input.charAt(peg$currPos);
|
|
2234
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 92 || peg$charCode === 96 || peg$charCode === 123)) {
|
|
2555
2235
|
peg$currPos++;
|
|
2556
2236
|
} else {
|
|
2557
2237
|
s4 = peg$FAILED;
|
|
2558
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
2559
|
-
}
|
|
2560
|
-
if (s4 !== peg$FAILED) {
|
|
2561
|
-
s2 = peg$f28(s4);
|
|
2562
|
-
} else {
|
|
2563
|
-
peg$currPos = s2;
|
|
2564
|
-
s2 = peg$FAILED;
|
|
2238
|
+
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2565
2239
|
}
|
|
2240
|
+
if (s4 === peg$FAILED) { break; }
|
|
2241
|
+
s3.push(s4);
|
|
2242
|
+
}
|
|
2243
|
+
if (s3.length < 1) {
|
|
2244
|
+
s3 = peg$FAILED;
|
|
2245
|
+
}
|
|
2246
|
+
if (s3 !== peg$FAILED) {
|
|
2247
|
+
s2 = input.substring(s2, peg$currPos);
|
|
2566
2248
|
} else {
|
|
2567
|
-
|
|
2568
|
-
s2 = peg$FAILED;
|
|
2249
|
+
s2 = s3;
|
|
2569
2250
|
}
|
|
2570
|
-
|
|
2571
|
-
if (s2 !== peg$FAILED) {
|
|
2572
|
-
while (s2 !== peg$FAILED) {
|
|
2573
|
-
s1.push(s2);
|
|
2251
|
+
if (s2 === peg$FAILED) {
|
|
2574
2252
|
s2 = peg$currPos;
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
if (peg$r4.test(s4)) {
|
|
2253
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2254
|
+
s3 = peg$c7;
|
|
2578
2255
|
peg$currPos++;
|
|
2579
|
-
} else {
|
|
2580
|
-
s4 = peg$FAILED;
|
|
2581
|
-
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2582
|
-
}
|
|
2583
|
-
if (s4 !== peg$FAILED) {
|
|
2584
|
-
while (s4 !== peg$FAILED) {
|
|
2585
|
-
s3.push(s4);
|
|
2586
|
-
s4 = input.charAt(peg$currPos);
|
|
2587
|
-
if (peg$r4.test(s4)) {
|
|
2588
|
-
peg$currPos++;
|
|
2589
|
-
} else {
|
|
2590
|
-
s4 = peg$FAILED;
|
|
2591
|
-
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
2256
|
} else {
|
|
2595
2257
|
s3 = peg$FAILED;
|
|
2258
|
+
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
2596
2259
|
}
|
|
2597
2260
|
if (s3 !== peg$FAILED) {
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
s2 = s3;
|
|
2601
|
-
}
|
|
2602
|
-
if (s2 === peg$FAILED) {
|
|
2603
|
-
s2 = peg$currPos;
|
|
2604
|
-
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2605
|
-
s3 = peg$c7;
|
|
2261
|
+
if (input.length > peg$currPos) {
|
|
2262
|
+
s4 = input.charAt(peg$currPos);
|
|
2606
2263
|
peg$currPos++;
|
|
2607
2264
|
} else {
|
|
2608
|
-
|
|
2609
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
2265
|
+
s4 = peg$FAILED;
|
|
2266
|
+
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
2610
2267
|
}
|
|
2611
|
-
if (
|
|
2612
|
-
|
|
2613
|
-
s4 = input.charAt(peg$currPos);
|
|
2614
|
-
peg$currPos++;
|
|
2615
|
-
} else {
|
|
2616
|
-
s4 = peg$FAILED;
|
|
2617
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
2618
|
-
}
|
|
2619
|
-
if (s4 !== peg$FAILED) {
|
|
2620
|
-
s2 = peg$f28(s4);
|
|
2621
|
-
} else {
|
|
2622
|
-
peg$currPos = s2;
|
|
2623
|
-
s2 = peg$FAILED;
|
|
2624
|
-
}
|
|
2268
|
+
if (s4 !== peg$FAILED) {
|
|
2269
|
+
s2 = peg$f28(s4);
|
|
2625
2270
|
} else {
|
|
2626
2271
|
peg$currPos = s2;
|
|
2627
2272
|
s2 = peg$FAILED;
|
|
2628
2273
|
}
|
|
2274
|
+
} else {
|
|
2275
|
+
peg$currPos = s2;
|
|
2276
|
+
s2 = peg$FAILED;
|
|
2629
2277
|
}
|
|
2630
2278
|
}
|
|
2631
|
-
|
|
2279
|
+
if (s2 === peg$FAILED) { break; }
|
|
2280
|
+
s1.push(s2);
|
|
2281
|
+
}
|
|
2282
|
+
if (s1.length < 1) {
|
|
2632
2283
|
s1 = peg$FAILED;
|
|
2633
2284
|
}
|
|
2634
2285
|
if (s1 !== peg$FAILED) {
|
|
@@ -2655,7 +2306,7 @@ function peg$parse(input, options) {
|
|
|
2655
2306
|
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
|
2656
2307
|
}
|
|
2657
2308
|
|
|
2658
|
-
peg$resultsCache
|
|
2309
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2659
2310
|
|
|
2660
2311
|
return s0;
|
|
2661
2312
|
}
|
|
@@ -2664,7 +2315,7 @@ function peg$parse(input, options) {
|
|
|
2664
2315
|
let s0, s1, s3, s5, s6, s7, s9;
|
|
2665
2316
|
|
|
2666
2317
|
const key = peg$currPos * 38 + 30;
|
|
2667
|
-
const cached = peg$resultsCache
|
|
2318
|
+
const cached = peg$resultsCache.get(key);
|
|
2668
2319
|
|
|
2669
2320
|
if (cached) {
|
|
2670
2321
|
peg$currPos = cached.nextPos;
|
|
@@ -2689,30 +2340,7 @@ function peg$parse(input, options) {
|
|
|
2689
2340
|
}
|
|
2690
2341
|
peg$parse_();
|
|
2691
2342
|
s5 = [];
|
|
2692
|
-
|
|
2693
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2694
|
-
s7 = peg$c34;
|
|
2695
|
-
peg$currPos++;
|
|
2696
|
-
} else {
|
|
2697
|
-
s7 = peg$FAILED;
|
|
2698
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
2699
|
-
}
|
|
2700
|
-
if (s7 !== peg$FAILED) {
|
|
2701
|
-
peg$parse_();
|
|
2702
|
-
s9 = peg$parseTernaryExpression();
|
|
2703
|
-
if (s9 !== peg$FAILED) {
|
|
2704
|
-
peg$parse_();
|
|
2705
|
-
s6 = s9;
|
|
2706
|
-
} else {
|
|
2707
|
-
peg$currPos = s6;
|
|
2708
|
-
s6 = peg$FAILED;
|
|
2709
|
-
}
|
|
2710
|
-
} else {
|
|
2711
|
-
peg$currPos = s6;
|
|
2712
|
-
s6 = peg$FAILED;
|
|
2713
|
-
}
|
|
2714
|
-
while (s6 !== peg$FAILED) {
|
|
2715
|
-
s5.push(s6);
|
|
2343
|
+
for (;;) {
|
|
2716
2344
|
s6 = peg$currPos;
|
|
2717
2345
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2718
2346
|
s7 = peg$c34;
|
|
@@ -2735,6 +2363,8 @@ function peg$parse(input, options) {
|
|
|
2735
2363
|
peg$currPos = s6;
|
|
2736
2364
|
s6 = peg$FAILED;
|
|
2737
2365
|
}
|
|
2366
|
+
if (s6 === peg$FAILED) { break; }
|
|
2367
|
+
s5.push(s6);
|
|
2738
2368
|
}
|
|
2739
2369
|
if (input.charCodeAt(peg$currPos) === 93) {
|
|
2740
2370
|
s6 = peg$c31;
|
|
@@ -2759,7 +2389,7 @@ function peg$parse(input, options) {
|
|
|
2759
2389
|
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
|
2760
2390
|
}
|
|
2761
2391
|
|
|
2762
|
-
peg$resultsCache
|
|
2392
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2763
2393
|
|
|
2764
2394
|
return s0;
|
|
2765
2395
|
}
|
|
@@ -2768,7 +2398,7 @@ function peg$parse(input, options) {
|
|
|
2768
2398
|
let s0, s1, s3, s4, s5, s6, s7, s8, s9, s11, s13;
|
|
2769
2399
|
|
|
2770
2400
|
const key = peg$currPos * 38 + 31;
|
|
2771
|
-
const cached = peg$resultsCache
|
|
2401
|
+
const cached = peg$resultsCache.get(key);
|
|
2772
2402
|
|
|
2773
2403
|
if (cached) {
|
|
2774
2404
|
peg$currPos = cached.nextPos;
|
|
@@ -2820,50 +2450,7 @@ function peg$parse(input, options) {
|
|
|
2820
2450
|
}
|
|
2821
2451
|
s4 = peg$parse_();
|
|
2822
2452
|
s5 = [];
|
|
2823
|
-
|
|
2824
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2825
|
-
s7 = peg$c34;
|
|
2826
|
-
peg$currPos++;
|
|
2827
|
-
} else {
|
|
2828
|
-
s7 = peg$FAILED;
|
|
2829
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
2830
|
-
}
|
|
2831
|
-
if (s7 !== peg$FAILED) {
|
|
2832
|
-
s8 = peg$parse_();
|
|
2833
|
-
s9 = peg$parseStringLiteral();
|
|
2834
|
-
if (s9 !== peg$FAILED) {
|
|
2835
|
-
peg$parse_();
|
|
2836
|
-
if (input.charCodeAt(peg$currPos) === 58) {
|
|
2837
|
-
s11 = peg$c15;
|
|
2838
|
-
peg$currPos++;
|
|
2839
|
-
} else {
|
|
2840
|
-
s11 = peg$FAILED;
|
|
2841
|
-
if (peg$silentFails === 0) { peg$fail(peg$e11); }
|
|
2842
|
-
}
|
|
2843
|
-
if (s11 !== peg$FAILED) {
|
|
2844
|
-
peg$parse_();
|
|
2845
|
-
s13 = peg$parseTernaryExpression();
|
|
2846
|
-
if (s13 !== peg$FAILED) {
|
|
2847
|
-
peg$parse_();
|
|
2848
|
-
s6 = [ s9, s13 ];
|
|
2849
|
-
} else {
|
|
2850
|
-
peg$currPos = s6;
|
|
2851
|
-
s6 = peg$FAILED;
|
|
2852
|
-
}
|
|
2853
|
-
} else {
|
|
2854
|
-
peg$currPos = s6;
|
|
2855
|
-
s6 = peg$FAILED;
|
|
2856
|
-
}
|
|
2857
|
-
} else {
|
|
2858
|
-
peg$currPos = s6;
|
|
2859
|
-
s6 = peg$FAILED;
|
|
2860
|
-
}
|
|
2861
|
-
} else {
|
|
2862
|
-
peg$currPos = s6;
|
|
2863
|
-
s6 = peg$FAILED;
|
|
2864
|
-
}
|
|
2865
|
-
while (s6 !== peg$FAILED) {
|
|
2866
|
-
s5.push(s6);
|
|
2453
|
+
for (;;) {
|
|
2867
2454
|
s6 = peg$currPos;
|
|
2868
2455
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2869
2456
|
s7 = peg$c34;
|
|
@@ -2906,6 +2493,8 @@ function peg$parse(input, options) {
|
|
|
2906
2493
|
peg$currPos = s6;
|
|
2907
2494
|
s6 = peg$FAILED;
|
|
2908
2495
|
}
|
|
2496
|
+
if (s6 === peg$FAILED) { break; }
|
|
2497
|
+
s5.push(s6);
|
|
2909
2498
|
}
|
|
2910
2499
|
if (input.charCodeAt(peg$currPos) === 125) {
|
|
2911
2500
|
s6 = peg$c43;
|
|
@@ -2930,7 +2519,7 @@ function peg$parse(input, options) {
|
|
|
2930
2519
|
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
|
2931
2520
|
}
|
|
2932
2521
|
|
|
2933
|
-
peg$resultsCache
|
|
2522
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2934
2523
|
|
|
2935
2524
|
return s0;
|
|
2936
2525
|
}
|
|
@@ -2939,7 +2528,7 @@ function peg$parse(input, options) {
|
|
|
2939
2528
|
let s0, s1, s2, s3, s4;
|
|
2940
2529
|
|
|
2941
2530
|
const key = peg$currPos * 38 + 32;
|
|
2942
|
-
const cached = peg$resultsCache
|
|
2531
|
+
const cached = peg$resultsCache.get(key);
|
|
2943
2532
|
|
|
2944
2533
|
if (cached) {
|
|
2945
2534
|
peg$currPos = cached.nextPos;
|
|
@@ -2997,7 +2586,7 @@ function peg$parse(input, options) {
|
|
|
2997
2586
|
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
|
2998
2587
|
}
|
|
2999
2588
|
|
|
3000
|
-
peg$resultsCache
|
|
2589
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3001
2590
|
|
|
3002
2591
|
return s0;
|
|
3003
2592
|
}
|
|
@@ -3006,7 +2595,7 @@ function peg$parse(input, options) {
|
|
|
3006
2595
|
let s0, s1, s2, s3, s4;
|
|
3007
2596
|
|
|
3008
2597
|
const key = peg$currPos * 38 + 33;
|
|
3009
|
-
const cached = peg$resultsCache
|
|
2598
|
+
const cached = peg$resultsCache.get(key);
|
|
3010
2599
|
|
|
3011
2600
|
if (cached) {
|
|
3012
2601
|
peg$currPos = cached.nextPos;
|
|
@@ -3017,7 +2606,7 @@ function peg$parse(input, options) {
|
|
|
3017
2606
|
s0 = peg$currPos;
|
|
3018
2607
|
s1 = peg$currPos;
|
|
3019
2608
|
s2 = input.charAt(peg$currPos);
|
|
3020
|
-
if (peg$
|
|
2609
|
+
if ((peg$charCode = s2.charCodeAt(0), (peg$charCode >= 97 && peg$charCode <= 122) || (peg$charCode >= 65 && peg$charCode <= 90) || peg$charCode === 36 || peg$charCode === 95)) {
|
|
3021
2610
|
peg$currPos++;
|
|
3022
2611
|
} else {
|
|
3023
2612
|
s2 = peg$FAILED;
|
|
@@ -3025,22 +2614,16 @@ function peg$parse(input, options) {
|
|
|
3025
2614
|
}
|
|
3026
2615
|
if (s2 !== peg$FAILED) {
|
|
3027
2616
|
s3 = [];
|
|
3028
|
-
|
|
3029
|
-
if (peg$r6.test(s4)) {
|
|
3030
|
-
peg$currPos++;
|
|
3031
|
-
} else {
|
|
3032
|
-
s4 = peg$FAILED;
|
|
3033
|
-
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
|
3034
|
-
}
|
|
3035
|
-
while (s4 !== peg$FAILED) {
|
|
3036
|
-
s3.push(s4);
|
|
2617
|
+
for (;;) {
|
|
3037
2618
|
s4 = input.charAt(peg$currPos);
|
|
3038
|
-
if (peg$
|
|
2619
|
+
if ((peg$charCode = s4.charCodeAt(0), (peg$charCode >= 97 && peg$charCode <= 122) || (peg$charCode >= 65 && peg$charCode <= 90) || peg$charCode === 36 || peg$charCode === 95 || (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
3039
2620
|
peg$currPos++;
|
|
3040
2621
|
} else {
|
|
3041
2622
|
s4 = peg$FAILED;
|
|
3042
2623
|
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
|
3043
2624
|
}
|
|
2625
|
+
if (s4 === peg$FAILED) { break; }
|
|
2626
|
+
s3.push(s4);
|
|
3044
2627
|
}
|
|
3045
2628
|
s2 = [s2, s3];
|
|
3046
2629
|
s1 = s2;
|
|
@@ -3054,7 +2637,7 @@ function peg$parse(input, options) {
|
|
|
3054
2637
|
s0 = s1;
|
|
3055
2638
|
}
|
|
3056
2639
|
|
|
3057
|
-
peg$resultsCache
|
|
2640
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3058
2641
|
|
|
3059
2642
|
return s0;
|
|
3060
2643
|
}
|
|
@@ -3063,7 +2646,7 @@ function peg$parse(input, options) {
|
|
|
3063
2646
|
let s0, s1;
|
|
3064
2647
|
|
|
3065
2648
|
const key = peg$currPos * 38 + 34;
|
|
3066
|
-
const cached = peg$resultsCache
|
|
2649
|
+
const cached = peg$resultsCache.get(key);
|
|
3067
2650
|
|
|
3068
2651
|
if (cached) {
|
|
3069
2652
|
peg$currPos = cached.nextPos;
|
|
@@ -3084,7 +2667,7 @@ function peg$parse(input, options) {
|
|
|
3084
2667
|
if (peg$silentFails === 0) { peg$fail(peg$e47); }
|
|
3085
2668
|
}
|
|
3086
2669
|
|
|
3087
|
-
peg$resultsCache
|
|
2670
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3088
2671
|
|
|
3089
2672
|
return s0;
|
|
3090
2673
|
}
|
|
@@ -3093,7 +2676,7 @@ function peg$parse(input, options) {
|
|
|
3093
2676
|
let s0;
|
|
3094
2677
|
|
|
3095
2678
|
const key = peg$currPos * 38 + 35;
|
|
3096
|
-
const cached = peg$resultsCache
|
|
2679
|
+
const cached = peg$resultsCache.get(key);
|
|
3097
2680
|
|
|
3098
2681
|
if (cached) {
|
|
3099
2682
|
peg$currPos = cached.nextPos;
|
|
@@ -3118,7 +2701,7 @@ function peg$parse(input, options) {
|
|
|
3118
2701
|
}
|
|
3119
2702
|
}
|
|
3120
2703
|
|
|
3121
|
-
peg$resultsCache
|
|
2704
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3122
2705
|
|
|
3123
2706
|
return s0;
|
|
3124
2707
|
}
|
|
@@ -3127,7 +2710,7 @@ function peg$parse(input, options) {
|
|
|
3127
2710
|
let s0;
|
|
3128
2711
|
|
|
3129
2712
|
const key = peg$currPos * 38 + 36;
|
|
3130
|
-
const cached = peg$resultsCache
|
|
2713
|
+
const cached = peg$resultsCache.get(key);
|
|
3131
2714
|
|
|
3132
2715
|
if (cached) {
|
|
3133
2716
|
peg$currPos = cached.nextPos;
|
|
@@ -3170,7 +2753,7 @@ function peg$parse(input, options) {
|
|
|
3170
2753
|
}
|
|
3171
2754
|
}
|
|
3172
2755
|
|
|
3173
|
-
peg$resultsCache
|
|
2756
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3174
2757
|
|
|
3175
2758
|
return s0;
|
|
3176
2759
|
}
|
|
@@ -3179,7 +2762,7 @@ function peg$parse(input, options) {
|
|
|
3179
2762
|
let s0, s1;
|
|
3180
2763
|
|
|
3181
2764
|
const key = peg$currPos * 38 + 37;
|
|
3182
|
-
const cached = peg$resultsCache
|
|
2765
|
+
const cached = peg$resultsCache.get(key);
|
|
3183
2766
|
|
|
3184
2767
|
if (cached) {
|
|
3185
2768
|
peg$currPos = cached.nextPos;
|
|
@@ -3189,26 +2772,20 @@ function peg$parse(input, options) {
|
|
|
3189
2772
|
|
|
3190
2773
|
peg$silentFails++;
|
|
3191
2774
|
s0 = [];
|
|
3192
|
-
|
|
3193
|
-
if (peg$r7.test(s1)) {
|
|
3194
|
-
peg$currPos++;
|
|
3195
|
-
} else {
|
|
3196
|
-
s1 = peg$FAILED;
|
|
3197
|
-
if (peg$silentFails === 0) { peg$fail(peg$e54); }
|
|
3198
|
-
}
|
|
3199
|
-
while (s1 !== peg$FAILED) {
|
|
3200
|
-
s0.push(s1);
|
|
2775
|
+
for (;;) {
|
|
3201
2776
|
s1 = input.charAt(peg$currPos);
|
|
3202
|
-
if (peg$
|
|
2777
|
+
if ((peg$charCode = s1.charCodeAt(0), peg$charCode === 32 || peg$charCode === 9 || peg$charCode === 10 || peg$charCode === 13)) {
|
|
3203
2778
|
peg$currPos++;
|
|
3204
2779
|
} else {
|
|
3205
2780
|
s1 = peg$FAILED;
|
|
3206
2781
|
if (peg$silentFails === 0) { peg$fail(peg$e54); }
|
|
3207
2782
|
}
|
|
2783
|
+
if (s1 === peg$FAILED) { break; }
|
|
2784
|
+
s0.push(s1);
|
|
3208
2785
|
}
|
|
3209
2786
|
peg$silentFails--;
|
|
3210
2787
|
|
|
3211
|
-
peg$resultsCache
|
|
2788
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3212
2789
|
|
|
3213
2790
|
return s0;
|
|
3214
2791
|
}
|
|
@@ -3250,10 +2827,10 @@ function peg$parse(input, options) {
|
|
|
3250
2827
|
/**
|
|
3251
2828
|
* The one lookup against a data stack: the innermost overlay carrying the name
|
|
3252
2829
|
* wins, `self` is the innermost overlay itself, and a function overlay counts
|
|
3253
|
-
* like an object one.
|
|
3254
|
-
* imperative facades cannot drift from what a template sees.
|
|
2830
|
+
* like an object one.
|
|
3255
2831
|
* @param {any[]} dataStack
|
|
3256
2832
|
* @param {string|symbol} prop
|
|
2833
|
+
* @returns {any} undefined when no overlay carries the name
|
|
3257
2834
|
*/
|
|
3258
2835
|
const resolveInStack = (dataStack, prop) => {
|
|
3259
2836
|
if (prop === 'self') {
|
|
@@ -3317,8 +2894,7 @@ class EvaluatingVisitor {
|
|
|
3317
2894
|
return this.visit(node.lhs) || this.visit(node.rhs);
|
|
3318
2895
|
}
|
|
3319
2896
|
[nodes.nullc](node) {
|
|
3320
|
-
|
|
3321
|
-
return lhs !== null && lhs !== undefined ? lhs : this.visit(node.rhs);
|
|
2897
|
+
return this.visit(node.lhs) ?? this.visit(node.rhs);
|
|
3322
2898
|
}
|
|
3323
2899
|
[nodes.not](node) {
|
|
3324
2900
|
return !this.visit(node.expr);
|
|
@@ -3385,8 +2961,7 @@ class EvaluatingVisitor {
|
|
|
3385
2961
|
return this.visit(node.cond) ? this.visit(node.ifTrue) : this.visit(node.ifFalse);
|
|
3386
2962
|
}
|
|
3387
2963
|
[nodes.elv](node) {
|
|
3388
|
-
|
|
3389
|
-
return cond ? cond : this.visit(node.ifFalse);
|
|
2964
|
+
return this.visit(node.cond) || this.visit(node.ifFalse);
|
|
3390
2965
|
}
|
|
3391
2966
|
[nodes.access](node) {
|
|
3392
2967
|
let prev;
|
|
@@ -3452,16 +3027,23 @@ class EvaluatingVisitor {
|
|
|
3452
3027
|
* spliced into the expression text.
|
|
3453
3028
|
*/
|
|
3454
3029
|
class Expressions {
|
|
3030
|
+
/** Parses the whole text as one expression: `user.name`. */
|
|
3455
3031
|
static MODE_EXPRESSION = Symbol('MODE_EXPRESSION');
|
|
3032
|
+
/**
|
|
3033
|
+
* Parses text with interpolations, `Hello {{ user.name }}`, evaluating to
|
|
3034
|
+
* its parts: `{ type, value }` for each literal run and each `{{ }}` (text),
|
|
3035
|
+
* `{{{ }}}` (html) or `{{{{ }}}}` (node) interpolation, in order.
|
|
3036
|
+
*/
|
|
3456
3037
|
static MODE_TEMPLATED = Symbol('MODE_TEMPLATED');
|
|
3457
3038
|
|
|
3458
3039
|
static #astCache = new BoundedCache(1000);
|
|
3459
3040
|
|
|
3460
3041
|
/**
|
|
3461
|
-
* Parses an expression.
|
|
3042
|
+
* Parses an expression, caching the ast by mode and text.
|
|
3462
3043
|
* @param {string} expression
|
|
3463
|
-
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
3464
|
-
* @returns the ast
|
|
3044
|
+
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode] MODE_EXPRESSION when omitted
|
|
3045
|
+
* @returns {any} the ast
|
|
3046
|
+
* @throws a peggy syntax error when the text does not parse
|
|
3465
3047
|
*/
|
|
3466
3048
|
static parse(expression, mode) {
|
|
3467
3049
|
const key = mode?.toString() + expression;
|
|
@@ -3472,12 +3054,12 @@ class Expressions {
|
|
|
3472
3054
|
);
|
|
3473
3055
|
}
|
|
3474
3056
|
/**
|
|
3475
|
-
* Evaluates
|
|
3057
|
+
* Evaluates a parsed ast against the modules and the data stack.
|
|
3476
3058
|
* @param {{[k: string]: any } | null | undefined } modules
|
|
3477
|
-
* @param {any[]} dataStack
|
|
3478
|
-
* @param {any} ast
|
|
3479
|
-
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
3480
|
-
* @returns the
|
|
3059
|
+
* @param {any[]} dataStack innermost overlay last
|
|
3060
|
+
* @param {any} ast what `parse` answered
|
|
3061
|
+
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode] the mode it was parsed in
|
|
3062
|
+
* @returns {any} the value, or the list of parts in MODE_TEMPLATED
|
|
3481
3063
|
*/
|
|
3482
3064
|
static evaluate(modules, dataStack, ast, mode) {
|
|
3483
3065
|
return new EvaluatingVisitor(modules, dataStack).visitRoot(ast, mode === Expressions.MODE_TEMPLATED);
|
|
@@ -3485,10 +3067,10 @@ class Expressions {
|
|
|
3485
3067
|
/**
|
|
3486
3068
|
* Parses and evaluates an expression.
|
|
3487
3069
|
* @param {{ [x: string]: any; } | null | undefined} modules
|
|
3488
|
-
* @param {any[]} dataStack
|
|
3070
|
+
* @param {any[]} dataStack innermost overlay last
|
|
3489
3071
|
* @param {string} expression
|
|
3490
|
-
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
3491
|
-
* @returns the
|
|
3072
|
+
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode] MODE_EXPRESSION when omitted
|
|
3073
|
+
* @returns {any} the value, or the list of parts in MODE_TEMPLATED
|
|
3492
3074
|
*/
|
|
3493
3075
|
static interpret(modules, dataStack, expression, mode) {
|
|
3494
3076
|
return Expressions.evaluate(modules, dataStack, Expressions.parse(expression, mode), mode);
|
|
@@ -3504,14 +3086,31 @@ class Expressions {
|
|
|
3504
3086
|
class ExpressionEvaluator {
|
|
3505
3087
|
#modules;
|
|
3506
3088
|
#dataStack;
|
|
3089
|
+
/**
|
|
3090
|
+
* @param {{ [k: string]: any } | null | undefined} modules
|
|
3091
|
+
* @param {any[]} dataStack innermost overlay last
|
|
3092
|
+
*/
|
|
3507
3093
|
constructor(modules, dataStack) {
|
|
3508
3094
|
this.#modules = modules;
|
|
3509
3095
|
this.#dataStack = dataStack;
|
|
3510
3096
|
}
|
|
3097
|
+
/**
|
|
3098
|
+
* A new evaluator with one more module: `#name:fn()` resolves into it, and an
|
|
3099
|
+
* empty name merges a whole map whose functions resolve bare, as `#fn()`.
|
|
3100
|
+
* @param {string} name
|
|
3101
|
+
* @param {object} value
|
|
3102
|
+
* @returns {ExpressionEvaluator}
|
|
3103
|
+
*/
|
|
3511
3104
|
withModule(name, value) {
|
|
3512
3105
|
const module = name ? { [name]: value } : value;
|
|
3513
3106
|
return new ExpressionEvaluator({ ...this.#modules, ...module }, this.#dataStack);
|
|
3514
3107
|
}
|
|
3108
|
+
/**
|
|
3109
|
+
* A new evaluator with the data pushed as the innermost overlays, the last
|
|
3110
|
+
* one winning a shared name.
|
|
3111
|
+
* @param {...any} data
|
|
3112
|
+
* @returns {ExpressionEvaluator}
|
|
3113
|
+
*/
|
|
3515
3114
|
withOverlay(...data) {
|
|
3516
3115
|
return new ExpressionEvaluator(
|
|
3517
3116
|
this.#modules,
|
|
@@ -3522,26 +3121,36 @@ class ExpressionEvaluator {
|
|
|
3522
3121
|
* Resolves a name against the data stack, with no parse round trip: the
|
|
3523
3122
|
* lookup a template's bare identifier makes, for an imperative caller.
|
|
3524
3123
|
* @param {string} name
|
|
3124
|
+
* @returns {any} undefined when no overlay carries the name
|
|
3525
3125
|
*/
|
|
3526
3126
|
resolve(name) {
|
|
3527
3127
|
return resolveInStack(this.#dataStack, name);
|
|
3528
3128
|
}
|
|
3529
|
-
/**
|
|
3129
|
+
/**
|
|
3130
|
+
* Evaluates an expression against this scope.
|
|
3131
|
+
* @param {string} expression
|
|
3132
|
+
* @returns {any}
|
|
3133
|
+
*/
|
|
3530
3134
|
evaluateExpression(expression) {
|
|
3531
3135
|
return Expressions.interpret(this.#modules, this.#dataStack, expression, Expressions.MODE_EXPRESSION);
|
|
3532
3136
|
}
|
|
3533
|
-
/**
|
|
3137
|
+
/**
|
|
3138
|
+
* Evaluates a templated text, the `{{ }}` form, against this scope.
|
|
3139
|
+
* @param {string} text
|
|
3140
|
+
* @returns {{ type: symbol, value: any }[]} its parts, as MODE_TEMPLATED describes
|
|
3141
|
+
*/
|
|
3534
3142
|
evaluateTemplated(text) {
|
|
3535
3143
|
return Expressions.interpret(this.#modules, this.#dataStack, text, Expressions.MODE_TEMPLATED);
|
|
3536
3144
|
}
|
|
3537
3145
|
}
|
|
3538
3146
|
|
|
3539
|
-
/** Creates and inspects
|
|
3147
|
+
/** Creates, serializes and inspects DocumentFragments. */
|
|
3540
3148
|
class Fragments {
|
|
3541
3149
|
/**
|
|
3542
|
-
*
|
|
3543
|
-
*
|
|
3544
|
-
* @
|
|
3150
|
+
* Parses html into a DocumentFragment adopted by the document, each piece
|
|
3151
|
+
* trimmed and the pieces joined.
|
|
3152
|
+
* @param {...string} html
|
|
3153
|
+
* @returns {DocumentFragment}
|
|
3545
3154
|
*/
|
|
3546
3155
|
static fromHtml(...html) {
|
|
3547
3156
|
const el = document.createElement('template');
|
|
@@ -3549,11 +3158,11 @@ class Fragments {
|
|
|
3549
3158
|
return document.adoptNode(el.content);
|
|
3550
3159
|
}
|
|
3551
3160
|
/**
|
|
3552
|
-
*
|
|
3553
|
-
*
|
|
3161
|
+
* Serializes a fragment, or a single node, to html, consuming it: the nodes
|
|
3162
|
+
* are moved out, not copied, and a fragment is left empty. Pass
|
|
3554
3163
|
* `fragment.cloneNode(true)` to keep the original usable.
|
|
3555
|
-
* @param {DocumentFragment} fragment
|
|
3556
|
-
* @returns {string}
|
|
3164
|
+
* @param {DocumentFragment|Node} fragment
|
|
3165
|
+
* @returns {string}
|
|
3557
3166
|
*/
|
|
3558
3167
|
static toHtml(fragment) {
|
|
3559
3168
|
var el = document.createElement('template');
|
|
@@ -3561,17 +3170,17 @@ class Fragments {
|
|
|
3561
3170
|
return el.innerHTML;
|
|
3562
3171
|
}
|
|
3563
3172
|
/**
|
|
3564
|
-
*
|
|
3173
|
+
* Whether a fragment holds no element and no text but whitespace.
|
|
3565
3174
|
* @param {DocumentFragment} fragment
|
|
3566
|
-
* @returns {boolean}
|
|
3175
|
+
* @returns {boolean}
|
|
3567
3176
|
*/
|
|
3568
3177
|
static isBlank(fragment) {
|
|
3569
3178
|
return fragment.childElementCount === 0 && fragment.textContent.trim() === '';
|
|
3570
3179
|
}
|
|
3571
3180
|
/**
|
|
3572
|
-
*
|
|
3573
|
-
* @param
|
|
3574
|
-
* @returns {DocumentFragment}
|
|
3181
|
+
* Moves the nodes, in order, into a new DocumentFragment.
|
|
3182
|
+
* @param {...Node} nodes
|
|
3183
|
+
* @returns {DocumentFragment}
|
|
3575
3184
|
*/
|
|
3576
3185
|
static from(...nodes) {
|
|
3577
3186
|
const fragment = new DocumentFragment();
|
|
@@ -3581,9 +3190,10 @@ class Fragments {
|
|
|
3581
3190
|
return fragment;
|
|
3582
3191
|
}
|
|
3583
3192
|
/**
|
|
3584
|
-
*
|
|
3193
|
+
* Moves the children of a node into a new DocumentFragment, leaving the
|
|
3194
|
+
* node empty.
|
|
3585
3195
|
* @param {Node} el
|
|
3586
|
-
* @returns {DocumentFragment}
|
|
3196
|
+
* @returns {DocumentFragment}
|
|
3587
3197
|
*/
|
|
3588
3198
|
static fromChildNodes(el) {
|
|
3589
3199
|
const fragment = new DocumentFragment();
|
|
@@ -3594,23 +3204,23 @@ class Fragments {
|
|
|
3594
3204
|
}
|
|
3595
3205
|
}
|
|
3596
3206
|
|
|
3597
|
-
/** Attribute
|
|
3207
|
+
/** Attribute helpers: unique ids, defaults, prefixed forwarding, and writes where a nullish value removes the attribute. */
|
|
3598
3208
|
class Attributes {
|
|
3599
3209
|
static id = 0;
|
|
3600
3210
|
/**
|
|
3601
|
-
*
|
|
3211
|
+
* A page-unique id under the prefix, as `prefix-n`.
|
|
3602
3212
|
* @param {string} prefix
|
|
3603
|
-
* @returns
|
|
3213
|
+
* @returns {string}
|
|
3604
3214
|
*/
|
|
3605
3215
|
static uid(prefix) {
|
|
3606
3216
|
return `${prefix}-${++Attributes.id}`;
|
|
3607
3217
|
}
|
|
3608
3218
|
/**
|
|
3609
|
-
* Sets an attribute
|
|
3219
|
+
* Sets an attribute when the element does not carry it.
|
|
3610
3220
|
* @param {Element} el
|
|
3611
3221
|
* @param {string} k
|
|
3612
3222
|
* @param {string} v
|
|
3613
|
-
* @returns
|
|
3223
|
+
* @returns {string|null} the attribute's value afterwards
|
|
3614
3224
|
*/
|
|
3615
3225
|
static defaultValue(el, k, v) {
|
|
3616
3226
|
if (!el.hasAttribute(k)) {
|
|
@@ -3619,7 +3229,9 @@ class Attributes {
|
|
|
3619
3229
|
return el.getAttribute(k);
|
|
3620
3230
|
}
|
|
3621
3231
|
/**
|
|
3622
|
-
*
|
|
3232
|
+
* Copies every attribute whose name starts with the prefix onto another
|
|
3233
|
+
* element, under the name without the prefix. `<prefix>class` adds its
|
|
3234
|
+
* classes to the target's instead of replacing them.
|
|
3623
3235
|
* @param {string} prefix
|
|
3624
3236
|
* @param {Element} from
|
|
3625
3237
|
* @param {Element} to
|
|
@@ -3642,7 +3254,7 @@ class Attributes {
|
|
|
3642
3254
|
});
|
|
3643
3255
|
}
|
|
3644
3256
|
/**
|
|
3645
|
-
* Sets
|
|
3257
|
+
* Sets an attribute, or removes it when the value is nullish.
|
|
3646
3258
|
* @param {Element} el
|
|
3647
3259
|
* @param {string} attr
|
|
3648
3260
|
* @param {string | null | undefined} value
|
|
@@ -3664,13 +3276,14 @@ class Attributes {
|
|
|
3664
3276
|
*/
|
|
3665
3277
|
class LightSlots {
|
|
3666
3278
|
/**
|
|
3667
|
-
*
|
|
3279
|
+
* Takes an element's children apart into slots, leaving the element empty.
|
|
3280
|
+
* A named child is removed and contributes what `slotFromNode` answers;
|
|
3281
|
+
* children sharing a name are gathered in order. A child with an empty
|
|
3282
|
+
* `slot` belongs to the default slot, in document order among the rest.
|
|
3668
3283
|
* @param {Element} el
|
|
3669
|
-
* @returns the slots
|
|
3284
|
+
* @returns {Record<string, DocumentFragment>} the slots by name, `default` always present
|
|
3670
3285
|
*/
|
|
3671
3286
|
static from(el) {
|
|
3672
|
-
//the platform reads slot="" as the default slot: such children stay in
|
|
3673
|
-
//the document order of the default content, their claim stripped like any named one
|
|
3674
3287
|
for (const child of el.children) {
|
|
3675
3288
|
if (child.matches('[slot=""]')) {
|
|
3676
3289
|
child.removeAttribute('slot');
|
|
@@ -3685,7 +3298,7 @@ class LightSlots {
|
|
|
3685
3298
|
el.removeAttribute('slot');
|
|
3686
3299
|
return [slot, LightSlots.slotFromNode(el)];
|
|
3687
3300
|
});
|
|
3688
|
-
const slots =
|
|
3301
|
+
const slots = Object.create(null);
|
|
3689
3302
|
slots.default = new DocumentFragment();
|
|
3690
3303
|
slots.default.append(...el.childNodes);
|
|
3691
3304
|
for (const [name, el] of namedSlots) {
|
|
@@ -3696,6 +3309,12 @@ class LightSlots {
|
|
|
3696
3309
|
}
|
|
3697
3310
|
return slots;
|
|
3698
3311
|
}
|
|
3312
|
+
/**
|
|
3313
|
+
* What a slotted node contributes: a template's content, the parsed markup
|
|
3314
|
+
* of a `<script type="text/html">`, or the node itself.
|
|
3315
|
+
* @param {Element} el
|
|
3316
|
+
* @returns {Element|DocumentFragment}
|
|
3317
|
+
*/
|
|
3699
3318
|
static slotFromNode(el) {
|
|
3700
3319
|
if (el instanceof HTMLTemplateElement) {
|
|
3701
3320
|
return document.adoptNode(el.content);
|
|
@@ -3707,12 +3326,13 @@ class LightSlots {
|
|
|
3707
3326
|
}
|
|
3708
3327
|
}
|
|
3709
3328
|
|
|
3710
|
-
/** Waits
|
|
3329
|
+
/** Waits on the parser and the document, and queries an element's own children. */
|
|
3711
3330
|
class Nodes {
|
|
3712
3331
|
/**
|
|
3713
|
-
*
|
|
3332
|
+
* Whether the parser has moved past the element: the element, or one of
|
|
3333
|
+
* its ancestors, has a next sibling.
|
|
3714
3334
|
* @param {Element} el
|
|
3715
|
-
* @returns
|
|
3335
|
+
* @returns {boolean}
|
|
3716
3336
|
*/
|
|
3717
3337
|
static isParsed(el) {
|
|
3718
3338
|
for (let c = /** @type {Node | null} */ (el); c; c = c.parentNode) {
|
|
@@ -3724,13 +3344,12 @@ class Nodes {
|
|
|
3724
3344
|
}
|
|
3725
3345
|
|
|
3726
3346
|
/**
|
|
3727
|
-
* Waits for the document's DOMContentLoaded
|
|
3728
|
-
*
|
|
3729
|
-
*
|
|
3730
|
-
*
|
|
3731
|
-
*
|
|
3732
|
-
*
|
|
3733
|
-
* never early.
|
|
3347
|
+
* Waits for the document's DOMContentLoaded. Resolves at once when that
|
|
3348
|
+
* moment already passed, and for a document with no view, which receives
|
|
3349
|
+
* no events. Never resolves early for a document still running its
|
|
3350
|
+
* deferred scripts.
|
|
3351
|
+
* @param {Document} doc
|
|
3352
|
+
* @returns {Promise<void>}
|
|
3734
3353
|
*/
|
|
3735
3354
|
static waitDomContentLoaded(doc) {
|
|
3736
3355
|
if (doc.readyState === 'loading') {
|
|
@@ -3743,7 +3362,13 @@ class Nodes {
|
|
|
3743
3362
|
}
|
|
3744
3363
|
const win = doc.defaultView;
|
|
3745
3364
|
if (win === null) {
|
|
3746
|
-
|
|
3365
|
+
return Promise.resolve();
|
|
3366
|
+
}
|
|
3367
|
+
// interactive spans both the deferred scripts and the time between DOMContentLoaded and load
|
|
3368
|
+
const [navigation] = /** @type {PerformanceNavigationTiming[]} */ (
|
|
3369
|
+
win.performance?.getEntriesByType('navigation') ?? []
|
|
3370
|
+
);
|
|
3371
|
+
if (navigation?.domContentLoadedEventStart > 0) {
|
|
3747
3372
|
return Promise.resolve();
|
|
3748
3373
|
}
|
|
3749
3374
|
return new Promise((resolve) => {
|
|
@@ -3762,22 +3387,12 @@ class Nodes {
|
|
|
3762
3387
|
* resolves once the element, or any of its ancestors, gains a next sibling,
|
|
3763
3388
|
* which is the parser having moved past this subtree. The document's
|
|
3764
3389
|
* DOMContentLoaded is the deadline. Resolves immediately for an element
|
|
3765
|
-
* that is already parsed.
|
|
3766
|
-
*
|
|
3767
|
-
*
|
|
3768
|
-
* predicate reads: an element last among its siblings becomes parsed when
|
|
3769
|
-
* an ancestor gains one, and a childList observer on the parent never sees
|
|
3770
|
-
* that. Formatted markup usually hides the difference, the whitespace
|
|
3771
|
-
* before a closing tag being a text node the parent does gain, so the gap
|
|
3772
|
-
* shows on whitespace-free markup, where the wait fell back to the
|
|
3773
|
-
* deadline. One observer takes many targets, so the cost is one observe()
|
|
3774
|
-
* per level, and it is disconnected at the first checkpoint past the
|
|
3775
|
-
* element either way.
|
|
3776
|
-
* @param {any} el
|
|
3777
|
-
* @returns {Promise<any>}
|
|
3390
|
+
* that is already parsed, or once the parser has finished the document.
|
|
3391
|
+
* @param {Element} el
|
|
3392
|
+
* @returns {Promise<Element>} the element
|
|
3778
3393
|
*/
|
|
3779
3394
|
static waitParsed(el) {
|
|
3780
|
-
if (Nodes.isParsed(el)) {
|
|
3395
|
+
if (Nodes.isParsed(el) || el.ownerDocument.readyState !== 'loading') {
|
|
3781
3396
|
return Promise.resolve(el);
|
|
3782
3397
|
}
|
|
3783
3398
|
return new Promise((resolve) => {
|
|
@@ -3799,10 +3414,10 @@ class Nodes {
|
|
|
3799
3414
|
}
|
|
3800
3415
|
|
|
3801
3416
|
/**
|
|
3802
|
-
*
|
|
3803
|
-
* @param {Element} el
|
|
3417
|
+
* The first child element matching the selector, descendants excluded.
|
|
3418
|
+
* @param {Element|DocumentFragment} el
|
|
3804
3419
|
* @param {string} selector
|
|
3805
|
-
* @returns
|
|
3420
|
+
* @returns {Element|null}
|
|
3806
3421
|
*/
|
|
3807
3422
|
static queryChildren(el, selector) {
|
|
3808
3423
|
for (const c of el.children) {
|
|
@@ -3813,10 +3428,10 @@ class Nodes {
|
|
|
3813
3428
|
return null;
|
|
3814
3429
|
}
|
|
3815
3430
|
/**
|
|
3816
|
-
*
|
|
3817
|
-
* @param {Element} el
|
|
3431
|
+
* Every child element matching the selector, descendants excluded.
|
|
3432
|
+
* @param {Element|DocumentFragment} el
|
|
3818
3433
|
* @param {string} selector
|
|
3819
|
-
* @returns
|
|
3434
|
+
* @returns {Element[]}
|
|
3820
3435
|
*/
|
|
3821
3436
|
static queryChildrenAll(el, selector) {
|
|
3822
3437
|
const r = [];
|
|
@@ -3873,9 +3488,11 @@ class NodeOperations {
|
|
|
3873
3488
|
|
|
3874
3489
|
/** The `data-tpl-*` commands, each taking the node it is written on and the scope it evaluates in. */
|
|
3875
3490
|
class CommandsHandler {
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3491
|
+
/**
|
|
3492
|
+
* The order the commands run in on one element, each seeing the node as the
|
|
3493
|
+
* ones before left it: tplIf gates before tplWith and tplEach push their
|
|
3494
|
+
* overlay, tplWhen gates after, inside the scope that overlay opened.
|
|
3495
|
+
*/
|
|
3879
3496
|
static ORDERED_COMMANDS = [
|
|
3880
3497
|
'tplIf',
|
|
3881
3498
|
'tplWith',
|
|
@@ -3886,8 +3503,7 @@ class CommandsHandler {
|
|
|
3886
3503
|
'tplRemove',
|
|
3887
3504
|
'tplVerbatim',
|
|
3888
3505
|
];
|
|
3889
|
-
|
|
3890
|
-
//if evaluates in the outer scope, before with/each
|
|
3506
|
+
/** Removes the node when the expression is falsy, evaluated before tplWith and tplEach open their overlay. */
|
|
3891
3507
|
static tplIf(node, expression, ops, evaluator) {
|
|
3892
3508
|
const accept = evaluator.evaluateExpression(expression);
|
|
3893
3509
|
if (!accept) {
|
|
@@ -3902,49 +3518,37 @@ class CommandsHandler {
|
|
|
3902
3518
|
.render();
|
|
3903
3519
|
ops.replace(node, newNode);
|
|
3904
3520
|
}
|
|
3521
|
+
/**
|
|
3522
|
+
* Renders the node once per entry, in place of the node. A Map iterates as
|
|
3523
|
+
* `{ key, value }` entries in its own order, a plain object as `{ key, value }`
|
|
3524
|
+
* entries in `Object.entries` order, and any other iterable as itself; a
|
|
3525
|
+
* value that is none of these throws. Each render sees its entry under
|
|
3526
|
+
* `data-tpl-var`, or as the whole overlay without one. `data-tpl-stat` names
|
|
3527
|
+
* an overlay beneath the entry carrying `index`, `count`, `size`, `first`,
|
|
3528
|
+
* `last`, `even` and `odd`, so an entry property of the same name wins; the
|
|
3529
|
+
* size, and so `last`, is null for a collection that knows neither its
|
|
3530
|
+
* `length` nor its `size`, which is never consumed to learn it.
|
|
3531
|
+
*/
|
|
3905
3532
|
static tplEach(node, expression, ops, evaluator) {
|
|
3906
3533
|
const varName = ops.popData(node, 'tplVar');
|
|
3907
3534
|
const statName = ops.popData(node, 'tplStat');
|
|
3908
3535
|
const template = new Template(node, evaluator);
|
|
3909
3536
|
const evaluated = evaluator.evaluateExpression(expression);
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
const proto = evaluated === null || typeof evaluated !== 'object' ? undefined : Object.getPrototypeOf(evaluated);
|
|
3916
|
-
const keyed =
|
|
3917
|
-
evaluated instanceof Map
|
|
3918
|
-
? [...evaluated]
|
|
3919
|
-
: !evaluated?.[Symbol.iterator] && (proto === Object.prototype || proto === null)
|
|
3920
|
-
? Object.entries(evaluated)
|
|
3921
|
-
: null;
|
|
3537
|
+
const proto =
|
|
3538
|
+
evaluated === null || typeof evaluated !== 'object' ? undefined : Object.getPrototypeOf(evaluated);
|
|
3539
|
+
const plain = !evaluated?.[Symbol.iterator] && (proto === Object.prototype || proto === null);
|
|
3540
|
+
const dict = plain ? Object.entries(evaluated) : null;
|
|
3541
|
+
const keyed = evaluated instanceof Map ? [...evaluated] : dict;
|
|
3922
3542
|
const entries = keyed === null ? evaluated : keyed.map(([key, value]) => ({ key, value }));
|
|
3923
3543
|
if (!entries?.[Symbol.iterator]) {
|
|
3924
3544
|
throw new Error(`Expected an iterable got '${evaluated}'`);
|
|
3925
3545
|
}
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
}
|
|
3930
|
-
ops.remove(node);
|
|
3931
|
-
return;
|
|
3932
|
-
}
|
|
3933
|
-
//the stat rides grouped under its declared name, overlaid below the
|
|
3934
|
-
//item, so data can never collide with its fields and an item property
|
|
3935
|
-
//sharing the stat's very name wins, as data always does. The size is
|
|
3936
|
-
//read where the collection already knows it (arrays and keyed entries
|
|
3937
|
-
//by length, sets and the like by size): an arbitrary iterator is never
|
|
3938
|
-
//consumed to learn it, so its size and last read null, the unknown
|
|
3939
|
-
const size = Array.isArray(entries)
|
|
3940
|
-
? entries.length
|
|
3941
|
-
: typeof entries.length === 'number'
|
|
3942
|
-
? entries.length
|
|
3943
|
-
: typeof entries.size === 'number'
|
|
3944
|
-
? entries.size
|
|
3945
|
-
: null;
|
|
3546
|
+
const measured = statName ? entries : null;
|
|
3547
|
+
const counted = typeof measured?.length === 'number' ? measured.length : measured?.size;
|
|
3548
|
+
const size = typeof counted === 'number' ? counted : null;
|
|
3946
3549
|
let index = 0;
|
|
3947
3550
|
for (const v of entries) {
|
|
3551
|
+
const item = varName ? { [varName]: v } : v;
|
|
3948
3552
|
const stat = {
|
|
3949
3553
|
index,
|
|
3950
3554
|
count: index + 1,
|
|
@@ -3954,16 +3558,13 @@ class CommandsHandler {
|
|
|
3954
3558
|
even: index % 2 === 0,
|
|
3955
3559
|
odd: index % 2 === 1,
|
|
3956
3560
|
};
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
template.withOverlay({ [statName]: stat }, varName ? { [varName]: v } : v).render(),
|
|
3960
|
-
);
|
|
3561
|
+
const layers = statName ? [{ [statName]: stat }, item] : [item];
|
|
3562
|
+
ops.prepend(node, template.withOverlay(...layers).render());
|
|
3961
3563
|
++index;
|
|
3962
3564
|
}
|
|
3963
3565
|
ops.remove(node);
|
|
3964
3566
|
}
|
|
3965
|
-
|
|
3966
|
-
//when evaluates after with/each, in the scope their overlay opened
|
|
3567
|
+
/** Removes the node when the expression is falsy, evaluated in the overlay tplWith or tplEach opened. */
|
|
3967
3568
|
static tplWhen(node, expression, ops, evaluator) {
|
|
3968
3569
|
const accept = evaluator.evaluateExpression(expression);
|
|
3969
3570
|
if (!accept) {
|
|
@@ -3977,12 +3578,8 @@ class CommandsHandler {
|
|
|
3977
3578
|
static tplRemove(node, value, ops, evaluator) {
|
|
3978
3579
|
switch (value.toLowerCase()) {
|
|
3979
3580
|
case 'tag': {
|
|
3980
|
-
const fragment =
|
|
3981
|
-
while (node.firstChild) {
|
|
3982
|
-
fragment.appendChild(node.firstChild);
|
|
3983
|
-
}
|
|
3581
|
+
const fragment = Fragments.fromChildNodes(node);
|
|
3984
3582
|
if ('tplVerbatim' in node.dataset) {
|
|
3985
|
-
//we are removing the parent element so we have to handle the lower priority commands
|
|
3986
3583
|
ops.popData(node, 'tplVerbatim');
|
|
3987
3584
|
ops.replace(node, fragment);
|
|
3988
3585
|
} else {
|
|
@@ -4018,6 +3615,9 @@ class CommandsHandler {
|
|
|
4018
3615
|
}
|
|
4019
3616
|
const tuples = Array.isArray(attributesAndValues[0]) ? attributesAndValues : [attributesAndValues];
|
|
4020
3617
|
tuples.forEach(([k, v]) => {
|
|
3618
|
+
if (v === null || v === undefined) {
|
|
3619
|
+
return;
|
|
3620
|
+
}
|
|
4021
3621
|
node.setAttribute(k, v);
|
|
4022
3622
|
});
|
|
4023
3623
|
}
|
|
@@ -4045,12 +3645,10 @@ class CommandsHandler {
|
|
|
4045
3645
|
}
|
|
4046
3646
|
}
|
|
4047
3647
|
|
|
4048
|
-
// Module-isolated string cache for dataset-to-attribute conversions
|
|
4049
3648
|
const attributeCache = new BoundedCache(1000);
|
|
4050
3649
|
|
|
4051
3650
|
/**
|
|
4052
|
-
*
|
|
4053
|
-
* Uses a cache lookup to avoid repetitive regex/string splitting.
|
|
3651
|
+
* The attribute a `tpl` dataset key targets: `tplAriaLabel` is `aria-label`.
|
|
4054
3652
|
* @param {string} dataSetKey
|
|
4055
3653
|
* @returns {string}
|
|
4056
3654
|
*/
|
|
@@ -4072,38 +3670,40 @@ function toAttr(dataSetKey) {
|
|
|
4072
3670
|
*/
|
|
4073
3671
|
class Template {
|
|
4074
3672
|
/**
|
|
4075
|
-
* Creates a template from
|
|
3673
|
+
* Creates a template from html.
|
|
4076
3674
|
* @param {string} html
|
|
4077
3675
|
* @param {{ [k: string] : any }?} [modules]
|
|
4078
|
-
* @param {...*} data
|
|
4079
|
-
* @returns
|
|
3676
|
+
* @param {...*} data the data stack, innermost last
|
|
3677
|
+
* @returns {Template}
|
|
4080
3678
|
*/
|
|
4081
3679
|
static fromHtml(html, modules, ...data) {
|
|
4082
3680
|
return new Template(Fragments.fromHtml(html), new ExpressionEvaluator(modules, data));
|
|
4083
3681
|
}
|
|
4084
3682
|
|
|
4085
3683
|
/**
|
|
4086
|
-
* Creates a template from the content of the first
|
|
3684
|
+
* Creates a template from the content of the first element matching the
|
|
3685
|
+
* selector, which is adopted: the template element is left empty.
|
|
4087
3686
|
* @param {string} selector for an HTMLTemplateElement
|
|
4088
3687
|
* @param {{ [k: string] : any }?} [modules]
|
|
4089
|
-
* @param {...*} data
|
|
4090
|
-
* @returns
|
|
3688
|
+
* @param {...*} data the data stack, innermost last
|
|
3689
|
+
* @returns {Template}
|
|
3690
|
+
* @throws when the selector matches no template element
|
|
4091
3691
|
*/
|
|
4092
3692
|
static fromSelector(selector, modules, ...data) {
|
|
4093
3693
|
const templateEl = document.querySelector(selector);
|
|
4094
3694
|
if (!(templateEl instanceof HTMLTemplateElement)) {
|
|
4095
3695
|
throw new Error('template selector does not match any template tag');
|
|
4096
3696
|
}
|
|
4097
|
-
|
|
4098
|
-
return new Template(fragment, new ExpressionEvaluator(modules, data));
|
|
3697
|
+
return Template.fromTemplate(templateEl, modules, ...data);
|
|
4099
3698
|
}
|
|
4100
3699
|
|
|
4101
3700
|
/**
|
|
4102
|
-
* Creates a template from the content of
|
|
3701
|
+
* Creates a template from the content of a template element, which is
|
|
3702
|
+
* adopted: the template element is left empty.
|
|
4103
3703
|
* @param {HTMLTemplateElement} templateEl
|
|
4104
3704
|
* @param {{ [k: string] : any }?} [modules]
|
|
4105
|
-
* @param {...*} data
|
|
4106
|
-
* @returns
|
|
3705
|
+
* @param {...*} data the data stack, innermost last
|
|
3706
|
+
* @returns {Template}
|
|
4107
3707
|
*/
|
|
4108
3708
|
static fromTemplate(templateEl, modules, ...data) {
|
|
4109
3709
|
const fragment = document.adoptNode(templateEl.content);
|
|
@@ -4111,11 +3711,12 @@ class Template {
|
|
|
4111
3711
|
}
|
|
4112
3712
|
|
|
4113
3713
|
/**
|
|
4114
|
-
* Creates a template
|
|
3714
|
+
* Creates a template over a fragment, which is imported afresh on every
|
|
3715
|
+
* render and never modified.
|
|
4115
3716
|
* @param {DocumentFragment} fragment
|
|
4116
3717
|
* @param { { [k: string] : any }? } [modules]
|
|
4117
|
-
* @param {...*} data
|
|
4118
|
-
* @returns
|
|
3718
|
+
* @param {...*} data the data stack, innermost last
|
|
3719
|
+
* @returns {Template}
|
|
4119
3720
|
*/
|
|
4120
3721
|
static fromFragment(fragment, modules, ...data) {
|
|
4121
3722
|
return new Template(fragment, new ExpressionEvaluator(modules, data));
|
|
@@ -4135,28 +3736,32 @@ class Template {
|
|
|
4135
3736
|
* Creates a new Template rendering in another scope: the one way to rebind
|
|
4136
3737
|
* a compiled template to a registry's modules and data.
|
|
4137
3738
|
* @param {ExpressionEvaluator} evaluator
|
|
3739
|
+
* @returns {Template}
|
|
4138
3740
|
*/
|
|
4139
3741
|
withEvaluator(evaluator) {
|
|
4140
3742
|
return new Template(this.#fragment, evaluator);
|
|
4141
3743
|
}
|
|
4142
3744
|
/**
|
|
4143
|
-
* Creates a new Template
|
|
3745
|
+
* Creates a new Template over another fragment, in the same scope.
|
|
4144
3746
|
* @param {DocumentFragment} fragment
|
|
3747
|
+
* @returns {Template}
|
|
4145
3748
|
*/
|
|
4146
3749
|
withFragment(fragment) {
|
|
4147
3750
|
return new Template(fragment, this.#evaluator);
|
|
4148
3751
|
}
|
|
4149
3752
|
/**
|
|
4150
|
-
* Creates a new Template with a
|
|
3753
|
+
* Creates a new Template with a module added, as `ExpressionEvaluator.withModule` does.
|
|
4151
3754
|
* @param {string?} name
|
|
4152
3755
|
* @param {{[k: string]: any}} value
|
|
3756
|
+
* @returns {Template}
|
|
4153
3757
|
*/
|
|
4154
3758
|
withModule(name, value) {
|
|
4155
3759
|
return new Template(this.#fragment, this.#evaluator.withModule(name, value));
|
|
4156
3760
|
}
|
|
4157
3761
|
/**
|
|
4158
|
-
* Creates a new Template with
|
|
3762
|
+
* Creates a new Template with the data pushed as the innermost overlays.
|
|
4159
3763
|
* @param {...*} data
|
|
3764
|
+
* @returns {Template}
|
|
4160
3765
|
*/
|
|
4161
3766
|
withOverlay(...data) {
|
|
4162
3767
|
return new Template(this.#fragment, this.#evaluator.withOverlay(...data));
|
|
@@ -4165,7 +3770,7 @@ class Template {
|
|
|
4165
3770
|
* Evaluates an expression in this template's scope, widened by the overlays.
|
|
4166
3771
|
* @param {string} expression
|
|
4167
3772
|
* @param {...*} data
|
|
4168
|
-
* @returns
|
|
3773
|
+
* @returns {any}
|
|
4169
3774
|
*/
|
|
4170
3775
|
evaluateExpression(expression, ...data) {
|
|
4171
3776
|
return this.#evaluator.withOverlay(...data).evaluateExpression(expression);
|
|
@@ -4174,33 +3779,29 @@ class Template {
|
|
|
4174
3779
|
* Evaluates a templated text, the `{{ }}` form, in this template's scope.
|
|
4175
3780
|
* @param {string} text
|
|
4176
3781
|
* @param {...*} data
|
|
4177
|
-
* @returns the parts
|
|
3782
|
+
* @returns {{ type: symbol, value: any }[]} the parts, as `Expressions.MODE_TEMPLATED` describes
|
|
4178
3783
|
*/
|
|
4179
3784
|
evaluateTemplated(text, ...data) {
|
|
4180
3785
|
return this.#evaluator.withOverlay(...data).evaluateTemplated(text);
|
|
4181
3786
|
}
|
|
4182
3787
|
/**
|
|
4183
|
-
*
|
|
3788
|
+
* The scope this template renders in.
|
|
3789
|
+
* @returns {ExpressionEvaluator}
|
|
4184
3790
|
*/
|
|
4185
3791
|
evaluator() {
|
|
4186
3792
|
return this.#evaluator;
|
|
4187
3793
|
}
|
|
4188
3794
|
/**
|
|
4189
|
-
* Renders the template
|
|
4190
|
-
*
|
|
3795
|
+
* Renders the template into a new fragment, applying the `data-tpl-*`
|
|
3796
|
+
* commands and bindings and the `{{ }}` interpolations.
|
|
3797
|
+
* @returns {DocumentFragment}
|
|
3798
|
+
* @throws {RenderError} naming the node and the directive that failed
|
|
4191
3799
|
*/
|
|
4192
3800
|
render() {
|
|
4193
3801
|
try {
|
|
4194
3802
|
const ops = new NodeOperations();
|
|
4195
3803
|
const imported = document.importNode(this.#fragment, true);
|
|
4196
|
-
const fragment =
|
|
4197
|
-
imported.nodeType === Node.DOCUMENT_FRAGMENT_NODE
|
|
4198
|
-
? imported
|
|
4199
|
-
: (() => {
|
|
4200
|
-
const d = new DocumentFragment();
|
|
4201
|
-
d.appendChild(imported);
|
|
4202
|
-
return d;
|
|
4203
|
-
})();
|
|
3804
|
+
const fragment = imported.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? imported : Fragments.from(imported);
|
|
4204
3805
|
const iterator = document.createNodeIterator(
|
|
4205
3806
|
fragment,
|
|
4206
3807
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
|
|
@@ -4226,8 +3827,6 @@ class Template {
|
|
|
4226
3827
|
try {
|
|
4227
3828
|
CommandsHandler[command](el, value, ops, this.#evaluator);
|
|
4228
3829
|
} catch (ex) {
|
|
4229
|
-
//the directive is popped before it runs, so the open tag no
|
|
4230
|
-
//longer carries it: the frame names it and its expression
|
|
4231
3830
|
throw RenderError.wrap(`Error evaluating data-tpl-${toAttr(command)}="${value}"`, el, ex);
|
|
4232
3831
|
}
|
|
4233
3832
|
if (ops.removed(el)) {
|
|
@@ -4250,17 +3849,13 @@ class Template {
|
|
|
4250
3849
|
el.setAttribute(attributeName, evaluated);
|
|
4251
3850
|
}
|
|
4252
3851
|
} catch (ex) {
|
|
4253
|
-
throw RenderError.wrap(`Error evaluating data-tpl-${
|
|
3852
|
+
throw RenderError.wrap(`Error evaluating data-tpl-${attributeName}="${expression}"`, el, ex);
|
|
4254
3853
|
}
|
|
4255
3854
|
}
|
|
4256
3855
|
}
|
|
4257
3856
|
ops.cleanup();
|
|
4258
3857
|
return fragment;
|
|
4259
3858
|
} catch (ex) {
|
|
4260
|
-
//a command, a text node or a nested render already named the node it
|
|
4261
|
-
//failed on: wrapping again would add a frame for the fragment that
|
|
4262
|
-
//contains it, one per level, serializing the whole template into the
|
|
4263
|
-
//message that survives. Only a failure outside those is framed here
|
|
4264
3859
|
if (ex instanceof RenderError) {
|
|
4265
3860
|
throw ex;
|
|
4266
3861
|
}
|
|
@@ -4268,22 +3863,26 @@ class Template {
|
|
|
4268
3863
|
}
|
|
4269
3864
|
}
|
|
4270
3865
|
/**
|
|
4271
|
-
* Renders this template
|
|
3866
|
+
* Renders this template into the element, replacing its children.
|
|
4272
3867
|
* @param {Element} el
|
|
3868
|
+
* @throws {RenderError}
|
|
4273
3869
|
*/
|
|
4274
3870
|
renderTo(el) {
|
|
4275
3871
|
el.replaceChildren(this.render());
|
|
4276
3872
|
}
|
|
4277
3873
|
/**
|
|
4278
|
-
* Renders this template
|
|
3874
|
+
* Renders this template and appends the result to the element.
|
|
4279
3875
|
* @param {Element} el
|
|
3876
|
+
* @throws {RenderError}
|
|
4280
3877
|
*/
|
|
4281
3878
|
appendTo(el) {
|
|
4282
3879
|
el.appendChild(this.render());
|
|
4283
3880
|
}
|
|
4284
3881
|
/**
|
|
4285
|
-
* Renders this template
|
|
3882
|
+
* Renders this template into the first element matching the selector,
|
|
3883
|
+
* replacing its children; does nothing when none matches.
|
|
4286
3884
|
* @param {string} selector
|
|
3885
|
+
* @throws {RenderError}
|
|
4287
3886
|
*/
|
|
4288
3887
|
renderToSelector(selector) {
|
|
4289
3888
|
const el = document.querySelector(selector);
|
|
@@ -4292,8 +3891,10 @@ class Template {
|
|
|
4292
3891
|
}
|
|
4293
3892
|
}
|
|
4294
3893
|
/**
|
|
4295
|
-
* Renders this template
|
|
3894
|
+
* Renders this template and appends the result to the first element
|
|
3895
|
+
* matching the selector; does nothing when none matches.
|
|
4296
3896
|
* @param {string} selector
|
|
3897
|
+
* @throws {RenderError}
|
|
4297
3898
|
*/
|
|
4298
3899
|
appendToSelector(selector) {
|
|
4299
3900
|
const el = document.querySelector(selector);
|
|
@@ -4317,30 +3918,26 @@ class Template {
|
|
|
4317
3918
|
}
|
|
4318
3919
|
|
|
4319
3920
|
/**
|
|
4320
|
-
* A render failure, one frame per nesting level
|
|
4321
|
-
*
|
|
4322
|
-
*
|
|
4323
|
-
*
|
|
4324
|
-
* the
|
|
4325
|
-
* `node`, so a failure costs no clone and a nested failure does not embed the
|
|
4326
|
-
* page in its own message.
|
|
3921
|
+
* A render failure, one frame per nesting level, chained through `cause` from
|
|
3922
|
+
* the outermost frame down to the error that failed the expression. A frame's
|
|
3923
|
+
* message names what was being evaluated and the node's open tag, with the
|
|
3924
|
+
* attributes it still carries: the directive being evaluated is already off
|
|
3925
|
+
* the tag. The subtree is not in the message; `html` serializes it on demand.
|
|
4327
3926
|
*/
|
|
4328
3927
|
class RenderError extends Error {
|
|
4329
|
-
/**
|
|
4330
|
-
* How many frames a chain keeps. The innermost are the specific ones, so a
|
|
4331
|
-
* deeper nesting drops the outer context rather than the failure site: three
|
|
4332
|
-
* frames name the offending node and the two levels that hold it, which is
|
|
4333
|
-
* the path a reader follows without the page arriving with it.
|
|
4334
|
-
*/
|
|
3928
|
+
/** How many frames a chain keeps: a deeper nesting drops the outermost ones and marks the chain `truncated`. */
|
|
4335
3929
|
static FRAMES = 3;
|
|
4336
3930
|
#node;
|
|
4337
3931
|
#depth;
|
|
4338
|
-
/**
|
|
3932
|
+
/** Whether the chain dropped outer frames to stay within FRAMES. */
|
|
4339
3933
|
truncated = false;
|
|
4340
3934
|
/**
|
|
4341
|
-
* Frames a failure, unless the chain already
|
|
4342
|
-
* cause
|
|
4343
|
-
*
|
|
3935
|
+
* Frames a failure, unless the chain already holds FRAMES frames: then the
|
|
3936
|
+
* cause is returned as it is, marked `truncated`.
|
|
3937
|
+
* @param {string} message
|
|
3938
|
+
* @param {Node} nodeOrFragment the node that failed
|
|
3939
|
+
* @param {any} cause
|
|
3940
|
+
* @returns {RenderError}
|
|
4344
3941
|
*/
|
|
4345
3942
|
static wrap(message, nodeOrFragment, cause) {
|
|
4346
3943
|
if (cause instanceof RenderError && cause.depth >= RenderError.FRAMES) {
|
|
@@ -4349,27 +3946,44 @@ class RenderError extends Error {
|
|
|
4349
3946
|
}
|
|
4350
3947
|
return new RenderError(message, nodeOrFragment, cause);
|
|
4351
3948
|
}
|
|
3949
|
+
/**
|
|
3950
|
+
* @param {string} message
|
|
3951
|
+
* @param {Node} nodeOrFragment the node that failed
|
|
3952
|
+
* @param {any} cause
|
|
3953
|
+
*/
|
|
4352
3954
|
constructor(message, nodeOrFragment, cause) {
|
|
4353
3955
|
super(`${message} in \`${RenderError.describe(nodeOrFragment)}\``, { cause });
|
|
4354
3956
|
this.name = 'RenderError';
|
|
4355
3957
|
this.#node = nodeOrFragment;
|
|
4356
3958
|
this.#depth = (cause instanceof RenderError ? cause.depth : 0) + 1;
|
|
4357
3959
|
}
|
|
4358
|
-
/**
|
|
3960
|
+
/**
|
|
3961
|
+
* How many frames this chain carries, this one included.
|
|
3962
|
+
* @returns {number}
|
|
3963
|
+
*/
|
|
4359
3964
|
get depth() {
|
|
4360
3965
|
return this.#depth;
|
|
4361
3966
|
}
|
|
4362
|
-
/**
|
|
3967
|
+
/**
|
|
3968
|
+
* The node the render failed on, live in the fragment being built.
|
|
3969
|
+
* @returns {Node}
|
|
3970
|
+
*/
|
|
4363
3971
|
get node() {
|
|
4364
3972
|
return this.#node;
|
|
4365
3973
|
}
|
|
4366
|
-
/**
|
|
3974
|
+
/**
|
|
3975
|
+
* The failed node's markup, whitespace trimmed, serialized on each read.
|
|
3976
|
+
* @returns {string}
|
|
3977
|
+
*/
|
|
4367
3978
|
get html() {
|
|
4368
3979
|
return RenderError.stringify(this.#node);
|
|
4369
3980
|
}
|
|
4370
3981
|
/**
|
|
4371
3982
|
* What identifies a node in a frame: an element by its open tag, a text node
|
|
4372
|
-
* by its source, a fragment by the open tags of the elements it holds
|
|
3983
|
+
* by its source, a fragment by the open tags of the elements it holds, cut
|
|
3984
|
+
* at 120 characters.
|
|
3985
|
+
* @param {Node} nodeOrFragment
|
|
3986
|
+
* @returns {string}
|
|
4373
3987
|
*/
|
|
4374
3988
|
static describe(nodeOrFragment) {
|
|
4375
3989
|
if (nodeOrFragment.nodeType === Node.TEXT_NODE) {
|
|
@@ -4388,10 +4002,13 @@ class RenderError extends Error {
|
|
|
4388
4002
|
static #ellipsize(text) {
|
|
4389
4003
|
return text.length > 120 ? `${text.slice(0, 120)}…` : text;
|
|
4390
4004
|
}
|
|
4005
|
+
/**
|
|
4006
|
+
* A node's markup with its whitespace-only text dropped and the rest trimmed.
|
|
4007
|
+
* @param {Node} nodeOrFragment left untouched: a clone is serialized
|
|
4008
|
+
* @returns {string}
|
|
4009
|
+
*/
|
|
4391
4010
|
static stringify(nodeOrFragment) {
|
|
4392
|
-
|
|
4393
|
-
t.content.appendChild(RenderError.#cleanup(nodeOrFragment.cloneNode(true)));
|
|
4394
|
-
return t.innerHTML;
|
|
4011
|
+
return Fragments.toHtml(RenderError.#cleanup(nodeOrFragment.cloneNode(true)));
|
|
4395
4012
|
}
|
|
4396
4013
|
static #cleanup(node) {
|
|
4397
4014
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
@@ -4413,11 +4030,6 @@ class RenderError extends Error {
|
|
|
4413
4030
|
}
|
|
4414
4031
|
}
|
|
4415
4032
|
|
|
4416
|
-
/**
|
|
4417
|
-
* Tracks the elements waiting to render. `ready` resolves once the queue has
|
|
4418
|
-
* drained and never rejects; the promise kept per element resolves when that
|
|
4419
|
-
* element has rendered and rejects with whatever its upgrade threw.
|
|
4420
|
-
*/
|
|
4421
4033
|
class UpgradeQueue {
|
|
4422
4034
|
#q = new Map();
|
|
4423
4035
|
#readyResolve;
|
|
@@ -4429,12 +4041,6 @@ class UpgradeQueue {
|
|
|
4429
4041
|
this.#start();
|
|
4430
4042
|
});
|
|
4431
4043
|
}
|
|
4432
|
-
/**
|
|
4433
|
-
* Waits for the page's readiness: the promise resolves right after the
|
|
4434
|
-
* ftl:ready event is dispatched, and immediately when that moment already
|
|
4435
|
-
* passed.
|
|
4436
|
-
* @returns {Promise<void>}
|
|
4437
|
-
*/
|
|
4438
4044
|
ready() {
|
|
4439
4045
|
return this.#ready;
|
|
4440
4046
|
}
|
|
@@ -4450,13 +4056,8 @@ class UpgradeQueue {
|
|
|
4450
4056
|
}
|
|
4451
4057
|
enqueue(el) {
|
|
4452
4058
|
if (this.#q.has(el)) {
|
|
4453
|
-
//already upgrading, can happen when disconnecting an element
|
|
4454
|
-
//while it's already queued for upgrade (e.g.: ful-form)
|
|
4455
4059
|
return;
|
|
4456
4060
|
}
|
|
4457
|
-
//one entry, two signals: readiness waits on a signal that only ever
|
|
4458
|
-
//resolves, so nothing here attaches a rejection handler to the upgrade
|
|
4459
|
-
//itself and a component that fails is still reported the way it always was
|
|
4460
4061
|
const { promise: finished, resolve: markFinished } = /** @type {PromiseWithResolvers<void>} */ (
|
|
4461
4062
|
Promise.withResolvers()
|
|
4462
4063
|
);
|
|
@@ -4468,11 +4069,6 @@ class UpgradeQueue {
|
|
|
4468
4069
|
});
|
|
4469
4070
|
this.#q.set(el, { upgrade, finished });
|
|
4470
4071
|
}
|
|
4471
|
-
/**
|
|
4472
|
-
* The one fixed-point loop: drains the accepted entries, including the ones
|
|
4473
|
-
* enqueued while waiting, since a component is only queued once its parent
|
|
4474
|
-
* connects it and a single pass would miss everything nested.
|
|
4475
|
-
*/
|
|
4476
4072
|
async #drain(accept, pick) {
|
|
4477
4073
|
for (;;) {
|
|
4478
4074
|
const pending = Array.from(this.#q)
|
|
@@ -4485,22 +4081,25 @@ class UpgradeQueue {
|
|
|
4485
4081
|
}
|
|
4486
4082
|
}
|
|
4487
4083
|
/**
|
|
4488
|
-
* Waits for the whole queue to drain
|
|
4489
|
-
*
|
|
4490
|
-
*
|
|
4084
|
+
* Waits for the whole queue to drain, the upgrades enqueued meanwhile included.
|
|
4085
|
+
* Never rejects: a failed upgrade counts as drained.
|
|
4086
|
+
* @returns {Promise<void>}
|
|
4491
4087
|
*/
|
|
4492
4088
|
settled() {
|
|
4493
4089
|
return this.#drain(() => true, (entry) => entry.finished);
|
|
4494
4090
|
}
|
|
4495
|
-
/**
|
|
4091
|
+
/**
|
|
4092
|
+
* Waits for the accepted upgrades, the ones enqueued meanwhile included,
|
|
4093
|
+
* rejecting with the first that failed.
|
|
4094
|
+
* @param {(el: Element) => boolean} accept
|
|
4095
|
+
* @returns {Promise<void>}
|
|
4096
|
+
*/
|
|
4496
4097
|
upgraded(accept) {
|
|
4497
4098
|
return this.#drain(accept, (entry) => entry.upgrade);
|
|
4498
4099
|
}
|
|
4499
|
-
/** The pending upgrade of one element, undefined when it is not queued. */
|
|
4500
4100
|
whenUpgraded(el) {
|
|
4501
4101
|
return this.#q.get(el)?.upgrade;
|
|
4502
4102
|
}
|
|
4503
|
-
/** The elements whose upgrade is still pending, in queue order. */
|
|
4504
4103
|
pending() {
|
|
4505
4104
|
return Array.from(this.#q.keys());
|
|
4506
4105
|
}
|
|
@@ -4511,8 +4110,8 @@ class UpgradeQueue {
|
|
|
4511
4110
|
* and attribute mappers. Elements defined before configure() are deferred and
|
|
4512
4111
|
* defined by it; from then on every defineElement takes effect immediately.
|
|
4513
4112
|
* The exported `registry` singleton is the page's own; a `new Registry()` is a
|
|
4514
|
-
* separate instance
|
|
4515
|
-
* singleton alone.
|
|
4113
|
+
* separate instance with its own upgrade queue, which dispatches its own
|
|
4114
|
+
* ftl:ready on the document, while Rendering waits on the singleton alone.
|
|
4516
4115
|
*/
|
|
4517
4116
|
class Registry {
|
|
4518
4117
|
#tagToClass = {};
|
|
@@ -4581,9 +4180,12 @@ class Registry {
|
|
|
4581
4180
|
* Registers a custom element under its tag: the class is augmented with its
|
|
4582
4181
|
* BITS (observed attributes, mappers, templates) and handed to the platform.
|
|
4583
4182
|
* Before configure() the definition is deferred, so import order never
|
|
4584
|
-
* matters.
|
|
4183
|
+
* matters. The element resolves its templates and components through this
|
|
4184
|
+
* registry, whichever one a module imports, and its `static config` is read
|
|
4185
|
+
* here, so a page replacing it does so before the definition.
|
|
4585
4186
|
* @param {string} tag
|
|
4586
4187
|
* @param {*} klass a ParsedElement subclass
|
|
4188
|
+
* @returns {Registry} this registry
|
|
4587
4189
|
*/
|
|
4588
4190
|
defineElement(tag, klass) {
|
|
4589
4191
|
if (!this.#configured) {
|
|
@@ -4601,13 +4203,8 @@ class Registry {
|
|
|
4601
4203
|
* ancestors', so a base class declares what every subclass keeps observing
|
|
4602
4204
|
* (a protocol attribute such as Field's disabled claim) and a leaf refines a
|
|
4603
4205
|
* mapping, or moves a name's position, without repeating the whole list.
|
|
4604
|
-
*
|
|
4605
|
-
*
|
|
4606
|
-
* stop can work, since a registered ancestor carries an own BITS of its own,
|
|
4607
|
-
* and nothing above the elements declares anything.
|
|
4608
|
-
*
|
|
4609
|
-
* Everything deriving a component's attribute vocabulary reads it here, so
|
|
4610
|
-
* the runtime and whatever documents it cannot walk the chain differently.
|
|
4206
|
+
* The observed attributes are applied in the composed order, a re-declared
|
|
4207
|
+
* name taking the position of its last declaration.
|
|
4611
4208
|
* @param {*} klass a ParsedElement subclass
|
|
4612
4209
|
* @returns {{ observed: string[], attributes: string[] }}
|
|
4613
4210
|
*/
|
|
@@ -4623,14 +4220,7 @@ class Registry {
|
|
|
4623
4220
|
* The property an observed attribute drives, by the platform's own
|
|
4624
4221
|
* dash-to-camel rule: the one `dataset` applies, so `clear-invalid-on-change`
|
|
4625
4222
|
* would reach `clearInvalidOnChange` the way `data-clear-invalid-on-change`
|
|
4626
|
-
* reaches `dataset.clearInvalidOnChange`.
|
|
4627
|
-
* unchanged, which is what every observed attribute in the library is.
|
|
4628
|
-
*
|
|
4629
|
-
* It exists because the observed tier is the one that becomes properties:
|
|
4630
|
-
* without it an attribute could only be observed if its name happened to be
|
|
4631
|
-
* a usable identifier, which is why every multiword observed attribute here
|
|
4632
|
-
* used to be squashed into one word while the configuration tier, which
|
|
4633
|
-
* never becomes a property, spelled the same idea with a dash.
|
|
4223
|
+
* reaches `dataset.clearInvalidOnChange`.
|
|
4634
4224
|
*
|
|
4635
4225
|
* Only this direction is mapped. A property never derives its attribute: a
|
|
4636
4226
|
* setter reflects through `reflectTo`, naming the attribute it writes.
|
|
@@ -4643,10 +4233,6 @@ class Registry {
|
|
|
4643
4233
|
#augmentAndDefineElement(tag, klass) {
|
|
4644
4234
|
const { observed, attributes } = Registry.declarationsOf(klass);
|
|
4645
4235
|
const { template, templates, slots, mappers, config } = klass;
|
|
4646
|
-
//a name a subclass re-declares takes the subclass's position, which is
|
|
4647
|
-
//how a field whose value setter reads its own shape attributes declares
|
|
4648
|
-
//that its value lands after them: the order the declarations compose in
|
|
4649
|
-
//is the order the base applies them
|
|
4650
4236
|
const declaredNames = observed.map((a) => a.split(':')[0]);
|
|
4651
4237
|
const observedNames = [...new Set(declaredNames.reverse())].reverse();
|
|
4652
4238
|
const attrToMapper = [...attributes, ...observed].reduce((acc, a) => {
|
|
@@ -4665,20 +4251,13 @@ class Registry {
|
|
|
4665
4251
|
const nameToTemplate = Object.fromEntries(namesAndTemplates);
|
|
4666
4252
|
|
|
4667
4253
|
klass.BITS = {
|
|
4668
|
-
//the defining registry travels with the definition: an element resolves
|
|
4669
|
-
//its templates and its components through the registry that defined it,
|
|
4670
|
-
//not through whichever one a module happened to import
|
|
4671
4254
|
registry: this,
|
|
4672
4255
|
enqueue: (el) => this.#upgradeQueue.enqueue(el),
|
|
4673
4256
|
SLOTS: slots,
|
|
4674
|
-
//the class's own constants, overlaid on its templates as `config`:
|
|
4675
|
-
//read here with the rest of the declaration, so a page replacing them
|
|
4676
|
-
//does it before configure() like every other definition-time choice
|
|
4677
4257
|
CONFIG: config,
|
|
4678
4258
|
OBSERVED: observedNames,
|
|
4679
4259
|
DECLARED: [...new Set([...observedNames, ...attributes.map((a) => a.split(':')[0])])],
|
|
4680
4260
|
ATTR_TO_MAPPER: attrToMapper,
|
|
4681
|
-
//resolved once here rather than at every attribute write
|
|
4682
4261
|
ATTR_TO_PROPERTY: Object.fromEntries(observedNames.map((a) => [a, Registry.propertyOf(a)])),
|
|
4683
4262
|
TEMPLATES: nameToTemplate,
|
|
4684
4263
|
};
|
|
@@ -4690,6 +4269,7 @@ class Registry {
|
|
|
4690
4269
|
* as `#fn`.
|
|
4691
4270
|
* @param {string} name
|
|
4692
4271
|
* @param {object} value
|
|
4272
|
+
* @returns {Registry} this registry
|
|
4693
4273
|
*/
|
|
4694
4274
|
defineModule(name, value) {
|
|
4695
4275
|
const module = name ? { [name]: value } : value;
|
|
@@ -4700,6 +4280,7 @@ class Registry {
|
|
|
4700
4280
|
/**
|
|
4701
4281
|
* Replaces the whole module map.
|
|
4702
4282
|
* @param {object} ms
|
|
4283
|
+
* @returns {Registry} this registry
|
|
4703
4284
|
*/
|
|
4704
4285
|
defineModules(ms) {
|
|
4705
4286
|
this.#modules = ms;
|
|
@@ -4711,6 +4292,7 @@ class Registry {
|
|
|
4711
4292
|
* through component().
|
|
4712
4293
|
* @param {string} name
|
|
4713
4294
|
* @param {*} value
|
|
4295
|
+
* @returns {Registry} this registry
|
|
4714
4296
|
*/
|
|
4715
4297
|
defineComponent(name, value) {
|
|
4716
4298
|
this.#components[name] = value;
|
|
@@ -4719,6 +4301,7 @@ class Registry {
|
|
|
4719
4301
|
/**
|
|
4720
4302
|
* Replaces the data stack the templates evaluate over.
|
|
4721
4303
|
* @param {...any} data
|
|
4304
|
+
* @returns {Registry} this registry
|
|
4722
4305
|
*/
|
|
4723
4306
|
defineData(...data) {
|
|
4724
4307
|
this.#data = data;
|
|
@@ -4728,6 +4311,7 @@ class Registry {
|
|
|
4728
4311
|
/**
|
|
4729
4312
|
* Appends to the data stack, the later entry winning a shared name.
|
|
4730
4313
|
* @param {...any} data
|
|
4314
|
+
* @returns {Registry} this registry
|
|
4731
4315
|
*/
|
|
4732
4316
|
defineOverlay(...data) {
|
|
4733
4317
|
this.#data = [...this.#data, ...data];
|
|
@@ -4739,6 +4323,7 @@ class Registry {
|
|
|
4739
4323
|
* `name:type` declaration.
|
|
4740
4324
|
* @param {string} k
|
|
4741
4325
|
* @param {{ unmarshal(str: string|null, name: string, el: Element): any, marshal(value: any, name: string, el: Element): string|null }} v
|
|
4326
|
+
* @returns {Registry} this registry
|
|
4742
4327
|
*/
|
|
4743
4328
|
defineMapper(k, v) {
|
|
4744
4329
|
this.#mappers[k] = v;
|
|
@@ -4747,6 +4332,7 @@ class Registry {
|
|
|
4747
4332
|
/**
|
|
4748
4333
|
* Hands the registry over to the plugin's configure.
|
|
4749
4334
|
* @param {{ configure(registry: Registry): void }} p
|
|
4335
|
+
* @returns {Registry} this registry
|
|
4750
4336
|
*/
|
|
4751
4337
|
plugin(p) {
|
|
4752
4338
|
p.configure(this);
|
|
@@ -4755,6 +4341,7 @@ class Registry {
|
|
|
4755
4341
|
/**
|
|
4756
4342
|
* Defines every element deferred so far; from then on, defineElement takes
|
|
4757
4343
|
* effect immediately.
|
|
4344
|
+
* @returns {Registry} this registry
|
|
4758
4345
|
*/
|
|
4759
4346
|
configure() {
|
|
4760
4347
|
for (const [tag, klass] of Object.entries(this.#tagToClass)) {
|
|
@@ -4766,23 +4353,36 @@ class Registry {
|
|
|
4766
4353
|
}
|
|
4767
4354
|
/**
|
|
4768
4355
|
* Waits for the queued upgrades the filter accepts, rejecting with the first
|
|
4769
|
-
* that failed
|
|
4356
|
+
* that failed, the upgrades enqueued meanwhile included: the rejecting
|
|
4357
|
+
* barrier Rendering is a facade over.
|
|
4770
4358
|
* @param {(el: Element) => boolean} accept
|
|
4359
|
+
* @returns {Promise<void>}
|
|
4771
4360
|
*/
|
|
4772
4361
|
settle(accept) {
|
|
4773
4362
|
return this.#upgradeQueue.upgraded(accept);
|
|
4774
4363
|
}
|
|
4775
|
-
/**
|
|
4364
|
+
/**
|
|
4365
|
+
* The pending upgrade of one element: resolving when it has rendered,
|
|
4366
|
+
* rejecting with what its upgrade threw.
|
|
4367
|
+
* @param {Element} el
|
|
4368
|
+
* @returns {Promise<void>|undefined} undefined when the element is not queued
|
|
4369
|
+
*/
|
|
4776
4370
|
whenUpgraded(el) {
|
|
4777
4371
|
return this.#upgradeQueue.whenUpgraded(el);
|
|
4778
4372
|
}
|
|
4779
|
-
/**
|
|
4373
|
+
/**
|
|
4374
|
+
* The elements whose upgrade is still pending, in queue order.
|
|
4375
|
+
* @returns {Element[]}
|
|
4376
|
+
*/
|
|
4780
4377
|
pending() {
|
|
4781
4378
|
return this.#upgradeQueue.pending();
|
|
4782
4379
|
}
|
|
4783
4380
|
/**
|
|
4784
|
-
* Waits for
|
|
4785
|
-
* dispatched
|
|
4381
|
+
* Waits for this registry's readiness: resolves right after its ftl:ready
|
|
4382
|
+
* event is dispatched on the document, and immediately when that already
|
|
4383
|
+
* happened. Never rejects: a failed upgrade counts as settled, and its
|
|
4384
|
+
* rejection is left unhandled so it still reaches the console and the
|
|
4385
|
+
* page's error reporting.
|
|
4786
4386
|
* @returns {Promise<void>}
|
|
4787
4387
|
*/
|
|
4788
4388
|
ready() {
|
|
@@ -4795,11 +4395,16 @@ class Registry {
|
|
|
4795
4395
|
* The scope every template on this registry renders in: the modules and the
|
|
4796
4396
|
* data stack, as one value. Replaced whenever either is defined, so a holder
|
|
4797
4397
|
* of an older one keeps rendering against what it was handed.
|
|
4398
|
+
* @returns {ExpressionEvaluator}
|
|
4798
4399
|
*/
|
|
4799
4400
|
evaluator() {
|
|
4800
4401
|
return this.#evaluator;
|
|
4801
4402
|
}
|
|
4802
|
-
/**
|
|
4403
|
+
/**
|
|
4404
|
+
* The component registered under the name.
|
|
4405
|
+
* @param {string} name
|
|
4406
|
+
* @returns {any} undefined when none is
|
|
4407
|
+
*/
|
|
4803
4408
|
component(name) {
|
|
4804
4409
|
return this.#components[name];
|
|
4805
4410
|
}
|
|
@@ -4807,33 +4412,59 @@ class Registry {
|
|
|
4807
4412
|
|
|
4808
4413
|
const registry = new Registry();
|
|
4809
4414
|
|
|
4810
|
-
/** The Template factories, each bound to the page registry's scope. */
|
|
4811
4415
|
/** The Template factories bound to the page's own registry: the same four sources, with its modules and data already applied. */
|
|
4812
4416
|
class Templates {
|
|
4417
|
+
/**
|
|
4418
|
+
* @param {string} html
|
|
4419
|
+
* @returns {Template}
|
|
4420
|
+
*/
|
|
4813
4421
|
static fromHtml(html) {
|
|
4814
4422
|
return Template.fromHtml(html).withEvaluator(registry.evaluator());
|
|
4815
4423
|
}
|
|
4424
|
+
/**
|
|
4425
|
+
* @param {string} selector for an HTMLTemplateElement
|
|
4426
|
+
* @returns {Template}
|
|
4427
|
+
*/
|
|
4816
4428
|
static fromSelector(selector) {
|
|
4817
4429
|
return Template.fromSelector(selector).withEvaluator(registry.evaluator());
|
|
4818
4430
|
}
|
|
4431
|
+
/**
|
|
4432
|
+
* @param {HTMLTemplateElement} templateEl consumed: its content is adopted
|
|
4433
|
+
* @returns {Template}
|
|
4434
|
+
*/
|
|
4819
4435
|
static fromTemplate(templateEl) {
|
|
4820
4436
|
return Template.fromTemplate(templateEl).withEvaluator(registry.evaluator());
|
|
4821
4437
|
}
|
|
4438
|
+
/**
|
|
4439
|
+
* @param {DocumentFragment} fragment
|
|
4440
|
+
* @returns {Template}
|
|
4441
|
+
*/
|
|
4822
4442
|
static fromFragment(fragment) {
|
|
4823
4443
|
return Template.fromFragment(fragment).withEvaluator(registry.evaluator());
|
|
4824
4444
|
}
|
|
4825
4445
|
}
|
|
4826
4446
|
|
|
4827
4447
|
/**
|
|
4828
|
-
*
|
|
4829
|
-
*
|
|
4830
|
-
*
|
|
4831
|
-
* leaves a failed component to its own unhandled-rejection report.
|
|
4448
|
+
* Waits for elements queued on the page's `registry` to render. Unlike
|
|
4449
|
+
* `registry.ready()`, these reject when an awaited upgrade fails. An element
|
|
4450
|
+
* defined by another Registry is awaited through that registry instead.
|
|
4832
4451
|
*/
|
|
4833
4452
|
class Rendering {
|
|
4453
|
+
/**
|
|
4454
|
+
* Waits for the element and its descendants, the ones their own renders
|
|
4455
|
+
* enqueue included.
|
|
4456
|
+
* @param {Element} el
|
|
4457
|
+
* @returns {Promise<void>} rejecting with the first upgrade that failed
|
|
4458
|
+
*/
|
|
4834
4459
|
static waitFor(el) {
|
|
4835
4460
|
return registry.settle((child) => el.contains(child));
|
|
4836
4461
|
}
|
|
4462
|
+
/**
|
|
4463
|
+
* Waits for the element's descendants, the element itself excluded: what a
|
|
4464
|
+
* component awaits from inside its own render.
|
|
4465
|
+
* @param {Element} el
|
|
4466
|
+
* @returns {Promise<void>} rejecting with the first upgrade that failed
|
|
4467
|
+
*/
|
|
4837
4468
|
static waitForChildren(el) {
|
|
4838
4469
|
return registry.settle((child) => el !== child && el.contains(child));
|
|
4839
4470
|
}
|
|
@@ -4847,9 +4478,15 @@ class Rendering {
|
|
|
4847
4478
|
* @property {(val: any, name: string, el: Element) => string|null} marshal
|
|
4848
4479
|
*/
|
|
4849
4480
|
|
|
4481
|
+
/**
|
|
4482
|
+
* The base of every fml element. A subclass declares its attributes, slots and
|
|
4483
|
+
* templates in statics and builds its dom in `render`; the base reads the light
|
|
4484
|
+
* slots, reads the declared attributes through their mappers, renders once, and
|
|
4485
|
+
* then forwards observed attribute writes to the matching properties. An element
|
|
4486
|
+
* resolves templates and components through the registry that defined it.
|
|
4487
|
+
*/
|
|
4850
4488
|
class ParsedElement extends HTMLElement {
|
|
4851
4489
|
static BITS = {
|
|
4852
|
-
//an element the registry never defined still answers the page's own
|
|
4853
4490
|
registry,
|
|
4854
4491
|
enqueue: (el) => {},
|
|
4855
4492
|
SLOTS: false,
|
|
@@ -4873,14 +4510,12 @@ class ParsedElement extends HTMLElement {
|
|
|
4873
4510
|
this.internals = this.attachInternals();
|
|
4874
4511
|
}
|
|
4875
4512
|
/**
|
|
4876
|
-
* The
|
|
4877
|
-
*
|
|
4878
|
-
*
|
|
4879
|
-
*
|
|
4880
|
-
*
|
|
4881
|
-
*
|
|
4882
|
-
* A subclass must not redeclare it: a class field with no initializer
|
|
4883
|
-
* assigns undefined after super() returns, which would wipe it.
|
|
4513
|
+
* The element's ElementInternals, attached by the base for every element: a
|
|
4514
|
+
* subclass never calls attachInternals itself, since a second call throws.
|
|
4515
|
+
* A subclass declaring `static formAssociated` gets the form apis here.
|
|
4516
|
+
* A subclass must not redeclare the field: a class field without an
|
|
4517
|
+
* initializer assigns undefined after super() returns, wiping it.
|
|
4518
|
+
* @type {ElementInternals}
|
|
4884
4519
|
*/
|
|
4885
4520
|
internals;
|
|
4886
4521
|
#parsed = false;
|
|
@@ -4897,26 +4532,36 @@ class ParsedElement extends HTMLElement {
|
|
|
4897
4532
|
#mapper(attr) {
|
|
4898
4533
|
const mapper = this.#bits().ATTR_TO_MAPPER[attr];
|
|
4899
4534
|
if (!mapper) {
|
|
4900
|
-
//an attribute the class never declared has no type to read it as:
|
|
4901
|
-
//say so rather than dying on the missing mapper. Content this
|
|
4902
|
-
//element does not own, such as a custom loader's own configuration,
|
|
4903
|
-
//is read with getAttribute, the platform's own answer
|
|
4904
4535
|
throw new Error(
|
|
4905
4536
|
`${this.constructor.name} declares no attribute '${attr}': declare it in static observed or static attributes, or read it with getAttribute`,
|
|
4906
4537
|
);
|
|
4907
4538
|
}
|
|
4908
4539
|
return mapper;
|
|
4909
4540
|
}
|
|
4541
|
+
/**
|
|
4542
|
+
* Reads an attribute value through the mapper it was declared with.
|
|
4543
|
+
* @param {string} attr
|
|
4544
|
+
* @param {string|null} str
|
|
4545
|
+
* @returns {any}
|
|
4546
|
+
* @throws when the class declares no such attribute; read undeclared ones with getAttribute
|
|
4547
|
+
*/
|
|
4910
4548
|
unmarshal(attr, str) {
|
|
4911
4549
|
return this.#mapper(attr).unmarshal(str, attr, this);
|
|
4912
4550
|
}
|
|
4551
|
+
/**
|
|
4552
|
+
* Writes a value as the attribute string its declared mapper produces.
|
|
4553
|
+
* @param {string} attr
|
|
4554
|
+
* @param {any} value
|
|
4555
|
+
* @returns {string|null} null for a value that removes the attribute
|
|
4556
|
+
* @throws when the class declares no such attribute
|
|
4557
|
+
*/
|
|
4913
4558
|
marshal(attr, value) {
|
|
4914
4559
|
return this.#mapper(attr).marshal(value, attr, this);
|
|
4915
4560
|
}
|
|
4916
4561
|
/**
|
|
4917
|
-
*
|
|
4562
|
+
* The registry that defined this element, the page's own for an undefined one.
|
|
4563
|
+
* @returns {typeof registry}
|
|
4918
4564
|
*/
|
|
4919
|
-
/** The registry that defined this element, the page's own for an undefined one. */
|
|
4920
4565
|
get _registry() {
|
|
4921
4566
|
return this.#bits().registry;
|
|
4922
4567
|
}
|
|
@@ -4924,10 +4569,18 @@ class ParsedElement extends HTMLElement {
|
|
|
4924
4569
|
* The component registered under the name on this element's registry, the
|
|
4925
4570
|
* one every ful loader and mapper resolves through.
|
|
4926
4571
|
* @param {string} name
|
|
4572
|
+
* @returns {any} undefined when none is registered
|
|
4927
4573
|
*/
|
|
4928
4574
|
component(name) {
|
|
4929
4575
|
return this.#bits().registry.component(name);
|
|
4930
4576
|
}
|
|
4577
|
+
/**
|
|
4578
|
+
* One of the class's templates, bound to its registry's scope with the
|
|
4579
|
+
* class's `static config` overlaid as `config`.
|
|
4580
|
+
* @param {string} [name] 'default', the `static template`, when omitted
|
|
4581
|
+
* @returns {Template}
|
|
4582
|
+
* @throws when the class declares no template of that name
|
|
4583
|
+
*/
|
|
4931
4584
|
template(name) {
|
|
4932
4585
|
const target = this.#bits().TEMPLATES[name ?? 'default'];
|
|
4933
4586
|
if (!target) {
|
|
@@ -4947,15 +4600,9 @@ class ParsedElement extends HTMLElement {
|
|
|
4947
4600
|
if (oldValue === newValue) {
|
|
4948
4601
|
return;
|
|
4949
4602
|
}
|
|
4950
|
-
//the mute is the attribute being reflected, not the element: a component
|
|
4951
|
-
//that legitimately changes another observed attribute while one reflects
|
|
4952
|
-
//is a change like any other, and used to be swallowed
|
|
4953
4603
|
if (this.#reflecting.has(attr)) {
|
|
4954
4604
|
return;
|
|
4955
4605
|
}
|
|
4956
|
-
//the properties go live only once the render is done: before that, an
|
|
4957
|
-
//attribute write lands in the observed snapshot and the base applies it
|
|
4958
|
-
//with the rest of the declared state
|
|
4959
4606
|
if (!this.#parsed) {
|
|
4960
4607
|
if (this.#pending !== null && attr in this.#pending) {
|
|
4961
4608
|
this.#pending[attr] = this.unmarshal(attr, newValue);
|
|
@@ -4965,14 +4612,18 @@ class ParsedElement extends HTMLElement {
|
|
|
4965
4612
|
this[this.#bits().ATTR_TO_PROPERTY[attr]] = this.unmarshal(attr, newValue);
|
|
4966
4613
|
}
|
|
4967
4614
|
/**
|
|
4968
|
-
* Upgrades once
|
|
4969
|
-
* to writes made while the render is
|
|
4970
|
-
*
|
|
4615
|
+
* Upgrades once, however often the element is connected: reads the declared
|
|
4616
|
+
* attributes, keeps the observed ones open to writes made while the render is
|
|
4617
|
+
* pending, renders, then applies the observed values to their properties in
|
|
4618
|
+
* the order the registry composed them, a base class's before a subclass's.
|
|
4619
|
+
* Only then do attribute writes forward to properties, and the element gains
|
|
4620
|
+
* the `rendered` custom state. A render that throws leaves the forwarding
|
|
4621
|
+
* shut and the state unset.
|
|
4971
4622
|
*
|
|
4972
4623
|
* An observed attribute drives the property the registry's `propertyOf`
|
|
4973
4624
|
* names, so a hyphenated attribute is authored with its dashes and read as
|
|
4974
|
-
* a camelCase property.
|
|
4975
|
-
*
|
|
4625
|
+
* a camelCase property.
|
|
4626
|
+
* @returns {Promise<void>} rejecting with what the render threw
|
|
4976
4627
|
*/
|
|
4977
4628
|
async upgrade() {
|
|
4978
4629
|
if (this.#started) {
|
|
@@ -4980,9 +4631,6 @@ class ParsedElement extends HTMLElement {
|
|
|
4980
4631
|
}
|
|
4981
4632
|
this.#started = true;
|
|
4982
4633
|
const slots = this.#bits().SLOTS ? LightSlots.from(this) : undefined;
|
|
4983
|
-
//both tiers are read here: the observed ones forward to a property once
|
|
4984
|
-
//the render is done, the rest are the element's configuration, read the
|
|
4985
|
-
//one time and never again
|
|
4986
4634
|
const declared = Object.fromEntries(
|
|
4987
4635
|
this.#bits().DECLARED.map((attribute) => [
|
|
4988
4636
|
attribute,
|
|
@@ -4994,21 +4642,11 @@ class ParsedElement extends HTMLElement {
|
|
|
4994
4642
|
this.#pending = declared;
|
|
4995
4643
|
try {
|
|
4996
4644
|
await this.render({ slots });
|
|
4997
|
-
//the declared state reaches the properties once the dom the setters
|
|
4998
|
-
//drive exists, in the order the registry composed the declarations:
|
|
4999
|
-
//a base class's attributes before the subclass's own
|
|
5000
4645
|
const properties = this.#bits().ATTR_TO_PROPERTY;
|
|
5001
4646
|
for (const name of this.#bits().OBSERVED) {
|
|
5002
4647
|
this[properties[name]] = declared[name];
|
|
5003
4648
|
}
|
|
5004
|
-
//the properties go live once the render is done: from here on, an
|
|
5005
|
-
//attribute write forwards to the property. A render that threw
|
|
5006
|
-
//leaves it shut, so a later attribute write cannot reach setters
|
|
5007
|
-
//that assume pieces the failed render never adopted
|
|
5008
4649
|
this.#parsed = true;
|
|
5009
|
-
//the same moment, said to css. :defined is true from the constructor,
|
|
5010
|
-
//which is before the dom exists, so a guard written against it reveals
|
|
5011
|
-
//an element that has nothing in it yet
|
|
5012
4650
|
this.internals.states.add('rendered');
|
|
5013
4651
|
} finally {
|
|
5014
4652
|
this.#pending = null;
|
|
@@ -5019,8 +4657,9 @@ class ParsedElement extends HTMLElement {
|
|
|
5019
4657
|
* drive, and the base applies the declared state onto the properties as
|
|
5020
4658
|
* soon as it returns. A render needing a declared value while it builds
|
|
5021
4659
|
* reads it through `declared(name)`. The slots are undefined for an element
|
|
5022
|
-
* declaring no slots.
|
|
5023
|
-
* @param {{ slots:
|
|
4660
|
+
* declaring no slots. It may be async; the upgrade awaits it.
|
|
4661
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} c
|
|
4662
|
+
* @returns {void | Promise<void>}
|
|
5024
4663
|
*/
|
|
5025
4664
|
render(c) {}
|
|
5026
4665
|
/**
|
|
@@ -5032,12 +4671,9 @@ class ParsedElement extends HTMLElement {
|
|
|
5032
4671
|
* observed name answers the snapshot while the render is pending, kept
|
|
5033
4672
|
* open to attribute writes landing in that window, and the live attribute
|
|
5034
4673
|
* afterwards, the property being live by then.
|
|
5035
|
-
*
|
|
5036
|
-
* The snapshot exists rather than a read of the dom because an element may
|
|
5037
|
-
* write its own observed attributes while it renders, whether a reflection
|
|
5038
|
-
* or a value the platform normalizes on the way in, and what the author
|
|
5039
|
-
* declared is what the base applies, not what the render left behind.
|
|
5040
4674
|
* @param {string} name
|
|
4675
|
+
* @returns {any}
|
|
4676
|
+
* @throws when the class declares no such attribute
|
|
5041
4677
|
*/
|
|
5042
4678
|
declared(name) {
|
|
5043
4679
|
if (name in this.#frozen) {
|
|
@@ -5048,15 +4684,18 @@ class ParsedElement extends HTMLElement {
|
|
|
5048
4684
|
}
|
|
5049
4685
|
return this.unmarshal(name, this.getAttribute(name));
|
|
5050
4686
|
}
|
|
5051
|
-
/**
|
|
4687
|
+
/**
|
|
4688
|
+
* Whether the element's render completed: the moment its properties went
|
|
4689
|
+
* live, which css reads as `:state(rendered)`. Unlike `:defined`, which holds
|
|
4690
|
+
* from the constructor, it is false until the dom exists.
|
|
4691
|
+
* @returns {boolean}
|
|
4692
|
+
*/
|
|
5052
4693
|
get rendered() {
|
|
5053
4694
|
return this.#parsed;
|
|
5054
4695
|
}
|
|
5055
4696
|
/**
|
|
5056
4697
|
* Projects a property back onto its observed attribute, marshalled through
|
|
5057
|
-
* the mapper the attribute was declared with
|
|
5058
|
-
* reaches its attribute, so a setter never has to know how its own type
|
|
5059
|
-
* serializes.
|
|
4698
|
+
* the mapper the attribute was declared with.
|
|
5060
4699
|
*
|
|
5061
4700
|
* A value the attribute already carries is not written at all, so reflecting
|
|
5062
4701
|
* what an attribute write just delivered ends there rather than looping, and
|
|
@@ -5096,9 +4735,13 @@ class ParsedElement extends HTMLElement {
|
|
|
5096
4735
|
const PLACEHOLDER = /\{(\w+)\}/g;
|
|
5097
4736
|
const POSITIONAL = /\{(\d+)\}/g;
|
|
5098
4737
|
/** @param {any} v @returns {v is Record<string, string>} */
|
|
5099
|
-
const isPlainObject = (v) =>
|
|
4738
|
+
const isPlainObject = (v) =>
|
|
4739
|
+
typeof v === 'object' && v !== null && [Object.prototype, null].includes(Object.getPrototypeOf(v));
|
|
4740
|
+
|
|
4741
|
+
/** @param {any} problem @returns {string|undefined} the reason, unless it is missing or blank */
|
|
4742
|
+
const reasonOf = (problem) =>
|
|
4743
|
+
typeof problem?.reason === 'string' && problem.reason.trim() !== '' ? problem.reason : undefined;
|
|
5100
4744
|
|
|
5101
|
-
/** every l10n problem is reported once per session: a missing key in a row template must not flood the console */
|
|
5102
4745
|
const warned = new Set();
|
|
5103
4746
|
const warnOnce = (problem) => {
|
|
5104
4747
|
if (!warned.has(problem)) {
|
|
@@ -5109,11 +4752,7 @@ const warnOnce = (problem) => {
|
|
|
5109
4752
|
|
|
5110
4753
|
const formatters = new BoundedCache(100);
|
|
5111
4754
|
/**
|
|
5112
|
-
* Intl
|
|
5113
|
-
* lookups), while formatting on a built instance is near free: a list rendering
|
|
5114
|
-
* a size per row must not rebuild a NumberFormat per cell, so instances are
|
|
5115
|
-
* memoized by constructor, locale and options.
|
|
5116
|
-
*
|
|
4755
|
+
* An Intl instance, memoized by constructor, locale and options.
|
|
5117
4756
|
* @param {{ new (locale: string | undefined, options: any): any }} ctor
|
|
5118
4757
|
* @param {string | undefined} locale
|
|
5119
4758
|
* @param {any} [options]
|
|
@@ -5132,26 +4771,29 @@ const formatter = (ctor, locale, options) => {
|
|
|
5132
4771
|
class Localization {
|
|
5133
4772
|
/**
|
|
5134
4773
|
* Resolves a message from the translations and interpolates its arguments.
|
|
5135
|
-
* A single plain object argument
|
|
5136
|
-
* ({name}); anything else interpolates positional ones ({0}).
|
|
4774
|
+
* A single plain object argument (an object literal, or one with a null
|
|
4775
|
+
* prototype) interpolates named placeholders ({name}); anything else interpolates positional ones ({0}).
|
|
5137
4776
|
* A plural leaf selects its form through Intl.PluralRules over the
|
|
5138
4777
|
* numeric {count} named argument.
|
|
5139
4778
|
*
|
|
5140
4779
|
* @param {string} key
|
|
5141
4780
|
* @param {...any} args
|
|
4781
|
+
* Each problem (a missing key, placeholder or plural form) is warned once
|
|
4782
|
+
* per page.
|
|
4783
|
+
*
|
|
5142
4784
|
* @this {Receiver}
|
|
5143
4785
|
* @returns {string} the message, or the key itself when the translations do not carry it
|
|
5144
4786
|
*/
|
|
5145
4787
|
static t(key, ...args) {
|
|
5146
4788
|
const messages = this.l10n ?? {};
|
|
5147
|
-
let message = messages[key];
|
|
4789
|
+
let message = Object.hasOwn(messages, key) ? messages[key] : undefined;
|
|
5148
4790
|
if (message === undefined) {
|
|
5149
4791
|
warnOnce(`missing message "${key}"`);
|
|
5150
4792
|
return key;
|
|
5151
4793
|
}
|
|
4794
|
+
const named = args.length === 1 && isPlainObject(args[0]) ? args[0] : null;
|
|
5152
4795
|
if (isPlainObject(message)) {
|
|
5153
|
-
|
|
5154
|
-
if (typeof named.count !== 'number') {
|
|
4796
|
+
if (typeof named?.count !== 'number') {
|
|
5155
4797
|
warnOnce(`plural message "${key}" needs a numeric {count}`);
|
|
5156
4798
|
message = message.other;
|
|
5157
4799
|
} else {
|
|
@@ -5164,10 +4806,9 @@ class Localization {
|
|
|
5164
4806
|
warnOnce(`plural message "${key}" has no "other" form`);
|
|
5165
4807
|
return key;
|
|
5166
4808
|
}
|
|
5167
|
-
if (
|
|
5168
|
-
const named = args[0];
|
|
4809
|
+
if (named) {
|
|
5169
4810
|
return message.replace(PLACEHOLDER, (literal, name) => {
|
|
5170
|
-
if (!(name
|
|
4811
|
+
if (!Object.hasOwn(named, name)) {
|
|
5171
4812
|
warnOnce(`message "${key}" wants {${name}}`);
|
|
5172
4813
|
return literal;
|
|
5173
4814
|
}
|
|
@@ -5193,6 +4834,7 @@ class Localization {
|
|
|
5193
4834
|
* @param {Date | number} value
|
|
5194
4835
|
* @param {Intl.DateTimeFormatOptions} [options]
|
|
5195
4836
|
* @this {Receiver}
|
|
4837
|
+
* @returns {string}
|
|
5196
4838
|
*/
|
|
5197
4839
|
static date(value, options) {
|
|
5198
4840
|
return formatter(Intl.DateTimeFormat, this.locale, options).format(value);
|
|
@@ -5204,6 +4846,7 @@ class Localization {
|
|
|
5204
4846
|
* @param {number} value
|
|
5205
4847
|
* @param {Intl.NumberFormatOptions} [options]
|
|
5206
4848
|
* @this {Receiver}
|
|
4849
|
+
* @returns {string}
|
|
5207
4850
|
*/
|
|
5208
4851
|
static number(value, options) {
|
|
5209
4852
|
return formatter(Intl.NumberFormat, this.locale, options).format(value);
|
|
@@ -5216,6 +4859,7 @@ class Localization {
|
|
|
5216
4859
|
*
|
|
5217
4860
|
* @param {number} value
|
|
5218
4861
|
* @this {Receiver}
|
|
4862
|
+
* @returns {string}
|
|
5219
4863
|
*/
|
|
5220
4864
|
static bytes(value) {
|
|
5221
4865
|
const format = formatter(Intl.NumberFormat, this.locale, { maximumFractionDigits: 2 }).format;
|
|
@@ -5231,16 +4875,37 @@ class Localization {
|
|
|
5231
4875
|
return `${format(value)}B`;
|
|
5232
4876
|
}
|
|
5233
4877
|
|
|
4878
|
+
/**
|
|
4879
|
+
* What went wrong, as text for the reader. A value carrying a non-empty
|
|
4880
|
+
* `problems` array reads as their reasons, one per line, a blank or missing
|
|
4881
|
+
* reason reading as the `failure.no-reason` message. Any other value with a
|
|
4882
|
+
* `message` reads as that message; anything else as its string form, and
|
|
4883
|
+
* null or undefined as the empty string.
|
|
4884
|
+
*
|
|
4885
|
+
* @param {any} value what was thrown or rejected with
|
|
4886
|
+
* @this {Receiver}
|
|
4887
|
+
* @returns {string}
|
|
4888
|
+
*/
|
|
4889
|
+
static failure(value) {
|
|
4890
|
+
if (Array.isArray(value?.problems) && value.problems.length > 0) {
|
|
4891
|
+
return value.problems.map((p) => reasonOf(p) ?? Localization.t.call(this, 'failure.no-reason')).join('\n');
|
|
4892
|
+
}
|
|
4893
|
+
if (value?.message !== undefined) {
|
|
4894
|
+
return String(value.message);
|
|
4895
|
+
}
|
|
4896
|
+
return value == null ? '' : String(value);
|
|
4897
|
+
}
|
|
4898
|
+
|
|
5234
4899
|
/**
|
|
5235
4900
|
* An imperative facade over the module functions, resolving the translations
|
|
5236
|
-
* and the locale from the registry overlays on every call
|
|
4901
|
+
* and the locale from the registry overlays on every call, the same lookup a
|
|
4902
|
+
* template makes: a facade taken at module scope, before the plugin
|
|
4903
|
+
* configures, still sees the translations.
|
|
5237
4904
|
*
|
|
5238
4905
|
* @param {{ locale?: string }} [overrides] an explicit locale, winning over the registry one
|
|
4906
|
+
* @returns {{ t: (key: string, ...args: any[]) => string, date: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string, number: (value: number, options?: Intl.NumberFormatOptions) => string, bytes: (value: number) => string, failure: (value: any) => string }}
|
|
5239
4907
|
*/
|
|
5240
4908
|
static of(overrides = {}) {
|
|
5241
|
-
//resolved per call, not per facade: a module-scope `Localization.of()` is
|
|
5242
|
-
//bound before the plugin configures. The registry's own evaluator does the
|
|
5243
|
-
//lookup, so this cannot drift from what a template sees
|
|
5244
4909
|
const resolve = (prop) => registry.evaluator().resolve(prop);
|
|
5245
4910
|
/** @param {any} fn */
|
|
5246
4911
|
const bind =
|
|
@@ -5252,6 +4917,7 @@ class Localization {
|
|
|
5252
4917
|
date: bind(Localization.date),
|
|
5253
4918
|
number: bind(Localization.number),
|
|
5254
4919
|
bytes: bind(Localization.bytes),
|
|
4920
|
+
failure: bind(Localization.failure),
|
|
5255
4921
|
};
|
|
5256
4922
|
}
|
|
5257
4923
|
}
|