From 5e1a177393820f078f9a65ab7a9a3e8da247d6e4 Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Wed, 21 Feb 2024 14:14:19 +0100 Subject: [PATCH 01/19] chore: add new logo (#33) Signed-off-by: Tony Gorez --- assets/banner.png | Bin 51434 -> 25095 bytes assets/logo.png | Bin 20479 -> 12382 bytes assets/logo.svg | 22 +--------------------- doxygen/logo.png | Bin 2952 -> 2382 bytes 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/assets/banner.png b/assets/banner.png index adca42b36ff69ea05e82762b155cb62d1620dbf8..598c331f55bfbdf796e64e720af0e7cb7ab88f65 100644 GIT binary patch literal 25095 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 WLs}w+-;w{uprd(=&N^)M%YOkn+C8=a literal 51434 zcmeFZWmH^Svo4G!(73w<2<{qaToN1_hd>|%cWd0;Ef6GlfZ*=I-Jug8XlNSOAdTxK zd!KjQGtRkZzu%wl-x*`|=+$e@o@33bnpICdv*wBdsmfuYlcOUbAYduT%W5DXJTF8* zK$Jv#{&Z#W3l-hd7ow|%oHRn!B<1eY4_R|P1q&4w1lFf>Gz7#5YXp=(O`bmFPagyX zi ziY4?r2s_Io=@u^(<q5~>>g^UA1i#uZ-KmyhZo3V#BX0{~SG?^dTRzgM z;O%92_?Q`4%_XnJAa*7*J|()NruGB2amYkJV7lN1RW#nvZc*>?D5qaGCn= zg7W}wi9!TnwmMjr$`3_{-A!<-FCos$LRn_ZP^E5cau8Eu-t~oZ*u)iJpaUMIT9qfr zu5FM6SWSwk(zbmVeYLd-kI!<%dUHm$;s5hJ-|Wl(QNVv>AH>QC%ET@`poi|nE~3ZB z#T%H;qP_j*&~fQ0uDa|>G{PzJ;S(YC_E61FPfNVR0W>OR!`cu!zFf`-MIQ4RnYS*P zB2($Fpf<})2L<*%WYYz54@1|p$ZU=O4qTK4NvZ$~ckC7&45oPcXEo}#N$b4@R`yXu z!r1JZf@BH^D0R-HI1GY>>iMLeJr)$0!RU_s)W>tXknDBDz;j>YF6@N0%*am~PPo_75pubQan^m8 zVm(RxIOWd7>}Of>{#in~~iE2Zz)JAc3PrnhYWG))^-^1f1P zWJzwX-`t#?WYK5!=b~6nd$)^>dI&lXXjJD6+WqR;pWhriu@Vxct^%wWXjK%#5=Y$7 zYy72#P?q|HCLqa`HES`4#u3^kwm&^{{qJ7xZOsjECB%0SbAZJ6x_NaAl5SZ>^m~Bo}+; zR>)1WIvLhHfbSqZTdo#9x>aY3#DfDk1tDLtZdg4e-ZqlQQ=ZB6zhi@Y%56>87xN&a zl1?N0DMjFBmySmqNv+#-0zf}G6pC@lKqBkSeMI3)=PPTgW)ys?swol}M{hGli4t1- zM`Z@p>afL?{Qeo!&rk<_c9D19>hf@>%TC^e!xHryNRzkHA;plvPwL<@(2i_|c%SR4 zQ<%E=i1PgUy;dcxef5$%-}J+?EIFlA&-j9xmL~2kHB<7Zpf)fB$_d##s*s814Q#SK<=?;@582ITL)8 z=x6R^%P)wdPq0kpPc*DusMw`!n>hbg$7P)UH}(wR#!oruKc^x#36dzUl->A0KjiB; ztzzyR2@~nrR=tFowH@J}P_bnLy(d$qQoY&4?~Z*rijZw{X$LXMcZBPE*Wk{!G`?oz z(^C%4q+tUdVc!8skizVLY)J? z)F&;0xjTQr!F6KukiyD9^XHO!?$6%%aiu6vgO~^*6nwjuCp*9C&SCqEEsT3Bs#E0*<&tfofsA<0z??Ykk3MZ4X|m^TPG)WkXI=Sx zAiYh?t*|5!5>62Q;p1CyRKZ$Etw{e*&Xf*xi?V7|iVb@yG|SlFDxG!I2@4fwnr2eD z&_U)AZzfy8VpD4BK_?vCmVFG3TCwDwGPG3Xj`iYMCXO(_a@#0=6ib)OUjieY{E{}z z=&id_%|9V%mpkQn8`{+U6KRqcxamGrFgF}>!i>2@oiM#_dUs{S0d?L86MRq;_m!9h zi4rHq3vBf@X)*>LM(EuSeB$wc04F9MCjL56U;?aZUeEU+*M5smP%G>kADkF#^nW}8 zSQx4_aqb_}(|6YICac9=UlB~fhWw(~@8vGeQEaPHMBbNdXR(?Yo03<7*G8G4cyE~I zv#vcUp+1AknL*x=?~(r7Wz6DDNeO}*reqnZxAIIC2jt&!c^>a+n$!aVXiA|gT4Vn_ z)$CBp2A_f;C79VYRm*@JRJ7@!x?P)M^V8}ST^ zdVWCKE@#EKD1)lsgatOM@vn!mll#~3h^+g`R%A{^PFCpG!{_3&E}=sP9Wq16VP5Sg zO+3|IyTUYjICW;Ob0OQsPVp+44&ycV9hdUo0b3#*&yVcJ*{Ut;zIU-BUMNlFcrp>{ zxVL(u4!bILG{)@%qoEW5AMg@)pkE~<157HnLJ2W#Xf(pwzYzx6aLS@_zAa_ zh#(OiC9cVe&?I>D)~?*TxiGERcMK@FpzER?27O|ZGV!+YX@9jH*+(A!qqH7ayj*AIa7ix3(MlbXvf%v2m@dcfJFmOoy zq@#yNMFp)|cv}`K806$eq&s;viJl7oeLL8WUW{J`c^^j9Y`wusF0S)?bM9F6r6^sZ z=sZnkUdVGY_+*=t-HT;y&iYa&liY)+=DKM~^;4Uhx*fCXO`Sz?*yYmyyTO* z=s!c-Z!ZF^cSh5;(nF!-4w|Z8Z?Q?5!kvZkb12f>2lJg=#7HMw46XYC-axdw z7Ncm6$Bfj?1+Y@ZS!b=G_}7H;tYFoUWeu_fwxX*NQRw#`!A7ZDQewtfiJGqMmJgy1 zaAzN|JP(e9gaP%q&n&Cx>0t;5=5B)(^rr!AYt3e?Jk{Q;*Y9(}3Opn6SA}qnX~b=T z5~<@Mx#^1ckSlKMTG&GK@AtfHXnqm&w-H0PYQZCwA z{|+DpqpUWS+QDRnsVLRN4?EhzRY?Poas{?M#3!o*jHjgfF4_H}KapqgUs5q;-EFsd z2wAJ@pJrTI2|Jd<9=+hTK=cF#jLa0r^eP|Z)(%7evyp$UYB$i)DtYrk*0+&1S5J&e@osJC-x z1uG%0|F+Y&7+2WurgVs7d_msbOo(EV4OnwU`bHvw*-#%l0O#)4m0#bi`U5=@e6#0L z*}3Qijll4y@bQrN<=^jWbH^i_5;oXmVE>ekzCdbxowr7%LALBP~3^f{Y)i^>ohv=6?ubP?sMT6KHET3N1t z`N^r_J5N7wivTD_DshQtqyD2YgrF2TOT!E{wlNa7aBI?|_A~j8N#$f^dSIx<`FsH= zR^`aY%KIfGCAYI89NF=$Yy|f7ci1aGAZ7g0t+4FvhW~fuE>zAE8z#(k?1;alNjt=)Fhzgr!X0eI)3GH&!tQ9-bOznoM@L{ldU6lYkry}d{ zj<$Adu^1m~fkPgUaY;(mvTY!8`}~E=U5(^O^=-JJ!gv52G$-+Ty$u;}CaBcNp9rz3Jlb*$d0SVxgYp?C{gx-G+3VR`vvqFVW z2}l$io9cL&w*nW|X1gOvCQ+MD5K6F)>G;WyYo^_6kX=u&BOb5HEQ;PRn@|@B<8jF- zGQT>`CbEUSkKQ+XAF%3J->=doY=Y&Vj~soJc$zJ-{MB{D1L=)5@3a%c;@b+*b$a+0 zv@zQdx%2BT)UWw`QJe04^eESzP0YQ%zLw-4uOiOl~ddp9xq8{caW2r$2yDfFO3`iBu>uUbNttzgPq*kRFeTzji z!HoBh@c=jIMNqVdymN16g7?w^?T9rZ)9>5!FvR+6U;gEm6VGNW8j;j&Ld&;R@q5EW z61d_Y#y#Y}>o@8rrdn@EoKNYj94#`z+5D z+<;rUsv`KJZ-u*F%@;Ql&aG0cLug-5#HnrTRfSYY(G9(E@P1>GnU`IU?w>&&90jQ=V$_<8XG%mKbG)zMf%>|d$M)wu)4sj6&1@5PLeLlyP;FTKBPQbS`ixl+SaK6hmz0M+ z{>qQQuySKG&I9bL61&V$%M%tV@GY)I{K-bdUWXg_y`5L|2@fT&e8f0H&T8C@ZoY{9vw`5I)HW{JbN%*p!wQ zj7``{VI!t%X(q;!Wkmy-N*AC}ZmcxF2}ZqVaPTP7=+&$TH35hy&tDZL27ws3;q>*4}i>&{pr(W-Iu*a8-}hoY!I z8g>Uo&y_E}`=%Ri`?v{xhgMf_JADwZZg&{p7)f_(uJ|bZaoh$^WzZ*!gp&^UNMxZg zsJ_UJP3R!iE2};6_z^5l<(tPNb`mKIyxTc=FVT5Vtz)Qv^Fp-wOlD!y5Z2l47k1%W z{!Ne$`x;_BP0a3x}UtWX48e;+Y0+F z^Aw$ld9U`p!W*@Yn5z znfSW1hVLqZ>7q$p&QZU93+}h>%!5n#$o+VGMDdz}=b_521QljX8o%L4zxdAVv@1}S zC3iBaNzb|7&(YD1BAZjJW|RXiFG36o!Uw+;7+Qz#>_oBJIsUe(@!cJ^!lTqMQ-Zn6 zwX?+?DXm{J_nv-pYZlS(`vHGdZ^iS$Y|O+9Z0Fplt!46A$LT|3-=1()-nwI40%giS z4=XY-PV#kiVx4w+e8}(g(4!v<2HJI$2@9E`1FnKR;!LB$JgSyx*}BU)JY(sbY)$>O zn{1hKfvN>W?;AJjIbvIpz8ce*uH3#LFB-R@5z^TyT(uFrKy;IeM`nDhS`;%tq||A4 zK`T^Xcf<)_zsijrBQit2@ljQW<{a_$A;)WoKTnEhaF|vY^|hE-Su1hbOlBd8&+A+o zVoSUJ4jANhht7^=-_HWd>u)Z2w*1bV#fQkpETGhWq1&-*g46AHWjwj>i72W1@Shmj zGR7Kun*apDX8iPoJkvZq`pon@iH&|uB~VTvtTnIpO%s=th*Q7AOPW3xUHWp&|B4$x z0VqE@i7O?(*wmtFy$CAH1a9pWOCh&wgYLxb!!Mazmp?I5Et;CEUZ^`8V)2@McmO=0 zA7s{PMJexYWFl6*YxC63tN+ThGB=B=X-&WsCPK*@PjsN&cJx~qJe=!Sk5XQ>HBmk8 z|2}iB;v!4hj%Nu{SF~LSYa8k{6I*P)#a=163@)$e{gE`X?B(=>Lvk@EM-wpcndEs&+@pLe?Y&n7}W0XKgqa{%qinJn>39X3Kcz8zRfY z(azWDJw-}=)2*k;@19l*KcF>8s`z7f;71qCSY$*wl1R}&?O1+~Y0KwicI8rJ8%EMiWgash*Y`-X|-yJwl+LOM9C|4-RZIj zc9R($onO|h`KDo0F>yFEugeNE-IaFsl|cq;4}5LLM2yMJ44kDMp62I-v$9j;!o#h1 z!lwe6UPe2%Y+XaIJ|b=KXV9?!4?;%)&|u=WvA9Lk#`O>GWd^$=ULjbpv-^t4*dBwy zTbG^Z#lL>HElBs-vnR*rj%YUbuRknPPinbf`_K@L6%mvty6BUSZTS>3DoaCGMZ(NI z2Fv<7F3$XAq==2!9S4>K_4sPpZqkoz#)Rs-Qzsj*ud>60zu$?Tu^`cbYEi1BCOQFF z@mNh^hlo~)aw3Hv|6g+{GqCFQFFQgyBmucReSyYEY;0h`PRd&0O>h{N?k^|&4&k>m zPox$rP?}LW-1Hg26}W_u-ZvK)Dz}OMGtO<4C>4s%X8$>?JtmUih7(oI!KmnN(tB!f zG|zcmtQd8F$lHD2X1rF841O1rgG|@FlF_u5Ee*Chcy1ZS)xgy!c4T-?utsoNU`c&B z$j@ma7OaXhxE;-SigOW^i*p(0wtrU{o~z79Q{JpMg-svN8;o~*XPz!(ImiiUb_XE#+bWEtf5N+FO0kg3@YC+m3P^m z)cQX$@~*hQ>$erVXZ02aZcsD$?ehKh3)Es40IIKmJ$iy7R>Rar%gxa9EFG-TK}XxR zl|f4H#LLN2WpY_)AoyraJ)puz54vDWTmH1P5Qe)GQ6j3q(WnrQ5Uh3gyX>F{t#O-r_eu3Ac%(sC)*_~_c@W}} zJI6*Dz;wrWo>Su6(dyzNOZQtMR(yL?L%p@{HpXUom_7hqM)_-=JDF&!~RJzDllu#xz2jc)OK z!k@02td2x;;y(7yhCOx{)N7kl_g1^S)$b0MyzCFdv=zzZa7T+wOSc7crYAjSP{sfb z^@dgBU;6fU=*rHKGFdW63&EpL($je|L^KU9yQvT z6ul#>jEu9Jd8cl;i*_MeN=Wy6LT|d1IkHaV=-hOZMPFmiPQgT?`ChpG_$_2E&oi^p zi%QY*Qy~zr^R@watI|ju6b#UclZj3~0(+kgY=~sz&HxA~s)kq1Zrq)s8ypUWv9Hj0 z#H*?kXX&vb>5PF0>0D!OQAfDPefm{L>~QvrSvg zZx1cJlpl9J9T`a0uk21gl^;hlb$7r*(MuT&n=&x4DoFS*rM!A*6(S^4PP%Wv(K=QC zH-LehQH~E{>tdsX@wo7U-ZBJ|(YP|F%w>XQ&qD@@s?xt)1l`P4rYCWyXLBb=Jw6{$ zjw*~sdy;oFP)VC8=p~x$^>-$9)$d+Ty=}(ELd13PsNx^uu$iD_y-q;I=h(-L2l_8` zX`GS7%J@R94SPr2QwLl=;%}un;^(?u?oVC$`xN{Py5{RR;y#8)f6Q^-J@Y&ORD2O8 z#g3*n5+9E-EF}cW`<^WIU($D6g!3Hr&~Bz34gqe@goo@c^>Wl(cqZ2v1|f(Z8!#vT zwbPJEQYd1|(wo$QE3lwyMl_LwX)U?qr)Cuk|J<8g6E{=R>vrr2Vvov>i{n!huZHTe zjEADQ%{t5~d2jF7X6d-|JIy>!YuJ zW?HYO>~5E;;YCX3QLRxX&a$0E6?|(Y@#X`QYkj0dq^yOb|8!OSzXtwyk--b%psh&1 zXJ@FOW&F&R_giBJiQ1_l8O*LsXAaC3jW3B*CFi~ntw@#SpuJSdvw2!X1Ru@KWgcu7 z3T3Ng5pK(hh7s)ls{Im@khXrQT@F*us2vbq9bi3>fIqDXEA6X|lcZ|)X=U{nYfdn* z+g?x}-M_w@bmuan>`;lFlI#6$ExnD`d_9>jWS>*?E&V+>`s{?c#K=_~q99Cn+lcNsx5V7g!PHY$N_ zWBr=hU!+;u$d303@1a7yhkWMnq3;AStkXi8X*`7WWUWQkYXXc0789=Lr>>}rtKNxi zv%$aIT>FMcWT>P^${m`#O-~>*lcLY8B2tD;|w1>HP@$*qV4L}#;4DbLeGNsKQTf74IGw{^y@sU}8* zuzic)I>@Gu4gHMssxoP{Q=1XwSt%URYsN%<x-g`u$q@>-znxqjpp#M8Y#npFHV55{!Bee1lO9t{8J^bQazfBEm2Lx-gQtg6?h7M?BV$SoX?MJfTJN}R;NV_ zSa<9Vw}jN^8;UWMiayz>O0$}(?2tBEhME;8$9Y!@Dhw8 z*gon=Q1eZ=<;)(mGONWqrqXORX;A;pA;7Ra6>QJ?TEsrq-c12n@LstGs#AI4NPf5X zVoC<`rbST`?_s$q>=Y>oNa#(OQl8%%s#jg$veF2tRywxa z*bx#bm^ssv`oZ4=DVy!QRL1l@E*tYitg8dE)#u&Do54qPa`%D6E)tH=pk zzrqg7LFSktGat)Lxb>m*W=tuUaz1vGZH*{(|)vgbk|0O_V8PpVuz=tH4GQ z6Ui5!jb^ik>nuAF?0Ya$Ez?W%^1l&8iK0QB!!BC#P1Uq^q-U*(LJBAxQjCTG0kj)a zW=EGoh(6=rhFF4t=HyB7l8<%2VQ6I95YugY-u{%UhdCL6$RU7voCoi0l ze8+(_*_O%8@1JaNm^l5TJ;UieASJ%kHXldkKa7D$QWCoqeFsHb>aPx7@CFq{3geG% zhcAUracsNx{U@9GSGn6R!A>k4Cz!DQ`2{?Gj0$F*X;~0>Bz-;kA?okJKl>vKB%qY` z-_>i8uUEzTJ9%CXkkOi;HtdhPB+WU}CuWa$RJb^D?L}*dDfBXCw zttKG38lNbLi3QM1{BH$Jk}fD0*du#C6S<%Lt;rc$MB&1{n(0}yKV6j|A{`ZAty3PZ z($in@`L^m3A>T?NRg&RiLQ?L?cdcg3 zPMJh<2W#`lmiUa%s#3l(A>Z!4-!_yQ6i?+x5kx!j6BGO zu{)?uNr;qvkk$?H$76TWHFk}oQ)rR3IC;k7hAC{m&<}l($WG9pViT4^z zx#yBxlv8dZg79qyU#FxLfKQ#O{hQ$7p(iS23uN4abF9bDA!pokDVJB|uJtaE*KHXo zw8ED6hH#A=>13f!-f9r% z!OYJ*%gd=B5)IeWsR+r(zh#_fTHbo7Yve!>jL+VGcY%x$Z_*s$kOp6P4s|tuCMfi^ zP&GpQxgVOM&s&XyR=QoDlyY$eqnK}_k>37h#t@i0amu#B1!zzwpG--J3daVXdYXw17`qxSP)l|_CH=%1xC69 zS#RWG4a%(SW%g1;t~kDm+rf2GF^3CMLrHK*WYj`#k|#|L*PpHDRZxddVdT5!UrHZ^ zc0Q}LxPHYN5LAHJ0Np`jYrI}!PQ0}O2{||NTd_O&P!v)CHp6})SczLlqdkP}1PLc? zuijeiR6+m{jmUTdES6@wmWB5*CQQ;(5!4ted!*47tZ!JojJHrGFiY%vua)N=S$PKh z)K_5fyj^IwR&si8x85b5oTQHD2HEEfIPjh5wSHoFap2Lj(=N46xw8NfhcNf9zsK1j zsT<{=&d-v(V@r93CC?gxaJ&CC^tSQoB!#i*-wFJ)Muv~pId2GuE;I{IvuTZ}$cyOkykGy+j(ARbR z))Aybmb`oI^F?#dXlEU?!kkn{=u#!`in&>)_Hph@74K;_&GoG)IS_vo{;u=NfOfJ; zzbNE$uj!!j&LPN%UO9-77K~Q^E(~p210%^I?4<@d-V4MB$$ymwf#OiU3A1)kU+g|P zkNq@BRQ`L#9XZH$epY1sTC6mGxzp((`c5WfF27BxT$@^EK*Cw;!DXJ!q`ie{Ps;K= zNU+Dr52DvCcw~5wlQI-`6wz?m@sJ8~eJ7 zw-=k=-#aGb37U=y&h@{Fp~`SsXgYXj?t;X|v4BVhU%o<2@zB2vBBlq=z%9Z@AdZr5 zcgUflx>FS9K|y?q@x2D zN@%P8leUc1A_meJM8Hyiv}`m#N^kTAfEFE++v~jfAnA8K8m51{S=MMtH97mQJ*vei zvM9btKI>y5ko`Q7+d&kGODQ9;q94ZFIMZ^Kl4jdeGlbqw1de7%hE+0?$p(r|{trCB zBi81#Ed@v+lZsc6g507Qq!y(5Lvd6lFd66}`G{%WHTPL-sdF4~LX@hydcq&K-cVE$ zTT1jWZE}EL^ zy8)l^#|NE`y#hF%P_^V#^-bzL1t{+J)P;Z3-^W#PQ4QP@AN< zr>Ut{Zjnrd8#6Nr2`{97#gyA}ly0q7RFqrwBpk>T?8LNx_w55;Lbor;X6xXddYKC< z9f!MYd#?%Cr&bblR(C^<2|v?y(G`o(IMcPaU1XMMi&w;F>{cur%!H@n4O*t3|A^$~ zzzOA8$o(Umbnpd15=phfg&Mb-Il~hV{bILGlI>eeU3)ue!-$+p3ek+NPjiCO z_@xlIz&N4QIPZ`?70TqX)KOt!WuobY9vA0<9Xe4rU$TEn&R3p-D>5i@9E?pN9++8m zA-q=|rouMwDr8~bEwBjmVsai;`$CIQ5%%kq0^fdN56+&DbAr~OJqw>bB^?bjvqU-euycJ=8IfHPA?bx}-Yx)P zJ|(A%3wAMnF;@!VhP9mCn&1&KBF(BwhIHE;NzEGn$>R26x)J!(lEXQ#!`LJ*zR@1@ zHGuWxZM}F-?3uZupJr8WEAB$5teUi1pb`2z46M=or#!s+bHAI1qbvWKErSCZ*K;q_ z1{I-NymLB;+T&~A>u+5q*UC1~_dlm(gjm*_dJPlVnRsEU4lmy4Gg>=jQ}P#8Mo415vH z3kdJX+m@2RdOkS670Sl+UO)V>eaF&`y)&`&B^A(|4zkzrGaEur*qQG4<1cmOnA=is7@J%7YkE!^mF6E4WU7Nd znhK1ul!#`dbHa}H$ajK3z@7DY-6XU6@$P2Le9YAf)uUQoi(ojK$2}z$To~qo8BmUrt<;D;oXE)WCE7aaNrb9!8=F0~) zA=aUonx-c!8qca(9{G5}I==?Ic}_b~ncD8F`Sx}Ys*XT2%`?e0e0r@kFC@&YklO7w zT&4YDENWgH!5e303k4usJv{MtDUB)QloZ37+IGiNNl8duK2-{)7i=1rS0i5hEDqoR z*LyYd5&HN()4G<#hTK}=3e!$hwZj&`HUk#Hr$*d7S!B>{MKV(hMbNDf&781i5bwei zdwwJRGj(H#Y4|{>#I`q!pk0?xZtHKg%rYczm_>@fq6c`S2{{1660M`Eo>D59oo~uDA6UVpAZJ zeIqa&y{~6qc&TOe^}H|+42T`Jxr=^_iO3|?h4X7QvL8Ao262dY%6Oeu_Ggp!?62a{ zm_NIg-r?>9>OA0&V(k2mC+= zI6Cy9vcNz4Jq-*^sqf(1?U^d!AjU(<4|2Rmz-DbfqxBI5O+LggKP#|Sfsb^zWzPm9 zrSd&e4}3smIBK#)4P&zQ4q)qMOnoTn)7h63>XkyDY+zEn*#Bve_*K<}n;ll>Rjffc z#{&WP4+WUZ%lRL&jn2y#=ZV9jOf(euRe5Uw!*F&XPMF!Aar6`?e?%0Tn8?dPT|Awg zI|8O5``-0C;ikY8yDDb@Q{46-d;K4Oa=>PyhsXcC38(L(9%R&YG8m!*u}SpZUQPIp zW`uFv@;TgzMg$Qkka+Dk|Fxb~!P1o@J|AhG+AbXbC{Ulsvc#Q;7kY5E= z=6VVW#ebl=!0S8+qLhjh$n*lcXCXs{d_WA?CP4uEH@L)S(rH`XE%GaV{E>PE$iID*fL&C#wm-vR6AQHzpg9DSV z#`I1ea-kZB6l0(VeTZA^S7_>&5iZX(Swg#LfaG?)Jd4y#foM$;xRxL3jq=&5DHnt%+BsqU4JuFh zPP*JvuuU9l<4)8}fpc6=+~!kCJQ8?wHV`yuY`)bR7sxRTtC`LdO(?7Ap}EUE4=E-|=%|B7U$K(7B*GDEnLBD=xnG?eeYeP>ketwvC`L zVDO;{VIlenXgyo$FrLsDyX8H?+$uB!?c6m9+XSDiIphYT9CAec4z#CFnPko+2s?*4 z3R&mF{S1`8UiLN(eo*V}2Q+Es$9x=SSEGK6aGG;I!VT44VqFuRsJvax4Z|g+#wRB3 zhi)EG;<<<1qsi%gw3utz2w>j0e~F>UQ_X)fsPk*iL=+b|LTpug@;Py+KqMcY$0Z$r zE=IVB^cK+TdK^Ye)QV(66CTP$CTq!99e^rhzdiYK?1NDwcX;$zD7FOf=1059(+;a< z)Abxfnbliej&Rl^pZqUol7U{53Ge7ZQBfGihYF;=5j->5;mX^7N~rtH zSdh9fexZ)G?Y%r#d2xW0lpNihN{YjU{rGl`H<>e@Aitg};~S$n<#*G}-IA?$w}Q^X zqjt{LA~cJOczW@EAsz{BzYDj_E?>ug8#NR{1uKqxD4|!Nm={h>p1}^PwHoD> za}5_cP#?cjarrpU2!3A3(vf&g7LW8~jFby0{aHHDdDf}@HWLU>Q#Y;wUnmb1)q-hW zOn!n)7vLAw=d%+M{Wl+LT)BttU&)O!w8~f0vQ?!j8sx|#{w2Cy{FmvJuhf%HcCXfb zV^rM3Pb3Wj?dU+2Pg|4Ae&%R){7J;~!~u4a^^Yi2XdT3#e`fa$ztvzs@q__?sOtj7 zyrk5zVH?ADE`(X24BMnBmH2k-5I;3JJ^U@DBn2g*q!c-V(4^HL1{{WP zi9Tm!FrY6;=E&&4S;{2#!T%aJypg70Mo6DflgW=Am6Y&BM;x(=*>gpG;vMA$vqetx zyW8*ExJ@!C%IL9h?Lu1p z>_w0Yw_U&a>~m$!>Zv^-W@E{IX^p+))tfheD(|#Jg1oG{*{zmr93%H~NfC`UTwcei zc=FWt6N8YJ6jPja0iz1_krMQ-O?`~kl^<=wdOJU`;R?=;(#e5cxseQ$jW?HH?HsI| zMXNLgoyb0E=owx~(}=V#{l1Cumi#?7DuSvgBLjV+I)Rc!^P2{qMR}!VX_aDn6I-RV z@5BZgjGYPF$%VWz={QvJRpqrNcyLg|9&I;;yxorhi&&Fev9%wi_=FE%xt_e~;#Zka zHWE7**`dmeCsYUwZE8Y{m2WP#0G!sgAF2?3{@LZ_f)MY+$p0z?zPRO)P zb*^J&Z2sMa?ES_>_2$QIP|f};7xG?UO8Ey?U6hZEPjm5y>?dPZ6hV`8xrpgSx11k6 zvJ2=kQ^YE9yFbb36AyXzXJ{N1e*qjFe*H>E=H4I+wk~=f2 zEXR(6F^^zd_Y`R0G1^x3k zANR1Z67)uum-^u&LUOd=ekGfjzKBn$5%h)C3};63I{F8$?|lew!X!y`m7UC|D-nH`C#2+^@)*9G)=bpTC-cTB zuok3Ww?|!x=>M2!yyf_ARz`=^(%XbSgbyZf?X8SL8r-i{VR8cr>HF}UExwn;TWViv z=}mf2tEqMm)vj9@5RdANTKw&Sm*h^C#v`e_%yja3&hOGVw!!G&#PIOx<-&2Hc>d@tPkEt+N zeqxY&^OtjatM5`e3!m5!(O4cmdvu~E&decdn&++LG9PKS{*=k+>10HE6UiEGjE33( zUJxB%Ir3~Qdb}?+i^Rv*P^GP6E$y?{L9e8*V8j-|*Uf=#YDi4ptfzCNjS~6`2&%P{ zNU*j;^IIiHGqJJ-S^?_w0MeUh7~i=124n8EQ){G^!Tp#`FZ&N))^c?=$&stl%@=B1 z#CBlsXzSHiQS?Uxe7jrKxntRiI!4)GGZ=FJaYL6{4fmu)W z_@>vWLMGb2PT})V2^q7~mr4l!yx|bPaG@eXSO4n@OqOcoUZ-b9HSN(UTv8GGE-jc% z`*{k#wyuRY8VicD1ZwWTf2e-0`PolX{&pdE=15vtv#)lQ2U3vtD=!RfD8M+v2<_fp z2csjrGTfE>b9&3nC@Cv;x=N%dP&GJZZSr+zQ>KX?Wi`%AIuHTM=UG`c)>mfP)4`??(;UuQHgO-Wx*(fs7Y ziXd%_0T1sHvizRv{~_!xqvC4Pwc$Vr8l-V|cL)xRyE_E8KyY^t?(XjH?gV!yI0Sch ze>>02d}q!)bJq7~ukPKeYgb)$Yt?nv?x4ZDC4lD^C9TPq6F-q$V&?$cMwazy--C?@ zBKtN0!r}tw>2Dhu-l6asQJ0CPYzGa};^LYk$_e$oiZm3j=wBHJ$<%1ZefL&p5{GvQ zU-mJ-2^!P9@o{BN){&+`;fzX4@ru)ILqF0x^&LWUyIMH-k7{W`xR7Yn*a4X_jfefW z1>Yv#tzc;ScCeFHBgQyPwajCMH&8+DcDd_Yf+H3<5ZMhPesHz=7*sqS>s0*$4cau{ zkEWVxR)pXG-E0|(+yx4i6_$?%Qvw*2ULu&iJN>V^^h$)R7acn5ePT+Uplxd9VhO=` z=_8{e%g{_Uel%VHWgYfTBHVN3fY`_N&WwRHDI-Jg$mA*iG;3KZ#V5>L@_a$Wy3b>*O;=*tT1!O#L#Vdr^nu9z|kR{n|Q5pTq z>GqO>u~T{=RVB1Cv2Q&TY{H`Pe2F0R0|F**?0Na5J`4n})aHk<<(E6l2&~qiB7!Yn z5k#Q*m{QemNtmQzk9gfwnt|M33YWs!6VMkmdfox+pLPxLDg&44qE< zC4V^gZ-8MiFj)j2(c2~oRTa`q$T=YmYez^~Gat4wS#()A^rq9dl}_icea$2Y^b|}F zueG&A>G)il@9Brq%Tw84+z-B0>P?u+CIlUCzXi1TebQ^{#`R!Psg?nR{#4 zh^q`cTbbH+9pcSSIljLfS7WdLLeQi@%3ex!urK2qy+tj|fMmiH^lO;Gr>Wn;tX zyR{ReyjtCAlNB#SO*J!8WC3x7S3j!Cgr>CuV!o7`Qy6wKAtT=Q@2)YfdMisz6cfJw z^b3E)rw_A!;myQy%H9vxs6vwwkX}ajRRsKoIE%_L5zt1U&{2PfrY^AruMF#Z{O+{a zr&dxj*YoL^56m+4<0?DuU9m9_$HLPAbzzeXo5*ky3L0BUqGxY|^~y47T1K})Tgy@T zZ8O8Q?42APumQuukM7Q+5Dy8Ae)Am6SO}84uV>>;6b@DrW*mOTJxU$)LOP@j&^p!Nx0xGvmMPF!>AXc*9Cc! zf&WC<7d$LfE_z#|rX?*Y&$<=`DzB8#c55Ge*j?96Yx&CW@No#xJ1&j(>iPWY4e5R# z=jq+*{-oLb$}_hb>e^cDMgyj0TcP|*f7XKT=!>ghEmr*%z;QW)^w)aM8E;;NG zN`1lAgfH|xwvwY0? z@!5hI#L9Zl>}bS1VX5LU9@}x2$i;ewLdpeq6-h0=NxX1bOnyC4kfslkEjY!gd}=-- zC^!w>2B<5N5NbXDFyEk3tJA)W=keqMvg1Nf?&7lfd=dOr+h|2TYITh&0rs#-L{0D20KOwwLqE31RxTLl zZsFi1IG@Hv9x#W2PWS;aMwp)q$juwTf|NQ9k8xMM9mjVEZdMw((j*4wY&hncHOzJ- zTqb0t&es&?m$2tGAWAbooS(cz<)K;XcMSo^?JbeM?|m2TK>Yx-(LbRTOGjpW-;i7?`#8SD$p}{;I$NU1-Z!1*#pb8V7GzVlefsC6#Ww;o6l!? zf`HM)pIva;6-`8IpK*bcK{9h5Y4EPCG|&x0X;AV=>8z{LFv2{Gw(wMv2Aqr{8?R+& z=(vu*lOgons1>*O_cmfp7isSDkV9X=et`*Q-K3tOmv_^>Rf$Zcl4t{~>@Aw_5pj2j zO>3`&Ea7ajd=@ps3zMIs-~-5{D$mn0DZCQ zLE%t_nQ{^8#Or|IU>WYvqQI?h$X`iRa2^+P{!zX%7QP#76_G#dUPqNj<+K?Jc+1-X49)MZ2l(?#fz=x4Z8Z2gFF-A{E+lj* zeGs*c3OPBnT{i%sA>LQFcvIxkKuWzKg-cB{KuTVBLBs$temrd4k*ruKo|yU&oI=vG zck2bgSABo=fEeaD0REigm5C)%>oC{@<>VMoUtx@geldUM4t~Ku(0rq@p(NIl%L;9S z`?j4S3bHd>C{&nJA9tRJH53NC2WE8TV=9%53qr2Nxxa|uc@)Oi|>RE$3XpmEZbd}7y%sDxh(5l~xSAVIJf%0m zjy3ha)@!E>j0;_gWJkhW7%Y>&nBwWdQTC`-a=)?GtTfMRIS1Q%%$C{S)T(n3%{0=I z6)90NjA_S7JBT-gDx7Qvo42Wa!#ZIf92!KQcdSvBc!m^3glsxd?^p3Q-+>mzYa-?^ zouaJt%)!6=R_XCDHp8HWcKUR>Bf5W?Wb1cD`#H{U0D6UiWMVMUrB@Hfs0K;~H*P8g zJwAnz2aCl_6C#vw3SesO+iJz18Bk3i@XSByZ-@KJldon*9!6Q~`s^#7WJm(glBhNq{?rju!uehj6^N#g!jdDp zw?i?IjuP34vlgDUiW`kp`+97r&(!&^Z6@lJ9PW8^kUXDNXKh2*rF7|k>2boDV}m&j zwqk7~C&X;QzKf`S(!}|k7pY0lJZ}k#{LCD6@7yiWI#>6tcRaS7*zGkY8jooxmR+Gd z1JO* zd=l<#qGn5$+U5Z=XQCk27<-r~b!$%)S&}t*Ub6(66)oglY^D=jtuR9mj54=swUOk| za&5<@V8(TMLcqV4M)h~ue9H1PawwcoP5OCr6^l^Z=syUA%?e=(k9ZOiLWYV9r9mXHpwh>7 z&*JOhx0eei4|yx0hnFepIi)k8g}b}n|0JBR3feCsmGVK6rl;y7Y8XnuItkdph}GW7 z_9GcA&kEK@X&|A25Gt4>F~wcrWL`zP%fr)e*{d?llc*$meg*TmIy*H8K!J9!S~AKX zSBKPG^milr?668LM3I<1#m5IRlyG04} z9cpH~A9weWPgl+@X(Y4@9^cMHC+;aOfMX>wD6HoTZYOE&@`{m2znm4+#BEhVWqJl| z8y{*_*nA6%*IUr!MR;Q$P{n{fxcQN!{}uq0n)fFt09&!IS$XP<97jv7La7-*MUg;= zR)1wQ`m04`wi=w>Ts9|PSLBm$8{DsCVBikIyad&cY0Y#!Cui32hjj!acshl(v-EcY zsEpGJ!RCsCQL;sq<^|o3Uirj)YJ{(bkv!D;8;j_U+%pP%orr$U`~zrsO(Q{V(UF!GsFHi!UR>>n8Xe4T)%q{hBik>FjAeYUWdSHi*b{x$$ z?Q6|>;!rtP`ho^;h+}CNFrI999CB{5Yq9Uu!Rwqibbh z*W}Olan>CVg3$AJ(LXEi3TRXDU*w^9Qy0mjmcwg9_*wtNMA+^XJ;!6tVi}?CdCxbc z7onwYAfMDAtd|x&fXZCM%}3hxQLtwQ7Pjq}tAe?VY(rC!TH`D%G^QAbLdIOdrRe}Z zG7#_MGkqjuDueGbeZ5X##zb=d4g(QZg8RmA;Z}28FMIKh-X9LDuz5;r`k*`=%02Ad zx<-cb%GoH+m~r{c&I{_U$pXe;8DGp}WpT@BvB_!Yn|)7}@M;(L)+i`HcnV;tQV)th zW-?m6*QNmqmMXCd?CjZHY^i?jz1M2pp@IIc5A%Z5NI`oiC<8(w;7XDhFKSrp(I75_ zEw3Nl38AwaS-0?rtQ$w}p5Fdedw~)cDuUjAO}QPKRMf}MQQ`+g>fB!l+7q1yQr(!@3cOKCO^P2^zsv{j7|~j?t*Wdzk5RRLx2uO}yWxfG zrbVcS)aWYfMWtubjt_>zZe6zs%d{CfxC*xWNTz19(TzH@4GD*FW|us|TM z@%Tq~bhN50JWLpJeFVwOF@ig`@rn$EX*|kU+_peuieDWjoqikY6Uuk_hqiCYGO_qc zbM_mH4~ad2DFj8*Hi0ake}}q{v8AlTkEc{zU%WrdkMT&D`FD$aA58mZHabC>w2hs{ zgFrGU1Y-TcfRCHyqM^+|bLAy&^EPq9g)h~YR7+Y0D2+qyXqKwpo?!5E-vgDeCJfsr@}kYT+0Gje=Q-Kea8A8R52o#)DzWvdcEho}$xXU) zl+7E>;4+B0h)8a(q=WBfBd~+fXf|^l?;Px)2ac=cT+-5j+F~ zvGTP8_jy347>4uuyvg360=ei4YVE@$b(6L#)ZEIK7_!)RN!9C4h zZ$v$N1tBE`&F0Xd_TG!%{Pa+IIBKZITE8Y};;-vA?D-1yKB}3;!jep(-2R-edn9(S zlXTqX)wfTsZvG~(m4QySI=K{?oo|zXPfJ|q$@F$^1y2=m>4s{!Ej9S_>(sQo?jnZT z1CH+`pMkqfx9W*8XzTvcrw->vF;?GKVM zW#-M6$Y&*N!~Iy+TtT=k*4_?z{4abo`gm2MU!gch(%`r!W%{94W>#W<@`uTg1H?0Y zPPce&1FO#tkdsca_A%_D<9S3u-0g#q!o*tI=BcSPD6TJ6lxdS z76~C>oe)E@b?@;TXn#l?47|;$3wERtUDS2>u5h@T8sMI7JjS$Vx(ZcuuV*NWYc-bh zENtz~#v-8rDW7;o%(4`e4RrGlQ(pr z|H#Sz6f6T?M$^V!XpjCS*krQ4EY9t%P9B_Ld7>%)25r&nlXebNZl1<~OL zJjen+N>i-J&(EC9o*$jGQqakG7*=o-+Ekr>Wl+l*0P$sRjcYFCjDJ@^U(H zgBZ9UaX7Ph)~ARP>gVh>syBu`C>==S4cqMC27$QmD?199OiJiqjS0z(3&yAtQPWem zm@)=6urKq8cAfl8jw@-EbA|dA9NkXNR z<&s*Iz7?=C#STv3DG6NJBhCzHxe6J4cQZJeQYr*o4y^_coU5#8i_K=PbXqBngCErc zeM-uis$8ejdI2Jp{akrJ0!%nq`{!xsbz5e_CaTK3t;d|Jz8JsE=~-BUB2Hx_-&q9= z9gF6^tZci0prt{gi?3o3xDjKXQ;Crmq+{*kozx-WN2F13Q?d(mL~BS+i17%%ECJ8G z8`&MRwE5uIo$CrkmU?_N6elC;=PkO{KSiinHzpvdE%^Ho10$~*95fqfJRype%dQ}qToGalzD!Xr_hdVtYbjMx1Iv!X>HYSd& zqI`NK%dgfA^l$m$BGiW~MmQMPZkn3`;t$!w8Ql<2-lu%bKIdl$V)K=ZC9{F7C0VI2 zK!kK^wU!VJ*@q{Ln^+$(M6$qrxEm#%JFa`eGU9nH`gl|T@C>@#=~(HS1m zWf9>?PV@z(fWBWB(a`S!$`n+jeV6>70C@}yrbSPmW?i@tK3x4OL2U%z==_);E=-ri zH};8(m2e-V=1N&E4Hj9Kj=6Ini6=r5e{F_mEuRlDSP^wjxkgNfss#3??sZOoeB}EC z#5jsofKEPv4L4n|r6I4T4%M-KwyQSh7=Bck3O+T=e#y9OAA{M?4iC&(RH69E(-Kh@ zKi0y9`3om7FFXDBW(@_Up}zRhJ^q;HN&ui4Yd8{tbeHoO{d<{DN3skTO_ZZiHTIn* zp1$oEA~&)98O0dZo;do_%RAC_?NH5Z!~>!c->5<#+Sli^2c8~esJagWj(HJeZnR2t zcksq?V^JSbA@!fpD2)}R@A=iK*qTI$xg}+lxyo+Y zvvCms;w1?a%7E$`3nZE%ul7a?I-Df-E}a~#Ucv4YSKs~bIXd#yB1BHnH<%hQ?}6(s z>^fUNl%~@^DJaoof+j5#g5%E?W@TH=Qk(wPR6U$%J9&(|^{rY?U*+?vnF@$nvb zSkp1Tc%wJXeJw57$h$*uaceS|F^O=)v$nz&)IU%pfmj+%WSk7au0%@5b{ToT>A1YO zBd^PBXD<{dv)QI_6r!DYisB&pC1d=sr=g4ZQu>1%At{elbfl(jh>F_FAJqcdxAh0p z0PNY~BiFKR>|7nDl7F*JaFtZDQNYRGvdJK(oMrFtgu zT#S&$m76)#D(4CQti`VPf~5aaK}z-VY8(3kC1I>#q+{_e6Uig%lkw_WK$5=Q7=^3f zpK4xX-3d+ErrAA3^bR~grM!PW%`S*0qV(@tVl0}f3N0Q|&wuTTzTqYcUx*|T+(Jd} zyKDap9E?dWD;U{)u~#ml9`_ci;H#T^L0;7Hv9bnHKl{vcvjhnOoDhcn2TPoVdbS}V zU_xF{{2k$8)S{tDWqtU-L!ePbe4>tzR{_TX_q5b$;~@k;sor#O6CbUL6e~iPwVHR~ z2ms*A=?ky9ikt#KWMPS9w_QQ~4paY?K_nA8fv@Ml9ei0xAAB$nKuvq9(*A zt_Ri8911@;6fXG=;N{oBl4$CxZJjCwHZmYO!=r5{}?R;@(J0AgGg{9$CEjR*&W&RIrf`v zmEFWApyfZXD%jXxvz@pn2^MSx%I)O<}xy8;6hM^t#3rDXknw)BR`# zm=i)iP+)tbDBdCYZ%Q)Od82W8+kwy6>-MSCso03%9hKLT+hHbkdliv{?`h@;{Q>T> z{gIHxB{BNQ$FRI?IiaO0{cEguewSEwRy%@J#6RT}t|wv7 zD?2R_gC9bm`^e=Fe5joSB<0&6*sOY<6w}|_?^o`~XKN88{v z1@oXMAOoHKcs~_vhhZ!=Ud~A_$_3K@_~oa^^4p_tJO@;VS8jt`J%=%gkt?kuA1IOY z40-?Y?d{RM@XHl7`N_m>C?IxZ_Rnfj}%vLsJVaeOtny~}LCN}FJt`bpDQ z3yCy~Z}oyi&zi8U1dV9uZPL4B7kH@eRngQA{EKT-Ayel_xwcc#@% z)&8CzR^rgzV+%Eo)24mwAsnpm#c>g}KX`uPA{ZHV;!@~I7lTGfV1wRGPIt9kb!3`j zBM;&vx&QsXyL8^~VKe5=dlSc#a^ZY|9p80YCCCi|$fO6s{|$d+V^J=r@fB?^Tr2FI zhgTw$;sTl~tQ*|f6k9R(e(!|bCl1p>n_*J-{F%TOcL z99Pi9SqR!_6bk;$xE=_;ks~Pg;{HmUzuoah;G#dt%fd$ECG9u|IQg9+tih#LMQjMB zW8@f-goyqI3X`ln=REI7*dg_lunX|{%Z^hseBits?%e7;IHrG?;QbsI0o@M$WTl>u z{kaXr@(C+`EO*FJftU=}gz5?h@)hqUmdAB}g}s@;rfZS+x#bJ5JAdAgP%sN}>ZC0; z8G{-wUXzxQS+9;9$ome8_FlAPPuGrbEO^u2<;(Egy@D_E2o5xf1?N!~P*lT+*fCpa z9!y1VJrjrTw-5+%vZX=X4#J0BbbN{5hm1sv47>~6Ly?_&r_{|)-o$m*f$V@X!!fxs zOWTfz%YOHN!x{-ujC8kASr>1%zSe3Yi9h5;w1jPd>D{OX)wB-Szb56dK{g&~S$`q7 zDC_TZMF_w9VYfQYq{@5f4_)*v!Ity!4a@;QK9Wwir2~H%f0_Py_|?Wn)w#z+>N~3I z=NM5zcF_=AA_VXAXTf&}AiLZP5XlP#MAvGJTfkJt=Pnd_bl<5NRAUaeJK<;Pb-IM4 zl(2)~@Y+j$Qxr?I)FVhx$^1ypzm%kWcWg&_ucSlr(2CPpmz6ivg>(o`Ip``eN)WT@ zoK3%funz5x_k?)hJ{6VI4i?w-Q@gg6n>WhW>QjLS%E&AC;UmT#U5P$uA*0#SOd|yP zBF3}rGi7J>*K6Ch&xL2HDi1otPjs64WAD#lObZ_HU*>pJBtSe=XpfQ~X~SV~I?~=C z`AA~%_fy2r;n0tf!#wvX-wQj2)eZ7F7qWH`i3Y}Zqx$1R@9y-dWk33Vv>zx!C;1Yc z{5+Iwz+5s@U#4)*$M21s^VaU-&M4T6|ZB*o>Gg^Z;z)+ydO;Y!MjY^T1Ew}4BgW2^r zV<_f(46c%GK_}W793GX7wk__9D`XcGgoZ#C2lxMw zbFTw|M)TC9gM^B7t80_D;erhzBemc!tuhXiIW077jy5KFUuU z6$#s$Q~h37IHRgRmYpYXykhY@n$JqitSgxg+i%jS7nYz}d%I)wLWMvoF6-WKbnvd` z(~apTxOt4bj_7ix_V9Do_R<%PQc^i*3e{MvpEzJS(y6G5%fcw4c@Z=G)lYDSsJxna z>x23b{R`j zbpkj=ZGUXh!Fo%WV2C(-=P=B(y@kKnisYerGnK?|r9BsLB`E4TuheffT*BW*QNG|l z)%NJ(7Mr*#L-C1Rvh^Q*#<2@Hx-);g{2W#DZC)0$OK`Jqqm)kV!rlxVM`acR_09dI zWX?>ca>yC&wNo=Jf5MS#0wXR>aXK~1jA0F{kWjvr-D-1+MYD;%H(MCdGEkoS+|47;PCpffQQ(JKLX-~=#nkqU7c6q(kE9{q~suyX#H&B zz~{|r?`P;Ub7>b|*)6*QqRNA@9=dn*QAhY8v5cv(VB%) z*}U8lzZf-dNpj+}z^y4!XW_;169E=pUYnWg#*u9C<3iJ@J*Rg;<=A`l#Y1)?x0#C7 zjPI%tVTr{|Xck3q^$l=1Aq9>glBoyZd7pOXpq#eTAFlOUocoN|c7TI60^I+t*w_?d*$vdfj)8 z_(2CGZ-J{iSc>pkYChHeXBw;FqYrb>$Y5&)CocG&?_^T5&;64sQGs^B1_o~PPMWj( z4gHU>6fv`u-l}B4nc`rsWicOr4~}CTg$eHf!4!HdpmY9-6~#qrJG5oC~|kv zyVJZX6}jmL;it$w(XaAI{Dewi_f9R^o7NSPis|JK9l7}Z1hP?z51P*JNrE3=#uYah z?;s*_PI(|lYmM@_YEe7>GH&ERWWh~*pz3_&TJRm?9wfx^I~|i?(Yn}r+na6fM%ubtlXzLIq$-l zd1!i(owrXUes?}Jc-1=IB3*%jZ7P`An$-8Qd~Y+5DM+Z+b%(vNnw;G$pGCfi_B18U zPdv<;bDa0;lRM5IDIWwDSWRg@__~|g9L0^Sri=sl2^oGPy1m(S6yDdFqh!w5Ct*v3p~nvS|(J@x}$VEaGmT^B6|<<2H~ToN%&M= z7LKgPa|@Hkv~G;@3zc!BL83wKmR&!K2nqUn6ZU0k{z{>fE4?mNqcwW=byrarbv4hi z2;V%|>PoHrC70wijD=#{>n=qQ-%3X1g-l;BYCkW-cSo_y{S|LYE2S5SO>cr@6%Ts8 z^YD+iE`eK={W+lmp=Y7GYMr)^I01Z3Pxcmd@w#O>oiXi7zL3waGrIXDCZ@OMbqdYi zXP>#BukR#ay$9@0N{aJ26zqjeRx8E$#Bg#R-1hk7tg5nJGcT$84<-)IZuhP)Oh&pW zUsgNR1WLMmHo9J|Uy9Hus64b^@82gvbwcyE_PgTl>QLWsHU~o~P$T45Gf`0A(jIvF zLqcmp4f?&|HgYcZQ&-SXA*hiLY*$lcspPQ*x`7sfmN>STMZ|ZDtQqLqmFIfeZ<_FX zOY9j>t-orGGuC~h=Ef2*9JQ6!&(H8~bE91_Q4EifKfS=>mn{lx@(JRuP$km54ECo_s27My z8p1r_t$Nc&9(vpmV07v{9ybc}DM_L2Y|=*{YyrM&x?4{YI3KJEv-KWODoQ6xw5 zG43BLWbLFjUUbgaCspPKHeK1b5FEFuhntI+V;ZMVT-ELeTHrRqD119+ei)~Gl%xA?aWgnibiz+uKRpGdMv)W$j2=F4_ zmK9Op(BHKWCgUFO5!O_~S~52K0(9NuPaxPzj|83ZGAy3VJ_X$#&z)yIdZWD5Z7^i` z*gY&CMe5I@^05!n1X6hr^zJ9UJ6qOzWmaSp$~W+zmzrn)xI>q}%5UQ1RsOmvG}3#Q za09HPj!Ni1lQnOC#d(p#`2+^Btj&KOj)$TwXYCwJ&g1P(a#=F*y=RYIIxb303YIKy zwcDCinr75G*xi!rjK+H*aKrDuBCt!igsnOuYqUgA0Sg=kywmq&(zW8^>!kNj-d|X5 z*(}lgZCW@KiC4pukXw`GRI;iZ_!B44%34xjU9#7@935?mP!k90kHQ+F^GbB!oW6oz z^(~MnwfRFZC-amoFRPu$*}Rn(>qg@~&R>^&TVMj@< z!~E;szh9R5LDn8eYo}apx+ATWPADPT4!Dz7nqcJp=iguuN7SI`B{Qnn{Boyb!C8Cg z{C{=fPmiW}!AbL%_ccuH3eyqpqhggvSE3{k|J7&tkG`G`;r1wz z*LZaMx{naJe;d#g!k>mVsZBg0&4C5x3H{d$c%9yTg)%CteP{oCtUQD7`@F9^8pi_< zU0ZFp9Xip!0rD3<{5UWmRPw?y`b!Gug+?s7_p(=c6vtm~O(}j+{-c%poNg+v{RQ&$ zd-i${%l`^(8gxG6vs{|EZR)2_Zqx-Wc8--Mao&}M;W&6qUKV|ZO7_GIovpD1(&xpus-?{R`E9T)vZlAuC!s z)YNgPZ2Z*d6qG1o1^7X!I{RDJzaKtX-C}fRwbA^N&WK14*K8);>Zvj<&y_^B=UVzU zx&LzTO=aymxC8KKl19**1>JedFL>m36Ty}@8A3adonHJCt0ez_o=Rbm$VpV7DKk%= zzuFlW721648+`nZKiy@GPB&2~OA)jB#cU*eXNr-_%U1u|0r@Rk!%gRm7`Ov@(Qtp4l_YX80B0l(v6?SCD4*0T!6;pIY zSl2A7QL*Bt@!F!o9=k$-tPYl~=^~P+qpu^3PNqYOQ2$Ue2EaqU7tVVu8DQn;p22Z| z6u4gHB3dK8NtzI}w<5=+rBI$;mJo%p;^X*tjnMfc$j5Fbc8zCC*Ugg);ZDd%(XstO%G|;On{OMx%K)FUVWH5;?s{vvW3Z|IgtdeYXTF zK&FINrue-s6_**hSY6ZV)_T?v*XjOB1`mBx<1BX4F4VVt3rJ&gTnpX!OFTdbf`i?= zamm%R{_u=*y1eipQ1GBP{h0W7lkyA;Ql1U-tmTxppt+MzM`Q(?w=?u-Xtx7O#PpBK zeJgSin7N0u3zZ~H35{QF{}T85f^G)KUxQTmQky3P3V4}vM`=`ZB4~eyPriP%iPtoh}>IL_W`d#yDo*F+iCuFv*u~_^TC5!V8~? z>E5djkxThcpk(W{<6IyVhh{NL`#)wIG*TIeWT8?SdWXcKL!xKgcMry`@CA|2Cs}LL z15xwp{F2h3cYL+H;*T>pdiTX+wfL)N@dAL{E3w*e#aREan29JCYTRBMSkFh7yRf%% zXX47HQ>&QyHm*9GZ&Q!S#aZv=zsraOv;UVZ7J}2N_=R?qe(56AlsZ5(W$=l&Ix+ z8`oOni~W&a(0IOn;_=AZ-lCJ$^YOwjR&VcT_7eW8Ur$eRE5IN#3G$&DskdH9TO; zi#ikz!e8p`!;b=2uDXH;N=g6Gg?~K=)ENVi!9ts@F;oMi2ulCldOjUYf_Tu%_Pp_Y zAGT;csnr}bmu_MwQSv;0c^5-rKU}hlZSmdjSBqHE%D)`a-!v5T6yK9i;^N<|SJ^@vh5l~?`G){8gPxZF zGqAS?#}RT}XKsJZC9|0Ke0p5dKlKw33A1e{<}Er~Kbeek`7oyyJ7TX;F=K&cKEGX- z6sy#6BT2-m5=GO`^iS3OkHLVxY6yT_HjP$4BsUad(muZU#-m7|8bdfHTmDaM^=wX( z#wZ(?v$8rJf*O~veSUEyXKIM0!;*?JYPDt^dzp52r9sR}`0G(W{$`^8M`H^>K9qVq zq+$g10?9Rs2XNUyAm;J*5)Ae_TAm%5cCWgUk?uBc+u|ZSTykhne3lX)<~q5DY$Xdi z34!W=n)%x&c`cun!+uY7%>aIo+JPkBw#H4;^C5jtX1zHmX?x0(Wc|4@xCDFRoQQ1Y z?T!Kd^4_6uK&Ay>=?p0H&xq!~;qF@jg51)wCl>Wndi>LD1)$^h!FQJA>0YYlic5Jn zfA*oK#bq1@5LYO?dT}2dl#s1aExuo}2@5nL`j-j*o3w+V)_l+=H;gk!R zrK^L=;PJX8Q&FgK_&2{}v0a)kK#U+c3=5=Ux`<+0-a&5iUy6jDi`yVdTl1K7Ff!Dp{Y{vxV9xMpS(CVM ze3)z-bEK-FlGViT|C%=W&JT6#@zw+QXwV!~^J=|!Yxl{>in?LVw`Z`_ra!bBu~0AX z)Wo!|Qi9(-#QG+BNq$wS1yS85=l;7P``@ikRsQj0w<8OO?HTbJ4_bZuT^N^qd?Vv+ z%0-1nZi|~jBoiK=Z8By5e}YmI~S0q5?TeMt<#i}ntE%Z_-nQuDFT0fv`a-o8Hw{@X15 zb#E7xhT>NX~l zmvT#!Aj)NwhQ#5hL9UzXlFP-WPaL?gra3z4*#-H}VDZ0!GbfnsOouQdJ~(tAcs2eA zbP8KEISSJ=>fJe^q z^ePHw|3$St zwD}F;Hno*~i~m-Sdv_=}E;1N1|M(a6Zn7V7=UYthB(SlI7loV0M`IeIR35RT^Pm^{iX#EvQhuGQ3L<4#HQpP6+s{oj4Fzy3Cc%?@+E{ zo!NF4)$FX;r?Mc{{&Ju-S+d6RqDAw$ta)KEn8BNID{Nx{$qk#Ap)6CeQL9#1qBAZ2 zH#egJ`z;qvyUba`Zykk9B{PCs?3=5{YZCnFsSsJ|r41MjWTkoDyd{GFW&!`)%Pv4x zd=ysh@;ZVkNIUKv=9L5~1cS%6XK$cZZZG?R8a04**OUxAGgQ4;IR5_DPI4Q1$6fky zSz2x80!nQkSt--+kdjPQmV?%y?`}LJeOY_BVKRf@a&Aj!BDEi_de>fx#Hxdi z-Du;%7O*`i_IZgd$>z#DFDg(5ms|B(hRT)OTfmC4>u{DtwQAV1_n0J%MkwR|FbMqa z(DlNCBQS9HZp+4c^nl%*N70jP2qhEZk&axCFKacz?7Ky>VJ=#|adh*O>kC4u({TB= zSr?sbouZK{WhCUK>}l>YuQySEXQ~>zlb@2jXO$46R^ut@%Q6zPa_JbCDd%R*Jqaz> zV_Rk}n4Qs^2Dgc+#hXYJz{ zQHPK(Hz|P8tOXfItMdKq)RTAFz#Elj4$j-jAmX#RYOmfv%8=SPWMwx5Tu1)CW~L*U z{BPs2Je-0dS#T5K4+CgN!$td+i7+!SJf`@SS2|0aoX13T_e#XhVq|te|15XumXmDZ zge1Ib-M(45eK%CDlH(cL#+F}K|4iZkZZdt{U|F;UM}VnpRI5w99b9*7+y+f+@$ob1 z9I~>UkMZXU+i6F$CI{qCaeyx-=CbJxEshn8@AAMbmIylwU6aYS9rc`@k!{Ij4lnmQ zWU3XB6IRv9C|dxOIYN!+-H=seVLgwIvq4{Y3xKbSK36xZ9<-i6=#?pEIi9*|-UozQ zqcQuTt7N!S&=;>O7nvh@hUZnxb3box=GK=NM*=ES^YfzPYDxPBPWSj({r_}%Q?%f% zcxyald^hWqxBg3F5`k+2qMvc2ahxWF?krvXJojkfSqn1>?DxgWHIt61cGnf-f1%n~ zXVAHy(9TplT(hz-Zp?oi8Xf^0aXJ^rQbn#gDOi^RA`UOCt0v$j9_ll@Wb5a19~|S( zB{&QVb-rBNb>#Bg?1HS8ALOnZ4%g$H?sZ)Y#r#>D*q9;?fs%pQ+ZVv`!v2xG%72NU z{}szMA{S57omWI^{sN~+TP-tfs%crr!PhCzaWX$7<^i&@moI+Nyjizl zK$3Ka;o#ie4<40-KV??|?qn*~?jGTgIQ>F$kd?$^WH`^KBLcx2f3Weer2KM4v3%l3woQ4Mt#S5ue!& z17o{z;*(>6f5k-E2EHBj`_r)Aj)H#hgQu|YY#_41-)v8+X7;8M>sdlgUf>@0QE;$! zLa?2|2>Y0)63+&W@e(sxZsB2Ngqu0-^kiDYI!vjK!@~D76BEgb`)Iq(eZQVvtZ@o9 zwGOwpg2$rDcGZpor*IBwU=f1y%(otnH85r5!pz-=USb_D<-S|z_GIOkQJVF%0*r4E^AgKTJEcZtPd!uxlvhp z7qiVV7@g~cw2!z(WvBWtE}nlDmc>DEB&3KawQWzOYEH)H7WZq_Iz}hV+16kH-2Cx3 z$-a6lfK)>82t{$aM>b(J=~PVliASVMW{qj<{5>es+xUJ~5+f;lTBq4(8zhRG4>2z* z8ThNUIVfg7uJsh3OlQ8+!>;((>BZ%hL^~P{OMLe7b#Z4IpHn!pv!twLRbPg?@~&=N zUPAJ+Y}G7Z8AhsZnio*rCt z3?3VkNt(T7jf7fvb+e!SCr~=sU4&C%Udm)<8il+I5Ct7iIK|{0n2!MI}-6c_6vD-A5np9{PN44Uzm z@Os)=6*^sw!R!#NlwzcQmJm<4fG|PrHqhiQLnVjy>R=9f0R_n&K4`bWVnBKvt)6-zFE0})iTz|Y+nfvj zm@n1ow^qB)$~&VCa9$^<>B=-I%D}Z9699aC#;71qNbtNF@c;$?h?GPs=UaW%DBT|& z*4v8j7rjte5Eo=ygi{t;9vaNLiZUn0sS?h=CTNbnr%C@7GCQZjYW#XQroK#;c;F0l z-xBD@{`AS$357$EqTG2Vw|@n+@%5hy;aiCI{lGuo+NO`QrNp%f zz;cBicXS(nx)n3k04vbmc62oBh*OE8JUa{TI>u z^D9mEaaQnpuS<%C>P-P{=ZVL34RzMx&g-9@86xnUr^cT*0Z=DNI3trl*2E+3hxLsR znzN{dTV}S~pRc%fQDjNa^P1MRnL$-RrmYO?scS2BD_8V)f=Z*gW+v>nGcdCJc+4`D zVT!ayyz+&WGq(;Z7 zE0Eat-n+hGV{8cX?G>-KntrhxE)h8bHYl)9Vu_af1;48hO{q1F0!@}!*+qC>jQYeT z6_Ay$f!`F;Ay%BDg1v$9BBz=QhemOujATnZsC${)#DNH|w#Cv_*B+|Jw_NE!3U=?6 z@+CkSYj>)yW_u^Cu*BDHn9?SvKpk7#nl0vl^=T^T`gotL4L-H@FPr5r2(L^2job&qs;(Enr?AiNyp0&QKeb?IB2M0C@3twrgvzAkb zj8Q3S=%^vlgFbEvt8oYkR><^Ob89{2X3F}P&OKP0yK8wjQ$n%DG%@&dQOD=jVeY9} zi%dh6BeYPAC({kOcPjGE*TZtRoj`6cRJC7z5xo%|{LJ!hf4i}GhXOZt|GO!T9BiFQY_Mh6`5>O$_)JV~Sm{$z< z7$>ZMaU|A)CP{nAPZ1mCGEF5cc?buW?Ev%>qqn#RyRW0UM2=>TR?-$$r7I5)@@mvA zSyO@>?pX|Q>^4L1v=@^a$?dUyWlyj18O$@-a_xIUBe^j;F6tql<-&Z_j&i;%sJyY*37|iLKqK=((oTt0ZnDPod_Qb#&8$jvp;dq-ePY>MmPnpoBYN9GN56@E&Zk8b&xM8<6-e4F`IHt$R|{4~CoCk)&!%u`AIbX4Lat9or>X zBgZ8aC+0zLgNEh8OVGD5wIi#$U#Mm8$F%qnb<<;8W!vz0e3W~+GM?<$&F;8Wr8_pX z#XWE0yBc$6gW0;&(T})3!<3pz$1qf3nVR;-Uxb4_P<+*t$abSJFIkICN7Az-G)g^! zi!%!km6SwNHWAts;qKWj_5fO*a%0@cNJ6_fV(I=J)bI=8ar17g*u6!TK+g@B-jKP` zaBo3Ncj5xF#$GKqR4R92=*CiVaLVv(jJ&tH#D#ospQ_>h7kH#kTG0;&BoCKs$q+^T z!5qaM?CG&fVuzXne~iu2B-rNq{J`Y?7+DHd*G#@Nzqr3_m7u#>uMByVTxgfx7MyQ_ zE!3+7+lQwIPbq{X-@*M3_<%!X4#bMeN?5*!lKfbL{$@`Hxt-N{+70qMF6tx<#e1Eu zao-OOPdgxQgq5b+eBGjK8gSY5wq2SxIp7UVd!0Rnhen3fn>idK^U%mXwjJ9H;9q2cnNldG9QW@|ZD zT|v+ARkDuiQpNRsddC$On`WZllep*jf-aWsV9nf0LWOcjorNvbxr2p9C+f7eZDf^xI{336^+thVeroTT1z zerW5i7o;8K&==b6IUMIp{53g6PdAvjyKn@G~;RigHSwLS+|K zysJq$rTrHc^xVTt#k-^@$b>BKnsPI$H>{OHeI@Q*coh@Ky`2$#b&YdoZZL>+4A*;% z62Aky12@Hr%lX=gt8bX_V=s^GDC>+-hs);L^m{A$9Q+s&q35RcKBPYM!r!Y5Pt@nT z`uh=b`dvwsCC^lOWfbn@)mU{6Js{nql6r4z|Qo#MlAJg2^pT0FN3C3*riZ` z&m-Z;f%m(TKzUS{6C>ZWxZAf~F+L;MnMBX8@_q8f#|IZ9Q*aO^5gF{RkG1+ub344f z7*RQUjI70AVf$mA1ICt0{X%2BzfQ6YAW~OtH37*eC_VHGxa{Qyg|Qvr)?^! z_(&@aPnB!>;N84bzWcjp*>RCH0@4zh1JxG6s0<_pdr~ZS@P71RT*Z}`l!Y~GEOsX- zPd>(bnPWqY{^%s6gKW&MEY{b^-l);zx4P}Wb9>Us1Wqbd-l4Xi#bhuxh@u6ULQ@)s zkI~Ffx}iHw6-+0wFYkw>fTtf?u1b;V ztw_G2W-WNa|2ON@NG&9Xy1SBTxDzt;-`sfbag8clL$l~c_rXAKbZ){Mn3Jk7a2mDC_O=CnicG{Sr~$2cj$e`&rC!{W=4A+ zR8p;5tD|tK2=$#@Gk>UfS+})WK%uMF2BFN=U#x=P{LN|oxla3Jy*i`?t1S&)o|&1f zW%TPWDo?_*y-0Fnw)DfK+3(Iavk;Gi4J6B9xw*lMUpROed*0 zX6v|++oc8yLDG|JqcX6Pd*F7$F$)`3G0T)p+(y0LUK0^+rAoh#A6z>m2m7v1kpoJ) zxruRknTaz48_kX;Z=xBBVf!N%alLsP^dTpd)g0q&QhNe&i`u5~u@yY!oX0gsaVBBu z8lh9JlLaFPeno!m@7sf4qxfQo58JwY`0T!_@1JbqUHUZ%@AsN)(PKL`jppH#F}cS* zFM_;xP7XLf>SeG;uA_f|ob<~ZJ1Xs?=d+*yf=sjG3)Re($DM9{h&$EWvRy-9Y3sva zmvi}*t-&8#10ysRldU>vrvePdkDA+F+^48BHU!&8+}P7`mosx?oKkn~!#XJF5#qB$ zqE<@t%s1=8!Qcleg;7QRDTx-y%qJApLq0{dVEgRG;C!fuH1V)YxWCxmK@5W}{8(x8 zN{gOCR!i%dZ-^sB4hNBhE5(TlnU`WjK7~)0H-cZS_i9TwBkfsW=9Rx~SMt8`R~KQP)@SEgDiM;AwAL z%;fKUg)<92?BTsP`srA$^Ym-#3Fo!_d3$I#{a$$LQ?6+gtt)8!TXStBSXI%Y|7A<9 zUS0mXq6#GqRp`TNO(=z3M3XMjUX^=ddd$-pK`tFgUtd1On#}wwl}c0ERl5=szsB7f zS&h#6vWu9rE0p~daiB8zK>kYRMPEaH%}vji4$2AEj8bJ25m~Du*vMF$A$#F(s~FHq zO^}+wjoICp)WfglxV76QG&hg1{PF!rlnh#BI-hpb#{p5a-nakT;ew9$}IFUiLgt0c4(YwS%{KI+YB4j~zI z@tH)V{sEnl%(9uEG+y9Z)1p&fhH%>Kfd;Vz)t-V`$?A;RqEhMaGKCSprG8UwfKtb@ zVz*y4QO(S|AUXCqkBiQT;pg?XxOKZ6n4l9|CbZo)YXFodlgdPZQZ)}avu2Ke`$Ds2 zCK%i{{J0`M~V*G@{R(_?0gk8L#RvNn2NU}FO@ z{+`nmTxJ%gX>$pl(Zc*1%I+1q=H|r*c57a1S_ZKj&5w?)ZO z^eJ0Buo1n7>!8W>kq^g8^^2M^CiWltw|Och80JfKUbZYa)imxV=WqAByrOy>mAJQ8r83L#z;Tu zlEjO*=)ysyi-yyPDh2m9bqhE{Xs5Pdp6ft(lT)BY+>Tz|QxS>GzW&T?D)Nz%F9$J+ zH5^c_Z^c{UvTN?Wm_>R%pWGfeVPkNz%D)x;A>SWUE3Q!{QZ0i3=TT_A7`hRk^$xm= zTfyNzc>3iXdmO%M9G<~%*$pvi<0xEP%-W%qI88M14ImF~X-~v#IqN^)@Hz21q^h?) zn7w>5^K?+SB|gN6BLsjEQEjdy0*Cb8g?;M)oHFQexQ2Oj5D}4)c@iC4U1voRkhFa? zp2L{Ly@l)QK7mGQj1|l#2#c&VPvQ}=8-nxh1bx zPF+Z`ekbj5?GYP@c5t${s^xyWKV=pS#kng81Gi?-5F{w2>d0DJkS9N67TT2>tZ=+0 zV3!a}pDwJj3G>^{;!P+ZPIlVhAEF#>6Iw`qpZb)2LqrRK7V1;gTbpYerpTv2#-V2|f%BS5cH39FC zaTgrDZkyNAv|qWFxn)@RhyG*iiJr@c#@fU_?g;d~y)rOpO<|6SGoOc9>ysKeXcKM= zfm6_$@EH$BQK|K57sI&0BZv2Rrg)6$Lw{vvD5(O#V;KXB324x@?V(Q?o`1b&wUZgM zP~(A#((qh~LN$+@IWMT5h>vfF0JIA}Qah77xqLGde4|lDePr*_LdL6EJ11!o-&`uG z+J6(e63!n$jPMo)Xwkq21KK)7N%jDJ`*@e~y*(B%2-Tf8wneUW zS3Hf3B+MPrSXD|TRTwfZm#@y(Y>g4;)Quh5%)Ro99l>L}x**asf-iv#+U)VR^~J2c zSf(=1V9OFOnBG{uGl|B_>3hT=A*kRQ{-Nq*Xe16b#MG1AfD3(Yr}oylAn#FwM3;DA zzaw(haLDj1t1$Yo1(oXT-JTZ~)L7qD#d5;fbnx?MEYY#L*jH}X9HO$b!XLWojXn%EYs0M1 z;j3(GGEPrqS^Z1LAk>1qVJ%(kiG|ykw0iNIPWcwbq@F$h#1M&_hhqiptb- zQE>YX_UT?4e*YedS3m26=}YDsU*EcOl&t=gK0lAV2Yx%GYaNDI<(tqy^Y~nBScRUp zo#L(#NDOFsT_{%8C|6~Ml>9`&?Sts#tYE7SI3!Xvh*Up`*MpEW|IWFE@d1I4hnyw) zt+dgEPu(;<55K;bZM$lU8^d$jtEzek zf6rE%vDL{jgks*NMIP+aSl4U%c_&34$@pP0I!=K%py;@PaJ`~g$9f{7BOfDu((~JnX7V+xuI;GimMG$j zEe`cu>4riV$w^z6v@y~0^b*-S?-WK;zl|69>QCILUt9@NtLHNbd}9+jSs>#t9tcx2 zOw%<0FF)tSBhfq12ne*Jg=Q`>ABCc_pk^Y(i(7MKQ z^47q)1@=O^kO06SxFp5q-qD?;FYY@2;yj2VF=-E%y@8v)ybR05<1@ww$AjNH!FD3I zFrk-m_A@wQzR-~;PL&vB-3k80%UX@{+{2A!Zu&4DeXZ%M$s<`IP1PbY?CHFV&uF#b zY#ZjL)mb0n`nE2GUQu?glFTS(q!525#_d%DVXrLxV$V*k8#kDj`2!YpRTaF#tvS2! z)EVD&;OJc$z5Zj*axsf9U-1(^{>l^d>m#VZA`-~;A5=(BNs{tOiBhXUA^?(Bkl30Q zAM?bPE{4rybyuvsKW z(>i?E>i7<8*5P6j$JNrb7tzG)>Pb1m=vUh*>DCaa?+cvNE5E* z!S_@WHnm00&>0OQo?v3<_YjXsYfTybC^9I7;DM~Yn85y~wrN~p?E61OApbHXeiQ^s zN?9+ID8pFa58IH2J5FWVXA9i!oYiDTC8X)LFDP&u#jB_n4i#Fl=Lyb}t0lLwv!}hb zq2+(}w0Sb`Nh1SkhU<_4q}I|gd~L#ccFM}NW-N*Fq0D10yc~UrW7Lz18R-CM-FNr& zAMlujaBuZ*buw=Snq##!@+i~RaogEB5xE+5NtW>BX9KlN1@zF48rzU?+BrYZr zI<;28j3ehvJJlfk#)1(ucKj`2rJitsFt;yhB#-dY;ch2uOcKn&p3E}L=6+%SUg0p; z*0yS;D>AUPBhXX9UAM49ZzAfbZJikf?<-&ch+_v1HQ5v!k%ogeqO(hFuPc3DDb}E0 z;Ly%er`BS*HgKN_ISv|n%A{WW3f5OCpywGiru+P0@f8x%oD%uIh?FWi((+ZlH0{r! z9Th+{9DGTQ)C2)A6`i5cfgDyGzaRV*mSM;^HprBE>hH|gjlPtkeVn<*V-azgWtYk# z;-hWx$LFP16XvVAbE7>4!St_J^5-l+lKiYS(&a#4Tg7T}k>CS$#rA2Ckx_Blq4<3w zAmu_t=oXGvp)`WJ+1xsJ%6b;@AJA+FIlq?49aakXHC3kc;uVFOf7P|;%XAkC%o5q2 zJTte+5A}UZEBjvCQETudz5fCMnA+`8qG8c~WxAnbd(7n6PI*Doh4iHqf(LhcvhhDA z?9@DPyZc+RX9r+!X4!(nOo_OS(k5ku9cBcL(!46*EB?$@ zpCBN05s#$X^-X%Rr#x{-0}@0kohpcbpZtbner!FfF@l-faO!GUD)BGRU&!9TvoTbi zt?H_{cFP$zLFzhA3s?$8y7%z@WLX7bAMJjOui?c=iMt}{MpGeqkJ$+=&Xjd z6X!J%vbAm}M+D+F%@v04$zH3=5zfbjh#s$@z_d6!12U+y^g`s-OqR$2IZM~Usc;EN zO_MB|Ujq1Nl)xz$z>8YOR$qN3?`M|WTn*ap4srwD&*SnE0Wte=9K@GzHsH^aQT1iR z%Kuu8;%Z`|4DEzaUmGubYE|rgjI=k$>@WiUbi=d6IPdkc+qHYb&s?>lB9|dSyH^E@ zq@g6a{FYnNEqR}?k4>f1l=Cs5n{L`iNt#dV8O@Vzr=KANf}WX-^4hDGag9g61pL@e&d8X^ z<+T3zo}?W4{9nCdv;klRu`Vm|e$spr%tF@T`<-E=jHe#WwGq$kB1N^`t6#G^@x9Oe zcq_X&JkC!}DEo!suD!Bs|7-IDKFV6Mp&X3PMGLlAk6oCkWQjrnKoeJ_ewTHbjd=GU zThUg0^|$3&1MGB*P^i%$zQj(g@gAKAOd?n^cdnDtH^|LKcW`hBgTHrtIH^@Bl0n56 zW@mdBkoo7V8~i-VU^&Jd=ag~F2q$U^6{XdbwKQ;^HKX-|noOQi0KjQ98k$~seCd@{ zxJUt1&oqA0T>uo#Y0n#Z9CH)b<&QWxF&@^K*4N0T!F@h$iSS5#m`-q_;^l^R_9_gSVwPhH zK-q>s#U{SNlIwq9?s2d*-TOthW6u#RDh{&?$t(Auboa>( zCRupBS-oLJT0Ti%;@~`+j3Wn2dT-~DQlsGmooDLBXkyaZTj|A{yc9f^Pw}$sXNw7m z$K^Vr=M%sqSp_YwEYBq%9UoVc2Y27+SbUm9P;YrI<123;U5A_~!A6SkPl-CQgzW2S zN>j-9;Vr*t`_BA2=y=${XK0nt-X?M>u?3w35zcp#oYnXQVLa<(0 zIuKDtj6Uo(=wE=}LI^{Bj)YJwq9tkyj>rWU`sevtD&S&fe#ZH^63NBtBhnDEscJjJQ zy)-b4s3lUgINy8WGr71{dxXydoFI>M<7jl9B7kh{P*in1(=EP{uul*9R1CJ(q72yFJh@H@HmFmwErej$_I zs2~i^f$)Rja=-eTNX$2?vWKai1gDwXwU0LI@D~c<9>=ow9~$LMvb0bz1#pS$INh3F z&RJ)To_(o_^)Qn2pi89zRj$V*y`F5?fx<5qvn zN_U7R<>A0vcYBkQX91G*&NV4ZxCg%!a_|7_dYcJZYw!M0-9hmzOMCnYJ8q^~oi!LG z@C_@tgUdJ6%-g9n1yk^7t#j@sRn03-SoiX@tOm|E)>gd6E%-qo7DuOG^@HA{Vnm7x zZ()B%w7N>{LvDC?p(%}zZSKsi-JmT8+e8xfxui!KfGj@4r_P-xrv&raYSkRih7>=? zWLI4>8d~F1K{pD8*XMJ@u&9h=&9xNw#zNedk^`X3exA-rLe#>s#hAS2# z?1cM3w1Vht3Y zj4}D^wg-DkO>N-JHk~%Go#@;bp6D7mehrO9%Kb|`XNfbC3VJO<0qfdy@#^0_F<$yD zl|)&&nw*R^kDkE*d zX@L|z5eL?df=J#U!)B71`+NbOir5aflMQyDfMK~xCOAP1dkmMRS$-7p!rH@YBjC z-&_KpJd+tgI`5UH#aFRwHQA9D}Cb=>u16cRQN zAy%YutZQ%3r)bLSn^@*6yQ!s+wvZjM?f!c`?a}#Zwd?y}4;VzS>$+|c;SA6KcnJ)@ ziys>}#XQxliSPHCYX7yKtG?{Dy@9Pz@*%CNkv29GYMlbQJmi_WaM~P8vtS6c-OhT) zCBRm=dLhn}&4~wxX%KolSRWk)L>=K%ywEdUy@g4KE0m*b^~=&H)0571MeE&sbEJOw z`0IoB>VJe%*5~Yde_7{WhppssVD_2A0_TsSW;6nx9lj|6+U(1`B!H0(zxonND$?FE z9AS5+A);%+vr72|Q}47@2hJg9K&#=R&0+QmGtr*GlHO$DB_WW{l(Pb5y-~V1iFQ)I zDm{clBx$??z8Puqw$br(f%aVAZ;#=t4@?UxtG{E>e7LF+R8~o z?cHq&{+y+Sdah@jTkHHCyW2lPk|~&hnro}8nbr=HHNPajlw&A|BIf zD0XH?*=ij>;y36;j3Q_O?e&E!*uw9+!t~PrwW)vVc~OU@n)PA|3UXhNE1^Dqaiq(F z!oE9rPd!*#(*w1plAS+c8Ge2Lcb^2iFUESOjtU89We19dp3g-1F_5>W@p>6J-5i2aGElwx^S#vmMt{$O&*hYpzKf1 z>los8XQIohjqdJ&tu}sJ8@iMX3Us)#Wqwi8^0r0;|4Rd&#>dPry`oAkz%uaitZvC^ zxg|Aj6PjxHWPv5br@eJykYrXuFGKz0V!LjnKzoW7;TbRmbM(-;0=~c*;tL;7`My*H zoq*J=^)F3 z!Qm+#Eb-ZB8f4m$S=zR=Qmh64*02YZSS7;6 z`cKR`!fsD9{g6Cm@Gd;ebkf`2DG1v0VRy+cGPP62S0zobAUM#S>j^&4h)&F#oP6b$W7K*FSGOd*#QQ+@W~c+hlZXf#WyH+(%rRu z7&a9%6Y0IZ>pkiWQ9AHE`c0nx97d!<&dbjPQ@ihRg7S3UcFn1Hh+)|2(fu{1ERVK_ zS~g!$Kb`!~f}matpvW?DevxtXWe*zhyEDyAeTlfX`~HA*-hZX#?S8Hyf4<#Mf93(M zyB6zXnrcr}&MZmTh;O%mWyfHNmqIh0s_m+K?r$~yKjFg*X$iox3~Cy+y4-7bd{}$b zNh+aPLjyQ2U%ds>g$Q#+jf`(Z{QR{4Z3aC59?ooOJ!;3M&q2fqp`5GV*M~s2Fta~M z8GY57-@RQr>@>VtVq)qccOmr*|F!sleKc{v*OMt+u2vUsj=P@w97!(>FM?xpcSvC0-+}*as0{> zY_6i$n#%C^I|fJx1rYL0a8#NN;M79STT4-K7V|Yh>}K-fSsRgV9jFMM3>KuPSRo>g z_GP!$Jh>))Fvm%8MCKKekUs=jOvc{@X+{JKo16ump42#3nbvwZO`PqAS}T>i{L?Z4 zDI*6C>m{78vuW;W)RTdrpeHxFR!copo9~A*YZqyEbDpeBYUb}$I3UTiXn4CN(v$3H zQtj?oj`Re*6_bBn+{)cC5MTLJH^C8VI%>H57j)zQ$cf(&6>zJ@UDX6JOX;(qk_<39 z^>d>5p;L1omh|LsXupB(#y?2aO^(~C@ozW^S*E{Vw2gn42n-eJ3U&O84wC=gZ~i8K1EYiW+q+! z`%8F$T1B1$FE)Aaq4433&0F#rf&VP?FSabz6iBIJ8nO&ZS!M!<5-<|BPbXQok5jf%Rl})(m)WY5qH`3yfHXmbBz`Eyvf z@Kf35{Ss2SD-W;J-0ZD45~6haI2N2u$;BMYmE9d&vDX`8e- z_n%D-=Oqt1*ZF5z@*FJ$NdjXP{N)O2yYC!cn(y}nCA+>EvG8QgDGM8cl$=BcF?p=y zpkQmN*tA^_i;DVPS_g@O@s9S|6e=r8G|;jh3;I4c33o(#C6wPSx7p6_nl-QYxIwA& z)!+GQX-EU2-iZ-NfBem%OAq1iM1o{Sl+h?eCd!>RPJS$tAc|ajt!?1#tG*0!W%{%e zuj+3&v9j$lBKGVd(D6rdZF-5+WAxQ4zs93K$%Q$SAFo9$mFUMeYFW&02Uy+b2!Pjf zlkz!n`!lovADG_+K%Ubu=y=-bAX8J45IMtyCi=$< zME!WZy%LH}1b&~i^k@A~{R9}z2m6=O-T!81{w1^0AI}Fo{oqnM`bP-73?v=~r>TSH zf18E$XUXs61*CMe`1b1GcC(%@p5{Dh>u+>BA@I-F{`!yt)qtEntAAPgx2?$MmKmTg zlL4=Q^D}4oyYoN4N6*SRjGYkm`TRW!0p|998}^?~{NINC*X{eCg#Fhj{ZA$Ti{1Yp cW7w%w1ikF|{eEl`bVhD4~TGNTN83q7sp&^xh#NB|w0T zq9W2uKzi>T5=tQCtT=P#ec$h#ALlyX_jBgDxW>J+_S&mF&;8u@z4miMea+)67g(5> zn2u{}-8N!kIzVRp9r+d9Y3dmX2md?ZYovLTskoJE4qP1ay{T<-1pF6r#OWEhKI)}q z;mgFt_L=c_AV!pp6SVPzncPF%)4QYK=;tlvD$~>>b^p2tEg> zGYqaQxI!Qb^1+;x1y*7&OlxKb8$K_I*oAdrB70Pz4RaZev-h=jbn zJmi`rL{d@=v=H+Rf+Oq$#o)e|Ko2Z@Kl`{1^>y@tc_Cn)a6U$#_70wY2xUP*7QVl_ zRzo0sU=Dxx4)+ze|9Quc@rXE>G{oM?7a}2kjWH}fKBYg~E2ug7GA{poi80js=f$5_ z?y#S4^0N2wg_;C;L6rrKpuV1dK910zJun{ntCL$kPWd#Hqjgq(yt^nv8HzdQQ# zk^k&Q!vXXnEh#N2BP}m+T|!n~TJB#D{QU7h+nad$Il3^Wq9XZszyG@Tv#k<@vAXWC zKNsca#b2xP_Y;3E*`E#nZCn1|x5~-!?``t(^Kt(f0#1$)s5{gH3P&(DN#d_fa&lBa zz!2`xe{GSPJK{gL2*jR(yFJ`lSujw{3Hrd^&mAGCa!DKR=7%0Q=>tXb znRvp3lo*Zv_iYgNKL`8&wZI@R|6bw$7)7AH*T1CzXr}NpbUl4cJU!i2ZrQ{A?Uf+^ z_4faDD1VL)WH!ig$lpi+F8;<6C>#KY4?qfn+*y4lCO#(Z+iE6(iAzI4fhJS5tu=!y ztQU_4e_}gu$^PUo>|ah9re0M`(>R%RgPEB;bIFLg=?bd2nsy_yb`H2i0I{t1eIQsF<4g70$sL8gbD;$mWYnphrEiDLtTN`__SZi+!hO$D&>F!^naMt%-R$ zF(S-Jp(m#%{Ru;lcn+bx7k@}3$$8)85HT?T)rPsxv>KIox^wPC)=P@fa2uUQd+lmem5|AT*HVK*c30`N5jv@~O{IWL zCi9=WTGLVG>nvtfakagE^@7@o)aK?pl-Z73DX7gpC?3qJDpt%Y`|aDe{9NZBzHoxa zqLFGoc4JaYuk(#4kwz{pFVMj>D&>NlSE`Yb(Vmjl_NT+VA*qVXm6t$=ETF@Wj}Nw>#QVn3JmiRPbgzbaFh1FcDl1*qN4L)=Gx|BiVx*+;B(6#Q^~t(o3b24%yISW@bK#;QQ?pr>?{at?G4-a`13Bs(nVmd)>O@C98@bowg+^ zEG*n!FT@_oa|7BGOX|$hl}7Icl8SA1(^X$YMD#p6d8y2mB=Y6+XQ9i#`yn1aeC`S% zAuYpQvg~j$zxg{Awux27Ed)%VXGP+%=50eEkb|UXVdGzvU*60(b>Pf}3;7)xnr@Td zBKu37u|~$mrgb4fBrrkoxPsBM51CjC1WkkQ_@u=7pgV_$21w-t+*EH&_4@j@4oq9d zt>@}#w+FwG9X?I@2#bsBdwY8`kI2rPQZziq{6r_MJSHR{U}-Sn%xp*M>!&Api$8z< zeB(sD;1Q(6?Qf69ml_3Ax~E$bKpe0eWoW#*4(rSWKRZ{(zG(X1+pU(LD zinBmF>Ix%6F37?cH@vMIsgwoESQsy|21P{ExUg#*ZK?rfS2j}B9&;HeMaRZw3+TqW zkn&A+w6!|`H2G1n5B?}#9e@YqI(=TU&X9adQuyT5{j9B zt{HFZzk#1#A}!OBaX~zHW$q2Zi_x8 zE>-kkhYEFbX*U5Cvfe1ToB*$G>_Cf{7cVAXvk%=}>??hO=0Wf8IB#|584m$0MO=Tn zXGfVQ`C`vYeXYgN(b$OIJYzxZ7B?5yVry$_-Rv5qmi#7TttCluOSWx?q(mckMMRW@ z?D$}@YqYHq!tU0}invupVTL0Jp3k&a#T9ErB8RA%Tz`X9o6ySxS_kfh$NWSCH%#@S%Cqy$_|Ol)a6%0{tWfB)LPg9KbtnvlPVGD_&Jw08qUT z4;(~HemjZVoPY!c1)=Rs8lrkNEG^@ovT^5w;x$)^2as3-7$wn^peVS`m_N(dU zcgDH2#o=13=g*&0$z2BA%Hje7>YzM#ev7<>+B_&DD{JmqONqT8`6cC)^-{?goRwkf2~myR`Fx zT-u#FC(sCx2;izBmQD{G&q+ZW<>)7s`OfI4EE!X$SUSN=82g)~g6hxNZ4KC7wf9>d zv{dQ?{Np`_zT`0la5koh}BfJ_D5W z6XnJ>P&wJz^O2f7YjY~RfujfX-d_8dvs)9rxafZT+_f7UGi_Tg!FDz0SscTX2>t@C2veX{H595(R$bH{d!h14SYRPE|Q zs;FBlcA1Zo6a$Ju=vg{7i0ZedsNw)uxz!NCy)hsWvh&q_@ka@Ask}F&f>_Yl*w~@G zHRwx{#e+5LYEAkv#yD0cd6Bahp-${@)W+y2-|;10yIhpq+FpU`>?BMDUTtV(^yb$SJX`>~ zxJPb6yQBX5;Q~uUWpN&7)~2kP z>28lHDP3Ej$~q1$#;X{al}F!P(sUKD*;${WYz}xHMxIj-O|8!{E4-IRSg9l2S9=E_ zFA(*V>&%(#3Xg$&fG{j-uD4^>nsOQv=Qkv--#g}Y~!_upaAxR<5! zD(CSWxSI8FFh;;y_|@8Vs~D5ijT6te!WZAXb<1zI{bG@Il@Yi@nHSYh!R+s-J6jD~ z>xda=zto7}$|LSgLGlgLKB>EXBn-hBCEYmtPRFMwtdO1UA3yHtCCc3eG0eikB4VoB z_5ccHAg#|{r6lyb3wgE!xmeP`&ckE-+xHLv%gBuuS!pEMC1uDd4wUk?0U5s%aT_>pdtqJ$|_Q&XGoE6rh4XaA*s8;XYBTwKCoz&e6EVzPplt29Bj z_^jfqYO1A`6&2$${YJ8E{Sr`NlH^HNVdOloaCMQd7;PjhA>Xw0dw=jX8%SHf>D#pU zsKms=;o4wE7-W<8GV9gHCnlsFzaAS3oOs2Ugj@z23ri=18N#}*Q0BTC*0|Rc1C~wT z@Z!+NkIMn3X&S%PAzJfTReGiMm%%m?c>8x0{1W*%?68*0Y<0$R3HUtE!5Uf4t@k}1-8w@%}tU%Y(TJy_*ynrD<%kUR&7vzc{t*}C8$d&tSIwc9JibgrD^{xvJz9nR;b;x2=nmM4Z9$6 z`YRTevrMF;1q1|`K}<%N>j-aryMz^zk?EOei}55Z$ux`%H8(e#=<7$+?M!oOVmW2p z-)2a?4*>#Qtg_S45*|W`28gVfY=!yp-u~=R#%LY@FA=4|-FM$)+<%O^Tp_yR?ZLY!q zxdWC2T_0y<4d_-T*t2|dT=E2OIB+)nLkfYylo*uUHPz!ZTW#9c{iVPyQBkdZ?5sXy;zRcwCWxT1 z_e3fwDE)m~kUftb7t!c#Lc&6?_OlPA8_|2J1=4FIkMB*sGNd9w*WPFCAMgtK=%miA zowX7AegN3`L&$Rn%=h+9KOV}F&DwS~D<1!vzzj=7pGk)Bf7&?TczN#g^V3fhZb6#q zrQ?BJol{pxYgvQVc#W5I{pYo@u)ec(wLAK6@*AQ_1mn{X#a@CsNHQdlO`vEwJW3cJ zJqskCZy8W6n3bH!L$R_QRz!5Ic|*Q!ZFR;H-o0;}7+;A{wHeSLjTsBmBJGN7m%2I!#F+j29+2s3L;pu8Xd67~AiIju}O zJd#}Ju;8zH`xENS{;Kj?7XK_D@eEDRnEd0^dPu%$K{gQL!Fx%=09+U@;CxpOcEXWk zO2<`Sb=RgQu*Ap5M=4pv573n1W4fIXS!EfQ_8W@+i4I0TxNfhGJ>tL<>UHa3AeQnan# zyScWu79J6?8MqrGYVP_aoWqvafI9VR+sSE5YKV z!zqCkPF{6@U`dNjTA;npoIjsuQThNN>lZe)u#rLk0gs4^kq^)pJeWOiEIxoR#1JwR zP`77+pJDdkbxu7Z6Buz3yi!2;f_gL`J`l1q6$ki;a~i*JZi+m)}W3!zYCEbPtBI5w-R8{r7ejCmW-rUAuD&^zD)J-NKaR zq22VUlMG>MTZ_!|ooPiA8e8XHIlqaHj7-bSy!?t=(d;mrbx3wOwCT)oZUqzBk&x1i ztlN+r-~x&mf9*T5e%3bd;{@UNnYNUb(zXvkTQ0cl4iN$hK;?^oUvF+|>UsgG%LPF_ z7siV=)X;d!uyPQ&Ph{NhU$U{nB|b24D=-+IO}%nF(V&OCP9T&yVrOuXgVrM$>0&u8 z9i2{)pS+;x>VniUPP@qr>f#@36IbrMO$7$aPs4evK8&^1vJC_zKxfzHw-VKx{caRM zd2QC$n&KelFV2XOXEU%!ltzI3D^6LnCoHWHC?J(EU`R0tD_D>;P-|i!cD4W@;#E-9 zzzRi4)&Vv?2mA}fUZr44h!Jo@D;H^%!0y4IN_l31SAdjR%3n@*k1sYSIpngh0Tx7WAE{H3gf;QzctBN{j-&j~MSr zeqUGr{L@3u<{{tJk?0({f#3(OCBkJPySkbQKLMT7@bJfWug*(pc-E{vZB6#8_&Dr@6t0e{HB}F1LSF16M-iq=ksz94cq~8$Y#);U$0Go zu#61Dk<-!AG6Wu7OmcGZCCvzzg`OhnWR!upqMCufe+4+){2m8ci7MbXmjZiiDuh|n zixfA1y}WE|9uR;lXi-hNHqSf8t zsTgzM=A8yRZv}SVl;H2dh(x@*(FgdZvX$y!2|2k>nRoP+CvdwGUwp}kTYLF2v7 zGjVU)bJI^A2u$Ig%1JgNC!lftcu(Hfj^>5;?sjGCiIQ6$oUI1d50}A9qwefG@5X1v z*KZ(clwMPS$NZ|xI~y}Gk&$ED39S0Zc*z5$8=}u&9_cuK)UqMNa3rADfJmg^b zrZhyG(@5X7=MzmGZH+$XplQPkE*L40tH6;I*J&Jy&bLn+Z~hGMAGwUp13#Y+@2^ zu*J>Jo*BGSYtAVPH*s)CA8|;=Au03J`2rl5fg@7*gvxd*kXskynx;0g)EQ2am`!!J z;A!te%*=qV-9@f_IZOL+$Q2Y5MqzOQq@2efZs9h-_-?>C0nwiW*v_!i^^=w6HYO%@ zm1By~^>s!BLL7|L+py=K2({xPQ5tp0lq(}diKCgIf^js(?1YPkM)1%0R9*L()bbdq zv$++R_c!y}Z04n^$ZL%*0UpJ2MOm)BHfbMQQefw&Wtr z-UKhp@#B;M=V5L|e-mKo0hK>T+2H2o#bH&bS_Z1LvYR(=?p0(5-M;<%6@%nLU^ct7 zr>aH7J*kb(%@rE*sy|-6P)uMcW)}k|U=|kY8#YVQBZ-E)s$%8|igEKxLBY|1~?O~~q4{hTPfGOzQxpRzsO^3a%;^{+BowN7Xu$bAroa9bmDljkt z1!^r%(P7(iS5r_WfV-wWKU_-ytj^NQ-^zrwd{WfBI5Ar!hxu?@lJpH{{1yZ?+1T9W{9(` zWj}Mq?6PAFI_TgU*k{*IzaO;(`W}?6Owb%g-!B+ho${$N$`4d8dDqG;DYII%<<- zfD9hC^>v=y86O}2^V}xm^HHDO^<5>e&rAM_)Q>)Sy5ID-#(b)36j+;ETKvk)%4FjR z8|&-fgx8Nedv^&~ZNR@a0yP>K;~XbXrU6d@9Ao7I^~3C&KXX`#9w!JWAs6aZ%bdbs zRaI4gm2Zy!;*Ye`g8D+z(xz!?X~5G7Ew0_Pv@Yj0ZuQLxCNXfmJaAX_cOy4hA0sJmwTMRT~^V^p-dd+pMGAy)Nm63~pdes|PpU zsn~2pWjOx+qzd8T9_?z5HEeN(a&VkX2PaqG8@(6q^amwrH}#A;zU$wshb6UK?dM$j zWh}w7?keRiXa4w7IT_(l zAlLBuw7^`8rglg%Bm@oS0%K(VOoLZdC_*>bIck{8fYM^Um30?T#OFa5*>PQmn7o9f zq>RCl#wK+Q?^m2<-hkh4VR5;5Q4NW{!zx|Z)90YnV9;;Ho+ZQpvyJH%R*)XoTiXvr zyMR!?+MSO)xKgdrXyfYUwIWBWgy;{o zv#xyo#GK`M>Or9nfUGkV#{v_Ut|D&NGkXEn?($#0AnDTI1qx{R@MKfQ!RYvx7ga}F z4vpb?14)&NMh{WIw%qjQhrOv$s1VyIX}b zrQRXc)468Flo5BY9&j||3i!z9!7xTgMRzZ?5sm!Qex-b$`+BC%!a-)ix_Dm!o?)g`)9s?C~X<ptGvfdqB-3 z*&*!UgSnQBg@OWr8McoE0ESru!2fQ6{YYRx001r@2!Mlaf&b3sgZ^_B1jvW`Kl}e~ zM7?VY0RSKXnGf$ic>qsx5IgBUro2w=WIIm^?h{*tB9C*Tz57s)!Q6pDQ&ZF4(T4(x zGzn9mO>rjb4V~9VypR^xCPGSOO=cvv#dW0INm(D zV>fkR)Kv6xQ{s3Yh^n_yc=+gdlMTQR*q26Cs`KI{{t_~9A{D0s)G|WeR?Xs@?Wz6k zlbWUs6bMeeUp8!oz;8zz8-EuBe$_H>TAo z{cjf3R8Wcln`vQJ`SJ?qeKoN`@%eH(g{&XqBSVy97q}5|B2g59c5A!qZMFk8oANqM z;{<_Q2?3MfG61;5ugQk~&%v?wO1J0**L{^*>5fvpb7^)yNctU46Q-~`a_n&+3Y9RW zUnLKa86fj{kw0}s@x)D09dN|wq1TY^W6<13Gf^nT#(s(OZ`Q4EjM_nE%I}04<&0Z5 zOSBzkwf@X2{t)pu;7g$s^Kx?glRTbtCL=5V^OyW+4imL94Z%e#4q zTWDL63Uh9-MEe(t7@2`{_z<0jZsVlP)d{rSF}WcOrZhSJ5}zH!f7g-7fra>x-O<@* zSJ{;67VAabmc$Bm94@82RJ%1CN>9mu5;A^cbVUX@e&#~N!VJS4>-N1+Vq(Z3hwn%+ zVQTsKOQKkIRJKCHu3TSj8du0umb_GPG@&q%J*Zz=e}Y7{t6iwh5!0E|auVq+*ZK~* zn8}7i6!_&FAB2f)F=q2Ajf7WSAxDU<&IB4bG+6IVu7!L-BvC}NP$Y@Yq-nsp8#+X! z`cr1`x0wZ}4zQ?gv(fu`>XB>t6fT5Uk%i{p`M^T)Qpz;;XURvY0uO{ZzLkj_8U;48uaaGzMsayXWJ#L&wzmTsj#%v?8x zd`q?r= zP|9e}^1b67Y7|!DmBog|1EB<#wJB9GJ01i$xf|&7(}V*bk}C8g?r+76&G3MAz$&C6 zir(mtOKD5V&`_LXpMZ6ekYFAK(~)Ia;AaM;?8_-#EUcEQUmu>vSVAjG7OkyT^u&CF zJOAcp3mjf8u3yYN{KoDh^)&`^yj_Y;%V>yMj)#V9azxiqxG&VE{Tf1dRwK2|yjCnH zhevx^cE!75%wS;})YFzeqMX8cY2;~fi}cT$ig;WUPesMUG2r0}`mxOt*zJpA{cK8O zZ1wUGLEwv>1}gkhOQPm+L^(ztp(ptMK0Mlo^Aj*%TM0whjmZ=+7H{!t+M>98x#_5H z>u>#ST-72v#w1@nFVMBIjmU$Ibz9TjwZ`3F%l>$)Hq`xwa#&P(tun0PdsW{Lz8m(d z0xq3&QK%M%g^t^e`1KK?0AnVdTIUZVf>riybxc0f4!4oi>Uwtv3`2wdunNHwD@5F| zfa&QXrhscc4bf%HW`m6%Z~>*B!4uLdG^zqqM$KH@uKcn@H~DpSQ2}nz{LjmcI5`YN zJ4URP-xeBzH~B-Axdt>LkTYsKZAlSqq`Kx$iz%bM5*MHUfO+oA^2L0MT*s1+E->D)NuGH>!)xFV#p+Xp^arc7)VTbis^frE55QSuHQUGeJ9!6{ zP#)?chzO2pGIliG^^-+~?zc&JFT{P%?hn8SaLw3QD=?S**=}`Bi=l~}Er*&mNwgA& z*tu!HO7@!UG}|UII%Ky-`sohg$3?@e0=?ypwHzv4*teD0>T=TQx?hW)IqmjSiglj;n>kE=& zd8$f;GswlDNWMojzfe`DP3Mn=|1_PhGJ=gN9ww3+?B{Wm*P^VEthGk|j*Co>wQ^~+ zEMc}p-RtyDC7P^YudOi;6KH)W)DmFbQA>f$hZh)vA~v+Cxq6kLnDvrn}$lNhxB z45sE0Pz4aR53uT4Xnj|mu5}`jb<_-fM@Z1E-K?#MYw3d(paegDU=a$B`uC)A;Phjd z$IG{IGnBTVlAh0hTJ2f!8}}5KGL5;ZoU_D>wk9gPRl=(>H%!%&G9%LC1k#b$Tbc60 z{RVoEm`SRX5#{fH9lDbkC1(&%m+Vs-wIx_9gL6~QOazlYHkerdovV8{sY^`F0m`W! zx2+Sii27T+l-~Tks;YBGI`XSv>3GD~^rM0zEzg`^IS7T489*Lj0@_RlT)K$*ImS1= z&=nS55yp`u&E+8MO;lF6RP0_cR*LhYRZo=nWS!>FjO0T1eUH(HY*vF*`?iEQTPYsa z5Jy5i!X3(0t?K0;@s)G#EgrGy@l$&6nIdE4aU-~;;BCCFFA`B%Cz65JuRToplH=Z zxJ^keYT}c+sXzK+mI>b>tUP89B%{%|J&D#W!L_5KzqW+M0zt!Qv698y4*MxYfe0Ga z;$Hgjq}q0yteR+FP`Vbu$SyF#y?pY833XDHX;=vVuw6VOJ54k9LZ`M>@sWwk{XAT^-;rCQ4hSDOLav>-6?Ocsn#M2L@*S~pwo3#Zs zVPy1j7mi!~Y&VGn1rS#3xYAh7eYYCsE)wOZ?|cb{OAWxMGXhFkKt1q+bHS`fW4rxu zrXu{k_4<-Z=IccK_4B?KRtVoGae|rXSqM;g23Y7pMc7 zHCPZPbre{I<lQ#%J8je$N6P);%@9AuO`%idEKpSlYIr#RKd)C&oO?RP~1i znnR?h1&wC6oZfN@VoYsdmD#TNmx3Jo=UcpuDRS0hV)uWm0<}mI2XLo6aneC$SOY(C zXz?Jcr*V#sd2Or0H`&DljcW{4`w}Bao;Z-KMB>SgEUiiTcuf&%BW-Qz`=Aa@kF*7S zraCvl$dZ7--oHD@@=9RTSWZjS2H&x^A0Ed$Oa6LaHOgBJZw5GT$cZ^P!Fgr7^e& z<~G#>zO2xE#dxm;mOR4zJ31biKh6>>`)S68i1QVX6(2zI+17d}J_*vg4`{ZX(uVlc z8ueBb?-Tnw$0+|vMG#LN+{0#eNr+1H?R?wem|9(3yx?==lGx*_y^$KHT;e>vL*_}r zfOSd%ptruzm@R2q77gOHkEEUdY>Z%+BK{e};M~tjq%@`>HB$7UMw4N;a1OJyI<*cW-RcmvQ`V&>w(>hn z7npw$BCI4Am;2pBsg?O75L)K{AdgB_XaDl6DEVkP!cq5o2O$&a<5h4mA@CLj@DezO zP*U(X#wUehLeR3mGIl5lBola(!Tx17nzepE_ug*fP0vxr)?TN{J(BS^P}FNwQ@3d8 z_`?UJ7SQk{w!@WmY~RnrHEyV{&!qr80@ly1JZb>wu}Y8M)L#J&74H}mcVqofD1p5L~o6?&C<9$>lTaF`#cNg7-6=qi=C`*(!TEGVvK-JBnvO9Ax12G$fOR^ zEg9tIS8>Oy2z!T}#b@L3Br?uA)B7a3*nVdvBq%lF<^+$#QEJB0Wf$nEYFrc*^~NpD zp~i2p!zu*Hral00qO~0Jy^}R2cZPw{qlerU{j5X^RL(gG=Rcp(YhIs$EO{xLj1O6@ zlszm)4j$L}F=nCTEOCpOk?hm{twgoTughBZR$#Qt(>dy(z>m1oXaTNnU8?unPI+2g zrA!IArA@MJ9&47)y0W9M`RPU~n|Ib3>q6o#doLeyk)dQTpm#QQTv77Dj{1pgg_=t1 zf!`rjmDJTl;%rZ5M|_95->royDhSxX zN@;V`bp?9-T+j4qs6FRtS5eq^WGfVa+~FO5a-!GeHgcuEul-A}0hFJ|1byU3t`611 zsU|YZd<*74lE~ANU-`9|-=pOUpj%<-wh`$@nTO@NSXj+!tqK?>!x^tTAfXv6x25t( z!abVHWeKvMq8! zMJ?nbf5jC?J!iA6DM#rwb($TvSJ;zVTP!SnX8~@8g<>>6&i1;F$7^S5Vo+GU6O(I? zw>-~h-4eb-5iPnVW&34{2H*h4f=U*J-RfFRKYy?T6_x{x(o$`!LiZOYpDl-On3PU7 zyMk`Qsf|FNW!bntFc>{8C(j5*NtdUEqRV`Li1D}9e7r!)%p(&wW;1fAbXPwrqd5=H zJ^r)Kt}}U5syN11d5R~gNXC>N_}rDiK!3jKx)@~0HNP6tWNy2R5lv}{P5E0q%k~LT zw*>cF)XXOU(W?x`n%lCy2kdQjIo^kI3XUcqO?FIXm0-gBY8VgQjseSn!TUO%VuQ6i zOtOWnsV=Kj3kGLYHl} zA8YOhGJ)hb0+o-0(TS-V1Yj0fnvPALAQXVzJFf9g<~@!&iu$@qrLjt_G<)mbXnu{mCc7oRtZ7aH5?nLqngeFSv=ym&l4DOpT3^D#+gy<{lK z6-utC_R+pI_VMb#?f|xGRFAkhl=VdA<6{k8B~>SK-F@CCfdk1#-1O0-b*erQ+Qc(&dJWLb0Mn~v~01G@|SO{xSh5?u_N#rR;C(NQfd`l zom$V>#cf2*yvCTvqCSMksD6KM;I3X5x!4fqa+J7qavu8p6y-VaA$X0|Rqbfmt}dnB zqO(f7GL_vVgT2$p1d8jpO$NWt$+cGCJ4z$9yfK+xZV;)DP_}Smr`B2e1NX;{!rEfJ zS2amm+>`;NNT@00R?q6nOiDD~ZP2z&tp86*K!|{HQdFuIri5|%>I8p<6jE^DS~J5H zSRQ(`sKLHFD;wLmPfX(bXvfTs;(}|9V#U(O=zt|n;{rm3y<)^87 z^QpgnojV%CwSz2r!#pwz9_W-dx;ysz@Q9!XRma%S4EeXMsm6y+4prG)tYV*I|7d9; zXfYa#At3sB4aK2S$fcX>HrL6ejs(J`TH`r=@r=-UauB>grApt3Q8@22L*gNxPEZD{ zz&ZXTr|F}%k$~K7^wo$9E?=t~(?@F#dxYoKrhClvIR)kIk~-{e2IE$fB6KI|yK50( z36J$WcFz*bARP=VX4s2f=ITL2Uagjnb^JXPpu+W>V7aqed?yfe z&Y3SBD7%&QIgY;Z(c`OA^9#`fEX!hsaLB5vr~#^VWm1alEN0*a@?kYj4~Jl~-ItCQ zS0@`0j%a|_#r;7*c0_;wkIxP$i&r0+@;N#@tbf7_c_?ps8oFYOpjmaJ>b}AgQ%$X% zd9h+9hLrg1>wmw(+ArIlPNpVTaQ!r1#uRX+LQYyM=0PdbaC2?_G^AqA$&Ca-?0jf% z(ss}F;Y%42Hy}I+IDl`I6*$j5dTX@(*wiv_6}=CHb0BcnA9{9aG=Dg_ zdH1|V9ICUK=!31aopm*n-C1)8sRiq^Z5wFepd z-1nE;nBXSudu9p_j<$NYuhTH1{25!AsV1b}UtxBQl{v@4Y?4>7+1*#%b z2x%Cu)+tHHHF7#E)~uG}wt_?wbNf;ASn3Y#EYRRUwfIUx)|%AAc6S`*`2_9*;0a4) zPC_3ewZM7xl7s{tT;!`P-067V(HsMGRB1lT!P!hIYo}`-&CAraa(fc-v6E&lrBo(2 z*SV}=#qFISLweEhHlE%1_~eE$RzVug2LgQ<6KmAm4r9NhY!Xxf2SA^fhKR#n;s#rE zkBg#Bm*3{O9wDChyc`PHPh|`x$o)84iBLEa46Q?>SbmGKz?sd~>Vm-JX=p(bUVo4x zo0tjs_cGV@?as)0(x4w!|A)69`f~N^=7V@J!+~=CRT3n6q%BEEkYT> z{~+)kB`O;fDvirX{J)tg?@RH|;1&04FT=*t|8ZvdJb`7}zyYoOm6F1(G)wuM%J}*O z7{>-N27fCDpqTb{{G$t?j4--DQk@@F?jL-O3_Cz35TX4?%oQRj1Bui(SXuv#^aghD zM(aHKACw*qBk7Djxi-}O8zr6!0v~VG%kvK*=Zu6=94ZSFeTn~u2?F3lg5anAXORDI z#f2Zk%m&jt5UWh<9m!(SgKLouez~d)v*yc=gL%2Kfnr|5oF$CG8X*?+lf5}k!z~5H zM`_1Hgn-NeE;LW_pnKdhZGE986{#`$*|P4p6{RnWm2A7CyLq9Jo>#5Mn;acC<))7m z+FdGqc4?@D*>ru&Z?=zKsH)=n|OrDM~(217bH=6~c2Qw3(lW|!x zIhid;`u4=Pcz>%f$)sn zfukuqbDAUid5P^!k*pC}$B4H$WS`*diAX#+@B;!B7OzELr43=*#H9@^!^#JR%PQ295relG_9GAlPBMB!2&K1iVGqoU-+mp&h8np)rY5l9 zqkaHwV&{X-W9igpBcL&+=Ifj};BTyN@+o2T=kuShIBoO*!~3n)F;`~!0Pr_Om~j5^ z+8W$fXr@s5=+_;j1%joigkcIl_PMjWLt6JuY7DPQYdK#)q+3jf`Pg8J#7s6WG;&Lq zUZ5w&Jw6}-rmg6zn*)M}qa?6y`wVf9xI}@GfuPldBl%lc zu#{Q9#!9RDsN3*&T&G{jHWv$9YJbi$8q(muY9buJGc3%!991r?n6G6a*J0{Vf3o}3 za}bgbkc0_<^IN6@;~O7x|C5FRri1c1Zuhn-HnkYBOh3i|pT0w$Ak$assMh85ZeNze zd7aRkgqID$0=vNQG!beT^^GhUhpXK#i9vqNsvz(_fK)oKuRFNjDLBpAkkQ4~>?%M1 z)}z;GGAM=HGj?3>O{utN?d@0i2lTO}ir*=ip9q0AfE?1N0YNxq59t6Ds6=`$-Sv89 zE?vl1dbG5#?qB9XBi04iubXNkgpqE3kG#F+T{ZHXIn-+VV?Ry1EhAM5nf}fL`xgU6 z=kZ!F`t`aAvxvd(VdBRcAOB$q5*0?i=|Z70^4M?jPxGHljf2}Vzg_p_o&E|pwl3!0 z6-~^#Yu%3xNs$slWe$+mtmO*nF#UG+F=S&>oPLbbFa?*vcZ$Uu;izS}uqSn^ht=JH zWyydkg~dE>(m@8A3R4{$i61rrNP(n`+Q|@3vK`htV7t2anSK&yt4-7I#qxfw!)DDL z4V^0<0t7FIu>wdOW}={0d597g94WQ0%C(E)20&%Ft*3~mgIlL7kN$flv9ww_0-IG(}5MJ2{p}-h;vmvt(t> zyu&_IyH9!S-H^M5s8I(cX}Hi}&d<-i+3}G|--Br(@K|J@_jUwnkeNw(Z|TnE59;1$j@h3 zbI~@3VaX{AP#h2H-C(vPW>}2z_M-HanG?sH3MdC#U8k&vYcCLei;zsTq=2nZ01Uv1!b6 zx8IpNSDqA-uwjg=ct@*{JZb=(dfjzzMs4}elq=U@8u%9wVuKi{X{Uc2Q9x&KXZ+s{ zN?K5kV`zU=(|d)*zq_GSrboGaYq+?%DQ6z{IA?T`w%6wd+ck2JnsMcSOVrUo4H*p% z*q4AHV(uq=zAOAe5BJvHk=$?mCnFFaBJd|d)dHtXQ}}OYB@1F~YrE(Nep9s(bX}1o z{=1U|QQVEYudtBf4}OoDFN+`dk-rFWn~Rs8(Bj{$YeXB&Ykyr^91KNut#zzikIWJV z!YV@Sd>*-5Ftg^RA7%O~@5a~wo-~y_%uM<|=_d0k=2tBJ7ME`G%kj7rp$5|at3XvI zW?0NpMmN(UP@vu=@+uCnhkGqy7B|2`g%Mn6nhX>Oi2RuID{hVW*>+;wJw z@=qV7=xNto3iIf+*e1gmo($xlgLo~X7LO_z-M*}UK?(oTe*m)o#r6hE7KAUs#2Z2n z#AXbjAn!s9RLQRl9ZmM!EUi+H6!+7p(72ZTmgC(e6IKpZf+^W!Z+wOnE7%rhUCZBo5@zBq zH;+jH9Xe$nT&}r%=@mdiFw2}SAYhcB1}~;Y_oh22F zRwTgVtzSobdkYn#uP>!&rzxpy;)xI!*yRtU?C7i`e_~z;NW`T4FWHC%p<8J~J1H+p z%W0ZmDYGk&RPrv5n1SOZ&c};Y>Z{YN$yY4c`jFnysr+CC2Ymu?agi*fIc%|Uh*P`k zvDD$gy!RXjc7wx)iql7<3HlZHIwVGt`IN`AWX)XVzx~Uy(ShJTSmvOLZj#Kv1=kTA zPgqC90rM7W%J;%vFN#FY>6&cNydz=ZH~gQd%IX;_cmw%M9_j_7T`e>;xv*R|7(M@V zT+VXr$hAmUmS`k+#DK40!7JY|N0}xJj6uFI;O#sYdKp5xTPvQlB}$XmEi0H}N(Ib8 zcKi}G*(9-YNq0Vq=rj@TLknvpBE{dnTO=%UX}Dw+b;vN9;cotJMg^>fjcuh)j#mN! z9gUiuauYAMK-YZR(bYiutL1PTL9|2W#u4NC?5G;UKTXBVhs|W5#4t~>>?G3F1@*jS zIjx7PcX)*g@xlrZ*L+HVYm-$9s}2*((%6c#*Qi{1H0;gJ=mT$-vUC-SpJ}E}S+OV7 zrr!Q!;mZ=b(_U2-qk1Ob!Kj}g7Temu6&o)Og(@h;#x^0>Tb*7H<{e=OfX*0g3*E>h-}L$Dt({{cMc*kk+HPSq5AIC;8l$ET4VDq}q@@GSd&H2$gWgOJcdp$sr}iv^n34^W@qxDYQ&)sSgruXl|$Y16j(H44>@+x0Jw;UcgsjvO`^ z>_T0nA+VBa+Zl@&B>r6Jaz=%I^szv%j`q*IB)PjmB|(SrtN@>P^a&@2LG*i|cIYpd zAuzK0@12SQ(Mn#=iSO^-!E@CrD9Z^YhWxHR_XNFe>2gcMK{y#*jRH0C-@uDI^`ERZ z9#xXY9Nw=8H{X1bHv5Z_(F_re6uuo9QR6OZaSQUKQ{I)GEosx6(X`KFqppY{R2Kcc;fPl9=p z;)iG~4UiVeVr#E?M`m4WZ^SwyYwEjg0Z*O1+IVd_vq@E6tsfAO8!Uhx51)G-AVa_I zA@-z@EX<=A7lQbzqqUPwGA`!tNA=xg%2fbb%Rb1{q*mQUL>$pzPMk|9hf8)b5(0e* z$~Ns8Kjs*!c!F-t-XL$UGNu|kEQVLGjp_h^2LV!fsV$K$*787ZZ$G&Xg3FkWohHK( z_p_AT91*2lQyP8RkDo%h_#?I+iU$nfv@tAS1X{(^iLYk=` z>r%<_BSZmGtwe%9z`33>6wgiBVz|F(Jm`dkz^{I3PtW^Ka{}dMm9L*_QN~>AVXiz3 z3N!o|15NgXRSWfY?(?JSTAp=Y0Nur>-BPFP^D?$f7PRm{cNHL!)}bUJaUrGQORi7j zuocosh{L89#Y^PVp_I)#;$Ul-l;kVFq-wHd!fKz(yR)5TWV-D3QT#P zBYPh6uNUzbzaKKBo_dw`%rOlYfrYwZO)k{*U}%{0Zmh$Y;a0(GHn@x)eP;x5x6&O+ zFP{4YtV)Mar$prpW$~umoD@6lzPH~OZO4XIK^>7uDiXb0%hW)#m^M(PBkAL8niOIqWqq zKgXVvQdxZx5gEQzrq0&3G}av=EtQpD^|m?pj`U}PsOo&GeLh#O>RkTiA3gU2nw5DI z}`*&N>g7Oj%AJY1J)wofx3GvBYdLVB{53J?VdbK7`)SCeY9 zX}mgNYx=w-sVY*m66HXq+xJ4T7e;qd{d3XiF$z~|Ze;!hoK zku9~cd2OV_Zf47qe0)?eC=#Ox*-S6K!AkM?OR`V3^v{nYtz5G;b{MFXZy%!4MjMHp zR3BFum;;i9*stK$WouW8=AoCaAo0g^3eLG0oo69#ulU(;si?--hjDFfUFN$e>o!)6 z3iZme8c3YI%~t}OZIRpIMz2djM8^!-jrQ4=G?!DKm3C<4!tUpx*s(|)b8qOESJq^j zr-j6YAh-_u7?L+yJiPf~UvlTC(ffjadQ+spg+-}NSxuzX#;aGRh#KT=+8`{mLv&HeM;HUz8-M6yJ zG4AHc_~i#Nlh{u{!y0Lv7igJofWEAECjl@8@=%vv7UepQT56UD)iM)PEg&vH;{MC?10sw?V+g z2c*Uum6a-SnD^z0LU#ZJVpb1ap~Dc+3i7dVnFW%g5vkXBa$g7c%i_4rhj`I<&pln= z@_c*~Mec(L5>HoYJH(X5ZJrt%;&%BQ=mpLTLnjU%Vm@jZ4VYV|f&#F)yn?j&f<`uv ze;#WuH0ga;Rm8I{Vd?OA(y#lNHQ&cCx$1aU%Gnbe0U4O9jTgE_2&db_?^NPE3nnm-e0S0qU!CzYDL zyw|RmZ+A`D>?+bwSZfcOIH;rM&d)30@R`vBp#P~%c!&1%)0NeG*&mWYV7qMQlEx`a zgrGNsr7HZT4*v|X#oe6bV$MdEW;;#4W!^xw;+u_!FnSZ5r2**DS$uz%8#J#GM){;x zjyu-FWd?4}_BZ~5J{zLl_aXokvlUo7Uk+85h~UyBp$pM$z#y;(OMn8xPNYTWrmq-VIQ z$G!2ik8&x-NaGUun8%=0Vnf0A2sf}(^B=yXbU|;BNAlYuv3Dgmzc4GGWAWbsVbwc)=;Pbi^4RXjbCwRGV0{9BdQe2Mn=>yqv zq6aCE1wy`(SS=~SC_~k=SQTYJq12w$GuL^TO=ztn0uB-r(Bo&ED{9?ftH1khtlbWT zd_v|Yv;8=h`7z$Nfa}~N*4IXK|LzIL}wNf{>CNBxN)Y`jd)mJ+3F0s_LO4d6riTW!TvbRe>B$oyQ`rsD!drpd%Aqi>~_;f4dY{H_%RX!qS!f_ z-=E~np`i-<4uC}aVs(*}JFkV!B>lT}?D132@SSUN@0|&2knXHO&b)=zM`VwJ!N|J$ zlaC`JTk^)D;V~wIhIB-WQ}!lNCH}qdGsGlfL*5nd>b}TbL|z35By#l(r;mmS63#;y zv|O%7EM`Kwei<#GR&vUxuk!WWp;@2PJt&L zl8j{JA0(BV+EOyoe~Vnj1Bap2ly3}G=FEggyEQ$ux&f?xdHcNPZV`w7;80isFu@18 zc6n9`A=jwbhpQ?E%%ssVpc#&2}&c5T=QAO*iCBI%nh(hn$w zkZ}_9C2|p=ejJ${s~PUJM*_OQcR%>vpLTJ3Ip)(1GAhsD12)f1_C(Q1_ZS~TqEvM% zHbHS#rpj3oCLGdlJnAe zEbBi+Z);+o0pBbUv4&Vor3}b%oS>{o7{M74*7;9|vzToIVD%ySG$k4dPJr51R?-(i ze4-wow_4a39;NrcE1iBduKQa;ioZIvegkWHUL6;>xsP0u#vzBs^vklJ5W$ffS#U}N ze=y%&S??}j{uUYi;-c|;%gnR@|A2^s=P&Y1%RDXO@a^ja&&5A#hUXK7Eegy1)>aDN z#LmM^$i~Sr`?$z&B&P^&gN^gTK_%f*PfS+f@3bO%0OOsZ9iwbexH=y}(15KZ*K^da z|Mk(D7#y-`0k^jO_-(Te7|9bN^;1+>S8Nkdz;9b#^2AlxIlQ9p-m zFM$t<#tyyv3Br;Zw`k1hlCU;soi`vCc4I~blAsED4HIdzfQSyg4m2;v3xj;go-sH@ zFLi-N`z@mS)0H;CLROO` z(ln4F3YGF_n-WVsQMoNr&hc#!9S|n&{9AY!)<1OI`*v*d`0Z?WF-RH^m=<>{ z7VqV{ptewM%4bS_#a~NO*f>xnSfK=keH%twS0i6NAMz?-C?WhvzPz!68g+s#(Gasf zh{HbzTb34#uG0&{7@LnXd!cD+;T#`kR+o*#dX3(N=hv%rLt1SV^owD5gGB=B@z=KF z+B-4;#hh3!p$vZY?D%5pbfs^!5PU+KmS*-B->?p#(w=|$nNMSAdU4C$#PVZVx!a zJ|~4Ig_Coiiy>ipEgW3Mw(K7|Yh*ZoB6aE~Dz`aYHejE?e1X-utT0F}A~)t^Ww9tk;78a=}- zM@-45YD8yQ7yOtm#e_xs(-L5fd1TU!d;n@FP$F49&DMD&R6HmUMosyY9~QNQyE5X%Cv5EtNlz!V32P#RMOD&wYi z$ZPZb_Pk*-LKy(71(My41+`0!34>7jQ%$p1is_xGW-8nF-+;`_n-v&y0xj3bLO?$ zqKLQij(D*sRAkp5m}H>hpl+dKGfZetq;noOet>tVJZupP+tVtPyQQFW?3$yZa)2JK z8R!j`6DS?=hT|VJyy!dn32;ix4UdDw4>a@!bU%=w@VlcIm4c@8aTtRTz+Ub%kZ_ua zfC=7b)cwiFG(I&qIT)M5_HL6B9kfjM{d0#E-oO_on$FuJ(m=6dxf}#nz&1SJ@8~i~OhYAkf<(NyslY z>_BFDiKYQD-?Dh9=o@Id&5coa8q7)ZlCl;&*?4e&zX~VNPXU=>SvG)u`s~g3G$;*P zib*^rA7^f>bp{NHZeWa8MPBqYegeGkSYQ;;0EULQ9)h$RdeQ$pXi0cu+@%X7xyiuR zLkHQUcn3qwM)vK)joOYQ=SwR$_$l;;Ci~G=Vc^hovkjvb7qZWx#o8^!q8n+Lrw7Tr$4J%>E5X)qK-543YK!!TVG_;i=0+T=7Z zi&E`2w(vq=v*6`FXZeR6h8(wohu31L07=u7FC8Cj9dP9x=F9d>ukF^@q+%b_#gg1$ z$TU<`qQnRs*xR*}@Cd(GFoQ(&&|}`&^HFNGyCH2?uIP-TAJ=&bE zx3C$n^O&JnV7K1ewCyiq5fV4QzJ6)>bm6J!Jwac9i}aj_1EWlj!f|Y*wriBiKlV}Q z;C7$6!BA=UqB(-QTzDSG|4f%A@U!Ib9A-pqZ1OYI>zT3buaG#7q73eD@wvTHy`PAp zu(cm(b0jl^!F3Mfl-(Q~eGT67ucwzM9l?O83rc%9EU?v*Crm(+!(cS}>AGBzXZ;LL z5ipVtf6`D7J3b4T`cJawyPZCfbr=QVI2F%Cq>%4K=Xt<#c`c*Efq%ND4#SdQ1pbGA zUvi#JBGJ(9{mg}-PXFb$JB!Gdzm(un;ayO7$3_SpRI9~>SbD#)* zIw!h#irdXyixj7MTUPpXFBRDQvdw8OR_dQbiMTPf0yo_i%4m3iWaJCgKj4i?0st`e z|NSoj{$bw!-CfL`E@G!Ut!X+a1&6zQGIdwfcGEA1GqAqa-hL=-?xbFwX)waUNNS{Z zliINRqnHk3ty0SFXFF4`Yj{?lLG+|G2HBxS1G+<2a@LpCx`h?CXnj2xv^%gnwN9%D z=mNeS6=*(A<}VpVZ1BB^UvCYRZ+$PuBi5R+Ic_8DE1CNsw`XoJ^N(#=T#)!lBayG* zY|i}9G&QnEuBz&FsKp_COQ0pTeAD=usjEY}R`CzVUS1T%%T?yFu$BuGV*n3qut^Ut zKIB&FfY1(KIoEXo4LaxTx>+z0pP-ZcHJT%taKQ_OD1GS^v%g*4dab_1a}4=%f2E?r z;kt&MnqFZ$={u2b!e>&FSC8?x@jGPzQ17_BG&B;Rhit5AFc#y|_pq*86lhC3vj8)xzU9$|4}ghu3~fv!(7|GSF=Of3_79kNhDB zkjaA}1vc=}wcv1dL4hoikdOtZ8Ck*qFGoLq8-DI*OOfK9oVA704 zgg*_s33s`0hU#8Fv5$P`So3rh*C(bXR`oVc0zTgpUZryz$>?N(R%y(+w%&Sd&}YxY z^NF}^7`wqX{{3Hae27&=WDo)b;Lzk~4HzR}gbS4iEuR2{a1>vOzx~TtB-g{L9x{Lz zVJ@;p@18VkNvi4*=bb>q=>r}RZw4dizk9=|6alz>hEEQj{u)m~GYkhr&ll?VFAggY zQYT!nJ_?;AyI(P z;O_JMaYJnOa?zxlZS4D1O!HBZDIBx+IxtRPxd;P>)Q zyFq10wm?1?D__`3iIY3w0N3M00@mAe+Mz#ai2dAWq7=lCyC3C$#gZu+aInNBcYqH( z_6UiXexyj^&FYj@9dgOv7kdTh`jb}1s=?_ zdWzCJ?p1Y)eca4u*2GAhGGN&d^2qM?A2I$;`X*0AQ!(d;1Gl6KMz{m2E5rIiLIBx? z3WoWyn>o9g*xWYp^EKt=$J1JMM?;d`jc4d-rMF82u#Dh^=n?g5`~#$2SPvxJnO z7dvPk&Z#p6rz$*;-tJgy_h>KvWK3!@2aPEr;MBo*H6y9erN1+{YdcZEGI>b zCsDPb)M|4)fkM$PgVbO8ijHl@Yyl>343r!0HSfc-Nnh1=?dFqT_H40?B;*+=R1XV= zHQ90IBJP_*KWMYxW>@{xsuxoE@JX#}RkbVgQzgwprR)N;%_U%8op~g~+2#r%spUId z7m8N?srVa@6-z20|GzvnjXKnY&vM7O@5u~^J23g8EzjbSOp!z#xDGx*W#lic8#-49 z!n)0FhJr7%U$fdl^(T8NVoiz!+)WC~Z5aA@aLu8Urj_hQUz z$h&z-2vwIsD(mgo{Pm!`B)nw^bB1W`g+g`!N{?;}>N0k>9!+|&0B8I+m4c5A4lyg4$lw+xt` zJ`iHMCI*eZ49A-(NeS={lZf39V}=|%%pc!}m07lDp(jgX9#R|)zE8o9z;b%5D%88P>r-1w9O>az3+d zKEw7psVL50P2(%s#p9RmEH*Gst1Mw!>KXMX(D7iwRFdJfD_ZC{eXO52j`V%FjMCY* zpq%~F z%knJ>jZq?G?VR>>ymu3k;Qzf8awkVVa`_!_c?DjFgyAlKm#m0*P&rYQO(}#%62_1- zt*!1=%OXgcPYLE&VVKxI+Ng~H_? z^IE1`LTlh|prJ78+|gYS&t-%&GQ7<-ldq$a*jrNALn%Iw^$hfg`+0rL^bl&^Ma2FV zx%fmk_HO8qBvgBE1vnL=xHaS8b#qyW(g1F5wek3+`f*P$wR&0h zy1v{l!+^!mrNsIxHsx8SWFY9`;8sA?bu1r?${x6G0X5{;L9Y_}&TCj~R4dW6%_$;{ znns2!6gl~IgqPF?jJp6fWB^53+f(RHBFz){uD6TxT@!Ov({F2jzVhTPwf>gM?w?%U zm*9wYSuCKRxdNae$2MpWIqvDxVyEu%Yma>Adu>V#t)Ld;Oq4PdJJ`7Ut| z1cZ2dW`7+P3ptS9Z?xb6$jcJ>?(e&EI(JA2`I}UV#26B(#n4 zV56hFBT;S$_rwwJ;YHiI1#lr0G8`WMU$< za>9UqZ3i5a@$!rL(TrezD`}l?n0A>;4TABG$Pd8}0~hM0W1oXF_X5$nY6x7P8KC@o zpT2s*;TUU;r2Wotv`k>MT)2h&>2hG<8QQyNSijJLe&Hdc zh*LC31?q=|9@;Tx%*E(Oh6L#LLX{)*jb?WT^VN%8Ohub~@eSU?n1=2^f(*ymrr=$! z0^1%BTm)RY835$!%j+Xyy!m3TENz4qvjbW*A>CXenks4@&b390FP3B$Z?iUr?kJE3 zQZ38xu?6tLMzrX#7wvTr0K->3?b5<;cbaKxeJ9R%H~BHQ#@D_$6AoB5$gjnQ@Ax!i zuBo8E47Dmza&t%5ff|;aUXEZJGjUOz8l-|Gev2xyCoerQb(0MB@{aNz z2b#5N3+5brji$}P53Q=~bygY8NnJi?Z-@0)7s)>uFLk4HHe*T+~2Xp&IY9nT9kEoxt ze?1OShM@wm+I$UvkG4`m-@SfzKvYJ)61MRlhIW^{t$*AXeb)&S03o#{dcciPb^Qh**^lY>_8P?ngAHG5}fV-A}R* zF*v5cpBlu}8iJ;YcR*8>v@$&M{Q@fx#N^jB>AMk46G2ne9~%Ow19R$!hyEv!lPOTf WkDOj;(({*;;OFY(PHWo5NctNIVQYf` diff --git a/assets/logo.svg b/assets/logo.svg index 4c162864..18054a89 100644 --- a/assets/logo.svg +++ b/assets/logo.svg @@ -1,21 +1 @@ - - - logo@2x - - \ No newline at end of file + \ No newline at end of file diff --git a/doxygen/logo.png b/doxygen/logo.png index bfe3b9d9ebc0578baa72a2493026a97c9be1500d..2fb5219b67ca04427a34a7b627f78723f1fee1b1 100644 GIT binary patch literal 2382 zcmbtWc~ld39*>Z<3Z>oGVmLG~g{=WXZU|(W1SupO78L?6P%MUI2=mO<%!C9A$l)Sv zsX*5Q1i|BpSZFC#v7!`Mq1Z<7e8?Kk_6enxbBQP{b|-;F?QY-e>;5tGoA2-U`F?)i z`%U4FZ6S6x&Net4&Mqu8I0{?+%+I>D*t^zvTZk>|)uC|+4);oj`B`&_{K`fg4v)am zv1n|>JD^0Rpo*ocB#5e4s4+AS#|_Y{#gaV`3M4@?Sji(zU2Y`-u#`vovu^}FLLCI9 zz@h0HNR+-UT9Up;!jX~!_%>WUh!H3tR1D}9awP)lc_a%jh<%&4X(SA!ktTyt!NL^? zCh55jf}?Na5ywNlg4CHFa!ljQ=(!$MTxj$3^ss;BN##?8d#0O zDkWg%6ep>)D33(40amC3QB(sbt+Fc-s@SrlHLFlDr)gp-LSsM} zI5OYyOhKSW!=!wcgq7^i;z%eEQ_7Uvu z9A3~|fsa}&E>wUQPJH3i{?OIU`U%IY678sAa~qB~<_Vm3USnAkqw*WaIU<;mo0%>e~D$Bq#zcAf$! zs%7Vge*E#13H9RQVnK0nS6dq{eCyWIl9KF_l0WLx)01F$y+|aQo}JCDt0Uhx8Y5$4 z3pzT24<0#ks*>jFZ4E%1<=lnL zpZu+cMhuhdq?@not8UFA=8yYLM~eKdYooo`B99C4-ISQzbxjd3*$66?@|2V<;o&w% z+J}dM^YN4@k;v(%=YiH_ureDtaut)IOCtgG91p!v%VM^8ToOH zj=Jek>4zWMf*@FO@L-1%Fph!;*oSiAZwU7G)8MzlgoI7Skxg(B@JU@=TK&nBxhxj~ z;cEqgum(N%+D_8+-`^Qk*AI5L$4rgQq`iyp&ANWoVb?7Jv~Yc;ph(D~7PVrN&^gD*2kwtKzbdnTEMJGaX%A zM!iz@>Xw+q$?Z_F($ER<)~Karbw zA>)KZ`;#?->Md|p(Lz!}Kk2j1vhfS!j*#i;QsT66mb>%ie?ERX`D$5p_0^W@IeGdL zcXV{LZ!Vqp^4dJX=bz@p{pIz{vns!L7n_QBXWwa;=Px!$pT;HoRFypzUP#766V|)J mZ}cQqor(Ch_Fidylf&i*56h-@4(QB(JYj-u!JoaoJNMrc>co}+ literal 2952 zcmZ`*c{J4h9{yQkl4We!_pxOgnk-`rV;lPzUS%I8?A=broC^WJ;z`JU(dJm>Q~&-wiKJ>OJ&TXPOJVKx8&I4ms?C^~EX z0*H}*%eR?w(@E0D0%ZdL(Q*I~e-i)>>7)2n0JsJPfORhbfENRRKycYJ2R*vMg0V73 z04Kjr<@4G+`h+#y(#Di^l@ZLPtopU;>?Q!5F0e!xp|8wsk^M8=oW#0r&}OI|ei7}{ zvH!rXeK(pX8MLT?TrMl36Vn)xFz|l$TQx{Of+LmrF3*L2@P)K1ZxxzIf=doLkxbua z-=L;Y3M#W(F}m%#k00xvr-fume4hLqp}RGb?*}@uiyZk$E1N&KbFwkx?{+}wllOQ@ z<=7GWQ@-d8^lI@0wEz91xE^5zeJ&^W8cWMIYj8%@GV42Aq5+aJQcR%;QO9Je>TE>< zmh2QQ<;d_Pbf`;I{ug#8%0Nvj!u~2Tw?wf3(;u!{f|!QrWn)s8anhWqDn1HNXZFUz zkzjJ%j^1^Nu9jlm(o?&N?I6;Mlx#9-W4$~^oGEdrwD+d7o1IerY#8dYA6JqHApk;# zke3D=*c1EGVWMg1G^=~OnYq@DalDhtTX|&NQc15P&gSQ$hTSa_WF00Zz3j=y12~>4m1X_>l&g4#vdPhNf87>noA!}E4iY}G6k8fO9rYBYQ|w&w~-6lW!l~K zLJ&uyc#~il?s1gTK^$)QBB)Rm_X)?@LG93CHYl`#v9a}b(a10onr+^1(3fxMMLsGu zv$XC(?=`aa?eBl+H5ERC z8_q>Kc-q}Cly6^K^EqipNaqhOWbH+New})Yc@5ScF+OfJ;mw|S$lfGqCE()Hb5%cRm$sjHv+TTVmb@mELBcWJ1rD4!XxK}+AhXe2k>b3ioc%-+7s*N~3Z)E`@6x~vkIv}SIJ$M_ zKm9&7pS`j%j!v8Nuq|6kc0x#Z!~mld9|i*9Wwl#-f{p9yCT7f7&K3fKGPl!$_X=Pz zuS@~^9)~Y&e!_3g8muxgi>CC!vGl0u@74Pb*J!#XFLio+1+N`fa z0rU^6(^YLusnGC1USq?Iq4I`wsYaEDLpcdxxDZ1j#r(QNU8Ax+h?GwhZ+Ym~aE`aU zVg$Irw_nws0r5eIJF`*8xZ)K@QXDCbgdgA$uS+I_Cc0eXM{P(4?4W(j+ZQ*Tmo`(` z#YAP^)j&Y@Y$jf0L9hk8$@XzT$!-xceI4?xHuu43>{2Tl5m3!t)5Av;XELqkeq$Ms z-fYz%VJKN32@2L{XQDPdjI2vTfmqV&T?PdnVJcI=H?0(MauFEZ-S)|qvI3Qx7;>5BJqd7#LL1RQ!0zKy zLr8(3*(iT-z-6kB>rgo-n0di?XqwiUiPUQmsfII_1Txg0eH6PFyEsA{sDn+AG;)vICGJb z>?lk4^4gc9pIu=hf}W2|9_}j8epWnZ-T!0#s#r)qdisGVPLttO$*hkmIeD%*qdb9d?aee+%tzFnziu#;kCb9}{~dK2b()2x z$-11Q#`s({_p>a=P@UWF2p9J%-&O1%Yz43#vaY>yywlG&6DvZ~yV$}-m0MhWR*g9}Yezmf^I}p@*q^Vk(6k)=J@5(JrmYU|u1BCkj^oSQi#3xdV!koj#1sC@nU~+-T@)ne1?) zmH5~Tvt;WV9r+fz_jO4IeU>Wf3Yj3%NCmY=qDM)(bOIWkYSmEHt@k9W_C0r| z7nx{4(J;=**g#*-Lz@b9o>M<1Xki&^mc4SuZ-(W(WzV#~ATJqGsT)O=TL+k%TiOv% z@{!yjJJ(s#TMew1L)K(1Qo-S3<02p|x-09rj<5S@KUbTDqPVKmxPG-W?EH~#lghGt z0(OBF^r6LkrGv}0znMZpAp(Rq@bweUw|QPI_1SbZWg|Lp@<(6=p{-5tzL*Go+DX*@ z?kLq-k%>p$W6C5734VLAYSsgeO;qBFy`Bs$54o4SPidWU1-KA~7T z0UA&Zm Date: Wed, 21 Feb 2024 09:59:03 -0400 Subject: [PATCH 02/19] Remove `sourcemeta_` prefix from CMake targets (#32) I'll remove it from other places in future PRs, but doing this first, as its a bit messy and requires changes on Noa too. Signed-off-by: Juan Cruz Viotti --- .github/workflows/ci.yml | 4 +- CMakeLists.txt | 2 +- DEPENDENCIES | 2 +- Makefile | 4 +- config.cmake.in | 2 +- src/engine/CMakeLists.txt | 10 +- src/engine/common/engine.cc | 2 +- src/engine/common/engine_context.cc | 2 +- src/engine/common/engine_error.cc | 2 +- .../{sourcemeta => }/includejs/engine.h | 10 +- .../includejs/engine_context.h | 6 +- .../{sourcemeta => }/includejs/engine_error.h | 4 +- .../includejs/engine_function.h | 4 +- .../includejs/engine_promise.h | 4 +- .../{sourcemeta => }/includejs/engine_value.h | 2 +- src/engine/javascript_core/engine.cc | 2 +- src/engine/javascript_core/engine_context.cc | 2 +- src/engine/javascript_core/engine_promise.cc | 2 +- src/engine/javascript_core/engine_value.cc | 2 +- test/engine/CMakeLists.txt | 14 +-- test/engine/engine_binding_test.cc | 2 +- test/engine/engine_evaluate_test.cc | 2 +- test/engine/engine_stacktraces_test.cc | 2 +- test/engine/engine_value_object_test.cc | 2 +- test/packaging/find_package/CMakeLists.txt | 2 +- test/packaging/find_package/hello.cc | 2 +- vendor/noa/cmake/noa/library.cmake | 94 +++++++++++-------- 27 files changed, 102 insertions(+), 86 deletions(-) rename src/engine/include/{sourcemeta => }/includejs/engine.h (87%) rename src/engine/include/{sourcemeta => }/includejs/engine_context.h (87%) rename src/engine/include/{sourcemeta => }/includejs/engine_error.h (89%) rename src/engine/include/{sourcemeta => }/includejs/engine_function.h (96%) rename src/engine/include/{sourcemeta => }/includejs/engine_promise.h (86%) rename src/engine/include/{sourcemeta => }/includejs/engine_value.h (96%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d95ba89..7d5c5f2f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,10 +99,10 @@ jobs: - run: cmake --build ./build --config Release --parallel 4 - run: > cmake --install ./build --prefix ./build/dist --config Release --verbose - --component sourcemeta_includejs + --component includejs - run: > cmake --install ./build --prefix ./build/dist --config Release --verbose - --component sourcemeta_includejs_dev + --component includejs_dev # Not every CTest version supports the --test-dir option. If such option # is not recognized, `ctest` will successfully exit finding no tests. diff --git a/CMakeLists.txt b/CMakeLists.txt index ffa8cdfa..297f612a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - COMPONENT sourcemeta_includejs_dev) + COMPONENT includejs_dev) if(INCLUDEJS_ENGINE) add_subdirectory(src/engine) diff --git a/DEPENDENCIES b/DEPENDENCIES index 59d4fdc7..b8e7575f 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,3 +1,3 @@ vendorpull https://github.com/sourcemeta/vendorpull 70342aaf458e6cb80baeb5b718901075fc42ede6 -noa https://github.com/sourcemeta/noa 653bda26413812241e503fd0b550a66f2df4700f +noa https://github.com/sourcemeta/noa 9da0f1877859f60e439e31856cd4ef5fd4ca6063 googletest https://github.com/google/googletest 987e225614755fec7253aa95bf959c09e0d380d7 diff --git a/Makefile b/Makefile index 5854a76e..fe18c99d 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,9 @@ compile: .always $(CMAKE) --build ./build --config $(PRESET) --target clang_format $(CMAKE) --build ./build --config $(PRESET) --parallel 4 $(CMAKE) --install ./build --prefix ./build/dist --config $(PRESET) --verbose \ - --component sourcemeta_includejs + --component includejs $(CMAKE) --install ./build --prefix ./build/dist --config $(PRESET) --verbose \ - --component sourcemeta_includejs_dev + --component includejs_dev lint: .always $(CMAKE) --build ./build --config $(PRESET) --target clang_tidy diff --git a/config.cmake.in b/config.cmake.in index 821612ad..0aeac31e 100644 --- a/config.cmake.in +++ b/config.cmake.in @@ -11,7 +11,7 @@ foreach(component ${INCLUDEJS_COMPONENTS}) if(component STREQUAL "engine") include(CMakeFindDependencyMacro) find_dependency(@INCLUDEJS_BACKEND@) - include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_includejs_engine.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/includejs_engine.cmake") else() message(FATAL_ERROR "Unknown IncludeJS component: ${component}") endif() diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 2cbb7cc5..46788890 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -12,20 +12,20 @@ else() message(FATAL_ERROR "Unknown IncludeJS backend: ${INCLUDEJS_BACKEND}") endif() -noa_library(NAMESPACE sourcemeta PROJECT includejs NAME engine +noa_library(PROJECT includejs NAME engine FOLDER "IncludeJS/Engine" PRIVATE_HEADERS context.h function.h error.h promise.h value.h SOURCES ${INCLUDEJS_ENGINE_SOURCES}) if(INCLUDEJS_INSTALL) - noa_library_install(NAMESPACE sourcemeta PROJECT includejs NAME engine) + noa_library_install(PROJECT includejs NAME engine) endif() -sourcemeta_includejs_add_compile_options(sourcemeta_includejs_engine) +sourcemeta_includejs_add_compile_options(includejs_engine) if(INCLUDEJS_BACKEND STREQUAL "JavaScriptCore") find_package(JavaScriptCore REQUIRED) - target_link_libraries(sourcemeta_includejs_engine + target_link_libraries(includejs_engine PRIVATE JavaScriptCore::JavaScriptCore) - target_compile_definitions(sourcemeta_includejs_engine + target_compile_definitions(includejs_engine PUBLIC SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) else() message(FATAL_ERROR "Unknown IncludeJS backend: ${INCLUDEJS_BACKEND}") diff --git a/src/engine/common/engine.cc b/src/engine/common/engine.cc index 9cb91238..903fd6a4 100644 --- a/src/engine/common/engine.cc +++ b/src/engine/common/engine.cc @@ -1,4 +1,4 @@ -#include +#include #include // assert #include // std::ifstream diff --git a/src/engine/common/engine_context.cc b/src/engine/common/engine_context.cc index 5f2e84a9..6f978015 100644 --- a/src/engine/common/engine_context.cc +++ b/src/engine/common/engine_context.cc @@ -1,4 +1,4 @@ -#include +#include namespace sourcemeta { namespace includejs { diff --git a/src/engine/common/engine_error.cc b/src/engine/common/engine_error.cc index abc6f181..8e7e3688 100644 --- a/src/engine/common/engine_error.cc +++ b/src/engine/common/engine_error.cc @@ -1,4 +1,4 @@ -#include +#include #include // std::cbegin, std::cend #include // std::move diff --git a/src/engine/include/sourcemeta/includejs/engine.h b/src/engine/include/includejs/engine.h similarity index 87% rename from src/engine/include/sourcemeta/includejs/engine.h rename to src/engine/include/includejs/engine.h index 6afd911f..802f0503 100644 --- a/src/engine/include/sourcemeta/includejs/engine.h +++ b/src/engine/include/includejs/engine.h @@ -6,10 +6,10 @@ #include "engine_export.h" -#include -#include -#include -#include +#include +#include +#include +#include #include // std::filesystem::path #include // std::initializer_list @@ -24,7 +24,7 @@ namespace sourcemeta { namespace includejs { /// @ingroup engine -class SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Engine { +class INCLUDEJS_ENGINE_EXPORT Engine { public: Engine(); ~Engine(); diff --git a/src/engine/include/sourcemeta/includejs/engine_context.h b/src/engine/include/includejs/engine_context.h similarity index 87% rename from src/engine/include/sourcemeta/includejs/engine_context.h rename to src/engine/include/includejs/engine_context.h index 640950d5..f0e7cd4b 100644 --- a/src/engine/include/sourcemeta/includejs/engine_context.h +++ b/src/engine/include/includejs/engine_context.h @@ -3,8 +3,8 @@ #include "engine_export.h" -#include -#include +#include +#include #include // std::unique_ptr #include // std::string @@ -13,7 +13,7 @@ namespace sourcemeta { namespace includejs { /// @ingroup engine -class SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Context { +class INCLUDEJS_ENGINE_EXPORT Context { public: // Consumers are not meant to create this class directly #ifndef DOXYGEN diff --git a/src/engine/include/sourcemeta/includejs/engine_error.h b/src/engine/include/includejs/engine_error.h similarity index 89% rename from src/engine/include/sourcemeta/includejs/engine_error.h rename to src/engine/include/includejs/engine_error.h index f1053dfd..45ccd63e 100644 --- a/src/engine/include/sourcemeta/includejs/engine_error.h +++ b/src/engine/include/includejs/engine_error.h @@ -13,7 +13,7 @@ namespace sourcemeta { namespace includejs { /// @ingroup engine -struct SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Frame { +struct INCLUDEJS_ENGINE_EXPORT Frame { const std::optional scope; const std::optional path; const unsigned long long line; @@ -21,7 +21,7 @@ struct SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Frame { }; /// @ingroup engine -class SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Error : public std::exception { +class INCLUDEJS_ENGINE_EXPORT Error : public std::exception { private: using FrameContainer = std::vector; diff --git a/src/engine/include/sourcemeta/includejs/engine_function.h b/src/engine/include/includejs/engine_function.h similarity index 96% rename from src/engine/include/sourcemeta/includejs/engine_function.h rename to src/engine/include/includejs/engine_function.h index 6b0f51d9..8acb6843 100644 --- a/src/engine/include/sourcemeta/includejs/engine_function.h +++ b/src/engine/include/includejs/engine_function.h @@ -3,8 +3,8 @@ #include "engine_export.h" -#include -#include +#include +#include #if defined(SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) #include // std::exception diff --git a/src/engine/include/sourcemeta/includejs/engine_promise.h b/src/engine/include/includejs/engine_promise.h similarity index 86% rename from src/engine/include/sourcemeta/includejs/engine_promise.h rename to src/engine/include/includejs/engine_promise.h index 7b0d69c8..ba78ff5e 100644 --- a/src/engine/include/sourcemeta/includejs/engine_promise.h +++ b/src/engine/include/includejs/engine_promise.h @@ -3,7 +3,7 @@ #include "engine_export.h" -#include +#include #include // std::unique_ptr @@ -11,7 +11,7 @@ namespace sourcemeta { namespace includejs { /// @ingroup engine -class SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Promise { +class INCLUDEJS_ENGINE_EXPORT Promise { public: // Consumers are not meant to create this class directly #ifndef DOXYGEN diff --git a/src/engine/include/sourcemeta/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h similarity index 96% rename from src/engine/include/sourcemeta/includejs/engine_value.h rename to src/engine/include/includejs/engine_value.h index f5e08c6b..966d9f87 100644 --- a/src/engine/include/sourcemeta/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -15,7 +15,7 @@ namespace includejs { // Inspired by https://github.com/sourcemeta/jsontoolkit /// @ingroup engine -class SOURCEMETA_INCLUDEJS_ENGINE_EXPORT Value { +class INCLUDEJS_ENGINE_EXPORT Value { public: // Consumers are not meant to create this class directly #ifndef DOXYGEN diff --git a/src/engine/javascript_core/engine.cc b/src/engine/javascript_core/engine.cc index da3936a5..4f90d7f3 100644 --- a/src/engine/javascript_core/engine.cc +++ b/src/engine/javascript_core/engine.cc @@ -1,4 +1,4 @@ -#include +#include extern "C" { #include diff --git a/src/engine/javascript_core/engine_context.cc b/src/engine/javascript_core/engine_context.cc index 650ee970..e8309d56 100644 --- a/src/engine/javascript_core/engine_context.cc +++ b/src/engine/javascript_core/engine_context.cc @@ -1,4 +1,4 @@ -#include +#include extern "C" { #include diff --git a/src/engine/javascript_core/engine_promise.cc b/src/engine/javascript_core/engine_promise.cc index a3289077..cc2872fe 100644 --- a/src/engine/javascript_core/engine_promise.cc +++ b/src/engine/javascript_core/engine_promise.cc @@ -1,4 +1,4 @@ -#include +#include extern "C" { #include diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index dc05eab9..660aa40b 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -1,4 +1,4 @@ -#include +#include extern "C" { #include diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index 7f621a10..7d768c30 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -1,15 +1,15 @@ -add_executable(sourcemeta_includejs_engine_unit +add_executable(includejs_engine_unit engine_binding_test.cc engine_evaluate_test.cc engine_stacktraces_test.cc engine_value_object_test.cc) -sourcemeta_includejs_add_compile_options(sourcemeta_includejs_engine_unit) +sourcemeta_includejs_add_compile_options(includejs_engine_unit) -target_link_libraries(sourcemeta_includejs_engine_unit +target_link_libraries(includejs_engine_unit PRIVATE GTest::gtest GTest::gtest_main) -target_link_libraries(sourcemeta_includejs_engine_unit - PRIVATE sourcemeta::includejs::engine) -gtest_discover_tests(sourcemeta_includejs_engine_unit) -set_target_properties(sourcemeta_includejs_engine_unit +target_link_libraries(includejs_engine_unit + PRIVATE includejs::engine) +gtest_discover_tests(includejs_engine_unit) +set_target_properties(includejs_engine_unit PROPERTIES FOLDER "IncludeJS/Engine") diff --git a/test/engine/engine_binding_test.cc b/test/engine/engine_binding_test.cc index 5cc7c688..fa03582a 100644 --- a/test/engine/engine_binding_test.cc +++ b/test/engine/engine_binding_test.cc @@ -1,6 +1,6 @@ #include -#include +#include static auto is_string(const sourcemeta::includejs::Context &context, SOURCEMETA_INCLUDEJS_ARGS arguments) diff --git a/test/engine/engine_evaluate_test.cc b/test/engine/engine_evaluate_test.cc index 734d9ec5..d32ec0e0 100644 --- a/test/engine/engine_evaluate_test.cc +++ b/test/engine/engine_evaluate_test.cc @@ -1,6 +1,6 @@ #include -#include +#include TEST(IncludeJS_Engine, evaluate_result_integer) { sourcemeta::includejs::Engine engine; diff --git a/test/engine/engine_stacktraces_test.cc b/test/engine/engine_stacktraces_test.cc index 597c3cb4..b6c691ae 100644 --- a/test/engine/engine_stacktraces_test.cc +++ b/test/engine/engine_stacktraces_test.cc @@ -1,6 +1,6 @@ #include -#include +#include #include #include diff --git a/test/engine/engine_value_object_test.cc b/test/engine/engine_value_object_test.cc index 3582f28c..209352fe 100644 --- a/test/engine/engine_value_object_test.cc +++ b/test/engine/engine_value_object_test.cc @@ -1,6 +1,6 @@ #include -#include +#include // TODO(tonygo): Add tests for each kind of type TEST(IncludeJS_Engine, set_object_property) { diff --git a/test/packaging/find_package/CMakeLists.txt b/test/packaging/find_package/CMakeLists.txt index 8ceef97d..6e006ecd 100644 --- a/test/packaging/find_package/CMakeLists.txt +++ b/test/packaging/find_package/CMakeLists.txt @@ -6,4 +6,4 @@ set(CMAKE_CXX_EXTENSIONS OFF) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/../../../cmake") find_package(IncludeJS REQUIRED) add_executable(includejs_hello hello.cc) -target_link_libraries(includejs_hello PRIVATE sourcemeta::includejs::engine) +target_link_libraries(includejs_hello PRIVATE includejs::engine) diff --git a/test/packaging/find_package/hello.cc b/test/packaging/find_package/hello.cc index d6c0807b..69488c9e 100644 --- a/test/packaging/find_package/hello.cc +++ b/test/packaging/find_package/hello.cc @@ -1,4 +1,4 @@ -#include +#include #include // EXIT_SUCCESS #include // EXIT_SUCCESS diff --git a/vendor/noa/cmake/noa/library.cmake b/vendor/noa/cmake/noa/library.cmake index 527bbfe5..dd7019a5 100644 --- a/vendor/noa/cmake/noa/library.cmake +++ b/vendor/noa/cmake/noa/library.cmake @@ -2,9 +2,6 @@ function(noa_library) cmake_parse_arguments(NOA_LIBRARY "" "NAMESPACE;PROJECT;NAME;FOLDER" "PRIVATE_HEADERS;SOURCES" ${ARGN}) - if(NOT NOA_LIBRARY_NAMESPACE) - message(FATAL_ERROR "You must pass the namespace name using the NAMESPACE option") - endif() if(NOT NOA_LIBRARY_PROJECT) message(FATAL_ERROR "You must pass the project name using the PROJECT option") endif() @@ -15,7 +12,12 @@ function(noa_library) message(FATAL_ERROR "You must pass the folder name using the FOLDER option") endif() - set(INCLUDE_PREFIX "include/${NOA_LIBRARY_NAMESPACE}/${NOA_LIBRARY_PROJECT}") + if(NOA_LIBRARY_NAMESPACE) + set(INCLUDE_PREFIX "include/${NOA_LIBRARY_NAMESPACE}/${NOA_LIBRARY_PROJECT}") + else() + set(INCLUDE_PREFIX "include/${NOA_LIBRARY_PROJECT}") + endif() + set(PUBLIC_HEADER "${INCLUDE_PREFIX}/${NOA_LIBRARY_NAME}.h") if(NOA_LIBRARY_SOURCES) @@ -27,41 +29,46 @@ function(noa_library) set(ABSOLUTE_PRIVATE_HEADERS) endif() + if(NOA_LIBRARY_NAMESPACE) + set(TARGET_NAME "${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME}") + set(ALIAS_NAME "${NOA_LIBRARY_NAMESPACE}::${NOA_LIBRARY_PROJECT}::${NOA_LIBRARY_NAME}") + else() + set(TARGET_NAME "${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME}") + set(ALIAS_NAME "${NOA_LIBRARY_PROJECT}::${NOA_LIBRARY_NAME}") + endif() + if(NOA_LIBRARY_SOURCES) - add_library(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + add_library(${TARGET_NAME} ${PUBLIC_HEADER} ${ABSOLUTE_PRIVATE_HEADERS} ${NOA_LIBRARY_SOURCES}) else() - add_library(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} INTERFACE + add_library(${TARGET_NAME} INTERFACE ${PUBLIC_HEADER} ${ABSOLUTE_PRIVATE_HEADERS}) endif() - add_library(${NOA_LIBRARY_NAMESPACE}::${NOA_LIBRARY_PROJECT}::${NOA_LIBRARY_NAME} - ALIAS ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME}) + add_library(${ALIAS_NAME} ALIAS ${TARGET_NAME}) if(NOA_LIBRARY_SOURCES) - target_include_directories(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} - PUBLIC - "$" - "$") + target_include_directories(${TARGET_NAME} PUBLIC + "$" + "$") else() - target_include_directories(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} - INTERFACE - "$" - "$") + target_include_directories(${TARGET_NAME} INTERFACE + "$" + "$") endif() if(NOA_LIBRARY_SOURCES) - set_target_properties(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + set_target_properties(${TARGET_NAME} PROPERTIES - OUTPUT_NAME ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + OUTPUT_NAME ${TARGET_NAME} PUBLIC_HEADER "${PUBLIC_HEADER}" PRIVATE_HEADER "${ABSOLUTE_PRIVATE_HEADERS}" EXPORT_NAME "${NOA_LIBRARY_PROJECT}::${NOA_LIBRARY_NAME}" FOLDER "${NOA_LIBRARY_FOLDER}") else() - set_target_properties(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + set_target_properties(${TARGET_NAME} PROPERTIES - OUTPUT_NAME ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + OUTPUT_NAME ${TARGET_NAME} PUBLIC_HEADER "${PUBLIC_HEADER}" PRIVATE_HEADER "${ABSOLUTE_PRIVATE_HEADERS}" FOLDER "${NOA_LIBRARY_FOLDER}") @@ -69,15 +76,15 @@ function(noa_library) if(NOA_LIBRARY_SOURCES) include(GenerateExportHeader) - generate_export_header(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + generate_export_header(${TARGET_NAME} EXPORT_FILE_NAME ${NOA_LIBRARY_NAME}_export.h) - set_target_properties(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + set_target_properties(${TARGET_NAME} PROPERTIES SOVERSION "${PROJECT_VERSION_MAJOR}" VERSION "${PROJECT_VERSION}") # To find the generated files - target_include_directories(${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + target_include_directories(${TARGET_NAME} PUBLIC "$") endif() endfunction() @@ -85,9 +92,6 @@ endfunction() function(noa_library_install) cmake_parse_arguments(NOA_LIBRARY "" "NAMESPACE;PROJECT;NAME" "" ${ARGN}) - if(NOT NOA_LIBRARY_NAMESPACE) - message(FATAL_ERROR "You must pass the namespace name using the NAMESPACE option") - endif() if(NOT NOA_LIBRARY_PROJECT) message(FATAL_ERROR "You must pass the project name using the PROJECT option") endif() @@ -95,22 +99,34 @@ function(noa_library_install) message(FATAL_ERROR "You must pass the library name using the NAME option") endif() + if(NOA_LIBRARY_NAMESPACE) + set(COMPONENT_NAME "${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}") + set(TARGET_NAME "${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME}") + set(INCLUDE_PATH "${CMAKE_INSTALL_INCLUDEDIR}/${NOA_LIBRARY_NAMESPACE}/${NOA_LIBRARY_PROJECT}") + set(NAMESPACE_PREFIX "${NOA_LIBRARY_NAMESPACE}::") + else() + set(COMPONENT_NAME "${NOA_LIBRARY_PROJECT}") + set(TARGET_NAME "${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME}") + set(INCLUDE_PATH "${CMAKE_INSTALL_INCLUDEDIR}/${NOA_LIBRARY_PROJECT}") + set(NAMESPACE_PREFIX "") + endif() + include(GNUInstallDirs) - install(TARGETS ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} - EXPORT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} - PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${NOA_LIBRARY_NAMESPACE}/${NOA_LIBRARY_PROJECT}" - COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_dev - PRIVATE_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${NOA_LIBRARY_NAMESPACE}/${NOA_LIBRARY_PROJECT}" - COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_dev + install(TARGETS ${TARGET_NAME} + EXPORT ${TARGET_NAME} + PUBLIC_HEADER DESTINATION "${INCLUDE_PATH}" + COMPONENT ${COMPONENT_NAME}_dev + PRIVATE_HEADER DESTINATION "${INCLUDE_PATH}" + COMPONENT ${COMPONENT_NAME}_dev RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT} + COMPONENT ${COMPONENT_NAME} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT} - NAMELINK_COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_dev + COMPONENT ${COMPONENT_NAME} + NAMELINK_COMPONENT ${COMPONENT_NAME}_dev ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_dev) - install(EXPORT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_${NOA_LIBRARY_NAME} + COMPONENT ${COMPONENT_NAME}_dev) + install(EXPORT ${TARGET_NAME} DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${NOA_LIBRARY_PROJECT}" - NAMESPACE ${NOA_LIBRARY_NAMESPACE}:: - COMPONENT ${NOA_LIBRARY_NAMESPACE}_${NOA_LIBRARY_PROJECT}_dev) + NAMESPACE ${NAMESPACE_PREFIX} + COMPONENT ${COMPONENT_NAME}_dev) endfunction() From 15040af5279b15456f5a285ed36f69b3f113aefd Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Wed, 21 Feb 2024 10:00:47 -0400 Subject: [PATCH 03/19] Fix typo on `INCLUDEJS_BACKEND` CMake option (#30) Signed-off-by: Juan Cruz Viotti --- .github/workflows/ci.yml | 4 ++-- Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d5c5f2f..652a0e0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,7 @@ jobs: run: > cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release - -DINCLUDE_BACKEND:STRING=JavaScriptCore + -DINCLUDEJS_BACKEND:STRING=JavaScriptCore -DINCLUDEJS_TESTS:BOOL=ON -DINCLUDEJS_DOCS:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=OFF @@ -89,7 +89,7 @@ jobs: run: > cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release - -DINCLUDE_BACKEND:STRING=JavaScriptCore + -DINCLUDEJS_BACKEND:STRING=JavaScriptCore -DINCLUDEJS_TESTS:BOOL=ON -DINCLUDEJS_DOCS:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=ON diff --git a/Makefile b/Makefile index fe18c99d..2fc14985 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ configure: .always $(CMAKE) -S . -B ./build \ -DCMAKE_BUILD_TYPE:STRING=$(PRESET) \ -DCMAKE_COMPILE_WARNING_AS_ERROR:BOOL=ON \ - -DINCLUDE_BACKEND:STRING=JavaScriptCore \ + -DINCLUDEJS_BACKEND:STRING=JavaScriptCore \ -DINCLUDEJS_ENGINE:BOOL=ON \ -DINCLUDEJS_TESTS:BOOL=ON \ -DINCLUDEJS_DOCS:BOOL=ON \ From 66b6b35bedf5b2e88539c560db073e204f2ace94 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Wed, 21 Feb 2024 10:07:28 -0400 Subject: [PATCH 04/19] Install `FindJavaScriptCore.cmake` to simplify consumption (#31) Now we don't need clients to manually specify `CMAKE_MODULE_PATH` Signed-off-by: Juan Cruz Viotti --- config.cmake.in | 2 ++ src/engine/CMakeLists.txt | 8 ++++++++ test/packaging/find_package/CMakeLists.txt | 1 - 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config.cmake.in b/config.cmake.in index 0aeac31e..17dce9c9 100644 --- a/config.cmake.in +++ b/config.cmake.in @@ -7,6 +7,8 @@ if(NOT INCLUDEJS_COMPONENTS) list(APPEND INCLUDEJS_COMPONENTS engine) endif() +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") + foreach(component ${INCLUDEJS_COMPONENTS}) if(component STREQUAL "engine") include(CMakeFindDependencyMacro) diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 46788890..5c66d03e 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -16,9 +16,17 @@ noa_library(PROJECT includejs NAME engine FOLDER "IncludeJS/Engine" PRIVATE_HEADERS context.h function.h error.h promise.h value.h SOURCES ${INCLUDEJS_ENGINE_SOURCES}) + if(INCLUDEJS_INSTALL) noa_library_install(PROJECT includejs NAME engine) + if(INCLUDEJS_BACKEND STREQUAL "JavaScriptCore") + install(FILES + "${PROJECT_SOURCE_DIR}/cmake/FindJavaScriptCore.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/includejs" + COMPONENT includejs_dev) + endif() endif() + sourcemeta_includejs_add_compile_options(includejs_engine) if(INCLUDEJS_BACKEND STREQUAL "JavaScriptCore") diff --git a/test/packaging/find_package/CMakeLists.txt b/test/packaging/find_package/CMakeLists.txt index 6e006ecd..a80d027e 100644 --- a/test/packaging/find_package/CMakeLists.txt +++ b/test/packaging/find_package/CMakeLists.txt @@ -3,7 +3,6 @@ project(includejs_hello VERSION 0.0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/../../../cmake") find_package(IncludeJS REQUIRED) add_executable(includejs_hello hello.cc) target_link_libraries(includejs_hello PRIVATE includejs::engine) From 9b5af021a99082fc001d9734fc567c8b7195f996 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Wed, 21 Feb 2024 10:07:53 -0400 Subject: [PATCH 05/19] Clarify backend to run on GitHub Actions (#29) So we can more conveniently increase the matrix for other engines like V8. Signed-off-by: Juan Cruz Viotti --- .github/workflows/ci.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 652a0e0e..4999d3e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,31 +9,36 @@ jobs: fail-fast: false matrix: platform: - # TODO: Build on more platforms - os: macos-latest cc: clang cxx: clang++ type: static + backend: JavaScriptCore - os: macos-latest cc: clang cxx: clang++ type: shared + backend: JavaScriptCore - os: ubuntu-latest cc: clang cxx: clang++ type: static + backend: JavaScriptCore - os: ubuntu-latest cc: gcc cxx: g++ type: static + backend: JavaScriptCore - os: ubuntu-latest cc: clang cxx: clang++ type: shared + backend: JavaScriptCore - os: ubuntu-latest cc: gcc cxx: g++ type: shared + backend: JavaScriptCore # Sanitizers - os: ubuntu-latest @@ -41,11 +46,13 @@ jobs: cxx: clang++ type: static options: -DINCLUDEJS_ADDRESS_SANITIZER:BOOL=ON + backend: JavaScriptCore - os: ubuntu-latest cc: clang cxx: clang++ type: static options: -DINCLUDEJS_UNDEFINED_SANITIZER:BOOL=ON + backend: JavaScriptCore runs-on: ${{ matrix.platform.os }} env: @@ -78,7 +85,7 @@ jobs: run: > cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release - -DINCLUDEJS_BACKEND:STRING=JavaScriptCore + -DINCLUDEJS_BACKEND:STRING=${{ matrix.platform.backend }} -DINCLUDEJS_TESTS:BOOL=ON -DINCLUDEJS_DOCS:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=OFF @@ -89,7 +96,7 @@ jobs: run: > cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=Release - -DINCLUDEJS_BACKEND:STRING=JavaScriptCore + -DINCLUDEJS_BACKEND:STRING=${{ matrix.platform.backend }} -DINCLUDEJS_TESTS:BOOL=ON -DINCLUDEJS_DOCS:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=ON From fca68b81d029f137c1420722b9e67623e163161c Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Wed, 21 Feb 2024 20:48:07 +0100 Subject: [PATCH 06/19] feat(value): add null (#35) Signed-off-by: Tony Gorez --- src/engine/include/includejs/engine_value.h | 1 + src/engine/javascript_core/engine_context.cc | 4 ++++ src/engine/javascript_core/engine_value.cc | 4 ++++ test/engine/CMakeLists.txt | 3 ++- test/engine/engine_value_null_test.cc | 16 ++++++++++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/engine/engine_value_null_test.cc diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index 966d9f87..c0b6696d 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -34,6 +34,7 @@ class INCLUDEJS_ENGINE_EXPORT Value { auto is_error() const -> bool; auto is_object() const -> bool; auto is_boolean() const -> bool; + auto is_null() const -> bool; auto to_number() const -> double; auto to_string() const -> std::string; auto to_boolean() const -> bool; diff --git a/src/engine/javascript_core/engine_context.cc b/src/engine/javascript_core/engine_context.cc index e8309d56..74ba79c9 100644 --- a/src/engine/javascript_core/engine_context.cc +++ b/src/engine/javascript_core/engine_context.cc @@ -80,6 +80,10 @@ auto Context::from(const char *value) const -> Value { return {this->internal->context, result}; } +auto Context::from(std::nullptr_t) const -> Value { + return {this->internal->context, JSValueMakeNull(this->internal->context)}; +} + auto Context::global() const -> Value { return {this->internal->context, this->internal->global}; } diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index 660aa40b..2ccd2e73 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -66,6 +66,10 @@ auto Value::is_boolean() const -> bool { return JSValueIsBoolean(this->internal->context, this->internal->value); } +auto Value::is_null() const -> bool { + return JSValueIsNull(this->internal->context, this->internal->value); +} + auto Value::to_number() const -> double { assert(is_number()); JSValueRef exception = nullptr; diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index 7d768c30..53492745 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -2,7 +2,8 @@ add_executable(includejs_engine_unit engine_binding_test.cc engine_evaluate_test.cc engine_stacktraces_test.cc - engine_value_object_test.cc) + engine_value_object_test.cc + engine_value_null_test.cc) sourcemeta_includejs_add_compile_options(includejs_engine_unit) diff --git a/test/engine/engine_value_null_test.cc b/test/engine/engine_value_null_test.cc new file mode 100644 index 00000000..532af606 --- /dev/null +++ b/test/engine/engine_value_null_test.cc @@ -0,0 +1,16 @@ +#include + +#include + +TEST(IncludeJS_Engine, create_null) { + sourcemeta::includejs::Engine engine; + + auto null = engine.context().from(nullptr); + EXPECT_TRUE(null.is_null()); +} + +TEST(IncludeJS_Engine, evaluate_null) { + sourcemeta::includejs::Engine engine; + sourcemeta::includejs::Value result{engine.evaluate("null", "index.js")}; + EXPECT_TRUE(result.is_null()); +} From c1f65eed15373b4cc96d75fd61f4f861065a0b36 Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Wed, 21 Feb 2024 20:48:23 +0100 Subject: [PATCH 07/19] test(value): revamp test for object (#37) Signed-off-by: Tony Gorez --- test/engine/engine_value_object_test.cc | 36 ++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/test/engine/engine_value_object_test.cc b/test/engine/engine_value_object_test.cc index 209352fe..283349fa 100644 --- a/test/engine/engine_value_object_test.cc +++ b/test/engine/engine_value_object_test.cc @@ -2,17 +2,45 @@ #include -// TODO(tonygo): Add tests for each kind of type -TEST(IncludeJS_Engine, set_object_property) { +TEST(IncludeJS_Engine, create_object) { + sourcemeta::includejs::Engine engine; + + auto object = engine.context().make_object(); + + EXPECT_TRUE(object.is_object()); +} + +TEST(IncludeJS_Engine, transform_object_to_map) { sourcemeta::includejs::Engine engine; auto object = engine.context().make_object(); object.set("foo", engine.context().from(42)); - engine.bind_global({"obj"}, std::move(object)); - sourcemeta::includejs::Value result{engine.evaluate("obj.foo", "index.js")}; + auto map = object.to_map(); + EXPECT_EQ(map.size(), 1); + EXPECT_EQ(map.at("foo").to_number(), 42); +} + +TEST(IncludeJS_Engine, evaluate_object) { + sourcemeta::includejs::Engine engine; + sourcemeta::includejs::Value result{engine.evaluate("({})", "index.js")}; + EXPECT_TRUE(result.is_object()); +} + +TEST(IncludeJS_Engine, set_and_get_object_property) { + sourcemeta::includejs::Engine engine; + + auto object = engine.context().make_object(); + object.set("foo", engine.context().from(42)); + object.set("bar", engine.context().from("baz")); + + sourcemeta::includejs::Value result = object.at("foo").value(); EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 42); + + sourcemeta::includejs::Value result2 = object.at("bar").value(); + EXPECT_TRUE(result2.is_string()); + EXPECT_EQ(result2.to_string(), "baz"); } TEST(IncludeJS_Engine, set_object_function) { From ba9f9e2bd25e871ab7ac2ce7cc37ddf853ce5f70 Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Wed, 21 Feb 2024 20:53:41 +0100 Subject: [PATCH 08/19] feat(value): add is_undefined (#36) Signed-off-by: Tony Gorez --- src/engine/include/includejs/engine_value.h | 1 + src/engine/javascript_core/engine_value.cc | 4 ++++ test/engine/CMakeLists.txt | 1 + test/engine/engine_value_undefined_test.cc | 16 ++++++++++++++++ 4 files changed, 22 insertions(+) create mode 100644 test/engine/engine_value_undefined_test.cc diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index c0b6696d..3d78995b 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -34,6 +34,7 @@ class INCLUDEJS_ENGINE_EXPORT Value { auto is_error() const -> bool; auto is_object() const -> bool; auto is_boolean() const -> bool; + auto is_undefined() const -> bool; auto is_null() const -> bool; auto to_number() const -> double; auto to_string() const -> std::string; diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index 2ccd2e73..ac0d3ff3 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -38,6 +38,10 @@ auto Value::is_string() const -> bool { return JSValueIsString(this->internal->context, this->internal->value); } +auto Value::is_undefined() const -> bool { + return JSValueIsUndefined(this->internal->context, this->internal->value); +} + auto Value::is_error() const -> bool { JSObjectRef global = JSContextGetGlobalObject(this->internal->context); JSStringRef class_name = JSStringCreateWithUTF8CString("Error"); diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index 53492745..9b9ea0aa 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(includejs_engine_unit engine_evaluate_test.cc engine_stacktraces_test.cc engine_value_object_test.cc + engine_value_undefined_test.cc engine_value_null_test.cc) sourcemeta_includejs_add_compile_options(includejs_engine_unit) diff --git a/test/engine/engine_value_undefined_test.cc b/test/engine/engine_value_undefined_test.cc new file mode 100644 index 00000000..2a6b6f66 --- /dev/null +++ b/test/engine/engine_value_undefined_test.cc @@ -0,0 +1,16 @@ +#include + +#include + +TEST(IncludeJS_Engine, create_undefined) { + sourcemeta::includejs::Engine engine; + + auto object = engine.context().make_undefined(); + EXPECT_TRUE(object.is_undefined()); +} + +TEST(IncludeJS_Engine, evaluate_undefined) { + sourcemeta::includejs::Engine engine; + sourcemeta::includejs::Value result{engine.evaluate("undefined", "index.js")}; + EXPECT_TRUE(result.is_undefined()); +} From 6e72884abca32c7ed60fccd00e5aae2d09f4a9ac Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Thu, 22 Feb 2024 09:41:44 +0100 Subject: [PATCH 09/19] feat(value): add array (#38) Signed-off-by: Tony Gorez --- src/engine/include/includejs/engine_context.h | 1 + src/engine/include/includejs/engine_value.h | 4 + src/engine/javascript_core/engine_context.cc | 5 + src/engine/javascript_core/engine_value.cc | 138 ++++++++++++++---- test/engine/CMakeLists.txt | 1 + test/engine/engine_value_array_test.cc | 44 ++++++ 6 files changed, 161 insertions(+), 32 deletions(-) create mode 100644 test/engine/engine_value_array_test.cc diff --git a/src/engine/include/includejs/engine_context.h b/src/engine/include/includejs/engine_context.h index f0e7cd4b..3a6118af 100644 --- a/src/engine/include/includejs/engine_context.h +++ b/src/engine/include/includejs/engine_context.h @@ -24,6 +24,7 @@ class INCLUDEJS_ENGINE_EXPORT Context { auto make_error(const std::string &message) const -> Value; auto make_object() const -> Value; auto make_promise() const -> Promise; + auto make_array() const -> Value; auto from(const std::string &value) const -> Value; auto from(const char *) const -> Value; auto from(int value) const -> Value; diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index 3d78995b..b41ec223 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -36,13 +36,17 @@ class INCLUDEJS_ENGINE_EXPORT Value { auto is_boolean() const -> bool; auto is_undefined() const -> bool; auto is_null() const -> bool; + auto is_array() const -> bool; auto to_number() const -> double; auto to_string() const -> std::string; auto to_boolean() const -> bool; auto at(const std::string &property) const -> std::optional; + auto at(const unsigned int &position) const -> std::optional; auto set(const std::string &property, Value value) -> void; auto set(const std::string &property, Function function) -> void; + auto push(Value value) -> void; auto to_map() const -> std::map; + auto to_vector() const -> std::vector; // For internal use only #ifndef DOXYGEN diff --git a/src/engine/javascript_core/engine_context.cc b/src/engine/javascript_core/engine_context.cc index 74ba79c9..e95160c9 100644 --- a/src/engine/javascript_core/engine_context.cc +++ b/src/engine/javascript_core/engine_context.cc @@ -59,6 +59,11 @@ auto Context::make_object() const -> Value { return {this->internal->context, res}; } +auto Context::make_array() const -> Value { + return {this->internal->context, + JSObjectMakeArray(this->internal->context, 0, nullptr, nullptr)}; +} + auto Context::make_promise() const -> Promise { return {static_cast(this->internal->context)}; } diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index ac0d3ff3..54b9ca84 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -18,6 +18,59 @@ struct Value::Internal { JSValueRef value; }; +static auto js_string_to_std_string(JSStringRef value) -> std::string { + // JavaScriptCore doesn't have a function to fetch the UTF-8 byte size + // of a given string. It can only give us the amount of Unicode code-points + // in the string, which may be more than the bytes required to store it. + // As a consequence, we can't do much than allocating the maximum possible + // buffer to hold the string. + const size_t max_size = JSStringGetMaximumUTF8CStringSize(value); + std::vector buffer(max_size); + // Converts a JavaScript string into a null-terminated UTF-8 string, + // and copies the result into an external byte buffer. + JSStringGetUTF8CString(value, buffer.data(), max_size); + return {buffer.data()}; +} + +// Converting a value into a string first requires copying +// the value reference into a string reference. +static auto js_value_to_std_string(JSContextRef context, JSValueRef value) + -> std::string { + JSValueRef exception = nullptr; + JSStringRef copy = JSValueToStringCopy(context, value, &exception); + assert(!exception); + + try { + std::string result{js_string_to_std_string(copy)}; + JSStringRelease(copy); + return result; + } catch (const std::exception &) { + JSStringRelease(copy); + throw; + } +} + +static auto get_current_object(JSContextRef context, JSValueRef value) + -> JSObjectRef { + JSValueRef exception = nullptr; + JSObjectRef object = JSValueToObject(context, value, &exception); + assert(!exception); + assert(object == value); + return object; +} + +static auto get_object_length(JSContextRef context, JSObjectRef object) + -> std::size_t { + JSValueRef exception = nullptr; + JSStringRef length_string = JSStringCreateWithUTF8CString("length"); + const double length = JSValueToNumber( + context, JSObjectGetProperty(context, object, length_string, &exception), + &exception); + assert(!exception); + JSStringRelease(length_string); + return static_cast(length); +} + Value::Value(const void *context, const void *value) : internal{std::make_unique()} { this->internal->context = static_cast(context); @@ -42,6 +95,10 @@ auto Value::is_undefined() const -> bool { return JSValueIsUndefined(this->internal->context, this->internal->value); } +auto Value::is_array() const -> bool { + return JSValueIsArray(this->internal->context, this->internal->value); +} + auto Value::is_error() const -> bool { JSObjectRef global = JSContextGetGlobalObject(this->internal->context); JSStringRef class_name = JSStringCreateWithUTF8CString("Error"); @@ -83,38 +140,6 @@ auto Value::to_number() const -> double { return result; } -static auto js_string_to_std_string(JSStringRef value) -> std::string { - // JavaScriptCore doesn't have a function to fetch the UTF-8 byte size - // of a given string. It can only give us the amount of Unicode code-points - // in the string, which may be more than the bytes required to store it. - // As a consequence, we can't do much than allocating the maximum possible - // buffer to hold the string. - const size_t max_size = JSStringGetMaximumUTF8CStringSize(value); - std::vector buffer(max_size); - // Converts a JavaScript string into a null-terminated UTF-8 string, - // and copies the result into an external byte buffer. - JSStringGetUTF8CString(value, buffer.data(), max_size); - return {buffer.data()}; -} - -// Converting a value into a string first requires copying -// the value reference into a string reference. -static auto js_value_to_std_string(JSContextRef context, JSValueRef value) - -> std::string { - JSValueRef exception = nullptr; - JSStringRef copy = JSValueToStringCopy(context, value, &exception); - assert(!exception); - - try { - std::string result{js_string_to_std_string(copy)}; - JSStringRelease(copy); - return result; - } catch (const std::exception &) { - JSStringRelease(copy); - throw; - } -} - auto Value::to_string() const -> std::string { assert(is_string()); return js_value_to_std_string(this->internal->context, this->internal->value); @@ -256,6 +281,55 @@ auto Value::to_map() const -> std::map { return map; } +auto Value::to_vector() const -> std::vector { + assert(is_array()); + JSObjectRef object = + get_current_object(this->internal->context, this->internal->value); + std::size_t length = get_object_length(this->internal->context, object); + + JSValueRef exception = nullptr; + std::vector vector; + for (unsigned int index = 0; index < static_cast(length); + index++) { + JSValueRef value = JSObjectGetPropertyAtIndex(this->internal->context, + object, index, &exception); + assert(!exception); + vector.emplace_back(static_cast(this->internal->context), + value); + } + return vector; +} + +auto Value::at(const unsigned int &position) const -> std::optional { + assert(is_array()); + JSObjectRef object = + get_current_object(this->internal->context, this->internal->value); + std::size_t length = get_object_length(this->internal->context, object); + + if (position >= static_cast(length)) { + return std::nullopt; + } + + JSValueRef exception = nullptr; + JSValueRef result = JSObjectGetPropertyAtIndex(this->internal->context, + object, position, &exception); + assert(!exception); + return std::make_optional(this->internal->context, result); +} + +auto Value::push(Value value) -> void { + assert(is_array()); + JSObjectRef object = + get_current_object(this->internal->context, this->internal->value); + std::size_t length = get_object_length(this->internal->context, object); + + JSValueRef exception = nullptr; + JSObjectSetPropertyAtIndex( + this->internal->context, object, static_cast(length), + static_cast(value.native()), &exception); + assert(!exception); +} + auto Value::native() const -> const void * { return static_cast(this->internal->value); } diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index 9b9ea0aa..a3601d8c 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(includejs_engine_unit engine_evaluate_test.cc engine_stacktraces_test.cc engine_value_object_test.cc + engine_value_array_test.cc engine_value_undefined_test.cc engine_value_null_test.cc) diff --git a/test/engine/engine_value_array_test.cc b/test/engine/engine_value_array_test.cc new file mode 100644 index 00000000..8e0a56a9 --- /dev/null +++ b/test/engine/engine_value_array_test.cc @@ -0,0 +1,44 @@ +#include + +#include + +TEST(IncludeJS_Engine, create_array) { + sourcemeta::includejs::Engine engine; + + auto arr = engine.context().make_array(); + + EXPECT_TRUE(arr.is_array()); +} + +TEST(IncludeJS_Engine, transform_array_to_vector) { + sourcemeta::includejs::Engine engine; + + auto arr = engine.context().make_array(); + arr.push(engine.context().from(42)); + + auto vec = arr.to_vector(); + EXPECT_EQ(vec.size(), 1); + EXPECT_EQ(vec.at(0).to_number(), 42); +} + +TEST(IncludeJS_Engine, evaluate_array) { + sourcemeta::includejs::Engine engine; + sourcemeta::includejs::Value result{engine.evaluate("([])", "index.js")}; + EXPECT_TRUE(result.is_array()); +} + +TEST(IncludeJS_Engine, push_and_get_array_element) { + sourcemeta::includejs::Engine engine; + + auto arr = engine.context().make_array(); + arr.push(engine.context().from(42)); + arr.push(engine.context().from("baz")); + + sourcemeta::includejs::Value result = arr.at(0).value(); + EXPECT_TRUE(result.is_number()); + EXPECT_EQ(result.to_number(), 42); + + sourcemeta::includejs::Value result2 = arr.at(1).value(); + EXPECT_TRUE(result2.is_string()); + EXPECT_EQ(result2.to_string(), "baz"); +} From 30311a3a10791573ce79c5d33f29924709cfcfbc Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Thu, 22 Feb 2024 10:10:57 +0100 Subject: [PATCH 10/19] feat(value): add is_function (#39) Signed-off-by: Tony Gorez --- src/engine/include/includejs/engine_value.h | 1 + src/engine/javascript_core/engine_value.cc | 11 +++++++++++ test/engine/CMakeLists.txt | 1 + test/engine/engine_value_function_test.cc | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 test/engine/engine_value_function_test.cc diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index b41ec223..01cf0d68 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -37,6 +37,7 @@ class INCLUDEJS_ENGINE_EXPORT Value { auto is_undefined() const -> bool; auto is_null() const -> bool; auto is_array() const -> bool; + auto is_function() const -> bool; auto to_number() const -> double; auto to_string() const -> std::string; auto to_boolean() const -> bool; diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index 54b9ca84..caf2b227 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -131,6 +131,17 @@ auto Value::is_null() const -> bool { return JSValueIsNull(this->internal->context, this->internal->value); } +auto Value::is_function() const -> bool { + if (!is_object()) { + return false; + } + + JSObjectRef object = + get_current_object(this->internal->context, this->internal->value); + + return JSObjectIsFunction(this->internal->context, object); +} + auto Value::to_number() const -> double { assert(is_number()); JSValueRef exception = nullptr; diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index a3601d8c..e40c9bd1 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(includejs_engine_unit engine_stacktraces_test.cc engine_value_object_test.cc engine_value_array_test.cc + engine_value_function_test.cc engine_value_undefined_test.cc engine_value_null_test.cc) diff --git a/test/engine/engine_value_function_test.cc b/test/engine/engine_value_function_test.cc new file mode 100644 index 00000000..8726690a --- /dev/null +++ b/test/engine/engine_value_function_test.cc @@ -0,0 +1,20 @@ +#include + +#include + +TEST(IncludeJS_Engine, is_function) { + sourcemeta::includejs::Engine engine; + + auto obj = engine.context().make_object(); + obj.set( + "foo", + [](std::vector arguments) + -> sourcemeta::includejs::Value { return std::move(arguments[0]); }); + obj.set("bar", engine.context().from(42)); + + EXPECT_TRUE(obj.at("foo").has_value()); + EXPECT_TRUE(obj.at("foo").value().is_function()); + + EXPECT_TRUE(obj.at("bar").has_value()); + EXPECT_FALSE(obj.at("bar").value().is_function()); +} From 546f7b1516c35925a11f1823db395692c974d1da Mon Sep 17 00:00:00 2001 From: Lorenzo Alberto Maria Ambrosi Date: Thu, 22 Feb 2024 11:57:54 +0100 Subject: [PATCH 11/19] Make logo more consistent with the org (#40) Closes: #15 Signed-off-by: Lorenzo Alberto Maria Ambrosi --- assets/banner.png | Bin 25095 -> 27044 bytes assets/logo.png | Bin 12382 -> 12665 bytes assets/logo.svg | 2 +- doxygen/logo.png | Bin 2382 -> 2334 bytes 4 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 assets/banner.png mode change 100644 => 100755 assets/logo.png mode change 100644 => 100755 assets/logo.svg mode change 100644 => 100755 doxygen/logo.png diff --git a/assets/banner.png b/assets/banner.png old mode 100644 new mode 100755 index 598c331f55bfbdf796e64e720af0e7cb7ab88f65..d7d8ff4677b82e45051c5b1597b325d4634f8eaf GIT binary patch literal 27044 zcmcG$bzD_#*EPBU2|-F41q6fc?hX-A0Y#;|yW5}y1woMx36TbAq+7Za1ZnA(?lYJ7 z^FH7Eyx%$Jj}!NgTXFBT*Sd1fF~=C!esy0}5g(Tt7llIM-&T@SL!mGh;rAmPEclb> zq0JKfb}|9*_Ui=*}5hZq}inpm44 z1LMTW&B6U2tu!_gakg-_Hu)b7m$r8PAFo(jAUzSWHn24lXLM&bHZe7Dv36#Zka4lF zHooRz=i+$H&dv6kvVp6CIyBVI-uarNi>(1oJgasE&khG|Gx5{590hk zY0lrv{#)<=9}bMPv$Lax;lBsR)``R5?<+3Ih;qPWa~c>U!^8C-!}HIlM5K+K{#(P5 zo~WBR{Et^)fRH!r4IG_JG(7B0#2M90oM2dtO#b_-_}2|(9Zd|JO^hXYxOn*3xp>%l zxWzdC$6NoNSh0V-A@A;d+gO6jgojsv*N}^yn}>^!osXB7kKK@4n4g``kc*Ft&yd%M z&(P@K_xk4}|J$7u4BOBE(f0psry;ZacMBu)3va;u^8UyC!fPVZF3#q5juMJ? zjwYVhH0*3W#E?t>>*fE^wg2}E5kkm+tipe{&)vZOe_MZWvB=-GV&|w~XJ;)TYhdeY zAjbJWU;e*q9`zYuh1AvE{H)cNni_Rc$cr)Hf%RWC zG&MU-i@({H!=I;%!>(U-&d$zoad7TSNj-}bv^z`F!^XsnrJ+M<2fiSHPsj=_{0Tof@h-l8n(ewas>87&8+hq~v2nV$Pvs>N)V>@tj`a`c78Y3f`5&Giv`Lou zo%$tmD%*@R2dHgXxJUoo0!G1>ZF$IRw zy{J20kd>ZZ`sdG|riu=tI$vGC7xzl!DAM_8prN6ewxLa7G9d^+w{_Z{30hfDcUDDk zRY>3UYB|N_%c(z$%~rzwPSReyeAyj_QUCG*vLdSeyG;kbm~@utH=vV|lE%Cf-m-3h|#aILB07WMd7x8cdNJwbe0v5{3K zR2-UU16vb&MbHl%*c30cix3)E$u0S@3AeIL6{70FM)=fr6t49Beriy5N z{`SG5D3lb*hsem(i5f5Uo^cfqkIGxB37?-7n`V`j{eW?b!};4JKIw-KAI5PTVQHG% zp&#umr40>fz-sM=M*q5sjAY6yW_I@PG2BKaX1%n5Fa;w#m zA{cD}FI`FbOEPXGWtZACK7!FODqO&iT`Q8ZrUbwUFr7i{sdvC zt}wKE{K9`)u{u$s1$*?%Pis>}>FXik;lsZwo#1ixa(`ErpyOg6eM@umA~XV;dGQ0M zUOqgg*a*dS@$Uk?`~LlVCKeXun>TO5`?uN1Lx1FHWjf5Z!hAlv$h25r_wdmp7IASM zDk>@nEuWR|+;LeNxaqRkC!Hwj_Q=_}L?N6uZ_M^<_v&X@f6jZWPvCK%k7Pc!;@8Q` z9=i?M=)4%pzsp-{zMdJ<@iZ#2n028~*r#^3M8HRvAwF>|-y`+eGnCC(*^HQkhq-+c?#749gaOiPF=UdtuBq z2mv-KDaqFL66#Ix3xWcd`7SDaYCfg5Fq*F)*G^AQcemQ;R%(yed4;G@_3;T3N6%$W zB<=cMe{uYpO4rjjU5$s8@#3rdN?!TSkovt?8VsrHA5)rGg|8C4xhkxd>^D&;C|7sb zZTCJgF>iCz{$(T@s`}OGFM&f%wup`I;pTPOb|KkA=aP~SmxR5Vf*Nf2tbV9??X4nV z7wH~4bZ;Pt&i6C3`X@>rt6vokFk$b)!_hYKr=n_4_q6UNiT&)0C6qWwG3|;mSXAM| z?~LXghG=#v@o>UxgPD!3t1tGghF)4n)8G(GUq!j$MnTW;j>p$a@!0!BR8(1rmb~y9!4K0HeB_MRHUo8i}!){N73v_vPa}gY{KQG%;X<4Eur0E z==Ck$-2^DUvV?@IG{TO}eX;P2w@nRswo?+zD=QB*H5myaUl3m<2wGlV?h2cJ5Jo4N zKkssUDS5?i>wD9F5VZuwyw(@vS3h!}7{R1*AWQ3Kl}pYvZ}FEe8hX9#wo|$Zs*IR4 zfm4;n)%%kk(&ZBajW>%GFI9cJ>10rwne6-2RdkpVB?ie!H?y#?Z!;DX6EjloHa1H8 zp{ePoKLlo#*1p4i*P^=vD?>s<$>`|pkO#@ZgP2)adA&_7EV8Z=V0*=&P@2CXk{GpK z8XuysH?bXZJ*dra&qQr}nq>fxQ<{?qOYBDlo0OXQ%n6W-i%7{9gT%of31A zmG+#-CsdG6K%~!645tn3xhm?Kdt*3hk^p61mE^Tvne1b8YQ}g;uWj0%#YH`0+G#rJ zG6~5;H8n#RFs#&+rj>((111iRo3c4h&5-cE1c{{Pal4F z3Cu4wJawQEah>Rkwb$e4=l48bD@S4;(&7vVZ?Xg~c4K9Ex*l^;opt-Wb6U8lO{49F z-t(4%=!E?KiejN&_T8F_f)OoooKtpL8{G{w zd(1`-p?)Pybp5TIFgEJsm!_Ui2865AdmxX{uDjb@elhoV>ie&VHHAXi0w@zm@Z(&;ISB^*&eIVl31_mcPG$j>LRc zv=g78L!ITyvYq)GKN`^jX+l%;^XZT)qqKJ?$L#9z;;1DO(8SPS{@MBXG_=ZXzgK%~ zlU}{*eRoVHhD&;^+^$Z$=jMYRG?e7Kckj~huLx)l8tLhsaN_$i$tGKiGG}g&&L`(o zqz_Msr+>b$ zHteu1&oOEXTOP;=O-)O4IX~UcG3!l|9Gx&MvUd`x6qVi}6MI02hDh~%E#V+Th^YDn*#AoBX`^eYOMtTkLG6LC+M8K5_k zZAgoH|K1$($kF(QubC?;3csFyy}s`7;Go^G2!2j1xAwNSA_@u$Ako1rGcBN==^<17 z{l^d3fx4!<%im2EQGHUY(%8N)@M_Ue)XPnTl6<1*)qRrZhxZaCe4f(N(*q2!e>w6J zkhgvcjLh0(?`eDgfu)rdlFeZp%~7y}QO}+Wby1qm9Afj?{LRHLg%VZS^=f~uQf?Z4 zbzM`_)lK@zjrw)1M;g02VQ@*qz~CbUkcST*d<+S}MY8U-Yf{gjKewE$t;v0qBO@#O zJ@*N3@vJ}$Tq`dhz@c0Hd3o9L`_K?{?DNB%N0#GNr7vE*FfQ60z!}cU&DD7DAR;?E z+j(n79xnRqu|043^GgOYxqW^2OKrzTS7U6mYHM|2v1aGz*PfiNY-|(&I>E%k$~Niz zfQyUE!#@j9eYab1GA8aLcd6B&%DBu+XD6i;nNe(}!hmG-xWjLTTM^ysZ@YC1sN-c# z=3ITevY)mv=D5t~uElNahOI0(i$nqZJKRR#Rz3cd4pX%%bo5caw#8!CD-uQ)F|m{E z@H@9}KX7m;GFUk}K3<76ORCJbu@;Eu;pN@^#+YnAS?eR>zL~>LQs*T#S+l*3Nj(6s{Lb_H$To1_GL$t_ke9bO*qjdRImv<@uo%i&+ee}2 z{jtVte|ecv__y*G)8qk}T{AIG-A|vF@HNd&`>n zax(R$o>wr+^`DBcWSfZwxY*>q-9sA|Z!>jcDkxO0Jfv_I+NgH@{odkuT}|hA(t6;N z8c%*q8uL^rawVGl-M)2n@Knp?>U@1vce-X*a8yBjU4iNP^`=6XmoHxyWNF_~b9F77 z@Y&a~nW%n3!J%!wIhrWqGVuG`yWNA?@EoUw9{eOT|2xqf7ArsUp4R!+2-u7|-<4l{ zdU$k{tykwu&2RZ$A?#`vQojuk#}xbj`SWL}#>-9C)Mo=`u-~en=9Z*nonBXLe0&bA zxF==RJcO#9<(vX)k!`R11Hm|6v#<&GS$tVDWi?pN2q^l0SO6RDEF*3<0Nx-lH5?2L*>)J$7fEeY@rBLV43g$yWq=CueekHVD7V z?gv;N)W;7o)bqOuXXWJ#pEZ$n94)_=Q0Dv*Eo{Q^q%EG5l(gNl6aq!P%gj~hdK5Gi z;Qy!GHG3iFjNYF}+0gJ3+iG*F0d`rGft}~QB(bdKW;vIQ37vc5yF>hb_or}SQNT7= zU+78XH|?TifAXcd&ymAt-|ytRrruHuh2Bv8a||+K;*SA%6mduUu7awW+u6N}Zidbi z>Y1v{92}~TavlzTx;to=>|?4V9G(8<3lD(zEVqpbYC+os0$MTic5Sypqc(z;*4AwJ zi0AJJ#S+tQ>ZZ=h8#I!>+H~HV&(~}AbprweEqfA#VOQ~Zzgb~kSkHBNTc?{es2=ch zw&bK6jaqb-JUYs0=_?`nkwV!Z?>S9Ajg{hJbJ)eFC(7^PC8wWpNgS-KovSz~TZq+M z&mb=O_|!1Bq}SG-QQVONlzr=NTspT=E0d_`n90hRwE#4fnSntDs#6ZFh3MaNbIbw) zkDy4^G&D>FpnAn-4Z>-6lDHQ15jOe&1PE#y8#j~r{f0MOECu7X!zYK^oRWmS$&z;W z8}-T@W);R=hIKq=UNLIu=&TKtYA+4mll%@N$ZtO-mG`(v2KK3CNhvZ9u-EPw7#JYM zxBKY&Kit>8Koou2r#) zfqw7z#a_kwE5HB{?m$rbtXZJ@#*=d>GV=1>1fd6hM}x`QzI+W3=g251GNH({YzZOD z&dYOI^3?47(<8dU1pVIH+WIoK_Q^zgcC6Ot>(Sm?4g{91>|p^eH65Kq1n>b&Qp6^> zYF^^<#{OW_;0>LmZkocIfiN0Tm2Si0pF3yA8?YC2q0Y10w7RX%DMvj1veak|=hS5) z(Q>k^@}~pGSKib-atXiaFgv<}=!G4PuL2WJ;(>wY%g}tSQ%R^P&(BxKJ+$v0o?~wg zj}PR3F=ij5WR82)A&_cVYrtT{cD?hpMQdatRp3m#Nnp%0BZFdoPV2&%6TNL|ZHra=ryjiys)_rD)*2}!YE2g~F&hR4N$w?W z^7?UdaS=^SOeE|ELYToNARu^L>n#j1L&zeH1p@un>Hg#_q}t~GG{r;JpvC&^hdER8 z^MO{w`CA{FzUOH67n|MtWTj;lN73Zy9cTn+W2hC`n3h@>xp~KGqE%V#!RaL%7-5k5?*`luWuz{(Wgg#mSRlD zdh*5i;;nm0T~^^d_rG|qZcaDF?xj;uP&7?W(ygzrznExTgy6Edxmgc&i9GL6yhfN> zRx{8MTs}w669xP!#-u@+nT(B%jmSfnmX;PL>m;GVqW_F-RZ!)=#h|UNO+-tpyVM)v zadya->^f3Y6>pBKOL84^{_dBSH4==??gg6zRmHyMlfK}$qanD?GM2%RPRIbZE{Nji zogVKSjh0xb7(%u-7%4P(Tw+cf65?NnAFiD7A~~5Z@Df$yp|^3WmU6~rs2Z9f-#|-V zS67RASQLlbgYCY{Z7UidTDc>t8$+o-4(HXOG_tKb-ZPI>I++Dbc+GW?g%ulgR_D`} zoez=m#46=Dp;laPGVse*sNeFxCM+CVhH+EQ7)C|z_out@w-!CZq0=qEvap_3zIcIt ziHhd}H#hfH;|whb^e>~Mqf-_pBFo3VnBe)I9h%h+61}-1Xsh3sBAuE%^HD8p6B61C zFgF|C1ta9MM;j#s=7!&T$t~Hc+u52UOSfPma0Trqev4wtDBZmOTs1hj#{2Mc-Ra(y zNsDUr$B!vhlO=Srdc99~hxsk}cV^qdji58$nbO(U=;_hkG2WXO#qW3DTcr{c7mr9v z>TzRHAtfg_1nSFfEkNboJ&Ny5I61chQ}wiMcIUO+&m!Z;Wh|*#`YsYvz#sG?Mbkb^Q5)u+G;;?%g^R&vjEC$jY z{Q_U*q2i`aX?I9xYB0OpBg5^2hv&4brYZlsryY}_-G3I2Rl!ke<(cHDE}IA5NUpDuef^P zMo+n?_0VVHU%!6!K|tcO7`Om6mcMdFBMf;&M8xxAv)-A5t=S5{a|y<^-b7J~{QUg; zOr$2d6zXV0MTt~#f&#|moQ&l-b*mL`@(gYV*PR}5`BkdC`0?Y`qOlnP8(DG79WFqZGZhuOiRZ%_7^MdBtm|rCwVtQL%u6j z#J}?Y8auM9`0d3f(@&m@lV2|ey7MVchEq57rJVQ;YO+7M5-yXGJz6<@>-O#2P}cjd zl*-}|6I6-b@L%kj>x_0dKl3TE{JvaT*V)-QTfLuG0wJntVuBXPaL~+Uq@~dyFGRe5 z?|*RM{%LHW;_FwVxsIs9q9W$)s;7CMbe*5GFfk!{!udy1X(_+9j?VPd)UyxlTB)|< zRc|}z+B-UAl$CL3W@jBh;LxsezHKJ_uoakYWZqQ`?=$m=i^ov2ay1T8&jywS8YzaB`>xL?s#uSDm1i&gcnUn2(%rlA0ACMP1Blenkn|X; zl%Y0Mpht%rfF4dOK4Y@618i}Md?@)_aT3f@%#tw1} zot>F6Y;J93U|>KWE3=VRP*8{(1v0BK^5z{b>ybj9f==Tv!)NEO3RfrV=m2RYln>@; za(2b><3S=L6JbR5801s9Jx#TC-P{xC=5~x@<<*9UhEZLIlystK<%~JnoPpsIZH_j# zNuMA<=Ce=)>6dj+gPP(1gtEJ*r{x%lI-zIId~25>ji~x*)DdrS)Z;o<;uW`>jYVmg zpL~82B=1@g1f1;p%?9M0PaCUx*}RR2kj50DXOMOa_8-!Reo=B8UJ$VT6$}vB*vxDe zu(Oh~vW%;%fSQ_GA@Ka(yWcgrxVigpt2#J16y*6s8B9z{+HCPP+568$U>XCH{m!TW zPOvy#*E{;8#}XyO5uFB!{V`&1iH&^4@UU^R zm&|@``SHhZURJ~SHs|>IiXg%H$u?n` z?RW^_p{9 zB69LT)9yG6y+P7W+<;USG>s}IH6~IR%LYhM4nW{L1GklE19S%-q$vc7socF27^!^Y zvdtB~be#h=b#;f61BafOa*IK%ws5*OAihfrEP9B$JyJa$--uA^5R;1hW(<+d-q~4B zLxc2acctw~5*gXmtFKcT%2+M^wz~ym_$(s#j+Z4y{_O6y1QTC>oQ{?9+w760B@1jb zsDWZzzGGgOb=`h@yrVCeTvPHpNO)7np4eu*vB=hp;SXL2_jzVcLdip|YVX4%bYFiW zgH-gyx74k_eq9A1j{}+;ff?&KYvz3>-Q&p4If&TIz<&^3zKjmhyyuS>)L~Ybp62FE zW^2G$UjoXg-i7Hu{w+`~tCPp6@xrxbBsyfQgl;b3I_tAbcD?5cDS0ZmDP z6|OH!SIc!Cp2($yxq;l=Tq0uP2d3iacMWu7o#a@e8lf4m)&jnM6{W~}6#O*Lv^MYQ zyIXe)fkar_&&^N1dFO-Fy?X_t4$mTWpz2|OM0x-5S;>N5!q z7p9rWc|xY8p3WMjd{xZ-?YlCCH`DsQMZZfP_;#lRl3ifmQ z?RWNoZC=xgKh;v|vv=JRar}+L=#ZhtEMPr?#7=Z3;Y?Co`O=Vkva+(PzbZ*UoHB?q z%>dac@bF{>ic-tW_k~wo20$|4Nh8l@6%*5bk9pL|=4wSjx!7rMuFl!@$3k!WvNS@bn}UpHnqO(BXVI8u zGWS8T_6n99uU*^dC^hS&+&T8_DR(szRbf&(i^7-*4bEelAYzNH1TzOJVH z;mru8O(<4UbZb0w2L?NOdliAbDw7Hi3p1U-y8k7+&QkD5)v}k z%hYw+`s%gM0c=RKSbkI#89F+8$z<_FxcgN7b4m$sp}`n32N2LcZ2@ZjI9~fYR6O2m zXR*OL#!FY1Heb7vp$h%9=hRwtrmRSyfkhHKz4cP#4>Fypi5lWXsto%+1_%FO>~VPr zA|*Cs?zdk zFxboe0uf#4)ynK_n$FnsoPIK(4@_vcZGZ}l+33t)n*PBS))rS(7NN_#!lnY|(!R1sQOVJd`a| z?n4f3^rt0p%`6QezcaDz1AvaB@m?IE^8>7QgZ6uI^b!(D9x6sgMo2J3xe>lbr9iem zSWF8SdUbjWB6-&yIW~%ymv`-lgLasV#mL+7RMR+YQbTHf60&0)OB$P-womlvjDkvJ z%5Hl#7R2o2&o(B7XPa2^-VS*BqT&qH)=oNYNveP#N2#$yvnSwsHhd) zX9tgj$ExGEm6V>T+?w54xM7t=s#CCM8KJ};)^!|Yc~ zv$nM@(?ndBHxtq6(_fh1B$Sb}g(_zBV{xvXC2UO*xAoUeL4>?-asUlAi+#$=%j*fD zSKBssrP9v=4FFZKChk|tuA_g-HM>!FuF#t#j%I&6#R^r51sm)yEPU!~*JbzR?H*!o zsK{;PpOCla<-P9rG`{kh?kCp1y3>}HJ5O2QP5Ltd{FeC_re+spf;RzY2De*03YcGR zP3}yh{~*{w-P6;9s)%n=wk!jpZl3$A+XjJ@U>Z9g;pZeVk46uz+=59k7NlpqvMN{s z1&Cf!lFroB)H_p+xsI+j+^T$4fA|rleEdTa*{-uutm3+|h8Djh`Wrh0GQMB&Od>)y zhAc0^TCG*T=C48I!b!~F2=yU$z0Px61A~U!+NgwIugAv5Fj77)q+0^R(#n?v^tkH$ zLn{DMpF&e=-i(A;jA;4AKfEQ3M%jIE7 zBzuzI`O&&!?YEQtRta^^?0Vpv%08JDe3|{SVz4_DsyNeco+AB$k@2~C&RW( z*HB#JaBH?rW%i*z2dyb;H9YEZ)_2R8xHulaiZrWj&9gW67?Tt%0}B-u*phw{1D-~T z*N?Q$GR-fc^vAKQc>MSkuJf6_@FgA10FD)>FSjTb4YeuX;JGXhNdsLbH}+C@^z1re zU#;DR9~;VYzG(Y{%GojuXpfFXr)tP=d1o?E^Tb}tds;dpiZ7#tiIh~+Z;Fbzw_||0 z=`xB8nf?-e424ia3&)#XbSvb=1t?PhB{~lfAaez;d<1WacV@|-nwT3HH3z{ z^B2Ut9<;kD7jW~uHyU&_8-0=Y0!SN-Sd~^cYX7&m0AGk2;{lj)hf`5dV5b<5F!!@_ zC~|67yGIm{WboUJzPG4uY?OgYY-!b7BTJ*gc_~tL)X*olS^3^Q!rhhO;cqg5RXbeb zgoETQA0q~RU&nZo6Emtm_)OY!ge5K_Sf6=r(F3I_=(#cB>sl*~Vho!KpoNfpD;NC^`Fq z>T@Esi;y~H+y}qhJod5K82=iSo_?dmc04X{XK4g#kO&}Vytz|>zF)TPwP9sto#*aN z5Pk^=hBy597D$WVZ;PUi(RDJ^8lWhL0If2+{6d?fpa|2`B0QN)f37wDapl&nu9am2 z{bbXF=DdsAU!OL1Y3zso-gUMN-rM-zvO8AwL{2UDGj<}8!${w!b&%!Cc`az zPW1l*$xN-Snx>}ZbEh#SM)AIZpEk81{ zoGmkFkx%R)vRcFT&VODv-=i0d*b6>pAFC1`TByb^N`s*Y#)FJZqzfK#?(o>SxDdd| z_D_k}fmTRLN~&;KAvd$Je-$deh;|K1O`xt-LUv$E3|e1PUHXz;0a($IC))_hsP?Wd zW7_f(eybn$)aMU*VqYI(lmYK}0thM98>LY5{ygOC-c{acZH4W1?9IcWVj;g>W-}WX z_vAI%)VS7>5z6lPK|@df;ER9TQ&~}Ae|fmKmk?-!gyyi&&?eZ44x3ZbBV%JmKx4Fb z42&15l2@?wJ!B!PJv*`j9$!n~DnGa+|S0R?U2_@M8fW0>6hfw0Ja?_Rz2ijc4apJbp8d{cd{Ig;e&I!u3M~ zf^7k|E@#Po9Tnhv%*DxN?iP0hqLSsfa+toMTk;lRH=D=&A;(A4W~Z?8|0 zeo1uoYS#nPjrr+mw5<2>df`BRwE>|S)4~dj%;yJbP1yo zh%Pc$)UbP>Gm9!l#o9>H0OE8ak5qv=klxe0=}2%!48!1&*aS*ygKiYlo^YiPUcY4W+|iz}#8= z`L6f?;YHP!`wY9DA+P4jmP}k7#pPJGyv74j?`Gjoster;G^>_6f z2)?grM9JS!^EdW=lr4ffHCL~W7Vgswrmh#Uyk?D1-vIlzxxe2wnE8wS)FDT&@;bYTmI@2GfS}{O;&LAz4)c%(s`^N|-K3RY zL9A|(<@aos7K%G|8K3q~9Fi8(@aj>*p`lt2Rxw<2Vu&j8s``= z{E1YNXi4l3yss1WInWCrzDR+94g?UyNq<2CA5J#5X36uDm(bOnjY&GdifzCk=I|vS z0lL`S-3@s6jzl#{?Awgr%PcUwNtxNyxNo5&B|GRP;94cLv$Io)kR7^}veMbi_P=8EJOj3^?kwdFfbWmYY6%|4iRaG-k8MhHio}eJ3e%i_j$syaZ zLMRdN&NTM+h7Y=eCo%v^y9TJQffHQ(Rmlr_bpS*);LonJvf?o_Ggr8-QKzP++Mk_x zsBULv11W#)#tr}C@k@?QPDNnUVFN-1rWlkTZ1^0IO%uO5wP5Oj%9B%6oQ1H6Y@{#6 z#jM}w%O`#DGSpr{X;Rym+}|Zj(V_HKkhx(05kxwB1sITRnq4X!JJ?^taJucLj4wwK= z2~m-(!GAMq(;JFr&Q{qs(v?#fF}0Hmph3;w~RNFHoh{GLN0aem?i^nU1uhS0m%Smw`pBajf} zFg<~-yUXphXAP__yeEg`XoS(w-Od8qxDV#4& ze0)Yq1Om3PcMZ(zT|ZYp#lI@nvsPF4*k|vj8Q*yVQ3Qf%8JKb&`>SDs; zkGw11K0Y5cSm@t<6B_HuNo@_I2?b{RqAfwieU(@qOt7prw1iR|s>*Nf?CutUjt}dW zC;3)mdB&Y+nJf*%!#{JNg@uOVLHXsv^Cy)@*|T@jh_*cc6*^ssU>o*YcWj$)^dJQ- z{mnc_E#V*J+H3hzIMcLHci<4ehf&f8Wb(GtYGPX!Rz3*P(zjTbcjz%5UyXl_H2Vsh?tTx7%*tvw$J5Pa&KGu+32ne@fI|>QL8}x z3=*95m-6!AC59A#qB5jx!U@aCVFmHN*^RmjEC=WS6;aCb*|;C2uu+ndk`0nX9^jPo zu=)xJ4npffo=?#sn25NI+lguirbiSJx><&`$Ra zyU3GwN;iNd#0Hak6X<xX)V#1=c0FDIn;WeKG;<}S1$@bP?d!RmC%>{kQIbRe+`Vk`(l7p-f;bP zvXBD-X{O*UjL~Zg*oTSc38RQJ}~98Cwe4h=YgM1k5Z5_R0V>iD+ov0K0Fg z_pWn}Or&*fw3MVvVrZd2q9q7}p~zR0L4##04DXy*gyv;i@~4k$bHKtMoNV|0MG1Es zD_7|K-#RMYxZIT>OaegV1x=t%9FUE`Kivge946)%*6=QF24+kGV0EkMI zL9Tm&frZ5@5Q_~#m-fy~1zU39IUGpf;^LYTjT#0$1cY`hpnVjY0`U)3Gi5H}<4qh$LaQl~OaB)$Da)k9d7VJK zkVC3@KDUh0p}$|b5)M66rLe1$ldQFMuD%z}&dv^E2hgtdrsCk>7#(g=ORz%JPB_Ui z%WekeTTkHNi}|k#?q`t?NM)XC5TcfU+|xo(DGg>R379r%#_y{<~bV zvarg)G*Mwc{bDMp+7HkR{E9x`n_NJ1$`GZ@s*`|G51LLtoL}J>$o;|_P22Qyg{d~q zNte_s*ldo8``bA~Yfsq6nG^Qkj>6#Y7ey8%*R>>31sNRaZxTzO#5Dm@=?7zV?O;FT zNLdw?OHd+Vk&uv}&i5)_WeE)*z@~SYsz`KIWMJd@8Ms%R0!r&sLvJ0oH(Fl@T$FiT9rcf&@UcQM14C!I&pDw__nij-de@1y3^CHIx=Lg91px$6)bSS$jQqaz}X2P)aPyzVqjo^m1Gu< zISF|m6uO2x-3@!VN+J;$jRXa9JH81_Y$2ub)z;_;k>U*%%lkAnb!fLK-2; zb&$GhFAruCB3c@Zm6aaJjM7WNh;PP=W96I>-(Er=07Gua-Gkl{6B9p&gCEhcW!L^H zHrc23O=Dw_z89(GTP&?l)(AvS7Kp@r&Khg4Gq-np9pmm++0PFcRlE^H3+GII`#!SU zP2>e*gc6tCgxKH7k^$*a?mg7XP$pv$(!OqQS4xodqeZ+C-l5DulXB=(!D&X+#fulg z9-ii^O-}Mz4DXy&;it5I#?1Mk81xiKx-Q|afCMzHyAYw7u z-%kwWb_+mQVlWAr_PTbrQ#@)@=ZH3f;H_flur#$5bl@z*M=iS1cA*Y0SS%_q_i9GZ zs9(gBV4LH}DZWJES z9!zRmV4<1;D-*H}Xu%XXcL4ha5(56!t5>Ji*9qL*_60c_)4s`eiO zdXd|PE}|?C7w8qJRYP&p(A0zh?j%KEojXqwO_jb>^4+ zAAP%TFpK`kdk7~{^l^$$d=(gKOz9hE4EggJYnv-87=t0WH$AYpPu_oZy91IQlA3`I z#F4#R8Yhr*tyCS{OByU?f*52}1GymGX?MBeeB=l$V~Mi%Qmg2AlA$IIKig?{!H@>E zGooCB+W?g7&EMZhz}iR;Tqztz>>C~qg76B-S>M_kp|^qmq6RatJS>zBoeL@q5nPGe zoh_9Op3kcW+639zk#$u8wFcmkAmG`5|Neaq?gV@#Bnt3Fya))u94)iK1Il^?qzdqT z7qsLp7Lhh_qbv7_b{C;P0|F7u4zP?bR=91@BDcxBm&^e701SISO9QzFaGlhA=Fi}4 zA0adaDU{$u!rs%95Yl%bqv@Zr>VCY>^=3a?vp^5!{^vI$rX%D^dV2abad8@`-A7kI zxM>7Z4n%O|hR{R6%eYonRwd^B=T7BLr$~AYm@yRItqp<3CaY9zF>gLBO(XB^E zm>s%JRZJasIy*XEwKGBjIhi~^rK_&4E-B!* zvu>}Z84bzZgZegOCgCl$(yzLji}dN2{q5iBlJq;|35h&oXDR@28W)Z3>?BxR-#Y}1lA2=zU192`DEa= z!TphbxBi`WGMmHh9MqBpqxm?RmuI| zc6?+_K!zYa`#mA%0{{X`cz`^g+cyKG0j%>0M)~Qpe8<1N&+ZUual?A*MVJ9v-SjgJ zmKKCYvatAuECHGnD24vs$kFhi2Tttnc%bdkWuVvGfPuJys&y#H@Vi|Nn8i3>3;M&9Kr$^{IXn!`tG2bK=3Y8?rS>N$S5N^Q*npz;F z$~ZSwC3aa&vA?}E$%>L%zgb(1LV44}fOv z2R@{35HpC95PAl=8&ylJ)EU37IxyaNJ_^ZFre%@CVmMmh^?h7nPmh!l?sAZNk-0E2 zKF9ogsKtFcP-?b#dgvgg(mTtJ-IxTnAr$j};{& zBjX7mC@^+;XUgDA$I5}B|4{V>(oi|R_ZIcVI#RY*QRBZ9#8rBmexK_$g979{K--@P z{-x^z0^~s1&mzNsx=;A8)-X|HeBgb4D-?CzOe%FMpFNgY!zD<6X%9;yVOR>G0^QcH zk}dcXu`f&iYcbBST|0KZ9q!q%7AZcEBb$oa8AEFoN2TRIOE(_b2Aoy|1sK*v5_)?F zhlb}E*!RnAb!ye={c+mQ;RyHn`P#V0<2Q%rlAC6s0(s^|{>HClU&+M1ru=&6hjC0h z&zG*p5_&7ITSa22n%X13@hDtriiz~er4M0ZkG#zORN>~$jJ5rsl?1&^)f{Jnr0^Ay z;fnQLm&t`+tt-BDlLdk#&VV*j1J(Ahn1X%cKU0WfgbX~7Oel|5Dg+Az-Vkda<;dwOvxo+rMUzwy-Lrk&$|DNj?WDZ4UIyl z1y!iQB>VdNBV2`&N#T$v(ofBNZSdfHENP-oB_#c4cEY=$D31WW1q2hRCr_S?PJ8bF z#~bnXEeaqv5PC{T6Q4O;`a3d;Y|z9|3eHwQ%o#KtikYDIBSk$h95>eP2QOZ4Apbku z;UMmDgP(+mh^XFj247BHodj_Qy1NU(=vdyjmS%*NaU_SBet{S{fC37bA*MBZ2_+~2 z5$@>HrAz5FxWqpG|LT-s4F{Dy+|DCB+tnEK@ccA{FhsZ@pCqe21Fc{opBl-&w(b0-;Wal|G4Z_2Q0kpHOa|LIO}uo4#6-xk7) zk!b&nIdsz)^>=aqKf81}9hwJfU;DRj(odem!e)V`YR;rAiefl&2D<$^9G#gFf%YTN z8IJ4M!*?R|m0AsBiI+o70;{Req>~)6Vx!(hM+X7XBCV-O;p^+`A~6pvhr`B%IDAXO z6-b--)SNy-)ipImP>!$+BkpXdPTx@WA4Am@hOii*I)e3^iJcu2g*esV*fVfxw7GeC zSNLz;?&Yt!0-9ZdxEDFdD!`dUAT2%m4daoju)WxS9azTi72{w9;&xlt2HF;B+J^T8 z9PkETE*eT7p(b-jEs!?YHBjzkx$9Y3|i<-My#@%dwYQe1)M-U`h$oipseyxd>EgenfW3dM39F~ z`!PR%Lcc8vlV2wusoZ8}^o@=EVblbCpUKH33%NQ#s~4uHpM$|#!!g(H=IC8L<6s3dS>P)4JT;J7F>iPy7F=ztm4n5o`E^K zvcpG5M+dg{Ce-^O?ByjT{!-UItE&;w(S?KNcNsR*v#>A%q;vyoF(T@@R5R#OUn81AzK5e^9m-rvQCBu7KSN=a%PJ~jLlCofa(Wk&Tenj4rKm{Szt|547l|K)uDfBcFZVy2>%gd{et9HvwsAsy)8lvGx9B1_3inp!EM z6k29W_=rSNDjJG(l9FS&T6MLAu85{dnvgbq@2~Cq{VTqH*v+V1*Y$qAp3legad9`o%*KIgscKX@<}_38wM?fZ3gyLkQN>*Gi)+rF&4!vUYcCJzk_4ReYB z@#pjT`JbujLk3QV`?Y=${{8nB+RC0tKK0|b;>{6nw5LbS&E45KmeD0Os{bP`9ABA& z(0^doC(B@-@JDZKk1--2?^F6?j;fN?d`tne0-d)M6F*xMYwipYk6(hH&IP zZ6!wYoH4{74WjYt*6Hk|@bd8)#ObW4sPLq2iP#)`{FEm5_al1+YiJhsOYLjK(Jso2 z4g*&I$G&gVdyF?VoAVF5mqr>mJIv>_b81MFeGUtj05>h@E?g*!yuEdh7zZHD7Jc87 zb;IA!MlgSn&%*gz6#2I%+Y5G5#t=7VY-%Wsf5I& zwC%&21(A{Sgm8}^Viaelr%)X6kJg8}jtw3%WGz2MyraVJUJk=0Eb=8RbBTuPf`pWo zMn!4OkJREUQy*^dc?GssC~^E+Fd8J~UPw)q07=>UH89t`cn_z9NlR1!`uJ_(B#Q`6#XOo#IV(b9D3(tMsO|!ni%zfY)ZC#rZQ7?~e5`og zEI^3o+>FE`u@I16TU*=m^yx0D{W!XOR?p0oqeoLuo!Ujmu+gvH(%EbZ7CZs=$0mN+ zHw@y1d{=6EdJHu}2TG0rzd8IW_rh!K+MU1?uWQkRMr?j*!A=;!?KO@+_;4qexwW+a zqb1)@5qEo8a_iQuz|EU2Xlv~s*OW$%BLrk)Z$C=SDR|44(f+mt1qDMS@s5vDOoA-l zd}CXzysK~VQ4^K!?xcQMK8vY@eFB>tQ4E^4A_SZekhrPFu3ocR0_^1!$NMa;2n`L@ zrsEM{wBq;!MY_njdm`~Btsf!^p8(sWnjGvmT9>ymp6sNy`Swzlf_l4sw!C^YE_u4g zLSiG_iT#HU$8%vscVTS(DfBKEd@aADBUjRsq%iHm9l_`Un_&|CZ1E+_!CZjzyx23D znO^KN5GXS+a0aJ9Wz;BL8y|*@Js=*NAHQ`v% z=36MlgzJ7Zi7hQb=<`GkrJe|sZ(^dsqYw%&mI>j^k=j?p7UqkKjP)O$QpsMcne|FI>0|+Bokon??-~2bY9d<-Req1PJC%y1b|aFaL)vJfHA!3ZEeMfOwFl z9G46>l56nmLGtoJ=#!b(I>)K}sK1sWC!w=0)A9Ywg2xr}xW`@H-4+oMX0(YsfWYA6 z!;AAv`agz0efF%C(J%(xn=Yy6D#MK?Ml@30AxGSEXvK$ScntuN$lKbSHWZVP*@N=DJj0?ylCxfPf%^ zHecvDuQ7fb)!#Q^Jgy8Teu4jNY;4MYoV4it_dS05v`kfTs{^nrc)*o!S=FRA;x{1G zbx}*Ie`Ux!I&YgM4^Xw{Dv3C{`PW+#!7YwwXLd?ZJ@#OPZ)M7v!Reao0vj(1E#{^~ zbOXPuhh@q6`LkJy^(pX9`W62H7#TL2*45PsISVi${mQ_=Kq&OSvfObLJ3YU=Z*4ea zY8~mdZ1WIdSy_8%V%Klp915$!+^3vF%1S|id{L7bZqJDV zGG$3KmW;*KaeMK&;W}yW;+eRO3bBt7srUE;rlh}&F~c!qvGBl(9?9^(RPQxw{RW24 znGopo;@2aSHclQr#lZrwU=r4?3u=_Nw}0U}o?DBLuSJ-g2;l3EceJz|2+tsqtiG~2 zy?Ulo)va5Z?tMyEwOx#N{}TA|Mfc2(7cab-25#2WRAoAzwz_lNEG!!1hky&{M++7% z94y|s>jYKRXx@S)K$IJ&T4T)qL&nNewdlFQ!cE6Gl(1smmsIi0%uF&&Io)%dXo=xL z4#zO+2~iOrp_b`ptBnt7d9VNK4HhE@-iO`3VKz2HC7u-J8HR>GhcTf)v zI0zRWAEzixe3hA*8LdFk$H#{=CX{&Z$4geP)`E`lTEE`;_d$+JaLmly)O`6rFCC?f zGFcI?wIepYs2!D&&;P}87>(Ws-5JYnoJM8siEPJ;_}Kegvi!;ASB0z+noAkeGbp%p zNn}wK%v-l+@JQjbvR5p|93ni;VrxOelaprjZX9f_@cbc~8IW%$yhVA)<&yzm?rZ!8 zWD@w@cd?0yBSnt{Z?(|vBA%D83}HBl;R&UJ54>}7)Woj9)|El^V+?(jSx&kGV?`)SYT}X*l9I#_m%|P3#2B~xb zU5+&_)^}nITH3+~4!wFYQDdfs;k?oa!Y^j1yj+=Yx`{lt_pZF;016)M~R!=ViF6g;=Fa5)-UvxSwp}3q!BqrNEj0=IlwNc5>FHDU5HN@#*W0YJuI_pKOjq5b6ED*XXuHYuq^Q z)sE7SABN)zkH#8Eu;mAW8%};I9iX}GN8D~)zkXf8JlidJZS$A5D9jSdAw2TRIaS{Y zHP_KmN(uI*Q6D@DCtY3rDTArWwhxB2zy2!dJQ%<7`}dUzNnXQ9B6Lii9ooJl+@PR+W%%Y^zs~aLz&5w4J6m_E=O0^k#4z((?g>3^ zVAcMKmir-0m_wYd=0H(_e7phz4BoafcPYBMx+1?EZ8Th^ru1r=6I0C~)_Gw-5fLQN z&vGZHB$GvjU4wS)-n}R(W&}A2>zI<;bHd;1gM@ao{u0D_wdoMg$=cv~xz$5{W>ZrW zRGZ%$xt;{JxfxHGipW%e|h-InPIh_RE~r%a5p#o($0|wEe#`H;FJC ztiT~`XINDR0{$a<+mh3IKzlQ0&9Yp#PB-$y@1N&wBb$LS^AEe=!Lr@FCjd`gEiKxv^Z(^V%2;UwISNWVmmeN(*;E{kgWa$NCJ+y-(-C)lV`FuOlnUmT6HFki zOpd=)tv7Y*Kd%l}AM#aMQ&TTLie4e+NJ@g!*xe8Y?9bUJ0wP#rL839m#l;ncLqRpW zi;L%qMJo)FuxfjA$PjE7fBE`0ONFDaTrp*CkWzJU1{m_*KYZC)4(FQ zdoSEKhm8CWHvYl~p10v7u8urbSbxIiwu|5v1s=r>(hdU1z3=NgNox%4?Vdc%qhucg zi+A_aTS-}NvLvEcV%mdw@aE?=vI6Gr-Mhjjzkk27uC8vJUSRU^<5%-By23k5w!55? zl5$q-fhn9SrtwzLgOC@QUq295)i6%b0X zBCGKy7CfR&k4qAu)fRw;Q4J2PT5e}+t3HWc>x?(z8(ILDH{AWN@yH<~$B$m}z$GtsK^U`zm`Ii$HQ9kJTObsHKM6+f z;xpCx{PQ80r;^+ceKB?FHIfaW#B1EunVf4H=SljyuQY8Cs7z(dn5i#D+-Hcko31Vt zAxIABF;DU*?Xq(dnEm%;XX{JN7_9mTSSL5j4DPY{cjb-Uj6s;?**;@8vp9VoJo35SyH=j$ji6DUfG+>~STiFA(mC z044Iv08(-$Wcmg5hUD~wXPbUM%^7|z^N5m@01*i#h^@hdnFVzS zA&sA1fmdnuWZxbC?C{C)=bh@v2*4?d%}??tPj)_ix=xHNbk##&`Pe1(B_FRTikLpk z_KxPs@bEAIpEdK47(bZxTMz`q0O{$e&7%?zj|q9tJ!|)4%ty>5KXAv(Xr45zDn7{; zemvINXaJe2M5Olnq8< zZ^QxBcSekDpc2A6!*E+wR8@)30L@@G9~Y0AH#O4-3Q5NaGfZF%VJ2LNQSu zv26(gl8;=Lddsvce`qu6D=Uz`5~&axgNQcpS>I=`3Q~uI;i7PBVW}k*g4n!Mn2%(7cL;0Ktfg=VX8=JVsi@R>$zRk^A z1poBt_g7vzI$!I$G$8iH$7$YTxlk86Q+r28sce83R}fB4^a9u&=K!DfCQ=+~Vx0+l zK?ZZfEjDkwTc4#SuxLlCb3({D-Km5|Xjtsk_44*!(Q!hd?QElcVfB#)V*v#O z{lSC-Ck^KvaxC%{IzuQ!9`l#AV^n?HU!0TW%a@;VZ0iCrx56Zgk)|Vqq{<7$?9@0_=_1P&Lce`;!c%>#PTIm}ZEZ2oIK65VAv zP+16M(}aqe(9UR$JKGY#pQV4Bo%#IDl%*FITGhqj3~Rx73oBlisiC1#zZBw+KhO_a zKajKWb(Kz#_-cNAwf&y)zrW+R|LV^Fh^yiyiC?+{{}sl0A-5#|YPbC9|AQ}mAN9%0 XMGtD%o&JNRgc4iprB=BXp3(mUYY6U3 literal 25095 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 WLs}w+-;w{uprd(=&N^)M%YOkn+C8=a diff --git a/assets/logo.png b/assets/logo.png old mode 100644 new mode 100755 index 9ddd2b7650eec2eeb25e7ff3deb52ebcf33cdb21..faca564d36f80fe3556e4892333a6cccd614579d GIT binary patch literal 12665 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 Q)PHJ_lTwr{64&$lFAoglPXGV_ literal 12382 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 \ No newline at end of file + \ No newline at end of file diff --git a/doxygen/logo.png b/doxygen/logo.png old mode 100644 new mode 100755 index 2fb5219b67ca04427a34a7b627f78723f1fee1b1..a681d3266e32c11ba3342a0282fe3315f1502f8c GIT binary patch delta 1527 zcmX>nG*4)PiWFmUkh>GZx^prw85kH?(j9#r85lP9bN@+Xov0}8#b8t78d2h$pPQSS zSHe(HWR+s&;^<}>78z7(l4oIMXr_~8Wo~9Z&A0?a5t?CZ-?@pvqk< zN<35S%q)xzEe*}gbyH1@(sWILfu);dnq&?n43km}4a^PFOw%TRU=*Fq#AH0#h)K^5 z;zsNqf!haBgvDK0y)u97jdYq}2O%o;v!WD?{=0 z%in#iva4<0BqH8o9`II(f%%6iR=*+*~OkWf-qUdVau>=B7O z`%({ehtHo_qbx98e`oTO$6R$c%8vRq96IDwQeMt|no;K>=c&`DHOzw@k z`PTzQ+!`AjL&EFB-JjiHShW88iBAut{>tok)}KG?<;};h-B&GFo%-$Dw~Ac%IWM=J zId|^ZmoFya3s$b=%*)G*nY(nU>XD;IJ6AYwd4KTFADcB{+P{AP{<-Laq=ZDn#f&50 zzM1XWyZ7R)Tc_&gzTYNWQN2?^@s|91`!yWz?W+D9JJzmSb6*3scv zy?XVFH*Z`@OHIYZ#4OzGH|<(*?3kO6kB@?iO3UO6SFf_JO_EuBe(UYG8X6i6N0S_j zi;aJmeo51;vS@o6zd!K%hm1pCwte{WMdaE^3td0!wi?;j%4TNMYG=-zsiCXu>g>#% zUy+^NUG2U;CooWO)22;3)^~MxPn=Xgsp;OmxSsz0 z<-qy#{nyQ;cz4u4*Sd4pr{dEe;op20u7CRQL0}s5H~;6B54TUfW`9@t_3jv>nLO^l z-XzTMQInFD6&02#-gji;+!yD~t3pyO!)9D#yK?WIUXuUwJ9Z0sczGADUCV21Ym!#flXUE-oz{7P4QTFUFt3foY%fgSgm)sl`W delta 1671 zcmZ`(eKgZ+9B0rk=wl1X;S9xT8gXgO5J<^sOOL8Ip61e-p=`)=P5E!7-X*zd%+=4 zj#z5y>cL}&N5;^(Km?ru#uBW@>t)seNF!M9at(A0WP8)2K|g*Royy;`Ba$BziKSV4 z5MkolwPKZz#7P&B?1Q+P;JvuqI4}a|MdJ`*007|QXi+#S{QwarxeGx_Mj=j{zClPl zu0M^4iNr*?W3Z8Ex-$)fcA+^rqOmSfj_4?7=cq`Rh;XcS!#jLcU7)}ubUjx|p&p8W zcla#N1Q)En3}3vozTYSdK^A~MbWUU($mW9kV~H@B#8KBmvP;*&2v3W|aX~JV{$FA* zCRdyIimt^rEeB-80-W$z4xk0a(E&8z^c~+XjL*LR6Z@g7Kh$1w7`hhzL%@g@V7kao z@EyRy)pj2;5r%i*;dm@Ii_Q(#4*%9ikJWY-r!D8Y=MlJ$4pivxS#*^IoiObibYi0bm8+vl<} zSh(u**NvM-%`NTkn;a?olv_EOFOwqU3u=pBl3V*4!rmWH5Qcj(vX1eY`r-bnW~zPt zC#6t8g%yOBG(HIW(V-b_L?V$@{+jlK{UJ{@+c}JPu5Zl==lwr`x{Us_g8jg&>7gMD zC5e4gH8|)w74L(3SDVR9m4vVVBXm5F9- zY;C=QgN+dg#GqPz{Mwv@K+&Jn3B z8JRw^VS+++*DKp$=SH=u4rxaRr7o=rTmmB%#4@9!Jp%$@IZcCuz|9c!b}H5QcYsVL z^Y9)54{4e>FE1lE*Qno$KtNViRf$BR!N+-ddBVy{hvru*)gSHcD{k!{NPYK^!$T8S z&fHBfl_lq=PHugXa`f5cSpG-9j7fJPMt&wOP45}mB*erHg{ln;4SjSaE9)n7lcyJ*74j!uC5M{Y?+MuW z0(tB4nXuNjwpX_kt@Q==ziv$5HoxK^Wcc;#`z!`yc*Kf(=@DhVrluz1(4jNZ`izWa zX5-`IZ9P3kZfq zo_XSgrS(y}A-jUTp-z0v*&C}&#}tC#zpoMD4s*Cd+s$HESn0&G=ZAYBiV&!u%DT%# z%v*)$?Mr!1N$WW4E%bfXHQSHcxs{|#?wFpPoy|+C_`uW Date: Thu, 22 Feb 2024 18:43:02 +0530 Subject: [PATCH 12/19] Add initial support for V8 backend on macOS (#41) Fixes: https://github.com/crossnx/includejs/issues/11 Screenshot 2024-02-22 at 17 55 23 Signed-off-by: Darshan Sen --- .github/workflows/ci.yml | 7 ++ Brewfile | 1 + Makefile | 3 +- cmake/FindV8.cmake | 22 +++++++ src/engine/CMakeLists.txt | 13 ++++ src/engine/common/engine.cc | 4 ++ src/engine/common/engine_context.cc | 4 ++ src/engine/include/includejs/engine.h | 3 + src/engine/v8/engine.cc | 95 +++++++++++++++++++++++++++ test/engine/CMakeLists.txt | 5 ++ test/packaging/find_package/hello.cc | 3 + 11 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 cmake/FindV8.cmake create mode 100644 src/engine/v8/engine.cc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4999d3e9..2db24a5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,13 @@ jobs: cxx: clang++ type: shared backend: JavaScriptCore + # TODO(RaisinTen): Support other OSs and static configuration for + # the V8 backend. + - os: macos-latest + cc: clang + cxx: clang++ + type: shared + backend: V8 - os: ubuntu-latest cc: clang cxx: clang++ diff --git a/Brewfile b/Brewfile index 97725f39..92ae3cd0 100644 --- a/Brewfile +++ b/Brewfile @@ -1,3 +1,4 @@ brew "cmake" brew "clang-format" brew "doxygen" +brew "v8" diff --git a/Makefile b/Makefile index 2fc14985..27ee24da 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ CTEST = ctest # Options PRESET = Debug SHARED = OFF +BACKEND = JavaScriptCore all: configure compile test @@ -12,7 +13,7 @@ configure: .always $(CMAKE) -S . -B ./build \ -DCMAKE_BUILD_TYPE:STRING=$(PRESET) \ -DCMAKE_COMPILE_WARNING_AS_ERROR:BOOL=ON \ - -DINCLUDEJS_BACKEND:STRING=JavaScriptCore \ + -DINCLUDEJS_BACKEND:STRING=$(BACKEND) \ -DINCLUDEJS_ENGINE:BOOL=ON \ -DINCLUDEJS_TESTS:BOOL=ON \ -DINCLUDEJS_DOCS:BOOL=ON \ diff --git a/cmake/FindV8.cmake b/cmake/FindV8.cmake new file mode 100644 index 00000000..302353b9 --- /dev/null +++ b/cmake/FindV8.cmake @@ -0,0 +1,22 @@ +if(NOT V8_FOUND) + if(APPLE) + add_library(v8 INTERFACE IMPORTED) + # Since the "includejs" library is compiled with the `-isysroot` flag of + # Clang, it is unable to find the V8 library and headers which have been + # downloaded from Homebrew. + # Refs: https://github.com/Homebrew/homebrew-core/issues/45061#issuecomment-541420664 + set(V8_VERSION "12.1.285.24") + target_include_directories(v8 + INTERFACE "/usr/local/Cellar/v8/${V8_VERSION}/include") + target_link_directories(v8 + INTERFACE "/usr/local/Cellar/v8/${V8_VERSION}/lib") + target_link_libraries(v8 INTERFACE "-lv8") + target_link_libraries(v8 INTERFACE "-lv8_libplatform") + target_compile_definitions(v8 + INTERFACE V8_COMPRESS_POINTERS) + target_compile_definitions(v8 + INTERFACE V8_ENABLE_SANDBOX) + add_library(V8::V8 ALIAS v8) + set(V8_FOUND ON) + endif() +endif() diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 5c66d03e..1d4f5fd9 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -8,6 +8,8 @@ if(INCLUDEJS_BACKEND STREQUAL "JavaScriptCore") list(APPEND INCLUDEJS_ENGINE_SOURCES javascript_core/engine_context.cc) list(APPEND INCLUDEJS_ENGINE_SOURCES javascript_core/engine_promise.cc) list(APPEND INCLUDEJS_ENGINE_SOURCES javascript_core/engine_value.cc) +elseif(INCLUDEJS_BACKEND STREQUAL "V8") + list(APPEND INCLUDEJS_ENGINE_SOURCES v8/engine.cc) else() message(FATAL_ERROR "Unknown IncludeJS backend: ${INCLUDEJS_BACKEND}") endif() @@ -24,6 +26,11 @@ if(INCLUDEJS_INSTALL) "${PROJECT_SOURCE_DIR}/cmake/FindJavaScriptCore.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/includejs" COMPONENT includejs_dev) + elseif(INCLUDEJS_BACKEND STREQUAL "V8") + install(FILES + "${PROJECT_SOURCE_DIR}/cmake/FindV8.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/includejs" + COMPONENT includejs_dev) endif() endif() @@ -35,6 +42,12 @@ if(INCLUDEJS_BACKEND STREQUAL "JavaScriptCore") PRIVATE JavaScriptCore::JavaScriptCore) target_compile_definitions(includejs_engine PUBLIC SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) +elseif(INCLUDEJS_BACKEND STREQUAL "V8") + find_package(V8 REQUIRED) + target_link_libraries(includejs_engine + PRIVATE V8::V8) + target_compile_definitions(includejs_engine + PUBLIC SOURCEMETA_INCLUDEJS_ENGINE_V8) else() message(FATAL_ERROR "Unknown IncludeJS backend: ${INCLUDEJS_BACKEND}") endif() diff --git a/src/engine/common/engine.cc b/src/engine/common/engine.cc index 903fd6a4..aaf6bc1e 100644 --- a/src/engine/common/engine.cc +++ b/src/engine/common/engine.cc @@ -8,6 +8,8 @@ #include // std::move #include // std::vector +#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) + namespace sourcemeta { namespace includejs { @@ -85,3 +87,5 @@ auto Engine::on_error(const Value &exception) -> void { } // namespace includejs } // namespace sourcemeta + +#endif diff --git a/src/engine/common/engine_context.cc b/src/engine/common/engine_context.cc index 6f978015..f6d0cc6d 100644 --- a/src/engine/common/engine_context.cc +++ b/src/engine/common/engine_context.cc @@ -1,5 +1,7 @@ #include +#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) + namespace sourcemeta { namespace includejs { @@ -14,3 +16,5 @@ auto Context::from(const std::string &value) const -> Value { } // namespace includejs } // namespace sourcemeta + +#endif diff --git a/src/engine/include/includejs/engine.h b/src/engine/include/includejs/engine.h index 802f0503..fc789233 100644 --- a/src/engine/include/includejs/engine.h +++ b/src/engine/include/includejs/engine.h @@ -35,8 +35,11 @@ class INCLUDEJS_ENGINE_EXPORT Engine { auto evaluate(std::ifstream &stream, const std::filesystem::path &path) -> Value; + // TODO(RaisinTen): Add support for bind_function() to the V8 backend. +#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) auto bind_function(std::initializer_list location, Function function) -> void; +#endif auto bind_global(std::initializer_list location, Value value) -> void; auto bind_global(std::initializer_list location, bool value) diff --git a/src/engine/v8/engine.cc b/src/engine/v8/engine.cc new file mode 100644 index 00000000..21623293 --- /dev/null +++ b/src/engine/v8/engine.cc @@ -0,0 +1,95 @@ +#include + +#include + +#include +#include + +namespace sourcemeta { +namespace includejs { + +struct Engine::Internal {}; + +Engine::Engine() : internal{std::make_unique()} { + // TODO(RaisinTen): This code is here to make it easy to verify if the V8 + // integration is working. + + // This example code has been taken from: + // https://chromium.googlesource.com/v8/v8/+/branch-heads/11.9/samples/hello-world.cc + + // Initialize V8. + std::unique_ptr platform = v8::platform::NewDefaultPlatform(); + v8::V8::InitializePlatform(platform.get()); + v8::V8::Initialize(); + + // Create a new Isolate and make it the current one. + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = + v8::ArrayBuffer::Allocator::NewDefaultAllocator(); + v8::Isolate *isolate = v8::Isolate::New(create_params); + { + v8::Isolate::Scope isolate_scope(isolate); + // Create a stack-allocated handle scope. + v8::HandleScope handle_scope(isolate); + // Create a new context. + v8::Local context = v8::Context::New(isolate); + // Enter the context for compiling and running the hello world script. + v8::Context::Scope context_scope(context); + { + // Create a string containing the JavaScript source code. + v8::Local source = + v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'"); + // Compile the source code. + v8::Local script = + v8::Script::Compile(context, source).ToLocalChecked(); + // Run the script to get the result. + v8::Local result = script->Run(context).ToLocalChecked(); + // Convert the result to an UTF8 string and print it. + v8::String::Utf8Value utf8(isolate, result); + printf("%s\n", *utf8); + } + { + // Use the JavaScript API to generate a WebAssembly module. + // + // |bytes| contains the binary format for the following module: + // + // (func (export "add") (param i32 i32) (result i32) + // get_local 0 + // get_local 1 + // i32.add) + // + const char csource[] = R"( + let bytes = new Uint8Array([ + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, + 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, + 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01, + 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b + ]); + let module = new WebAssembly.Module(bytes); + let instance = new WebAssembly.Instance(module); + instance.exports.add(3, 4); + )"; + // Create a string containing the JavaScript source code. + v8::Local source = + v8::String::NewFromUtf8Literal(isolate, csource); + // Compile the source code. + v8::Local script = + v8::Script::Compile(context, source).ToLocalChecked(); + // Run the script to get the result. + v8::Local result = script->Run(context).ToLocalChecked(); + // Convert the result to a uint32 and print it. + uint32_t number = result->Uint32Value(context).ToChecked(); + printf("3 + 4 = %u\n", number); + } + } + // Dispose the isolate and tear down V8. + isolate->Dispose(); + v8::V8::Dispose(); + v8::V8::DisposePlatform(); + delete create_params.array_buffer_allocator; +} + +Engine::~Engine() {} + +} // namespace includejs +} // namespace sourcemeta diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index e40c9bd1..75f1ee69 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -1,3 +1,8 @@ +if(INCLUDEJS_BACKEND STREQUAL "V8") + # TODO(RaisinTen): Start testing the V8 backend. + return() +endif() + add_executable(includejs_engine_unit engine_binding_test.cc engine_evaluate_test.cc diff --git a/test/packaging/find_package/hello.cc b/test/packaging/find_package/hello.cc index 69488c9e..cd221632 100644 --- a/test/packaging/find_package/hello.cc +++ b/test/packaging/find_package/hello.cc @@ -6,8 +6,11 @@ auto main() -> int { sourcemeta::includejs::Engine engine; + // TODO(RaisinTen): Remove this once V8 supports this. +#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) sourcemeta::includejs::Value result{engine.evaluate("1 + 3", "index.js")}; assert(result.is_number()); std::cout << result.to_number() << "\n"; +#endif return EXIT_SUCCESS; } From b1f75fdfe428937fcd097d4f57f8b0919b7cb4eb Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Thu, 22 Feb 2024 20:03:28 +0100 Subject: [PATCH 13/19] feat(value): add to_function (#44) Signed-off-by: Tony Gorez --- src/engine/include/includejs/engine_value.h | 1 + src/engine/javascript_core/engine_value.cc | 34 +++++++++++++++++++++ test/engine/engine_value_function_test.cc | 27 ++++++++-------- test/engine/engine_value_object_test.cc | 11 +++++++ 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index 01cf0d68..4fd3ca68 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -41,6 +41,7 @@ class INCLUDEJS_ENGINE_EXPORT Value { auto to_number() const -> double; auto to_string() const -> std::string; auto to_boolean() const -> bool; + auto to_function() const -> Function; auto at(const std::string &property) const -> std::optional; auto at(const unsigned int &position) const -> std::optional; auto set(const std::string &property, Value value) -> void; diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index caf2b227..f70009a7 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -161,6 +161,31 @@ auto Value::to_boolean() const -> bool { return JSValueToBoolean(this->internal->context, this->internal->value); } +auto Value::to_function() const -> Function { + assert(is_function()); + + return [context = this->internal->context, + value = this->internal->value](std::vector args) { + JSValueRef exception = nullptr; + JSObjectRef func = JSValueToObject(context, value, &exception); + assert(!exception); + assert(func != nullptr); + + std::vector js_args; + js_args.reserve(args.size()); + for (Value &arg : args) { + js_args.push_back(static_cast(arg.native())); + } + + // Now we can call the function, get the result and return through + // the Value class. + JSValueRef result = JSObjectCallAsFunction( + context, func, nullptr, js_args.size(), js_args.data(), nullptr); + assert(result != nullptr); + return Value{context, result}; + }; +} + auto Value::at(const std::string &property) const -> std::optional { assert(is_object()); JSValueRef exception = nullptr; @@ -179,6 +204,15 @@ auto Value::at(const std::string &property) const -> std::optional { property_string, &exception); assert(!exception); JSStringRelease(property_string); + + // The function could not be called outside of this object context + // as the C++ function store is tied to the object. + // This is why we don't support function properties. + if (JSObjectIsFunction( + this->internal->context, + JSValueToObject(this->internal->context, result, &exception))) { + throw std::runtime_error{"Function properties are not supported"}; + } return std::make_optional(this->internal->context, result); } diff --git a/test/engine/engine_value_function_test.cc b/test/engine/engine_value_function_test.cc index 8726690a..6b383df9 100644 --- a/test/engine/engine_value_function_test.cc +++ b/test/engine/engine_value_function_test.cc @@ -5,16 +5,19 @@ TEST(IncludeJS_Engine, is_function) { sourcemeta::includejs::Engine engine; - auto obj = engine.context().make_object(); - obj.set( - "foo", - [](std::vector arguments) - -> sourcemeta::includejs::Value { return std::move(arguments[0]); }); - obj.set("bar", engine.context().from(42)); - - EXPECT_TRUE(obj.at("foo").has_value()); - EXPECT_TRUE(obj.at("foo").value().is_function()); - - EXPECT_TRUE(obj.at("bar").has_value()); - EXPECT_FALSE(obj.at("bar").value().is_function()); + auto result = engine.evaluate("(function a() {})", "index.js"); + + EXPECT_TRUE(result.is_function()); +} + +TEST(IncludeJS_Engine, to_function) { + sourcemeta::includejs::Engine engine; + + auto result = engine.evaluate("(function a() { return 42; })", "index.js"); + + EXPECT_TRUE(result.is_function()); + + auto value = result.to_function()({}); + EXPECT_TRUE(value.is_number()); + EXPECT_EQ(value.to_number(), 42); } diff --git a/test/engine/engine_value_object_test.cc b/test/engine/engine_value_object_test.cc index 283349fa..ebb5667f 100644 --- a/test/engine/engine_value_object_test.cc +++ b/test/engine/engine_value_object_test.cc @@ -63,3 +63,14 @@ TEST(IncludeJS_Engine, set_object_function) { EXPECT_TRUE(result2.is_string()); EXPECT_EQ(result2.to_string(), "bar"); } + +TEST(IncludeJS_Engine, at_throw_for_functions) { + sourcemeta::includejs::Engine engine; + sourcemeta::includejs::Context &context = engine.context(); + + auto obj = context.make_object(); + obj.set("woo", + [](std::vector args) + -> sourcemeta::includejs::Value { return std::move(args[0]); }); + EXPECT_THROW(obj.at("woo"), std::runtime_error); +} From a482369dfd5dbee05c7ccb659c5df57995edc8de Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Thu, 22 Feb 2024 20:09:45 +0100 Subject: [PATCH 14/19] chore: delete sourcemeta namespace (#45) Signed-off-by: Tony Gorez --- src/engine/common/engine.cc | 2 - src/engine/common/engine_context.cc | 2 - src/engine/common/engine_error.cc | 2 - src/engine/include/includejs/engine.h | 2 - src/engine/include/includejs/engine_context.h | 2 - src/engine/include/includejs/engine_error.h | 4 - .../include/includejs/engine_function.h | 11 +-- src/engine/include/includejs/engine_promise.h | 3 - src/engine/include/includejs/engine_value.h | 2 - src/engine/javascript_core/engine.cc | 2 - src/engine/javascript_core/engine_context.cc | 2 - src/engine/javascript_core/engine_promise.cc | 2 - src/engine/javascript_core/engine_value.cc | 2 - src/engine/v8/engine.cc | 2 - test/engine/engine_binding_test.cc | 75 ++++++++----------- test/engine/engine_evaluate_test.cc | 18 ++--- test/engine/engine_stacktraces_test.cc | 7 +- test/engine/engine_value_array_test.cc | 14 ++-- test/engine/engine_value_function_test.cc | 4 +- test/engine/engine_value_null_test.cc | 6 +- test/engine/engine_value_object_test.cc | 40 +++++----- test/engine/engine_value_undefined_test.cc | 6 +- test/packaging/find_package/hello.cc | 4 +- 23 files changed, 81 insertions(+), 133 deletions(-) diff --git a/src/engine/common/engine.cc b/src/engine/common/engine.cc index aaf6bc1e..b3a309ce 100644 --- a/src/engine/common/engine.cc +++ b/src/engine/common/engine.cc @@ -10,7 +10,6 @@ #if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) -namespace sourcemeta { namespace includejs { // For convenience @@ -86,6 +85,5 @@ auto Engine::on_error(const Value &exception) -> void { } } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/common/engine_context.cc b/src/engine/common/engine_context.cc index f6d0cc6d..cc59e14a 100644 --- a/src/engine/common/engine_context.cc +++ b/src/engine/common/engine_context.cc @@ -2,7 +2,6 @@ #if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) -namespace sourcemeta { namespace includejs { auto Context::from(int value) const -> Value { @@ -15,6 +14,5 @@ auto Context::from(const std::string &value) const -> Value { } } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/common/engine_error.cc b/src/engine/common/engine_error.cc index 8e7e3688..a7714423 100644 --- a/src/engine/common/engine_error.cc +++ b/src/engine/common/engine_error.cc @@ -3,7 +3,6 @@ #include // std::cbegin, std::cend #include // std::move -namespace sourcemeta { namespace includejs { Error::Error(std::string &&new_message, FrameContainer &&new_stacktrace) @@ -22,4 +21,3 @@ auto Error::end() const -> FrameContainer::const_iterator { } } // namespace includejs -} // namespace sourcemeta diff --git a/src/engine/include/includejs/engine.h b/src/engine/include/includejs/engine.h index fc789233..a86d6853 100644 --- a/src/engine/include/includejs/engine.h +++ b/src/engine/include/includejs/engine.h @@ -20,7 +20,6 @@ #include // std::string #include // std::vector -namespace sourcemeta { namespace includejs { /// @ingroup engine @@ -58,6 +57,5 @@ class INCLUDEJS_ENGINE_EXPORT Engine { }; } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/include/includejs/engine_context.h b/src/engine/include/includejs/engine_context.h index 3a6118af..01be84c7 100644 --- a/src/engine/include/includejs/engine_context.h +++ b/src/engine/include/includejs/engine_context.h @@ -9,7 +9,6 @@ #include // std::unique_ptr #include // std::string -namespace sourcemeta { namespace includejs { /// @ingroup engine @@ -39,6 +38,5 @@ class INCLUDEJS_ENGINE_EXPORT Context { }; } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/include/includejs/engine_error.h b/src/engine/include/includejs/engine_error.h index 45ccd63e..d05ce8bc 100644 --- a/src/engine/include/includejs/engine_error.h +++ b/src/engine/include/includejs/engine_error.h @@ -9,9 +9,7 @@ #include // std::string #include // std::vector -namespace sourcemeta { namespace includejs { - /// @ingroup engine struct INCLUDEJS_ENGINE_EXPORT Frame { const std::optional scope; @@ -35,8 +33,6 @@ class INCLUDEJS_ENGINE_EXPORT Error : public std::exception { const std::string message; const FrameContainer stacktrace; }; - } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/include/includejs/engine_function.h b/src/engine/include/includejs/engine_function.h index 8acb6843..0a153bc7 100644 --- a/src/engine/include/includejs/engine_function.h +++ b/src/engine/include/includejs/engine_function.h @@ -17,15 +17,13 @@ #else #if __cplusplus >= 202002L #include // std::span -#define SOURCEMETA_INCLUDEJS_ARGS std::span +#define SOURCEMETA_INCLUDEJS_ARGS std::span #else -#define SOURCEMETA_INCLUDEJS_ARGS \ - const std::vector & +#define SOURCEMETA_INCLUDEJS_ARGS const std::vector & #endif #endif #if defined(SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) -namespace sourcemeta { namespace includejs { // This is a opaque function signature that can be force-casted into // JSObjectCallAsFunctionCallback @@ -33,7 +31,6 @@ namespace includejs { using Function = const void *(*)(const void *, const void *, const void *, const size_t, const void *[], const void **); } // namespace includejs -} // namespace sourcemeta #endif #if defined(SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) @@ -41,7 +38,7 @@ using Function = const void *(*)(const void *, const void *, const void *, static const void *function(const void *context, const void *, const void *, \ const size_t argc, const void *raw_arguments[], \ const void **exception) { \ - std::vector<::sourcemeta::includejs::Value> arguments; \ + std::vector<::includejs::Value> arguments; \ arguments.reserve(argc); \ for (std::size_t index = 0; index < argc; index++) { \ arguments.emplace_back(context, raw_arguments[index]); \ @@ -49,7 +46,7 @@ using Function = const void *(*)(const void *, const void *, const void *, try { \ return call_as({context}, arguments).native(); \ } catch (const std::exception &error) { \ - const ::sourcemeta::includejs::Context ignition_context{context}; \ + const ::includejs::Context ignition_context{context}; \ *exception = ignition_context.make_error(error.what()).native(); \ return ignition_context.make_undefined().native(); \ } \ diff --git a/src/engine/include/includejs/engine_promise.h b/src/engine/include/includejs/engine_promise.h index ba78ff5e..e8261e2d 100644 --- a/src/engine/include/includejs/engine_promise.h +++ b/src/engine/include/includejs/engine_promise.h @@ -7,7 +7,6 @@ #include // std::unique_ptr -namespace sourcemeta { namespace includejs { /// @ingroup engine @@ -27,8 +26,6 @@ class INCLUDEJS_ENGINE_EXPORT Promise { std::unique_ptr internal; bool completed{false}; }; - } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index 4fd3ca68..e36165ef 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -10,7 +10,6 @@ #include // std::string #include // std::vector -namespace sourcemeta { namespace includejs { // Inspired by https://github.com/sourcemeta/jsontoolkit @@ -61,6 +60,5 @@ class INCLUDEJS_ENGINE_EXPORT Value { }; } // namespace includejs -} // namespace sourcemeta #endif diff --git a/src/engine/javascript_core/engine.cc b/src/engine/javascript_core/engine.cc index 4f90d7f3..d548b408 100644 --- a/src/engine/javascript_core/engine.cc +++ b/src/engine/javascript_core/engine.cc @@ -12,7 +12,6 @@ extern "C" { #include // std::move #include // std::vector -namespace sourcemeta { namespace includejs { struct Engine::Internal { @@ -197,4 +196,3 @@ auto Engine::bind_global(std::initializer_list location, } } // namespace includejs -} // namespace sourcemeta diff --git a/src/engine/javascript_core/engine_context.cc b/src/engine/javascript_core/engine_context.cc index e95160c9..374c3461 100644 --- a/src/engine/javascript_core/engine_context.cc +++ b/src/engine/javascript_core/engine_context.cc @@ -6,7 +6,6 @@ extern "C" { #include // assert -namespace sourcemeta { namespace includejs { struct Context::Internal { @@ -94,4 +93,3 @@ auto Context::global() const -> Value { } } // namespace includejs -} // namespace sourcemeta diff --git a/src/engine/javascript_core/engine_promise.cc b/src/engine/javascript_core/engine_promise.cc index cc2872fe..e60e4e87 100644 --- a/src/engine/javascript_core/engine_promise.cc +++ b/src/engine/javascript_core/engine_promise.cc @@ -6,7 +6,6 @@ extern "C" { #include // assert -namespace sourcemeta { namespace includejs { struct Promise::Internal { @@ -54,4 +53,3 @@ auto Promise::value() -> Value { } } // namespace includejs -} // namespace sourcemeta diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index f70009a7..7eac8567 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -10,7 +10,6 @@ extern "C" { #include // std::runtime_error #include // std::vector -namespace sourcemeta { namespace includejs { struct Value::Internal { @@ -380,4 +379,3 @@ auto Value::native() const -> const void * { } } // namespace includejs -} // namespace sourcemeta diff --git a/src/engine/v8/engine.cc b/src/engine/v8/engine.cc index 21623293..d6a2721b 100644 --- a/src/engine/v8/engine.cc +++ b/src/engine/v8/engine.cc @@ -5,7 +5,6 @@ #include #include -namespace sourcemeta { namespace includejs { struct Engine::Internal {}; @@ -92,4 +91,3 @@ Engine::Engine() : internal{std::make_unique()} { Engine::~Engine() {} } // namespace includejs -} // namespace sourcemeta diff --git a/test/engine/engine_binding_test.cc b/test/engine/engine_binding_test.cc index fa03582a..48ec13e9 100644 --- a/test/engine/engine_binding_test.cc +++ b/test/engine/engine_binding_test.cc @@ -2,25 +2,22 @@ #include -static auto is_string(const sourcemeta::includejs::Context &context, - SOURCEMETA_INCLUDEJS_ARGS arguments) - -> sourcemeta::includejs::Value { +static auto is_string(const includejs::Context &context, + SOURCEMETA_INCLUDEJS_ARGS arguments) -> includejs::Value { return context.from(!arguments.empty() && arguments.front().is_string()); } // TODO: Add overload that doesn't take arguments -static auto get_details(const sourcemeta::includejs::Context &context, - SOURCEMETA_INCLUDEJS_ARGS) - -> sourcemeta::includejs::Value { - sourcemeta::includejs::Value result{context.make_object()}; +static auto get_details(const includejs::Context &context, + SOURCEMETA_INCLUDEJS_ARGS) -> includejs::Value { + includejs::Value result{context.make_object()}; result.set("version", context.from("1.0.0")); return result; } -static auto promise_test(const sourcemeta::includejs::Context &context, - SOURCEMETA_INCLUDEJS_ARGS) - -> sourcemeta::includejs::Value { - sourcemeta::includejs::Promise promise{context.make_promise()}; +static auto promise_test(const includejs::Context &context, + SOURCEMETA_INCLUDEJS_ARGS) -> includejs::Value { + includejs::Promise promise{context.make_promise()}; promise.resolve(context.from(true)); return promise.value(); } @@ -30,106 +27,94 @@ SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(get_details); SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(promise_test); TEST(IncludeJS_Engine, bind_global_root_integer) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_global({"my_global"}, 2); - sourcemeta::includejs::Value result{engine.evaluate("my_global", "index.js")}; + includejs::Value result{engine.evaluate("my_global", "index.js")}; EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 2); } TEST(IncludeJS_Engine, bind_global_nested_integer) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_global({"foo", "bar", "baz"}, 8); - sourcemeta::includejs::Value result{ - engine.evaluate("foo.bar.baz", "index.js")}; + includejs::Value result{engine.evaluate("foo.bar.baz", "index.js")}; EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 8); } TEST(IncludeJS_Engine, bind_global_nested_boolean_true) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_global({"foo", "bar", "baz"}, true); - sourcemeta::includejs::Value result{ - engine.evaluate("foo.bar.baz", "index.js")}; + includejs::Value result{engine.evaluate("foo.bar.baz", "index.js")}; EXPECT_TRUE(result.is_boolean()); EXPECT_EQ(result.to_boolean(), true); } TEST(IncludeJS_Engine, bind_global_nested_boolean_false) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_global({"foo", "bar", "baz"}, false); - sourcemeta::includejs::Value result{ - engine.evaluate("foo.bar.baz", "index.js")}; + includejs::Value result{engine.evaluate("foo.bar.baz", "index.js")}; EXPECT_TRUE(result.is_boolean()); EXPECT_EQ(result.to_boolean(), false); } TEST(IncludeJS_Engine, bind_global_array) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_global({"my", "array"}, {engine.context().from("foo"), engine.context().from("bar"), engine.context().from("baz")}); // Length - sourcemeta::includejs::Value length{ - engine.evaluate("my.array.length", "index.js")}; + includejs::Value length{engine.evaluate("my.array.length", "index.js")}; EXPECT_TRUE(length.is_number()); EXPECT_EQ(length.to_number(), 3); // Value at index 0 - sourcemeta::includejs::Value result1{ - engine.evaluate("my.array[0]", "index.js")}; + includejs::Value result1{engine.evaluate("my.array[0]", "index.js")}; EXPECT_TRUE(result1.is_string()); EXPECT_EQ(result1.to_string(), "foo"); // Value at index 1 - sourcemeta::includejs::Value result2{ - engine.evaluate("my.array[1]", "index.js")}; + includejs::Value result2{engine.evaluate("my.array[1]", "index.js")}; EXPECT_TRUE(result2.is_string()); EXPECT_EQ(result2.to_string(), "bar"); // Value at index 2 - sourcemeta::includejs::Value result3{ - engine.evaluate("my.array[2]", "index.js")}; + includejs::Value result3{engine.evaluate("my.array[2]", "index.js")}; EXPECT_TRUE(result3.is_string()); EXPECT_EQ(result3.to_string(), "baz"); } TEST(IncludeJS_Engine, bind_function_return_boolean_false) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_function({"isString"}, &is_string); - sourcemeta::includejs::Value result{ - engine.evaluate("isString(1)", "index.js")}; + includejs::Value result{engine.evaluate("isString(1)", "index.js")}; EXPECT_TRUE(result.is_boolean()); EXPECT_EQ(result.to_boolean(), false); } TEST(IncludeJS_Engine, bind_function_return_boolean_true) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_function({"isString"}, &is_string); - sourcemeta::includejs::Value result{ - engine.evaluate("isString('foo')", "index.js")}; + includejs::Value result{engine.evaluate("isString('foo')", "index.js")}; EXPECT_TRUE(result.is_boolean()); EXPECT_EQ(result.to_boolean(), true); } TEST(IncludeJS_Engine, bind_function_details_object) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_function({"getDetails"}, &get_details); - sourcemeta::includejs::Value result{ - engine.evaluate("getDetails()", "index.js")}; + includejs::Value result{engine.evaluate("getDetails()", "index.js")}; EXPECT_TRUE(result.is_object()); - const std::optional version{ - result.at("version")}; + const std::optional version{result.at("version")}; EXPECT_TRUE(version.has_value()); EXPECT_TRUE(version->is_string()); EXPECT_EQ(version->to_string(), "1.0.0"); } TEST(IncludeJS_Engine, bind_function_promise) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; engine.bind_function({"myPromise"}, &promise_test); - sourcemeta::includejs::Value result{ - engine.evaluate("myPromise()", "index.js")}; + includejs::Value result{engine.evaluate("myPromise()", "index.js")}; EXPECT_TRUE(result.is_object()); } diff --git a/test/engine/engine_evaluate_test.cc b/test/engine/engine_evaluate_test.cc index d32ec0e0..1ddf673c 100644 --- a/test/engine/engine_evaluate_test.cc +++ b/test/engine/engine_evaluate_test.cc @@ -3,27 +3,25 @@ #include TEST(IncludeJS_Engine, evaluate_result_integer) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Value result{engine.evaluate("1 + 3", "index.js")}; + includejs::Engine engine; + includejs::Value result{engine.evaluate("1 + 3", "index.js")}; EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 4); } TEST(IncludeJS_Engine, evaluate_result_string) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Value result{engine.evaluate("\"foo\"", "index.js")}; + includejs::Engine engine; + includejs::Value result{engine.evaluate("\"foo\"", "index.js")}; EXPECT_TRUE(result.is_string()); EXPECT_EQ(result.to_string(), "foo"); } TEST(IncludeJS_Engine, invalid_function_call) { - sourcemeta::includejs::Engine engine; - EXPECT_THROW(engine.evaluate("xyz()", "index.js"), - sourcemeta::includejs::Error); + includejs::Engine engine; + EXPECT_THROW(engine.evaluate("xyz()", "index.js"), includejs::Error); } TEST(IncludeJS_Engine, evaluate_syntax_error) { - sourcemeta::includejs::Engine engine; - EXPECT_THROW(engine.evaluate("1 +", "index.js"), - sourcemeta::includejs::Error); + includejs::Engine engine; + EXPECT_THROW(engine.evaluate("1 +", "index.js"), includejs::Error); } diff --git a/test/engine/engine_stacktraces_test.cc b/test/engine/engine_stacktraces_test.cc index b6c691ae..668e9a7f 100644 --- a/test/engine/engine_stacktraces_test.cc +++ b/test/engine/engine_stacktraces_test.cc @@ -6,15 +6,14 @@ #include TEST(IncludeJS_Engine, unknown_global_function) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; try { engine.evaluate("this_does_not_exist()", "index.js"); FAIL(); - } catch (const sourcemeta::includejs::Error &error) { + } catch (const includejs::Error &error) { EXPECT_EQ(std::string{error.what()}, "Can't find variable: this_does_not_exist"); - const std::vector stacktrace{error.begin(), - error.end()}; + const std::vector stacktrace{error.begin(), error.end()}; EXPECT_EQ(stacktrace.size(), 1); EXPECT_FALSE(stacktrace.at(0).scope.has_value()); EXPECT_TRUE(stacktrace.at(0).path.has_value()); diff --git a/test/engine/engine_value_array_test.cc b/test/engine/engine_value_array_test.cc index 8e0a56a9..e3dfeaa1 100644 --- a/test/engine/engine_value_array_test.cc +++ b/test/engine/engine_value_array_test.cc @@ -3,7 +3,7 @@ #include TEST(IncludeJS_Engine, create_array) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto arr = engine.context().make_array(); @@ -11,7 +11,7 @@ TEST(IncludeJS_Engine, create_array) { } TEST(IncludeJS_Engine, transform_array_to_vector) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto arr = engine.context().make_array(); arr.push(engine.context().from(42)); @@ -22,23 +22,23 @@ TEST(IncludeJS_Engine, transform_array_to_vector) { } TEST(IncludeJS_Engine, evaluate_array) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Value result{engine.evaluate("([])", "index.js")}; + includejs::Engine engine; + includejs::Value result{engine.evaluate("([])", "index.js")}; EXPECT_TRUE(result.is_array()); } TEST(IncludeJS_Engine, push_and_get_array_element) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto arr = engine.context().make_array(); arr.push(engine.context().from(42)); arr.push(engine.context().from("baz")); - sourcemeta::includejs::Value result = arr.at(0).value(); + includejs::Value result = arr.at(0).value(); EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 42); - sourcemeta::includejs::Value result2 = arr.at(1).value(); + includejs::Value result2 = arr.at(1).value(); EXPECT_TRUE(result2.is_string()); EXPECT_EQ(result2.to_string(), "baz"); } diff --git a/test/engine/engine_value_function_test.cc b/test/engine/engine_value_function_test.cc index 6b383df9..6aba1cd0 100644 --- a/test/engine/engine_value_function_test.cc +++ b/test/engine/engine_value_function_test.cc @@ -3,7 +3,7 @@ #include TEST(IncludeJS_Engine, is_function) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto result = engine.evaluate("(function a() {})", "index.js"); @@ -11,7 +11,7 @@ TEST(IncludeJS_Engine, is_function) { } TEST(IncludeJS_Engine, to_function) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto result = engine.evaluate("(function a() { return 42; })", "index.js"); diff --git a/test/engine/engine_value_null_test.cc b/test/engine/engine_value_null_test.cc index 532af606..4697afe7 100644 --- a/test/engine/engine_value_null_test.cc +++ b/test/engine/engine_value_null_test.cc @@ -3,14 +3,14 @@ #include TEST(IncludeJS_Engine, create_null) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto null = engine.context().from(nullptr); EXPECT_TRUE(null.is_null()); } TEST(IncludeJS_Engine, evaluate_null) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Value result{engine.evaluate("null", "index.js")}; + includejs::Engine engine; + includejs::Value result{engine.evaluate("null", "index.js")}; EXPECT_TRUE(result.is_null()); } diff --git a/test/engine/engine_value_object_test.cc b/test/engine/engine_value_object_test.cc index ebb5667f..6c4da93b 100644 --- a/test/engine/engine_value_object_test.cc +++ b/test/engine/engine_value_object_test.cc @@ -3,7 +3,7 @@ #include TEST(IncludeJS_Engine, create_object) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto object = engine.context().make_object(); @@ -11,7 +11,7 @@ TEST(IncludeJS_Engine, create_object) { } TEST(IncludeJS_Engine, transform_object_to_map) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto object = engine.context().make_object(); object.set("foo", engine.context().from(42)); @@ -22,55 +22,53 @@ TEST(IncludeJS_Engine, transform_object_to_map) { } TEST(IncludeJS_Engine, evaluate_object) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Value result{engine.evaluate("({})", "index.js")}; + includejs::Engine engine; + includejs::Value result{engine.evaluate("({})", "index.js")}; EXPECT_TRUE(result.is_object()); } TEST(IncludeJS_Engine, set_and_get_object_property) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto object = engine.context().make_object(); object.set("foo", engine.context().from(42)); object.set("bar", engine.context().from("baz")); - sourcemeta::includejs::Value result = object.at("foo").value(); + includejs::Value result = object.at("foo").value(); EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 42); - sourcemeta::includejs::Value result2 = object.at("bar").value(); + includejs::Value result2 = object.at("bar").value(); EXPECT_TRUE(result2.is_string()); EXPECT_EQ(result2.to_string(), "baz"); } TEST(IncludeJS_Engine, set_object_function) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto object = engine.context().make_object(); - object.set( - "foo", - [](std::vector arguments) - -> sourcemeta::includejs::Value { return std::move(arguments[0]); }); + object.set("foo", + [](std::vector arguments) -> includejs::Value { + return std::move(arguments[0]); + }); engine.bind_global({"obj"}, std::move(object)); - sourcemeta::includejs::Value result{ - engine.evaluate("obj.foo(42)", "index.js")}; + includejs::Value result{engine.evaluate("obj.foo(42)", "index.js")}; EXPECT_TRUE(result.is_number()); EXPECT_EQ(result.to_number(), 42); - sourcemeta::includejs::Value result2{ - engine.evaluate("obj.foo('bar')", "index.js")}; + includejs::Value result2{engine.evaluate("obj.foo('bar')", "index.js")}; EXPECT_TRUE(result2.is_string()); EXPECT_EQ(result2.to_string(), "bar"); } TEST(IncludeJS_Engine, at_throw_for_functions) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Context &context = engine.context(); + includejs::Engine engine; + includejs::Context &context = engine.context(); auto obj = context.make_object(); - obj.set("woo", - [](std::vector args) - -> sourcemeta::includejs::Value { return std::move(args[0]); }); + obj.set("woo", [](std::vector args) -> includejs::Value { + return std::move(args[0]); + }); EXPECT_THROW(obj.at("woo"), std::runtime_error); } diff --git a/test/engine/engine_value_undefined_test.cc b/test/engine/engine_value_undefined_test.cc index 2a6b6f66..3b885eca 100644 --- a/test/engine/engine_value_undefined_test.cc +++ b/test/engine/engine_value_undefined_test.cc @@ -3,14 +3,14 @@ #include TEST(IncludeJS_Engine, create_undefined) { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; auto object = engine.context().make_undefined(); EXPECT_TRUE(object.is_undefined()); } TEST(IncludeJS_Engine, evaluate_undefined) { - sourcemeta::includejs::Engine engine; - sourcemeta::includejs::Value result{engine.evaluate("undefined", "index.js")}; + includejs::Engine engine; + includejs::Value result{engine.evaluate("undefined", "index.js")}; EXPECT_TRUE(result.is_undefined()); } diff --git a/test/packaging/find_package/hello.cc b/test/packaging/find_package/hello.cc index cd221632..9e7eeea4 100644 --- a/test/packaging/find_package/hello.cc +++ b/test/packaging/find_package/hello.cc @@ -5,10 +5,10 @@ #include // std::cout auto main() -> int { - sourcemeta::includejs::Engine engine; + includejs::Engine engine; // TODO(RaisinTen): Remove this once V8 supports this. #if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) - sourcemeta::includejs::Value result{engine.evaluate("1 + 3", "index.js")}; + includejs::Value result{engine.evaluate("1 + 3", "index.js")}; assert(result.is_number()); std::cout << result.to_number() << "\n"; #endif From e469c9d4d163fcd18bd0f1c136e7dd431ca3c5c4 Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Thu, 22 Feb 2024 20:34:31 +0100 Subject: [PATCH 15/19] chore: delete SOURCEMETA_ refs (#46) Close #43 Signed-off-by: Tony Gorez --- cmake/CompilerOptions.cmake | 2 +- src/engine/CMakeLists.txt | 6 ++-- src/engine/common/engine.cc | 2 +- src/engine/common/engine_context.cc | 2 +- src/engine/include/includejs/engine.h | 6 ++-- src/engine/include/includejs/engine_context.h | 4 +-- src/engine/include/includejs/engine_error.h | 4 +-- .../include/includejs/engine_function.h | 30 +++++++++---------- src/engine/include/includejs/engine_promise.h | 4 +-- src/engine/include/includejs/engine_value.h | 4 +-- test/engine/CMakeLists.txt | 2 +- test/engine/engine_binding_test.cc | 16 +++++----- test/packaging/find_package/hello.cc | 2 +- 13 files changed, 42 insertions(+), 42 deletions(-) diff --git a/cmake/CompilerOptions.cmake b/cmake/CompilerOptions.cmake index 918ec110..8db8a300 100644 --- a/cmake/CompilerOptions.cmake +++ b/cmake/CompilerOptions.cmake @@ -1,4 +1,4 @@ -function(sourcemeta_includejs_add_compile_options target) +function(includejs_add_compile_options target) if(NOA_COMPILER_MSVC) # See https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category target_compile_options("${target}" PRIVATE diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 1d4f5fd9..e54272d3 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -34,20 +34,20 @@ if(INCLUDEJS_INSTALL) endif() endif() -sourcemeta_includejs_add_compile_options(includejs_engine) +includejs_add_compile_options(includejs_engine) if(INCLUDEJS_BACKEND STREQUAL "JavaScriptCore") find_package(JavaScriptCore REQUIRED) target_link_libraries(includejs_engine PRIVATE JavaScriptCore::JavaScriptCore) target_compile_definitions(includejs_engine - PUBLIC SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) + PUBLIC INCLUDEJS_ENGINE_JAVASCRIPT_CORE) elseif(INCLUDEJS_BACKEND STREQUAL "V8") find_package(V8 REQUIRED) target_link_libraries(includejs_engine PRIVATE V8::V8) target_compile_definitions(includejs_engine - PUBLIC SOURCEMETA_INCLUDEJS_ENGINE_V8) + PUBLIC INCLUDEJS_ENGINE_V8) else() message(FATAL_ERROR "Unknown IncludeJS backend: ${INCLUDEJS_BACKEND}") endif() diff --git a/src/engine/common/engine.cc b/src/engine/common/engine.cc index b3a309ce..1ea5f3a5 100644 --- a/src/engine/common/engine.cc +++ b/src/engine/common/engine.cc @@ -8,7 +8,7 @@ #include // std::move #include // std::vector -#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) +#if !defined(INCLUDEJS_ENGINE_V8) namespace includejs { diff --git a/src/engine/common/engine_context.cc b/src/engine/common/engine_context.cc index cc59e14a..9875e302 100644 --- a/src/engine/common/engine_context.cc +++ b/src/engine/common/engine_context.cc @@ -1,6 +1,6 @@ #include -#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) +#if !defined(INCLUDEJS_ENGINE_V8) namespace includejs { diff --git a/src/engine/include/includejs/engine.h b/src/engine/include/includejs/engine.h index a86d6853..e2d1c3f8 100644 --- a/src/engine/include/includejs/engine.h +++ b/src/engine/include/includejs/engine.h @@ -1,5 +1,5 @@ -#ifndef SOURCEMETA_INCLUDEJS_ENGINE_H_ -#define SOURCEMETA_INCLUDEJS_ENGINE_H_ +#ifndef INCLUDEJS_ENGINE_H_ +#define INCLUDEJS_ENGINE_H_ /// @defgroup engine Engine /// @brief The IncludeJS higher-level abstraction of a JavaScript engine @@ -35,7 +35,7 @@ class INCLUDEJS_ENGINE_EXPORT Engine { -> Value; // TODO(RaisinTen): Add support for bind_function() to the V8 backend. -#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) +#if !defined(INCLUDEJS_ENGINE_V8) auto bind_function(std::initializer_list location, Function function) -> void; #endif diff --git a/src/engine/include/includejs/engine_context.h b/src/engine/include/includejs/engine_context.h index 01be84c7..80d6c93a 100644 --- a/src/engine/include/includejs/engine_context.h +++ b/src/engine/include/includejs/engine_context.h @@ -1,5 +1,5 @@ -#ifndef SOURCEMETA_INCLUDEJS_ENGINE_CONTEXT_H_ -#define SOURCEMETA_INCLUDEJS_ENGINE_CONTEXT_H_ +#ifndef INCLUDEJS_ENGINE_CONTEXT_H_ +#define INCLUDEJS_ENGINE_CONTEXT_H_ #include "engine_export.h" diff --git a/src/engine/include/includejs/engine_error.h b/src/engine/include/includejs/engine_error.h index d05ce8bc..8e0b27e6 100644 --- a/src/engine/include/includejs/engine_error.h +++ b/src/engine/include/includejs/engine_error.h @@ -1,5 +1,5 @@ -#ifndef SOURCEMETA_INCLUDEJS_ENGINE_ERROR_H_ -#define SOURCEMETA_INCLUDEJS_ENGINE_ERROR_H_ +#ifndef INCLUDEJS_ENGINE_ERROR_H_ +#define INCLUDEJS_ENGINE_ERROR_H_ #include "engine_export.h" diff --git a/src/engine/include/includejs/engine_function.h b/src/engine/include/includejs/engine_function.h index 0a153bc7..e6d4129f 100644 --- a/src/engine/include/includejs/engine_function.h +++ b/src/engine/include/includejs/engine_function.h @@ -1,29 +1,29 @@ -#ifndef SOURCEMETA_INCLUDEJS_ENGINE_FUNCTION_H_ -#define SOURCEMETA_INCLUDEJS_ENGINE_FUNCTION_H_ +#ifndef INCLUDEJS_ENGINE_FUNCTION_H_ +#define INCLUDEJS_ENGINE_FUNCTION_H_ #include "engine_export.h" #include #include -#if defined(SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) +#if defined(INCLUDEJS_ENGINE_JAVASCRIPT_CORE) #include // std::exception #include // std::vector #endif #ifdef DOXYGEN /// @ingroup engine -#define SOURCEMETA_INCLUDEJS_ARGS +#define INCLUDEJS_ARGS #else #if __cplusplus >= 202002L #include // std::span -#define SOURCEMETA_INCLUDEJS_ARGS std::span +#define INCLUDEJS_ARGS std::span #else -#define SOURCEMETA_INCLUDEJS_ARGS const std::vector & +#define INCLUDEJS_ARGS const std::vector & #endif #endif -#if defined(SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) +#if defined(INCLUDEJS_ENGINE_JAVASCRIPT_CORE) namespace includejs { // This is a opaque function signature that can be force-casted into // JSObjectCallAsFunctionCallback @@ -33,8 +33,8 @@ using Function = const void *(*)(const void *, const void *, const void *, } // namespace includejs #endif -#if defined(SOURCEMETA_INCLUDEJS_ENGINE_JAVASCRIPT_CORE) -#define __SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION_INTERNAL(function, call_as) \ +#if defined(INCLUDEJS_ENGINE_JAVASCRIPT_CORE) +#define _INCLUDEJS_EXPOSE_FUNCTION_INTERNAL(function, call_as) \ static const void *function(const void *context, const void *, const void *, \ const size_t argc, const void *raw_arguments[], \ const void **exception) { \ @@ -55,15 +55,15 @@ using Function = const void *(*)(const void *, const void *, const void *, #ifdef DOXYGEN /// @ingroup engine -#define SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(function) +#define INCLUDEJS_EXPOSE_FUNCTION(function) /// @ingroup engine -#define SOURCEMETA_INCLUDEJS_EXPOSE_TEMPLATE_FUNCTION(function) +#define INCLUDEJS_EXPOSE_TEMPLATE_FUNCTION(function) #else -#define SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(function) \ - __SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION_INTERNAL(function, function) -#define SOURCEMETA_INCLUDEJS_EXPOSE_TEMPLATE_FUNCTION(function) \ +#define INCLUDEJS_EXPOSE_FUNCTION(function) \ + _INCLUDEJS_EXPOSE_FUNCTION_INTERNAL(function, function) +#define INCLUDEJS_EXPOSE_TEMPLATE_FUNCTION(function) \ template \ - __SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION_INTERNAL(function, function) + _INCLUDEJS_EXPOSE_FUNCTION_INTERNAL(function, function) #endif #endif diff --git a/src/engine/include/includejs/engine_promise.h b/src/engine/include/includejs/engine_promise.h index e8261e2d..b7b1ec08 100644 --- a/src/engine/include/includejs/engine_promise.h +++ b/src/engine/include/includejs/engine_promise.h @@ -1,5 +1,5 @@ -#ifndef SOURCEMETA_INCLUDEJS_ENGINE_PROMISE_H_ -#define SOURCEMETA_INCLUDEJS_ENGINE_PROMISE_H_ +#ifndef INCLUDEJS_ENGINE_PROMISE_H_ +#define INCLUDEJS_ENGINE_PROMISE_H_ #include "engine_export.h" diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index e36165ef..f69179f1 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -1,5 +1,5 @@ -#ifndef SOURCEMETA_INCLUDEJS_ENGINE_VALUE_H_ -#define SOURCEMETA_INCLUDEJS_ENGINE_VALUE_H_ +#ifndef INCLUDEJS_ENGINE_VALUE_H_ +#define INCLUDEJS_ENGINE_VALUE_H_ #include "engine_export.h" diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index 75f1ee69..9eb4d4e8 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable(includejs_engine_unit engine_value_undefined_test.cc engine_value_null_test.cc) -sourcemeta_includejs_add_compile_options(includejs_engine_unit) +includejs_add_compile_options(includejs_engine_unit) target_link_libraries(includejs_engine_unit PRIVATE GTest::gtest GTest::gtest_main) diff --git a/test/engine/engine_binding_test.cc b/test/engine/engine_binding_test.cc index 48ec13e9..3e20de74 100644 --- a/test/engine/engine_binding_test.cc +++ b/test/engine/engine_binding_test.cc @@ -3,28 +3,28 @@ #include static auto is_string(const includejs::Context &context, - SOURCEMETA_INCLUDEJS_ARGS arguments) -> includejs::Value { + INCLUDEJS_ARGS arguments) -> includejs::Value { return context.from(!arguments.empty() && arguments.front().is_string()); } // TODO: Add overload that doesn't take arguments -static auto get_details(const includejs::Context &context, - SOURCEMETA_INCLUDEJS_ARGS) -> includejs::Value { +static auto get_details(const includejs::Context &context, INCLUDEJS_ARGS) + -> includejs::Value { includejs::Value result{context.make_object()}; result.set("version", context.from("1.0.0")); return result; } -static auto promise_test(const includejs::Context &context, - SOURCEMETA_INCLUDEJS_ARGS) -> includejs::Value { +static auto promise_test(const includejs::Context &context, INCLUDEJS_ARGS) + -> includejs::Value { includejs::Promise promise{context.make_promise()}; promise.resolve(context.from(true)); return promise.value(); } -SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(is_string); -SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(get_details); -SOURCEMETA_INCLUDEJS_EXPOSE_FUNCTION(promise_test); +INCLUDEJS_EXPOSE_FUNCTION(is_string); +INCLUDEJS_EXPOSE_FUNCTION(get_details); +INCLUDEJS_EXPOSE_FUNCTION(promise_test); TEST(IncludeJS_Engine, bind_global_root_integer) { includejs::Engine engine; diff --git a/test/packaging/find_package/hello.cc b/test/packaging/find_package/hello.cc index 9e7eeea4..b218544e 100644 --- a/test/packaging/find_package/hello.cc +++ b/test/packaging/find_package/hello.cc @@ -7,7 +7,7 @@ auto main() -> int { includejs::Engine engine; // TODO(RaisinTen): Remove this once V8 supports this. -#if !defined(SOURCEMETA_INCLUDEJS_ENGINE_V8) +#if !defined(INCLUDEJS_ENGINE_V8) includejs::Value result{engine.evaluate("1 + 3", "index.js")}; assert(result.is_number()); std::cout << result.to_number() << "\n"; From 41c723c9b3e3da17fa31ca75bab6d932afcfb68f Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Fri, 23 Feb 2024 13:30:05 +0530 Subject: [PATCH 16/19] Use correct Homebrew Cellar on arm64 macOS (#47) Refs: https://github.com/crossnx/includejs/pull/41#discussion_r1499231236 Signed-off-by: Darshan Sen --- cmake/FindV8.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/FindV8.cmake b/cmake/FindV8.cmake index 302353b9..eb6cb15f 100644 --- a/cmake/FindV8.cmake +++ b/cmake/FindV8.cmake @@ -6,10 +6,15 @@ if(NOT V8_FOUND) # downloaded from Homebrew. # Refs: https://github.com/Homebrew/homebrew-core/issues/45061#issuecomment-541420664 set(V8_VERSION "12.1.285.24") + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(HOMEBREW_CELLAR "/opt/homebrew/Cellar") + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(HOMEBREW_CELLAR "/usr/local/Cellar") + endif() target_include_directories(v8 - INTERFACE "/usr/local/Cellar/v8/${V8_VERSION}/include") + INTERFACE "${HOMEBREW_CELLAR}/v8/${V8_VERSION}/include") target_link_directories(v8 - INTERFACE "/usr/local/Cellar/v8/${V8_VERSION}/lib") + INTERFACE "${HOMEBREW_CELLAR}/v8/${V8_VERSION}/lib") target_link_libraries(v8 INTERFACE "-lv8") target_link_libraries(v8 INTERFACE "-lv8_libplatform") target_compile_definitions(v8 From fb41818f081b8ec41cafe3361243874c9da4ebc6 Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Fri, 23 Feb 2024 20:48:18 +0100 Subject: [PATCH 17/19] doc: add basic readme (#49) Signed-off-by: Tony Gorez --- README.markdown | 84 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 411284b5..75f5272a 100644 --- a/README.markdown +++ b/README.markdown @@ -1 +1,83 @@ -![IncludeJS](./assets/banner.png) +

includejs logo

+

includejs

+

Build your own JavasScript runtime

+

+ github action build +

+ +

+ + 📖 Documentation +

+ +`includejs` offers a unified API for building your own JavaScript runtime, bridging multiple engines and platforms with ease. + +## Features + +- Multiple runtime support: `JavascriptCore`, `v8` (more in the furture) +- Cross platform support +- Direclty consumable from `CMake` + +> 🤙 Stay tuned as we continue to expand our feature set. + +### JavasScript + +| Feature | JavaScriptCore | V8 | +|----------------|-------------------|------------------| +| Boolean | ✅ Supported | ❌ Not Supported | +| Number | ✅ Supported | ❌ Not Supported | +| String | ✅ Supported | ❌ Not Supported | +| Object | ✅ Supported | ❌ Not Supported | +| Array | ✅ Supported | ❌ Not Supported | +| Promise | ✅ Supported | ❌ Not Supported | +| Function | ✅ Supported | ❌ Not Supported | +| Error | ✅ Supported | ❌ Not Supported | +| Class | ❌ Not Supported | ❌ Not Supported | +| Set | ❌ Not Supported | ❌ Not Supported | +| Map | ❌ Not Supported | ❌ Not Supported | +| BigInt | ❌ Not Supported | ❌ Not Supported | +| Symbol | ❌ Not Supported | ❌ Not Supported | +| ArrayBuffer | ❌ Not Supported | ❌ Not Supported | +| TypedArray | ❌ Not Supported | ❌ Not Supported | + +### WHATWG APIs + +- [ ] Timers +- [ ] Console + +### Platform support + +| Platform | JavaScriptCore | V8 | +|-----------|-------------------|------------------| +| macOS | ✅ Supported | ✅ Supported | +| Linux | ✅ Supported | ✅ Supported | +| Windows | ❌ Not Supported | ❌ Not Supported | + +## Dependencies + +- C++ +- CMake +- JavascriptCore +- Brew (macOS) + +## Usage + +You can consume `includejs` just with CMake: + +```cmake +cmake_minimum_required(VERSION 3.18) + +project(your_runtime VERSION 0.0.1 LANGUAGES CXX) + +include(FetchContent) +FetchContent_Declare( + includejs + GIT_REPOSITORY https://github.com/crossnx/includejs + GIT_TAG main + DOWNLOAD_EXTRACT_TIMESTAMP NO) +FetchContent_MakeAvailable(includejs) + +add_executable(your_runtime main.cc) +target_link_libraries(your_runtime PRIVATE includejs::engine) +``` + From 1e5d4a06b5c3315c95e9aaf7f6e7fa4e2b541e5e Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Fri, 23 Feb 2024 21:14:52 +0100 Subject: [PATCH 18/19] feat(value): add .type helper (#48) Signed-off-by: Tony Gorez --- src/engine/include/includejs/engine_value.h | 14 +++++ src/engine/javascript_core/engine_value.cc | 26 ++++++++ test/engine/CMakeLists.txt | 1 + test/engine/engine_value_type_test.cc | 66 +++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 test/engine/engine_value_type_test.cc diff --git a/src/engine/include/includejs/engine_value.h b/src/engine/include/includejs/engine_value.h index f69179f1..907debd3 100644 --- a/src/engine/include/includejs/engine_value.h +++ b/src/engine/include/includejs/engine_value.h @@ -12,6 +12,19 @@ namespace includejs { +enum class ValueType { + Number, + String, + Error, + Object, + Boolean, + Undefined, + Null, + Array, + Function, + Unknown +}; + // Inspired by https://github.com/sourcemeta/jsontoolkit /// @ingroup engine class INCLUDEJS_ENGINE_EXPORT Value { @@ -41,6 +54,7 @@ class INCLUDEJS_ENGINE_EXPORT Value { auto to_string() const -> std::string; auto to_boolean() const -> bool; auto to_function() const -> Function; + auto type() const -> ValueType; auto at(const std::string &property) const -> std::optional; auto at(const unsigned int &position) const -> std::optional; auto set(const std::string &property, Value value) -> void; diff --git a/src/engine/javascript_core/engine_value.cc b/src/engine/javascript_core/engine_value.cc index 7eac8567..e29fdf90 100644 --- a/src/engine/javascript_core/engine_value.cc +++ b/src/engine/javascript_core/engine_value.cc @@ -82,6 +82,32 @@ Value::~Value() {} Value::Value(Value &&other) noexcept : internal{std::move(other.internal)} {} +auto Value::type() const -> ValueType { + if (is_number()) { + return ValueType::Number; + } else if (is_string()) { + return ValueType::String; + } else if (is_error()) { + return ValueType::Error; + } else if (is_function()) { + return ValueType::Function; + } else if (is_array()) { + return ValueType::Array; + } else if (is_object()) { + return ValueType::Object; + } else if (is_boolean()) { + return ValueType::Boolean; + } else if (is_undefined()) { + return ValueType::Undefined; + } else if (is_null()) { + return ValueType::Null; + } else if (is_function()) { + return ValueType::Function; + } else { + return ValueType::Unknown; + } +} + auto Value::is_number() const -> bool { return JSValueIsNumber(this->internal->context, this->internal->value); } diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt index 9eb4d4e8..5d5aaefc 100644 --- a/test/engine/CMakeLists.txt +++ b/test/engine/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(includejs_engine_unit engine_value_array_test.cc engine_value_function_test.cc engine_value_undefined_test.cc + engine_value_type_test.cc engine_value_null_test.cc) includejs_add_compile_options(includejs_engine_unit) diff --git a/test/engine/engine_value_type_test.cc b/test/engine/engine_value_type_test.cc new file mode 100644 index 00000000..b8ed02ac --- /dev/null +++ b/test/engine/engine_value_type_test.cc @@ -0,0 +1,66 @@ +#include + +#include + +TEST(IncludeJS_Engine, null_type) { + includejs::Engine engine; + + auto null = engine.context().from(nullptr); + EXPECT_TRUE(null.type() == includejs::ValueType::Null); +} + +TEST(IncludeJS_Engine, undefined_type) { + includejs::Engine engine; + + auto undefined = engine.context().make_undefined(); + EXPECT_TRUE(undefined.type() == includejs::ValueType::Undefined); +} + +TEST(IncludeJS_Engine, error_type) { + includejs::Engine engine; + + auto error = engine.context().make_error("error"); + EXPECT_TRUE(error.type() == includejs::ValueType::Error); +} + +TEST(IncludeJS_Engine, object_type) { + includejs::Engine engine; + + auto object = engine.context().make_object(); + EXPECT_TRUE(object.type() == includejs::ValueType::Object); +} + +TEST(IncludeJS_Engine, array_type) { + includejs::Engine engine; + + auto array = engine.context().make_array(); + EXPECT_TRUE(array.type() == includejs::ValueType::Array); +} + +TEST(IncludeJS_Engine, number_type) { + includejs::Engine engine; + + auto number = engine.context().from(42); + EXPECT_TRUE(number.type() == includejs::ValueType::Number); +} + +TEST(IncludeJS_Engine, string_type) { + includejs::Engine engine; + + auto string = engine.context().from("foo"); + EXPECT_TRUE(string.type() == includejs::ValueType::String); +} + +TEST(IncludeJS_Engine, boolean_type) { + includejs::Engine engine; + + auto boolean = engine.context().from(true); + EXPECT_TRUE(boolean.type() == includejs::ValueType::Boolean); +} + +TEST(IncludeJS_Engine, function_type) { + includejs::Engine engine; + + auto result = engine.evaluate("(function foo() {})", "index.js"); + EXPECT_TRUE(result.type() == includejs::ValueType::Function); +} From 04ebfbe9b0bfb67fd841d00d6978b8a50d6a99c6 Mon Sep 17 00:00:00 2001 From: Tony Gorez Date: Fri, 23 Feb 2024 23:50:25 +0100 Subject: [PATCH 19/19] doc: link small project (#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/crossnx/small 🚀 Signed-off-by: Tony Gorez --- README.markdown | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.markdown b/README.markdown index 75f5272a..a1db321a 100644 --- a/README.markdown +++ b/README.markdown @@ -12,6 +12,13 @@ `includejs` offers a unified API for building your own JavaScript runtime, bridging multiple engines and platforms with ease. +## Example + +In our journey to enhance `includejs`, we've also developed small - a minimalist, experimental runtime +aimed to provide ground for concepts and features we're considering for it. + +Hosted on GitHub at [`crossnx/small`](https://github.com/crossnx/small). + ## Features - Multiple runtime support: `JavascriptCore`, `v8` (more in the furture)