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/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, uriHelperSource, date, ipv4, dateTime, ipv6, hostname, uri, uriReference, uuid, time, noReserved, jsonPointer, relativeJsonPointer, uriTemplate, email, duration, uriChars, uriAuthority, uriCharsSource, uriAuthoritySource, iri, iriReference, idnEmail, iriSource, iriReferenceSource, idnEmailSource, dateSource, ipv4Source, dateTimeSource, ipv6Source, hostnameSource, uriSource, uuidSource, timeSource, noReservedSource, jsonPointerSource, relativeJsonPointerSource, uriTemplateSource, emailSource, durationSource };
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 };
@@ -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(' or ')}`));
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 }, 'must NOT have duplicate items'));
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(' or ')}`));
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 }, 'must NOT have duplicate items'));
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
  }