ata-validator 1.34.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -15
- package/build.d.ts +23 -0
- package/build.mjs +4 -0
- package/compiled.d.ts +17 -0
- package/compiled.js +7 -0
- package/compiled.mjs +3 -0
- package/index.browser.mjs +3 -2
- package/index.d.ts +6 -0
- package/index.js +741 -3035
- package/index.mjs +1 -1
- package/index.node.mjs +10 -0
- package/lib/aot-build.js +46 -0
- package/lib/buffer-gate.js +0 -1
- package/lib/compiled.js +96 -0
- package/lib/defaults.js +88 -0
- package/lib/enrich-error.js +7 -0
- package/lib/formats-source.js +323 -0
- package/lib/formats.js +1 -317
- package/lib/interpreter.js +4 -4
- package/lib/js-compiler.js +216 -128
- package/lib/rejections.js +329 -0
- package/lib/schema-order.js +53 -3
- package/lib/validator-core.js +2031 -0
- package/lib/version.js +1 -1
- package/lib/vocabularies.js +1 -2
- package/package.json +24 -11
package/lib/formats.js
CHANGED
|
@@ -368,7 +368,6 @@ function uri (s) {
|
|
|
368
368
|
// than the engine on the common case, which is why it is not the first answer.
|
|
369
369
|
const NON_PRINTABLE = /[^\u0021-\u007e]/;
|
|
370
370
|
|
|
371
|
-
|
|
372
371
|
// RFC 3986 allows these ASCII characters in a URI and nothing else: the
|
|
373
372
|
// unreserved set, the delimiters, and "%" when it introduces two hex digits.
|
|
374
373
|
// The printable characters missing from that list are the ones this rejects:
|
|
@@ -394,12 +393,6 @@ function uriChars (s, from) {
|
|
|
394
393
|
}
|
|
395
394
|
return true;
|
|
396
395
|
}
|
|
397
|
-
const uriCharsSource = (v, from) =>
|
|
398
|
-
`for(let _ri=${from};_ri<${v}.length;_ri++){const _rc=${v}.charCodeAt(_ri);` +
|
|
399
|
-
'if(_rc<33||_rc>126||_rc===34||_rc===60||_rc===62||_rc===92||_rc===94||_rc===96||_rc===123||_rc===124||_rc===125)return false;' +
|
|
400
|
-
`if(_rc===37){const _h1=${v}.charCodeAt(_ri+1),_h2=${v}.charCodeAt(_ri+2);` +
|
|
401
|
-
'if(!((_h1>=48&&_h1<=57)||(_h1>=97&&_h1<=102)||(_h1>=65&&_h1<=70))||' +
|
|
402
|
-
'!((_h2>=48&&_h2<=57)||(_h2>=97&&_h2<=102)||(_h2>=65&&_h2<=70)))return false;_ri+=2}}';
|
|
403
396
|
|
|
404
397
|
function allDigits (s, from, to) {
|
|
405
398
|
for (let i = from; i < to; i++) {
|
|
@@ -464,21 +457,6 @@ function uriAuthority (s, start) {
|
|
|
464
457
|
if (firstColon !== lastColon) return false;
|
|
465
458
|
return allDigits(s, lastColon + 1, authEnd);
|
|
466
459
|
}
|
|
467
|
-
const uriAuthoritySource = (v, start) =>
|
|
468
|
-
`if(${v}.charCodeAt(${start})===47&&${v}.charCodeAt(${start}+1)===47){` +
|
|
469
|
-
`let _ae=${v}.length;` +
|
|
470
|
-
`for(let _ai=${start}+2;_ai<${v}.length;_ai++){const _ac=${v}.charCodeAt(_ai);` +
|
|
471
|
-
'if(_ac===47||_ac===63||_ac===35){_ae=_ai;break}}' +
|
|
472
|
-
`const _au=${v}.slice(${start}+2,_ae);const _aat=_au.lastIndexOf('@');` +
|
|
473
|
-
'if(_aat!==-1&&/[[\\]]/.test(_au.slice(0,_aat)))return false;' +
|
|
474
|
-
'const _hp=_aat===-1?_au:_au.slice(_aat+1);' +
|
|
475
|
-
'if(_hp.charCodeAt(0)===91){const _cl=_hp.indexOf("]");' +
|
|
476
|
-
'if(_cl===-1)return false;const _rs=_hp.slice(_cl+1);' +
|
|
477
|
-
'if(_rs!==""){if(_rs.charCodeAt(0)!==58||!/^[0-9]*$/.test(_rs.slice(1)))return false}}' +
|
|
478
|
-
'else{const _co=_hp.lastIndexOf(":");' +
|
|
479
|
-
'if(_co!==-1){if(_hp.indexOf(":")!==_co)return false;' +
|
|
480
|
-
'if(!/^[0-9]*$/.test(_hp.slice(_co+1)))return false}}}';
|
|
481
|
-
|
|
482
460
|
|
|
483
461
|
// An IRI is a URI that also admits non-ASCII. The ASCII rules are identical,
|
|
484
462
|
// so the same character test runs with everything above 0x7e allowed through.
|
|
@@ -494,12 +472,6 @@ function iriChars (s, from) {
|
|
|
494
472
|
}
|
|
495
473
|
return true;
|
|
496
474
|
}
|
|
497
|
-
const iriCharsSource = (v, from) =>
|
|
498
|
-
`for(let _ii=${from};_ii<${v}.length;_ii++){const _ic=${v}.charCodeAt(_ii);` +
|
|
499
|
-
'if(_ic===127||(_ic<127&&(_ic<33||_ic===34||_ic===60||_ic===62||_ic===92||_ic===94||_ic===96||_ic===123||_ic===124||_ic===125)))return false;' +
|
|
500
|
-
`if(_ic===37){const _j1=${v}.charCodeAt(_ii+1),_j2=${v}.charCodeAt(_ii+2);` +
|
|
501
|
-
'if(!((_j1>=48&&_j1<=57)||(_j1>=97&&_j1<=102)||(_j1>=65&&_j1<=70))||' +
|
|
502
|
-
'!((_j2>=48&&_j2<=57)||(_j2>=97&&_j2<=102)||(_j2>=65&&_j2<=70)))return false;_ii+=2}}';
|
|
503
475
|
|
|
504
476
|
function iri (s) {
|
|
505
477
|
const n = s.length;
|
|
@@ -516,17 +488,7 @@ function iri (s) {
|
|
|
516
488
|
if (colon === -1) return false;
|
|
517
489
|
return iriChars(s, colon + 1) && uriAuthority(s, colon + 1);
|
|
518
490
|
}
|
|
519
|
-
function iriSource (v, isStr) {
|
|
520
|
-
return guard(v, isStr, `const _n=${v}.length;if(_n===0)return false;` +
|
|
521
|
-
`const _f=${v}.charCodeAt(0);if(!((_f>=97&&_f<=122)||(_f>=65&&_f<=90)))return false;` +
|
|
522
|
-
`let _co=-1;for(let _i=1;_i<_n;_i++){const _c=${v}.charCodeAt(_i);if(_c===58){_co=_i;break}` +
|
|
523
|
-
`if(!((_c>=48&&_c<=57)||(_c>=97&&_c<=122)||(_c>=65&&_c<=90)||_c===43||_c===45||_c===46))return false}` +
|
|
524
|
-
`if(_co===-1)return false;` +
|
|
525
|
-
iriCharsSource(v, '_co+1') +
|
|
526
|
-
uriAuthoritySource(v, '_co+1'));
|
|
527
|
-
}
|
|
528
491
|
function iriReference (s) { return iriChars(s, 0); }
|
|
529
|
-
function iriReferenceSource (v, isStr) { return guard(v, isStr, iriCharsSource(v, '0')); }
|
|
530
492
|
|
|
531
493
|
// An internationalised mailbox differs from a mailbox only in admitting
|
|
532
494
|
// non-ASCII on both sides. The separator stays the ASCII "@": a fullwidth one
|
|
@@ -552,25 +514,6 @@ function idnEmail (s) {
|
|
|
552
514
|
}
|
|
553
515
|
return true;
|
|
554
516
|
}
|
|
555
|
-
function idnEmailSource (v, isStr) {
|
|
556
|
-
const inner =
|
|
557
|
-
`const _at=${v}.lastIndexOf('@');` +
|
|
558
|
-
`if(_at<=0||_at===${v}.length-1)return false;` +
|
|
559
|
-
`const _lp=${v}.slice(0,_at),_dm=${v}.slice(_at+1);` +
|
|
560
|
-
`if(_lp.charCodeAt(0)===34){if(_lp.length<2||_lp.charCodeAt(_lp.length-1)!==34||_dm.length===0)return false}` +
|
|
561
|
-
`else{` +
|
|
562
|
-
`if(_lp.charCodeAt(0)===46||_lp.charCodeAt(_lp.length-1)===46)return false;` +
|
|
563
|
-
`if(_lp.indexOf('..')!==-1)return false;` +
|
|
564
|
-
`if(_dm.charCodeAt(0)===91){if(_dm.charCodeAt(_dm.length-1)!==93||_dm.length<=2)return false}` +
|
|
565
|
-
`else{` +
|
|
566
|
-
`if(_dm.charCodeAt(0)===46||_dm.charCodeAt(_dm.length-1)===46)return false;` +
|
|
567
|
-
`if(_dm.indexOf('..')!==-1)return false;` +
|
|
568
|
-
`for(let _di=0;_di<_dm.length;_di++){const _dc=_dm.charCodeAt(_di);` +
|
|
569
|
-
`if(_dc<=32||_dc===127||_dc===64)return false}` +
|
|
570
|
-
`}` +
|
|
571
|
-
`}`;
|
|
572
|
-
return isStr ? `{${inner}}` : `if(typeof ${v}==='string'){${inner}}`;
|
|
573
|
-
}
|
|
574
517
|
|
|
575
518
|
function noReserved (s, from) {
|
|
576
519
|
if (!NON_PRINTABLE.test(s)) return true;
|
|
@@ -585,18 +528,6 @@ function noReserved (s, from) {
|
|
|
585
528
|
return true;
|
|
586
529
|
}
|
|
587
530
|
|
|
588
|
-
// Source twin of noReserved, same two tiers. `from` is an expression for the
|
|
589
|
-
// first index the loop reads; the variable names stay clear of the ones the
|
|
590
|
-
// other format emitters use.
|
|
591
|
-
function noReservedSource (v, from) {
|
|
592
|
-
return `if(/[^\\u0021-\\u007e]/.test(${v})){` +
|
|
593
|
-
`for(let _ri=${from};_ri<${v}.length;_ri++){const _rc=${v}.charCodeAt(_ri);` +
|
|
594
|
-
'if(_rc>32&&_rc<127)continue;' +
|
|
595
|
-
'if(_rc<=32||_rc===127)return false;' +
|
|
596
|
-
'if(_rc===160||_rc===5760||(_rc>=8192&&_rc<=8202)||_rc===8232||' +
|
|
597
|
-
'_rc===8233||_rc===8239||_rc===8287||_rc===12288||_rc===65279)return false}}';
|
|
598
|
-
}
|
|
599
|
-
|
|
600
531
|
// 8-4-4-4-12 hexadecimal digits. The four hyphens are read by index, then
|
|
601
532
|
// each run of hex digits is read with fixed bounds, so no character pays for a
|
|
602
533
|
// test of where it sits. A digit is one unsigned compare and a letter is one
|
|
@@ -679,162 +610,6 @@ function uriReference (s) {
|
|
|
679
610
|
return uriChars(s, 0);
|
|
680
611
|
}
|
|
681
612
|
|
|
682
|
-
// Source twins. `v` is the expression holding the string; when `isStr` is
|
|
683
|
-
// false the check is wrapped in a typeof guard, matching FORMAT_CODEGEN's
|
|
684
|
-
// convention. Each returns a statement that `return false`s on mismatch.
|
|
685
|
-
function guard (v, isStr, body) { return isStr ? `{${body}}` : `if(typeof ${v}==='string'){${body}}`; }
|
|
686
|
-
|
|
687
|
-
function dateSource (v, isStr) {
|
|
688
|
-
return guard(v, isStr, `if(${v}.length!==10)return false;for(let _i=0;_i<10;_i++){const _c=${v}.charCodeAt(_i);if(_i===4||_i===7){if(_c!==45)return false}else if(_c<48||_c>57)return false}const _m=(${v}.charCodeAt(5)-48)*10+(${v}.charCodeAt(6)-48),_d=(${v}.charCodeAt(8)-48)*10+(${v}.charCodeAt(9)-48);if(_m<1||_m>12||_d<1)return false;const _y=(${v}.charCodeAt(0)-48)*1000+(${v}.charCodeAt(1)-48)*100+(${v}.charCodeAt(2)-48)*10+(${v}.charCodeAt(3)-48);const _dim=_m===2?(((_y%4===0&&_y%100!==0)||_y%400===0)?29:28):((_m===4||_m===6||_m===9||_m===11)?30:31);if(_d>_dim)return false`);
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
function dateTimeSource (v, isStr) {
|
|
692
|
-
return guard(v, isStr, `const _n=${v}.length;if(_n<20)return false;` +
|
|
693
|
-
`if(${v}.charCodeAt(4)!==45||${v}.charCodeAt(7)!==45)return false;` +
|
|
694
|
-
`const _sep=${v}.charCodeAt(10);if(_sep!==84&&_sep!==116)return false;` +
|
|
695
|
-
`if(${v}.charCodeAt(13)!==58||${v}.charCodeAt(16)!==58)return false;` +
|
|
696
|
-
`const _y0=${v}.charCodeAt(0)-48,_y1=${v}.charCodeAt(1)-48,_y2=${v}.charCodeAt(2)-48,_y3=${v}.charCodeAt(3)-48;` +
|
|
697
|
-
'if((_y0>>>0)>9||(_y1>>>0)>9||(_y2>>>0)>9||(_y3>>>0)>9)return false;' +
|
|
698
|
-
'const _y=_y0*1000+_y1*100+_y2*10+_y3;' +
|
|
699
|
-
`const _mo0=${v}.charCodeAt(5)-48,_mo1=${v}.charCodeAt(6)-48;` +
|
|
700
|
-
'if((_mo0>>>0)>9||(_mo1>>>0)>9)return false;const _mo=_mo0*10+_mo1;if(_mo<1||_mo>12)return false;' +
|
|
701
|
-
`const _dm=_mo===2?(((_y%4===0&&_y%100!==0)||_y%400===0)?29:28):(_mo===4||_mo===6||_mo===9||_mo===11?30:31);` +
|
|
702
|
-
`const _d0=${v}.charCodeAt(8)-48,_d1=${v}.charCodeAt(9)-48;` +
|
|
703
|
-
'if((_d0>>>0)>9||(_d1>>>0)>9)return false;const _d=_d0*10+_d1;if(_d<1||_d>_dm)return false;' +
|
|
704
|
-
`const _h0=${v}.charCodeAt(11)-48,_h1=${v}.charCodeAt(12)-48;` +
|
|
705
|
-
'if((_h0>>>0)>9||(_h1>>>0)>9||_h0*10+_h1>23)return false;' +
|
|
706
|
-
`const _mi0=${v}.charCodeAt(14)-48,_mi1=${v}.charCodeAt(15)-48;` +
|
|
707
|
-
'if((_mi0>>>0)>5||(_mi1>>>0)>9)return false;' +
|
|
708
|
-
`const _se0=${v}.charCodeAt(17)-48,_se1=${v}.charCodeAt(18)-48;` +
|
|
709
|
-
'if((_se0>>>0)>6||(_se1>>>0)>9||_se0*10+_se1>60)return false;' +
|
|
710
|
-
`let _i2=19;if(${v}.charCodeAt(19)===46){_i2=20;const _st=_i2;while(_i2<_n){const _c2=${v}.charCodeAt(_i2);if(_c2<48||_c2>57)break;_i2++}if(_i2===_st)return false}` +
|
|
711
|
-
`const _tz=${v}.charCodeAt(_i2);let _dtoff=0;` +
|
|
712
|
-
`if(_tz===90||_tz===122){if(_i2!==_n-1)return false}` +
|
|
713
|
-
`else{if(_tz!==43&&_tz!==45)return false;if(_n-_i2!==6)return false;` +
|
|
714
|
-
`const _oh=${v}.charCodeAt(_i2+1),_oh2=${v}.charCodeAt(_i2+2),_om=${v}.charCodeAt(_i2+4),_om2=${v}.charCodeAt(_i2+5);` +
|
|
715
|
-
`if(_oh<48||_oh>57||_oh2<48||_oh2>57||_om<48||_om>57||_om2<48||_om2>57)return false;` +
|
|
716
|
-
`if(${v}.charCodeAt(_i2+3)!==58)return false;` +
|
|
717
|
-
`const _ohv=(_oh-48)*10+(_oh2-48),_omv=(_om-48)*10+(_om2-48);` +
|
|
718
|
-
`if(_ohv>23||_omv>59)return false;` +
|
|
719
|
-
`_dtoff=(_tz===43?1:-1)*(_ohv*60+_omv)}` +
|
|
720
|
-
`if(_se0*10+_se1===60){` +
|
|
721
|
-
`const _dtu=(((_h0*10+_h1)*60+(_mi0*10+_mi1)-_dtoff)%1440+1440)%1440;` +
|
|
722
|
-
`if(_dtu!==1439)return false}`);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// The scan, over a range of the string given as source expressions. The email
|
|
726
|
-
// check reads its domain half through this, without slicing it out, which was an
|
|
727
|
-
// allocation on every call.
|
|
728
|
-
//
|
|
729
|
-
// A separate function rather than optional parameters on hostnameSource: the code
|
|
730
|
-
// generator calls every entry of its format table as `fn(v, isStr, ctx)`, so a
|
|
731
|
-
// third parameter here would silently receive a context object and emit
|
|
732
|
-
// `_st=[object Object]`. That declines the whole compile, which is how it was
|
|
733
|
-
// found.
|
|
734
|
-
function hostnameRangeSource (v, st, en) {
|
|
735
|
-
return `const _st=${st},_en=${en},_n=_en-_st;if(_n===0||_n>253)return false;let _ll=0,_pv=46;` +
|
|
736
|
-
`for(let _i=_st;_i<_en;_i++){const _c=${v}.charCodeAt(_i);` +
|
|
737
|
-
`if(_c===46){if(_ll===0||_pv===45)return false;_ll=0;_pv=_c;continue}` +
|
|
738
|
-
`const _an=(_c>=48&&_c<=57)||(_c>=97&&_c<=122)||(_c>=65&&_c<=90);` +
|
|
739
|
-
`if(!_an&&_c!==45)return false;` +
|
|
740
|
-
`if(_c===45&&_pv===46)return false;` +
|
|
741
|
-
`if(++_ll>63)return false;_pv=_c}` +
|
|
742
|
-
`if(_ll===0||_pv===45)return false`;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
function hostnameSource (v, isStr) {
|
|
746
|
-
return guard(v, isStr, hostnameRangeSource(v, '0', `${v}.length`));
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
function uuidSource (v, isStr) {
|
|
750
|
-
const run = (from, to) => `for(let _ui=${from};_ui<${to};_ui++){const _uc=${v}.charCodeAt(_ui);` +
|
|
751
|
-
'if(!((_uc-48>>>0)<10||((_uc|32)-97>>>0)<6))return false}';
|
|
752
|
-
return guard(v, isStr, `if(${v}.length!==36)return false;` +
|
|
753
|
-
`if(${v}.charCodeAt(8)!==45||${v}.charCodeAt(13)!==45||` +
|
|
754
|
-
`${v}.charCodeAt(18)!==45||${v}.charCodeAt(23)!==45)return false;` +
|
|
755
|
-
run(0, 8) + run(9, 13) + run(14, 18) + run(19, 23) + run(24, 36));
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
function timeSource (v, isStr) {
|
|
759
|
-
return guard(v, isStr, `const _n=${v}.length;if(_n<8)return false;` +
|
|
760
|
-
`const _h1=${v}.charCodeAt(0)-48,_h2=${v}.charCodeAt(1)-48;` +
|
|
761
|
-
'if((_h1>>>0)>9||(_h2>>>0)>9||_h1*10+_h2>23)return false;' +
|
|
762
|
-
`if(${v}.charCodeAt(2)!==58||${v}.charCodeAt(5)!==58)return false;` +
|
|
763
|
-
`const _m1=${v}.charCodeAt(3)-48,_m2=${v}.charCodeAt(4)-48;` +
|
|
764
|
-
'if((_m1>>>0)>5||(_m2>>>0)>9)return false;' +
|
|
765
|
-
`const _s1=${v}.charCodeAt(6)-48,_s2=${v}.charCodeAt(7)-48;` +
|
|
766
|
-
'if((_s1>>>0)>6||(_s2>>>0)>9||_s1*10+_s2>60)return false;' +
|
|
767
|
-
`let _ti=8;if(_ti<_n&&${v}.charCodeAt(_ti)===46){_ti++;const _tf=_ti;` +
|
|
768
|
-
`while(_ti<_n){const _tc=${v}.charCodeAt(_ti)-48;if((_tc>>>0)>9)break;_ti++}` +
|
|
769
|
-
'if(_ti===_tf)return false}' +
|
|
770
|
-
'if(_ti===_n)return false;' +
|
|
771
|
-
`const _tz=${v}.charCodeAt(_ti);let _off=0;` +
|
|
772
|
-
'if(_tz===90||_tz===122){if(_ti!==_n-1)return false}' +
|
|
773
|
-
'else{if(_tz!==43&&_tz!==45)return false;' +
|
|
774
|
-
`if(_n-_ti!==6||${v}.charCodeAt(_ti+3)!==58)return false;` +
|
|
775
|
-
`if((${v}.charCodeAt(_ti+1)-48>>>0)>9||(${v}.charCodeAt(_ti+2)-48>>>0)>9||` +
|
|
776
|
-
`(${v}.charCodeAt(_ti+4)-48>>>0)>9||(${v}.charCodeAt(_ti+5)-48>>>0)>9)return false;` +
|
|
777
|
-
`const _oh=(${v}.charCodeAt(_ti+1)-48)*10+(${v}.charCodeAt(_ti+2)-48),` +
|
|
778
|
-
`_om=(${v}.charCodeAt(_ti+4)-48)*10+(${v}.charCodeAt(_ti+5)-48);` +
|
|
779
|
-
'if(_oh>23||_om>59)return false;' +
|
|
780
|
-
'_off=(_tz===43?1:-1)*(_oh*60+_om)}' +
|
|
781
|
-
'if(_s1*10+_s2===60){' +
|
|
782
|
-
'const _u=(((_h1*10+_h2)*60+(_m1*10+_m2)-_off)%1440+1440)%1440;' +
|
|
783
|
-
'if(_u!==1439)return false}');
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// The same walk as `uri` above, as source, for the code generator to hoist
|
|
787
|
-
// once per compiled function and call. Two copies of one algorithm is what
|
|
788
|
-
// this file has always done for every format, so they sit together here and
|
|
789
|
-
// tests/test_uri_helper_parity.js holds them to the same answer over a corpus
|
|
790
|
-
// built from the walk's own boundaries.
|
|
791
|
-
const URI_HELPER_TABLES = 'const _uct=new Uint8Array(128);for(let _i=33;_i<127;_i++)_uct[_i]=1;' +
|
|
792
|
-
'_uct[34]=_uct[60]=_uct[62]=_uct[92]=_uct[94]=_uct[96]=_uct[123]=_uct[124]=_uct[125]=0;' +
|
|
793
|
-
'const _uch=new Uint8Array(128);for(let _i=48;_i<58;_i++)_uch[_i]=1;' +
|
|
794
|
-
'for(let _i=97;_i<103;_i++)_uch[_i]=1;for(let _i=65;_i<71;_i++)_uch[_i]=1;' +
|
|
795
|
-
'const _ucs=new Uint8Array(128);for(let _i=48;_i<58;_i++)_ucs[_i]=1;' +
|
|
796
|
-
'for(let _i=97;_i<123;_i++)_ucs[_i]=1;for(let _i=65;_i<91;_i++)_ucs[_i]=1;' +
|
|
797
|
-
'_ucs[43]=1;_ucs[45]=1;_ucs[46]=1;const _ufa=/' + URI_FAST.source + '/';
|
|
798
|
-
const URI_HELPER_BODY = 'if(_ufa.test(_s))return true;const _n=_s.length;if(_n===0)return false;let _c=_s.charCodeAt(0);if(_c>127||_ucs[_c]===0||(_c>=48&&_c<=57)||_c===43||_c===45||_c===46)return false;let _co=-1;for(let _i=1;_i<_n;_i++){_c=_s.charCodeAt(_i);if(_c===58){_co=_i;break}if(_c>127||_ucs[_c]===0)return false}if(_co===-1)return false;let _i=_co+1;let _ae=_n;if(_s.charCodeAt(_i)===47&&_s.charCodeAt(_i+1)===47){const _as=_i+2;let _at=-1,_fc=-1,_lc=-1,_br=0,_ba=0,_hs=_as;_ae=-1;for(_i=_as;_i<_n;_i++){_c=_s.charCodeAt(_i);if(_c>127||_uct[_c]===0)return false;if(_c===47||_c===63||_c===35){_ae=_i;break}if(_c===37){const _h1=_s.charCodeAt(_i+1),_h2=_s.charCodeAt(_i+2);if(!(_h1<=127)||!(_h2<=127)||_uch[_h1]===0||_uch[_h2]===0)return false;_i+=2;continue}if(_c===64){_ba=_br;_at=_i;_fc=-1;_lc=-1;_hs=_i+1}else if(_c===58){if(_fc===-1)_fc=_i;_lc=_i}else if(_c===91||_c===93){_br=1}}if(_ae===-1)_ae=_n;if(_at!==-1&&_ba)return false;if(_s.charCodeAt(_hs)===91){let _cl=-1;for(let _j=_hs+1;_j<_ae;_j++){if(_s.charCodeAt(_j)===93){_cl=_j;break}}if(_cl===-1)return false;if(_cl+1!==_ae){if(_s.charCodeAt(_cl+1)!==58)return false;for(let _j=_cl+2;_j<_ae;_j++){const _d=_s.charCodeAt(_j);if(_d<48||_d>57)return false}}}else if(_lc!==-1){if(_fc!==_lc)return false;for(let _j=_lc+1;_j<_ae;_j++){const _d=_s.charCodeAt(_j);if(_d<48||_d>57)return false}}_i=_ae}for(;_i<_n;_i++){_c=_s.charCodeAt(_i);if(_c>127||_uct[_c]===0)return false;if(_c===37){const _h1=_s.charCodeAt(_i+1),_h2=_s.charCodeAt(_i+2);if(!(_h1<=127)||!(_h2<=127)||_uch[_h1]===0||_uch[_h2]===0)return false;_i+=2}}return true;';
|
|
799
|
-
const uriHelperSource = (name) =>
|
|
800
|
-
URI_HELPER_TABLES + ';function ' + name + '(_s){' + URI_HELPER_BODY + '}';
|
|
801
|
-
|
|
802
|
-
function uriSource (v, isStr) {
|
|
803
|
-
return guard(v, isStr, `const _n=${v}.length;if(_n===0)return false;` +
|
|
804
|
-
`const _f=${v}.charCodeAt(0);if(!((_f>=97&&_f<=122)||(_f>=65&&_f<=90)))return false;` +
|
|
805
|
-
`let _co=-1;for(let _i=1;_i<_n;_i++){const _c=${v}.charCodeAt(_i);if(_c===58){_co=_i;break}` +
|
|
806
|
-
`if(!((_c>=48&&_c<=57)||(_c>=97&&_c<=122)||(_c>=65&&_c<=90)||_c===43||_c===45||_c===46))return false}` +
|
|
807
|
-
`if(_co===-1)return false;` +
|
|
808
|
-
uriCharsSource(v, '_co+1') +
|
|
809
|
-
uriAuthoritySource(v, '_co+1'));
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
function ipv6Source (v, isStr) {
|
|
813
|
-
return guard(v, isStr, `const _n=${v}.length;if(_n<2||_n>45)return false;let _end=_n,_g=0;` +
|
|
814
|
-
`const _dot=${v}.indexOf('.');` +
|
|
815
|
-
`if(_dot!==-1){const _lc=${v}.lastIndexOf(':',_dot);if(_lc===-1)return false;` +
|
|
816
|
-
`{const _f=_lc+1,_t=_n,_ln=_t-_f;if(_ln<7||_ln>15)return false;let _o=0,_val=0,_dg=0;` +
|
|
817
|
-
`for(let _i=_f;_i<=_t;_i++){const _c=_i<_t?${v}.charCodeAt(_i):46;` +
|
|
818
|
-
`if(_c===46){if(_dg===0||_val>255)return false;_o++;_val=0;_dg=0;if(_o>4)return false}` +
|
|
819
|
-
`else if(_c>=48&&_c<=57){if(_dg===1&&_val===0)return false;_val=_val*10+(_c-48);_dg++;if(_dg>3)return false}` +
|
|
820
|
-
`else return false}if(_o!==4)return false}` +
|
|
821
|
-
`_end=_lc+1;_g=2}` +
|
|
822
|
-
`let _cp=false,_dg2=0,_i2=0;` +
|
|
823
|
-
`if(${v}.charCodeAt(0)===58&&${v}.charCodeAt(1)!==58)return false;` +
|
|
824
|
-
`while(_i2<_end){const _c2=${v}.charCodeAt(_i2);` +
|
|
825
|
-
`if(_c2===58){if(_dg2>0){_g++;_dg2=0}` +
|
|
826
|
-
`if(_i2+1<_n&&${v}.charCodeAt(_i2+1)===58){if(_cp)return false;_cp=true;_i2+=2;if(_i2<_n&&${v}.charCodeAt(_i2)===58)return false;continue}` +
|
|
827
|
-
`_i2++;if(_i2===_end&&_end===_n)return false;continue}` +
|
|
828
|
-
`if((_c2>=48&&_c2<=57)||(_c2>=97&&_c2<=102)||(_c2>=65&&_c2<=70)){if(++_dg2>4)return false;_i2++;continue}` +
|
|
829
|
-
`return false}` +
|
|
830
|
-
`if(_dg2>0)_g++;if(_g>8)return false;if(_cp){if(_g>=8)return false}else if(_g!==8)return false`);
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
function ipv4Source (v, isStr) {
|
|
834
|
-
return guard(v, isStr, `const _n=${v}.length;if(_n<7||_n>15)return false;let _o=0,_val=0,_dg=0;for(let _i=0;_i<=_n;_i++){const _c=_i<_n?${v}.charCodeAt(_i):46;if(_c===46){if(_dg===0||_val>255)return false;_o++;_val=0;_dg=0;if(_o>4)return false}else if(_c>=48&&_c<=57){if(_dg===1&&_val===0)return false;_val=_val*10+(_c-48);_dg++;if(_dg>3)return false}else return false}if(_o!==4)return false`);
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
|
|
838
613
|
// --- RFC 6901 JSON pointers -------------------------------------------------
|
|
839
614
|
// A pointer is empty or a run of "/"-prefixed tokens, and the only escape is
|
|
840
615
|
// "~" followed by 0 or 1. Everything else, including "#", is not a pointer:
|
|
@@ -849,10 +624,6 @@ function jsonPointer(s) {
|
|
|
849
624
|
}
|
|
850
625
|
return true;
|
|
851
626
|
}
|
|
852
|
-
function jsonPointerSource(v, isStr) {
|
|
853
|
-
const body = `{let _ok=${v}==='';if(!_ok&&${v}.charCodeAt(0)===47){_ok=true;for(let _i=0;_i<${v}.length;_i++){if(${v}.charCodeAt(_i)!==126)continue;const _n=${v}.charCodeAt(_i+1);if(_n!==48&&_n!==49){_ok=false;break}}}if(!_ok)return false}`;
|
|
854
|
-
return isStr ? body : `if(typeof ${v}==='string')${body}`;
|
|
855
|
-
}
|
|
856
627
|
|
|
857
628
|
// A relative pointer is a non-negative integer without leading zeros, then
|
|
858
629
|
// either "#" or a JSON pointer.
|
|
@@ -869,10 +640,6 @@ function relativeJsonPointer(s) {
|
|
|
869
640
|
if (rest === '#') return true;
|
|
870
641
|
return jsonPointer(rest);
|
|
871
642
|
}
|
|
872
|
-
function relativeJsonPointerSource(v, isStr) {
|
|
873
|
-
const body = `{let _i=0;while(_i<${v}.length){const _c=${v}.charCodeAt(_i);if(_c<48||_c>57)break;_i++}let _ok=_i>0&&!(_i>1&&${v}.charCodeAt(0)===48);if(_ok){const _r=${v}.slice(_i);if(_r!=='#'){_ok=_r==='';if(!_ok&&_r.charCodeAt(0)===47){_ok=true;for(let _j=0;_j<_r.length;_j++){if(_r.charCodeAt(_j)!==126)continue;const _n=_r.charCodeAt(_j+1);if(_n!==48&&_n!==49){_ok=false;break}}}}}if(!_ok)return false}`;
|
|
874
|
-
return isStr ? body : `if(typeof ${v}==='string')${body}`;
|
|
875
|
-
}
|
|
876
643
|
|
|
877
644
|
// --- RFC 6570 URI templates -------------------------------------------------
|
|
878
645
|
// Everything outside braces must be a literal, and each "{...}" must hold one
|
|
@@ -897,46 +664,6 @@ function uriTemplate(s) {
|
|
|
897
664
|
}
|
|
898
665
|
return true;
|
|
899
666
|
}
|
|
900
|
-
function uriTemplateSource (v, isStr) {
|
|
901
|
-
const inner =
|
|
902
|
-
`let _i=0;` +
|
|
903
|
-
`while(_i<${v}.length){` +
|
|
904
|
-
`const _c=${v}.charCodeAt(_i);` +
|
|
905
|
-
`if(_c===125)return false;` +
|
|
906
|
-
`if(_c!==123&&(_c<=32||_c===127))return false;` +
|
|
907
|
-
`if(_c!==123){_i++;continue}` +
|
|
908
|
-
// `_ute`, not `_e`: this source is spliced into a generated function whose
|
|
909
|
-
// error accumulator is `_e`, and a `const _e` here shadowed it, so
|
|
910
|
-
// `(_e||(_e=[])).push(...)` ran against a number and threw. The verdict was
|
|
911
|
-
// right, so the suite never saw it; only a caller reading `.errors` did.
|
|
912
|
-
`const _ute=${v}.indexOf('}',_i+1);` +
|
|
913
|
-
`if(_ute===-1)return false;` +
|
|
914
|
-
`const _x=${v}.slice(_i+1,_ute);` +
|
|
915
|
-
`if(_x===''||_x.indexOf('{')!==-1)return false;` +
|
|
916
|
-
`if(!${URI_TEMPLATE_EXPR.toString()}.test(_x))return false;` +
|
|
917
|
-
`_i=_ute+1` +
|
|
918
|
-
`}`;
|
|
919
|
-
return isStr ? `{${inner}}` : `if(typeof ${v}==='string'){${inner}}`;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// --- RFC 5321 mailbox -------------------------------------------------------
|
|
923
|
-
// Local part is either a quoted string or dot-separated atoms, so a leading,
|
|
924
|
-
// trailing or doubled dot is not a mailbox. Domain is a hostname or a bracketed
|
|
925
|
-
// address literal.
|
|
926
|
-
// Local-part characters: alphanumerics, the RFC 5322 atext punctuation, and
|
|
927
|
-
// the dot that separates atoms. Written as code ranges rather than a regular
|
|
928
|
-
// expression because this lands inside every emitted module that validates an
|
|
929
|
-
// email, and the expression cost more bytes there than the whole check.
|
|
930
|
-
// The emitted form keeps the comparison chain: a standalone module pays for the
|
|
931
|
-
// bytes of a 128-entry table in every file that validates an email, and the
|
|
932
|
-
// runtime pays for the chain on every call. Different budgets, same answers,
|
|
933
|
-
// which `tests/test_format_engine_parity.js` holds.
|
|
934
|
-
// Stated as the complement: of the printable range, only twelve characters are
|
|
935
|
-
// not atext or the dot, so excluding them is 54 source bytes shorter than listing
|
|
936
|
-
// what is allowed, and a standalone module carries this expression. Checked
|
|
937
|
-
// against the allowed-list form over every code point from 0 to 65536 in
|
|
938
|
-
// tests/test_formats_single_pass.js.
|
|
939
|
-
const EMAIL_LOCAL_SRC = (v) => `(${v}>32&&${v}<127&&${v}!==34&&${v}!==40&&${v}!==41&&${v}!==44&&${v}!==58&&${v}!==59&&${v}!==60&&${v}!==62&&${v}!==64&&${v}!==91&&${v}!==92&&${v}!==93)`;
|
|
940
667
|
// The same table treatment the rest of this file uses for character classes, and
|
|
941
668
|
// no slicing: the two halves are read in place by offset. The version that split
|
|
942
669
|
// the string at the '@' and tested each local character against a chain of ten
|
|
@@ -991,45 +718,6 @@ function email(s) {
|
|
|
991
718
|
}
|
|
992
719
|
return hostname(s, at + 1, n);
|
|
993
720
|
}
|
|
994
|
-
// Emitted rather than bound as a closure: a standalone module embeds format
|
|
995
|
-
// functions by their source text, so anything reaching a free variable would
|
|
996
|
-
// not survive the trip. The domain half reuses hostnameSource, which keeps
|
|
997
|
-
// one hostname implementation for both halves of this file.
|
|
998
|
-
function emailSource (v, isStr) {
|
|
999
|
-
const inner =
|
|
1000
|
-
// One forward pass, and neither half sliced out. '@' is not a local-part
|
|
1001
|
-
// character, so in an unquoted address the first one is the separator and the
|
|
1002
|
-
// local part is checked on the way to it. A quoted local part may contain
|
|
1003
|
-
// '@' and keeps the backward scan, which is the rare shape.
|
|
1004
|
-
// The bounds tests are merged into one condition per branch, and there is no
|
|
1005
|
-
// separate length check: an empty local part fails `_at<=0` and an empty
|
|
1006
|
-
// domain fails `_at===_n0-1`, so a short string is already refused. This
|
|
1007
|
-
// lands in every emitted module that validates an email, and 25 bytes of it
|
|
1008
|
-
// put the CLI smoke build over its --max-size once.
|
|
1009
|
-
`const _n0=${v}.length;let _at;` +
|
|
1010
|
-
`if(${v}.charCodeAt(0)===34){` +
|
|
1011
|
-
`_at=${v}.lastIndexOf('@');` +
|
|
1012
|
-
`if(_at<2||_at===_n0-1||_at>64||${v}.charCodeAt(_at-1)!==34)return false` +
|
|
1013
|
-
`}else{` +
|
|
1014
|
-
`if(${v}.charCodeAt(0)===46)return false;` +
|
|
1015
|
-
`_at=-1;let _pd=false;` +
|
|
1016
|
-
`for(let _i=0;_i<_n0;_i++){const _lc=${v}.charCodeAt(_i);if(_lc===64){_at=_i;break}if(!${EMAIL_LOCAL_SRC('_lc')})return false;if(_lc===46){if(_pd)return false;_pd=true}else _pd=false}` +
|
|
1017
|
-
`if(_at<=0||_at===_n0-1||_at>64||${v}.charCodeAt(_at-1)===46)return false` +
|
|
1018
|
-
`}` +
|
|
1019
|
-
// An address literal is rare enough to pay for its own slice inside the
|
|
1020
|
-
// branch that needs it; the hostname path, which is every real address,
|
|
1021
|
-
// reads the domain in place.
|
|
1022
|
-
`if(${v}.charCodeAt(_at+1)===91){` +
|
|
1023
|
-
`const _dm=${v}.slice(_at+1);` +
|
|
1024
|
-
`if(_dm.charCodeAt(_dm.length-1)!==93||_dm.length<=2)return false;` +
|
|
1025
|
-
`const _in=_dm.slice(1,-1);` +
|
|
1026
|
-
`if(_in.startsWith('IPv6:')){const _i6=_in.slice(5);${ipv6Source('_i6', true)}}` +
|
|
1027
|
-
`else{${ipv4Source('_in', true)}}` +
|
|
1028
|
-
`}` +
|
|
1029
|
-
`else{${hostnameRangeSource(v, '_at+1', `${v}.length`)}}`;
|
|
1030
|
-
return isStr ? `{${inner}}` : `if(typeof ${v}==='string'){${inner}}`;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
721
|
|
|
1034
722
|
// RFC 3339 appendix A duration. The units form a chain rather than a set: a
|
|
1035
723
|
// year may be followed by a month and a month by a day, and the same on the
|
|
@@ -1037,9 +725,5 @@ function emailSource (v, isStr) {
|
|
|
1037
725
|
// no unit takes a fraction.
|
|
1038
726
|
const DURATION_RE = /^P(?:\d+W|(?:\d+Y(?:\d+M(?:\d+D)?)?|\d+M(?:\d+D)?|\d+D)(?:T(?:\d+H(?:\d+M(?:\d+S)?)?|\d+M(?:\d+S)?|\d+S))?|T(?:\d+H(?:\d+M(?:\d+S)?)?|\d+M(?:\d+S)?|\d+S))$/;
|
|
1039
727
|
function duration (s) { return DURATION_RE.test(s); }
|
|
1040
|
-
function durationSource (v, isStr) {
|
|
1041
|
-
const inner = `if(!${DURATION_RE.toString()}.test(${v}))return false`;
|
|
1042
|
-
return isStr ? inner : `if(typeof ${v}==='string'&&${inner.slice(3)}`;
|
|
1043
|
-
}
|
|
1044
728
|
|
|
1045
|
-
module.exports = { IPV4, IPV6_FULL, ipv4Range, URI_FAST,
|
|
729
|
+
module.exports = { IPV4, IPV6_FULL, ipv4Range, URI_FAST, date, ipv4, dateTime, ipv6, hostname, uri, uriReference, uuid, time, noReserved, jsonPointer, relativeJsonPointer, uriTemplate, email, duration, uriChars, uriAuthority, iri, iriReference, idnEmail, DURATION_RE, URI_TEMPLATE_EXPR };
|
package/lib/interpreter.js
CHANGED
|
@@ -631,7 +631,7 @@ function evalLeaf(P, data, errors, instancePath, schemaPath) {
|
|
|
631
631
|
const schema = P.schema;
|
|
632
632
|
const bits = dataBits(data);
|
|
633
633
|
if (P.hasType && (bits & P.typeMask) === 0) {
|
|
634
|
-
if (errors !== NOERRORS) errors.push(err('type', 'type', instancePath, schemaPath + '/type', { type: schema.type }, `must be ${P.typeNames.join('
|
|
634
|
+
if (errors !== NOERRORS) errors.push(err('type', 'type', instancePath, schemaPath + '/type', { type: schema.type }, `must be ${P.typeNames.join(', ')}`));
|
|
635
635
|
valid = false;
|
|
636
636
|
}
|
|
637
637
|
if (P.enum !== null) {
|
|
@@ -666,7 +666,7 @@ function evalLeaf(P, data, errors, instancePath, schemaPath) {
|
|
|
666
666
|
outer: for (let i = 0; i < data.length; i++) {
|
|
667
667
|
for (let j = i + 1; j < data.length; j++) {
|
|
668
668
|
if (deepEqual(data[i], data[j])) {
|
|
669
|
-
if (errors !== NOERRORS) errors.push(err('uniqueItems', 'uniqueItems', instancePath, schemaPath + '/uniqueItems', { i, j },
|
|
669
|
+
if (errors !== NOERRORS) errors.push(err('uniqueItems', 'uniqueItems', instancePath, schemaPath + '/uniqueItems', { i, j }, `must NOT have duplicate items (items ## ${j} and ${i} are identical)`));
|
|
670
670
|
valid = false;
|
|
671
671
|
break outer;
|
|
672
672
|
}
|
|
@@ -920,7 +920,7 @@ class Interpreter {
|
|
|
920
920
|
|
|
921
921
|
// type / enum / const
|
|
922
922
|
if (P.hasType && (bits & P.typeMask) === 0) {
|
|
923
|
-
if (errors !== NOERRORS) errors.push(err('type', 'type', instancePath, schemaPath + '/type', { type: schema.type }, `must be ${P.typeNames.join('
|
|
923
|
+
if (errors !== NOERRORS) errors.push(err('type', 'type', instancePath, schemaPath + '/type', { type: schema.type }, `must be ${P.typeNames.join(', ')}`));
|
|
924
924
|
valid = false;
|
|
925
925
|
}
|
|
926
926
|
if (P.enum !== null) {
|
|
@@ -961,7 +961,7 @@ class Interpreter {
|
|
|
961
961
|
outer: for (let i = 0; i < data.length; i++) {
|
|
962
962
|
for (let j = i + 1; j < data.length; j++) {
|
|
963
963
|
if (deepEqual(data[i], data[j])) {
|
|
964
|
-
if (errors !== NOERRORS) errors.push(err('uniqueItems', 'uniqueItems', instancePath, schemaPath + '/uniqueItems', { i, j },
|
|
964
|
+
if (errors !== NOERRORS) errors.push(err('uniqueItems', 'uniqueItems', instancePath, schemaPath + '/uniqueItems', { i, j }, `must NOT have duplicate items (items ## ${j} and ${i} are identical)`));
|
|
965
965
|
valid = false;
|
|
966
966
|
break outer;
|
|
967
967
|
}
|