MZ@ !L!This program cannot be run in DOS mode. $Q?F0Q0Q0QH0QmR0Q0Pq1QmP0QmT0QmU0QmQ0Qm_D0Qm0QmS0QRich0QPEdi[" f' `///`A *PpP+ @/+^P/  8(P .textC `.rdata##@@.data%+ t+@.pdata^+`~+@@.tls!,"+@.rsrc@//@@.reloc P/ /@BH(H U+XH H(騻H 霻H )錻H i|H(H u+H H(XH(/CH H(?H ,H H  H(觢H H(H(HH ւ+H bH(H(HEH +mH BH(鑺H 9|H 9lH 9\H 9LH 9<H 9,H IH I H IH IH IܹH I̹H I鼹H I鬹H I霹H I錹H I|H(E3H +3ׯH 4H(SH )<H ),H )H ) H )H )H )ܸH )̸H )鼸H )鬸H )霸H )錸H )|H )lH )\H )LH )<H ),H )H ) H )H )H )ܷH )̷H )鼷H )鬷H )霷H )錷H )|H )lH )\H )LH )<H ),H )H ) H )H )H )ܶH )̶H )鼶H )鬶H )霶H )錶H )|H )lH )\H )LH )<H ),H )H ) H )H )H )ܵH )̵H )鼵H )鬵H )霵H )錵H )|H )lH )\H )LH )<H ),H )H ) H )H )H )ܴH )̴H )鼴H )鬴H )霴H )錴H )|H )lH )\H )LH )<H ),H )H ) H )H iH iܳH y̳H y鼳H y鬳H y霳H y錳H y|H ylH y\H LH <H ,HH{+Hsg+H{+H+H{+HYH{+HKH|{+H i̲H(3H +DBPH SH(颲H(gH @H(H(cH 0H(_H(跰H H(?H(ϧH H(H(˧H H(H\$Hl$Ht$WH %x+IHE3HH y+AHD$XHx+HD$PH+x+HH֋2HHHXHhHpHx ATAVAWH H3Hc3~ LHHA<uHHHH;|GLcJ HHtgN<~8LLL+M<6HHHǀ<:uHILLHIuH$HH\$@Hl$HHt$PH|$XH A_A^A\H(eH %X3ҋv+A0LJH(@SH eH%XHT$8HA0 9v+H J 3҈SuHL$8H HtHH [HHT$SH HHL$8u+eH%XHЀ<HH [@SH 38+H [HUVWAVAWHHPHEHXHLHЋP!H~Hee u+eH%XA@HJ;HEHEJ;HMHUHM@LƋHM8f{HM8tX"H3wHM8GkHM@HMkHEJ;I=u+HHHUWAVHHPHEHX E3LEDE -t+eH%XA@HtS Rl+eH%XHE3HM0HU8HDHdHM(H\HU(E3HM L(E3HE3HM0WHU8HKDH1HM(H\HU(E3HM LR(E3HE3HM0 HU8HHHDHM(Z\HU(E3HM L(H _[]HHHUWAVHHPHEHX E3LEDE b+eH%XA@HHOb+HtL Ce+E3H1`H  H8̋A8 t߉A8u @tHAHHJLIB8 HJ BIHHHLJ(I ƂLHb`BHHR@B8@u@B8 tHB@3H\$WH HHAHD$@LL$HHHT$@uHT$HH,HH\$0H _H'A8LAu8HI@pHa@HAHHu IHpI8A8HQP@u @A8 u 3HH@HA@@SH Hma+H l+Hg-HL$0s\HHHH [A8LAu?HI@xHa@HAHHu'IHxI8A8HQP@u@A8 tHA@3HH@A8HQtJH9JpuHAHHBpH9wHQ@HzHQHHza8A8@t ࿉A8 u3HAH@SH HHHHT$@fuHT$@HeHH [H#H\$WH 3HHHHAfAHfGH\$0GHH _H\$WH 3HHHHAHAAfAHWHfG>H\$0HH _HƒZIH H\$UVWATAUAVAWHHPHR+H3HE3HUHEH]HEE3H<:u HNJ<:E3H}E3LmHHHEH^HHH{HHE<HH:H}EMuuL7uE MtHEH;tTA+HcHH]HEH;u7HEEHHMH3H$HPA_A^A]A\_^]H!)@VH0ALHEyHHfH|$HH\$@HH0^HӹtH@SH H;CHr CHH [CLH\$WH HAHE333HC@HHH{HHC{HC HHC(HC0H3H{PH{XH{`H{pH{hH{xHHHHHHHHCHH{8H\$0H _@SH H {HHHrHHY+HHjHH*Z+HHbHHY+HHZHyHY+HHRHYHJY+HH RHHHYH HiHHoY+ HzHHhY+H{HHaY+ۿHtH˿H|HHX+H}HHX+H~HHX+HHHX+oHHHfX+XHHHX+AHHHhX+*HHH1X+HHHRX+HHHHH X+վH&X+H [H\$WHHlM+H3H$H$LE3HHL$8zE3HHL$8W+E3AxHO@W+W+ W+HHHD$0D$0tLL$`HD$ A HW+HD$`DljW+ E3AHHHHD$0D$0tLL$`HD$ A H 7W+D$`Dω &W+HdH$H3HH$HĐ_H(I OH`H b+MH b+@H Yb+3H d+HH! d+H(H(=d+uHlH ud+$H 9a+H(LVH`ICI[Icd$P U+eH%X@HH3ICICH3LY+MuFAH3IKMH$HL$8tHH Y+HL$8LY+Hd$ E3HZ+H$ :HD$XH3H\$pH`^@SH H!WH*HyX\^\HMH [LAHJBHJ B8 IHHH3LB(IH\$Ht$H|$ AVH HH a+VH֋(=c+LT+D$@E3HL$@IH)a+H2a+=a+HH_2a+HHa+HPH a+HH`+H`+}`+`+HHHHq`+HPH n`+HH <`+g=$c+Ha+H`+=`+HHa+HH`+HPH8W+H `+HS+Hu"HH\$0Ht$8H|$HH A^3&H(=ea+t H<^+H(HH Ia+H\$Hl$Ht$WH E3HHE33AQHH3H^HuIHH;u&HH\$0Hl$8Ht$@H _H>H;0HշH@SH H HH [HUWAVHHPHEHXHp HHHeeD(Q+eH%XA@JHEHEK>HM0.HU8HbAHgHM0ILE0HU@HM8 H8HHM08MHH=9H=<AHHM0HHHM8kLE0HU0HM8t H9u0HM8LHHM08usHM08tfHHM8kHU8HM;oHH U+,FHMEHU0HM0HU0HMYHH T+YHMaE@HMK >@HPA_A^_^]LI[WH@ N+eH%XIcd$(@HHH;ICICH;j88P+t0P+H [+t3HHKH G\+bHD$0H;H\$PH@_H "\+}YHUWATAVAWHl$HpHD$PHXHp HC+H3HE`LHHd$8d$@ M+eH%X@HHU@HM/eHH -O+PHMDHuHM@>HU@HMdHH O+HMDHAHM@=HU@HMdHH N+HMwDHHM@=HU@HMdHH N+HM?DHHM@l=HU@HMOdHH N+pHMDHHM@4=HU@HMdHH uN+8HMDHyHM@<HU@HMcHH N+HMDHIHM@<HU@HMcHH %N+HM_DHHM@<HU@HMocHH M+HM'DHHM@T<HU@HM7cHH M+XHMDHHM@<HU@HMbHH M+ HMDHHM@;HU@HMbHH L+HMDH]HM@;HU@HMbHH L+HMGHUHH M+HU@H5H]@H@AHM@RLM(E3H4L+HAVHM@&LME3HL+HAVHM@LME3HK+HAV HM@LME3HL+HpAV HM@LMxE3HK+HDAVHM@wLMME3H L+HAFfnHM@<LME3HK+HWI*NHM@;LME3HuK+HWI*N Y ܳHM@LE@ME3H|K+H|WI*N(Y HM@LE@Mt{E3HwJ+HGWI*N0Y nHM@MLE@MtFE3HJ+HLHHM(HEJ&HL\$PI[0Is8IA_A^A\_]L?H!H@WH HHT$@?+H\$0eH%X@Ht$8Ht$@HHH;t@KHT$Hyu@HT$HLH tu+CH7Ht$8H\$0HH _HӹtH@SH D>+HeH%XA@J LHJ &HH [H\$Ht$WH D>+HeH%XHٿ@JH<H?ȽOHT$0~u.HT$0LHyuGH3Ht$@HH\$8H _H#@SH H%?+H?+H%?+7H?+HH [HL$UHH`HEH\$xLLHUo9H]H;t?+tC A9}RHeEAEHUHM4HUl7LH HD$ LHUc8H]HM 4HM4HC(H\$xH`]Ht~H\$Hl$Ht$WH HHH3HMH4HH4H4HMHz4HMHy3H3H\$0Hl$8Ht$@H _@USVWAUAVAWHH0AIH=A+MLEHHM@5HU@HM\HH oA+HMIEHwHM@v5HU@HMY\HH A+zHMEHGHM@>5HU@HM!\HH oA+BHMEHHM@5HU@HM[HH A+ HMHt;u3HE@}@HM@H3HE@}@HM@HHMPE4EHMXH4EHHM@4LE@HM@HUP~LEXHM@HU@mI&3Hu`HDCHHT^DCHHDEHM`HVr4HH$EHM`3LE`HM`HU@HU`HM@LEHHM`3LE`HM`HU@HU`HM`jHU`HI$HM@H}`E3H*?+HL'LEPE3H?+HHtH?+E3LHMt%EHM`I#3LE`E3H>+HIH0A_A^A]_^[]LD$HT$SVWH0D 9+HeH%XJ4HH?tHHLL$hHT$ HT$ LD$(AϣudLD$hHӹ@H 1y!HH0_^[LD$hHH 'Gu'HL$hHLHuLD$`HT$XuH#H\$WH HHH8"HML#H\$0LH _HUVWATAUAVAWH8HHD$hHXHx.+H3HLHE3L|$@D|$H Y8+eH%X@H#E3HT$8IHHL$XyEHT$0IH%D,EHT$0IH$D,EGHT$0IH HL|$(Dl$ EHt$XLHUfHL$03LHT$pHL$@HH HMcHL$X@HD$PHHHH3mH$HĐA_A^A]A\_^]@UHH`fAH$HUIxLt$XMpIJHt$xLEHuHUHHMH\$pL|$PHt+LMfA90&3ۋHAQf0f vzLMLEHHU%=HMHU'HULEINHEH\$pL|$PHt$xH$Lt$XH`]HH;kIIA IHEHUDMD;DAHIcϋ HUH]HNH3DHF(LEHEHMH0LuHL;H HHPUVWAVAWHH`HEHXILHeeV4+eH%X@LHT$XHulHD$PHt_LD$XDHL;HcBMHHuf,_H$H|$`Hh^]H׹ќHf/HH@USVWATAVAWHH@HELHHeeD0+eH%XA@JISIKH >Ht"HLH UUL;Ht4IHD$8H>H HIH\$XHl$`Ht$hH@_LIKAVH@ICI[IsI{ HHhHIcd$0 *+eH%XHICICI>HC0HtfHS8HK(HD$8I>HjHHKHt {̯@tL3H ,+HH\$XHt$`H|$hH@A^H{ tHK(9 LWAVAWH`ICI[IkIs IMLH3Ikȉl$H )+eH%X@H4HHICICHHC0H,H9C 6$L{ H{0H$HC8HLs(H{Ds L{(H$Hu5H$t*H$HuH$@ DpL8H$K uL$HT$ HHl$ H[H$H 1+uELD$8HT$ H$u)HT$(HL$ fuE3LHT$(HHD$PHL\$`I[(Ik0Is8IA_A^_@SH HًHT$@ u3 (+eH%XLD$@A@H HJ HH [H#HUATAUAVAWH(HHEHXHpHx H+H3HLE3Lt$HDt$P w'+eH%XA@H4IHHD$XHD$HHD92PHB HHT$0rFLD$0HT$8HLH\$8HHL$xH=n,+HLD$(HT$8H:u5HT$0HL$8u!LD$ HT$0Hu 8D$ L|$xML:HMHT$0H p,+AHUHL$(H8L-O,+HT$8L$0`uLHT$8I[ILHHMvH8HL$(#HIEH H;H [H;H ?H;H {H;H H;HLHT$(H ++HT$@HLHT$(HL$H HI $HL$x6HL$XHH@L-*+HT$8Hu@LEHT$0HL$8u(HT$@HL$0uE3LHT$@IOHL$XHtLHT$( Lt$(M4$MtM3H v'+0HD$XHIHH3[L$I[8Is@I{HIA_A^A]A\]HMItHItHL$hH8Hπ=4+eT7E3LHH )+#HL$(pHHL$h3DHH p)+#HL$hH=Y)+HDH=rHje[-PHL$`H8H;RHUWAVHHPHEHXHpH3H]]\#+eH%XA@H,+HtLLHU HEHtLE HU H H] HEHJ7HL\$PI[(Is0IA^_]HM 蜮HHM-HH ++-HMHH ++lH ++0H ++cHUVWAVAWHHPHEHXLH3H]]DI"+eH%XA@J)HMHLHEHtHU@HH]@HEHJ?HH$HPA_A^_^]@UVWATAUAVAWH$PHHEH$ H6+H3HHLE3Ld$PDd$X !+eH%X@LHH `$+HL$@蘤LI$+@SH HHExD;}H@ IcH H HH [HL$HHH H(H HtcH(@UVHxH3H)H$HiHH1{+H$H$H|$peH<%X@HHT$`H2u[HD$XHHL$`LϋAHD$hH$HD$0H$HD$(HD$ 1u H$@,8H$H|$pHHx^]H׹&H@/@UVWATAUAVAWHH@HEH$HL3H]]D+eH%XA@N4K.HEHEK.9PHB H`K?WHG HHUHMLEHHUPK .mHMP3L?-HO HIHUH|uLEHHUPK ./H]P? HG HHH,?HG HHH,DIW L; 7H;;Iw(IHUHHu(H}Ht!HUHHuHEH@ xH0HMH6HMHHEI $HEK.IH$H@A_A^A]A\_^]HHPUAVAWHHHEHXHpHx EHL3H}ȉ}Ћ*+eH%X@H4HHHEHEHHUI6LEHUHM4HUHMLEHUH]ϢLEHUHuH]HUHur}ulHE@ELHU(HMHD$ =)+9HMHtLHUH}HMI>HIL$I[ Is0I{8IA_A^]H̋+3HAeH%XA@HJHAHJ H\$Ht$WH H9IHHOHT$0u.HT$0LHuGH3Ht$@HH\$8H _H#@SH HIHHtyHH [H"@SH HIHHtAHH [H"@SH HIHHtHH [H"H\$Ht$WH H9IHHuHѹpu@OHT$0u.HT$0LHuGH3Ht$@HH\$8H _H#eH%X=+A@HHAIH\$Ht$WH H9IHHt@OHT$0u@HT$0LHu+GH3Ht$@HH\$8H _HѹtH#H(HT$8u |$8H(2H(LD$@u D$@H(2H(,H(H(H,H(H\$WH H^3RH\$@HT$8HL$8EϊH\$0H _H\$Ht$WH HHT$@uy +eH%XHt$@@HH<H?t@OHT$Hbu@HT$HLH]u+GH3Ht$8HH\$0H _H׹tH#H\$WH0HT$H)t$ H3ۅuO|$HuHHNf/(w3HT$PWf.z u f/rH\$@(t$ H0_2H\$WH0HT$HH3ۅ|$HHT$HHuɝ|$HH|$PHT$XH_uGD$Xf/Ew< 3f/w.HT$ Jf.zuH\$@H0_W2H(HT$8~u |$8H(2H(HT$8~u |$8H(2H(HT$8~uD$8u H(3H(2H(HT$8A~u |$8H(2@SH HHL$@LD$8HH}L$83҅EʊH [H(HT$8}u |$8t H(2@SH HT$8H}|$8H\$@HT$HH~u D$HH [WHL@HPUVWAVAWHHpHEHXAIHE3L95+dD+eH %XAJIH\$PHt$XH|$hH@A^IATAVAWH@HD$0H\$`Hl$hHt$pH|$xMALLCLcиILHL@3H +H3o~HtHH|$8 0+eH%XH,Ⱦ(HH>HHDCLL$ HIxHt$ @H+H;HT$(KyLHT$(H yusCI6L3H 4+}IH\$`Hl$hHt$pH|$xH@A_A^A\HI+HIJD:MHGHw%3!I@SH E3E3H\HH [@SH HHL$8wuHD$8HHH [H@WH HHL$8\x +H\$0eH%X@Ht$HHt$8HHH;uHӹxu@KHT$@Kxu.HT$@LH FxuCH7Ht$HH\$0HH _HH\$WH0HHHT$PH wu0HT$PLD$XHovuHL$XHT$ wH,L$ H\$@H0_HHz+H3H$LLHL$ zLbMtFE3LxbIB LD$ L+@B +uHutOTIMu3IH$H35BHĸLD$LL$ SWH(LL$XHZxtS:H(_[H\$Ht$WH@Hy3ۋH9Ht$XH\$PH@_H\$Ht$WH0HHyH&AHfL3D$(HD$ H#sHυ:3DB qHHHy3H\$@Ht$HH0_H(HtL3H W +zH(̋ +eH%X@HH@SH HH Ht2{u,O +eH%XA0HI<t 3qtH#H [@SH HHHBAH Ht u3tHH [H\$WH zHu0H H:H H;Ht 3HtHH\$0H _HH@SH HH HuH [À{uY+eH%XA0HI<t3{sH#H!HAH\$ WH 3HH9yuHL$0ru @8|$0_H9{u"HL$8`rL$8EϊH\$HH _ð@SH yHuHL$0ru 8D$0eH%X U+H HH H [eH%X+HaAALKHHK HL$H8HD$ 8 HD$@Ht&HHHHtHHHHtHf@H8EHL$H8HD$ 8贃HHD$@Ht8H+HHQHt H+HHQHt H+HHH82EHL$WH0HD$ H\$HHpHHD$@f`H tHWHHHH\$HH0_H(H y+LH$I$IIH;LL$XHH Q+E3IAH ;+H;tFEnLH #+H;uL IAMD8XiH+M HHIAH(LIH+LH+LHHHHWHPH@HXMH3HxH9=+t9H+L;A@ A9}JH$HD$(MAHHH$HD$(L R+AHH\$hHP_H$HD$ MHT$8bHH HH +HAxuED9@ |HHxtH HH@@USVWATAVAWHH@HELHee+eH%XA@H4J&HEHEJ&HMH$AEHHM@HMPE3LHU@H]HHEHĔHM@HMHE3LHU@H`EHHM@HMHdE3LHU@H2EHXHM@_+HMHE3LHU@HEHHM@++HMHE3LHU@HH ߓ>H@EHœHM@@HMHHE3LHU@HLHU@HMHIHEJ&IH@A_A^A\_^[]@SH Hلt HL$@muHD$@HHH [H@SH HHL$8|luHD$8HHH [H#LUVWAVAWH@ICI[HHIcd$0D+eH%XA@JHJ(HB HHB(HJ HAHBHJ8HHtH %H;Hu H(H(H%nH\$WH0HyG0H_E3H 3觶HH#H 4HHH;HuH\$HH0_3nH\$WH H;HHr tHHH\$0H _HL$WH0HD$ H\$HHLA8\ H;HܪHGHGP Gp HPHHOXHHHHW`H HHH@HH\$HH0_HHXHhHpHx ATAVAWH E3H-9L9=J*L%DHIEFHH@@HuH+L9{PH+H[HChHHL9{xtmAHI;ߍ]HCpHHHAэɍD9{8ōe;CHHs`CHHIQL9{PuL9{XuD9{8uD9{SAkcL9{X/HCxHHHHxHAHHHAPH;3YL9HCHH9G`HHHAHHHAPH;͌3ڥL9u39Q݌@S`JH+H*H3H$PHم3d$(LL$@HK@HT$PD$ AH*jt\39T$@v1HHLXHa(H HCPH[HIHHKP;T$@rH$PH3k1H`[vZ_=t+H\$VH HyXHt{LCXI@0HCXA`8AHAP8 e`t?Au4IH(I@ HIH I@(HAI@pAH8IHt IiH{XuH\$0H ^à R8IH\$Ht$WH HAPHHHpHHaPHHHGHL3H;AIHE  P6͍mMA@8AqII3iHuH\$0Ht$8H _H\$Ht$WH HA`3HHuH\$0Ht$8H _HH@@HuHtfHG`H+CHH;}HHHUHHHEHXHp=8*+*H w+2Hee *eH%XHȾ@HHEHEHH *HuqAHJHM(LHU H *nHM HU HM PHU HMHH *HMH *HHEHeEHEHHd$ E3L*HU HMHM3HEHL$I[IsI]HtBSH HHHKHK(HK8HKHHH [@SH HHHHK8HK(HK#HKH6HH [H\$WH HHkH;Ht 3HaH\$0H _@SH zHuHHH [HH@SH HHHAHHt3=aHH [HT$SH HT$8HHH [H\$WH zHu)H:H;Ht 3H`HH\$0H _HHeH %X*H30H9A8HQtUH9JxuHAHHBxH9UHQ@HXHQHHtHA@HB@a8A8@t࿉A8 tHAH3HQ HM2HHAHHQHA HHBH\$Hl$Ht$WHPH 2HHHq3HFA0LA(MtIH *HD$0D$8eH%X@HHL$ H+HD$@HD$0H+HHHL$ HL3Hm*HOHt$pHHHHV*HG HD$@H+HH\$`Hl$hH 5*HP_H\$Ht$WH D*HeH%XHٿ@JH<H?uH׹^u@OHT$0^u.HT$0LH^uGH3Ht$@HH\$8H _H#@SH D O*HeH%XLڹNLL$HI HBI I\uHT$HHHH [H#@SH HH HH [@SH *HHL$0GHHHH [H\$WH HIHT$H&uHL$HLHRH\$0H _H\$WH HHHL$@\uHL$@LHH\$0H _H\$WH HHHHT$HI\uHT$HLH[H\$0H _@SH0HHHHT$PE3HL$@H觷HT$@HL$ HHH f*iHL$ HL$@HHH H0[LAHJB HJ B8 IHHH3LB(IHbxHbhLWH@ICI[IkIs HHIcd$0D*eH%X@J4H.ICICH.lHD$PHt HSH+LCHT$PHL$(HHHD$8H.HH\$XHl$`Ht$hH@_HHHUWAVHHPHEHX E3LEDE %*eH%XA@HHUIb~H8AIWHMPLeHHUXHMPVu;LEHU`HMXVu%HUHM`yHHMLk.H{HHHML92Hj{HHHMLW2H0{HHHML2HzHHHMjL-H{HHHMHLa-HzHfHHM&L-HzHDHHML=-HvzH"HU0H [*{HAHzHM(E3LHU(HM ĭHEJ7H$HPA^_]HL$USVWATAVAWHHPP*3ۨ]H W6*H~H0*HiH**H~H4*HmH.*Ho~H8*H!H2*H;~H<*HH6*H}H@*HH:*H}HD*HH>*H}HH*HHB*HK}HL*HHF*Hg*i*Hz*|*H**H**H**H**H**H**!H5*ALHVHMLLoHMH"HIHM~HHUyHVHMHAH8HMHHUPLe@Qu;HMPLEHUXQu%HMXHU|RuHUE3LIRI H IJHPA_A^A\_^[]HL$USVWAVHHPHEHee #*eH%XA@HH\$HH0_HHXHhHpHx AVH A8IHyILHEuHLsxHOHHHkhH;HBȃK8C8HK`@u@C8 tHC@HKHHHCpHHO`%H\$03Hl$8Ht$@H|$HH A^H\$Ht$H|$AVH H933HLHtH!{HDOH!{@HsPDKXHtIHKPHtI`X3H\$0Ht$8H|$@H A^H(HL$0mFt HD$0H(G@SHH*H3H$EL0s HL$`LA HT$jEAJE3H j3}DH*HHrHDH *HrH*jDH s*HdrHu*ODH X*H1rHR*4DH =*HqH'*DH "*HqDH *HqH(*CH *HTqCH *HqH*CH *HpH*CH *HpH*C(HL$0D3K*H*\$0HtnH=q*tdH=W*tZL~*HT$0H *tLu=H a*H*H3*AhOLH @*tH*3LH%#*H$H3Hİ[HUWAWHH`HEHXHHHeeD`*eH%XJpIHHHMHHEHHH$HĀA^A\_^]H\$Hl$Ht$WH AIAHHHzqH6HNXAQ FhH\$0Hl$8Ht$@H _@SH HًzqREHcHKhHqH [H\$Hl$H|$AVH IALL$`AHLH|$`HD$PHHD$XHH$qH6HMXAQ EhH\$0Hl$8H|$@H A^H\$Hl$VWAVHPHIHHA;qDHI;tgHqI;q3DLL$pHHHD$ 3;qD$pHChI;pL\$PI[(Ik0IA^_^LshpH\$Hl$Ht$WH0IIAHH3LHHHE3ɉD$ LpHpH7HOXAQ GhH\$@Hl$HHt$PH0_H(LH3IH(LI[IkIsWH@Hمҹ EIcE3HD$(D$ EA:HHApH Ch9ȉrH\$PHl$XHt$`H@_H3Hf9AuHvf|A:tf|A\t f|A/tfTALI[IkIs WATAUAVAWH03IMIHLM5pD$(E3ICȹ<Lc3MoK<$9$oHl$pMoL|$pHSpHBHHpHLpDd$(ALHD$ 3ҹ<HHHKHCHKH3HC HCHH|H\$0H|$@Ht$8H A^ÿH\$WH HHHH`HAHIHt|,@tH *L36HH\$0H _@SH0HI3H\$ +hH0[@SH YhH [̸A@SH 3Mt_HH+\u HBH+\Ht HH+\u HBH+\HhIHHH@H;u|H [û@5H(HIHtHH H@`H;ºu H(H(H%>5H(HtHHH@H;ºu H(H(H%5H\$Ht$WH0H3HC0LC(t$@LM+hL;SshDCD+C(HK8AHhHK@L HS(HH@I;LL$@hDx1HK8HhD$@hHC(HHC(@4HH|AEx_C(+C ahHS chDEiAhAhAqh@8rChH*HCH\$HHt$PH0_@USVWATAVAWHH0E3HAD9!u&HA`HHH+AHQ0HH+HCxHH;hE{(+{ }HhEhD9#hCxLHK`H+KPLK`HS H+HKE@HH@I;hHE@LEHHD$ ^x2UHDE@HC EhAHHC`HCPHK`H9ChufD!H0A_A^A\_^[]fCpLHtHysHH;h2HLD$HT$HL$SVWAVHHHD$0MHHHHhLAIHHHHH;hLFL$3Mt0IwiH|$(H 0*Hvh31HtHHt?H|$ MhH{hH;HsLsHrHB3HHA^_^[&H\$WH HHmh3H9QnhEthHu HyHYsH\$0HH _H H\$Ht$WH IHHgAhE3HHqThHH\$0Ht$8H _@UVWATAUAVAWH$@HHD$XH$H5*H3HMMHLE3AH *Hh3DBX-0HtHH|$@HehHGL>gHHÀ<uHWHgHH;HgH;MHH|Ht4HHHt LHc H_HHLw G(L0L8L@H1HGHLPH|$PHGPHuhL|$@L|$8D|$0H2HHhL|$@L|$8D|$0 ھ*eH%XLdHF HLl$PLl$XHU#5H]I<$H?dHUOk$dLHUHc$dGH\$HHLE HU(Hq#pdLl$8Ll$0Dl$(Ll$ DM LE(3ҹ ?dHHD$XL@IH q*H'd3'HtHH|$PLEpHH"uNHEpH dLmHPHD$0HEHD$(Lt$ LAHuHE8HMh#cL}hI$H;cHUxK#cMHUxH #cCL|$hHHpHHpLxLHx)LL3HL1LLHDžLfDLLHDžLfDDAHtM HHEHbHHHHCLsHCHbLl$0D$(D$ E3DƺHMHbHCHHH@H H;HbHH@H H;HbbWEHHM0HEHHUHHMHHEHH=0H v0HtNABuAH]HHH;H!bI0AC uHMHH@H;bc0IH i*Ha3A8$HtHH]L-H5DNHHH3HKHHCHK HKHHK@HHCPHHHKpHKXHK`HKhHHHǃHǃHfHHǃǃ H(L0HWEHHMHEHHUHHMHxHEHxHt\ABuOH]HHH H;H`pAC u HMHH@HH;`HxHH@H H;Hj` g`3LL/ LL 1 H H HxHH@XH;`HH@0HH;MaH0I;tI;_`u3H $ H} L&L Lx L1ZHxH HH@XH;H` EfaHHpHHHCHaKNtAHfHDž3HfI;* HHpDH5HIHfH_H AH0H @HHH\$0H _H\$Hl$VWAVH HH3DHOHH@^oH9o tHG@H^HG(HG8DH9opu6H ި*HH^3A LHtHHwpH^HGpHGXHGhHG`HLJHf(EF=^^HLI;i^Lw`ILJL|$@ | ^ ^ ^HLH+G`HHHw`L|$@A{t^HO`HHH+G`HHHO`;T^AщHHLHA# ALJH0H\$HHl$PH A^_^H;wh8HHOH+G`LHL+HHw`IȋЅxHG`J4x]AHL$WH0HD$ H\$HHt$PHH7HH(HE3AHHH;?]H_H\$@HUHCHLChMt3H G*H9HCLCMt3H #*HK@Ht HH@HH;u8|HC@@tL3H *HH\$HHt$PH0_HT$UVWAVAWH0HD$(H\$pLH3l$ yhZ\Hy(HWH$HLl<L;rHHHGH AI;-\HoHHf(~hu,HNHH@0HH;HVh\\~h\HNHH@HH+H;HT$`\[IHt$`>HvHf9.[HHf9,^uHWHIHH;I;[H;8LGHHHt5H'HHt LHH_H Hf,XIFInfA.H_H[L;[I;[IFH;LHIHt?HrH?I~IHt LHI^I~If,XD$ IH\$pH0A_A^_^]Hs9HHGH AH;ZHHHHHHZHHH:ZIEI`HT$VWAVH0HD$(H\$`Hl$hLH3l$ yhZHIHH@@HE3H;HT$PsZrZH|$PH(f9/uZH@Hf9,_uHVH HH;rH=HHFH AH;8ZHH;PZH;HKZH~HHt LH)H^H~Hf,XIFInfA.H^HZHIL; ZE3t4H~s[I~s~IHt LHI^I~sdIf,XD$ IH\$`Hl$hH0A^_^HFHaH6HLFHHRH ;IIHLHtHyrHH;YY2HLD$HT$HL$SVWAVAWH@HD$0MHHHII;)YLAIHHHHH;YLFL$E3AMt@HL;Lt$(H *HXM3 HtHHtpH|$ Mu,H{sFH;HsL{HrHfF4{H@A_A^_^[H{XHMtO?HLMt3H *E @SH HHH;XHQH;rE{XHXH [LAHrHu3H\$Hl$Ht$WH IHH3VXE3HHft-H{r>H Ht L?HH{H{r$Hf,xHH\$0Hl$8Ht$@H _HHH\$WH HHHLHHH\$0H _VA+HHHED|$(L|$ DL3ҹHЉEVD-**DDDl$4E3Dt$0EILL@IH *HV3 HtHWEEHHMHuL}LHt$PL}3HEL|$HH=t*VLO*L X*IIlH=l*pVLG*L P*IQM+IK g<AEE3fE$G *I GED$(HL$ DLE3ҹHD$XHEWD$XHtFHL$`HUDl$4Lt$PHt$`L|$XHD$XHEHA2HL$XLHVH\$`HtCULt$PLd$8Ll$@ w*eH%XL<ȹJ9HBJ9LMLEHL$H(WH]@J48H>YVHUN&hVLHUH^VFH\$pHV(IH>IVHHEALMHUH%{VH]Ⱦ@J4>H>$VHUЋN3VLHUH)VFH\$xH&VI$MtSAFuFH\$PHHH 8H;HuO+{ uHL$PHH@HH;u0IHMH35HA_A^A]A\_^[]SK@UVWATAUAVAWH$HHDžH$@ H*H3HLHUPHHM3H}} `*eH%XL,L@J.HEHEJ.ga=UHB HHUJHa}>aA9$"UID$ HLH|$HH|$PHIcHJ4.H9>uH֍H|THNTLHHTFH]HLHHTH|$8H|$0|$(H|$ DL3ҹbTHHD$PL@LH *HIT3HtLLt$HLHHuRHH&TH}HHHD$0HEHHD$(L|$ MAHu HEHB0@A<$SID$ HH}H}H}@HJ4.H>SHN SLHHSFH]HLHHSH|$8H|$0|$(H|$ DL3ҹKSHHEHHHLM@HH *H$S3HtHHuLHUxHu9HH SDȋL;BMHcHLExHUuf<^H}J)HEH}EHEJ)A<$R|$ E3LEIHGHHSHUH +WEED$p8*SHADL%G*L@DHHHMS|$(H|$ EM3ҹHc>SH 6HmS}HHASt$(HD$ EM3ҹHHL@HXIHfwPEHHP~P~PD+Ld$`HHHE0|$(H|$ EL3ҹFЉD$hND-**DDDl$X3@t$AEILM@HH *H9P3HtHWEXDHHMXHu`H}`HuH]XH}XH]H=y*PLT*L ]*IHqH=q*OLL*L U*IQM+HKJ a@AEfOHNOLHHOFH] HP(IH>OHHALHHUPHK4,H>fOHNlOLHHYOFH](H]HOHMHtdAAuNH]HHH H;HOD{ Au HMHH@HH;NLt$HH]HNHuHt;H>1OHN'uLHH uFHH]H;}uHL$Bu 8D$BNHEȹJ)LEMt3H Y*MtM3H A*HEK,HHH3H$@ HA_A^A]A\_^]HT$SVWH0HD$ HH3H|$`H LJ*HP3DB:HtHH|$hHt&HQHGG HHHwHKHuH{H3H0_^[藇H(HIHtHH)H@pH;ºu H(H(H%H(HtHHH@H;ºu 芺H(H(H%HT$WH0HD$ H\$@Ht$PHH3H|$XH *HO3DB HtHH|$(Ht&H)HGG HHHwHKHuH{H3H\$@Ht$PH0_gH(HtHHH@H;ºu 蚹H(H(H%HL$H8HD$ H Dž*HN3DB0:Ht+HD$@HHHHtHHHHtHf@H8H(LH b*Ht3HtH(eH %`HI0H 7*H\$Hl$VH`IHM3I-H|$pHT$HH;H A#uhH\$HLD$PHHYuNLL$PHD$XHD$03HD$(DHD$ 4u LD$XLL$@HHu8D$@tH|$pH\$xH$H`^ø@SH LHH -*HlM3Ht H3H [øH\$WH zHu2H H:HIL$HAIBIQIH;7ILHILILHMLL$8ICx'IIHHAL H @AIAHHAIALHLL$@bHBH;tHHIHP'H8H Ht$UWAVHHMHHHHUH HULE(H8E(KH `~*H$HK3DBHH_3LEHCHfOHL3HsCyKH]HMHuHUH 'HU3LEE3HUHMVHUH HU3LEE3HUHM HUH !uoHU3Cu_LEE3HUHMuFHt-HUH Pu,HUE3HMLuLELM8HHH$H$HĀA^_]@SH HH Ht5{u/y*eH%XA0HI<t3HH [@WH zHIJH H\$0HHIHHt 3HVH\$0HH _@USVATAUHH`H3HMH]EMHUH$H _H}LEHHC8]:LEHH"HMHU HuH x*eH%XH>L$L$L<Ⱥ@LM7I9.IANHUn6IHULIf&IHHfEtIEH}I?HELv H9IOHUuHUMHuGIދNL$tMu(HFH H;LEHMHtj6HHEL$HEH$H`A]A\^[]MEHUIH~[`HUH(LEHH;t H(蕅3HLH L@UVWATAUAVAWHhHHEHXHLE3AH y*HG3DBXHtHH}A@D%v*HWHH]HMwH7HOGHGH_G HGLo(G0Lo8G@LoHGPLmDmeH%XJ4I7HEHEI7HMHH]EHt 3HHO(0HdGH_(Ht3H0HtH<0t3H8LmHMHH]EHt 3HHO8H%GH_8Ht 3HHt0H<0t3HLmHEI7A@LE3H <GH]HUH U7FHuLEH~HgFHEHD$0Ll$(Ll$ LMD'FLMLEHH}F8EjFlFH}eH%XAJHH;tIHUKuJLHUH u6CI>IH$HA_A^A]A\_^]HӹtM.@UVWATAUAVAWHPHD$(H$LE3AH v*HE3A HtHH\$0@-s*HEL+CLkCLk Lk(Lk0Lk8Lk@LkHCPLkXLk`LkhLkpLkxLƃDfǃƃLl$8Dl$@eH%XL$DMIHD$HHD$8IH$EH$I7H>uH֍HDH$NDLH$HDFHt 3HH 0HDH;Ht3HJ<&t 3HHD$HI@L$H!5H~DH$eH%XHHH;uHӹuHHT$ K'u6LHT$ H "u!CI>IH$HPA_A^A]A\_^]M.HT$SVWH@HHT$ H Ht$ LD$pHHY3ۅum8\$pt]LD$(HHuRHL$(HT$xPu>H|$xHL$hHT$0u%HD$0H9GHuH@_^[HH\$x2H(HT$8nuHL$8HI(H(HT$SH@HHT$ H H|$0LD$`H|$ HHf8D$`BLD$(HH#HL$(HT$hSHL$hHI(HT$`H\$X2urH|$`Hl$8Ht 3HHO0HTBH_Ht13Ho*eH%XHH|t 3HHl$8ƇH|$0H@[HHXL@HPWH0HPAHuLD$PDHT$HHd4H\$@H0_H\$Ht$WH@HHHT$ H ? !H|$ LD$`HH8D$`ALD$(HHHL$(HT$huzH\$hH{8ZAn*eH<%XH[8@HuLHU@LH :u8CI6Ll$HL$L|$@IHPA^_^[]HӹtIHfDH UATAUAVAWHhHHEHXHpHxMDH3Huu j*eH%X@LH}LEHH >8E=LEHH=HUHM=LeIEfIvI?H?uH׹X=HUNjOJ=LHUH9=GI<$I?H?%=HUNjOw/=LHUHo =G3EwȉEHuH]DmLuI$H fHUH;uCHMTHEHHMIHL$I[0Is8I{@IA_A^A]A\]H S0H;t?H H;H H;H gfH;HM {HM0mMD$HHUIL$(. H0H;HOHMHUDžHELEHSu 8E!HMHUDžHELEH%8EHM&HMeHUWATAVAWHxH`HEHXHpH]*H3HXHL3H|$X|$` kg*eH%X@LuI֍H:HUAN:LHUI:AFH\$HHLEHUH:H|$8H|$0|$(H|$ DMLE3ҹFX:HHD$xL@HH h*H?:3>HtHHt$pLEHUHHuOHEH&:H|$@HEHD$0HD$@HD$(HD$ LAHM"zu HD$@0=t*9}(H}@E(Hsq*HExEpHHHH9|$(H|$ AL3ҹALc9K 6H9HH9Dt$(HD$ AL3ҹHHHHfHf9H|$0D$(D$ E3ɺEAHHA@HHDȉLExA@EH =s**9=o*"69HM HM`9LuH\$hHt5H;9HUKuHUMH uCII<$HtL3H f*HD$hIIHXH3蟚L$`I[8Is@IA_A^A\_]HHf#fA;3uDtH8HHHHHM8LuH\$hHH;8HUȋKHUH H\o7H  7AfD@H DHH$Af fD fDEfDI*!NbH4IIBzՔIHHHH,IIHHHH$IIHHHH;wfHHHHD'EfDH̃u"Ãtw7HHXHhHpWH@HIHPIuKH\$ H$HD$pHL$(HC8HD$xHC@Hk Hs(H{00kHHKHHHL$(XH\$PHl$XHt$`H@_H(HT$8Qu HD$8ƀH(H(HT$8!u HD$8ƀH(@SH HT$@u HD$@H [HHPUATAUAVAWHhHHEHXHpHx MMHUHEL H]WE3LmLmLEHUHtHUHMD^pMLmHUύH0H}H}Hu:3HGHGHGHG(L/GLo G(wHHMHO H7HU3<*7E3LEHUHL$X 7Ht6HUH ~@6E3LHUHL$X6LL$@LD$XII68D$@66HHD%X*/H8$H@H H0H(HpHxHXHhH`HUH5H]HU@H /5LEHHU@H5HUPHMHXH,]P5DoH_HH|$HeH%X@JHH;tgHKW5LHH <5CI}IHXH3ŎH$H`A_A^A]A\_^]Hӹ$t4HL$H M4LHUz4HUHMD4HȸHLHL@LH rY*H23HtLLsxLl$HHt$0Ht$8\HD$0Dt$DL9wXuL9w u D8tuHD$0HHHD8q2H;2DžHHHL$0JLH HD$ LHUHL$0H]HHC(ADt$DH`uH(u HL$0HAHـxux E2H@xtH;=2DžHHHL$0LH HD$ LHU HL$0@H] H5rHC(ADt$DHpH8Hx'H@Hx]H@RHhGH0<Hhu"H0uHXuH u HL$0HAHـxux X1H@xtH;P1DžHHHL$0LH HD$ LHU(HL$09H](HfHC(A Dt$DHt$hLU*IRHIMʀzu(DA E;0AytE;}LHH ytAyI yuD;q 0HIytLI;M+HIʀz0D9p 0HHxtI;0D;q 0Hy(I€z0D9r 0HHztI;v0D;p l0Lp(Lt$heH%XJุHH^0HM0n0L}0HU8H Q0LEHU8I80(HH; 0HH@LHLPALL$HH@HM|/8HD$0HXL{u7IVHL$0M6HtL3H U*IA~tHD$0H@HD$0HHD$0H@Ht$8LD$0Mt3H T*|Ll$pIxHHy.HHyu H;A.HLt$HHt$xHuHUxH jhR/LD$xHUxIJ8/H|$x,/HUH Che/LEHUHL$x .LD$AHHM.8D$ALuL|$xHL$`.HH .H.E3LHHL$`a.HH EE.H@..E3LHHL$` .HH @-H-E3LHHL$`e-HtHL$XHT$ u*HT$ LD$PHL$PEϊH\$@H0_2H\$WH@HHHT$hI HL$hLD$8HT$ HL$ HT$(HT$(LD$0H*uytA*eH%X@Ht$PHt$0HHH;8KHT$hHu.HT$hLH CuCH7Ht$PHH\$XH@_HHHHPUATAUAVAWHhH HEHXHpHx MMHL3H|$8H|$@LD$HHT$PHlHUHL$PgUwMH C*H_3DB0uHtHH\$HHV3HCHCHCHC(H;CH{ C(sHUXHM(`0D=?*xPH8HK HH{ Ht3H03HMHt&}u eH%XJH<t 3۪H}LsHUpHM A0x'H8H HH;HHMH LD$83H  Lt$8HT$XH H|$XLD$`HqeH0H\$`HL$(HT$pH tHT$h3YE3LD$hHT$pHL$(٪gHUH `NHT$x3 9E3LD$xHUHL$(HUH HU3E3LEHUHL$(AHt6HUH éE3LHUHL$(LL$ LD$(HIXv8D$ d3M|ދuߨuLt$@H|$8L}HL$0$tSHUH )HUE3LEHUHL$0>tSHUH NHUdE3LEHUHL$0tHt6HUH nhVE3LHUHL$09MLL$!LD$0II8D$!L$ I[0Is@I{HIA_A^A]A\]ù0%HHD$HH3DB0HH;CH{ C({HUXHM[HK HHMLcHUpHMHH'HM2LL$@LaHH ޸2HUH +uE3MHUHL$0r2LD$USAWHHHLHHUABHMLEHU(HMHUH$H$Ld$xLt$p@DDDH]0HMLetRHUH "3HUƥ}LEE3HUHMI`AtNHUH xʥAEHUr)LEE3HUHM tRHUH w3HULEE3HUHMHt1HUH ^ HUE3HMLduLELMIIug8Etbu^Ld$xH$H$Lt$pHĀA_[]LE0E3HUI뾋5A| 22@UVWATAUAVAWH$ HHE`H$0HF.*H3HHL3Ht$`t$h )8*eH%XA@L$K4HD$pHD$`K4H959H*3^HB HHT$P|$P9@HC H8HT$TH֢2|$T'H|$xHUH1ED,D|$@;!HC HHHT$X~"|$X;H{ H;#HMHMHEHT$\2u |$\LHuHuHUHNH]A@O<HH#HAHL GHAHx>HHHAHL} MHyAH?HHHAHL3 sH/AH?HHEHAHL aHAH ;HHHALH HAH;HHHAHLUA(HUAH?HHkHAHL H AH ?HH!HAHL -HAHN=HHHAHL{ ۓHwAH,6HHHAHL1 H-AH29HHCHAHL HAH<HHHAHL UHAH=HHHAHLS HOAH<HHeHAHL  YHAH=HHHAHL HAH`<HHHAHLu HqAH7HHHAHL+ kH'HAHY:H=HAHL HL$ AH6HHHAHL HL$(AH\;HHHAHLQ iHL$0OAH8HHeHAHL  HL$8AH7HHHAHL ɏHL$@AH6HHHAHLy yHL$HwAH6HHHAHL1 )HL$P/AH5HHEHAHL َHL$XAH5HHHAHL HL$`AH2HHHAHLY 9HL$hWAH1HHmHAHL HL$pAHt3HH%HAHL HL$xAH2HHALHH IHMAH0HHHAHL: HM9AH2HHOHAHL HMAH0HHHAHL \HMAH/HHHAHLe HMdAHA.HHzHAHL HMAH-HH3HAHL oHMAH/HHHAHL HMAH4.HHHAHLI ъHMHAH=.HH^HAHL HMAH.HHHAHL 3HMAH'-HH HAHLt HMsAH0HH HAHL- HM,HHR-AHB HAHL FHMAHj.HH HAHL HMAHc,HH HAHLX HMWAHL-HHm HAHL YHMAH.HH& HAHL HM AH.HH HAHL HM AH'.HH HAHL< lHM; AH,HHQ HAHL HM AH*HH HAHL ΆHM( AH,HH HAHLg HM0f AHK*HH| HAHL  0HM8 AH.HH5 HAHL HM@ AH])HH AHLH HMH AH*HH HAHLK CHMPJ AH)HH` HAHL HMX AHx*HH HAHL HM` AHA+HHHAHLv VHMhu AH,HHHAHL/ HMp. AHc,HHDHAHL HMx AH+HHHAHL iH AH*HHHAHLW HS AH'HHiHAHL  łH AH%HHHAHL sHAH%HHHAHLy !HuAH)HHHAHL/ ρH+AH`)HHAHAHL }HAHv&HHHAHL +HAH#HHHAHLQ ـHMAH#HHcHAHL HAH#HHHAHL 5HAH#HHHAHLs HoAHH"HHAHL) H%AHz#HH;HAHL ?HAH$HHHAHL ~HAH&#HHHAHLK ~HGAHL%HH]HAHLA(HAHV*HHHAHLA(HAH8)HHHAHLu }HqAH)HHHAHL+ 3}H'AH,(HH=HAHLA(H AHf(HHHAHL |H(AH'HHHAHLQ i|H0MAH"'HHcHAHL H8AH&HHHALH {H@AH>&HHHAHLs s{HHoAHT%HHHAHL)L$A(sA({E(CE(KE(SE([E(cE(xE(hI[]@SH HHH [HVWATAVAWHPH@HXHhAHLIEy IH<uCHcHLM@E3AH *H&3vHtHH|$@HH7H.Dd$(Ld$ DL3ҹ,oHl$(H|$ DL3ҹnHcȅHcL$HpH$ *eH%X@HHH;t`HT$0KqulLHT$0H qu\CI6HtL3H *uIL\$PI[0Ik8IA_A^A\_^HӹptM&M&M&M&@WH HT$@(Hp *eH%XH\$0@Ht$8HHt$@HH;KHT$Hpu.HT$HLH puCH7Ht$8H\$0HH _H@SH HDHHHIHt {dH [@SUWHPHHL$8$0xHKH8HPH{Ht 3HoHL$8Ht+|$@u$D*eH%XJH|t3nH{HL$8LD$pHHnu 8D$pH$H$H 1oujH$LD$ HmuPHL$ D@LL$(H$wmu0HL$(HT$0nuHD$0HtxpHHx~HtH{u#HKHL蒆HK3mCHP_][HCH3HAAAH@SH HHL$8luHD$8HHH [HHHHUSVWATAUAVAWHHHE`)p)xLHz3H|$H|$P *eH%XL4A@K.HD$XHD$HK.9:HB HHHlzmHT$0HlW{|$0pH\$8HUHmz}f/=tHU8(pf.f/A?>IG HHT$4H.l0|$4%H\$@HT$`Hmut$`L,EI?HH O*H3DB@pHtHH]HHIWH@HH{C{H>HHMy 0xH0HKHHsHt3Hl0HMHt}uJ<0t 3@kH}HsHL$hujHT$hHELHju8uyHt$xHT$pH ku^LEHT$pHAjuHD@LMHT$xHMiu-HUHM\kuHEHtHHxxp~HtH{u#LHHK3HKhjCH{ H{0H} }(K.HE0HE K.Lc H{0H{8MnHH *HM3nHtHHs(LcDk HC(HHMP*HI/LeAHEHD$ LEHI'HUHMKjHEHHHHMhHUHELI.iu @8uoLeHUH "iukLEHUIhuVD@LMHUHM%huuH֍Hiu+HUNCiuMHUH?iuFIH[HUH F*@huHH |)_EHHMPlHEHHM@VE3LHU@H =)3HM@UHHMHH )9HMoH)EHNHM@E3LHU@H )蟼HM@EHHMPE3H}@LHUPH )iEHHMPHEHYHM@E3LHU@H.EHHMP[HEHvHM@EE3LHU@HEHHMP HEHcHM@ E3LHU@H踻EHHMPHEHHM@E3LHU@H}EHHMPHEHHM@E3LHU@HBEHHHMPoHEHjHM@YE3LHU@HEHHMP4HEH?HM@E3LHU@H̺EH HMPHEHHM@E3LHU@H )荺EH3HMPHEHHM@E3LHU@H )NEHD HMP{HEHHM@eE3LHU@H L)EHHM@IHMaSHUIELEwHSu@8uwuH}HT$(H ؂TLEHT$(H0SD@LMHUHMRHT$ HMCTHD$ Ht@8tHFHc;HC HHHUwHSWu 9Ewy;xHC HxHUwHSl}wbH}HT$ HTjD$ H,D;[HC HHHUwRu 9EwM;LHC HxHUwHR@}w6H|$(HT$ HS?D$ H,;1HC HHHUERu 9E#;#HC HXHUHR} H]HUHSuuH,΋H;"L;PIU H;jH;H+I+HH;HBH+H;HIU(HHMILUHUoOR@H}oI4H;ZHUwK#RLHUwH RuyCH]Ht9H;9HUKQuLHUH QuCLH]H}gL?I4H($HA_A^A]A\_^[]IIIHL$USWHHPHU(PE(H] HU0H]P3E0HM8OHU8LE(HHEPu @8}(-HUH]H PHULEH]OHMD@LMHUNHMHUqPHEH@8HHM8NHU8LE(HHEZOu@8}(uoHUH]H Q~PuaHULEHNuLHMD@LMHUTNu2HMHUOHEHt@8tHHHP_[]H@SH HHHHH [@SH HT$8HNuD$8u HH [3HUHhHfAHxHUIxLpMpLxIMxNH$LEHuHUH,NHMH$L$HLMfA90{3ۋHtsAQf0f v\HFHxLEHHUMHMHUDNkHUE3MINPHH;rIIA IHEHUIQDD;MHUwIM}wIHMHUMEH,HIc̉})eH%XhHHT$`HL$xEuBLD$@HT$xHL$`Eu)HT$ HL$xFuE3LHT$ HVFHHt5~u/)eH%XA0HI<t3EHH\$hHt$pHP_HAHHHtrH\$UH Hٽ0HI Ht/{(u)D_)eH%XJH|t 3DHc H HH )L3IH\$0H ]HUATAVHHPHEHXHpHx LHHeeD)eH%XA@J4J&HEHEJ&3IN詑HHt9HH(Ht0HqlHg(E3HU(IHHM(HH HEJ&HL\$PI[ Is0I{8IA^A\]H\$WH A8HHyuZHQ Z uA8uA8HGXHA0HOXA8`<`tHA@A8࿃A8H\$0H _à <DC8`<`u$C8࿃C8uC8HGXHC0H_XHC@@SH A8Ht,HIHH`-c8C8@t࿉C8 tHCH3H [H\$L3HR@LHIRHIJPEZXHu3HIEuAHuI;xHuH\$IHJP9ZXu܉ZXH\$Ht$WH0HHHHT$ AI:Bu.HT$ LD$(H@uLL$`DHL$(H@H\$@Ht$HH0_@SH HT$8HAuD$8uHŒHH [3@SH HT$8H@u|$8u HH [3H\$WH@LE3HII@D8Hu 9H }TH@D8HtI;uMHHT$0D$0LL$8NVLHD$ HT$PHLH VH\$PHC(H\$XH@_HH먋C 9}H(yLQuB ЀuuLI`E3IJ@3G;33H(ÃH\$WH HHHT$@H xnZ@uHT$@LHH\$0H _H\$Ht$WH0IHLD$XH>u)8D$Xt3LD$ HH>uHL$ H?H\$@Ht$HH0_H#3@SH H٨u0u2N3HCxHHHCpH [HCHUHhHHD$PHXHxLp H:)H3HHHd$8d$@ )eH%XA@HHx)HD$8Hd)HD$@LD$@HT$8H+HHT$8HF)HT$@H2)HH [H(cHH(@SH H37+H6+.HȺ H [H%.HL$HH -).H)HD$HE3HT$PHL$HX.HD$@H|$@tBHD$8HD$XHD$0HD$`HD$(H׽)HD$ LL$@LD$HHT$P3.#HJ)HH)H9)HH.)H)H)H$H)ϼ) ɼ)Ӽ)HkH ˼)HHkH )H)HHkH )H)HHkH e)HLhHkH X)HLhH OHĈHxH )-H)HD$HE3HT$PHL$H,HD$@H|$@tBHD$8HD$XHD$0HD$`HD$(Hg)HD$ LL$@LD$HHT$P3,#Hڼ)HH0)Hɼ)HH)H)H)n) h)r)HkH j)HH NHx%2%2%2%4+@SH HHHHH [@SH HOAHT$0HD$0HHPHHH [@SH HHGHHH [HL$SH HT$0HHT$0hHHHH [@SH HJHHHH [@SH H"HHHH [HL$SH HT$0HHT$0HHHH [HMHH\$WH HHHntHջHH\$0H _H\$WH H8tH蟻HH\$0H _HHHL$ &HS(HL$ HHHHL$ cH(HL$ HHHHL$ H(HL$ tH=(Ht9tHHxu3H@H=HH9t9tHHxu3H@H%-@SH ,H [H\$Ht$WH 3,HHt(HHH\ PHt H-HH.Ht$8HH\$0H _H%%) H\$Ht$WH Ho)uH)H H(HuH\$0HHt$8H _@SH Hمu J }HcH H)H O HH [H\$WH ۴)yHO)H H(HuH\$0H _H(Hcu H H(O}H H)H H(H\$Ht$WH HHH H;tHHt-H&Ht4?HtHÀ;uH+HK-HHtLCHH H\$0HHt$8H _H\$WH HO HHFHK(HtC-Hc(H H@tHHH\$0H _@SH Hٹ:HD$8HtH)HHXH~)H [Hq)@WH0HD$ H\$P@3HL$@H=)HuN3HHC ?HK(H8oH)H HAH(-H)H")@tHHH@-HL$@HH\$PH0_@WH0HD$ H\$HH3HL$@%H_9HHGH Ht)HH@,LHtHHI,HuHO+HL$@[H\$HH0_H\$WH HH33(HH GHDHOHHPHtH3`(HHHHOXHDHH\$0H _H(HyHtHQHHuHQP3(H(H\$WH @8U83HD$8HHt8@HK(HSHHSS H@{$HQHMHHH\$0H _@SH =?)HuH k,)H)H [H(H Ht)HH@*LHtHHI*H(H(3HL$0 H q)H%d)HL$0~H(H%&@SH HAHHtH k) <GHNH[@Ht6H Ht&HH@$*HHtHH *H H [H\$WH HY8HDCHHC3)HHuHO0HtH轳HHuHg0HO8HtH蟳HHuHg8H\$0H _@SH H%P%C'HCHtf|%HKDB|HI@ A H0I0@@A@HPIP@`A`IHpIIHuC%cHCTHCHH [H\$Hl$ VWAVHPHcHHuH$DHDwHHuCw sHuv$uHGXtHuc$HHHGHtÈ\$yD$xD$z\$xD$yD$@H$Dt$8LL$xD$0AHD$(H3ɉt$ 5$t $ L\$PI[ Ik8IA^_^H\$Ht$WH !3HHDB,#PS#GB#G3HO H!& u533#tH֋HL:L:HƁ|H\$0HHt$8H _H\$Hl$ VWAVHPHcHHuH"DHDwHHuCw sHuB"uHG@4XtHuW"HHHGHtÈ\$yD$xD$z\$xD$yD$@H$Dt$8LL$xD$0AHD$(H3ɉt$ 5$t $ L\$PI[ Ik8IA^_^H%E3H% H%H(H)HuR#HHw)H j)H)HH(HLH D@HPSVWAVH8MIcH`HHHHx\$pxH+H|$`HIHW$D$ H8A^_^[H\$DD$HL$VWAVH@IALH\$pxI+H|$`HH#H\$hH@A^_^%"H\$WH HtH训HH\$0H _% % %r %^ %J %6 HHXHp HPHHWAVAWH0MEHH3ۉX؉X܉\$ A;}HI"HH|$PD$$H\$`Ht$hH0A_A^_H8HD$ n/HD$PH8%4% % %%%xH(MA8HIH(@SEHALALtA@McPLHcL#IcJHCHHKAt AHLL3I[HHXHhHpHx AVH IY8HMHIHILCdD[ADUAA#AAfDDEtLMHHDH\$0AHl$8Ht$@H|$HH A^%,@SH H[HHH [%J %%p ffffHL$L\$M3LT$L+MBeL%M;sfAMEM;uL$L\$HHD$(HAHI)HHHAHcPHmHD HAHcPDBDD HcAH+vHcAH+PvHcAH+vHcAH+wHcAH+H逬HcAH+HmHcAH+THcAH+Hx@HIHbbHHHHAHẢ )ٽ)̉ )É ))̉ ְ))̹)̸A ̸ HW̋AHWH̸@3̸H\$WH ADHًQtAXHAh3fH@TH`XHhHT$UH HHMXHtHH@`335HP鴢HT$UH H3T33HT$UH HHMxHMxH3 HE HNH ]HT$UH HE3HMp 33H@$H@TH@H0<H@H@HPH(ԡHT$UH HHMHr33HďHtHP鼈HpHHpH锫HpH鄫HpH(HpHH|Hp逭@UH HH=HH ]H*HHHHH@HH@H}H@HH@HH@HH颯@UH HE t e HMhH ]@UH HE t e HMX\H ]HT$UH HHMxHMxH3QHE H`H ]HT$UH HE3HMp 33 HHȩH鼩H鰩H餩HHtHHxHqHH@TH0qH0H$HpH鄨HhHlH`HTHHH0ĨHX鸨H0鬨H`頨HHhDHT$UH HHMXHtHH@p33uH(HT$UH HHMH蒙337HT$UH HHM@^33HT$UH HHMH.33HT$UH HHMP33HT$UH0HH˘33pHHH鄟HHdHH(HH8HHH餙HpȊH\HPH0dHhtHXTHpXH 鸥HPHPHHP|HPЛHP$HPXH餛HH(4HH`$H0dH0XH0LH0|H0pH0Ey LfhHfx,H@H"MHT$8HL$@gHH H,Ht$ L LMPHL$0BHHG55I5I8"HOIɃIHcH^HHIc ZIHIc GIHIc H4IHIc H!IHIcuZHUI4HHHF8AHt"HN`LEHMHMLu<H"HLEIHIHj4H_4Gm\\\\3IH/KH'KKeH%`H$HH0H )KHS'HS'AHMH1vHHMP AHPD'HMHvHHMP蓯HH MIH['HL$@uHHL$PHH HL$hK .1OIHqP'HMuHHL$@cqIHK['HL$xyuHHM=HH2 NDHT$HH]HiH,N00HD$HHtHgHÆLE3M|$(u)HHۆHD$0Ht$(Ll$ LL$PLL$@DD$pIHcE3LH-)I $|@M'y!IwhIgx)H@AItM$HT$HHL$XQcHHM(Hd$ L LPHL$H`>HH MIHdQ'HL$H*tHHL$x譭HH HD$hK.M̀{O0H<8O3H+OHyL M~L@T@tHpHOP0H<8$P3HcPHS8HK(PHK(opPMt*IXHC(MPLC IHPHk(PHL$(rwRIRNUAHB'rHHL$`HI HL$xf[THHHM|wWHOJAHM@HHMHfHHMZ HM@vLHUHHM`HHHEWAHoA'HL$0MrHHL$8HT$8I HL$`IYH6'HEHHEAHL$0rAHT$8H2ZHT$hHtLHT$0HL$@>HHL$@HI_XDXLML@'HpmHIqqcD$ A L@'H=mHI>q0AH}@'HL$@+qHHL$0HT$0IHL$hYHL$xYXH7ZH/ZZeH%`H$HH0H 1z)ZHMHu[HO'I2 \HMXt[H[HMXtH[HMHtH[HMHtH[HN'I/n\HN'IY\HN'ID\H=]eaLHUHM^HIHEHy]Hѹh]-^HT$@H`2`HT$PHbH|$P'bHT$@HndH\$@cvHH;'HMHMHDMHMdHMHMHDMHMdHMeeHM>SHM5sHH !eeH%`HH0H 4x)eIHkfHӹ4GffeH%`HH0H w)fIHjkgHӹIggHhHwHojH\$0E3ɉ\$(D3H|$ >Njh Hjj{kt)eH%XA0HI<k3H#kHL$@lHD$@HClHL$8lHD$8HClHT$XH 8LHH u)H;AnLInI@HPH H;u>HJD8YttL;@u HL:I@@I@HHDYIPHRm7D8Yt:L;u HLUI@@I@HHDYIPHRI@m@AI@HHDYI@L@L;u1LJAA9A nH$HD$(E3HJmHwnEE9P IHD$`A8xtMHFMA8yuIALH@@8xt(IHH;uHHL$`HI@8ytL@8xLDLL$`E9Q }=IAH@8xH$HD$(tE3lHmMAlHmE9P mMLD$`A8xuCI@@8xtI@%LH@8xtLL$` L;HuLHD$`H@@8xtLHD$`L;t E;Q imI@H@8xH$HD$(tME3lH1mAkH!m̹HAlL\HeU'Wy+HHhqpAqHM@gLHU,qAAAtiAt,ApIIL@HU@HMYpKH3HLLIIEDHHM@jHIHH@HHMtB >f pHI;rEHHM@IEHM@BpIIIIHH RL+II+HIHHHHHkHLLII@DHHM@HiHH0Af@oIIlBt9IHMHIBEHHM@hH0HeoEIno̺ HMD:qHMc <HMLpHd$ HL$@Lx)E3HWTFq3CLYsHH@HWhHtEHO`HHH;HHBHO`H;KHHBKHHO`H聐Ht.HA/' G̃g8G8@t࿉G8 tHGHHGx3H3HHH]s-r3;sL3II@HHI@PL9urHC(H;rrHr3,sD9{8tD{8H\$@Hl$HHt$PH|$XH A_A^A\HA(H;sH9QXssH@HHAHHCPHHHsH4'̃t\tIttIt%(tIP(I@ HIP I@(HBsIH蕄sIcQssAP8stt sI+sIHjsIHsIqsp$tKt6tIH8%%tIIIAHIAIIHAIA`HtIsIIIAHIAIIHAIIXAAAQ IIA`sIQPMH sIQPMHXsIQ`zt2z tzssMHbsMHQsMHϘ@sIQXzt(z tz&sMHsMHВrIzt(z tzrOMHgrMHڑrrIH$rrA@8HCXI@0LCXrIMHmrIztFz t/zTrMHu y:r*/rMHArMH rIHoqIMHB8u ޝq軡qMIHSq̹芹HH.'HMGLsHAHHuHAHHBHù{xi)eH%XA0HI<w3H#wHO`H踒驊HHHy H@1~ HH&H]y H^@:H^H1D9IX4HQPHB@H;HBHHtD9HXu`XHڃaXDJXLAHL;uLI@@HAHHtI@@HHPHAPI@PHtHAPH;H@uL@@ L@HMIH@HLAPHH؃aXHJ@DJXHAHHB@HtHAHHPPHBPHAPHtHBPH;P@uHH@ HHHIHQHHt D9HX8LA@L;uLI@HHA@HtI@HHHPHAPI@PHtHAPH;H@uL@@ L@HMIHHHLAPHH؃aXHJHDJXHA@HBHHtHA@HPPHBPHAPHtHBPH;P@uHH@ HHHIHQ@HJP閉Hh)LD$`AHE_)H`x)HH j)Ë̺HM 2t$HM0dLHU8HMOHH WHM[H=Nm)鎌̺HM1t$HM0dLHU8HMNHH 餎HMS[Hee f)eH%XH4A@I4HEHEI4H1HEHeEHEH1 HHEHtHE@HHHCLsHc3HEHD$(HHD$ LLHHM躐HUHt0HM脊LHHM NHMo^HEI4EHt H.HMJ^HEI4E3H DHuDuEDE qHU(HHNHHH3HVH QHKhǃ ǃaE3H DHGu eDAFEF ƎIV(HHMHHH3HUH 馎Lshǃ ǃ;gNz=3HL$0DB 課|$@HD$0H |$D龎&؎Lsh2͎DFDF QE3H CHDtHV(HHOHHH3HWH HHH2t=,t=u 3H/)HKh ȉ HchHspHqDTAFAEF 騐IH8.uHHLd$pD$(EMHD$ 3ҹHLc3Mu8pDAFEF d$tD$pHD$pIF*J<餏HHHCxHҏD|$(AMH|$ 3ҹHHFDF 饑E3H E@HltHV(HHOHHH3HWH n3HL$pA (LD$0HT$0HL$p蔿t!H H LLՑ3HL$8DB0׮K /LD$8HT$pHH@ "uHD$HK /HD$PAHH@K/H3vLL$ MLHH ̢WRHM]AH'HMHHM#HHMHM]M!I鐒I鈒I递AԒeH%`HH0H fb)HҒCI鼓HH p' AHH'HMMHHM%HHMlHHM`HM\HU (H׹ 鋓HM(\HU0LHL$@FHIMHL$`@顓eH%`HH0H a)H|$`eH%`HH0H pa)H|$HoH ]a)3H%LBL鷕AAL;ArD@fA@@fA @EJfff AɀfAAAf ʺ(f+fAJARDʀfAuv?ʺ$fA f+fHHI ?DA>tAARʀu1?fAfA fϕAf+ʺf;L; H!xH!xH!xH!x8H!y(HH@I!>'HHZ'MHHeH%`HH0H _)8؁HHHBp3HH+RZ'u HBH+MZ'HMHH+BZ'u HBH+=Z'HuHAHuHI I@+IH+{HK8Ht$1LK8IAI+AIIHIIHAIAHKIWH){(HH){ HC(@4HH|HK8He鍗HS8Ht$HJHBH+BHHJHAHBHK8eHCHHC(HC HC(@4HH|;0LiMerAA鐗Aߖ鐗r @82Ǘ ȗ@8ru@8ru HO])鬗H[])頗zu@8ru$@8ruH%])H])HCHC tH]) zuH])HCHC PztzjH\)HCHC '@8ru+B*虘M<$I$HD$0HD$ LL$8LD$@3H eAWFHGHXvXx̃tt H钙=/=t=t9=u)ݘӘ=t!=t=tH高願#ń镘鏘t t H˘鄘{$Pu/u!HdžPHFhdž鏘HHFh2MYeH%`HH0H V)H|$X鞘HQH8Q!I钚I銚I邚AԚeH%`HH0H V)H\$@fD/9HH[Q4HAQIyIqIiA黛eH%`HH0H -V)H\$H黛.M鄜HӋ0鵪HP>ѪHLHDH<陫eH%`HH0H 7C)H]隫AH=Hֹ-5HcH[HS鰬eH%`HH0H B)Lt$HH]麬f>AHIo!H,AHIJ!HH@!AHI%!HH0 A<$~>AH I H+tAHPI H`)A<$~=DHXI H+tDH I H)LEHUI`H0 H@ UA@鏸A@鈸H\H M)BDzJ)DJ)HD$`HD$`H{J)HHHHfyHHLDD /L 3Hku:f fD8@fH  #LD饭QHXDIH j HiHt$pH@齭eH%`HH0H ?)Lt$Ht$@ޭHH CL)jD I)DI)HD$hHD$hHH)EHHX铮wHXEЮDIH Nj)HHP?ȮHH K)ULʉ EDdݯLDDdA3AzDdAqD&wdLȉ wH@L$h 釯DIH jC~mHE3EH8d߅y MHXHgHg DH k!H =j}AH ;lI}HL$p?HM?PHh˪` ݮH` ȮHH J) ݮLH`DLjD(DAЉ` >0H+/HPL<7=\x! t#tHH+IcH;} H€: tHE8AOHHHAC IHHH@`3IH j#1}LL$XLE3HMFeH%`HH0H 5<)Lt$HDl$Xt$A韯LB;)LV;)@<qHHHǩAC HHH@鍰HgHHHHDžHfHXLIH۲IcH6H+HUHJHHLcIH+HHH+LIHLI+HMLALHLCIBH+HH+HIJVE3H訜HMH;靯H]HHHAC  HMHH@^Hֹ2H`HXHPH1H^VHֹSH鲰H骰H颰ݧ߰ѧH(4LH0HMHH]H HM/HM'HL$HHMK ,lHֹ鴰HnHMЅHDHMH XaH `IyHMQ;LePHM.IH &xH8HM_H@3HHaDIH R&xLt$ E3LH`HHHHMQ_Hu3HLHMHH]H HM?.HMHL$HzHE@J)I虈HLIH &wE3HPIH2cHEHU&HXLHH`wHEHHhLHHpPHHxHHHHM2^HV2HIH&H(HHH2LHHM-HH HEJ.eH%`HH0H 6)H|$`6eH%`HH0H 6)H|$X>eH%`HH0H 6)eH %`HI0H 6){̀{3)eH%XA0HI<3H#酲eH%`HH0H J6)gH$)H h]rL IH;˶LöHPH H;uoHJyu&@AICHHAICLXL\$8L;XuLHD$8HIc3IC@ICHHAISHRIOfyu#@AICHHAICLXL\$8=L;uLHD$8HINIC@ICHHAISHRI2AA A9LH$HD$(AIA1HH$(H %\hqLXILI镴HJyu&@AIAHHAIALHLL$@ L;HuLHD$@HI12IA@IAHHAIQHRIMƴLHD$@HIMYA A9I IHL$0AytIAHT$0HȅxSǃ%f-twu 0HPȅx"HHHs^H0H\$8H _@SH HQ`HHHH+A`HQ`HHHxH 6\ǃH0H [3H/HHHHHQHAH~HHQ HQHHQ@HAPHHHHQpHQXHQ`HQhHHHǁHfHZH0HHHHHǁǁ H(@SH HIHHuH! DHH [H\$Ht$WH H9IHHuHѹstH#-OHT$0suHT$0LHsuGH3Ht$@HH\$8H _H\$Ht$WH`IcIHEu3LD$PHT$XruHT$PHu$uшͅLAHʋH;BHd$HHd$@HL$HHL$0HL$@HL$(HL$XHt$ Yu$HD$@uHHtL$HH\$pHt$xH`_HHXHhHpHx AVH03IcALEu3|ExLD$ HT$(quH\$ Hu D$`ufA.̅H >H;s+LD$(~MpIHcHH4L[uuD$`ufB,6ËH\$@Hl$HHt$PH|$XH0A^@SH LD$8HT$@ q3ۅt3%HT$8LL$HHL$@A3L$HEˋH [@SH HHu HtH! 36HtLHT$0ptH#LD$@HT$0ypuHD$0H [H(HT$8D$8H(@SH H蒼u3 HT$8H譼tHD$8@ H [@SH HBu3HT$8H]uHD$8HH [H(;DH(H(LD$@yoL$@3҅EʊH(@SH HHT$@4otH# HT$@He(HH [H(HT$8n3Ʌt29L$8H(HT$SH0HT$P{ou1H\$PHT$HHL$ HHK跉HL$ MƃH0[H\$WH HHH;Ht 3HnH\$0H _HHH[HHHHHLA@SH yIHuH LH@H 3mCH [H!HD$0HAD$(AHDLIHQ ̊A̋@SH HHL$8llu8D$8tHL$@Olu HD$@HCH [@SH E3HALAHDD8tHHD8uL@HH [@SH LHT$0MHMH H [c@SH HALHTUUUUUUHH;rHL$X3H *@LT$XHICMJIL;uLPILI"EtMIL;uLMQIL;HuLPIBMIAHPH H;uDHJyt@L;HuHILIA@IAHHAIIQHR_[yu@AIAHHAIALH7L;uHIL&IA@IAHHAIIQHR.IAxCILHHHAH [LBIHBIxuHPHBI@HH;PuL@HBH;uLL@ILBHt$LL$ LD$WH HHHL;u2L;u-HR萀HH@HHHH@HHgHHnM;tfAxIu@IHyuHHHztIHL;AuLHL$@HIytHL$@LHT$0H%LL$HLD$@LHHt$8H _H @SH 3HAHAIE3fHHH [HHXHhHpHx AVH HzIHHI;s H (a=I+L;IBH;uJ|ML3HLOE3HaE3t=H~rH6H{rH HHnL^LH{H{rHHfD4xHl$8HH\$0Ht$@H|$HH A^@SH HHHKHHKDHHxHH [H@SH HكAu)HHzmC uHHH@]mH [HL$WH@HD$0H\$XIHHaAaH:HHg Hg0D$(Hd$ E3L3HHH\$XH@_HPHL$SH@HD$0HHS:HD$(Hd$ E3E33(HH@[HPHL6HM'@SH HH@QHK8HtE3H+HHH [@SH H!HHaLBHMtA@HH [H(HIHtH(@SH0HHL$ HSL@HPLCHLHHL$(LHtHH0[H\$Ht$WH HIHIHHtH3Ht$8H{H\$0H _OH(H HtH(H\$Ht$WH H3HOHH@Xju!HOHWhHH@0j؅uhuHOHHBXjHt$8EًH\$0H _@SH0HLD$PHHT$PHL$ WD$ jtHK HD$(HC HD$ HCHtv8vHD$PHtHvWHL$ HD$ 8.HKHD$(HCHD$ HCHt$HKHSHH@iH0[@SH HH8HHIHcHcHtHK Hc HcHtHKHE3/]HK(E3!]HK HtHKHtH8HH [H\$Ht$WH HHH+YXHH5DxHGXH XAHH\$0Ht$8H _HL$SH0HD$ HHHHKH0[H@H@SH H7HHHIHtHK0HtHH@=hHc0H [H\$WH0d$@HHA LALM+trIH+yHI(Ht$LK(IAI+AIIHIIHAIAHKIfH){H){3HCHH|HK(HtYRL;QtLHQ(Ht$HJHBH+BHHJHAHBHK(HC3HCHCHCHH|DCD+CHK(AHt!HK0LL$@HSHH@gDx3HK(HtbL$@uDAHK3HCHH|AH\$HH0_H(H5HHI Ht`H(HAH9A t HAfQ(HA3fH\$WH yHHv,H LËWL+IL+MHQ eOHH+كgHH\$0H _H(HAH9tH H(H\$DI E3D;IuA ;HAA;AAAM‰A AIAAAB! tF H\$AHL$WH@HD$0H\$XMHH (HALAxu AL;P }AHE2H@xtIEtsL; u)HD$pHD$(AHT$PHHGHAytIY8IxuHH@xt IA H;u HH@xt{HDA9C }#HD$pHD$(HT$PXHHGHHT$pHGHH\$XH@_HT$UH0HHUp33A@WHPHD$8H\$`Ht$hMH@2L MAA8puMA@ A9}M@M@IH\$0@:HL;u,H$HD$(AHT$@,HHGHA8qtIYHHH=HHHHHHHBHAHH̋HBHAHBHABAHB HA HHJIB A ̋HBHAHBHABAHBHAHHJIH\$Ht$WH Ht+HyLL <@tH%HH<Ht HH\$0Ht$8H _HAHHH\$Ht$H|$UHHPfAs AIxHUIpHC\t (H]LEHU(H6u8E(tVH{@t&HC`LEUHMHEHCPH}x`HkMHU[uHUH}[u+BH{Ht HC(LEHEHMHCH}"`LEH&EHEH\$`Ht$hH|$pHP]IAAeH(DLA@AtjAtTAt>At(AtAt At63IHcʋ >IHc H.IHc HIHc IHc HT$0Z*IHcAuZHT$0ZtSHD$0H(HUATAUAVAWHhHHEHXHpHxfAs IxIpHUHYE3t K&H]LEHUwH4uD8mw`Duυt(D;s#AHfHMHL$0LE333PLKHMuL9k8uLEHH'<AMLmDm e(eH%X@DL$I HMHEIHK`HMH}LEAHMI]HUHWYtHMK <,uHEKHE/HEK>HYHUHuVH}HGXHt#HO`HMH]HUHMZHHM!HUH@t!t "HG Ht#HO(HMH]HUHMZHHU"HUH@t w!t K|#HUHMHMHUAHEHD$ LEHz7uHUHM>tmHEHM/K >L$I[ Is(I{0IA_A^]HhIAA)IAE3 HUVWATAUAVAWHHHEHXEfs 躟HyHqHUHTE3t !H]LEXHUHHG/uD8eHUDuXtD;s y$gL9cHLeDe `(eH%X@DL$I HMHEIHK`HMH}LEAHMXHCHXHUHH'tQ }Hu#HHEKHxuHBH@@r1IAAHˈBAAHI@ABIHCHtHHCHD$@H\$0Ht$8HHH _̋AHH(HT$8Gt2|$8H(H(LD$8HiL$83҅EʊH({@SH HHL$@LD$8HHFL$83҅EʊH [H(LD$8HT7L$83҅EʊH(@SH Do(HeH%XA@J LHJ zHH [@SH D(HeH%XA@J LHJ HH [@SH HHT$@FtH# HT$@H襛HH [@SH H,HL$8贚HD$8HHH [@SH HH,HT$@JFtH# HT$@HHH [@SH HHT$@$EtH# HT$@HHH [@SH HBH,HL$8胱HD$8HHH [H H%D@SH HBHH#H [H\$WH <(HeH%X8HHEHEI>tH#DHM(HUuLE8LMعH9HBH9HML>uHUHHEI>HH\$pHPA^_]@SH Hd$HAHLD$H tH# HT$HHHH [@SH HHT$@tH# HT$@HHH [@SH HHT$@=tH# HT$@HuHH [H(>H(H\$WH0H!HHaHT$@HHzHHt1HHcHOHOd$ E3AHHHHH\$HH0_@SH HHH#H [@SH E3HkHHvHH [@SH@Hd$8AI!IHd$0Dʃd$(LHd$ 3ҋ:uH3H@[@SH 3HT$8\$8Y<L$8EˋH [H\$Ht$WH HHHHH@AHHHtKH@AHHHAH{ADHL$8H#HHHWAHD$8HH?AHH\$0HHt$@H _@SH HtHH [H\$Ht$WHPIcAHEu3ExLD$@HT$H;uHT$@Hu$üȅHڍ H;r+HL$H~H yHd$0LHd$(E3H|$ ]u$u3ËH\$`Ht$hHP_eH%X (H Ȱ H\$WH |(eH%X0HH ;:t2H$;H\$0H _H(:H(@SH eH%XHT$8HA0 (H J O:uHD$8HH [H@SH HRHH#H [@SH HHH#H [@SH H蒺HH#H [髻@SH0HHT$PH g9u_HT$PLD$HH8uH8D$HtBHT$PLD$XHy8u+HL$XHT$ 9uHD$ Ht H`H @H0[H(@SH HHHHT$@8tH# HT$@H߃HH [@SH HHHHT$@8tH# HT$@H蟃HH [H"HH(3HtHw IHu H(@SH HHH [ H\$Ht$HL$UWAVHH@H3HAHU MI7up} uhHU Hl7uY} uQLE8HHUq7u>LEH]HUHX7u%LEL9E8HULGE8HM);A3H\$hHt$pH@A^_]@SH HHHtHH [@SH HKHHtHH [H\$Ht$WH0DJ(HeH%XHJHH;uLLc{HH {6u&݁H HT$ AHD$ LHt$(P5H\$@Ht$HH0_̋ (eH%X L LI9t3LJHH JH%+6H\$WHPEHD$HL$ED$HHD$0HH$AHD$(AH$HD$ |u%LD$HLL$@HH5u 8D$@uH\$`HP_LSH@HHHIS85u4Hd$8AHd$0EHD$xHH$HD$(DD$ H@[H\$WH0HIHLD$(HHT$X4u(HL$XHT$ J5uHT$ LE3Hr5H\$@H0_H\$UVWH@H(H3HD$8eH%XH(H`HHHL$8HL$8H|$PHCL$8HoE3HL$8" HSHL$ ~HL$XH3H`[H ~H(iHuHLӮH(@SH HMtMHD$pD$$D$xIHT$PIH@ t LGLIxrMH ?&HL$HHtPHL$8Ht@ƋHGH+GHH;h3HH3zL$I[0Is8IA^_]H0ʨH@龨HAVHPH@HXHhHpHx EAHH8 HHD$8Ht"H `H`H`H` H`(`03H\$8Hd$@H HD$HHD$@HD$(H\$ EDHHEt H 8D&EHHL$@tH D&LL3HL$@fHt2HSHt!LCHK!HcHcHc H H\$`Hl$hHt$pH|$xHPA^H8-H8H@HAVH@HD$ HXHhHxH\(H3H$0@L(eH%XHAI HuH }M&HH@I$AA<uA@uCHOHE3LHT$0ryiOLNjPH M&'HL$0DH$0H3L$@I[IkI{ IA^H0靥HHXHhHpWH03@*Hf)HHHA3I8 u+dLH :&{M~< 2ȍHvH4OHHO:&|uf.H3H\$@Hl$HHt$PH0_H\$Hl$Ht$WAVAWH@HIHAH!D$(IHd$ EL3ҹ_ Hcu2LH ;&s E3AFHI@HWHL$0EHD$0cHNHD$8HFHD$0HHt褢HEωl$(L3HD$ ȅWH$3H\$`Hl$hHt$pH@A_A^_L$LƋHtLH ;&HUAVAWHHpHEHXHpHxEHL33؉E8utH =&XJHeHM{HMJt H =&GHH9AwDHMHDD$ DNMH@tH =&'Hee P(eH%XA@H&EtHMtH W>&PHMgHMHMRHEJ?$HMHH@(HM@x-L\$pI[ Is(I{0IA_A^]HAH0HXHHH8HWAVAWHpH@HXHhHpAIDLH 0&7HHD$`LLT$hHuH q0&.Hd$@LD$@Hu/H 0&؅؁zHd$HHT$HH`؅uHd$PHT$PHL$@E؅t}H L0&0HHD$HHD$0HD$PHD$(Dt$ ML0&HHt HL\$pI[ Ik(Is0IA_A^_H`HUWATHxHpHD$0HXHpH(H3H`HAE3H@yH`=&HD$ LLY=&AH@:؅tLNjH @=&l\H@ HHuL@3H =&gW5HHHd$ E3L@HT$@8ty#_HHXL@H =&H}3H9uIIB|uHHK H|$ L@L=&IHPC tLL@H =&XGHE3LPHU@zyGLPPH 8>&cHH<uHHHM@HcH;E53HL$@H`H3L$pI[(Is0IA\_]H@鱝H@饝HUHHpHEHXHpLp HB(H3HELWEHeHQ(HM芗HMH]Ht HUHH H]E3HMMH9]twHsHHMH9]tE3H#HuHMH}HCMMHUtLEH}LCEЋH /&E3HMH]H}t"LHUHM茎WEHe3HMH3}L\$pI[Is Ms(I]H H@H@LWHHD$@I[HՍ(H3H$pHHH"3A IAH$`Hz3AH$PHd$8Hd$0D$(H$PHD$ AL$`3ҹ7uuL$`H )&xDHE3L$PHT$Py&DHXH *&MHL$PCH$HX(HL$PH3&H (& ~ H$pH3H$HĀ_HP銚H(H3H HtHHH@H(HUWAUAVAWHHHHD$`HXHp H(H3HHHi9` Е(eH%XL4ȸJ<0tH D<&?33+؉D$HAAAutH <&AMAMNjH.tLƋH <&3A HL$p2D$(HD$pHD$ AM3ҹ u78LD$pH 2=&ME7Hd$0D$(D$ E3EAAHL$pLHHD$PH HL$XHu5LH 9=&HH =&Hd$@HT$@H<t8 ;uMH =&vHFMNjH 2>&]HL$@:HH >&'HD$@3HL$@J2û\$HB23HtHd$@HH@ HL$PxHH 9&WHH3L$I[@IsHIA_A^A]_]HH HP鋘H@3H\$UVWAVAWHpH(H3H$`H$AH$ELHHS(H<uHˉC0FtH )&F@t3H=Lt"DKI@M@HAHDKI8uHL$@D3aDLD$@AI؅tH )&3H$PA H$P|$(AHD$ LD$@3ҹu#H )&_Hd$0H$PD$(E3E3D$ @[HH;t HHHHHv3+H *&LD$@~ H$`H3H$HpA_A^_^]@SVWHPHD$0H(H3H$@IHH>HE3LH$@~yu>HXH &&*H$Hf#ȸ@f;tWH N&&Lk->HHd$ E3LHT$@iy >HXLNjH k&&"Ht$ LD$H$HXHL$@XH$@JH$@H3HHP_^[H@H@HUVWATAUAVAWHl$H`HD$ HXH(H3HEPMEHLH3HM@HMHHEHHM@M0H]@H;w+H9UHt%sLHM0I3H]@HE0H}HHCE0 DEcHHM@HE0H}HHCE0A8uL LIC8 uIHM0TAH#&H??uE3 LIB<uHHH]0H}HHC]0QH]Cf#@f;uI:.HqHt0H#&HuHCHHFHNHU0dHHH<uHHHL$0DA3E;s7;HXLE0H}HLCE0H "&PHL$0E3HM0HMPH3H$H`A_A^A]A\_^]H0JH0鮑H(Ht HH@H(H8E3HBH=AWEGEx MDHtAH8LD$LL$ SVWH 3HBH=HWGx5HZHHLL$X3xHH;wu@<3@<3zHtH _^[E3MHt*L+HtE EtD HHHuHu HAzALWHPHD$ I[H (H3H$@HH93AIAL$0H؅tLNjH 0& lG9HE3L$0HT$0/y)&9HXL$0H 1&H3HL$0膷HH /&WH$@H3pH$pHP_H0?H\$WH HzHHsLBIt-HtHHH"HCHGHCHGHcHCH\$0H _H(HtHH@H(HI雀I;t0H\$WH IHE3H蚺H H;uH\$0H _@SH HHHH{(3҅tHSHH [HAVH@H@HXHpHx HL3H|$XHt.HH;wHHHHD$XHuLIVIMFIIH+Ht IHHI^HHIvI>H\$PHt$`H|$hH@A^HT$UH0HHMXO33H(HQLAHI+HHsUL+IIII+Hs H 6&H+IHHHL+L;s3HI;IBH(HHXHhHpHx AVH HBIMHHI;s H GHII+I;HBHH+H;w H 8KHtVH,9E3HHt@H~rH6H{rH HHKJ6LFH{HkrHH(Hl$8HH\$0Ht$@H|$HH A^H\$Hl$Ht$WH IHHBt%H{rHHH+LLHHpHKHH+H;w H NaHtKH,9E3HHt5H{rH HHKLHgH{HkrHH(HH\$0Hl$8Ht$@H _@WH0HD$ H\$PHHHAH;s8H9w3H+9H;AuHH;HKHL$@HL$HHt H`'H;AubHKHL$@HL$HHt H7HC H\$PH0_@UH HHU@HMH舃H ]@UH HHU@HMHlH ]HHHAVH0H@HXHpHx MHHIH+HHqH;w+H9Qt%A3ɄtHsH{rHHf pI;tDH7 HH\$HHt$PH|$XH0A^HT$UH HE3HM@33%HHPWH0H@HXHpHH @HHD$XHt%HTHCC HHHs3HOHt誇H_H7H\$@Ht$PH0_HX+HT$UH HHMHz33n@SH HHHtzHH [HHXHhVWAVH@IIڅu!PL@HR;|9u yuyt3d$(+Hd$ DLc3LMuH 5Wd$hLD$hL΋HT$hMHl$(L P3LL$ DHHL$0H)3H\$`Hl$pH@A^_^HUAVAWHH`HEHXHpHxMLHWEEHeLEHUEtDHH YH]WEH]HtCH]LHUHMۇUHM7tHH ݲe8LM8LEUHM,tDHH MHUI.E8A3Ht H!HMHtL\$`I[ Is(I{0IA_A^]HP†H0鶆HWH@HD$ HXHw(H3H$0HHg/HE3LHT$0TyK/HXDHH H$HHH 3HL$0設H$0H3覸H$`H@_H0uHUVWAVAWHH`HEHXHw(H3HEHcHHMHH LE3HuHNHt较2HHL}L}HEL}fD}HXLIHMHH?H+HJHHLcIH+HHH+LIdLHLMI+HI BLEH}LCEHI+HH+H-E3HMHNHtHMH3IH$H`A_A^_^]H(靄H0驰H\$Hl$Ht$WH0D(BD(3AHAIIHMEHH@HjWHL$ DHD$ =HKHD$(HCHD$ HHt*H=&(L(LC(L (H L (L(H=(LC(I+HIQHH HHH\$@f,H(Hl$HHt$PH0_HUVWATAUAVAWHXHpHD$XHX Ht(H3H`MLLHT$@s33L|$@IcHD$@H2WD$HDHHL$HEHD$PIL$ID$HD$HI$Ht+HH|$(D$ E3MHT$`蝭߅y +HX$DIH [6HL$`HL$`کI$@+HH|$0H|$(HD$@HD$ LDHT$`蹦Hc؋υy +HHI;tNDIH *HE3DHU`踥y*xHM`SHL$`H@HL$`:*HE3DH`oy*M}H`3H`H3H$HpA_A^A]A\_^]H`ʀH`龀H`鲀H`馀@SH L2LɃ|8A8#u2Ax!u+A< ttIHcI+ H;} A LA8 uIIHt~H [HHXHpHxAVH0` MHL@ 3H؅tH 0&:lL$X3蟢WHL$ DHD$ fHOHD$(HGHD$ HHt_~HLD$XH"؅t H 1&뒋D$XA3H\$@Ht$HH|$PH0A^IuHyrH fD QHyrH H QAs@SH HHHHm(轺3҅tHSHH [@SH HHHHl(}3҅tHSHH [@SH HHHHl(=3҅tHSHH [HHXHhHpHx AVH HHHIAH+HH;w H -E3HtAH4E3HH"t+HSDLHH{HsrHHfD4pHl$8HH\$0Ht$@H|$HH A^H|$LMt HIfH|$I@SH HSHHtoHH [H\$WH HtHSoHH\$0H _̃yty t ̋A8̋A8̃yty tVA8tD$HId$ HD$HAA8u D$׃yuME3 A8tD$HId$ HD$HAA8u D$׃yty t yuSE3閘̋Q8s1yidQ8u$A<@u⿉Q8 tHAH3B8LLRLud$D$$HD$IBHa AHQPLAXr8AA`R8IAIdAAAdu@u@AQ8 tIA@IR(HIKHHHISH AA8uAA8IBXIA0MJX3HHB8LRud$\D$X$HD$XIBzthz t@ztA&'AAABEB HD$pHD$(DL$ MLHIHHD$pHD$(DL$ MLHI&HD$pHD$0Hd$(DL$ MLHIHHHHB8LRu D$X$/ztA&'AABEB uD$Xd$\HD$XIB*HD$xHD$0HD$pHD$(DL$ MLHI腖HHH\$Ht$WH H*(HH;t43HHHAHwHHcHrHH\$0Ht$8H _@SH =(uHH ("KHHuHD+&HHHH [@SH0Hمt|3HK@LL$@LD$PD$ HT$HHT$@HtHH[H0[s=tfH*&p@SH HH8HK0HKH [H%%H\$Ht$WH aHىH.3HK0uHK8Pt&HK0HKH\$0Ht$8H _3H\$Ht$WH HyHHCC;uHK8HK0HHs0HHhHOCuHHK8HHGHK8HK8H\$0Ht$8H _H\$Ht$WH H=r(HtHr()H3HN9t HN8lH\$0Ht$8H _@SH H=br(Hu4HI8CuHK0.uHK)H [H\$WH !HHBE3E333"HC0Ht%E3E33AQHC8Hu"HK0HKH\$0H _3@SH =c(HuHGH P(Htq(HHt3H [H [8H\$Ht$WH H=)q(HtH]q(?)H+3HN92t HN0H\$0Ht$8H _@SH 3WH9p(I*tJMyXz^JHp(L,u~=t̃H [MyX0^L,H [QH(AH=0p(tH_p(IutH(LI[IkIsI{ AVH0HA0HiICHHA8AHICLH7IDHT$ E3NH͋;u?t3Ht HO8UItru 3H\$@Hl$HHt$PH|$XH0A^H(F3H(H(H(H(9uFH(@SH H=n(HuHK(H [@SH =C}(HuH'H 0}(H=Kn(HtHon(iyHK(ocP3H [@SH H=m(HtHm(H [H%CP{Pu HK(HH [H%@SH H=m(HtHm(H [H%CPu HK(HH [H%H\$WH H7m(HHtY2/u$9CPu HK(3uCPH/H\$0H _H(H=l(tHl(H(H(H(H=l(tHl(H%H(H%H=`l(tHl(H%H(H%H(H #uH(@SH HE33AHHH [H(H E3APuJH(H(H 3uH(=uH(H `tH(@SH HكH +tH H#3H [H\$WH HYH9)HHH\$03H _HQHD̃ RtDtEt:t&tt"t uG@øø@øHøXøÃ tGt<t1t&tttHøøXø øøøøH(Hk\3ɅH(H(H\3ɅH(HAH̋A8 u A8u @tHA@̃t@t5t*t+t&tt tHøhøøø`øPA83LMt89t HHI;rI;t#II;sL+A t HHI;r3Mt&MHMtH+D EtDHHI;rH8y u%f9uDHLD$ D$ d$DHID$@HD$@HAH8HHy u9AfD9u-EJBJLD$ A)D$ L$0D$8裰d$THID$PHD$PHAHHH8z ufA8uALD$ D$ {d$LHJD$HHD$HHAH8HHz u0fA8u)AA@AHLD$ )D$ L$0D$8вd$\HJD$XHD$XHAHHH\$Ht$H|$AVH0LIHHHu;Hd$(L}d$ L3H03HxIHu H3H\$@Ht$HH|$PH0A^HHyu*f9u DD$ DHLD$0D$0 d$THID$PHD$PHAHHHXyu>AfD9u2EJBJADD$ LD$0)D$0L$@D$Hd$dHID$`HD$`HAHX̃yuHt M$d$ HID$HD$HÃytd$ HID$HD$HAHHzu/HD$pf8u$HD$xHD$(HD$0HD$ D$0d$\HJD$XHD$XHAHHHXzuFH$f8u8H@D$HH$HD$(HD$0HD$ )D$0L$@d$lHJD$hHD$hHAHXH\$Hl$Ht$WH HY HyIHH;?tHKA8u HHH[H;uH\$0Hl$8Ht$@H _̃HHXWH HHMuD!@@H@HAtHJ LBXH!BHZPLJ`3DB ݰAH ^HuDqCDC HS(HHOHHH3HWH H\$0H _H\$WH HAXHHyPHO@LK E33upH&z 3H\$0H _H\$VH@@HȺ HuHqHd$8AHd$0LÃd$(3Hd$ HctH&Hr(HuH&H Hd$8AHd$0LÉt$(3ҹHD$ IH˅uH Mr(Y3H\$PH@^H\$UH$H`HV(H3HP3HuHD$0HD$02HD$@D$(LHD$ A3uDzu#HD$01HL$@ZuD>D$0DD$4HT$@3HtH=vHD$07\f|D>\:u"Huf9T$Bt"HH Hs/f\ @Hr*f9T$Bu#L$@AfvAfw>f 蠛̋ft+=fL$2T$4HL$0HT$@fD$0'HHPH3ϖH$xH`]H\$UVWATAUAVAWH$PHHBU(H3H3HT$`@85Rn(HL$huH4 H =n( HL$p}8DLHu!t$DD$@kHHud$DD$@HLL$\H^(DùyH^(E3 LnI^D$TDD$PL &D|$ HM HD$@AE3HD$ HUHHL$@HD$THD$(H&HD$XE3E3HD$ HL$@HD$PHD$(H&HE3E3HD$ eHL$@JD$XIKY8m4DL$PCIImAH HH?HIHIMI+MHH HH?HIHSImH HH?HIHSLImH HH?H3HD$8HD$0HS 3҉D$(HD$ HCD$HHHcrHCHHd$8LL$H3Hd$0DL$PL$(AHD$ HCAHcL$HH8I0D;HHD$`8HD$hL0HpHH3聓H$HİA_A^A]A\_^]hDHL$@D$HDD$LH\$H=DD$@DD$DH\$@tIHmH8IuIZHQHYH\$Ht$WH HcH~HH H[8HuHH\$0Ht$8H _H%HxH=Q(H3HD$`HL$ D$ @"HL$0HHDHHL$`H3KHxH\$WH =j(HHuHH i(H }g(7Lk(Mu>u-H Zg(,DdD$@DD$DHD$@*Lk(LHH>H g(HzH\$0H _HxH-P(H3HD$`HL$ D$ @HL$(HHDHHL$`H3;HxH(=i(uHH h(H=h(u3BHL$07tHcD$43ҋL$0Hiʚ;H5h(3LHiʚ;I H5h(IH(HHXHHUVWATAUAVAWH@E3LDxAE3H9HσW$HHLH$E33HD$ 3^uEIHHhL9LGHAL|$83L|$0D|$(L|$ HHHGHDŽ$H$yt-t&$$HDŽ$HtE}HvHDŽ$H@AH(HuHHHHHu;HwOHi D$D$.LIcHH Lt+|tt3,"%,*- 3@SH HH̲HcHShHu $H [H\$Hl$Ht$WATAUAVAWHPIMIE3IHHHfD9IV(HHMHHH3HUH !HHMXAQ EhHl$0Ht$8H|$@H A^Ht$WH LL$XAHH\H|$XtPE3H . HUusDFDF ;HV(HHOHHH3HWH HghHOXAQ GhHt$0H _H\$Hl$Ht$WH AIAHH[HtPE3H p HuD3EDE >HU(HHNHHH3HVH !HHNXAQ FhH\$0Hl$8Ht$@H _H\$Hl$Ht$WH AIAHH)[HtPE3H HǕuDcEDE >HU(HHNHHH3HVH !HHNXAQ FhH\$0Hl$8Ht$@H _Hl$Ht$H|$AVH IALL$PA HLSZH|$PHtQE3H HuDAFEF >IV(HHMHHH3HUH !HyHMXAQ EhHl$0Ht$8H|$@H A^H\$Hl$VH0LL$hAA )t$ (HHtYH|$hD$`tPE3H HuDEDE >HU(HHNHHH3HVH !H4HNXAQ FhH\$@Hl$H(t$ H0^H\$Hl$Ht$WH0IILL$`AHHX3LH9D$`LHHD$ EUyvH|$`tME3H H u+DEDE HU(HHNHHH3HVH !HHNXAQ FhH\$@Hl$HHt$PH0_H\$Hl$Ht$WH0IIAHHW3LHHHE3ɉD$ \TysHtME3H H'uEDFDF HV(HHOHHH3HWH !HaHOXAQ GhH\$@Hl$HHt$PH0_H\$Ht$H|$AVH0EILL$`AHHV3LH9D$`HHE3ɉD$ tSy}H|$`DtME3H H5uSDFDF HV(HHOHHH3HWH !HHOXAQ GhH\$@Ht$HH|$PH0A^H\$Ht$WH0LL$`IAHHU3LH9D$`HHE3ɉD$ }RyvH|$`tME3H HEucDFDF HV(HHOHHH3HWH !HHOXAQ GhH\$@Ht$HH0_H\$Hl$Ht$WH0IIAHHT3LHHHE3ɉD$ QysHtME3H @HguDFDF HV(HHOHHH3HWH !HHOXAQ GhH\$@Hl$HHt$PH0_H\$Hl$Ht$WH0IILL$`AHHT3LH9D$`LHHD$ PyvH|$`tME3H VH}uDEDE HU(HHNHHH3HVH !H;HNXAQ FhH\$@Hl$HHt$PH0_H\$Hl$Ht$WH0IIAHHS3LHHHE3ɉD$ OysHtME3H pHuD3FDF HV(HHOHHH3HWH !HHOXAQ GhH\$@Hl$HHt$PH0_H\$Hl$H|$AVH AALL$`AHL3RH|$`HD$PHHD$XHtQE3H Hu·DLAFEF >IV(HHMHHH3HUH !H HMXAQ EhH\$0Hl$8H|$@H A^H\$Hl$Ht$WH0IILL$hAHHDQ3LH9D$hLHHD$ MyH|$hD$`tME3H HuΆDLEDE HU(HHNHHH3HVH !H>HNXAQ FhH\$@Hl$HHt$PH0_H\$WH QPHHyX jt^tOt@t1t"t!Ku WJIct@t1t"t6 NJtAt5t0t$tt u]VOeHAo:3t)tttuHahE HO@LK E33(u΄H%3H\$0H _H\$Hl$Ht$WH0IIAHHN3LHHHE3ɉD$ LKysHtME3H Hu5D賽FDF HV(HHOHHH3HWH !HHOXAQ GhH\$@Hl$HHt$PH0_H\$Ht$WH@LL$xIA )t$0(HHM3LH9D$xHHE3ɉD$ eJyH|$xD$ptME3H Hu2D谼FDF HV(HHOHHH3HWH !H:HOXAQ GhH\$PHt$X(t$0H@_H\$Hl$H|$AVH IALL$`AHLLH|$`HD$PHHD$XHHtQE3H Hu=D軻AFEF >IV(HHMHHH3HUH !HeHMXAQ EhH\$0Hl$8H|$@H A^H\$WH HHHHtHuC8uC8HGXHC0H_XC8`<`tHC@C8࿃C8H\$0H _@SH B8HHHtHHHt\HHHtBHHK@Ht +Hc@HHtHHK(HC HHC(HK HAHCHK8HHt HH [@SUVWAUAVAWHpH(H3H$`3MH\$@HH!\$(IH!\$ EM3ҹ׃LcIQHHuHJ%KIEDt$(M3HD$ uD=DE EAH-Zt HLfAHT$PH(.LHHT$@hL3HL$PMH\$@HLx3Hd$0E3D$(BID$ EyAEAaHHt H4HI;HU@E3LHt}AAcHHuH%H3H_hHDB ?gHd$8E3HEHH\$0Hd$(D$ "4~HO@Ht {Hg@HHtdHHHtJHH9HI;t ~LHHtH/] D3H$`H3~OHpA_A^A]_^][@SH HJLQBHJ B8 HIHHHLR(I IHHHHHLHbhBP HRHaHC@HuH1%H̋C8@u@C8 tHC@H [H\$Ht$WH@HrhH3HHDB OeHd$8E3HAHHt$0Hd$(D$ /}uQE|;|3| HHOHHHaHHCPHtH@HHAHHCPHHHHIHHKPH\$PHt$XLJH@_H\$UVWATAUAVAWHPA@83ALIDͨt A@8IEXI@0MEX{B MH9j(HLHuXEFIV HI9t EFIV HIMHHuHA=AF5HHf9,KuAFHc艄$H mHD$@LHIF LHD$(L %HH\$ I $3E3Hc3fA,LI{Hc؅t?HHHHDHIztHf,F H~HIrHtFLD$@3HH΋SHl$@3uAHD$ D$HHuEfIn AD$D$3HHD$8EHD$0LʼnD$(3ҹHD$ 9}؅t\@HcL3MHD$8EHD$0Lʼn\$(3ҹL|$ |3tHB,8I|L3AFt-v tUv!wAHE3IHI7HL+HAG8QAH%赽H%製H%葽E3EA(HV(DޱAEE E3AEH3HeG8u HIwuG8IEXHG0I}XH$HPA_A^A]A\_^]H\$Hl$Ht$WATAUAVAWH HMHE3HLHfD9,iuHcŋH A~Hf9\tf9/uu_HtH ЁHHuH%H聼HйyuHL/II$HtEFLcK ?lHHuHe%HHcMLIHHfD,X+HcH ?(I$HHuH%Hջ̍EHHcHcLHMFPI$fD,X3H\$PHl$XHt$`H A_A^A]A\_H\$WH0HHXHu#HKH8H=H\$HH0_H{htg9`d$DLL$@L !(HpHD$@HAHXHx؉``HtBx'HG(H9(uHGH9u Gf9tHxLL3OG  O00ǃ`HD;} D;ua:HYMt:HIu"uA;tQu}uFu }t8FLHUH+Lh%HxHcHIAIIx*LEHL+IM uYIIH<uHA;t>u:HHEH+HI;v H%HMLEI^xH~HMH3AH$HĐA_A^A]A\_^]HHXHhVWATAVAWH 9Lp33XLHL%%IHwHt3A A+ȅttQwIAu%Ã;.u/t+t&I3A}u|D$PAH}H%H\$XHl$`H A_A^A\_^IL҃ttH%MHIMHIH(HALIpƁE33HH@ou,nHC%6H(H\$T$UVWATAUAVAWH0H|3E33E3MLHH91t9!l$(AL3H!l$ qtcLH;HGHAH9/uC$HcN$yO<$IwHHuN!l$tD$pH\$pHwHwHOmDͦD$pDD$tHD$pH 6xwHHu!D$tHMIH+AH3HD$(Hl$ pDo|$xt%HIH+LHH+HuAGH4FHMH+HHHL+HIO<$IHɃ fHI>_HvH9{I}H$H0A_A^A]A\_^]H\$UVWATAUAVAWHl$HH'H3HEE3HE H%LHHEH%AHHEH%LeHEH%HEH%HEH%HEHE LeHELeL9!tkL'Lu3MFII ttHI H| HDLE3Dd$(A3Ld$ o~gHHLL9'uAH]D9cu!H E33mt:HKCHLH HcHrK ?3uHHu*HEjDIEDEHEH=LAHAH+3H+D$(H\$ InHHHCL9&uEHuD9fuGLHH+IHHH+jsHFDFHHC=HfClt[FHCAH IcHrHxfD#I}HMH3;H$HİA_A^A]A\_^]HtiH%ƮLI[IkIsWAVAWH@$IL$IL$HHt"MsHM{IcICHueLt$8H%L|$0LHD$(LHHD$ HlHu0Lt$8H%L|$0LHD$(LHHD$ H7H\$`Hl$hHt$pH@A_A^_H\$Hl$Ht$WAVAWH HME3HHHfD9"tfA>'uIHfA|V"t fA|V'uHDd$0LL|$(LILl$ FHL$3H_H3L\$@I[0Ik8IsHIA_A^A]A\_H\$Ht$LD$WATAUAVAWH 3MHLC\Hrf9/tf9uyHrkfy:uKHr fy/t>f9At8H$Hr%HAH$ou IH&H!Hvfy:H$HDH$Ld$xI]HIHH !oL$LHHLgnIvHt"SH ;%mHu \fHHHI+LHMH+HHIIHnE3H{Ht!SH %lHu AG\fHLD$`HI+HHMH+HHIIHmJkMtEMt.f9CtfHLD$pHVHMI+HHH+IIHmmJcI+IHfE<^5dt uI Im3H\$PHt$XH A_A^A]A\_HH 'H3H$3HL$@HD$03!D$0AHD$ HD$(K3D$P<HL$ dH(HucH`% ALD$@ HYdubHF%٧H$H34HH\$WH Htzt tt D$@#D{e]b؃u0HT$8HPet|$8tD$@0d$DHD$@L觛D$@\$DHT$8eubD~D$@DD$D뾁|$8uHpH\$0H _H\$WH D3ҹdHHu9aWu!|$DD$@0HD$@4aDD$@DD$DދHHHMbHH\$0H _H\$WH B8Hڃ`H<`tHB@B8H࿃B8Ht+Heu`H)%HuC8uC8HGXHC0H_XH\$0H _@SH HHaHK(HC HHC(HK HAHCHK8HHt HkH [HHXWH HًHHuHS` @HHHJ!itHKAH A ≻3H\$8H _H\$Ht$WH B8HƂHtB8HAXHB0HQXHHt'aHC8@t࿉C8 tHCxt|$8!HHT$8KbL$8DϋL$8H{@t!HHFHDHC@HHG@HNH؅%V(LEHNH؅HNHtHUqLmH؅HN HtHUwLewH؅tY33 `؅HgHEwLHuHD$PHЋ_Z;RE3H v%3_؅6HQgHEHtDH F%H_;LEIHL$X8HEHuHD$P"LHIKE3H؅HWEhLEfEE HUfffF(fMHLHMHL HMHLHMtfDE fEF(HUEHMHL$HE3HMHL$@HMLd$8Ll$0D$(D$ ^3ɅHUEHGHF(uJ8 (uH:H ("HUH (\u{[tH׵%耠3D9F,~7HN0 tHL yu9t E3AHD;F,|HLD$( HL$ L\uZHp%HM[ZDND$PDD$TH\$PHL$XeHMdHMdIdIdHMdHHHE3HtL&G8@u@G8 tHG@t.ƇMfHIGPHtH@HIFHIGPLpHMvHMwP3HEwHEwHAH$@HA_A^A]A\_^]HHXHpHx AVH0`LH`HL3ҹAh]Hc YDD$PDD$THD$PIHHcHHu!D$TD$P׉|$(ALHD$ 3ҹ]H hIH\$@Ht$HH|$XH0A^H\$WH0HYHyC8t u5HYHH{}%HHD$ H\$@H0_H%b@SH HHHtHHH [@SH HٹbHSHHPL@ @ LJ@8 IILBLH(MH`xH`hHHXHH [H(HHtE3HEA2=H(HHXWH@H`H@@E3@E3HWHt [Wu8Hd$0E3D$(@E3D$ HWHtGWu8Hd$0E3D$(@E3@D$ HYWHtHH\$PH@_H\$Ht$WH HYXHHsHHT$0Hu.OYH0uXucV)YV/DL$0LHHuLO I!0V LO HIHN@E33`WuVH%H\$83Ht$@H _H\$WH HHIPHyH^VHO@LK E33VuUH%裚3H\$0H _H(HA`LI Q(E3HHHI@Vu>UHU%HH(H(LQE3LD9t=HHuA3'A{ABEB DIH(LLMtj8 DDZpLHLBp LHRhLI@PJ8HI@XHIHPMXXA8uHE3I 3H(H\$Hl$H|$AVH@A8LHyHtA&'A芍GDG HtA8u ǁHcH mHH^HHuH%H輘3҅~53HHd HLPHdXD HHI`;|̓d$(AHd$ M3ҹWHcH]HHuH%H8HAl$(M3HD$ VuRDHd$8d$0AHE3D$(@D$ 0UHHAPHL@PIu6RDD;uG DAt A{tA*GDG )E3HHt]NRD̋DG GHHt\HHHHPHSHHHPHK83H\$PHl$XH|$`H@A^H\$Ht$WH H3HHt [HC8t>9~6HHHL0PHtgRHHL0PH`;|͋C8tHˉC8{8tHHtRHH\$0Ht$8H _H\$WH HAR8Hs(kdS8u$A<@u⿉S8 tHCD@K8 s( kdK8u$A<@uΈK8 tHCD@H{`uC8uC8HGXHC0H_Xc8C8`<`tHC@C8࿃C8H\$0H _HHXHhHp WAVAWH0HjHHa H`IH`MHQX3LIPE ASHcHZHHuH %HHAt$(M3HD$ PSHHT$PLHuk`O=uvEFHH Tt^KdACduC8@u@C8 tHC@HU(HHOHHHHWH C`DL$PLHWXHtGNHHt!YHIt IO~ HcHG Hg HHh$KdC`ACduC8@u@C8 tHC@HU(HHOHHHHWH H\$XHl$`Ht$hH0A_A^_H\$UWAWHH'H3HD$pHE3J8Hڋ%HHD9Ljdu$A<@uΈJ8 tHBHHOHGHHOHGHAL9Xt"HD$0;HD$0HEHGXHXK`C8D9{` C8HEXHC0H]XHLD$HH'HT$8A(D$ 5XDtqkduS8ʀA@u⿉S8 tHCHHOHGHHOHGHAk8L9XKH'AWD!EDE D$dH9D$`u HT",AH 8QkduK8$A<@uΈK8 tHCHHOHGHHOHGHAk8L9X LaD9z`tVHHt 3VLC8t4HHtXMHHHt LLC8tHULHC HK(HHC(HS HBHCHK8HHt HwVHL$pH32H$HĀA__]HJLIBHJ B8 IHHH3LJ(I HHB@HB`HHHDHHH\$Ht$WH Q8HyHمtL rD$0d$4HD$0HGs D$0r D$0! ЉQ8IdACdu@u@S8 tG3L9~0E3HcƅHHAL@IL ;|3H\$8Ht$@H _H\$WH HًSHHt{HKE3LH$tdk8 3CpHHK8HCp HH[hHH9t u3LCA&'A腂A@EH H\$0H _i8HHXHhHpWH@IHHEH`E3D!H@HD$(AD$ JHGPHu+]HSHKH HHG E3LHHtHOPIHOP3Hw HDB 0HOPHSJu_G=tRG=uH&4HOPHHOPGGG HHHHlC`H\$PHl$XHt$`H@_H\$Hl$Ht$WH0B8HzhHHtIAH H L%%GGG HHG 3Hw HDB /C8t HGPHHG8HH'E3Ht$ E3Gu F=uqC8HPu.E3E333JHGPHuvFH%耋HOXH9uWHW8L*D$(LσL$ Gu22F(F F HHHHH&k8C`H\$@Hl$HHt$PH0_H\$LD$WH@HHH3w8Hhd$dLD$0]%D$`HHD$`HHCHGXD$0Ht E3P HGPPH\$PH@_H\$Hl$Ht$WH@HIHAHHh~(ELD$0CH{ HHFXfD$0Ht E3P HFPPH\$PHl$XHt$`H@_H8A(fD$ Amu LL$ OH8@SH DQdi8HYDY8ABAdEuA@uA@DY8A tCA8LAPLIXHQHu HH3H [@USVWATAUAVAWH$HH'H3HHX3PMILLt'9PuHuHD$0!HD$0HAHt{ uC8tH`Lz HILB`HBPBrhH3I7DB 3,9ΉL$@Ht6LD$PH7uL$@C8L$@tL$@PuA$L$@HD$HuM0LIw AGI`IwPAGh3I_ HDB +D$@HT$@$H\$ HE3ɁxLAHBup~B=tDqBD{AEEE LLH^H%HL̊D$@$HɁxHIO@HO@Iw@OdAGduG8@u@G8 tHG@IU(HIOHHHIWH G`D$@M~ G8HcPtrA$IvHAFpHHtH@HIFHHLpHMvHL9uH HH~A$Md$HHuIN@HO@E$E3IT$HL|$ Au5A=HH~A$Md$HHuIN@HO@Iv@G8taE3E333DIHu@H)%輅IV8L0D$(IL$ M BOdAGduG8@u@G8 tHG@IU(HINHHHIVH G`3HH3HA_A^A]A\_^[]H\$WH0Hd$ LL$@HHI`HyHDCpHSx+@u&??? HHC HO@LK E33@u|?H%膄3H\$HH0_H\$WH0Hd$ LL$@HHi'H E3HyHj?u&??? HHC HO@LK E335@u>H%3H\$HH0_H\$Ht$WH Ax IHH|+HI@XHLHt93HI,IHPHt V?HOPC8uE3LHH~K`C8t{`uuC8HFXHC0H^XH\$0Ht$8H _H\$Ht$WH jdIHHuR8$A<@u⿉S8 tHCHIHI@HIHI@HAIxPAH xNk8 IȃcpHHHHHCp 3H[hI@P(H:'tHDvFDF HHGPSHK`C8t{`uuC8HFXHC0H^XH\$0Ht$8H _HUSVWAVHH)pHr'H3Hr8HHIHHtN s89%Hb'D$@GLL$@HDHHd$(HD$4HE3E3HD$ 3>L$4aHDHLL$0Hd$ HT$`A</L$`HLL$0Hd$ HT$pAx;tEHHHHD$pHHHI@AHI@AHI@AHIHuHI@ A H0I0@@A@HPIP@`A`@pApL$`tHD$hHL$4;CȉL$4HCHHDHL$PEHLL$0Hd$ 0fofA~fsfH~E:T$0tpH)HCXHt'HLD$@Hft$@HEA GEHCPHtLD$@ft$@H(EHHt(>DHHCPLD$@Hft$@DD9t$0vCs8f8H%~Y%D$@9LL$@HDHC8%;u HHK`C8ɉK`tuuC8HGXHC0H_XHH3# ($HA^_^[]H\$Ht$WH jdIHHuR8$A<@u⿉S8 tHCHIHI@HIHI@HAC8tHYC8tHHGXHt 3HCK`C8t{`uuC8HFXHC0H^XH\$0Ht$8H _H\$Ht$WH I@@IH)B@HڃjdHuR8$A<@u⿉S8 tHCHIHI@HIHI@HAC8t5IHtr9HHHt8HhtHH;ugMHABHGPHt9O y'Hf'BDpFDF HGP3H{BC8tHtHjHt"uC8uC8HFXHC0H^XK`C8t{`uuC8HFXHC0H^XH\$0Ht$8H _H(LMtIPHI;u H HBHI@H3Ht,AH Q;uo6H&%y{H(HHXHhHpWHP`IAHHHPHE3E3u8u6Wu 6'6jH_'LD$0AD$ HT$8HAuD$0u&D$0 uHU@E3LH6Hu k8k8 s83HH\$`Hl$hHt$pHP_H\$Hl$Ht$ WAVAWH@AM@HLH=8@D$(L ݏ%Ht$ DI=Hd$8Ad$0E3D$(ID$ 6HHu4D=tu&HIV@E3LH5Hu24D2nD$hDD$lH\$hHt H5HQk8 cpHHHHHH!CCp H[hHH\$`Hl$pHt$xH@A_A^_H\$WHPH'H3HD$@d$<='HD$,HىD$(HHD$ HBHHD$0D$8uHH '7|HOHL0'HT$ ^zu)2=t2DlCDC 3HL$@H3QH\$pHP_H(B8E3`D<<`tHB@B8࿃B8D88u$D89uuB8HAXHB0HQXH(H(HHXHhHpHx AVH0IL3H3EHH %HIJH+uIJH+HHDDHcHrEyIIcHHulEB\MARXAJLHn@D$(!\$ >1HI;t4E3HAP.3tE3LHHX3Hu H:1IHHH\$@Hl$HHt$PH|$XH0A^H\$Hl$Ht$ WH H3HHL;u:HX@8(HL;u;Hx@9 HT$8D$8AH y9kyD='@8<t@<jE3GDO U9jr]B@EBt"<"B tC8@<@t࿉C8 tHCHtD3HC@H;D89A ф<t HH'C8@tEuuuC8HGXHC0H_XH\$0Hl$@Ht$HH _H(B8D<Et@u(@B8 tHB@@t࿉B8 tHBH98 ф<t HJ3H(H\$Hl$VWAVH 8HHu&<H8HzX;Ƃ:99u&<H9Hzx:Ƃ; Ht$HH|$HHO OHHBHggHG<GEG<tO3Lv IDB HKPMHut=.=t0--- HHHIH\$@Hl$PH A^_^@SH E33AQD2HHu.H%s3H 'DB +HH'H [̋B8E3`D<<`tHB@B8࿃B8D88uD89uuB8HAXHB0HQXH\$WH HHHL;u:Ƃ8HL;u;Ƃ9D$8Ax }:<tXH'Ƃ<AH 8DfDG E3GE@(D#<D#t3HC@Hn8D89A ф<t HH&C8tEuuuC8HGXHC0H_XH\$0H _H(B8D<Et@u(@B8 tHB@@t࿉B8 tHBH98 ф<t HJ3H(H\$WH 8Hu"<H8;Ƃ:09u"<H9:Ƃ;H\$8AH OH0u1+++ HHHHC H\$0H _H\$H|$Lt$ UHHpH:'H3HEHAHD<tDuHCHHEe<tDuHCHHEDuHCHHEeeeHELMHD$ LEEHUA)ȃuY*)) HKLO HE3H3HI@,uo*H{%o2~}AGƃ}w}v LO I!E3HG(3HKHI@+u]*Ht{%go3HMH38L\$pI[I{ Ms(I]HbHHAPHtH@HHBHHAPHPHHRHHQPH\$WH HHA?3HHLH\$0H _@SVWHHF'H3H$Hd$@HD$THd$8IHD$0HHD$XD$(HHD$ E3E3"HH.(HVHwGG8 HO HLL$`HD\$XA HHHHD$PHW(H HH_HƇ<D$PtHD$ 't'DQbFDF WHT$`HHtHGPo8f8 HHH3HH$H3NH_^[H\$WH A8IDHHuy *H{@3H\$0H _E3HA8űBH9AH}~HBH9ArwH;r3H;H(t4t(u9tt+H(3H(ùH(H\$Hl$Ht$WH3H '8+H!l$0HD'3t$h$HHL$ 'y HH[P H[XHuHu9sHuuƇuHKLE33HI@'tsHCXHtHH@PHu*HC`HtH;XPuHH;XXu HH@`HuH[`HuH '*L$I[IkIs I_&&H=w%0k̃ tE~(~7t7t2t(tttd$D$HD$ H4H(H'H=H %u %D_D$0DD$4HD$0H'H84H(H\$WH HH3҇;SHu HC@HZ0K8$<uK8HGXHC0H_XH\$0H _H\$WH HHHC8`<`tHC@C8࿃C8uuC8HGXHC0H_XH\$0H _HJLAB8 HJ ADJIHHH3LB(IBHHB@HDJxHRpHHXHpWH AHHEuHID!@$@ H@ HA|D;AHuHQ@nyHtH ''tHSH d'HB'HӉ{HH F''C8Hs@@u@C8 tHC@3H\$0Ht$8H _@SH yHHtrH 'd'CH~-~u#H\'H3H "H @'HH '3'cHC8@t࿉C8 tHCH3H [H\$Ht$WH H='33HHHHyHP~+HXHuH!{XH!{PHs`ChHty H^PHH^XH'H3H\$0Ht$8H _HJ`E3LHEZD9YhHQ`HBPH;HBXHtD9XhuDPhLDQhDZhhLAXM;uPI@PHAXHtI@PHH`HA`I@`HtHA`H;HPuL@P L@XL'IHPHLA`ILDQhHJPDZhHAXHBPHtHAXHP`HB`HA`HtHB`H;PPuHHP HHXH w'HQXHt D9Xh0LAPM;uPI@XHAPHtI@XHH`HA`I@`HtHA`H;HPuL@P L@XL'IHXHLA`ILDQhHJXDZhHAPHBXHtHAPHP`HB`HA`HtHB`H;PPuHHP HHXH 'HQPHJ`II`HMH'DPhH(LBPLMuLBX HJXHu:HR`EKhMtIP`HtL9ZPu LBPLBXL@'HAPHH@PHuLAXHQ`DIhMtIP`HtH9JPuLBP LBXL'L9Y`ACPHDAPAK`I`IC`HtL9XPuHHP HHXH 'ICPHH`ICXHtHH`EuIH(E3EQMt E9HhL;o'HJPI;HJXD9QhuWDIhHJXDRhHAPHBXHtHAPHP`HB`HA`HtHB`H;PPuHHP HHXH 'HQPHJ`HJXHAPHtD9HhuHAXHD9HhHAXHt D9HhHAPHtDHhLAPDQhI@XHAPHtI@XHH`HA`I@`HHA`H;HPL@PD9QhuWDIhHJPDRhHAXHBPHtHAXHP`HB`HA`HtHB`H;PPuHHP HHXH 'HQXHJ`HJPHAPHt D9HhHAXHt D9HhDQhLHR`XL@XL'IHXLA`HJXBhAhDJhHAXHtDHhHJXHAPHBXHtHAPHP`HB`HA`HtHB`H;PPuHHP HHXH j'HQPHAPHtD9Hhu`HAXHtDHhLAXDQhI@PHAXHtI@PHH`HA`I@`HtHA`H;HPuL@P L@XL'IHPLA`HJPBhAhDJhHAPHtDHhHJPHAXHBPHtHAXHP`HB`HA`HtHB`H;PPuHHP HHXH 'HQXHJ`L'MtEHhH(HLI Q(E3HHHI@iuH&m%aH(HHXHhHpHx AVH0HAMHE3AP{HHu$DȋLCUA@EH E3HAPvu'lLCDTA@EH H}HKD΃d$ LHdxHDIuDȸ@'D;u-k8 k8 3H\$@Hl$HHt$PH|$XH0A^A1@SUVWATAVAWH`B8MHrMHHtDATFDF \B8u'HT$PHD$P'MxLI>uHI7`uA?'3EH] H}XH#HL}PDB HHD$@E3H\$0HD$(IId$ EA%tVW8sjOdG`AGdu@u@W8 tHG@LN(HILEIHL@LMMd^=t{DOdG`AGduG8@u@G8 tHG@HV(HHMHHHHUH 3H`A_A^A\_^][@SUVWATAVAWHpB8MHrMHHtDAaRFDF sB8u5R'HT$P_' O'H)D$PL$`D$hKxLI>uHIh^uA?'3EH] H}XH#HL}PDB HHD$@E3H\$0HD$(IId$ EAA#tVW8sjOdG`AGdu@u@W8 tHG@LN(HILEIHL@LMM^=tDOdG`AGduG8@u@G8 tHG@HV(HHMHHHHUH 3HpA_A^A\_^][HHXDH D@WH0H@HLHHϺAu" LCDAuPA@EH -|$Pt$D$ LL$XHDBt3H\$@H0_DD$SH0HD$ LL$PHHDBQu"N LCDAOA@EH 3H0[H\$Ht$WH0HIIHPHHuhR8  kdS8u$A<@u⿉S8 tHCHHAH ]DMOFDN HNAx |RLD$ A pku.HHHHHt03H #HOPHOPC8t HHK`C8t{`uuC8HFXHC0H^XH\$@Ht$HH0_H\$Ht$WH0jdIHHuR8$A<@u⿉S8 tHCHIHI@HIHI@HAAH HE3Ƀd$ ApZuJk8 !!CpHHHHK8Cp H[h3/.DMDF \DMDN FHGPH K`C8t{`uuC8HFXHC0H^XH\$@Ht$HH0_H\$H|$ UATAVHHH)t$pR8HMS8Ax %;kdS8u$A<@u⿉S8 tHCHK8tHeHEeH0AH )u[E'D;u G O {LGDO HCPLEHfuHAIx(v0IV(LEHCPHEI9F(At'kdS8u$A<@u⿉S8 tHCHs8g HeeGEWHCHHMAHKHd$0LM(Hd$(HUHAe0HE0HD$ EtwE(t7(ELEЋfEHCPHE9E(Dc8oK8~kdK8u$A<@uΈK8 tHCHg GeA3'DA;uAJ(E3fEЉGDO \K8kdK8u$A<@uΈK8 tHCHE'D;u G O AsJGDG (EfEHHCPLEHC8%A;u HHK`C8ɉK`tuuC8HGXHC0H_X(t$pL$I[ I{8IA^A\]H\$Ht$WH I@@IH)B@HڃjdHuR8$A<@u⿉S8 tHCHIHI@HIHI@HAC8t%IHtHHtHPt*O WDGIFHDN HGPHt"uC8uC8HFXHC0H^XK`C8t{`uuC8HFXHC0H^XH\$0Ht$8H _HHXHhHxLp AWH0LE3HiHHMuA3'AHEDE MFPIuAI'׋A8HJ%ED!|$ AAyINP A?o8 D!D!pL!L!HL!O8Gp HhIHIINPC8uIC8u IH 3 r$HH˃ K8K8AH\$@Hl$HH|$PLt$XH0A_HHXHhHpHx AVH B8HAt,B8@uHA0 jHu^E3YB8@tPHtFHbt:3o HHL7PHt|7 u _ HL7PHǐHuˋK8s&kdK8u$A<@u#ωK8 tHCPK8 s& kdK8u$A<@u#ωK8 tHCPEtH k8c8C8`<`tHC@C8#ǃ{`C8uHKuC8HAXHC0HYXH\$0Hl$8Ht$@H|$HH A^HHXHpWH A8IHuZA8uHI` @H@HAPH u LCDOEA@EH HLNjK uk8H\$8Ht$@H _H\$Hl$Ht$ WAVAWH HھR8HHH{du$A<@uDw!S8AtHCpHHHH@HHHHH@HAC8td$LD$H;HD$HHE1Hl ;t3 D4DEDE HHAXHtHs`C8T{`JBC8HEXHC0H]X+"{` uHU  {8Hs8uyHtoC8tQ3Dw!LJ>H;t J>J>xHt J>xHƐIuHHC8#;u3HH;t  HHHt_ HHK(HC HHC(HK HAHCpK8HHt HYH\$@Hl$PHt$XH A_A^_@SH A8HYuA&'A_BCDC 2A8t DHdt D3H [@SH A8HYuA&'AACDC 2A8t DHt :D3H [HHXHhHpWH0A@`E3HLHAPJHHu$LCDLAA@EH E3HAPu'LCDAA@EH HDMLLHKHD$  xօtBk8 cpHHHHK8Cp H[hHCK8@3H\$@Hl$HHt$PH0_LAHJB HJ B8 IHHH3LB(IHHB@HB`HHHH\$WH HHHtEDttk8s83H\$0H _H\$Ht$UATAUAVAWHH0A8AHqMDHAtLse4E0HE0HF sDA:?FDF  r$'HUEV8xLI8uAHHUE}6EEE_H(EfEKuA?'C8@u%HA[u DWKdA S8A LS8ACdu@u@S8AtHC@C8%AH2HHuHU%HIE3E3LMIf INPIAF IC8t1E3E333wIxHu-HU%7IIxIHAIĐD;yA;sDHiȐD+AHHd HLPHD HHHu3H\$hHt$pH0A_A^A]A\]H\$WH HHHtDttk8s83H\$0H _H\$Ht$ WHHϓ'H3H$HD$0tHHD$0HHD$ LL$@A u!LGDR=t59/' HHHHC`pk8C`C8t_HOXH9uUHWPLD$(LσL$ Vu0 HHHHnH$HP_^]H\$WH i8HHyI8HSHSdLCPBCdu@u@K8 tGC8uOC8t;Hu1E3E333GHHuHtO%CHH3H\$0H _HHXHhHpHx AVH0I@HL@H~fHAjAA;uD7GDG AHW@E3LHHu 9D$`t> S8 'H'D 'Ht5S8u0u,HDtk8{uC8tAHH9_C8tA<HHEAs9Huk83H\$@Hl$HHt$PH|$XH0A^̋A8L sHID$d$ HD$HAùtt-IHD$!Ӆuu A@8 s A@83LHXA8'E'LMStDIcICIcE3ICE3ICD$("HICItLT$hIHXHHXHhHpHx AVH@HD$xLr I&IHZ`HHBPHBI3IDB 3IDB C8tAE3E333.HHuH[L%?HHHG8Hd$0LL$xDD$pHHLt$(d$ 3uZC8t}Hg@KdC`ACduC8@u@C8 tHC@HV(HHOHHHHWH 7=t2D3FDF HcL$p3H~EHmHHuHW@KdC`ACduC8@u@C8 tHC@HV(HHOHHHHWH HG@HC@C8t_HHD$( LL$ Lu0dZR HIHH3H\$PHl$XHt$`H|$hH@A^H\$WH HyxHHyuGHG A8t(HO`H苼c8C8@t࿉C8 tHCHHShHtUHOHHHH;HHBHK`HO`輴HtH|S% =̃K8C8@u@C8 tHC@3H\$0H _HB`LH9A`svHJpI9Hpr3I9HpHAhHQhH3HHR@HũftW( uEt+IHS%IEtHR%HR%IHR%IEtHR%HR%EtIHR%IHR%IEtHYR%HYR%EtIHMR%IHFR%IEtHR%HR%EtIH~R%IHwR%IEtHQ%HQ%EtIHsQ%IHlQ%IEtH|Q%H|Q%EtIHpQ%IHiQ%IEtHQ%HQ%EtIHQ%IHQ%IEtH:Q%H:Q%EtIH.Q%IH'Q%IEtHP%HP%EtIHP%IHP%Ã-tl(2t^tLt:t(tJabyYpuSEtjIHO%IEtHP%HP%EtIHP%IHP%IEtH\O%H\O%IH]O%ÃthgR<&+ tDtIEtHP%HP%Et IH~P%IHwP%ÄtIEtH+P%H+P%Et IH#P%IHP%ÄtIEtHO%HO%Et IHO%IHO%ÄtIEtHuO%HuO%Et IHmO%IHfO%ÄKb.EtIEtHO%HO%EtIHtO%IHmO%ÃuSt[t1tI!3øIEtHO%HO%øIEtHO%HO%øItEtHXO%HXO%EtHSO%HSO%øItEtHO%HO%EtHN%HN%øItEtHN%HN%EtHN%HN%øItEtHVN%HVN%EtHQN%HQN%øItEtHN%HN%HN%EuHM%H\$WH@r8HN%H)t$0R8Ax }xsYHtOkdS8u$A<@u⿉S8 tHCHAH HP'D)GHDG :A3'A)G3DG !EH(EuA3'A)GDG IHCPLD$ Hft$ !C8%=u HHK`C8ɉK`tuuC8HGXHC0H_XH\$P(t$0H@_HUSVWATAVAWHhH)pH%'H3HEHHR8E3#W8Ds;E9x }YzH'W8AH ID(L%DF HFLEHGPHE+HHUYujDE(FIDF O8DwdO8u$A<@uΈO8 tHGHAL%HGPLEIHEI5L%IEH])uAD9}w D8 QG8D LHH HLMEMǸf9uFH 'H ?'I;tHUt HMH 'H]SAfD9H]Eu)uf$H]fD9DA%u:f-wH]I!IH]f`f LAf(AfA;wH]f A Att ƇAAA$L|$83L|$0D$(fA;w DJfELEfMEHcHHHL$ fD ^LMA AAA#XH]HAt ƇMH]HILHAE3 D$8svEu#HGHHMAHE\$0)uE㊌8HE IDH]D;e&HGPLEIcHfuft DD  D$FDF O8DwdO8u$A<@uΈO8 tHGHIE~IcHGPLEHfuAG8%=u HH O`G8+ˉO`tuAuA ƉG8HFXHG0H~XHMH3_($HA_A^A\_^[]H\$Ht$WH I@@IH)B@HڃjdHuR8$A<@u⿉S8 tHCHIHI@HIHI@HAIxPt3AH HȄ'DP#FHDF HGPHt"uC8uC8HFXHC0H^XK`C8t{`uuC8HFXHC0H^XH\$0Ht$8H _H\$UVWATAUAVAWH`Hy'H3HD$XA9ILuAE3EuE33;uE3DEA\$4IHT$@\$(HT$@d$ DE3E@|$(EƉD$8HT$@Dd$ DHD$0DL$:+HD$ L$@+IDº t(DD$0HD$0T$HDIHD$ u Wu \$4)3 HL$XH3عH$H`A_A^A]A\_^]@SH HHC8tHa c8C8`<`tHC@C8࿃{`C8uHKuC8HAXHC0HYXH [@SH0A9It(HLL$XHd$ u 3H0[H\$WH z8HHHHSdHHH@HHHHH@HAHHAXHt1C8t#d$<D$8;HD$8HGHHAX3HK`C8t]{`uWuSC8HGXHC0H_X?B8t9z`u3HJ(HB HHB(HJ HAHBHJ8HHt H%H\$0H _@SVWH@Hyv'H3HD$8HHHHT$ Ifu!LCDA@EH 6H R'HL$ 6H ;'w'w'3HL$8H36H@_^[@SUVWAVHPHu'H3HD$@HEAHlHHuHD$ HL$ HN<3EuVHT$(HuD8FDF H x'HL$(H-v'U H Z'C8 HVHsHK CHHHHHS(H k8 H{@H{`{pHC8H HCp H[hHHC8EtCA%H C83HH HfC8@3HL$@H3舵HPA^_^][H\$WH0HLL$@H A A;HyHDBHHd$ tD$@LK I!HC()  LK HIHO@E334uH3%'3H\$HH0_H\$Ht$WH HAAHd |$XDu'L$PtGAA;}At'A;|J@tG؅y3 t';|XHt$8f\$XH\$0fL$ZD$XH _@SUVWAVAWHXHr'H3HD$HH$EEH;tj@$HHT$0u@t$(HT$0ED|$ DHluWt3HL$HH3dHXA_A^_^][H\$Ht$WH HHHHsHLO I!E3HN@3cu H 2%&H\$0Ht$8H _B8HHXHhHpHx AVHPHzhH3Lw HIDB aHCHHL$@A HHH>u8AHLD$0Ld$(Hȃd$ )uH&AH Hu0 HHHIk8C`H\$`Hl$hHt$pH|$xHPA^HHXHhHpHx AVH0\=%HH3HDB FHHHD$( L$ LKhLu9H&?5- HHShHHk8C`H\$@Hl$HHt$PH|$XH0A^H(DQ8LLYArd$4D$0HD$0ICoADQ8IdAAAduA@uA@EQ8A tACAA8MAPIQHu,A vIIQhII/ IIb3H(H\$WHPHn'H3HD$@q8HHyI8kdu$A<@uΈK8 tOC8#;uKHLL$ 3HT$(HD$(HD$0D$8D@suD/GDG HHtH3HL$@H3jH\$hHP_Hl$Ht$ WH`Hm'H3HD$P3HHl$09*HUHtHHT$8tiD$8 DD$:DL$0HDHD$4HD$ et*DL$0HD$4DD$4HHD$ su5Wt~HL$PH3dL\$`Ik Is(I_HL$8-n'3H\$Ht$ WHPHl'H3HD$HA8I@HtA8t%DLD$(E3D$ u@tQC8tHHHT$0}u D$8wf#Hf St3HL$HH3pH\$hHt$xHP_H\$Ht$ WH@Hk'H3HD$8A8I@HtnHHT$ u HL$ D$$k8fD$&f+cm'f@tD$(f#k8f3HL$8H3諬H\$XHt$hH@_HHXHhVWAVH HًI8rHK` @H@HA3AA#;HڃuLCDA@EH C8tHsHHHkPtHt$@E2Hl$@s8% C8EtLHHK3H\$HHl$PH A^_^H\$UVWATAUAVAWHH@H"j'H3HEE3LL@@DfAfu AAAEILAH~"AWfuWAAEAII;|ހu@:u@:u D:IHUA$ffA;uAftfuE뙍AfA;vfuE녍AfA;wYtf'uAcAfA;wyUf1uAAfA;w AY6AfA;)EyUt1f#fUtffUtffUtf fU@t@tff#fU@t5f#fU@tf@fU@tf fU@tffUAtEt f f#fUI03HMH3JH$H@A_A^A]A\_^]@SH DAA D+i'ADwi'D i'ji'Dsi'uQAA+;LDQBA;~AA+3HЉ=i'AtAtA;uE;t iH [H\$WH Hb HHD$XMHBPMBHLB`AHdA@`AAA@duA@8@u@A@8 tI@@DD$PHW(HHKHLL$XHHHSH IHc@IBuHc D$X~ HHC HH讫H\$03H _HT$SUVWATAUAVAWHXHIcع@M3DLD@AH ?}'$E3H\$8AA‰$HHD$0L$AHAAf~D$@$THL$HD$ÊEuBDt0AubAwA+ȽA#E*,-$YD8w [GHŃABtaEtMEIHzE3ErftAL|$(E3D$ E3HiEtMEIH"E3ED8t DAAE3L|$(3D$ EtMEIHE3ED8t DAEtMEIHE3ED8t L|$(E3D$ A)EtMEIHXE3ED8t 뽺EtMEIH#E3ED8t DAAEtMEIHE3ED8t DAA뾋ŃJ<tRt+EtMEIH|3D3sEtMEIHZ3D3~EtMEIH83DIHEtMEIH E3Erft DAEʀrftAL|$(DT$ rEtMEIHE3ED8t A҃E3=EtMEIHeE3ED8t A҃AMH;E>@tu@@t.@x "u @m\d@π[@RF\u @7u @,"u @=@@@HHXHhHpWAVAWH@`E$MHكt$tHI`@H@HAHy@uaE3AP7HHuhLCDA@EH HKDLHy HY뚃u,k8u"uHK@LL$0WD$ DGHK@EIvwk8 3H\$`Hl$hHt$pH@A_A^_H\$Hl$Ht$WAVAWHPHjHY H$HH#MHQPH3AHAXHMcDB )Hd$@L$$EHO@IH\$8D$0H$HD$(d$ u_G8tHf@OLGHAGLuG8@u@G8 tHG@HVHLE(IHHPLFIH蝠=tD'EDE a3IE~AMvHHuHV@OLGHAGLuG8@u@G8 tHG@HU(HHNHHHHVH 3L\$PI[ Ik(Is0IA_A^_H\$Hl$Ht$WH0A8IHyHHtA5'A`GDG A8uDe'E3HT$ D$ xԋKLS8S8ACLu@u@S8 tHC@C8H8H@u HH3H\$@Hl$HHt$PH0_̋A8s:AA8HADiLuQ8$A<@u⿉Q8 tHAD@3@SUVWHxHY'H3HD$`B8AH$IHHD$Pu&'d'E3HT$@HD$@qy0H$DHD$0LHD$PD$(HHD$ HHL$`H3;Hx_^][@SUVWHHX'H3H$B8AH$IHHH@)D$`L$pD$xu=pc'HT$@}c' mc'E3H)D$@L$PD$Xy0H$DHD$0LHD$`D$(HHD$ HH$H3ZHĘ_^][@USVWAVHl$HHW'H3HEDJ8MAHDJ8HAp AD=8'ttt]A^HˉGDW AD[8tHd$XHD$Pd$PHL$PD$pEEu+IV(L3D$PHHD$ XAbH@HL$PAH\HMD3D$pڮHd$@HD$dHd$8LL$`HK@DFd$hHT$pHD$0HEHD$(HD$hHD$ t$dNt(D$pLMT$`d$ fD$P=8'u1(D$pLMT$`LD$PH8L$ HfD$PA3'A;u&A(D$pE3Ƀd$ fD$P3҉GDG 9tAH(D$pfD$PGw d$ E3HH8LD$PHC8%=u HHcKHC8ɉKHtuuC8HGXHC0H_XHMH3莖HA^_^[]H\$WH jLMHHuR8$A<@u⿉S8 tHCHIHI@HI@IHHAI@XHt5AH x3I  DGDO IIBX%KHC8t{HuuC8HGXHC0H_XH\$0H _H\$WH HHHHK@C8`<`tHC@C8࿃{HC8uuC8HGXHC0H_XH\$0H _H(B8t9zHu3HJ(HB HHB(HJ HAHBHJ8HHt H=H(@SH A8HYuA&'A_CDC HI@t D3H [HJLABHJ B8 IHHHH=LB(I3HJ@HHHHP3HJHHJpBXHRPH\$WHHR'H3H$HD$0tHHD$0HHD$ LL$@A u!LCDGA@EH !D$LHKHO3ɅAH$H3yH$H_H\$VWAVHPLrpH3HIDB Hd$0Hl'HK@LL$xk8HT$@d$@AHD$HHD$pLt$(HD$ HHD$pu)C8s`HSPC8H΋D$xHCxCH蠖H=t3 HHSPHI`k8CHH$HPA^_^@SH@A8HىT$Xu#['E3HT$0D$0yFHK@LL$XD$ A ݾtLCDmA@EH 3H@[H\$Ht$UWAVHH@A8AILHu$['E3HUEnyC8tE#HKeHEHA3HE Ht Hd3IΉE$NE tt EA A HK@LM 3D$ ӽu!LCDbA@EH K3H\$hHt$pH@A^_]@SH@A8HىT$Xu#Z'E3HT$0D$0`ySC8LL$XHK@A D$ u*3't%ELCDA@EH 뱺)3H@[@SH@BT$XH=w|A8uiY'E3HT$0D$0xoC8LL$XHK@A D$ u*3t%LCDA@EH %)3HId$dD$`HD$`HAH@[@SUVWAVHHM'H3H$ID$0AAHDD$ HLL$0HκڻAA;uDiCADC LD$0~fHA;tE3HAPuHS@E3LH˽HtH=W'tHD$4D$4tLL$@HD$ A HQA;t|$huHHW'Hct#o8H+HHHHPWHw@uo83H$H3ՍHA^_^][@SH@BT$XH=w~A8u)W'E3HT$0D$0vxqC8LL$XHK@D$ u.3DBDt)bLCDA@EH ))DB3HId$dD$`HD$`HAH@[̸ HtHHXHpWH@H`H`H`H@DHD$ A3ҹƼHD$XHj%HHE荤HHtDH\$ LHO%LHM%DHL$XHtt%́ws3@UHH0E%LE`FHUEvEt>(EfEH0]LSHH^J'H3HD$pIcICIcIICMCD$(AI[D$`OuH#3HL$pH3@HĀ[H\$Hl$Ht$WAVAWHp3ILLMIxI@HL˸ D$HE3Lt$@H׉D$8IH$T'Lt$0D$($ Ht$ Hul=u\Hϋ;uFHϋ{&ME3Ht$`E333HH\5t$`H9tt 6L\$pI[ Ik(Is0IA_A^_̸ ;v|D;^trtX G;B'Á"t>#t0$t"4tځ:tҁC@'ø6'ø'ø'ø;TtL9-!tntL'øJ'ø='ÁH0-\D3'ø;\@;?t7-t;=<te=tc>tU?EI'ÁAtNt@t> t*   F'øG'ø8'øA'ø@;RtJ6t<7t.<t =t>t?tJQ'øC'øu'øM'ø'ÁAtUytBjt(AA#A;tø&'ø3øE'HHXHpHxAVHH$3MHH9$H$HPغD@@C ED$ptD$pFHD$`\$HLH\$@LDD$8E3HD$0HO'HHVD$( Ht$ dȉFAtLtMt9@t)@t@t $ 8'1&' L$I[IsI{ IA^HHXHpHxAVHH$3MH6L$M%L$MH9$H$HPȺD@@C LT$xEL$D$ptD$pFHD$`\$HLH\$@LDD$8(E3HD$0H N'HHVD$( Ht$ ŽȉFAtLtMt9@t)@t@t b$ 8'&'L$I[IsI{ IA^H\$Ht$WH HHHIrHKHH;tHtBH{HCH\$0HHt$8H _H(HtJH(HHHWAVAWH@H@HXHp LH3|$h@8:uE3 IIB8<2uHHcHHt(H~ I;~I+3HHL$( |$0u HHcHD%@t1H~(HHcHTXHLHuu |$hHӅuXHHcHHLHHMIH@HI;t"H~(HHcHTXHLH*uu |$hHHHcHHd( H\$`|$hHHcHHE3+tHL$( HH\$pHt$xH@A_A^_H( HT$UH HHU`HHcHHAsHH ]@SH HH{HHH [@SH HIHHuH! 4BHH [H\$WH HHHÀ<uHHpHtHH+׊ :HHuH\$0H _HWH@H@HXHp H3HH膊H=JZ'H|$`H G'1HHRHHufHtH\HHL$`OHu$H%HL$(HJ&HL$( H\$`HY'HHH@H詋HL$XzHH\$PHt$hH@_HX[HWH@H@HXHp H3HH螉H=ZY'H|$`H &X'IHHQHHufHtH\HHL$`kOHu$H %HL$(HI&HL$(8H\$`HX'HHH@HHL$X蒉HH\$PHt$hH@_HXsHWH@H@HXHp H3HH趈H=jX'H|$`H &W'a HHPHHufHtH\HHL$`COHu$H"%HL$('HH&HL$(PH\$`HW'HHH@ɷHىHL$X誈HH\$PHt$hH@_HX鋈HD@HHSH0H@Hك`HLc@H˓IHLc@EHELHaHHcHH'iLCLD$@IHcHHJIHcHQBTHHcHHrHHHcHQTHH0[H@HÖ@SH H{HHkHtH HC`HKHK HCHCHC(HC8HC0HC@HCHHCPHCLHCXH!HC@H HCX HCH HC8H HCP HH [@SH HaHHAڄHH [@SH HaHHAUHH [HD@HHWH0H@HXH`H%HH%HAHHD$PHYHHHcHHמH9HHcHhT9H\$XH}H%HHchcpHH\$HH0_@UH HEPtePHM@HH ]H@H HX:@SH HWDAHHDNHH [HL$SH0HD$ HDAHHEt1AH.%HM*HHMaHMHUE3HUIHL,E3ҹ:DLHu*^H!\$ L L%HM/HMD|$ L > DHME3y)L|$ L L%HMi LE3ҍJHHuϕLp%HD$ E3E3AQHHHt[LMtSL|$0D|$(L|$ E33IjHHulL5%,Hot?ML.% >L$L|$ L ˻HMx.HHM̿IHt HHt H7Ht HٕHM-HI $HM@J (IHMH3fH$ HA_A^A]A\_^]HXHHHWH@H@HXHpH``D/'eH%X@JH3HD$8HD$(H3Rt '~HH$H HL$PuHL$8H 3H\$XHt$`H@_H(CLMCVWAVHPICI[IkAHHIcd$@DC.'eH%XA@JJ3ICICJ3IQt Z}HH $HHd$ DL$HHHL$HJ 3H\$pHl$xHPA^_^H8cLWH@ICI[38">'u[>'ICD$0 u-'eH%X@HH;ICICH;|HH$HD$8H;H\$PH@_H(HL$UHH`HEAH\$HM&HM E3LHUHMAH8HM %LHUHMHUHMAH$HM %HHM3HM HHM g,'eH%XAHJHEHeEHEJHEHD$ ALEHU HMHM$t HM HMo$H`]HH]$H({HL1)H*='uH ='9eH%X +'H  zDT#'H$H<zH<'H(H(;'u2zHH$jzH,3H(@SH H2*HH [HUAVAWHH`HEHXHpHxH3H]]D*'eH%XA@N4K>HEHEK>HMHuf>=t3HPt Hl?E33HDu tHM8'LHUHM!HHHM"HEK>HL\$`I[ Is(I{0IA_A^]H@H0HUVWATAUAVAWHHPHEHXL3H]])'eH%X@L$LeXI=u3HULHMUHH HMHEJ7HL\$`I[ Is(IA^_]H@H0IHL@UVWHH`HEHXHHeeD&'eH%X@JHU(HM!BHH ''BHM٧Lz''HU(H ''HM() u)H\HUHU(HM0HU(HJHE(HE(HHEHeEHEHHE(HD$ ALo''HU8HM0:HM1t&HuGHM{HM8 u%HuHIHM<HEIH$HĀA^_]H`S HHHUVWATAUAVAWHl$HpHD$@HX HZ'H3HE`MLLHT$H3H\$(\$0 8 'eH%X@L$IHD$8HD$(IL 1{ DHL$` A6;Gt%H|$`DHT$ IPHHH;rHT$ I胲LL$`DHT$PHLHT$XHL$(HIUHT$8@IIIHM`H3VH$HpA_A^A]A\_^]HHH(HUVWATAUAVAWHH@HEHXLHee'eH%XA@LICICK>HH'H-9'3$H;-.'t LCMtHL$`H[H;uLD$`HT$`HL$ 0H\$hHl$pHHD$0K>HHHt$xH@A_A^_HUVWATAVHl$HHD$hHXHHd$HHd$Pd$XD'eH%XA@J4J&HD$`HD$PJ&HHpFHHL$8|$@~-HHLFHuHT$8HHH_EHHAH$HaHT$pHtLHT$xH H8uIAHI$HHT$ H0LHT$0HHuAE2HMOEAH$HHHLHT$0H{HHL$ >HT$ HM+HHL$ AHy$HUHHfLHT$0HHHHHL$ HT$ HMHH $HHMFHL$ pHMHL$8[HD$`J&HH$HĀA^A\_^]HPH8HCH H HA(HUWATAVAWHH@HEHXHp HL3H}}D'eH%XA@J4J&HEHEJ&пL9;E3HU8HH>=u1AH$HM@HHM8:LHU8InE3HU@HHHM8E3HU@HM8EHH,؋AHU@HM8|EHH,ȋHiʚ;HL+HM8BH/KimIIH+HHHHM@L3H]8HYiʚ;D+AHM8tLH4LHU8HM\HIHEJ&IL\$@I[0IsHIA_A^A\_]H(@UVWAVAWHH@HEH\$pLHHeeD 'eH%XA@J4J>HEHEJ>:t-AHC$HM8HHM@ƹHH軧zE3HU8IH"H,AHU8IH,Ћt&HHM8LHU@HM$ HM8HHHEJ>HH\$pH@A_A^_^]H(@UVWHH@HEH\$hLHHeeD'eH%X@JH3HEHEH3E3HU0I!HU HHU HM LE HU HMHHHEH3HH\$hH@_^]H( HIG@HHPUWAVHHPHEHXHp AMHHee'eH%XA@H'HUHz3ۋ ^'eH%XAHJHEH!]]HEJHM@HUHMgHL'HUHH tHMlHHL'HUHHHMHd$ E3LHUHHM tHMHMHE@HD$ ELE(HUHM0qHMh u@tHL0'HUH\HHMPHd$ E3LHUH(HM z=`'u%['%X'1Hd$ E3L'HUH 'HM 0HEHHM- HL$I[ Is8IA^_]H` HUWAVHHpHEHXHpH3H]]\'eH%XA@HL$I[I{ M{(I]H0H8LL$(E3LD$ E3H8H(致@8H(LWH@ICI[Is HIcd$0D'eH%X@JH3ICICH3AIKHHL$`lHHaHD$8H3HH\$XHt$hH@_H(@USVWATAVAWHHPHEHL3H]]D'eH%XA@N"M0\ 'LHU8HMNHH HEH7HH\$`H@_^]H( @UWAVHHPHEH\$pHHee1'eH%XA@HJ3HEHEJ3=W'tHM0LHU8HMM0'AH$HM8LHU0H 'AHz$HMLHU8H 'HM0u!QHHM$/pQqHM8u!QHHW$p#qHU0HM0=HU8HM80AH5HMHHKH@[@SHPHL$ HI@H@ HKC HP[H\$WH H3HH;zs HBHHHu8Z$t9H;xsH@HHH\$0H _HA83H9tHAPHc%HBA t+HAt#HALtH fI6@4HAɁuAotEHAAA AXD@HA@SH@HHHHT$ CHK H@[HHHWAVAWH`H@HXHpALHbHHT$(IUHcHc Hc(@L5`uLwHT$(I)L3I8HCLD$(3H &!HC LD$(3H & HC(@tfC.,HKHGKL\$`I[(Is0IA_A^_HT$UH HH)33BHUVWATAUAVAWHhHHEHXH&H3HEMIHULEoD$0L}wLuMtA,+u3HcAA%=uHOI;wAIHH@8TdHUIHǫLHM/9HUIH]H}HC]ߊ<}wRIIH@ dD6~9HIH+H;s*L+EAIHMHC8HO؊ uLuI](H~ I;vI+3AE%LEHUIE@=tHH\$ D|$0Ew3MLMH}LCMH|$ LEHUIeLMH}LCMH|$ MH\$ D|$0ELEHUI3LMH}LCMH|$ D|$0ELMH}LCML+LLt$ LEHUIGIe(MH\$ ELEHUI{E3HM@"E3HM1"HEHMH3)H$HA_A^A]A\_^]H@7HpN"H@6H6"@SH0HD$ HHHcH|u5Dt.HLHHH@hauHHcHHE3APpH0[HT$UH HHH ]HA@3H9tHAXHcH\$Hl$Ht$WH H\$PIIHHtHHHuEH\$0HHl$8Ht$@H _H\$Hl$Ht$WH H|$PAIHHt@H足HuHl$8HHt$@H\$0H _@SH HH Ht_H#H [@SH A Hم~ HIv_ y HIHK(H [H%Y_@SH HHIHK HK(H [H\$Ht$WH AHHHu H cv.E3).t'DL3H%H{H{rHH8Ht$8HH\$0H _HHuHzHB(HuHB0@UHH`AQ#Et 33HĠ_^[@SVWHH&H3H$AIL1$EIHHT$PHD$@ L$HL$`L@hUHcLHT$0LD$@$HD$`HD$(HˈT$ HHH$H3}Hİ_^[@SVWHH&H3H$AILm$EIHHT$PHD$@KL$HL$`L@THcLHT$0LD$@$HD$`HD$(HˈT$ HHH$H3Hİ_^[@USVWATAVAWHl$HHEH2&H3HEIILLDewAA@u1AEHDEHBHDD$(Dd$ LEIeV7HUIHӝHHM;+HeHeHEHeEHUHˀ}tHHM轨HHM訨E3HMH_(HMH~ H;vH+3ۋG%@t-EH\$ ELEHUI3HMELMH}LCMHL$ LEHUIHg(MH\$ ELEIIHE3HM IHMH3HĠA_A^A\_^[]H@)HX4Hx(Hx̊AHQ+H\$Hl$Ht$WH 3IH+HI;HGHtHi H+HHH;uHl$8HH\$0Ht$@H _HQv-H\$Hl$Ht$WH 3IH+HI;HGHtHi H*-HHH;uHl$8HH\$0Ht$@H _@SH0d$ HHQ(HjHH0[@SH IIL+0HH [̃d tytlt_tRtEt8t+ttyH{H#HHHHHCH'nHHsà t_tRtEt8t+ttHHgHHHHHHHà tytlt_tRtEt8t+ttyHH[H3HHcHHHcHcHCÃ!t_tRtEt8t+ttHHHH?HHHoHHÃwntyetlt_tRtEt8t+ttjH H4HHHLHH|HH,HDÃot_tRtEt8t+ttH@HHH(HHHHHø;rthxt[tNtAt4t'tt usHHH]HHHHHHÁtctVtIt<t/t"ttHjH*H"HZHHHHRH@SH0HHڃd$ H@0OHH0[@SH@HD$ HHHcPH| HtTHHL$(誝|$0t5HHcHHLHHH@hNuHHcHHE3APbHL$(HH@[H(ڠ@SH HHQ@H臜HH [@SH0HHڃd$ H@(%NHH0[@WH0HD$ H\$HHHHa@HaaAHA Ha(Ha0Ha8E33hrZHtHHG@H_HHgPHT$@H/HBHHL$@y"H HA@ HkMGXHHuE3APH*H\$HH0_H@7"HHXHhHpHx AVH HEHIIHH;s H wHH+I;w H vMtvJ,E3HH-t`H{rH HH{rHHLCL+tH1H 0H]KELHHH{HkrHH(Hl$8HH\$0Ht$@H|$HH A^H\$Hl$Ht$WAVAWH ApHtu3Apt(LA@I8tHQhI9sHAXHcII+HCXHC@HHt HSXLcJH;s A@UHu3HCXHc8HCH+8HHǹ HH;rHHtH+H;sHuHJL<93I HKHL1HtLIHHuAt5I8t/Mx*ISIChH+L;ICXA+A)IK@HcHLHcHÃcH|$LH\$H(…tQ HyHuH(̃ KtAt4t'tt uDH]HHHHHÃt/t"ttHbHHHHH\$WH @HH~HCXHK@LI@HA8@HH@H@FH\$0H _HUHH`HEHXHn&H3HEHHUE3DEApu=HA@L9t4LAhL;LBHA L+HHMtHUH+EpApu?HA8HHt3HAPLcLHAL+HHM/HUH+E+LELEHELEDEHUHm+EE3HMHHMH3 H$H`]H82@UH HE t e HM0H ]H8H8@SH0d$ HHHH0[@SH0HHڃd$ H@8eDHH0[@SH HHH@02D;tHCPHK8HHBHH [LI8IHtOLQPIcHH;sApu6HA@LMt*L;wH9QhvL9AhsLAhHAhA+AHA8HÃHHHH`D`AH`H@3HD$ D:HD$XHt2HH<uHcx$< t< uHHD$XyH$HHHHXHhHpHx AVH 3IHLM~iIHH~4IV8H;HHLLHIFPHHH+)(IN8HcH IIH@8BtHHHHH\$0HH|$HHl$8Ht$@H A^HHXHhHpHx AVH 3IHLM~kIHH~4IN@H;HHLLH IFXHHH+)0IN@HcH"IIUH@AtHHHHH\$0HH|$HHl$8Ht$@H A^HUVWATAUAVAWHHpHEHXHLE3L}D}D&eH%XN$@J!HEHEJ!E3HUPHHFtE3HUXHHUH׺ HMH9~DHUPHѱHUXHEAH@$HMoxE;~ADHUPH蔱H茼t&DHUPHyHE:DDHMPnHMYHUHMPH8HMWHMNHHMHYHUPHnHUXHLHHNJJ!HEL}D}HEJ!3HNbHu-Hf$AHMPyHHMX=qHI2_~HH Hu HX$HUP5oL8MuEtWIHMGCHUPHYmHUXHLHHNL;~tMHUPHM踶L8M>HMHMH9@HEJ!IH$HpA_A^A]A\_^]HXHH@HUVWATAUAVAWHHHEHXLHHeeD &eH%XN<@J;HEHEJ;E3HUXIMHu9AH$HMXHHMqHH]HEJ;E3HUXIHUHͷHAAD$A9~DHUIͮHUHAEH=$HMlAxE2;~ADHUI萮H船t&DHUIuHE:DDHMk3HۅHUHWH8HMSHHMPVHUXHkHUHLHINOJ9HEHeEHEJ93INfHu,Hj$EHMX~HHMBnHH7\~HH Hu H]$HUX:lL MuEt\HHMLCHUXH^jHUHLHINM;ftMHUXHM轳L L&HMHMP6@HEJ9HH$HĀA_A^A]A\_^]H0HHH@USVWAUAVAWHH`HEHHHeeD&eH%XJ4A@J.HEHEJ.:~E3HUPHUHUXHAHĝ$HMDxE2A;~AEHUPHHt&EHUPHH胴E:DDHMPhHHMHoTH1HEHeEHEH13HO5Hu-H9$AHMPLHHMXlHHZWHH Hu H+$HUPjHHuEt*HHMH;OtLHUPHM貱HH HMHMH4HEJ.HH`A_A^A]_^[]HH!HH0HUVWATAUAVAWHHpHEHXLLHeeD&eH%XN,@J+HEHEJ+9:}9AH$HMH HHMPHIXHEJ+#E3HUHIHUPHL0DHUHIH tDHUPIݩHUH豲 HM覻HAE9~HUHI謩HUPH AH$HMJH0AHMP@2}H;~DDHUIeH]t)DEPHUHIIHѱ@:D}HHMPeHMNQHUHMP H8HM%HMHHMXQHUPHeHUHWLHIO J)HEHeEHEJ)LIHMPHMPHu}HtkIHM[UHUP gH0HtHUHH\eHUPHLHIO I;wtLHUHHM軮H0I4$HMHMX1@HEJ)IH$HpA_A^A]A\_^]HXHH@þHUVWATAUAVAWHHHEHXLLHeeD&eH%XN,@J+HEHEJ+9:}9H$AHMHHHMPHIUHEJ+DHUHIHC u Hd$E3HUHIHUPH_L0DHUIͦHUH衯HAE9$~HUHI覦HUPHAH$HMDH0A$HMP@2}H;~DDHUI^HVt)DEPHUHIBHʮ@:D}HHMPb3H}HUH" H8HMHHMXNHUPHbHUHYLHIL$J)HEHeEHEJ)LIHMPHMPHu}HtlIHM\VHUP!dH0HtHUHH]bHUPHLHIL$I;t$tLHUHHM身H0I7HMHMX.@HEJ)IH$HĀA_A^A]A\_^]H HH8HUVWATAUAVAWHHpHEHXLHHeeD &eH%XN<@J;HEHEJ;AD9"}9AH$HMPHHMXHHRHEJ;E3HUPI HUXH耾H8E9&~EHUPIHUXH]AHX$HM臻HADhE2A;~AEHUPI覣H螮t&EHUPI苣HE:DDHMP+`HHMHKJ9HEHeEHEJ9LHHMPQHHuEtHHMh3INzHHu-AH$HMP誺HHMXncHHcQ(HHMHO HHMзIFHHM蠹HMH%,@HEJ9HH$HpA_A^A]A\_^]H8頩HTHPHHUVWATAUAVAWHH`HEHXLHHeeD&eH%XN4@J3HEHEJ3AD9"}9AH$HMP船HHMX HHAPHEJ3ZE3HUPI蔡HUXHH8E9'~EHUPIqHUXHAH$HMHADhE2A;~AEHUPI.H&t&EHUPIH蛩E:DDHMP]HHMHIJ1HEHeEHEJ1LHHMPHMPHuEt芑HHMz-HUP?_HHtI;OtLHUPHMHHHMbHMH)@HEJ1HH$H`A_A^A]A\_^]HHbHH0 H\$WH0HH3HOOOHHO O(HL$ HHHO $HL$ ڴH\$@HH0_@SH zHu H)HHHH [H\$Ht$WH HHHH iHN `Hx@tHH\$0HHt$8H _H\$Ht$WH HHHH HN H@tH莳H\$0HHt$8H _HHHUWAVHHHEHXHeeD &eH%XA@JA "H ]@UH HHM@H@L A H ]H@H@H\$Hl$ VWAVH HH鋑\H4k39\~\DHcHM@HT$@H@H HALPH@H HT$HHAVL,A;\|H\$PHHl$XH A^_^HUVWATAUAVAWHHPHEHXLHE3L}D}D#&eH%XA@J4J&HEHEJ&3INlHL9=&t9H$AHMP HHMXHHCHEJ&$E3HUHIHMH,u Hi$HUPHMHҝHMP LHMPmLAHUPIȔHР,LcM;r0H5$AHMP`HHMX$UHHCwAHUPIrHz,LcK>I;v H$HEHH&L%&E3DaO'HK McLHL-&L-&D8atL/AHMrC7M;[7AH$HMP聫HUPHMXDTHUPHMX臜AHl$HMSE3LEHUHMPvHcHH¥&AHHM!HAH>HM E3LHUHMPvLEXHUPHM趙LEHUPHMwHH@HEHHH$HPA_A^A]A\_^]H8HUVWATAVHHPHEHXLH3H}}D)&eH%XA@N4K&HEHEK&3IIiH@aHH E3E3a@8atH>HM8{7AH$HU8HM@RHU8HM@3HMpHAH$HMH覩E3LHUHHM8SuHcHH&AHHMuHAHo<HMH^E3LHUHHM8 uLE@HU8HM 胭HHHEK&HH$HPA^A\_^]H0邘HUVWAVAWHH`HEHXHHee&eH%XA@H4J>HEHEJ>L&HU0HIvmHM0轘tyHU8HAHHML@HU8IHHMH_HU0HM8+vHMHL$ ALHU0HH}0uƇaI Ƈ`HEJ>H$H`A_A^_^]HHhH\$Hl$Ht$WH Hy H_3HHDB '@$H_3ۅuCHDgH@G3 Hl$8HXf`H\$0Ht$@H _HHHUVWATAUHHPHEHX E3LEDE ڭ&eH%XA@H4J.HEHEJ.EH HM8h6HU@H}8HH?H{MAEH́$HM8褦HU8H<3HM@mHEH$HM8wEL$LHU8H=AT$HM@UmHEH$HM8?EL$LHU8HK=LHe$Hi:L~HW$HS:L HI$H=:HU@Hm?HEH$HM8ǥE3LHU8HM0tqEH$HM8补HU8HMHH &2HM<2EH$HM8iHU8HMLHH &m2HM2EHƀ$HM81HU8HMHH &52HM1EH$HM8HU8HMHH Z&1HM1EHv$HM8HU8HMHH B&1HM\1EHF$HM8艤HU8HMlHH ʲ&1HM$1EH$HM8QHU8HM4HH &U1HM0EH$HM8HU8HMHH *&1HM0EH$HM8HU8HMHH r&0HM|0EH$HM8詣HU8HMHH ʱ&0HMD0EHR$HM8qHU8HMTHH &u0HM 0EH"$HM89HU8HMHH &=0HM/EH~$HM8HU8HMHH &0HM/EH~$HM8ɢHU8HMHH &/HMd/EH~$HM8葢HU8HMtHH 2&/HM,/EHb~$HM8YHU8HMICICK>E3ISH=HE,v5AH)v$H$ԛHH$DHH27hH$Ht HHHVHGHFHHD$8K>HH\$pH@A_A^_^]H(׊H雜LVWAVH@ICI[IkHHIcd$0Dڡ&eH%XA@JX u\ǃXXHHHH HH hXLHHHHH HH H\$03Ht$8H _H\$Ht$WH <IHH;8t<LcIA2IAH <LHHHH2H HH H\$03Ht$8H _H@USVWAVHH@L&HU0HHIXHM03u3HM8輍HH]8@8`tIHU8@H&E3HL'_G u%H@HU8 H&E3HL^Lw HXAu+W6HMH&E3HL^HMA$<u"W4HM8YH&E3HL^W0HM8YH&E3HLs^W2HM8YH&E3HLQ^fA9vv3H(HLVWAVHPICI[Ik H3I{Љ|$@&eH%X@L4I.ICICI.9XtLt&HT$pHNUHL$ptrHF|E3HUHIrH'~,AHUPIrH ~,ȅxoxk;~"Hg$AHMH蕉HHMPY2eHcI;G v Hf$HcIW(+LcAHMPjLHUXHMxHH ,AHoW$HMH.HHMPHHHEJ'HH@A_A^A\_^[]H(px@USVWATAVAWHH@HELHHeeD&eH%XA@JLE3HUHHfH=ruH\$IE3HUHHfHHH裳u=3HMHDEHH=2&HUPH &E3LHHI3'AHUPH@fHHr,HcAHUHHfH׀t IU H+!AHUXHeHrH,ЋIE H+H;HBHuLHUPHMufHIHEK'IH$HPA_A^A]A\_^]H8gHUVWATAUAVAWHHPHEHXHLHeeD)~&eH%XA@N 4HD$`fD$`IfD9|$`t IH HL$`nuHH HH\$PH A_A^_^]H\$UVWAVAWH HHHHT$`AYHaAuXE3HT$`HAXHcuHO$H' EHT$`HXHFbu HSO$@2E3HT$`HXHdED$`HT$hHxXHdHOH,PrL4(@t+HOHu-HcH;wH;sH6O$H4HD$`fD$`IfD9|$`u I HL$`tHH HH\$PH A_A^_^]HHH@SH HHH [@SH HHH [@SH HHH [@SH HHH [@SH HHH [@SH H.HH [@UWAVHH@HEH\$`Ht$hHHHeeDHu&eH%XA@JHHM04LHU8HMu\HH HEJ7HH\$`Ht$hH@A^_]H(!]HUVWATAUAVAWHH@HEHXLHHeeD%t&eH%XA@J$2TE3HU8HFHHM蠒HNHHURvtHH\HM8S%LHU@HMLHIHMFHEJ;IH$HPA_A^_^]H8MH(FLUVWAVAWHPICI[HL3I{|$@Dd&eH%XA@J4J>ICICJ>3HKaHHu,O蝳HApLqH=$E3H$HEHHL$(]2H$Ht H<HHUHL /LD$(HO(xH(LH$HL$8KHIHL$(hEHD$HJ>IH$HPA_A^_^]H8+LH(/EHA@HL$USVATAVHHpHEHee c&eH%XA@L4K&HEHEK&E3E3H1HM@AHu;$HM8\HU8Hu@HHU8HhHAH@;$HM8[HHU@H8D$0d$(Hd$ E3LHHLIHHLHHLHHLWH:$HLq H:$HvL{!H:$H`L$H:$HJL#H:$H4Ly&H:$HLC&H:$HL}H:$HLwH:$HLHz:$HLHHLHV:$HHU8HHHMkHH Lj&kHMvWH7j&AHl9$HM8YE3LHU8HM0%HEK&HpA^A\^[]HXGILWH@ICI[IsHIcd$0a`&eH%X@HH3ICICH3ISH i&SLHHL$(#HHD$8H3HH\$XHt$`H@_H(HLVWAVH@ICI[Ik HHIcd$0D_&eH%XA@JJ3ICICJ33HNHHu,ḪHA LH8$#EE3HT$hH@HL,HMHLept HH|VHL$h@LHT$pHL$(FHHHD$8J3HH\$`Hl$xH@A^_^H(}GLUVWAVAWH@ICI[HLIcd$0D^&eH%XA@J4J>ICICJ>HHD$pHt+H_E3HT$xH?HIKDHHLGHT$pHL$(FHIHD$8J>IH$H@A_A^_^]H(FHpYXHUVWATAVHH`HEHXLHeeD]&eH%XA@J>HIuIHHEPHEHt3AHqH/LE3HGtHH+HHHd$ ALIHB"HEHuȉEHuXHV@zE3EEHUPH]HHE7HmBEEHUPH%7HUHH?3HMHLh(H;_&HuBAH/$HMPNHUPHMuHH _&HMCH^&E3LEHI-I^(H HD$(Ll$ ALEHV@H""I^(H HD$ ALEH.DL3EWH*HMHOE3LH^&IHGEt\MHHLIVIFHIVIFHBIKI&I KHJHMH~LHUPHM<3HF@H u MK uMKMHUHHM#DHUPI13HUHH<3HMH H@(HEPHC[&HuBAH+$HMXJHUXHMqHH [&HMKHZ&E3LEHH5H~(HHD$(HEPHD$ ALEIT$@H%"H~(HHD$ ALEH1DH7EWH*HMHKE3LHZ&HIJEt\PHHHHVHFHHVHFHBHGH&H GHFHMHzLHUPHM84ID$@H u MG uMGLHUHHM%8HI@HEIIH$HĀA_A^A]A\_^]H`8@UH HHHM0/MH ]HP靀HUVWATAUAVAWHHHEHXLLHeeDvO&eH%X@NH>HD$HJ?HL$pH3L$I[0Ik8IA__^H80H(H UZ&HtH%CZ&H(@SH HHL$0 rHHHH [@UHHPHEH\$`Ht$pH|$x38Y&Y&K8HEHtHXXHXX @,HHY&3H .H]] (G&eH%X@HH3HEHEH3DHNHM$@HUHMgHH P&(HMDH] $HM?HUHMfHH }P&HMDH- $HM?HUHMfHH P&HMODH $HM|?HUHM_fHH O&HMDHHMD?HUHM'fHH O&HHMHEH3H\$`Ht$pH|$xHP]H8u.H\$WH0HRHH W&IHR| HD$(Hlj\$ D$ H\$@H0_H8ALD$ D$ HH8H8AE3LD$ D$ H8HUVWATAUAVAWHhHHEHX H:&H3HEEMHHE3LmDmߋ D&eH%X@L$IHEHEIH^MHHy=MtDl$ LCHUH V&w HH;Ll$ E3HM+|$ LCHUH V&@ HAHMHM^AV+HMHHMHMHHML EEHMA uHHMZ&AuHHMvAuHHMHHt HEAHC@H u H E&HtGHD&Ht;A#u.H E&Ht"HD&HtA LcHS&HEHD$ EHMLL&HS(HE@I HMH3/zH$HĐA_A^A]A\_^]H@x+LVWAVH@ICI[LHIcd$0DB&eH%XA@JICICK>3IIHHu,HMHAL$H$Ʈ̹HD$xHt HqH3LHU@HO(&H(t79HH6HHL$xiLH$HL$('LHT$xHL$(U'HHHD$8K>HH\$pH@A_A^_^]H('LISWH@ICI[Is HIcd$0>&eH%X@HH3ICICH3AH$IK7HHL$PnqHHHD$8H3HH\$`Ht$hH@_H(*'LI[IsWH@V>&HIcd$(eH%X@HH3ICICH3HA@IKP@KHG&E3HOLHD$0H3H\$XHt$`H@_@SH HHH [HUVWATAUAVAWHH`HEHXHLHeeD=&eH%X@NI0I7W,HMXHHMXZHIM1HM0w(Hw0MHWHMH_(ITH4Hw0B 3O(HMK ,HH$HPA_A^A]A\_^]H8t"HWHpHD$8HXHhH/&H3H$`HHd$ d$(v9&eH%X@HH+HD$0HD$ H+LL$HL$`Y.g(Hg0AHT$`HL$@N2HHL$H1YHOHUHL$HHD$0H+H$`H3!pL$pI[Ik I_H p!@UVWHH@HEH\$hHHeeD8&eH%X@JH3HEHEH3ƒt+ЃHM &HHM HU8H H#HMgβLGH#HMg跲LH#HMg蠲LiH#HMg色LH#HMgrL{H#HMg[L$H#HMgDLH#HMg-HMwOHAH#HMo8E3LHUoHMgHMwHAH#HMoE3LHUoHMg3HMwHAHd#HMoE3LHUoHMgxAHHMoHUoHM8HH E"&訞HM?HEJ7H$HA^_]H HUVWHH`HEHXLHHeeD&eH%X@J#HM AH:#HM E3L}M;txHM8AIWHM E3LHUHM8@AWHMrE3LHUHM8AHMSAE3LE8HHMM?MuHM VHUIdHEJ.L$Is Mc(Mk0IA_A^]H@nHUATAUAVAWHhHHEHXHxELLHeeD l&eH%X@JH6HuHL$h^PHT$ HHl$PHt$XH@_@WHPHD$0H\$hHt$xHً)Hd$8d$@ &eH%X@HHHuI!I!MAǁMtyMHML &I3H(HE3LHzEZD9iHHH;0HHt&D9uDLDDLM;utIHHtIHHIHt"HH;u LLL&IHLILDHDHHHtHHHHHt"HH;u HHH &H Ht D9LM;utIHHtIHHIHt"HH;u LLL &IHLILDHDHHHtHHHHHt"HH;u HHH &HHIHH]&DH(LLMu L HHuLHEMtIHt!L9u LLL&H HHHuLHDMtIHtH9u LLLx&L9AHDAIHtL9u HHH !&IHIHtHEuIH(E3EQMt E9^L;&QHI;_HD9DHDHHHtHHHHHt"HH;u HHH ,&HHHHHt D9uHHeD9XHHt D9zHHtDLDIHHtIHHIHHH;LD9DHDHHHtHHHHHt"HH;u HHH &HHHHHt D9HHt D9DLHLLg&ILHDHHtDHHHHtHHHHHt"HH;u HHH &H=HHt D9HHtDLDIHHtIHHIHt"HH;u LLL%&ILHDHHtDHHHHtHHHHHt"HH;u HHH &HHLq&MtEH8H &ILD$ ~H8LB@L9A@s3L9A@H\$WH HoIHHtH)HH\$0H _LAVH@ICI[IsI{ HHIcd$0D%eH%XA@JICICK>vHHD$`Ht%L@8HWHCHFHH[@ƃLGHT$`HL$( HHHD$8K>HH\$hHt$pH@A_A^_H(@USVWAUAVAWHl$HHEH%H3HEAHHee%eH%XA@L4K.HEHEK.LyEtHHHMK&-At HЁAHI#AHMLHHM>HHMH]HtAHHMHHMHEHM"HHM\HHEL&Mu@AH#HMHUHMHH &}HMp}Lq&HEHD$ AIWHMHEK.4fHMH3.HĠA_A^A]_^[]HHHUWATAVAWHH`HEHXHp HHHeeD%eH%XA@N4K>HEHEK>3HK誯HHu*HEHDNjL\lH]#?daẽ;E3HU8HH8E3HU8HHHMϣHȃd$ L PLEHV8Du.D@HU8HlHu HN8gƆyHH0AHM8LHU@HMHHHMeHE@I4AH#HM8HHM@5(HHjHEK>HL\$`I[0IsHIA_A^A\_]HHH8H\$WH HHH(HH\$0H _HUVWATAUAVAWHHpHEHXHHee%eH%XA@L,K/HEHEK/H9DL DvEHM脮HM@H{hu6HCxL(E3HuL!D$ HD$ 胷HHMKrHHMH趪HHMECP g }Z;t>A;t0t+~ HSpHM@3 ShHM@HHME3t;tAHSpHM@HspD{hAHM@蠩E3H]@E~IAHHM@dAHMHXE3LE@HHHH<uHHAE;|H]A@DL}%MuBAHEHM@HU@HMHH L%xHMxL6%HEHD$ EHHM@HO(HWHGHHWHGHBHH'HH~HEK/H$HpA_A^A]A\_^]HXHH"HUWATAVAWHl$HHD$hHXHp H%H3HEpLHHd$Pd$X %eH%XA@HEy LfhHfxH@H^MHT$8HL$@Ey LfhHfxmH@HMHT$0HL$@HH rEy!MfhIfxLH@AIMHT$0HL$@HH HD$P@H HLt$ MEHT$`1y=Lt$ L $nLkPHL$0hHHrHL$`B@HL$0HH AHS#HL$0HHL$8HHqHD$PJ?HHM`H3H$HpA_A^A]A\_^]H@AH`HUWATAVAWHHHHD$XHXHp )p)xH/%H3HE`LHHd$@d$H %eH%X@HEy LfhHfx而H@HMHT$0HL$@HH HD$P@HAHHd$(|$ (EHT$`By3Hd$ L TjLM#PHL$0蘡HHMnHL$0HH HL$`a HD$PH7HHM`H3XL$I[@IsHA(sA({IA_A^A\_]H@H`HUWATAVAWHl$HpHD$PHXHp H%H3HE`LHHd$8d$@ %eH%X@H讉Hd$ L gLzePHL$0-HHkHL$`@HL$0KHH AH#HL$0HHL$XaHHkHD$HH7HHM`H3L$pI[@IsHIA_A^A\_]H8H`uHUWATAVAWHl$HpHD$PHXHp H %H3HE`LHHd$8d$@ %eH%X@HHd$ L YeLbPHL$0蝜HHRiHL$`w@HL$0HH AH#HL$0NHHL$X HHiHD$HH7HHM`H3-L$pI[@IsHIA_A^A\_]H8uH`H,WH*f.zu3HUWATAVAWHHHHD$hHXHp HG%H3HLHHd$@d$H *%eH%XA@HMHT$0HL$PHH HL$@̱HL$`@H }HHd$ EHt$@LHT$pEyHl}Ht$ L [LmYPHL$0HH_HL$pHL$@K@HL$0HH AH̥#HL$0HHL$8HHJ_HD$`J7HHMpH3qL$I[@IsHIA_A^A\_]HP鹷H@齰HpHUWATAVAWHl$HHD$hHXHp H%H3HEpLHHd$@d$H %eH%XA@HEy!MfhIfxtlH@AIMHT$8HL$H详HH HL$`_HL$pTHD$X@HlHHd$(Dd$ Ht$`LLD$pHUGy2kHt$ L *JLHPHL$8nHH#NHL$8藻HH HM8HL$`轟HL$p貟HD$XJ?HHH3L$I[@IsHIA_A^A\_]HH^HpbH`VHJHHUWATAVAWH8HHD$hHXHp )p)xH/%H3HEpLHHd$@d$H %eH%XA@HEy LfhHfx~hH@HMHT$8HL$@躢HH HL$XjHD$P@H1hHHd$(|$ (Ht$XLHT$py2hHt$ L @FL1#PHL$0}HH9JHL$0護HH HL$pMHL$XқHD$PJ?HHMpH39L$I[@IsHA(sA({IA_A^A\_]H@wHX{Hp۽HUWATAVAWHl$HHD$hHXHp Hi%H3HEpLHHd$@d$H O%eH%XA@Hy H~hHfx`H@HMHT$XHL$`HH `HHd$0H|$(Ll$ MDD$PHUKy3R`Hd$ L >L<PHL$XuHHB$HL$XrLHT$HHL$`:HH HM@HD$pIHHH3vH$HĐA_A^A]A\_^]H`鿚H/HUWATAVAWHhHHEHXLE3LuDu%eH%X@L$LeIHEHEIHUwHL$ RtHMw(3HL$(gD9uwLd$ IHM虤AT$HMkqHDHR#HMUE3LHHMvA$HM6qHDH%#HM E3LHHMuAT$HMqHDHSHME3LHHMuAT$HMpHDH#HM贩E3LHHMbuAT$HMpHDH#HM~E3LHHM,uHM胣DIT$HMRHDHU#HM#HM"ML6#IHMyH:#HMEƣL0HMڝL8AHUHM覣HAH#HM菣E3LHI>oAH#HMjE3MHIoA|$t HM( HMHAEH#HL$p"E3LHInHT$0HԝMNjT$0HeI(I(Hl$8E~BCLl$hH\$HHL$@8LHT$pHL$P膑HIMHD$`@H IHM@H3L$PI[8Is@I{HIA_A^A]A\]HPHt$UWAVHH@%HeH%XHM HeeA@H<кJ7HEHEJ7_WHM0HM 3LSWHM0解HM L6WHM0芣HM LLE HU HM@HHEJ7HHHt$hH@A^_]HUHhHHD$PHXHpHx H %H3HHHd$0d$8 %eH%X@HH#HMHEHEJ>LqHM x_HHMȋHЃDHM XHHM;uLHHoL%Mu?DH#HM HU HMHH ѩ%$%HM$L%HEHD$ AIVHM 8HEJ>L\$pI[(Is0I{8IA_A^]HX)HL$USVATAUAVAWHl$HLHMXHH#DjLEXHU`HMP9\HMhHSHMhHUXHc]XFHLH@H'E3IG0A_,TE3fAnHMϘHMhHUL[HL$(H DH0#HL$ ΖH\$(HU`LD$ H[DH#HL$0褖HT$0HM`tIG0A$DH~#HL$8pHT$8HM`†DƄtWIG0Hhw#HL$@A1>LD$@HUH [HL$HHHHL$HBHHHIG0IL3Hm~#HL$PHT$PHM`EAHJ~#HL$X3ƕLD$XHUXHZAH~#HL$`蠕HT$`HMXAt>Hv#HL$hyLD$hHUHHZHL$pH胸HL$pAHHL$x;HT$xHMX荅At2H6v#HMLEHUHYHMH!HMUHp}#HMHUHMX6At=Hu#HM辔LEHUHYHMHʷHM3gTHpH`H}#HM联HUHMXԄt?AH}u#HM\LEHUH,YHMHhHM3THp8IG0AIG0ItHEDH|s#HMLEHUHXH;IG0H,AIG0ALAIIHA_A^A]A\^[]HUVWATAUAVAWHhHHEHXHLE3Ld$ Dd$(D-%eH%X@NICICK>\HHD$`Ht-L@8HUHHH>HHW8LEHT$`HL$(xHHHD$8K>HH\$hHl$pHt$xH@A_A^_H(XyH`H`pLWHPICI[Is HIcd$@DP%eH%X@JHEHEJ>AH9=h%EH0l#HM评HUHM蒫HH 8%HMJEHl#HMwHUHMZHH %{HMEHf#HM?HUHM"HH %CHMEHPk#HMHUHMHH % HMEH k#HMσHUHM貪HH (%HMjHM}tptHM[H$%H]HKAAHU}KEHUHMKE3LHޙ%H]HNL%PHKAAHU|K|EHUHME3LH%H]HNLi%E3HO%HNHMIH%E3LHgNLIHMhqHMJ >IHM'H3L$I[@IsHIA_A^A\_]H8qHUVWAVAWHhHHEHXH~%H3HE'H1HAXLpHee ш%eH%XA@HJ;HEHEJ;tI6HHHMHHHMIVHM?HHM?HM|{HHM>HMg{HHM>HEHD$ AL]%HHMmHLHu,H+HAL7HXi#E3HU8HgHHMAHU@HfHsD,HUHM'EINHHUnt2HH|HM8oELHU@HMmHHHMfHEJ;HH$HpA_A^_^]HPmH(fHUWATAVAWHhHHEHXHp )p)xHHHeeD%eH%XA@N4K&HEHEK&3HKn=LHu,HHALHg##E3HUoHeHHMoAHUwH|eHqD,HUHM&0xX HEwHt H|\H3u}]IWHL LEHO(H(t141HHzH8HMo躭LHUwHMkLHUoHMXkHHHM eHEK&HL$I[0IsHA(s(|$pIA_A^A\_]H8kH(dHUWATAVAWHHHEHXHp )pHHHeeD%eH%XA@N4K&HEHEK&3HK;LHu,HHALHe#8E3HU8HcHHM脯AHU@HcHoD,HUHMG$0*HE@Ht HZH3fuIWHL LEHO(H(t1X/HHyH76HM8ޫLHU@HM6iLHU8HM|iHHHM-cHEK&HL$I[0IsH(t$pIA_A^A\_]HPiH(bHUVWHhHHEHXHv%H3HE7LHHd$(e ۀ%eH%X@HLHUHL$(hHH HEH7HHM7H3@H$ H_^]H(hHUVWHhHHEHXHu%H3HE7LHHd$(e %eH%X@H HU8HnHHMbHH %胆HMrEHU#HM8tHU8HM芛HH %HMBEHHM8otHU8HMRHH P%sHM H+%EH!^#HM80tE3LHU8HM0?HEK&H$HpA_A^A\^]HXscLWH@ICI[IsHIcd$0z%eH%X@HH3ICICH3ISH |%?mLD$PHHL$(MbHD$8H3HH\$XHt$`H@_H(bLVWAVH@ICI[Ik HHIcd$0Dy%eH%XA@JJ3ICICJ33HN2HHu,HHA@LH]#CeE3HT$hHZHf,HMHLEt&HHpHL$h`9LHT$pHL$(`HHHD$8J3HH\$`Hl$xH@A^_^H(aLWH@ICI[IkIs HHIcd$0Dx%eH%X@J4H.ICICH.PHD$PHt HSHLCHT$PHL$(W`HHHD$8H.HH\$XHl$`Ht$hH@_H(`HPrHUVWAVAWHHPHEHXHHeeDw%eH%XA@J#HLUH?#HLHpHL)H?#HnL#H?#HXL-H=#HBLGHx?#H,LHr?#HL; Hl?#HL Hf?#HLHh?#HL) Hb?#HLHHL]HrHHHM"zHU8HHHMdHH 7e%dHMaPHMWPHe%EH=#HM8RE3LHU8HM0HEK&H$HĀA_A^A\_]HhBHXOLWH@ICI[IsHIcd$0)Y%eH%X@HH3ICICH3ISH Xd%KLD$PHHL$(@HD$8H3HH\$XHt$`H@_H(pALWH@ICI[IkIs HHIcd$0DyX%eH%X@J4H.ICICH.HD$PHt HSHLCHT$PHL$('@HHHD$8H.HH\$XHl$`Ht$hH@_H(@HPhRH\$WH0HRHH j%IHRHD$(Hlj\$ D$ H\$@H0_@USVWATAUAVAWHl$HHEH`M%H3HEMMHE3LeDeNjCW%eH%XA@H4J.HEHEJ.HyHHIHĉD$ MHLGHUH i%HHWy)HMr HHMvHH-NHEEL$bHMI HHMHMHM5qAV+HMf.HHMHMT.HHMIHMHHMHEAHD$ La%HWHM;HEJ.HMH3rHĘA_A^A]A\_^[]H@>HUVWAVAWHHHEHXHK%H3HEHeeU%eH%XA@HJ;HEHEJ;H1HAPLpt*HHLHMHHMIVHM HHM L`%HUH#HEHD$ AL`%HHM:H HEJ;HMH3DH$HĀA_A^_^]H8=LWH@ICI[IsLHIcd$0DT%eH%X@Jx)~5uHHu H`0#Ho0# Hv0#HcS@HM0 S0HM ƃHE HEHE0HEHEHD$ ALGV%HSHM "0HHH@HEJ7H$H`A^_]HH 3@SH Hً AutHK(Fws HK(S: HHt /@HH [LWH@ICI[Is LHIcd$0DI%eH%X@JH3ICICH33IIH(HL$PFLHT$XHL$(1HHHD$8H3HH\$`Ht$hH@_H(1LWH`ICI[IkHHyHHEQHIcd$PDH%eH%X@JH+ICICH+AIKAHHL$8fnHL$pCHHL$@,HD$8HD$ ALT%HWHL$p.ƇHHH@ظHD$XH+L\$`I[Ik I_HH0@USVWATAUAVAWHHxHEHL3H]؉]DG%eH%X@N$I HEHEI 3HNLE3HUHH/)H75L,DCHUHH)H5H,HE`DCHUHH(H4H,HEXDCHUHH(H4H,H}P>|fDCHUHH(HJtJDCHUH(HUHH`1HMHqHH,HHMHaHLHܔH|$0H\$(HEPD$ DMXEŋU`IJI HMH-DHIHE@I IHxA_A^A]A\_^[]HP*/@SH@HaXHHa`HahDT$pDDD Aw A@u Aw؉t-tt#t tAw1HK(d6DT$(HK(DL$ D0CtH*+#H^HD$xHH$HƃC H@[HHHUVWAVAWHH`HEHX D)XE3LEDE E%eH%XA@HHEH)#HM8HEHj)#HM8qHEH@)#HM87ICIKJ >H=}tx3L5}I3H xJ9L7tBAHH$#ND7JT7HL$x(E3LD$xH$HL$p/HH<[HJ7H8uHD$8J>H@A_A^_^[H(@UVWHHPHEH\$pHHeeD)%eH%X@JH3HEHEH3HM E3H|Htm3L|HMH+DD E+uHEuEtAHHRIHu-IcH@EDITHM0p"LE0HU0HMHM0&LHU8HMHHHM HEH3HH\$pHP_^]H8H( HUVWATAUAVAWHhH HEHXH%H3HEHHE3D9=*%HL$0%HHL|$hD|$p R(%eH%XA@L4K&HD$xHD$hK&E3HT$8H HHL$0lDHL$0HL$8u7IHN#!!HHL$0HHٷHD$xK&NHDHT# LHT$HHL$0HHL$Xx HD$XL%##IHHELD89t9 tHD89uD89tD9HL39 tH8uAHT$0HHu1DHC#HL$0I HL$@H HHgAHT$@HYHHL$04CH\$0HoDHL$@uH\#HL$0HI"LHT$0HHT$PH'LHH,EHDHL$Pu H4#9H`#{LHT$@HKHHMHEHLELeHE3DHL$Hu)H#,HHL$8HH@H#LHT$8HHT$0HVKH.H,EH>DHL$Hu H##HZ#LHT$8H}HT$0HKHH,EHHE8$uL}EDeHHF8$(uLmEDeHEHEHEHEHEHEHEHD8$0uHEuDeHEHEHELMAHcVH T)%H5&%'HL$P%"HHHMVHL$XK@HD$xIHHMH3[H$pH A_A^A]A\_^]Hh HXHHUWAUAVAWHhHHEHXHp H%H3HE'LH=g%%HL$0S!HHHee #%eH%XA@L4K.HEHEK.E3HT$0IHu2IH#HL$0HL$8HXHHMAHT$8IHuHB#HL$8IDHL$0E3HT$8ImHHL$0H?H\$0HHL$8u Hs#HDHc"LHT$0HHUHBHHH,EH*DHMu H# HD#LHT$8HgHT$0HGHH,EAHUIHHL$8s>HHDHMu H#H#LHT$8HHHMHMH]#HHEHEHRDDŽu-H#HL$0HHMHH胱H+"HMLHT$0HnHUHFHH,EHEHEADEeHEHEDEeHEHǀ<8uHE}eHEHEDEe#LMHRH x%%HY"%KHMJHHHM{HEK.HHM'H3WL$I[@IsHIA_A^A]_]HH+ H/HUVWATAUAVAWHl$HpHEHXH+%H3HE`HLE3D9-!%HL$@HILmDm %eH%X@L$I4HEHEI4E3HT$@H5HHL$8HL$h3@HEI IHM`H3QH$HpA_A^A]A\_^]HHhHHHXHUWATAVAWHhHHEHXH%H3HE'HL=;%HL$0'HIIHee %eH%X@L$I# HL$0H茶HI聤 H" HHT$8HL$00LHUHL$0]HUH9HH,EDuHEHMuH#< HMoH4#' LHUHHHMHMHh"HHEHEH]EHMu)H# HHL$0虵HI莣H # LHT$0H}HT$8H9HH,EHEHMu H#H#X LHT$0H(HT$8H8HH,EHEHEADEeHEHEDEeHEIB<0uAHEDueHEHEDEe#LMHDH .%H%HMHIHM1@HEI IHM'H3IH$0HA_A^A\_]HPHHUATAUAVAWHHpHEHXHxLL=h%HM@UHIHee %eH%X@L$IHEHEIE3HU@IH"u0AH"HM@ HHMH^HIS)E3HU@IHHMH-AEH"HML LHU@H}HHHM@trHU@HMHG-HMHEDŽu Hx"`Hl"HMH HHU@HM@ -LHUHM@HUH76H@H"EHM@u H`"H" LHUHH`HHM$HEHMu(Hq"T HMHHI H", LHUHHUH5HYHqEHMȄuHW"HMH"LHUHHUH-5HDHUIHuEHC"HMDHU@IHHM@ HIHMHEIIL\$pI[0I{8IA_A^A]A\]HPH@HUWATAVAWHhHHEHXH%H3HE'HL=+%HL$0 HIIHee y%eH%X@L$IHHH H0[H8HcH %Ht"H %HtLAH9%xH8H8HcH %Ht"H %HtLA H%xH8HL$WH0HD$ H\$HH3HAAAHZdHHHHG 聵HCCC8 HHS HH HQHC(HHG HxHH\$HH0_H@DHL$SH0HD$ HHcHHHK 7/HH0[H@H\$WH HtHCHH\$0H _@USVWATAVAWHl$HHEH$H3HEIILqHee %eH%XA@LH\$HH>Ht$XHl$PH A_A^_HHXHhHpHx AVH Hy(HLwP4H7#HHv0HKL3HKHuH7HI;uHM0HMHtH\$0Hl$8Ht$@H|$HH A^@SH HHIHtH HtxH [H\$Hl$Ht$WH Hy3A HHkXHH;t,HHYJL3HSJH/HoHXHGH;u1JLC3H*JHt$@HÉk HkH\$0Hl$8H _H\$Ht$ UWAVH$HpHp$H3H`H"HHKH\$(Lj"DD$ xHL$PHd$0HT$PAE33LHtHHL$0V3HLP ؅yHD˺ HT$@HL$0L3LD$8H!|$8HL$PE3؅yHWaD Lt$83ۅyHD˺j IH3ۅy D˺zHtUH>H3HL$@Ht HL$0Ht`H`H3SL$pI[0Is8IA^_]LHT$0HL$P؅yDȺ'H H(GuHL$(L*#PH(H\$UVWHPHv$H3H$@HIHLt3LHL$0JLG"HL$0) HLL$0HDƋHDG؅yH$hD 8L"HL$0 HMLL$0ED؅y3H$@H3H$xHP_^]HHHD$HLD$8E3D$0WHD$(Hd$ HH@SH HFL3HH [H%FHHXHhHpHx AVH @2H$MHHHt<HDDHIHH HL+J D9St H[Hu3HtDH;t>MHLHtH~@HHKHHHOH[@ HuH$Ht H@OH\$0Hl$8Ht$@H|$HH A^@SH H@HHuHL$8DϺ;WD$ tl+LHL$ IHyHL$8DȺ>fHK IXHCDHD$ 3I&Hd$ HCHD$(Hd$(HCQ'fk HK(3C$DE7'H33HHL$ HtHH\$@H|$XHl$HHt$PH0A^H\$Ht$ WH0HHT$HHL.uy3HNHN3H\$HHt=Hˋq=38$uIH$Ht Hu0H^>L3H>H\$HHtHH\$PHt$XH0_H(FAuHL$(L~ )H(HHXHhHpHx AVHPL$ILpЋH&؅~ ؁\$8E3D$0LLt$(Hd$ HHl$hH\$`Ht$pH|$xHPA^HHuAHH<uH3HuBHHf9AuHEHHHD$HHD$(HHHHHD$HL"DL$8E3D$0HD$(Hd$ HH@SH H$3Hu! HHu"=H$Ht F؊H [HHXHhHpHx ATAVAWH DALyBHi(I'La@AHB8LfAHeAHHA0HI$$HA8HJIN0HINxH}HH{HtH9{Ps<#<LǺH <HHt<LCH3H;HsHH{PHKHHt:H[PMMF0HH2MFxLHH MFMHHH\$@Hl$HHt$PH|$XH A_A^A\HHXHhHpHx AVH@3H9iH@DuXH9iuG@tBG;UAH-;HCHt!HC HL$(fD0IH;uHKHtr@t6C HkXHHT$8H;t!DCHD9AvF9tCIHAH;uC"AK HCfS"DC"AHkXHHKH\$PHl$XHt$`H|$hH@A^̺MЋLE3fE9t IHuHtTLL+JAAI+t3ILL+MtE fEtfDIHHuHu HzfDWLD$LL$ SUVWH(3HBH=HWGx5HZHHLL$hV@xHH;wuf,^f,^zHtf.H(_^][H\$Ht$UWAVH$HPH$H3H@I MLHL$0L"HL$0LD$03H<HHu.7HhLr"]d$$HT$$d$ HyHhDȺE~L8"HL$0LD$03ҋ;HHuHT$ HyHhDȺH HHcL$ HcD$$HH I3HtHH@H3L$PI[ Is(IA^_]H\$WH H9HHE3:3=tt=t HL$(̩uHH HH\$0H _H\$WH0HD$(33ɉ\$ Y:Ht HH-HL$8L+؋H\$@H0_H\$Hl$Ht$WH H1HHHt5H΋5H\$0Ht$@H/Hl$8H _@SH d$@H3HT$@D$D5u{5~  |$DtD$@3H [H(Ht7uHL$(L!"PH(H\$WH H,A HHH $Ht HH@ @H,HHcHc Hc(cHKHt ZHcHK Ht GHc 3HK(Hc0HÃc8c<H\$0H _H\$WH aH?,HHHIHt HgHO Ht Hg 3HO(DHO(Hg0g8g<HO HOH\$0G H _H\$WH HXtHHH\$0H _HHE3LD9QuHL$HLr̅tDQ< A<;A8sAuHx-ILA*Q؅tI0 D؅tH'H`H3L$pI[8IsHIA_A^A\_]HHXHhHpHx AVH 3ALHE~/HzuDHcH IH ct H(;|Hl$8H\$0Ht$@H|$HH A^H\$Hl$Ht$WAVAWH 3ALHE~EHZD{u,fD9{u #E;CDHcH IHzbt AH(;|H\$@Hl$HHt$PH A_A^_HHXHhHp WH0DA03H)HpHمy u3T$`L@It0Ht$@HtsDE@EtjHU8H\y uVT$`LD$@I+t u9s$uHSH C H\$(VHt$@HtDE@Et HU8H-LƋHF w5s+y u%9q$u HQA HL$(HAZ;u E38H\$HHl$PHt$XH0_H\$Ht$WH0Hy(H"uHBH;F >uHBHHH+FuHAH+F HtHI΋LvC؅tI# D؅tH'H`H3dL$pI[ Is0IA^_]H\$WHH$H3H$Hy0H@NjH$PH3H$H`A_A^_^]H\$Hl$Ht$WH 339Hu!1yuAyuAy uA yu!qy5uC{uCuBHHHHǃ{0!s0@@HHH9='U@H HtwH.HE HHt5 HC(HtJHM HK(HHC(H98t0C0{@uH!{8!{@H9{HutH ޑ" HCHHu^HHtx HHC(HtHHtY HK(Ht J Hc(HKHHt 6 HcHHt H# H\$0Hl$8Ht$@H _Åp@USWHH He(He He0wHM( uHM(u HM($t0LE(HU HM0wHM( tHM0Htx HE0HtHE 3H _[]HHXHhHp PWATAVH HDrAP 3HHuEHAfAIfA;|H $HtH u"\$HHHL$H D$H>IH|fDLMEA(AADڊ9AC!D9MAk+ȊM+uHB 3H\$@Hl$PHt$XH A^A\_H\$Ht$WH :HH;HtuH8uL#"HHTHt~ u3HDB  F L"HH!Ht~u3HDB  FLՎ"HHHt~u3HDB  FL"HHHt ~uFHH u8H\$03Ht$8H _H\$Hl$Ht$WAVAWH y0HHt539i0~3HK(H 9 H;k0|HK( Hc(K03H@8.u/c03H\$@Hl$HHt$PH A_A^_EuHNJuH*u8utHcH' HC(Hu3@8.E3k0H>tuH8uLL+IOHK(IHC(I HtMHHC(J 0H+H9HuI8uk0H\$Ht$WH HI3HHA8<uH+H;rLHuH<3H\$0HHt$8H _H\$LD$UVWATAUAVAWHHPLcM3HHUDHUHUIA } %AfDAID Fff ȸf;uEHEHEH~ HD$ HLMH%؅HcUHN&LEHJHI;vHM[qD!uXBHcHEQHEHELMHD$ HH%؅(HcEHHHW H;UfDGD GfG GfDG HD A!AKLHHEHtLMEGHff LMfAIOGff fAIOGff HEHfAIIHOHD$ $؅u7HM HeIcDmXHADmXE;  LmPHMHtHMHttMtIDMu3H$HPA_A^A]A\_^]H\$LD$UVWATAUAVAWHHPE3LcLmHLmELmM(A } AfDAID Fff ȸf;uEHEHEH~ HD$ HLMHq#؅HcUHN&LEHJHI;vHMqBHcHEHEHELMHD$ HH#؅HcEHHHW H;UfDGD GfG GfDG HD DEXujAudAKLHtnHEHtLMEGHff LMfAIHEHIHD$ HON"؅u0HMHcEXAHeHE;  HMHtHMHttMtI HEPL03H$HPA_A^A]A\_^]HteH\$WH HH -H{ HHHHuHKHKH HKHH\$0H _HHXLH L@PUVWATAUAVAWHhH3LcEMLMtIA } AfAI AGff ȉ}f;uHEEIw HD$ HLMI} HcUO'LEHJHI;vx %BHcHMtQHLHu xLe-OHLHu"HMIAFLLLe]lj]w]ӅH]H]LuLmDEgHELMHD$ IHyHcMHLF L;ENFVffDND F DMFfDF D F DUF FI ЉU˃AAHMIfHMMtHFH;LEALEHUHy HFH;{HMEAHMEHDMIHHUHMLEAudMt HMHEH HMDEgHEEwLMHEIHHD$ C IELe9E~E HMHcEHH;uEE;E%Lc}NjEwEuMtHIHuoH lHHthAOHcHSHGHtEL'DLwHGE~HGIcAHIH HI;|HGJ3H>cHHM Mt$HcuwH~I HH;|IIIH$HĐA_A^A]A\_^]HHXLH L@PUVWATAUAVAWHH3LcEMLMtIA } AfAI AEff ȉ}ظf;uHE`EIu HD$ HLMI2pHcU`O/LEHJHI;vx %BHcHMtQHLHu xLeOHLHu"HMxIoAFLLLe]]X]ąH]LuDEHHE`LMHD$ IHonHcM`HLF L;ECFVffDND F DMFfDF D F DUF FI ЍGU;D;uAHMI&HUMtHFH;HMAHMHy HFH;yEDMиEHHMAudMt HMHEH HMDEHHE`EXLMHEIHHD$ IELe9E~E HMHcEHH;uEE;E=HcuEXuMtHILmPM BHHtvNHcH*HGHtTL'DLwHG~IcAI HGH HH;|HGHuMt II}3cHHM Mt$HcuXH~I HH;|II}ItH$HĀA_A^A]A\_^]MH\$Hl$Ht$WH0HcIHiHHH~HHGH;rhH+HG HFHHOHtHH~HuJH!HtHV E3H!EAHfPH\$@Hl$HHt$PH0_HH+HG3HvHHXHhHpHx AVH0HcMHiHHHH} u/H}u"DHH"HMw}(J8HHu!D$ D@E3HHLH`HGpHHcGxHc HCH{HEPHtHX *H!HtHU AH!EcH]HEXH]PHcHDLL$HLHrLL$HLHHT$HH39~33H8tLD$HHYHLj;|H\$0Ht$8H _IH\$Hl$Ht$WAVAWH03IMH9DE3HIHK HI;E3Ƀ{,HcS,EAD+C,H(HHcȅ-HuLŋHqK,{,K(C) ȉK0HcHC8HuqLŋH0bDC0HcS@D+C@HS8DHcȅtK@DC0D9C@u8HS8DHl$(HD$ HK8HtHc8c,c@Iƈ;H\$PHl$XHt$`H0A_A^_IH\$Hl$VWATAVAWHHq$H3H$p3MMH93HH|;;L9|;<;HT$`AHDE3ɉD$0HD$0HL;HD$(HD$8HD$ LcIu0uuMMċHXD$8;;uW<;t!<;uKHD;H+D$@u HD; H+D$HHD;;D$ttA$uIiIHtIML#uMu$EIfGfDgHEH83]Mt IunHtbHHtH_Ht! HH[HHuHOHGHtHHtHOHHMH3H$HĀA_A^A]A\_^]@SH ILʃt&uDAHI!?'0AHI;uu 3 ~H [HHXHhHpHx AVH 33LHtRH-_"HHHHt4Džtt(+͍AuÅt A3H\$0Hl$8Ht$@H|$HH A^H\$Hl$Ht$WATAUAVAWH @133MHLL@tFE3H^"@HIBHHtCŅttHR^"+فvE3H\$PHl$XHt$`H A_A^A]A\_ÍF<wIԈIH@/t03H^"3A6@stHI+HIIqH\$Hl$Ht$WATAUAVAWH 9Hq3L%]"ILLA0,XLfE8<${A $BhHA<$E3Iy@szDAtiAt pL%_]"IA+Eu AAuHHH(AIE3>HƅuEtHHHAIL%\"A/utD8>*M;>H3ۋI/HȍA+A >Hƅt#A:s@uuM;'A} L%["u3ۋIA+č He>HƅtA:s@uHHHAIƅ/.u>HA:s@yH\$PHl$XHt$`H A_A^A]A\_A}rA}r E8}ۃIHcI+HH;} AA+u A}CDIHcI+HHHHtAIHH;[8'HH\$UVWATAUAVAWHHpHV\$H3HE3LEH!EH]HEHHEHU<:u HNJ<:3H}ЃME3uE3MD`LmHPZ"AHHEHHHuuHZ"AHHEHHuVA:H}EuH9EwH]Y?hHEL;wUA3IE3D{HE3M&+MADD EEAD7Eth539A.u5H{HEH;HMLEHfuANHJA/HUHuEt!HCHMH;AD{HMuAFAEPA;EXAL…LUAEHcHELHt8HH+I;t2H|$L@MLL+L+ACAIHuII;t&FALcL;Ev8'HMHUHMH3(H$HpA_A^A]A\_^]HHXHhHpATAVAWH0L@(ELHt HL$x`H\$pHt2HD$xEHD$(AHɣHHHD$ 蕪H@HHuIH0HCHu HكK(Hlc4Iփc8Ld$x3HCLc CD{A <.uHŠu;N |2c,HH\$(EAHD$ IC0Hکc0LD$pC,IHV(Hu2HT$pH[H\$(DEEHD$ H莩HL$p(HKHĨd$ E3E3}H\$PHl$XHt$`H0A_A^A\H\$Hl$Ht$WAVAWH HMHHLHÀ<uHǀ<uHKHMIHHuF/LIH葯HK.HLH{H>D3H\$@Hl$HHt$PH A_A^_@SH0HDL$ MDA4HI HCHKHH0[H%H\$WH0DA4BH9MH٩y0tQ(uQ8HcA,;G0}dHW(LD$@HIHtE3ɋE3HDKHDCHHT$@c0C,H\$(HD$ 譧HL$@bQ(u.DIHADAHQHL$(A0HHD$ l,uy8t E3E3AQE3E3DL$`MH\$HH0_H\$Hl$VWATAVAWH IHLHHǀ<uHd$X.8T/Y@;HH)H %T"wHHQ"H6LHLD$hIHT$X؅Ld$XLIH uI< tH u8tH{xu HNJuHH+HMsHLHtLHH輬L+A>IQIxHYHL$X8I_ tF|~ H&+A uA~0tH&3H HHЃH\$PHl$`H A_A^A\_^HH T$H3H$3HL$ AHL$ D$ u-3HL$ AޫHL$ D$ u31D$0t$tt u H$H3谔HH\$Hl$Ht$WH HAH陹HHcLHfu"t /7~3x!˅3H\$0Hl$8Ht$@H _ÀH\$Hl$LL$ VWATAVAWH0IcLHE=!33HHu DeIcHGpLHu HHcHHHu IAGLAIff H_fAHGp@hHOpHHGpHDgxHHҤHH$H9NuD9~(HHDHRH\D;|ۄu ˉLGHLJ HWXIHIXIxH_(H_0H8H_@H_HHPHHzHJHHHHPHHcHH@H IHHIHL@LDMbAiT$xHD+HAiLD$xD$|HD$xHD$x3ۍSH$E3E3\$ YH\$`Hl$hH0A_A^A\_^H\$Hl$Ht$WAVAWH L\$pE3AH|$hADHEWE;L?D89t79\u HAD88HEHAD89uy.tAA~  ABHcA\HHHuA3HAfA@qD9|$`t AfA *"+u S)"+ЅuHH p<.yEHӄt*:.t:\u HBD88HEHAD8:uA?EDH;.t;\u HCD88HE؊HHD8;uD8;t HÊuD9AAA3@iDqH\$@Hl$HHt$PH A_A^_HHXDH L@PUVWATAUAVAWHHHEhE3HcHEL!( } AfDAID Fff Deܸf;uHEDH~ HD$ HLMHHcULLEHJHI;vX "BE3HcHAN@mHEHu XLemD!mELeL!mHEDLMHD$ HHx؅HcMHHW H;UGL}ffDOD G DEGfDG HD DMA IIUDEHHELMHD$ HH؅Mt IqLuHHA<uHNHUHHEH HHLIC<uIHHA<uHMAHEAŋED;|XHMHcHEHtlDEHEAu/DEHHELMHD$ HH؅uMILeIHcEHH;}w5D}AD}D;}}-]H/IqIc8I` u MuIcK /HHHCHHLc}XIL}HHsH>AEHcHHCH3L3E~L}IHKHHH;|L}HCMHUPH$E`HKfCEXfCH ٢HCHMH`HEhHe3nHMW Ic!HDHK:H1L}3H~I HtHH;|IMt IIH$HĀA_A^A]A\_^]H9Iu H9 u3HQHtHHPHQHHH!HaH(LHAIDAHbtHbHHR"JfofsfH~HfH~HPEtI`MM@$AA`fofsfH~LfH~L@H(IHHA.H\$ WH`HH$H3HD$PAHQIDAD HL$@D$0T$(DD$ LrG"HcH;r3LD$@HHHHL$PH3̉H$H`_H\$Hl$Ht$WAVAWH 3LE&'H3IcELrIָH+H9wHHHH;|HtXHHHuH HMHIVޟI.MvHuE3DHI]HHcYH3H\$@Hl$HHt$PH A_A^_H\$Ht$WH0HzHHHt+HsHHF HCHHNHtHH{HuHcPHK8HtHc8Hc,HS H;tALH?HtfHHH9H8uHH| tsIHBH;rL<IqHtHM>ALH+H޿HuHuHÿٍY H\$@Hl$HHt$PH A_A^_È\3DAtODIQAЃt3fD;t(0fD;tAA uAu Hyu3H\$LL$ HT$UVWATAUAVAWH AE3DAHT$`MHAt3MuOIt7vttހ9u#H`$HtH%tcK$ CAM<*MMIMD<,MD,< MFMLD$hM;unN{4@7wk{@A Kl h9yj+B+@ HA:?HK @HZ$C놃-&P'*+ ++ + + @  A:C.MHq_$Ht < 6 @P, C @ՈSK@  A: HKAD @ wHTHrA~uƸÃ~AA;t<uAH 3"H AA"tKA#tE9AH 3"H AA"tA#A?"AH g3"H AA"tA#tRA?AAH $3"H AA"tA#tA?5ø3Hu@Ë 3Hu@Ë E3MuA@5t'tu HIA@I HcIAH\$Ht$WH 3HHH9(u#H93"KH(Hu H(HHt$8H\$0H _@SH 3LMu@UHH+u HBH+Ht&HH+2"u HBH+2"Ht I@IH HAIH [@SH  uHtHHB`S]H [E3Ʌt8t t.A@,t#I@H=vAWDAAH\$Ht$WH yAHHvH L‹CL+IL+MHAKHH+1H;Ht$8CH\$0H _@SH HQ`HHHH+A`HQ`HHHa>xH 6ǃH0H [H\$Hl$VWATAVAWH HHHEH+q`LH u  3f;0DgADHH\$P utH duH\$PHT$PHA;t x5H\$P3Eu't#H\$Pº HH+M`HH+I;E‹H\$PHl$`IH\$XH A_A^A\_^@SH HA`HT$0HD$0H'= u,H ߄H0ǃ  DH [HQ`HHH+A`HHH"HQ`HgǁHDH03HQ`HHH+A`HHHʆHQ`HǁHDH03@SH HA`HT$0HD$0H%xHD$0Hf8]u H [k&H [H\$Ht$ UWATAVAWHH HA`E3HHE0Af8-uHHU0HE0}E3HU0H?dHu0f>.u>HHU0HHu0g<EHU0H#Hu0EfEfutHHU0HHu0HM0f+fuHHU0HM0HAHU0HyHu0EHH+C`H=v  |D>HU0fD&EHK`A DH9u0t  D=u!HK`H3-"LL+IIu*Au}HK`H!-"LL+IIt\LI~MfrIIfD LHS`IL+II~rM6Lǃ}ǃDjHysLE0HU8HK`(H9u8Hf.ztWsc"f.z u +ǃfD>HH+C`HHHs`H\$`Ht$hH A_A^A\_]H(Hf8u0H;Ahr*H+A`H=v H5u  H(H\$Hl$Ht$WAVAWH HyAMHEH؅x;L6HLII }t I .HHH+GXHHHOXHl$HH\$@Ht$PH A_A^_H\$Hl$Ht$WAVAWH HBIMHHI;s H @WlHII+I;HBHH+H;w H 1WDlE3Ht[H,9E3HH9tEH~rH6H{rH HHCJvLH A{H{HkrHHfDGDE`3DMXLUDL_hHWlGHG HtH@GAAȸB+k;uwA$<tH-"ID$ HWlAA΃;O(v H"θE333ɉG1AA։GAAD$LA D7'HWlH"ID$ E3GtyEYHMAًD<HG HtHP0HtOH;H8sD<GHHMEtA;rGtHDËO=GE3ɋD+HEE HG HtLH0L}L_hDE`HWlDMXLU]PG3HO HtG AHt9ȉHDF<HBHHJHHHK$HcHFHC H\$PHl$XHt$`H A_A^A]A\_H\$WH HHHy(HtxHy0tqHy8tjaa Ha AHHGg(HG G,y؉G,G,Ƀṃq,Ou3 E333mCLHσg@$Q3H\$0H _H\$Hl$Ht$WAVAWH 3AHLEHHY(HH{,{,u {*9s,t ILAFLs3CD;v +DHHKPHELHCPDDSp@3#S|SpAHCPNHShDCLD CpHK`D3D#K|L#DKpBJfBAKpHChf4HA;vPH\$@Hl$HHt$PH A_A^_HHXHhHpHx AUAVAWH 3L-lDHًwD=s&H~ =s E*A;rhHCPDHShAIDCpHK`D3D#C|CLL#DCpBBfBICLSpH#HC`,HHKhfQtFCD+-;w2B;v Hx A;u;uH' D9AHDfD+fDHA*׋HfDB(л)HcffE;s A AAHB(м)DHcf +9A);D9ȉHCPDHShAIDCpHK`D3D#C|CLL#DCpBBfBICLSpH#HC`,HHKhfQuHSPDDCpAD3D#C|DCp^DHCPHfxHSPHDE3D+H@H H9x.3H\$@Hl$HHt$PH|$XH A_A^A\9tEHCP+Hf;sLu+х~ ;rL}uDAAu9Eu IADd$(BHT$ t A$ %H!H!H&!IG A$AH+؋L+D+иA#HCII+I@IGIFAGHAGA|$@ET$DH(A_A^A]A\_^][Hu3H\$Ht$H|$H5!DAEHEt$t AH3HDD3AuA "AHD3AHAHDAHD3D3AD3 D3CEAHAHADHD3D3AD3 D3CEAHAHADHD3D3AD3 D3C EAHAHADHD3D3AD3 D3CEAHAHADHD3D3AD3 D3CAHAHEDAAHD3D3AD3 D3CEAHAHADHD3D3AD3 D3CH AHAHDAHD3D3AD3 HArVEID3AEHAHAHADHD3D3AD3 IuEt AH3HDD3AuH\$AHt$AH|$H\$WH Lѿ_ffA  ~LAR(AIJ AB(AR(IJA A*AB(fAfA AAAE3AffA  ~MAR(AIJ AB(AR(IJA A*AAB(fAfA AAIA A+  ~WAR(ffA AIJ AB(AR(IJA A*AB(fAfAfAfA AA ~\EB(AIRffA AAAB(EB(AIRAA*AB(@fAAfEfAAfE AInAǂ H\$0H _HHXHhHpHx AVH AAE3HHEqD9~ZEtHD9pHuH@ HYHX HJHDȋ ;wAPʍG;wHtDDHHUAD9; ~XS(DFAff HK C(S(HK *C(fA胃fDA0ff AD` AH AHL H ~XS(DFAff HK C(S(HK *C(fA胃fDA6ff AL"H "HH tH\$0Hl$8Ht$@H|$HH A^Hǁ H@ H)#HP H HX HM#Hh H Hp H#H 3f LLڋ ~]AR(AffA AIJ AB(AR(IJA A*AB(fAAfEfAAfE AII̋LɃu5DA(HQAA(Q(AHI AA(3A*|-Q(AHI AA(AAfA̋E3LɃ~DA(HQAA( ~AQ(HI AA(fEE@SH DH HH D` H H Hp HCH " f u HH}ߍ EH [H\$Hl$Ht$WATAUAVAWH HBE3H2HLELcpLDeDǁ=AE~;fD9t#DAHcD D9fDTEII;|AKA;}AADHc HcfD$D8Mt AD)D9|jAA;|DHHi A+A;}HcEHc H֋ H2 Hc HHcMcΉ Hc ffB;9:sAEA9HfDtHfDtD ED9;ILc B =L HH\$PHl$XHt$`H A_A^A]A\_HHXHhHpHx ATAVAW3MHLD]9]L%CIAD hI|EHcADLA+;~_DAR(AffA AIJ AB(AAR(IJ AA*AAAB(fAfEffA B F'л)AtA+;~bDAR(AffA AIJ AB(AAR(IJ AA*FAB(fAAfEffA 1AG)EC+)AAA+;~\AR(ffA AIJ AB(AAR(IJ AA*A@AB(fAfAfBfA AAAs C!м)AB м)AtA+ƋA;~bEAR(AffA AIJ AB(AAR(IJ AA*FAB(fAAfEAffA 1AE )EE+ )AAA+;~^AR(AffA AIJ AB(AAR(IJ AA*A@AB(fAfEAfABfE AA;AA+;~gDEB(AIRffA AAAB(AEB(IRAGE*AB(AfAAfEffA 9AH\$ Hl$(Ht$0H|$8A A_A^A\H\$WH AHLtEK(ICAǃ DfAAAC(EK(ICEAC(AS(IC AC(fAS(ICf AC(HIKAЈ AC(EC(uH\$0H _H\$Hl$Ht$ WATAUAVAWHBH rE3HLEщt$0L8LhAID`HcPAfIcIc fDLA=AHcI;hM L+M4AIc>LDL;~DfL;PHcfA@ 3A;| A+HcAtB<AMtCDAt$0IAM+tE3EDJAE{IcfE9H uA+HcfE9@ tHcE+fE@ AHcfEH fEP EtbLcHcA@ tJM O M+MIA91/McBD;t+BAfBTAA+uA+uH\$8Hl$@Ht$HA_A^A]A\_H\$Ht$WH0H#H3HD$ 3HcHD$LDL+wDKHfDfEfFLLI~Hׅx>EDEt+F DBfBDAD+#A EfA HH;~HL$ H3H\$HHt$PH0_E3HEHfDH@I+uH fDH@I+uH fDH@I+ufDLDDH\$Ht$H|$IcG HLc y};AQHcLc IcHc fB9ruA8 wDIcLc BfB9r4uA A8 v IcEED D;xH\$Ht$H|$IcD HHXHhHpHx zE3Lɍ^D^u ^AA@HcȸfDIcEHL@DHc:E;};toD;} fE 3t;t fA fA A  fA fA E3ҋu _A;u D[ D[HL+rH\$Hl$Ht$H|$ H\$Hl$Ht$WH HEًA ~YDS(Aff HK k(S(HK M*k(fAꃃfDƺf+ff A ~WS(AAff HK k(S(HK *k(fA胃fDAf+ff A ~XS(ECAff HK k(S(HK *k(fA胃fDACff AEL !MӋA ~]D S(Aff HK k(S(HK *k(fA胃fD Aff LL+mDFHH/DGHH H\$0Hl$8Ht$@H _HHXHhHpHx ATAUAVAWzE3LLڍCKDkuAIcE AIkLrEgELc}D;} D;D;C AA+;~fG AQ(AffA AII Ey(AAQ(II AA*CEy(fAAfEC ffA AE+ZED;C AA+;~fG AQ(AffA AII Ey(AAQ(II AA*CEy(fAAfEC ffA AE+A AA+;~eE AQ(AffA AII Ey(AAQ(II AA*CEy(fAAfEA ffA AA~bAQ(EBAffA AII Ey(AQ(IIA AA*Ey(fAAfE@fE+ՍA!AAA  A +;~eE AQ(AffA AII Ey(AAQ(II AA*CEy(fAAfEA ffA AA ~bAQ(EBAffA AII Ey(AQ(IIA AA*Ey(fAAfE"fE+ՍAA +;~eE AQ(AffA AII Ey(AAQ(II AA*CEy(fAAfEA ffA AA ~_AQ(EBAffA AII Ey(AQ(IIA AA*Ey(fAAfEfA AfAfE AE3Aۅu D;u AHHM+H\$(Hl$0Ht$8H|$@A_A^A]A\3LDLfA9uIII | u#HDf9uIHI | I‰PHf`X&0&   `  P0hpP\\[] p[P[pf0f pp0 p   ` ``  `PpPpP0pk0kpk0 pk 0ipk `jpk Љ+p+``I)xN)oR`I)`I)7N)d N) K)pȳPx'ȳ `I)N)K){K)!K)`I)K)0na O)K) `I)H`I)'`@'xA'?'5''E'M'F'(7'@'`Q'p4''&'H'ȵ('8'O'B' D'0C'@G'X:'hI'6'=';'9'жL'3'fI)deI)q 8!Ph J)hx L)jgI)khJ)l0mJ))N)xз&(no*(K)O)Ps`tpuvw yи'xظz{ȳ|0N) N)K)P}`~p K)iO)p@N)ع `I)L)L)$ " 8P`pHrкЛP0   `[0[ЛP ``[@@@0[@   &&`&PQ0-&0@pk ؇+PX5!-.fjp.l}D}0n"f"#B#.б\#З -p>h=pImOHa8pA{`A5o p pTX  @ ` /H @ y8 p vh  p l pl d d 4 /"Г ȓ   ( EY(  >  7 @ 4(   x   P Z 8    \  u Seu V xU 0* +* 0 !-mfjp.lD}P""bB#3.@б\#З@ P '->h=pmOHa8,{`Ao  pTX `[@ 0B/H  y8 PRvh `Ap p'pl d /"Nȓ = EY( 0> 7 `e4( X x  Z 8  \  @1Seu xU +*  ؀++x++++@++++(+h+ȁ+P++8+`+,1/ܑ+Pp@` p@`  Y@@.. .P  @ZЛЏpZЛP0 0 Z@@ @ `P   @[[[@```)PQP)PQl z@l @~l  @@l @}l @l `@|l @l `@l  @0l P{@l  @|$PQE````` P``PМ З ЗЗ З З З"!-T(fjp.PlQ%D}pD("pI%"'B#".!бP \Pp##Зp% W$H -&(>h %=p0"mOHa8ph'{`AP#o #pTX 0Z!@ !/H @y8 #vh @"p  %pl !d 2"/"&ȓ 6  @%EY( i> Т!7 #4(  # x && &Z 8 7( %\  (Seu :!xU b"+* !f)f)f)f)f)f)f)f)f)g)g)g)g)(g)4g)f+,f+f+f+e+e+e+e+e+e+e+f+pe+f+Ze+De+0e+e+e+d+d+d+d+c+d+rd+f+g+g+.g+@g+Tg+dg+zg+g+g+g+g+^d+c+Nd+c+m+&m+m+m+l+l+`+l+l+l+l+hl+Zl+Jl+@l+4l+*l+"l+l+ l+k+k+k+k+k+k+vk+lk+^k+@k+$k+ k+k+j+j+j+j+j+j+j+j+j+j+j+}+}+}+tj+}+jj+Xj+Jj+@j+6j+,j+ j+j+j+j+i+i+i+i+i+i+i+i+i+i+xi+pi+`i+Ti+Ji+@i+6i+(i+i+i+i+h+h+h+h+h+h+~~+`+`+a+a+`+`+`+`+`+}+>}+L}+T}+^}+j}+t}+~}+}+}+}+}+~+h+x+w+w+w+pw+Rw+h+@P@ 0p@` p0PP@ @0`pPP`pP0@ 0p` @0 @Pp`` 0Pp@ 0@P`pP0p 0@Pp@P`p 0@P 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p0Pp@P` !!% ',@-.0P0`112`223p33 4p44@6 7;p<<==?`@@0CC0EF0HpHHIRRR ST U X0YP[P]^ _Pbde0ffgijPn`oppPsssupwxz@{p{{{{0||`} ~P~~~~0`00@p`PЏ0P0`М P С` @0 `p0P P@ 0 0 p `0  !0""#$' *0p111245pDFH IIIJJKLL@NNpOOPV`YЍ@`pPp`0Pи ppp00`@P 0p 0@` 0` 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p0@P`p`@pЌ@Ѝ@ @PЏpp0`0Pp0`p0`@зP`0`й@0 `pмp@о0`@` P PP` Pp0p`@`0`0`p@p`  `p @` ` P  `!! #@#`### $$$P%%%% &`&&&'@'''P(((((P)`)))P**++,p,, -P--@.../0p2@66677p8p;0<<> >`>>P???FFGPGGGabcpd eefghpiPjPk0lmnnopr`sptv`pЈ`@ pPP0з@@0P 0@P04456`78 9`; <0<0BC@EEMPNUUXYZZZ0[`[[ \@\]`^p^^^p__b`cffg hijk`n`orswwyz{{P@Л 0` P0P @ `P@ @` 0Pp p @` !""""P$p$$$$$%`%& &&P'(P(`()P))0*+ -..P11 34p56770F@G`HIJ0J0LLLL OPPPQpQpST TVVZp\^_ ab@de`ghllr`rrvyzP{||}~0 ` `pЖ0Кp`ppp@0Pp 0`0p`P`@   `0@PP P!" #$$0&P')p*+0-p---. 3@3409:P:;= >?@?p?`BCDE`FHILU`WXY imqw{` `p@Ўp `P@`00P`@0P[p[[P\\] _@`0fpfh0i`jpkkЗМTimerontimeoutagaingetRepeatsetRepeatstopstartunrefrefcloseopenreadfdatasyncfsyncrenameftruncatermdirmkdirreaddirlstatfstatlinksymlinkreadlinkunlinkwritechmodfchmodchownfchownutimesfutimes--expose_gc--expose-gcnode-debug-handler-%udevinomodenlinkuidgidrdevsizeblksizeblocksatimemtimectime-i-p-e-h-v--no-console--throw-deprecation--trace-deprecation--no-deprecation--v8-options--interactive-pe--print--eval--help--max-stack-size=--version--debug--disable-node-env-vars--cache-builtinstatENOENTno such file or directorysyscallerrnopathcode, \\?\UNC\\\?\ ''StatsoncompleterequirereadJsonPackagerequireBuiltinModulefileExistsNotDirloadCacheFilePathContextlogisLogLevelEnabledverboseinfowarnerrorlogLevelsloggernativesNuwK&M\ EventWriteEventUnregisterEventRegisteradvapi32.dllDatentdll.dllRtlNtStatusToDosErrorNtQueryInformationFileNtDeviceIoControlFileNtSetInformationFileNtQuerySystemInformationapi-ms-win-core-io-l1-1-1.dllGetQueuedCompletionStatusExSetFileCompletionNotificationModesCreateSymbolicLinkWCancelIoExInitializeSRWLockAcquireSRWLockSharedAcquireSRWLockExclusiveTryAcquireSRWLockSharedTryAcquireSRWLockExclusiveReleaseSRWLockSharedReleaseSRWLockExclusiveInitializeConditionVariableSleepConditionVariableCSSleepConditionVariableSRWWakeAllConditionVariableWakeConditionVariable0123456789ABCDEF0123456789abcdef0.0.0.0::_immediateCallbackemitexternalEvents\/:Binding %snode_%s%s_moduleconstants_tickFromSpinnerconcatStringtlscryptotls_snitls_npnipv6uvdebugStatWatcherSlowBufferrunInNewContextrunInThisContextrunInContextcreateContextNodeScriptsetFastBufferConstructormakeFastBufferObjectmakeFastBufferbyteLengthcopyfillwriteDoubleBEwriteDoubleLEwriteFloatBEwriteFloatLEreadDoubleBEreadDoubleLEreadFloatBEreadFloatLEhexWriteucs2Writebase64WritebinaryWriteasciiWriteutf8Writeutf8SlicehexSliceucs2Slicebase64SliceasciiSlicebinarySlice_charsWrittenlengthCOUNTER_HTTP_CLIENT_RESPONSECOUNTER_HTTP_CLIENT_REQUESTCOUNTER_HTTP_SERVER_RESPONSECOUNTER_HTTP_SERVER_REQUESTCOUNTER_NET_SERVER_CONNECTION_CLOSECOUNTER_NET_SERVER_CONNECTIONPerfDecrementULongLongCounterValuePerfDecrementULongCounterValuePerfIncrementULongLongCounterValuePerfIncrementULongCounterValuePerfSetULongLongCounterValuePerfSetULongCounterValuePerfDeleteInstancePerfCreateInstancePerfSetCounterSetInfoPerfStopProviderPerfStartProviderExnode_DTRACE_HTTP_CLIENT_RESPONSEDTRACE_HTTP_CLIENT_REQUESTDTRACE_HTTP_SERVER_RESPONSEDTRACE_HTTP_SERVER_REQUESTDTRACE_NET_SOCKET_WRITEDTRACE_NET_SOCKET_READDTRACE_NET_STREAM_ENDDTRACE_NET_SERVER_CONNECTIONnode.jsnode.jsNativeRequireUtils::RequireFromString Failed to load %s from bytecode cache.0:s *Dw=FCould not retrieve script from bytecode cache: %d - %sLoadByteCode: Failed on LoadByteCodeForScript, for script name: %S, error code: %dGetByteCodeForScript: thread not initialized: %d - %SNativeRequireUtils::RequireFile Failed to load %s from bytecode cache.//# sourceMappingURL=mainProxyset__finalizerObject____external__value__getSelf____hiddenvalues__configurableenumerablewritablelengthprototypeget// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Hello, and welcome to hacking node.js! // // This file is invoked by node::Load in src/node.cc, and responsible for // bootstrapping the node.js core. Special caution is given to the performance // of the startup process, so many dependencies are invoked lazily. (function(process) { this.global = this; function startup() { var EventEmitter = NativeModule.require('events').EventEmitter; process.__proto__ = Object.create(EventEmitter.prototype, { constructor: { value: process.constructor } }); EventEmitter.call(process); process.EventEmitter = EventEmitter; // process.EventEmitter is deprecated // do this good and early, since it handles errors. startup.processFatal(); startup.globalVariables(); startup.globalTimeouts(); startup.globalConsole(); startup.processAssert(); startup.processConfig(); startup.processNextTick(); startup.processStdio(); startup.processKillAndExit(); startup.processSignalHandlers(); startup.processChannel(); startup.resolveArgv0(); if (NativeModule.exists('_third_party_patch')) { // allow third parties to patch node before any script loading is done NativeModule.require('_third_party_patch'); } // if node is using chakra // load the chakra patch module in order to fix some known issues // caused by incompatbility of chakra and v8 if (process.ischakra) { if (NativeModule.exists('_chakra_patch')) { NativeModule.require('_chakra_patch'); } } // There are various modes that Node can run in. The most common two // are running from a script and running the REPL - but there are a few // others like the debugger or running --eval arguments. Here we decide // which mode we run in. if (NativeModule.exists('_third_party_main')) { // To allow people to extend Node in different ways, this hook allows // one to drop a file lib/_third_party_main.js into the build // directory which will be executed instead of Node's normal loading. process.nextTick(function() { NativeModule.require('_third_party_main'); }); } else if (process.argv[1] == 'debug') { // Start the debugger agent var d = NativeModule.require('_debugger'); d.start(); } else if (process._eval != null) { // User passed '-e' or '--eval' arguments to Node. evalScript('[eval]'); } else if (process.argv[1]) { // make process.argv[1] into a full path var path = NativeModule.require('path'); process.argv[1] = path.resolve(process.argv[1]); // If this is a worker in cluster mode, start up the communiction // channel. if (process.env.NODE_UNIQUE_ID) { var cluster = NativeModule.require('cluster'); cluster._setupWorker(); // Make sure it's not accidentally inherited by child processes. delete process.env.NODE_UNIQUE_ID; } var Module; if (!process.ischakra) { Module = NativeModule.require('module'); } if (global.v8debug && process.execArgv.some(function(arg) { return arg.match(/^--debug-brk(=[0-9]*)?$/); })) { Module = Module || NativeModule.require('module'); // XXX Fix this terrible hack! // // Give the client program a few ticks to connect. // Otherwise, there's a race condition where `node debug foo.js` // will not be able to connect in time to catch the first // breakpoint message on line 1. // // A better fix would be to somehow get a message from the // global.v8debug object about a connection, and runMain when // that occurs. --isaacs var debugTimeout = +process.env.NODE_DEBUG_TIMEOUT || 50; setTimeout(Module.runMain, debugTimeout); } else { // Main entry point into most programs: if (process.ischakra) { Module = NativeModule.require('nativerequire'); } else { Module = NativeModule.require('module'); } Module.runMain(); } } else { // use regular Module for REPL var Module = Module || NativeModule.require('module'); // If -i or --interactive were passed, or stdin is a TTY. if (process._forceRepl || NativeModule.require('tty').isatty(0)) { // REPL var opts = { useGlobal: true, ignoreUndefined: false }; if (parseInt(process.env['NODE_NO_READLINE'], 10)) { opts.terminal = false; } if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { opts.useColors = false; } var repl = Module.requireRepl().start(opts); repl.on('exit', function() { process.exit(); }); } else { // Read all of stdin - execute it. process.stdin.setEncoding('utf8'); var code = ''; process.stdin.on('data', function(d) { code += d; }); process.stdin.on('end', function() { process._eval = code; evalScript('[stdin]'); }); } } } startup.globalVariables = function() { global.process = process; global.global = global; global.GLOBAL = global; global.root = global; global.Buffer = NativeModule.require('buffer').Buffer; process.binding('buffer').setFastBufferConstructor(global.Buffer); process.domain = null; process._exiting = false; // exposing the external events emitter: // the event emitter will be used to fire events from external sources var events = NativeModule.require('events'); global.externalEvents = new events.EventEmitter(); }; startup.globalTimeouts = function() { global.setTimeout = function() { var t = NativeModule.require('timers'); return t.setTimeout.apply(this, arguments); }; global.setInterval = function() { var t = NativeModule.require('timers'); return t.setInterval.apply(this, arguments); }; global.clearTimeout = function() { var t = NativeModule.require('timers'); return t.clearTimeout.apply(this, arguments); }; global.clearInterval = function() { var t = NativeModule.require('timers'); return t.clearInterval.apply(this, arguments); }; global.setImmediate = function() { var t = NativeModule.require('timers'); return t.setImmediate.apply(this, arguments); }; global.clearImmediate = function() { var t = NativeModule.require('timers'); return t.clearImmediate.apply(this, arguments); }; }; startup.globalConsole = function() { var emptyConsole = { log: function() { }, debug: function() { }, info: function() { }, warn: function() { }, warning: function() { }, error: function() { }, }; global.__defineGetter__('console', function() { if (process.ischakra && process.noconsole) { return emptyConsole; } else { return NativeModule.require('console'); } }); }; startup._lazyConstants = null; startup.lazyConstants = function() { if (!startup._lazyConstants) { startup._lazyConstants = process.binding('constants'); } return startup._lazyConstants; }; startup.processFatal = function() { // call into the active domain, or emit uncaughtException, // and exit if there are no listeners. process._fatalException = function(er) { var caught = false; if (process.domain) { var domain = process.domain; var domainModule = NativeModule.require('domain'); var domainStack = domainModule._stack; // ignore errors on disposed domains. // // XXX This is a bit stupid. We should probably get rid of // domain.dispose() altogether. It's almost always a terrible // idea. --isaacs if (domain._disposed) return true; er.domain = domain; er.domainThrown = true; // wrap this in a try/catch so we don't get infinite throwing try { // One of three things will happen here. // // 1. There is a handler, caught = true // 2. There is no handler, caught = false // 3. It throws, caught = false // // If caught is false after this, then there's no need to exit() // the domain, because we're going to crash the process anyway. caught = domain.emit('error', er); // Exit all domains on the stack. Uncaught exceptions end the // current tick and no domains should be left on the stack // between ticks. var domainModule = NativeModule.require('domain'); domainStack.length = 0; domainModule.active = process.domain = null; } catch (er2) { // The domain error handler threw! oh no! // See if another domain can catch THIS error, // or else crash on the original one. // If the user already exited it, then don't double-exit. if (domain === domainModule.active) domainStack.pop(); if (domainStack.length) { var parentDomain = domainStack[domainStack.length - 1]; process.domain = domainModule.active = parentDomain; caught = process._fatalException(er2); } else caught = false; } } else { caught = process.emit('uncaughtException', er); } // if someone handled it, then great. otherwise, die in C++ land // since that means that we'll exit the process, emit the 'exit' event if (!caught) { try { if (!process._exiting) { process._exiting = true; process.emit('exit', 1); } } catch (er) { // nothing to be done about it at this point. } } // if we handled an error, then make sure any ticks get processed if (caught) process._needTickCallback(); return caught; }; }; var assert; startup.processAssert = function() { // Note that calls to assert() are pre-processed out by JS2C for the // normal build of node. They persist only in the node_g build. // Similarly for debug(). assert = process.assert = function(x, msg) { if (!x) throw new Error(msg || 'assertion error'); }; }; startup.processConfig = function () { // used for `process.config`, but not a real module if (process.ischakra) { Object.defineProperty(process, 'config', { get: function () { throw new Error('process.config is removed due to optimizations, please do not use.'); } }); return; } var config = NativeModule._source.config; delete NativeModule._source.config; // strip the gyp comment line at the beginning config = config.split('\n').slice(1).join('\n').replace(/'/g, '"'); process.config = JSON.parse(config, function(key, value) { if (value === 'true') return true; if (value === 'false') return false; return value; }); }; startup.processNextTick = function() { var _needTickCallback = process._needTickCallback; var nextTickQueue = []; var needSpinner = true; var inTick = false; // this infobox thing is used so that the C++ code in src/node.cc // can have easy accesss to our nextTick state, and avoid unnecessary // calls into process._tickCallback. // order is [length, index, depth] // Never write code like this without very good reason! var infoBox = process._tickInfoBox; var length = 0; var index = 1; var depth = 2; process.nextTick = nextTick; // needs to be accessible from cc land process._nextDomainTick = _nextDomainTick; process._tickCallback = _tickCallback; process._tickDomainCallback = _tickDomainCallback; process._tickFromSpinner = _tickFromSpinner; // the maximum number of times it'll process something like // nextTick(function f(){nextTick(f)}) // It's unlikely, but not illegal, to hit this limit. When // that happens, it yields to libuv's tick spinner. // This is a loop counter, not a stack depth, so we aren't using // up lots of memory here. I/O can sneak in before nextTick if this // limit is hit, which is not ideal, but not terrible. process.maxTickDepth = 1000; function tickDone(tickDepth_) { if (infoBox[length] !== 0) { if (infoBox[length] <= infoBox[index]) { nextTickQueue = []; infoBox[length] = 0; } else { nextTickQueue.splice(0, infoBox[index]); infoBox[length] = nextTickQueue.length; if (needSpinner) { _needTickCallback(); needSpinner = false; } } } inTick = false; infoBox[index] = 0; infoBox[depth] = tickDepth_; } function maxTickWarn() { // XXX Remove all this maxTickDepth stuff in 0.11 var msg = '(node) warning: Recursive process.nextTick detected. ' + 'This will break in the next version of node. ' + 'Please use setImmediate for recursive deferral.'; if (process.throwDeprecation) throw new Error(msg); else if (process.traceDeprecation) console.trace(msg); else console.error(msg); } function _tickFromSpinner() { needSpinner = true; // coming from spinner, reset! if (infoBox[depth] !== 0) infoBox[depth] = 0; // no callbacks to run if (infoBox[length] === 0) return infoBox[index] = infoBox[depth] = 0; process._tickCallback(); } // run callbacks that have no domain // using domains will cause this to be overridden function _tickCallback() { var callback, nextTickLength, threw; if (inTick) return; if (infoBox[length] === 0) { infoBox[index] = 0; infoBox[depth] = 0; return; } inTick = true; while (infoBox[depth]++ < process.maxTickDepth) { nextTickLength = infoBox[length]; if (infoBox[index] === nextTickLength) return tickDone(0); while (infoBox[index] < nextTickLength) { callback = nextTickQueue[infoBox[index]++].callback; threw = true; try { callback(); threw = false; } finally { if (threw) tickDone(infoBox[depth]); } } } tickDone(0); } function _tickDomainCallback() { var nextTickLength, tock, callback, threw; // if you add a nextTick in a domain's error handler, then // it's possible to cycle indefinitely. Normally, the tickDone // in the finally{} block below will prevent this, however if // that error handler ALSO triggers multiple MakeCallbacks, then // it'll try to keep clearing the queue, since the finally block // fires *before* the error hits the top level and is handled. if (infoBox[depth] >= process.maxTickDepth) return _needTickCallback(); if (inTick) return; inTick = true; // always do this at least once. otherwise if process.maxTickDepth // is set to some negative value, or if there were repeated errors // preventing depth from being cleared, we'd never process any // of them. while (infoBox[depth]++ < process.maxTickDepth) { nextTickLength = infoBox[length]; if (infoBox[index] === nextTickLength) return tickDone(0); while (infoBox[index] < nextTickLength) { tock = nextTickQueue[infoBox[index]++]; callback = tock.callback; if (tock.domain) { if (tock.domain._disposed) continue; tock.domain.enter(); } threw = true; try { callback(); threw = false; } finally { // finally blocks fire before the error hits the top level, // so we can't clear the depth at this point. if (threw) tickDone(infoBox[depth]); } if (tock.domain) { tock.domain.exit(); } } } tickDone(0); } function nextTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) return; if (infoBox[depth] >= process.maxTickDepth) maxTickWarn(); var obj = { callback: callback, domain: null }; nextTickQueue.push(obj); infoBox[length]++; if (needSpinner) { _needTickCallback(); needSpinner = false; } } function _nextDomainTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) return; if (infoBox[depth] >= process.maxTickDepth) maxTickWarn(); var obj = { callback: callback, domain: process.domain }; nextTickQueue.push(obj); infoBox[length]++; if (needSpinner) { _needTickCallback(); needSpinner = false; } } }; function evalScript(name) { var Module = NativeModule.require('module'); var path = NativeModule.require('path'); var cwd = process.cwd(); var module = new Module(name); module.filename = path.join(cwd, name); module.paths = Module._nodeModulePaths(cwd); var script = process._eval; if (!Module._contextLoad) { var body = script; script = 'global.__filename = ' + JSON.stringify(name) + ';\n' + 'global.exports = exports;\n' + 'global.module = module;\n' + 'global.__dirname = __dirname;\n' + 'global.require = require;\n' + 'return require("vm").runInThisContext(' + JSON.stringify(body) + ', ' + JSON.stringify(name) + ', true);\n'; } var result = module._compile(script, name + '-wrapper'); if (process._print_eval) console.log(result); } function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function createWritableStdioStream(fd) { var stream; var tty_wrap = process.binding('tty_wrap'); // Note stream._type is used for test-module-load-list.js switch (tty_wrap.guessHandleType(fd)) { case 'TTY': var tty = NativeModule.require('tty'); stream = new tty.WriteStream(fd); stream._type = 'tty'; // Hack to have stream not keep the event loop alive. // See https://github.com/joyent/node/issues/1726 if (stream._handle && stream._handle.unref) { stream._handle.unref(); } break; case 'FILE': var fs = NativeModule.require('fs'); stream = new fs.SyncWriteStream(fd); stream._type = 'fs'; break; case 'PIPE': case 'TCP': var net = NativeModule.require('net'); stream = new net.Socket({ fd: fd, readable: false, writable: true }); // FIXME Should probably have an option in net.Socket to create a // stream from an existing fd which is writable only. But for now // we'll just add this hack and set the `readable` member to false. // Test: ./node test/fixtures/echo.js < /etc/passwd stream.readable = false; stream.read = null; stream._type = 'pipe'; // FIXME Hack to have stream not keep the event loop alive. // See https://github.com/joyent/node/issues/1726 if (stream._handle && stream._handle.unref) { stream._handle.unref(); } break; default: // Probably an error on in uv_guess_handle() throw new Error('Implement me. Unknown stream file type!'); } // For supporting legacy API we put the FD here. stream.fd = fd; stream._isStdio = true; return stream; } startup.processStdio = function() { var stdin, stdout, stderr; // TODO: we might want also to add a specific switch for this? if (process.ischakra && process.noconsole) { stdin = { id : '__mock_stdin', write: function() { }, read: function() { }, pipe: function() { } } stdout = { id: '__mock_stdout', write: function() { }, read: function() { }, pipe: function() { } } stderr = { id: '__mock_stderr', write: function() { }, read: function() { }, pipe: function() { } } } process.__defineGetter__('stdout', function() { if (stdout) return stdout; stdout = createWritableStdioStream(1); stdout.destroy = stdout.destroySoon = function(er) { er = er || new Error('process.stdout cannot be closed.'); stdout.emit('error', er); }; if (stdout.isTTY) { process.on('SIGWINCH', function() { stdout._refreshSize(); }); } return stdout; }); process.__defineGetter__('stderr', function() { if (stderr) return stderr; stderr = createWritableStdioStream(2); stderr.destroy = stderr.destroySoon = function(er) { er = er || new Error('process.stderr cannot be closed.'); stderr.emit('error', er); }; return stderr; }); process.__defineGetter__('stdin', function() { if (stdin) return stdin; var tty_wrap = process.binding('tty_wrap'); var fd = 0; switch (tty_wrap.guessHandleType(fd)) { case 'TTY': var tty = NativeModule.require('tty'); stdin = new tty.ReadStream(fd, { highWaterMark: 0, readable: true, writable: false }); break; case 'FILE': var fs = NativeModule.require('fs'); stdin = new fs.ReadStream(null, { fd: fd }); break; case 'PIPE': case 'TCP': var net = NativeModule.require('net'); stdin = new net.Socket({ fd: fd, readable: true, writable: false }); break; default: // Probably an error on in uv_guess_handle() throw new Error('Implement me. Unknown stdin file type!'); } // For supporting legacy API we put the FD here. stdin.fd = fd; // stdin starts out life in a paused state, but node doesn't // know yet. Explicitly to readStop() it to put it in the // not-reading state. if (stdin._handle && stdin._handle.readStop) { stdin._handle.reading = false; stdin._readableState.reading = false; stdin._handle.readStop(); } // if the user calls stdin.pause(), then we need to stop reading // immediately, so that the process can close down. stdin.on('pause', function() { if (!stdin._handle) return; stdin._readableState.reading = false; stdin._handle.reading = false; stdin._handle.readStop(); }); return stdin; }); process.openStdin = function() { process.stdin.resume(); return process.stdin; }; }; startup.processKillAndExit = function() { process.exit = function(code) { if (!process._exiting) { process._exiting = true; process.emit('exit', code || 0); } process.reallyExit(code || 0); }; process.kill = function(pid, sig) { var r; // preserve null signal if (0 === sig) { r = process._kill(pid, 0); } else { sig = sig || 'SIGTERM'; if (startup.lazyConstants()[sig]) { r = process._kill(pid, startup.lazyConstants()[sig]); } else { throw new Error('Unknown signal: ' + sig); } } if (r) { throw errnoException(process._errno, 'kill'); } return true; }; }; startup.processSignalHandlers = function() { // Load events module in order to access prototype elements on process like // process.addListener. var signalWraps = {}; var addListener = process.addListener; var removeListener = process.removeListener; function isSignal(event) { return event.slice(0, 3) === 'SIG' && startup.lazyConstants().hasOwnProperty(event); } // Wrap addListener for the special signal types process.on = process.addListener = function(type, listener) { if (isSignal(type) && !signalWraps.hasOwnProperty(type)) { var Signal = process.binding('signal_wrap').Signal; var wrap = new Signal(); wrap.unref(); wrap.onsignal = function() { process.emit(type); }; var signum = startup.lazyConstants()[type]; var r = wrap.start(signum); if (r) { wrap.close(); throw errnoException(process._errno, 'uv_signal_start'); } signalWraps[type] = wrap; } return addListener.apply(this, arguments); }; process.removeListener = function(type, listener) { var ret = removeListener.apply(this, arguments); if (isSignal(type)) { assert(signalWraps.hasOwnProperty(type)); if (this.listeners(type).length === 0) { signalWraps[type].close(); delete signalWraps[type]; } } return ret; }; }; startup.processChannel = function() { // If we were spawned with env NODE_CHANNEL_FD then load that up and // start parsing data from that stream. if (process.env.NODE_CHANNEL_FD) { var fd = parseInt(process.env.NODE_CHANNEL_FD, 10); assert(fd >= 0); // Make sure it's not accidentally inherited by child processes. delete process.env.NODE_CHANNEL_FD; var cp = NativeModule.require('child_process'); // Load tcp_wrap to avoid situation where we might immediately receive // a message. // FIXME is this really necessary? process.binding('tcp_wrap'); cp._forkChild(fd); assert(process.send); } } startup.resolveArgv0 = function() { var cwd = process.cwd(); var isWindows = process.platform === 'win32'; // Make process.argv[0] into a full path, but only touch argv[0] if it's // not a system $PATH lookup. // TODO: Make this work on Windows as well. Note that "node" might // execute cwd\node.exe, or some %PATH%\node.exe on Windows, // and that every directory has its own cwd, so d:node.exe is valid. var argv0 = process.argv[0]; if (!isWindows && argv0.indexOf('/') !== -1 && argv0.charAt(0) !== '/') { var path = NativeModule.require('path'); process.argv[0] = path.join(cwd, process.argv[0]); } }; // Below you find a minimal module system, which is used to load the node // core modules found in lib/*.js. All core modules are compiled into the // node binary, so they can be loaded faster. var Script = process.binding('evals').NodeScript; var runInThisContext = Script.runInThisContext; function NativeModule(id) { this.filename = id + '.js'; this.id = id; this.exports = {}; this.loaded = false; } NativeModule._source = process.binding('natives'); NativeModule._cache = {}; NativeModule.require = function(id) { if (id == 'native_module') { return NativeModule; } var cached = NativeModule.getCached(id); if (cached) { return cached.exports; } if (!NativeModule.exists(id)) { throw new Error('No such native module ' + id); } process.moduleLoadList.push('NativeModule ' + id); var nativeModule = new NativeModule(id); nativeModule.cache(); nativeModule.compile(); return nativeModule.exports; }; if (process.ischakra) { NativeModule.requireBuiltinModule = process.binding('nativerequire_wrap').requireBuiltinModule; } NativeModule.getCached = function(id) { return NativeModule._cache[id]; } NativeModule.exists = function(id) { return NativeModule._source.hasOwnProperty(id); } NativeModule.getSource = function (id) { if (process.ischakra) { // this will happen only when repl is used return process.lazyBindBuiltinModule(id); } else { return NativeModule._source[id]; } } NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = [ '(function(exports, require, module, __filename, __dirname) { ', '\n});' ]; NativeModule.prototype.compile = function() { if (process.ischakra) { // prevent us from fetching large strings into javascript var fn = NativeModule.requireBuiltinModule(this.id); fn(this.exports, NativeModule.require, this, this.filename); } else { // original node.js code var source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); var fn = runInThisContext(source, this.filename, true); fn(this.exports, NativeModule.require, this, this.filename); } this.loaded = true; }; NativeModule.prototype.cache = function() { NativeModule._cache[this.id] = this; }; startup(); }); getOwnPropertyDescriptorhasOwnhasdeletePropertyenumerateownKeysconstructornamev0.10.10processO_EXCLx64_needImmediateCallbackWSAEPROVIDERFAILEDINITdisable_node_env_varslazyBindBuiltinModuleWSASERVICE_NOT_FOUNDWSAEINVALIDPROCTABLEWSAEINVALIDPROVIDERWSAVERNOTSUPPORTEDWSAESOCKTNOSUPPORT_getActiveRequestsWSAEPROTONOSUPPORTWSASYSCALLFAILURE_needTickCallback_getActiveHandlesWSANOTINITIALISEDWSATYPE_NOT_FOUNDWSAEADDRNOTAVAILWSAENAMETOOLONGWSA_E_CANCELLEDWSAEPFNOSUPPORTEPROTONOSUPPORTWSAECONNABORTEDWSAEHOSTUNREACHWSAECONNREFUSEDWSAEAFNOSUPPORTWSAETOOMANYREFSWSAEDESTADDRREQWSAENETUNREACHWSASYSNOTREADYWSAENOPROTOOPTWSAEINPROGRESSWSAEWOULDBLOCKmoduleLoadListWSAEADDRINUSEWSAECANCELLEDWSA_E_NO_MORE_usingDomainsWSAEOPNOTSUPPWSAEPROTOTYPE_debugProcessWSAECONNRESETEADDRNOTAVAIL_tickCallbackEHOSTUNREACHECONNABORTEDWSAEHOSTDOWNECONNREFUSEDEAFNOSUPPORTWSAENOTEMPTYWSAENETRESETWSAESHUTDOWNEDESTADDRREQ_tickInfoBoxENAMETOOLONGWSAETIMEDOUTWSAEMSGSIZEhttp_parserWSAEREFUSEDEINPROGRESSWSAENOTSOCKEWOULDBLOCK_debugPauseENETUNREACHWSAEALREADYENOPROTOOPTWSAEPROCLIMWSAENETDOWNWSAENOTCONNmemoryUsageWSAENOBUFSECONNRESETWSAEISCONNreallyExitEPROTOTYPEEADDRINUSEEOPNOTSUPPWSAENOMOREWSAEREMOTEWSAEDISCONWSAEINVALETIMEDOUTnoconsoledebugPortWSAEUSERSWSAEMFILEWSAESTALE1.9.0-DEVENETRESETENOTEMPTYECANCELED_debugEndWSAEACCESWSAEDQUOTEOVERFLOWWSAEFAULTischakraWSAELOOPO_APPENDWSAEBADFexecArgvfeaturesWSAEINTR11.0.0.0SIGWINCHO_WRONLYO_RDONLYexecPathENOTCONNENETDOWNEALREADYEMSGSIZEENOTSOCKversionsSIGBREAKplatformEBADMSGEDEADLKENOTSUPS_IFLNK_eventsSIGTERMSIGSEGVS_IFREGS_IFDIRO_CREATSIGKILLEISCONNSIGABRTbindingexports0.10.10ENOTDIRO_TRUNCETXTBSYmodulesENOLINKversionENOBUFSENOEXECENODATAS_IFCHRENOSPCSIGINTSIGFPEEPROTOENOTTYEMLINKERANGEEILSEQuptimeENOMEMEACCESESPIPEEISDIRS_IFMTdomainENOSYSdlopenENOSTRECHILDO_RDWREFAULThrtimeENFILEEINVALEEXISTSIGILLEAGAINflavorSIGHUPENOLCKEMFILEENOMSGENODEVtitleENXIOEINTRwin32ENOSRETIMEEBUSYEBADFEPERMEXDEV_killELOOPchdirEIDRMEROFS1.2.3ESRCHE2BIGEFBIGEPIPEumaskabortzlibarchEDOMargvnodearespidenvcwd1.0EIO11v8bad allocationfile existsfilename too longdevice or resource busyio errorno space on devicefunction not supportedno lock availableresource unavailable try againcross device linktoo many files openpermission_deniedaddress_in_useaddress_not_availableaddress_family_not_supportedconnection_already_in_progressbad_file_descriptorconnection_abortedconnection_refusedconnection_resetdestination_address_requiredbad_addresshost_unreachableoperation_in_progressinterruptedinvalid_argumentalready_connectedtoo_many_files_openmessage_sizefilename_too_longnetwork_downnetwork_resetnetwork_unreachableno_buffer_spaceno_protocol_optionnot_connectednot_a_socketoperation_not_supportedprotocol_not_supportedwrong_protocol_typetimed_outoperation_would_blockaddress in usealready connectedargument list too longargument out of domainbad addressbad messageconnection abortedconnection resetexecutable format errorfile too largehost unreachableidentifier removedillegal byte sequenceinappropriate io control operationis a directorymessage sizenetwork downnetwork resetnetwork unreachableno buffer spaceno child processno linkno message availableno messageno protocol optionno stream resourcesno such device or addressnot a socketnot a streamnot connectednot supportedoperation in progressoperation not supportedoperation would blockowner deadread only file systemresource deadlock would occurresult out of rangestate not recoverablestream timeouttext file busytimed outtoo many files open in systemtoo many linkstoo many symbolic link levelsvalue too largewrong protocol type"X*`* "X** *C"P*`** invalid map keyinvalid map/set iteratormap/set too longinvalid string positionstring too longNativeRequireUtils::RequireFile failed on Script::New for %SNativeRequireUtils::RequireFile failed on Script::Run for %SGetByteCodeForScript: Invalid Argument(s) %p - %p - %p - %pGetByteCodeForScript: could not compute key: %d - %SGetByteCodeForScript: could not find byte code: %d - %S(function (exports, require, module, __filename, __dirname) { });NativeRequireUtils::GetFileSize failed for %S, error code: %dNativeRequireUtils::ReadFileContents failed on open for %S, error code: %dNativeRequireUtils::ReadFileContents failed on read for %S, error code: %d NativeRequireUtils::CreateScriptString failed on first call to MultiByteToWideChar, last error is: %dNativeRequireUtils::RequireFile failed on ReadFileContents for: %S, error code:NativeRequireUtils::RequireFile !# symbol was removed for: %S, error code:NativeRequireUtils::RequireFile failed on CreateScriptString for: %S, error code:falsetrue:     ExceptionReturnHrLogHrFailFast%hs(%d)\%hs!%p: %hs!%p: (caller: %p) %hs(%d) tid(%x) %08X %ws Msg:[%ws] CallContext:[%hs] [%hs(%hs)] [%hs] onecoreuap\inetcore\wwa\bytecode\lib\bytecodecache.cpponecoreuap\inetcore\Wwa\AppModelCommon\AutoPtr.hpponecoreuap\inetcore\Wwa\AppModelCommon\GenericMap.hpp+hOUr߀ onecoreuap\inetcore\wwa\bytecode\lib\serialize.cpp s/Cwfinternal\sdk\inc\wil\ResultMacros.hinternal\sdk\inc\wil\Resource.hWilError_01onecoreuap\inetcore\wwa\bytecode\lib\memorymappedbytecodecache.cpptruefalsenull"** *8"\*l**0"))) "4*D*l* "L*\**H"*** " ))D)0"`)p)) "\)l)) "))) "))0"**" * *("**("* *"p*x*"**x" \**"\*d*" *8 *"t*|*8"x))0"))0")) ")) )0"h*p*X" *$ *L *8"0*@*h* "***0"*** ")) 8)0")) ")) " * *`" * *0")) " * *0"T)|)"))X" !*(!* "T!*d!*!* "!*!*"* ""*"*"*0"#*#* "t#*#*`"#*#* "$$*4$*0"|$*$*0"$* %*@"%*%*"%*%*"`&*x&*8"&*&*0",'*<'* "'*'*X"'*'*@"0(*8(* "d)t)"**")) " )2)X"D)E)"h(*(*(* ") ) H) " )8) `) " )*)*D)* ")*)* " ** ,**X"**** "****(")) ) ")) ) "0)H) p) "** ")) "))("p)x)("3*3*3* "4*$4* "\4*d4* "4*4* "5*5* "85*@5* "@*H*("t5*5*5* "6*$6* "L6*\6*6* "6* 6*x"l7* 7*h"7*7* "8*88* "h8* 8*("8* 9*P"9*9* ":*$:* L:*@":*:* ";* ;* ")) ")$)0"d)l) "`;*h;*0";*;*p") )("))0"`**@")) ";*<* "H<*X<* "<*<* "<*=* "d) |) "P=*`=* "=*=*8"=*=* ")4)">*(>*0"|))"p>*x>* ">*>* ">*>*8" ?*(?* "X?*`?* "?*?* "**P"?*@*0"`@*h@* ") )@")) ")) "@* @*h"dA* A*h"A*A* ",B*4B*0"dB*lB* "B*B* "B*C*H"8C*@C*0"))x") )P"tC*|C*8"C*C* "C*D*@"p)x)0"))0"tD*|D*("D*D* "D* 0E* "@)P) "E*E* "E* E* "PF* hF* "F* F*`"PG*hG* "G*G* ",H* DH*h"H* H* ")) "))8")) "$I*,I* "`I*hI* "d)l) "I*I* ")) "I*I*0"J*J* "DJ*dJ* "J*J*0"K*K* "DK*LK* "K*K*0"K*K* "$L*,L*0"dL*lL*X"L*L*0",M*4M*0"lM*tM*0"M*M*0"M*M*0",N*4N*0"lN*tN*0"N*N* "N*N* " O*(O* "t)|) "\O*dO* "O*O* ")) ")) ")) "O*O* " *(*"P*P* "))0"**0"**`"`)h)@"PP*XP*0"P*P* "P*P* "P*P* ",Q*4Q* "**0"** "|Q*Q* "Q*Q* "R* R*P"TR*\R*0"R*R* "R*R* "S*S* "XS*`S* "S*S* "S*S*@"T*$T* "\T* tT*8"T* T*8"lU* U*8"U*U* ",V*4V* "hV*pV* "V*V*P"V*V*P"0W*8W*X"hW*pW* "W*W*0"X* X* "@=@;@9@8@7@4@3@2@1@0@.@,@*@(@$@@@@@// Copyright (c) Microsoft Corporation. All rights reserved. // Patch classes for chakra var extend = function (dest, from) { var props = Object.getOwnPropertyNames(from); props.forEach(function (name) { var destination = Object.getOwnPropertyDescriptor(from, name); try { Object.defineProperty(dest, name, destination); } catch (e) { // ignore errors } }); }; if (!global.__chakra_wp_patched) { // patch fs.js to ignore handling of symbolic links var pathModule = require('path'); var fs = require('fs'); var isWindows = process.platform === 'win32'; // Regex to find the device root, including trailing slash. E.g. 'c:\\'. if (isWindows) { var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; } else { var splitRootRe = /^[\/]*/; } if (isWindows) { var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; } else { var nextPartRe = /(.*?)(?:[\/]+|$)/g; } fs.realpathSync = function realpathSync(p, cache) { // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return cache[p]; } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { knownHard[base] = true; } } // walk down the path, swapping out linked pathparts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { continue; } var resolvedLink; if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // some known symbolic link. no need to stat again. resolvedLink = cache[base]; } else { var permError = false; var stat; try { stat = fs.lstatSync(base); } catch (e) { if (e.errno == 50) { permError = true; stat = null; } else { throw e; } } if (permError || !stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; continue; } // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); } resolvedLink = pathModule.resolve(previous, linkTarget); // track this, if given a cache. if (cache) cache[base] = resolvedLink; if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } if (cache) cache[original] = p; return p; }; function maybeCallback(cb) { return typeof cb === 'function' ? cb : rethrow(); } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { if (typeof cb !== 'function') { return rethrow(); } return function () { return cb.apply(null, arguments); }; } // path fs.realpath: fs.realpath = function realpath(p, cache, cb) { if (typeof cb !== 'function') { cb = maybeCallback(cache); cache = null; } // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return process.nextTick(cb.bind(null, null, cache[p])); } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function (err) { // PATCH: we ignore permissions error, path exists in this case if (err && err.errno != 50) return cb(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } // walk down the path, swapping out linked pathparts for their real // values function LOOP() { // stop if scanned past end of path if (pos >= p.length) { if (cache) cache[original] = p; return cb(null, p); } // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { return process.nextTick(LOOP); } if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // known symbolic link. no need to stat again. return gotResolvedLink(cache[base]); } return fs.lstat(base, gotStat); } function gotStat(err, stat) { // PATCH: we ignore permissions error, path exists in this case if (err && err.errno != 50) return cb(err); // PATCH: we ignore permissions error, path exists in this case // if not a symlink, skip to the next path part if ((err && err.errno == 50) || !stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; return process.nextTick(LOOP); } // stat & read the link if not read before // call gotTarget as soon as the link target is known // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } fs.stat(base, function (err) { if (err) return cb(err); fs.readlink(base, function (err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target, base) { if (err) return cb(err); var resolvedLink = pathModule.resolve(previous, target); if (cache) cache[base] = resolvedLink; gotResolvedLink(resolvedLink); } function gotResolvedLink(resolvedLink) { // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } }; Object.defineProperty(global, '__chakra_wp_patched', { enumerable: false, value: true }); }_third_party_patch// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // A bit simpler than readable streams. // Implement an async ._write(chunk, cb), and it'll handle all // the drain event emission and buffering. module.exports = Writable; Writable.WritableState = WritableState; var util = require('util'); var assert = require('assert'); var Stream = require('stream'); util.inherits(Writable, Stream); function WriteReq(chunk, encoding, cb) { this.chunk = chunk; this.encoding = encoding; this.callback = cb; } function WritableState(options, stream) { options = options || {}; // the point at which write() starts returning false // Note: 0 is a valid value, means that we always return false if // the entire buffer is not flushed immediately on write() var hwm = options.highWaterMark; this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; // object stream flag to indicate whether or not this stream // contains buffers or objects. this.objectMode = !!options.objectMode; // cast to ints. this.highWaterMark = ~~this.highWaterMark; this.needDrain = false; // at the start of calling end() this.ending = false; // when end() has been called, and returned this.ended = false; // when 'finish' is emitted this.finished = false; // should we decode strings into buffers before passing to _write? // this is here so that some node-core streams can optimize string // handling at a lower level. var noDecode = options.decodeStrings === false; this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. // Everything else in the universe uses 'utf8', though. this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement // of how much we're waiting to get pushed to some underlying // socket or file. this.length = 0; // a flag to see when we're in the middle of a write. this.writing = false; // a flag to be able to tell if the onwrite cb is called immediately, // or on a later tick. We set this to true at first, becuase any // actions that shouldn't happen until "later" should generally also // not happen before the first write call. this.sync = true; // a flag to know if we're processing previously buffered items, which // may call the _write() callback in the same tick, so that we don't // end up in an overlapped onwrite situation. this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) this.onwrite = function(er) { onwrite(stream, er); }; // the callback that the user supplies to write(chunk,encoding,cb) this.writecb = null; // the amount that is being written when _write is called. this.writelen = 0; this.buffer = []; } function Writable(options) { // Writable ctor is applied to Duplexes, though they're not // instanceof Writable, they're instanceof Readable. if (!(this instanceof Writable) && !(this instanceof Stream.Duplex)) return new Writable(options); this._writableState = new WritableState(options, this); // legacy. this.writable = true; Stream.call(this); } // Otherwise people can pipe Writable streams, which is just wrong. Writable.prototype.pipe = function() { this.emit('error', new Error('Cannot pipe. Not readable.')); }; function writeAfterEnd(stream, state, cb) { var er = new Error('write after end'); // TODO: defer error events consistently everywhere, not just the cb stream.emit('error', er); process.nextTick(function() { cb(er); }); } // If we get something that is not a buffer, string, null, or undefined, // and we're not in objectMode, then that's an error. // Otherwise stream chunks are all considered to be of length=1, and the // watermarks determine how many objects to keep in the buffer, rather than // how many bytes or characters. function validChunk(stream, state, chunk, cb) { var valid = true; if (!Buffer.isBuffer(chunk) && 'string' !== typeof chunk && chunk !== null && chunk !== undefined && !state.objectMode) { var er = new TypeError('Invalid non-string/buffer chunk'); stream.emit('error', er); process.nextTick(function() { cb(er); }); valid = false; } return valid; } Writable.prototype.write = function(chunk, encoding, cb) { var state = this._writableState; var ret = false; if (typeof encoding === 'function') { cb = encoding; encoding = null; } if (Buffer.isBuffer(chunk)) encoding = 'buffer'; else if (!encoding) encoding = state.defaultEncoding; if (typeof cb !== 'function') cb = function() {}; if (state.ended) writeAfterEnd(this, state, cb); else if (validChunk(this, state, chunk, cb)) ret = writeOrBuffer(this, state, chunk, encoding, cb); return ret; }; function decodeChunk(state, chunk, encoding) { if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { chunk = new Buffer(chunk, encoding); } return chunk; } // if we're already writing something, then just put this // in the queue, and wait our turn. Otherwise, call _write // If we return false, then we need a drain event, so set that flag. function writeOrBuffer(stream, state, chunk, encoding, cb) { chunk = decodeChunk(state, chunk, encoding); var len = state.objectMode ? 1 : chunk.length; state.length += len; var ret = state.length < state.highWaterMark; state.needDrain = !ret; if (state.writing) state.buffer.push(new WriteReq(chunk, encoding, cb)); else doWrite(stream, state, len, chunk, encoding, cb); return ret; } function doWrite(stream, state, len, chunk, encoding, cb) { state.writelen = len; state.writecb = cb; state.writing = true; state.sync = true; stream._write(chunk, encoding, state.onwrite); state.sync = false; } function onwriteError(stream, state, sync, er, cb) { if (sync) process.nextTick(function() { cb(er); }); else cb(er); stream.emit('error', er); } function onwriteStateUpdate(state) { state.writing = false; state.writecb = null; state.length -= state.writelen; state.writelen = 0; } function onwrite(stream, er) { var state = stream._writableState; var sync = state.sync; var cb = state.writecb; onwriteStateUpdate(state); if (er) onwriteError(stream, state, sync, er, cb); else { // Check if we're actually ready to finish, but don't emit yet var finished = needFinish(stream, state); if (!finished && !state.bufferProcessing && state.buffer.length) clearBuffer(stream, state); if (sync) { process.nextTick(function() { afterWrite(stream, state, finished, cb); }); } else { afterWrite(stream, state, finished, cb); } } } function afterWrite(stream, state, finished, cb) { if (!finished) onwriteDrain(stream, state); cb(); if (finished) finishMaybe(stream, state); } // Must force callback to be called on nextTick, so that we don't // emit 'drain' before the write() consumer gets the 'false' return // value, and has a chance to attach a 'drain' listener. function onwriteDrain(stream, state) { if (state.length === 0 && state.needDrain) { state.needDrain = false; stream.emit('drain'); } } // if there's something in the buffer waiting, then process it function clearBuffer(stream, state) { state.bufferProcessing = true; for (var c = 0; c < state.buffer.length; c++) { var entry = state.buffer[c]; var chunk = entry.chunk; var encoding = entry.encoding; var cb = entry.callback; var len = state.objectMode ? 1 : chunk.length; doWrite(stream, state, len, chunk, encoding, cb); // if we didn't call the onwrite immediately, then // it means that we need to wait until it does. // also, that means that the chunk and cb are currently // being processed, so move the buffer counter past them. if (state.writing) { c++; break; } } state.bufferProcessing = false; if (c < state.buffer.length) state.buffer = state.buffer.slice(c); else state.buffer.length = 0; } Writable.prototype._write = function(chunk, encoding, cb) { cb(new Error('not implemented')); }; Writable.prototype.end = function(chunk, encoding, cb) { var state = this._writableState; if (typeof chunk === 'function') { cb = chunk; chunk = null; encoding = null; } else if (typeof encoding === 'function') { cb = encoding; encoding = null; } if (typeof chunk !== 'undefined' && chunk !== null) this.write(chunk, encoding); // ignore unnecessary end() calls. if (!state.ending && !state.finished) endWritable(this, state, cb); }; function needFinish(stream, state) { return (state.ending && state.length === 0 && !state.finished && !state.writing); } function finishMaybe(stream, state) { var need = needFinish(stream, state); if (need) { state.finished = true; stream.emit('finish'); } return need; } function endWritable(stream, state, cb) { state.ending = true; finishMaybe(stream, state); if (cb) { if (state.finished) process.nextTick(cb); else stream.once('finish', cb); } state.ended = true; } _stream_writable// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a transform stream is a readable/writable stream where you do // something with the data. Sometimes it's called a "filter", // but that's not a great name for it, since that implies a thing where // some bits pass through, and others are simply ignored. (That would // be a valid example of a transform, of course.) // // While the output is causally related to the input, it's not a // necessarily symmetric or synchronous transformation. For example, // a zlib stream might take multiple plain-text writes(), and then // emit a single compressed chunk some time in the future. // // Here's how this works: // // The Transform stream has all the aspects of the readable and writable // stream classes. When you write(chunk), that calls _write(chunk,cb) // internally, and returns false if there's a lot of pending writes // buffered up. When you call read(), that calls _read(n) until // there's enough pending readable data buffered up. // // In a transform stream, the written data is placed in a buffer. When // _read(n) is called, it transforms the queued up data, calling the // buffered _write cb's as it consumes chunks. If consuming a single // written chunk would result in multiple output chunks, then the first // outputted bit calls the readcb, and subsequent chunks just go into // the read buffer, and will cause it to emit 'readable' if necessary. // // This way, back-pressure is actually determined by the reading side, // since _read has to be called to start processing a new chunk. However, // a pathological inflate type of transform can cause excessive buffering // here. For example, imagine a stream where every byte of input is // interpreted as an integer from 0-255, and then results in that many // bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in // 1kb of data being output. In this case, you could write a very small // amount of input, and end up with a very large amount of output. In // such a pathological inflating mechanism, there'd be no way to tell // the system to stop doing the transform. A single 4MB write could // cause the system to run out of memory. // // However, even in such a pathological case, only a single written chunk // would be consumed, and then the rest would wait (un-transformed) until // the results of the previous transformed chunk were consumed. module.exports = Transform; var Duplex = require('_stream_duplex'); var util = require('util'); util.inherits(Transform, Duplex); function TransformState(options, stream) { this.afterTransform = function(er, data) { return afterTransform(stream, er, data); }; this.needTransform = false; this.transforming = false; this.writecb = null; this.writechunk = null; } function afterTransform(stream, er, data) { var ts = stream._transformState; ts.transforming = false; var cb = ts.writecb; if (!cb) return stream.emit('error', new Error('no writecb in Transform class')); ts.writechunk = null; ts.writecb = null; if (data !== null && data !== undefined) stream.push(data); if (cb) cb(er); var rs = stream._readableState; rs.reading = false; if (rs.needReadable || rs.length < rs.highWaterMark) { stream._read(rs.highWaterMark); } } function Transform(options) { if (!(this instanceof Transform)) return new Transform(options); Duplex.call(this, options); var ts = this._transformState = new TransformState(options, this); // when the writable side finishes, then flush out anything remaining. var stream = this; // start out asking for a readable event once data is transformed. this._readableState.needReadable = true; // we have implemented the _read method, and done the other things // that Readable wants before the first _read call, so unset the // sync guard flag. this._readableState.sync = false; this.once('finish', function() { if ('function' === typeof this._flush) this._flush(function(er) { done(stream, er); }); else done(stream); }); } Transform.prototype.push = function(chunk, encoding) { this._transformState.needTransform = false; return Duplex.prototype.push.call(this, chunk, encoding); }; // This is the part where you do stuff! // override this function in implementation classes. // 'chunk' is an input chunk. // // Call `push(newChunk)` to pass along transformed output // to the readable side. You may call 'push' zero or more times. // // Call `cb(err)` when you are done with this chunk. If you pass // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. Transform.prototype._transform = function(chunk, encoding, cb) { throw new Error('not implemented'); }; Transform.prototype._write = function(chunk, encoding, cb) { var ts = this._transformState; ts.writecb = cb; ts.writechunk = chunk; ts.writeencoding = encoding; if (!ts.transforming) { var rs = this._readableState; if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); } }; // Doesn't matter what the args are here. // _transform does all the work. // That we got here means that the readable side wants more data. Transform.prototype._read = function(n) { var ts = this._transformState; if (ts.writechunk && ts.writecb && !ts.transforming) { ts.transforming = true; this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); } else { // mark that we need a transform, so that any data that comes in // will get processed, now that we've asked for it. ts.needTransform = true; } }; function done(stream, er) { if (er) return stream.emit('error', er); // if there's nothing in the write buffer, then that means // that nothing more will ever be provided var ws = stream._writableState; var rs = stream._readableState; var ts = stream._transformState; if (ws.length) throw new Error('calling transform done when ws.length != 0'); if (ts.transforming) throw new Error('calling transform done when still transforming'); return stream.push(null); } _stream_transform// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = Readable; Readable.ReadableState = ReadableState; var EE = require('events').EventEmitter; var Stream = require('stream'); var util = require('util'); var StringDecoder; util.inherits(Readable, Stream); function ReadableState(options, stream) { options = options || {}; // the point at which it stops calling _read() to fill the buffer // Note: 0 is a valid value, means "don't call _read preemptively ever" var hwm = options.highWaterMark; this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; // cast to ints. this.highWaterMark = ~~this.highWaterMark; this.buffer = []; this.length = 0; this.pipes = null; this.pipesCount = 0; this.flowing = false; this.ended = false; this.endEmitted = false; this.reading = false; // In streams that never have any data, and do push(null) right away, // the consumer can miss the 'end' event if they do some I/O before // consuming the stream. So, we don't emit('end') until some reading // happens. this.calledRead = false; // a flag to be able to tell if the onwrite cb is called immediately, // or on a later tick. We set this to true at first, becuase any // actions that shouldn't happen until "later" should generally also // not happen before the first write call. this.sync = true; // whenever we return null, then we set a flag to say // that we're awaiting a 'readable' event emission. this.needReadable = false; this.emittedReadable = false; this.readableListening = false; // object stream flag. Used to make read(n) ignore n and to // make all the buffer merging and length checks go away this.objectMode = !!options.objectMode; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. // Everything else in the universe uses 'utf8', though. this.defaultEncoding = options.defaultEncoding || 'utf8'; // when piping, we only care about 'readable' events that happen // after read()ing all the bytes and not getting any pushback. this.ranOut = false; // the number of writers that are awaiting a drain event in .pipe()s this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled this.readingMore = false; this.decoder = null; this.encoding = null; if (options.encoding) { if (!StringDecoder) StringDecoder = require('string_decoder').StringDecoder; this.decoder = new StringDecoder(options.encoding); this.encoding = options.encoding; } } function Readable(options) { if (!(this instanceof Readable)) return new Readable(options); this._readableState = new ReadableState(options, this); // legacy this.readable = true; Stream.call(this); } // Manually shove something into the read() buffer. // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should // write() some more. Readable.prototype.push = function(chunk, encoding) { var state = this._readableState; if (typeof chunk === 'string' && !state.objectMode) { encoding = encoding || state.defaultEncoding; if (encoding !== state.encoding) { chunk = new Buffer(chunk, encoding); encoding = ''; } } return readableAddChunk(this, state, chunk, encoding, false); }; // Unshift should *always* be something directly out of read() Readable.prototype.unshift = function(chunk) { var state = this._readableState; return readableAddChunk(this, state, chunk, '', true); }; function readableAddChunk(stream, state, chunk, encoding, addToFront) { var er = chunkInvalid(state, chunk); if (er) { stream.emit('error', er); } else if (chunk === null || chunk === undefined) { state.reading = false; if (!state.ended) onEofChunk(stream, state); } else if (state.objectMode || chunk && chunk.length > 0) { if (state.ended && !addToFront) { var e = new Error('stream.push() after EOF'); stream.emit('error', e); } else if (state.endEmitted && addToFront) { var e = new Error('stream.unshift() after end event'); stream.emit('error', e); } else { if (state.decoder && !addToFront && !encoding) chunk = state.decoder.write(chunk); // update the buffer info. state.length += state.objectMode ? 1 : chunk.length; if (addToFront) { state.buffer.unshift(chunk); } else { state.reading = false; state.buffer.push(chunk); } if (state.needReadable) emitReadable(stream); maybeReadMore(stream, state); } } else if (!addToFront) { state.reading = false; } return needMoreData(state); } // if it's past the high water mark, we can push in some more. // Also, if we have no data yet, we can stand some // more bytes. This is to work around cases where hwm=0, // such as the repl. Also, if the push() triggered a // readable event, and the user called read(largeNumber) such that // needReadable was set, then we ought to push more, so that another // 'readable' event will be triggered. function needMoreData(state) { return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); } // backwards compatibility. Readable.prototype.setEncoding = function(enc) { if (!StringDecoder) StringDecoder = require('string_decoder').StringDecoder; this._readableState.decoder = new StringDecoder(enc); this._readableState.encoding = enc; }; // Don't raise the hwm > 128MB var MAX_HWM = 0x800000; function roundUpToNextPowerOf2(n) { if (n >= MAX_HWM) { n = MAX_HWM; } else { // Get the next highest power of 2 n--; for (var p = 1; p < 32; p <<= 1) n |= n >> p; n++; } return n; } function howMuchToRead(n, state) { if (state.length === 0 && state.ended) return 0; if (state.objectMode) return n === 0 ? 0 : 1; if (isNaN(n) || n === null) { // only flow one buffer at a time if (state.flowing && state.buffer.length) return state.buffer[0].length; else return state.length; } if (n <= 0) return 0; // If we're asking for more than the target buffer level, // then raise the water mark. Bump up to the next highest // power of 2, to prevent increasing it excessively in tiny // amounts. if (n > state.highWaterMark) state.highWaterMark = roundUpToNextPowerOf2(n); // don't have that much. return null, unless we've ended. if (n > state.length) { if (!state.ended) { state.needReadable = true; return 0; } else return state.length; } return n; } // you can override either this method, or the async _read(n) below. Readable.prototype.read = function(n) { var state = this._readableState; state.calledRead = true; var nOrig = n; if (typeof n !== 'number' || n > 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we // already have a bunch of data in the buffer, then just trigger // the 'readable' event and move on. if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { emitReadable(this); return null; } n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up. if (n === 0 && state.ended) { if (state.length === 0) endReadable(this); return null; } // All the actual chunk generation logic needs to be // *below* the call to _read. The reason is that in certain // synthetic stream cases, such as passthrough streams, _read // may be a completely synchronous operation which may change // the state of the read buffer, providing enough data when // before there was *not* enough. // // So, the steps are: // 1. Figure out what the state of things will be after we do // a read from the buffer. // // 2. If that resulting state will trigger a _read, then call _read. // Note that this may be asynchronous, or synchronous. Yes, it is // deeply ugly to write APIs this way, but that still doesn't mean // that the Readable class should behave improperly, as streams are // designed to be sync/async agnostic. // Take note if the _read call is sync or async (ie, if the read call // has returned yet), so that we know whether or not it's safe to emit // 'readable' etc. // // 3. Actually pull the requested chunks out of the buffer and return. // if we need a readable event, then we need to do some reading. var doRead = state.needReadable; // if we currently have less than the highWaterMark, then also read some if (state.length - n <= state.highWaterMark) doRead = true; // however, if we've ended, then there's no point, and if we're already // reading, then it's unnecessary. if (state.ended || state.reading) doRead = false; if (doRead) { state.reading = true; state.sync = true; // if the length is currently zero, then we *need* a readable event. if (state.length === 0) state.needReadable = true; // call internal read method this._read(state.highWaterMark); state.sync = false; } // If _read called its callback synchronously, then `reading` // will be false, and we need to re-evaluate how much data we // can return to the user. if (doRead && !state.reading) n = howMuchToRead(nOrig, state); var ret; if (n > 0) ret = fromList(n, state); else ret = null; if (ret === null) { state.needReadable = true; n = 0; } state.length -= n; // If we have nothing in the buffer, then we want to know // as soon as we *do* get something into the buffer. if (state.length === 0 && !state.ended) state.needReadable = true; // If we happened to read() exactly the remaining amount in the // buffer, and the EOF has been seen at this point, then make sure // that we emit 'end' on the very next tick. if (state.ended && !state.endEmitted && state.length === 0) endReadable(this); return ret; }; function chunkInvalid(state, chunk) { var er = null; if (!Buffer.isBuffer(chunk) && 'string' !== typeof chunk && chunk !== null && chunk !== undefined && !state.objectMode && !er) { er = new TypeError('Invalid non-string/buffer chunk'); } return er; } function onEofChunk(stream, state) { if (state.decoder && !state.ended) { var chunk = state.decoder.end(); if (chunk && chunk.length) { state.buffer.push(chunk); state.length += state.objectMode ? 1 : chunk.length; } } state.ended = true; // if we've ended and we have some data left, then emit // 'readable' now to make sure it gets picked up. if (state.length > 0) emitReadable(stream); else endReadable(stream); } // Don't emit readable right away in sync mode, because this can trigger // another read() call => stack overflow. This way, it might trigger // a nextTick recursion warning, but that's not so bad. function emitReadable(stream) { var state = stream._readableState; state.needReadable = false; if (state.emittedReadable) return; state.emittedReadable = true; if (state.sync) process.nextTick(function() { emitReadable_(stream); }); else emitReadable_(stream); } function emitReadable_(stream) { stream.emit('readable'); } // at this point, the user has presumably seen the 'readable' event, // and called read() to consume some data. that may have triggered // in turn another _read(n) call, in which case reading = true if // it's in progress. // However, if we're not ended, or reading, and the length < hwm, // then go ahead and try to read some more preemptively. function maybeReadMore(stream, state) { if (!state.readingMore) { state.readingMore = true; process.nextTick(function() { maybeReadMore_(stream, state); }); } } function maybeReadMore_(stream, state) { var len = state.length; while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { stream.read(0); if (len === state.length) // didn't get any data, stop spinning. break; else len = state.length; } state.readingMore = false; } // abstract method. to be overridden in specific implementation classes. // call cb(er, data) where data is <= n in length. // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. Readable.prototype._read = function(n) { this.emit('error', new Error('not implemented')); }; Readable.prototype.pipe = function(dest, pipeOpts) { var src = this; var state = this._readableState; switch (state.pipesCount) { case 0: state.pipes = dest; break; case 1: state.pipes = [state.pipes, dest]; break; default: state.pipes.push(dest); break; } state.pipesCount += 1; var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; var endFn = doEnd ? onend : cleanup; if (state.endEmitted) process.nextTick(endFn); else src.once('end', endFn); dest.on('unpipe', onunpipe); function onunpipe(readable) { if (readable !== src) return; cleanup(); } function onend() { dest.end(); } // when the dest drains, it reduces the awaitDrain counter // on the source. This would be more elegant with a .once() // handler in flow(), but adding and removing repeatedly is // too slow. var ondrain = pipeOnDrain(src); dest.on('drain', ondrain); function cleanup() { // cleanup event handlers once the pipe is broken dest.removeListener('close', onclose); dest.removeListener('finish', onfinish); dest.removeListener('drain', ondrain); dest.removeListener('error', onerror); dest.removeListener('unpipe', onunpipe); src.removeListener('end', onend); src.removeListener('end', cleanup); // if the reader is waiting for a drain event from this // specific writer, then it would cause it to never start // flowing again. // So, if this is awaiting a drain, then we just call it now. // If we don't know, then assume that we are waiting for one. if (!dest._writableState || dest._writableState.needDrain) ondrain(); } // if the dest has an error, then stop piping into it. // however, don't suppress the throwing behavior for this. function onerror(er) { unpipe(); if (EE.listenerCount(dest, 'error') === 0) dest.emit('error', er); } dest.once('error', onerror); // Both close and finish should trigger unpipe, but only once. function onclose() { dest.removeListener('finish', onfinish); unpipe(); } dest.once('close', onclose); function onfinish() { dest.removeListener('close', onclose); unpipe(); } dest.once('finish', onfinish); function unpipe() { src.unpipe(dest); } // tell the dest that it's being piped to dest.emit('pipe', src); // start the flow if it hasn't been started already. if (!state.flowing) { // the handler that waits for readable events after all // the data gets sucked out in flow. // This would be easier to follow with a .once() handler // in flow(), but that is too slow. this.on('readable', pipeOnReadable); state.flowing = true; process.nextTick(function() { flow(src); }); } return dest; }; function pipeOnDrain(src) { return function() { var dest = this; var state = src._readableState; state.awaitDrain--; if (state.awaitDrain === 0) flow(src); }; } function flow(src) { var state = src._readableState; var chunk; state.awaitDrain = 0; function write(dest, i, list) { var written = dest.write(chunk); if (false === written) { state.awaitDrain++; } } while (state.pipesCount && null !== (chunk = src.read())) { if (state.pipesCount === 1) write(state.pipes, 0, null); else state.pipes.forEach(write); src.emit('data', chunk); // if anyone needs a drain, then we have to wait for that. if (state.awaitDrain > 0) return; } // if every destination was unpiped, either before entering this // function, or in the while loop, then stop flowing. // // NB: This is a pretty rare edge case. if (state.pipesCount === 0) { state.flowing = false; // if there were data event listeners added, then switch to old mode. if (EE.listenerCount(src, 'data') > 0) emitDataEvents(src); return; } // at this point, no one needed a drain, so we just ran out of data // on the next readable event, start it over again. state.ranOut = true; } function pipeOnReadable() { if (this._readableState.ranOut) { this._readableState.ranOut = false; flow(this); } } Readable.prototype.unpipe = function(dest) { var state = this._readableState; // if we're not piping anywhere, then do nothing. if (state.pipesCount === 0) return this; // just one destination. most common case. if (state.pipesCount === 1) { // passed in one, but it's not the right one. if (dest && dest !== state.pipes) return this; if (!dest) dest = state.pipes; // got a match. state.pipes = null; state.pipesCount = 0; this.removeListener('readable', pipeOnReadable); state.flowing = false; if (dest) dest.emit('unpipe', this); return this; } // slow case. multiple pipe destinations. if (!dest) { // remove all. var dests = state.pipes; var len = state.pipesCount; state.pipes = null; state.pipesCount = 0; this.removeListener('readable', pipeOnReadable); state.flowing = false; for (var i = 0; i < len; i++) dests[i].emit('unpipe', this); return this; } // try to find the right one. var i = state.pipes.indexOf(dest); if (i === -1) return this; state.pipes.splice(i, 1); state.pipesCount -= 1; if (state.pipesCount === 1) state.pipes = state.pipes[0]; dest.emit('unpipe', this); return this; }; // set up data events if they are asked for // Ensure readable listeners eventually get something Readable.prototype.on = function(ev, fn) { var res = Stream.prototype.on.call(this, ev, fn); if (ev === 'data' && !this._readableState.flowing) emitDataEvents(this); if (ev === 'readable' && this.readable) { var state = this._readableState; if (!state.readableListening) { state.readableListening = true; state.emittedReadable = false; state.needReadable = true; if (!state.reading) { this.read(0); } else if (state.length) { emitReadable(this, state); } } } return res; }; Readable.prototype.addListener = Readable.prototype.on; // pause() and resume() are remnants of the legacy readable stream API // If the user uses them, then switch into old mode. Readable.prototype.resume = function() { emitDataEvents(this); this.read(0); this.emit('resume'); }; Readable.prototype.pause = function() { emitDataEvents(this, true); this.emit('pause'); }; function emitDataEvents(stream, startPaused) { var state = stream._readableState; if (state.flowing) { // https://github.com/isaacs/readable-stream/issues/16 throw new Error('Cannot switch to old mode now.'); } var paused = startPaused || false; var readable = false; // convert to an old-style stream. stream.readable = true; stream.pipe = Stream.prototype.pipe; stream.on = stream.addListener = Stream.prototype.on; stream.on('readable', function() { readable = true; var c; while (!paused && (null !== (c = stream.read()))) stream.emit('data', c); if (c === null) { readable = false; stream._readableState.needReadable = true; } }); stream.pause = function() { paused = true; this.emit('pause'); }; stream.resume = function() { paused = false; if (readable) process.nextTick(function() { stream.emit('readable'); }); else this.read(0); this.emit('resume'); }; // now make it start, just in case it hadn't already. stream.emit('readable'); } // wrap an old-style stream as the async data source. // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. Readable.prototype.wrap = function(stream) { var state = this._readableState; var paused = false; var self = this; stream.on('end', function() { if (state.decoder && !state.ended) { var chunk = state.decoder.end(); if (chunk && chunk.length) self.push(chunk); } self.push(null); }); stream.on('data', function(chunk) { if (state.decoder) chunk = state.decoder.write(chunk); if (!chunk || !state.objectMode && !chunk.length) return; var ret = self.push(chunk); if (!ret) { paused = true; stream.pause(); } }); // proxy all the other methods. // important when wrapping filters and duplexes. for (var i in stream) { if (typeof stream[i] === 'function' && typeof this[i] === 'undefined') { this[i] = function(method) { return function() { return stream[method].apply(stream, arguments); }}(i); } } // proxy certain important events. var events = ['error', 'close', 'destroy', 'pause', 'resume']; events.forEach(function(ev) { stream.on(ev, self.emit.bind(self, ev)); }); // when we try to consume some more bytes, simply unpause the // underlying stream. self._read = function(n) { if (paused) { paused = false; stream.resume(); } }; return self; }; // exposed for testing purposes only. Readable._fromList = fromList; // Pluck off n bytes from an array of buffers. // Length is the combined lengths of all the buffers in the list. function fromList(n, state) { var list = state.buffer; var length = state.length; var stringMode = !!state.decoder; var objectMode = !!state.objectMode; var ret; // nothing in the list, definitely empty. if (list.length === 0) return null; if (length === 0) ret = null; else if (objectMode) ret = list.shift(); else if (!n || n >= length) { // read it all, truncate the array. if (stringMode) ret = list.join(''); else ret = Buffer.concat(list, length); list.length = 0; } else { // read just some of it. if (n < list[0].length) { // just take a part of the first list item. // slice is the same for buffers and strings. var buf = list[0]; ret = buf.slice(0, n); list[0] = buf.slice(n); } else if (n === list[0].length) { // first list is a perfect match ret = list.shift(); } else { // complex case. // we have enough to cover it, but it spans past the first buffer. if (stringMode) ret = ''; else ret = new Buffer(n); var c = 0; for (var i = 0, l = list.length; i < l && c < n; i++) { var buf = list[0]; var cpy = Math.min(n - c, buf.length); if (stringMode) ret += buf.slice(0, cpy); else buf.copy(ret, c, 0, cpy); if (cpy < buf.length) list[0] = buf.slice(cpy); else list.shift(); c += cpy; } } } return ret; } function endReadable(stream) { var state = stream._readableState; // If we get here before consuming all the bytes, then that is a // bug in node. Should never happen. if (state.length > 0) throw new Error('endReadable called on non-empty stream'); if (!state.endEmitted && state.calledRead) { state.ended = true; process.nextTick(function() { // Check that we didn't get one last unshift. if (!state.endEmitted && state.length === 0) { state.endEmitted = true; stream.readable = false; stream.emit('end'); } }); } } _stream_readable// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a passthrough stream. // basically just the most minimal sort of Transform stream. // Every written chunk gets output as-is. module.exports = PassThrough; var Transform = require('_stream_transform'); var util = require('util'); util.inherits(PassThrough, Transform); function PassThrough(options) { if (!(this instanceof PassThrough)) return new PassThrough(options); Transform.call(this, options); } PassThrough.prototype._transform = function(chunk, encoding, cb) { cb(null, chunk); }; _stream_passthrough// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a duplex stream is just a stream that is both readable and writable. // Since JS doesn't have multiple prototypal inheritance, this class // prototypally inherits from Readable, and then parasitically from // Writable. module.exports = Duplex; var util = require('util'); var Readable = require('_stream_readable'); var Writable = require('_stream_writable'); util.inherits(Duplex, Readable); Object.keys(Writable.prototype).forEach(function(method) { if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; }); function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); Readable.call(this, options); Writable.call(this, options); if (options && options.readable === false) this.readable = false; if (options && options.writable === false) this.writable = false; this.allowHalfOpen = true; if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; this.once('end', onend); } // the no-half-open enforcer function onend() { // if we allow half-open state, or if the writable side ended, // then we're ok. if (this.allowHalfOpen || this._writableState.ended) return; // no more data can be written. // But allow more writes to happen in this tick. process.nextTick(this.end.bind(this)); } _stream_duplex// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. function init(list) { list._idleNext = list; list._idlePrev = list; } exports.init = init; // show the most idle item function peek(list) { if (list._idlePrev == list) return null; return list._idlePrev; } exports.peek = peek; // remove the most idle item from the list function shift(list) { var first = list._idlePrev; remove(first); return first; } exports.shift = shift; // remove a item from its list function remove(item) { if (item._idleNext) { item._idleNext._idlePrev = item._idlePrev; } if (item._idlePrev) { item._idlePrev._idleNext = item._idleNext; } item._idleNext = null; item._idlePrev = null; } exports.remove = remove; // remove a item from its list and place at the end. function append(list, item) { remove(item); item._idleNext = list._idleNext; list._idleNext._idlePrev = item; item._idlePrev = list; list._idleNext = item; } exports.append = append; function isEmpty(list) { return list._idleNext === list; } exports.isEmpty = isEmpty; _linklist// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'), path = require('path'), net = require('net'), vm = require('vm'), repl = require('repl'), inherits = util.inherits, spawn = require('child_process').spawn; exports.start = function(argv, stdin, stdout) { argv || (argv = process.argv.slice(2)); if (argv.length < 1) { console.error('Usage: node debug script.js'); process.exit(1); } // Setup input/output streams stdin = stdin || process.stdin; stdout = stdout || process.stdout; var args = ['--debug-brk'].concat(argv), interface_ = new Interface(stdin, stdout, args); stdin.resume(); process.on('uncaughtException', function(e) { console.error("There was an internal error in Node's debugger. " + 'Please report this bug.'); console.error(e.message); console.error(e.stack); if (interface_.child) interface_.child.kill(); process.exit(1); }); }; exports.port = 5858; // // Parser/Serializer for V8 debugger protocol // http://code.google.com/p/v8/wiki/DebuggerProtocol // // Usage: // p = new Protocol(); // // p.onResponse = function(res) { // // do stuff with response from V8 // }; // // socket.setEncoding('utf8'); // socket.on('data', function(s) { // // Pass strings into the protocol // p.execute(s); // }); // // function Protocol() { this._newRes(); } exports.Protocol = Protocol; Protocol.prototype._newRes = function(raw) { this.res = { raw: raw || '', headers: {} }; this.state = 'headers'; this.reqSeq = 1; this.execute(''); }; Protocol.prototype.execute = function(d) { var res = this.res; res.raw += d; switch (this.state) { case 'headers': var endHeaderIndex = res.raw.indexOf('\r\n\r\n'); if (endHeaderIndex < 0) break; var rawHeader = res.raw.slice(0, endHeaderIndex); var endHeaderByteIndex = Buffer.byteLength(rawHeader, 'utf8'); var lines = rawHeader.split('\r\n'); for (var i = 0; i < lines.length; i++) { var kv = lines[i].split(/: +/); res.headers[kv[0]] = kv[1]; } this.contentLength = +res.headers['Content-Length']; this.bodyStartByteIndex = endHeaderByteIndex + 4; this.state = 'body'; var len = Buffer.byteLength(res.raw, 'utf8'); if (len - this.bodyStartByteIndex < this.contentLength) { break; } // pass thru case 'body': var resRawByteLength = Buffer.byteLength(res.raw, 'utf8'); if (resRawByteLength - this.bodyStartByteIndex >= this.contentLength) { var buf = new Buffer(resRawByteLength); buf.write(res.raw, 0, resRawByteLength, 'utf8'); res.body = buf.slice(this.bodyStartByteIndex, this.bodyStartByteIndex + this.contentLength).toString('utf8'); // JSON parse body? res.body = res.body.length ? JSON.parse(res.body) : {}; // Done! this.onResponse(res); this._newRes(buf.slice(this.bodyStartByteIndex + this.contentLength).toString('utf8')); } break; default: throw new Error('Unknown state'); break; } }; Protocol.prototype.serialize = function(req) { req.type = 'request'; req.seq = this.reqSeq++; var json = JSON.stringify(req); return 'Content-Length: ' + Buffer.byteLength(json, 'utf8') + '\r\n\r\n' + json; }; var NO_FRAME = -1; function Client() { net.Stream.call(this); var protocol = this.protocol = new Protocol(this); this._reqCallbacks = []; var socket = this; this.currentFrame = NO_FRAME; this.currentSourceLine = -1; this.currentSource = null; this.handles = {}; this.scripts = {}; this.breakpoints = []; // Note that 'Protocol' requires strings instead of Buffers. socket.setEncoding('utf8'); socket.on('data', function(d) { protocol.execute(d); }); protocol.onResponse = this._onResponse.bind(this); } inherits(Client, net.Stream); exports.Client = Client; Client.prototype._addHandle = function(desc) { if (typeof desc != 'object' || typeof desc.handle != 'number') { return; } this.handles[desc.handle] = desc; if (desc.type == 'script') { this._addScript(desc); } }; var natives = process.binding('natives'); Client.prototype._addScript = function(desc) { this.scripts[desc.id] = desc; if (desc.name) { desc.isNative = (desc.name.replace('.js', '') in natives) || desc.name == 'node.js'; } }; Client.prototype._removeScript = function(desc) { this.scripts[desc.id] = undefined; }; Client.prototype._onResponse = function(res) { var cb, index = -1; this._reqCallbacks.some(function(fn, i) { if (fn.request_seq == res.body.request_seq) { cb = fn; index = i; return true; } }); var self = this; var handled = false; if (res.headers.Type == 'connect') { // Request a list of scripts for our own storage. self.reqScripts(); self.emit('ready'); handled = true; } else if (res.body && res.body.event == 'break') { this.emit('break', res.body); handled = true; } else if (res.body && res.body.event == 'exception') { this.emit('exception', res.body); handled = true; } else if (res.body && res.body.event == 'afterCompile') { this._addHandle(res.body.body.script); handled = true; } else if (res.body && res.body.event == 'scriptCollected') { // ??? this._removeScript(res.body.body.script); handled = true; } if (cb) { this._reqCallbacks.splice(index, 1); handled = true; var err = res.success === false && (res.message || true) || res.body.success === false && (res.body.message || true); cb(err, res.body && res.body.body || res.body, res); } if (!handled) this.emit('unhandledResponse', res.body); }; Client.prototype.req = function(req, cb) { this.write(this.protocol.serialize(req)); cb.request_seq = req.seq; this._reqCallbacks.push(cb); }; Client.prototype.reqVersion = function(cb) { cb = cb || function() {}; this.req({ command: 'version' } , function(err, body, res) { if (err) return cb(err); cb(null, res.body.body.V8Version, res.body.running); }); }; Client.prototype.reqLookup = function(refs, cb) { var self = this; // TODO: We have a cache of handle's we've already seen in this.handles // This can be used if we're careful. var req = { command: 'lookup', arguments: { handles: refs } }; cb = cb || function() {}; this.req(req, function(err, res) { if (err) return cb(err); for (var ref in res) { if (typeof res[ref] == 'object') { self._addHandle(res[ref]); } } cb(null, res); }); }; Client.prototype.reqScopes = function(cb) { var self = this, req = { command: 'scopes', arguments: {} }; cb = cb || function() {}; this.req(req, function(err, res) { if (err) return cb(err); var refs = res.scopes.map(function(scope) { return scope.object.ref; }); self.reqLookup(refs, function(err, res) { if (err) return cb(err); var globals = Object.keys(res).map(function(key) { return res[key].properties.map(function(prop) { return prop.name; }); }); cb(null, globals.reverse()); }); }); }; // This is like reqEval, except it will look up the expression in each of the // scopes associated with the current frame. Client.prototype.reqEval = function(expression, cb) { var self = this; if (this.currentFrame == NO_FRAME) { // Only need to eval in global scope. this.reqFrameEval(expression, NO_FRAME, cb); return; } cb = cb || function() {}; // Otherwise we need to get the current frame to see which scopes it has. this.reqBacktrace(function(err, bt) { if (err || !bt.frames) { // ?? return cb(null, {}); } var frame = bt.frames[self.currentFrame]; var evalFrames = frame.scopes.map(function(s) { if (!s) return; var x = bt.frames[s.index]; if (!x) return; return x.index; }); self._reqFramesEval(expression, evalFrames, cb); }); }; // Finds the first scope in the array in which the epxression evals. Client.prototype._reqFramesEval = function(expression, evalFrames, cb) { if (evalFrames.length == 0) { // Just eval in global scope. this.reqFrameEval(expression, NO_FRAME, cb); return; } var self = this; var i = evalFrames.shift(); cb = cb || function() {}; this.reqFrameEval(expression, i, function(err, res) { if (!err) return cb(null, res); self._reqFramesEval(expression, evalFrames, cb); }); }; Client.prototype.reqFrameEval = function(expression, frame, cb) { var self = this; var req = { command: 'evaluate', arguments: { expression: expression } }; if (frame == NO_FRAME) { req.arguments.global = true; } else { req.arguments.frame = frame; } cb = cb || function() {}; this.req(req, function(err, res) { if (!err) self._addHandle(res); cb(err, res); }); }; // reqBacktrace(cb) // TODO: from, to, bottom Client.prototype.reqBacktrace = function(cb) { this.req({ command: 'backtrace', arguments: { inlineRefs: true } } , cb); }; // reqSetExceptionBreak(type, cb) // TODO: from, to, bottom Client.prototype.reqSetExceptionBreak = function(type, cb) { this.req({ command: 'setexceptionbreak', arguments: { type: type, enabled: true } }, cb); }; // Returns an array of objects like this: // // { handle: 11, // type: 'script', // name: 'node.js', // id: 14, // lineOffset: 0, // columnOffset: 0, // lineCount: 562, // sourceStart: '(function(process) {\n\n ', // sourceLength: 15939, // scriptType: 2, // compilationType: 0, // context: { ref: 10 }, // text: 'node.js (lines: 562)' } // Client.prototype.reqScripts = function(cb) { var self = this; cb = cb || function() {}; this.req({ command: 'scripts' } , function(err, res) { if (err) return cb(err); for (var i = 0; i < res.length; i++) { self._addHandle(res[i]); } cb(null); }); }; Client.prototype.reqContinue = function(cb) { this.currentFrame = NO_FRAME; this.req({ command: 'continue' }, cb); }; Client.prototype.listbreakpoints = function(cb) { this.req({ command: 'listbreakpoints' }, cb); }; Client.prototype.setBreakpoint = function(req, cb) { req = { command: 'setbreakpoint', arguments: req }; this.req(req, cb); }; Client.prototype.clearBreakpoint = function(req, cb) { var req = { command: 'clearbreakpoint', arguments: req }; this.req(req, cb); }; Client.prototype.reqSource = function(from, to, cb) { var req = { command: 'source', fromLine: from, toLine: to }; this.req(req, cb); }; // client.next(1, cb); Client.prototype.step = function(action, count, cb) { var req = { command: 'continue', arguments: { stepaction: action, stepcount: count } }; this.currentFrame = NO_FRAME; this.req(req, cb); }; Client.prototype.mirrorObject = function(handle, depth, cb) { var self = this; var val; if (handle.type === 'object') { // The handle looks something like this: // { handle: 8, // type: 'object', // className: 'Object', // constructorFunction: { ref: 9 }, // protoObject: { ref: 4 }, // prototypeObject: { ref: 2 }, // properties: [ { name: 'hello', propertyType: 1, ref: 10 } ], // text: '#' } // For now ignore the className and constructor and prototype. // TJ's method of object inspection would probably be good for this: // https://groups.google.com/forum/?pli=1#!topic/nodejs-dev/4gkWBOimiOg var propertyRefs = handle.properties.map(function(p) { return p.ref; }); cb = cb || function() {}; this.reqLookup(propertyRefs, function(err, res) { if (err) { console.error('problem with reqLookup'); cb(null, handle); return; } var mirror, waiting = 1; if (handle.className == 'Array') { mirror = []; } else if (handle.className == 'Date') { mirror = new Date(handle.value); } else { mirror = {}; } var keyValues = []; handle.properties.forEach(function(prop, i) { var value = res[prop.ref]; var mirrorValue; if (value) { mirrorValue = value.value ? value.value : value.text; } else { mirrorValue = '[?]'; } if (Array.isArray(mirror) && typeof prop.name != 'number') { // Skip the 'length' property. return; } keyValues[i] = { name: prop.name, value: mirrorValue }; if (value && value.handle && depth > 0) { waiting++; self.mirrorObject(value, depth - 1, function(err, result) { if (!err) keyValues[i].value = result; waitForOthers(); }); } }); waitForOthers(); function waitForOthers() { if (--waiting === 0 && cb) { keyValues.forEach(function(kv) { mirror[kv.name] = kv.value; }); cb(null, mirror); } }; }); return; } else if (handle.type === 'function') { val = function() {}; } else if (handle.type === 'null') { val = null; } else if (handle.value !== undefined) { val = handle.value; } else if (handle.type === 'undefined') { val = undefined; } else { val = handle; } process.nextTick(function() { cb(null, val); }); }; Client.prototype.fullTrace = function(cb) { var self = this; cb = cb || function() {}; this.reqBacktrace(function(err, trace) { if (err) return cb(err); if (trace.totalFrames <= 0) return cb(Error('No frames')); var refs = []; for (var i = 0; i < trace.frames.length; i++) { var frame = trace.frames[i]; // looks like this: // { type: 'frame', // index: 0, // receiver: { ref: 1 }, // func: { ref: 0 }, // script: { ref: 7 }, // constructCall: false, // atReturn: false, // debuggerFrame: false, // arguments: [], // locals: [], // position: 160, // line: 7, // column: 2, // sourceLineText: ' debugger;', // scopes: [ { type: 1, index: 0 }, { type: 0, index: 1 } ], // text: '#00 blah() /home/ryan/projects/node/test-debug.js l...' } refs.push(frame.script.ref); refs.push(frame.func.ref); refs.push(frame.receiver.ref); } self.reqLookup(refs, function(err, res) { if (err) return cb(err); for (var i = 0; i < trace.frames.length; i++) { var frame = trace.frames[i]; frame.script = res[frame.script.ref]; frame.func = res[frame.func.ref]; frame.receiver = res[frame.receiver.ref]; } cb(null, trace); }); }); }; var commands = [ [ 'run (r)', 'cont (c)', 'next (n)', 'step (s)', 'out (o)', 'backtrace (bt)', 'setBreakpoint (sb)', 'clearBreakpoint (cb)' ], [ 'watch', 'unwatch', 'watchers', 'repl', 'restart', 'kill', 'list', 'scripts', 'breakOnException', 'breakpoints', 'version' ] ]; var helpMessage = 'Commands: ' + commands.map(function(group) { return group.join(', '); }).join(',\n'); function SourceUnderline(sourceText, position, repl) { if (!sourceText) return ''; var head = sourceText.slice(0, position), tail = sourceText.slice(position); // Colourize char if stdout supports colours if (repl.useColors) { tail = tail.replace(/(.+?)([^\w]|$)/, '\u001b[32m$1\u001b[39m$2'); } // Return source line with coloured char at `position` return [ head, tail ].join(''); } function SourceInfo(body) { var result = body.exception ? 'exception in ' : 'break in '; if (body.script) { if (body.script.name) { var name = body.script.name, dir = path.resolve() + '/'; // Change path to relative, if possible if (name.indexOf(dir) === 0) { name = name.slice(dir.length); } result += name; } else { result += '[unnamed]'; } } result += ':'; result += body.sourceLine + 1; if (body.exception) result += '\n' + body.exception.text; return result; } // This class is the repl-enabled debugger interface which is invoked on // "node debug" function Interface(stdin, stdout, args) { var self = this, child; this.stdin = stdin; this.stdout = stdout; this.args = args; // Two eval modes are available: controlEval and debugEval // But controlEval is used by default var opts = { prompt: 'debug> ', input: this.stdin, output: this.stdout, eval: this.controlEval.bind(this), useGlobal: false, ignoreUndefined: true }; if (parseInt(process.env['NODE_NO_READLINE'], 10)) { opts.terminal = false; } else if (parseInt(process.env['NODE_FORCE_READLINE'], 10)) { opts.terminal = true; // Emulate Ctrl+C if we're emulating terminal if (!this.stdout.isTTY) { process.on('SIGINT', function() { self.repl.rli.emit('SIGINT'); }); } } if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { opts.useColors = false; } this.repl = repl.start(opts); // Do not print useless warning repl._builtinLibs.splice(repl._builtinLibs.indexOf('repl'), 1); // Kill child process when main process dies this.repl.on('exit', function() { process.exit(0); }); // Handle all possible exits process.on('exit', this.killChild.bind(this)); process.once('SIGTERM', process.exit.bind(process, 0)); process.once('SIGHUP', process.exit.bind(process, 0)); var proto = Interface.prototype, ignored = ['pause', 'resume', 'exitRepl', 'handleBreak', 'requireConnection', 'killChild', 'trySpawn', 'controlEval', 'debugEval', 'print', 'childPrint', 'clearline'], shortcut = { 'run': 'r', 'cont': 'c', 'next': 'n', 'step': 's', 'out': 'o', 'backtrace': 'bt', 'setBreakpoint': 'sb', 'clearBreakpoint': 'cb', 'pause_': 'pause' }; function defineProperty(key, protoKey) { // Check arity var fn = proto[protoKey].bind(self); if (proto[protoKey].length === 0) { Object.defineProperty(self.repl.context, key, { get: fn, enumerable: true, configurable: false }); } else { self.repl.context[key] = fn; } }; // Copy all prototype methods in repl context // Setup them as getters if possible for (var i in proto) { if (Object.prototype.hasOwnProperty.call(proto, i) && ignored.indexOf(i) === -1) { defineProperty(i, i); if (shortcut[i]) defineProperty(shortcut[i], i); } } this.killed = false; this.waiting = null; this.paused = 0; this.context = this.repl.context; this.history = { debug: [], control: [] }; this.breakpoints = []; this._watchers = []; // Run script automatically this.pause(); // XXX Need to figure out why we need this delay setTimeout(function() { self.run(function() { self.resume(); }); }, 10); } // Stream control Interface.prototype.pause = function() { if (this.killed || this.paused++ > 0) return false; this.repl.rli.pause(); this.stdin.pause(); }; Interface.prototype.resume = function(silent) { if (this.killed || this.paused === 0 || --this.paused !== 0) return false; this.repl.rli.resume(); if (silent !== true) { this.repl.displayPrompt(); } this.stdin.resume(); if (this.waiting) { this.waiting(); this.waiting = null; } }; // Clear current line Interface.prototype.clearline = function() { if (this.stdout.isTTY) { this.stdout.cursorTo(0); this.stdout.clearLine(1); } else { this.stdout.write('\b'); } }; // Print text to output stream Interface.prototype.print = function(text, oneline) { if (this.killed) return; this.clearline(); this.stdout.write(typeof text === 'string' ? text : util.inspect(text)); if (oneline !== true) { this.stdout.write('\n'); } }; // Format and print text from child process Interface.prototype.childPrint = function(text) { this.print(text.toString().split(/\r\n|\r|\n/g).filter(function(chunk) { return chunk; }).map(function(chunk) { return '< ' + chunk; }).join('\n')); this.repl.displayPrompt(true); }; // Errors formatting Interface.prototype.error = function(text) { this.print(text); this.resume(); }; // Debugger's `break` event handler Interface.prototype.handleBreak = function(r) { var self = this; this.pause(); // Save execution context's data this.client.currentSourceLine = r.sourceLine; this.client.currentSourceLineText = r.sourceLineText; this.client.currentSourceColumn = r.sourceColumn; this.client.currentFrame = 0; this.client.currentScript = r.script && r.script.name; // Print break data this.print(SourceInfo(r)); // Show watchers' values this.watchers(true, function(err) { if (err) return self.error(err); // And list source self.list(2); self.resume(true); }); }; // Internal method for checking connection state Interface.prototype.requireConnection = function() { if (!this.client) { this.error('App isn\'t running... Try `run` instead'); return false; } return true; }; // Evals // Used for debugger's commands evaluation and execution Interface.prototype.controlEval = function(code, context, filename, callback) { try { // Repeat last command if empty line are going to be evaluated if (this.repl.rli.history && this.repl.rli.history.length > 0) { if (code === '(\n)') { code = '(' + this.repl.rli.history[0] + '\n)'; } } var result = vm.runInContext(code, context, filename); // Repl should not ask for next command // if current one was asynchronous. if (this.paused === 0) return callback(null, result); // Add a callback for asynchronous command // (it will be automatically invoked by .resume() method this.waiting = function() { callback(null, result); }; } catch (e) { callback(e); } }; // Used for debugger's remote evaluation (`repl`) commands Interface.prototype.debugEval = function(code, context, filename, callback) { if (!this.requireConnection()) return; var self = this, client = this.client; // Repl asked for scope variables if (code === '.scope') { client.reqScopes(callback); return; } var frame = client.currentFrame === NO_FRAME ? frame : undefined; self.pause(); // Request remote evaluation globally or in current frame client.reqFrameEval(code, frame, function(err, res) { if (err) { callback(err); self.resume(true); return; } // Request object by handles (and it's sub-properties) client.mirrorObject(res, 3, function(err, mirror) { callback(null, mirror); self.resume(true); }); }); }; // Utils // Returns number of digits (+1) function intChars(n) { // TODO dumb: if (n < 50) { return 3; } else if (n < 950) { return 4; } else if (n < 9950) { return 5; } else { return 6; } } // Adds spaces and prefix to number function leftPad(n, prefix) { var s = n.toString(), nchars = intChars(n), nspaces = nchars - s.length - 1; prefix || (prefix = ' '); for (var i = 0; i < nspaces; i++) { prefix += ' '; } return prefix + s; } // Commands // Print help message Interface.prototype.help = function() { this.print(helpMessage); }; // Run script Interface.prototype.run = function() { var callback = arguments[0]; if (this.child) { this.error('App is already running... Try `restart` instead'); callback && callback(true); } else { this.trySpawn(callback); } }; // Restart script Interface.prototype.restart = function() { if (!this.requireConnection()) return; var self = this; self.pause(); self.killChild(); // XXX need to wait a little bit for the restart to work? setTimeout(function() { self.trySpawn(); self.resume(); }, 1000); }; // Print version Interface.prototype.version = function() { if (!this.requireConnection()) return; var self = this; this.pause(); this.client.reqVersion(function(err, v) { if (err) { self.error(err); } else { self.print(v); } self.resume(); }); }; // List source code Interface.prototype.list = function(delta) { if (!this.requireConnection()) return; delta || (delta = 5); var self = this, client = this.client, from = client.currentSourceLine - delta + 1, to = client.currentSourceLine + delta + 1; self.pause(); client.reqSource(from, to, function(err, res) { if (err || !res) { self.error('You can\'t list source code right now'); self.resume(); return; } var lines = res.source.split('\n'); for (var i = 0; i < lines.length; i++) { var lineno = res.fromLine + i + 1; if (lineno < from || lineno > to) continue; var current = lineno == 1 + client.currentSourceLine, breakpoint = client.breakpoints.some(function(bp) { return bp.script === client.currentScript && bp.line == lineno; }); if (lineno == 1) { // The first line needs to have the module wrapper filtered out of // it. var wrapper = require('module').wrapper[0]; lines[i] = lines[i].slice(wrapper.length); client.currentSourceColumn -= wrapper.length; } // Highlight executing statement var line; if (current) { line = SourceUnderline(lines[i], client.currentSourceColumn, self.repl); } else { line = lines[i]; } self.print(leftPad(lineno, breakpoint && '*') + ' ' + line); } self.resume(); }); }; // Print backtrace Interface.prototype.backtrace = function() { if (!this.requireConnection()) return; var self = this, client = this.client; self.pause(); client.fullTrace(function(err, bt) { if (err) { self.error('Can\'t request backtrace now'); self.resume(); return; } if (bt.totalFrames == 0) { self.print('(empty stack)'); } else { var trace = [], firstFrameNative = bt.frames[0].script.isNative; for (var i = 0; i < bt.frames.length; i++) { var frame = bt.frames[i]; if (!firstFrameNative && frame.script.isNative) break; var text = '#' + i + ' '; if (frame.func.inferredName && frame.func.inferredName.length > 0) { text += frame.func.inferredName + ' '; } text += path.basename(frame.script.name) + ':'; text += (frame.line + 1) + ':' + (frame.column + 1); trace.push(text); } self.print(trace.join('\n')); } self.resume(); }); }; // First argument tells if it should display internal node scripts or not // (available only for internal debugger's functions) Interface.prototype.scripts = function() { if (!this.requireConnection()) return; var client = this.client, displayNatives = arguments[0] || false, scripts = []; this.pause(); for (var id in client.scripts) { var script = client.scripts[id]; if (typeof script == 'object' && script.name) { if (displayNatives || script.name == client.currentScript || !script.isNative) { scripts.push( (script.name == client.currentScript ? '* ' : ' ') + id + ': ' + path.basename(script.name) ); } } } this.print(scripts.join('\n')); this.resume(); }; // Continue execution of script Interface.prototype.cont = function() { if (!this.requireConnection()) return; this.pause(); var self = this; this.client.reqContinue(function(err) { if (err) self.error(err); self.resume(); }); }; // Step commands generator Interface.stepGenerator = function(type, count) { return function() { if (!this.requireConnection()) return; var self = this; self.pause(); self.client.step(type, count, function(err, res) { if (err) self.error(err); self.resume(); }); }; }; // Jump to next command Interface.prototype.next = Interface.stepGenerator('next', 1); // Step in Interface.prototype.step = Interface.stepGenerator('in', 1); // Step out Interface.prototype.out = Interface.stepGenerator('out', 1); // Watch Interface.prototype.watch = function(expr) { this._watchers.push(expr); }; // Unwatch Interface.prototype.unwatch = function(expr) { var index = this._watchers.indexOf(expr); // Unwatch by expression // or // Unwatch by watcher number this._watchers.splice(index !== -1 ? index : +expr, 1); }; // List watchers Interface.prototype.watchers = function() { var self = this, verbose = arguments[0] || false, callback = arguments[1] || function() {}, waiting = this._watchers.length, values = []; this.pause(); if (!waiting) { this.resume(); return callback(); } this._watchers.forEach(function(watcher, i) { self.debugEval(watcher, null, null, function(err, value) { values[i] = err ? '' : value; wait(); }); }); function wait() { if (--waiting === 0) { if (verbose) self.print('Watchers:'); self._watchers.forEach(function(watcher, i) { self.print(leftPad(i, ' ') + ': ' + watcher + ' = ' + JSON.stringify(values[i])); }); if (verbose) self.print(''); self.resume(); callback(null); } } }; // Break on exception Interface.prototype.breakOnException = function breakOnException() { if (!this.requireConnection()) return; var self = this; // Break on exceptions this.pause(); this.client.reqSetExceptionBreak('all', function(err, res) { self.resume(); }); }; // Add breakpoint Interface.prototype.setBreakpoint = function(script, line, condition, silent) { if (!this.requireConnection()) return; var self = this, scriptId, ambiguous; // setBreakpoint() should insert breakpoint on current line if (script === undefined) { script = this.client.currentScript; line = this.client.currentSourceLine + 1; } // setBreakpoint(line-number) should insert breakpoint in current script if (line === undefined && typeof script === 'number') { line = script; script = this.client.currentScript; } if (/\(\)$/.test(script)) { // setBreakpoint('functionname()'); var req = { type: 'function', target: script.replace(/\(\)$/, ''), condition: condition }; } else { // setBreakpoint('scriptname') if (script != +script && !this.client.scripts[script]) { var scripts = this.client.scripts; Object.keys(scripts).forEach(function(id) { if (scripts[id] && scripts[id].name.indexOf(script) !== -1) { if (scriptId) { ambiguous = true; } scriptId = id; } }); } else { scriptId = script; } if (ambiguous) return this.error('Script name is ambiguous'); if (line <= 0) return this.error('Line should be a positive value'); var req; if (scriptId) { req = { type: 'scriptId', target: scriptId, line: line - 1, condition: condition }; } else { this.print('Warning: script \'' + script + '\' was not loaded yet.'); var escapedPath = script.replace(/([/\\.?*()^${}|[\]])/g, '\\$1'); var scriptPathRegex = '^(.*[\\/\\\\])?' + escapedPath + '$'; req = { type: 'scriptRegExp', target: scriptPathRegex, line: line - 1, condition: condition }; } } self.pause(); self.client.setBreakpoint(req, function(err, res) { if (err) { if (!silent) { self.error(err); } } else { if (!silent) { self.list(5); } // Try load scriptId and line from response if (!scriptId) { scriptId = res.script_id; line = res.line + 1; } // Remember this breakpoint even if scriptId is not resolved yet self.client.breakpoints.push({ id: res.breakpoint, scriptId: scriptId, script: (self.client.scripts[scriptId] || {}).name, line: line, condition: condition, scriptReq: script }); } self.resume(); }); }; // Clear breakpoint Interface.prototype.clearBreakpoint = function(script, line) { if (!this.requireConnection()) return; var ambiguous, breakpoint, index; this.client.breakpoints.some(function(bp, i) { if (bp.scriptId === script || bp.scriptReq === script || (bp.script && bp.script.indexOf(script) !== -1)) { if (index !== undefined) { ambiguous = true; } if (bp.line === line) { index = i; breakpoint = bp.id; return true; } } }); if (ambiguous) return this.error('Script name is ambiguous'); if (breakpoint === undefined) { return this.error('Script : ' + script + ' not found'); } var self = this, req = { breakpoint: breakpoint }; self.pause(); self.client.clearBreakpoint(req, function(err, res) { if (err) { self.error(err); } else { self.client.breakpoints.splice(index, 1); self.list(5); } self.resume(); }); }; // Show breakpoints Interface.prototype.breakpoints = function() { if (!this.requireConnection()) return; this.pause(); var self = this; this.client.listbreakpoints(function(err, res) { if (err) { self.error(err); } else { self.print(res); self.resume(); } }); }; // Pause child process Interface.prototype.pause_ = function() { if (!this.requireConnection()) return; var self = this, cmd = 'process._debugPause();'; this.pause(); this.client.reqFrameEval(cmd, NO_FRAME, function(err, res) { if (err) { self.error(err); } else { self.resume(); } }); }; // Kill child process Interface.prototype.kill = function() { if (!this.child) return; this.killChild(); }; // Activate debug repl Interface.prototype.repl = function() { if (!this.requireConnection()) return; var self = this; self.print('Press Ctrl + C to leave debug repl'); // Don't display any default messages var listeners = this.repl.rli.listeners('SIGINT').slice(0); this.repl.rli.removeAllListeners('SIGINT'); // Exit debug repl on Ctrl + C this.repl.rli.once('SIGINT', function() { // Restore all listeners process.nextTick(function() { listeners.forEach(function(listener) { self.repl.rli.on('SIGINT', listener); }); }); // Exit debug repl self.exitRepl(); }); // Set new this.repl.eval = this.debugEval.bind(this); this.repl.context = {}; // Swap history this.history.control = this.repl.rli.history; this.repl.rli.history = this.history.debug; this.repl.prompt = '> '; this.repl.rli.setPrompt('> '); this.repl.displayPrompt(); }; // Exit debug repl Interface.prototype.exitRepl = function() { // Restore eval this.repl.eval = this.controlEval.bind(this); // Swap history this.history.debug = this.repl.rli.history; this.repl.rli.history = this.history.control; this.repl.context = this.context; this.repl.prompt = 'debug> '; this.repl.rli.setPrompt('debug> '); this.repl.displayPrompt(); }; // Quit Interface.prototype.quit = function() { this.killChild(); process.exit(0); }; // Kills child process Interface.prototype.killChild = function() { if (this.child) { this.child.kill(); this.child = null; } if (this.client) { // Save breakpoints this.breakpoints = this.client.breakpoints; this.client.destroy(); this.client = null; } }; // Spawns child process (and restores breakpoints) Interface.prototype.trySpawn = function(cb) { var self = this, breakpoints = this.breakpoints || [], port = exports.port, host = 'localhost', childArgs = this.args; this.killChild(); if (this.args.length === 2) { var match = this.args[1].match(/^([^:]+):(\d+)$/); if (match) { // Connecting to remote debugger // `node debug localhost:5858` host = match[1]; port = parseInt(match[2], 10); this.child = { kill: function() { // TODO Do we really need to handle it? } }; } } else if (this.args.length === 3) { // `node debug -p pid` if (this.args[1] === '-p' && /^\d+$/.test(this.args[2])) { this.child = { kill: function() { // TODO Do we really need to handle it? } }; process._debugProcess(parseInt(this.args[2], 10)); } else { var match = this.args[1].match(/^--port=(\d+)$/); if (match) { // Start debugger on custom port // `node debug --port=5858 app.js` port = parseInt(match[1], 10); childArgs = ['--debug-brk=' + port].concat(this.args.slice(2)); } } } if (!this.child) { this.child = spawn(process.execPath, childArgs); this.child.stdout.on('data', this.childPrint.bind(this)); this.child.stderr.on('data', this.childPrint.bind(this)); } this.pause(); var client = self.client = new Client(), connectionAttempts = 0; client.once('ready', function() { self.stdout.write(' ok\n'); // Restore breakpoints breakpoints.forEach(function(bp) { self.print('Restoring breakpoint ' + bp.scriptReq + ':' + bp.line); self.setBreakpoint(bp.scriptReq, bp.line, bp.condition, true); }); client.on('close', function() { self.pause(); self.print('program terminated'); self.resume(); self.client = null; self.killChild(); }); if (cb) cb(); self.resume(); }); client.on('unhandledResponse', function(res) { self.pause(); self.print('\nunhandled res:' + JSON.stringify(res)); self.resume(); }); client.on('break', function(res) { self.handleBreak(res.body); }); client.on('exception', function(res) { self.handleBreak(res.body); }); client.on('error', connectError); function connectError() { // If it's failed to connect 4 times then don't catch the next error if (connectionAttempts >= 10) { client.removeListener('error', connectError); } setTimeout(attemptConnect, 500); } function attemptConnect() { ++connectionAttempts; self.stdout.write('.'); client.connect(port, host); } setTimeout(function() { self.print('connecting..', true); attemptConnect(); }, 50); }; _debugger// Copyright (c) Microsoft Corporation. All rights reserved. // Patch classes for chakra var extend = function(dest, from) { var props = Object.getOwnPropertyNames(from); props.forEach(function(name) { var destination = Object.getOwnPropertyDescriptor(from, name); try { Object.defineProperty(dest, name, destination); } catch (e) { // ignore errors } }); }; function patchErrorStack() { var util = require('util'); // the 2nd argument is ignored for now Error.__proto__.captureStackTrace = function(err, func) { var currentStack; try { throw new Error; } catch (e) { currentStack = e.stack; } // remove the first line so this function won't be seen var splittedStack = currentStack.split('\n'); var firstLine = splittedStack[0]; splittedStack.splice(0, 3); if (err.name) { firstLine = err.name + ': ' + err.message; } err.stack = firstLine + '\n' + splittedStack.join('\n'); } } function patchTypedArrays() { ArrayBuffer.prototype.slice = function(begin, end) { if (!begin) { throw new Error('Wrong number of arguments.'); } // boundary/arguments check - we do exactly the same ones as in node's // ArrayBuffer if (!end) { end = this.byteLength; } if (begin < 0) { begin = this.byteLength + begin; } if (begin < 0) { begin = 0; } if (begin > this.byteLength) { begin = this.byteLength; } if (end < 0) { end = this.byteLength + end; } if (end < 0) { end = 0; } if (end > this.byteLength) { end = this.byteLength; } if (begin > end) { begin = end; } var slice_length = end - begin; var slicedBuffer = new ArrayBuffer(slice_length); var sourceDataView = new DataView(this); var destDataView = new DataView(slicedBuffer); for (var i = 0; i < slice_length; i++) { destDataView.setInt8(i, sourceDataView.getInt8(begin + i)); } return slicedBuffer; }; // patch slice method for each type: [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array].forEach(function(item) { item.prototype.slice = item.prototype.subarray; item.prototype.get = function(i) { return this[i]; }; item.prototype.set = function(first, second) { if (first instanceof Array) { // in this case - first is an array of values, second is the offset for (var j = 0; j < first.length; j++) { this[j + second] = first[j]; } } else { this[first] = second; } } }); } // this patch fix some failing tests which rely on the stack trace // this little patch adds "JsonParse" to the stack trace function patchJsonParse() { var JsonParseOriginal = JSON.parse; var JsonParse = function() { return JsonParseOriginal.apply(this, arguments); } JSON.parse = JsonParse; } if (!global.__chakra_patched) { // patch console patchErrorStack(); patchTypedArrays(); patchJsonParse(); Object.defineProperty( global, '__chakra_patched', { enumerable: false, value: true }); } _chakra_patch// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Transform = require('_stream_transform'); var binding = process.binding('zlib'); var util = require('util'); var assert = require('assert').ok; // zlib doesn't provide these, so kludge them in following the same // const naming scheme zlib uses. binding.Z_MIN_WINDOWBITS = 8; binding.Z_MAX_WINDOWBITS = 15; binding.Z_DEFAULT_WINDOWBITS = 15; // fewer than 64 bytes per chunk is stupid. // technically it could work with as few as 8, but even 64 bytes // is absurdly low. Usually a MB or more is best. binding.Z_MIN_CHUNK = 64; binding.Z_MAX_CHUNK = Infinity; binding.Z_DEFAULT_CHUNK = (16 * 1024); binding.Z_MIN_MEMLEVEL = 1; binding.Z_MAX_MEMLEVEL = 9; binding.Z_DEFAULT_MEMLEVEL = 8; binding.Z_MIN_LEVEL = -1; binding.Z_MAX_LEVEL = 9; binding.Z_DEFAULT_LEVEL = binding.Z_DEFAULT_COMPRESSION; // expose all the zlib constants Object.keys(binding).forEach(function(k) { if (k.match(/^Z/)) exports[k] = binding[k]; }); // translation table for return codes. exports.codes = { Z_OK: binding.Z_OK, Z_STREAM_END: binding.Z_STREAM_END, Z_NEED_DICT: binding.Z_NEED_DICT, Z_ERRNO: binding.Z_ERRNO, Z_STREAM_ERROR: binding.Z_STREAM_ERROR, Z_DATA_ERROR: binding.Z_DATA_ERROR, Z_MEM_ERROR: binding.Z_MEM_ERROR, Z_BUF_ERROR: binding.Z_BUF_ERROR, Z_VERSION_ERROR: binding.Z_VERSION_ERROR }; Object.keys(exports.codes).forEach(function(k) { exports.codes[exports.codes[k]] = k; }); exports.Deflate = Deflate; exports.Inflate = Inflate; exports.Gzip = Gzip; exports.Gunzip = Gunzip; exports.DeflateRaw = DeflateRaw; exports.InflateRaw = InflateRaw; exports.Unzip = Unzip; exports.createDeflate = function(o) { return new Deflate(o); }; exports.createInflate = function(o) { return new Inflate(o); }; exports.createDeflateRaw = function(o) { return new DeflateRaw(o); }; exports.createInflateRaw = function(o) { return new InflateRaw(o); }; exports.createGzip = function(o) { return new Gzip(o); }; exports.createGunzip = function(o) { return new Gunzip(o); }; exports.createUnzip = function(o) { return new Unzip(o); }; // Convenience methods. // compress/decompress a string or buffer in one step. exports.deflate = function(buffer, callback) { zlibBuffer(new Deflate(), buffer, callback); }; exports.gzip = function(buffer, callback) { zlibBuffer(new Gzip(), buffer, callback); }; exports.deflateRaw = function(buffer, callback) { zlibBuffer(new DeflateRaw(), buffer, callback); }; exports.unzip = function(buffer, callback) { zlibBuffer(new Unzip(), buffer, callback); }; exports.inflate = function(buffer, callback) { zlibBuffer(new Inflate(), buffer, callback); }; exports.gunzip = function(buffer, callback) { zlibBuffer(new Gunzip(), buffer, callback); }; exports.inflateRaw = function(buffer, callback) { zlibBuffer(new InflateRaw(), buffer, callback); }; function zlibBuffer(engine, buffer, callback) { var buffers = []; var nread = 0; engine.on('error', onError); engine.on('end', onEnd); engine.end(buffer); flow(); function flow() { var chunk; while (null !== (chunk = engine.read())) { buffers.push(chunk); nread += chunk.length; } engine.once('readable', flow); } function onError(err) { engine.removeListener('end', onEnd); engine.removeListener('readable', flow); callback(err); } function onEnd() { var buf = Buffer.concat(buffers, nread); buffers = []; callback(null, buf); engine.close(); } } // generic zlib // minimal 2-byte header function Deflate(opts) { if (!(this instanceof Deflate)) return new Deflate(opts); Zlib.call(this, opts, binding.DEFLATE); } function Inflate(opts) { if (!(this instanceof Inflate)) return new Inflate(opts); Zlib.call(this, opts, binding.INFLATE); } // gzip - bigger header, same deflate compression function Gzip(opts) { if (!(this instanceof Gzip)) return new Gzip(opts); Zlib.call(this, opts, binding.GZIP); } function Gunzip(opts) { if (!(this instanceof Gunzip)) return new Gunzip(opts); Zlib.call(this, opts, binding.GUNZIP); } // raw - no header function DeflateRaw(opts) { if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); Zlib.call(this, opts, binding.DEFLATERAW); } function InflateRaw(opts) { if (!(this instanceof InflateRaw)) return new InflateRaw(opts); Zlib.call(this, opts, binding.INFLATERAW); } // auto-detect header. function Unzip(opts) { if (!(this instanceof Unzip)) return new Unzip(opts); Zlib.call(this, opts, binding.UNZIP); } // the Zlib class they all inherit from // This thing manages the queue of requests, and returns // true or false if there is anything in the queue when // you call the .write() method. function Zlib(opts, mode) { this._opts = opts = opts || {}; this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK; Transform.call(this, opts); if (opts.flush) { if (opts.flush !== binding.Z_NO_FLUSH && opts.flush !== binding.Z_PARTIAL_FLUSH && opts.flush !== binding.Z_SYNC_FLUSH && opts.flush !== binding.Z_FULL_FLUSH && opts.flush !== binding.Z_FINISH && opts.flush !== binding.Z_BLOCK) { throw new Error('Invalid flush flag: ' + opts.flush); } } this._flushFlag = opts.flush || binding.Z_NO_FLUSH; if (opts.chunkSize) { if (opts.chunkSize < exports.Z_MIN_CHUNK || opts.chunkSize > exports.Z_MAX_CHUNK) { throw new Error('Invalid chunk size: ' + opts.chunkSize); } } if (opts.windowBits) { if (opts.windowBits < exports.Z_MIN_WINDOWBITS || opts.windowBits > exports.Z_MAX_WINDOWBITS) { throw new Error('Invalid windowBits: ' + opts.windowBits); } } if (opts.level) { if (opts.level < exports.Z_MIN_LEVEL || opts.level > exports.Z_MAX_LEVEL) { throw new Error('Invalid compression level: ' + opts.level); } } if (opts.memLevel) { if (opts.memLevel < exports.Z_MIN_MEMLEVEL || opts.memLevel > exports.Z_MAX_MEMLEVEL) { throw new Error('Invalid memLevel: ' + opts.memLevel); } } if (opts.strategy) { if (opts.strategy != exports.Z_FILTERED && opts.strategy != exports.Z_HUFFMAN_ONLY && opts.strategy != exports.Z_RLE && opts.strategy != exports.Z_FIXED && opts.strategy != exports.Z_DEFAULT_STRATEGY) { throw new Error('Invalid strategy: ' + opts.strategy); } } if (opts.dictionary) { if (!Buffer.isBuffer(opts.dictionary)) { throw new Error('Invalid dictionary: it should be a Buffer instance'); } } this._binding = new binding.Zlib(mode); var self = this; this._hadError = false; this._binding.onerror = function(message, errno) { // there is no way to cleanly recover. // continuing only obscures problems. self._binding = null; self._hadError = true; var error = new Error(message); error.errno = errno; error.code = exports.codes[errno]; self.emit('error', error); }; this._binding.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, opts.level || exports.Z_DEFAULT_COMPRESSION, opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, opts.strategy || exports.Z_DEFAULT_STRATEGY, opts.dictionary); this._buffer = new Buffer(this._chunkSize); this._offset = 0; this._closed = false; this.once('end', this.close); } util.inherits(Zlib, Transform); Zlib.prototype.reset = function reset() { return this._binding.reset(); }; // This is the _flush function called by the transform class, // internally, when the last chunk has been written. Zlib.prototype._flush = function(callback) { this._transform(new Buffer(0), '', callback); }; Zlib.prototype.flush = function(callback) { var ws = this._writableState; if (ws.ended) { if (callback) process.nextTick(callback); } else if (ws.ending) { if (callback) this.once('end', callback); } else if (ws.needDrain) { var self = this; this.once('drain', function() { self.flush(callback); }); } else { this._flushFlag = binding.Z_FULL_FLUSH; this.write(new Buffer(0), '', callback); } }; Zlib.prototype.close = function(callback) { if (callback) process.nextTick(callback); if (this._closed) return; this._closed = true; this._binding.close(); var self = this; process.nextTick(function() { self.emit('close'); }); }; Zlib.prototype._transform = function(chunk, encoding, cb) { var flushFlag; var ws = this._writableState; var ending = ws.ending || ws.ended; var last = ending && (!chunk || ws.length === chunk.length); if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input')); // If it's the last chunk, or a final flush, we use the Z_FINISH flush flag. // If it's explicitly flushing at some other time, then we use // Z_FULL_FLUSH. Otherwise, use Z_NO_FLUSH for maximum compression // goodness. if (last) flushFlag = binding.Z_FINISH; else { flushFlag = this._flushFlag; // once we've flushed the last of the queue, stop flushing and // go back to the normal behavior. if (chunk.length >= ws.length) { this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH; } } var availInBefore = chunk && chunk.length; var availOutBefore = this._chunkSize - this._offset; var inOff = 0; var req = this._binding.write(flushFlag, chunk, // in inOff, // in_off availInBefore, // in_len this._buffer, // out this._offset, //out_off availOutBefore); // out_len req.buffer = chunk; req.callback = callback; var self = this; function callback(availInAfter, availOutAfter, buffer) { if (self._hadError) return; var have = availOutBefore - availOutAfter; assert(have >= 0, 'have should not go down'); if (have > 0) { var out = self._buffer.slice(self._offset, self._offset + have); self._offset += have; // serve some output to the consumer. self.push(out); } // exhausted the output buffer, or used all the input create a new one. if (availOutAfter === 0 || self._offset >= self._chunkSize) { availOutBefore = self._chunkSize; self._offset = 0; self._buffer = new Buffer(self._chunkSize); } if (availOutAfter === 0) { // Not actually done. Need to reprocess. // Also, update the availInBefore to the availInAfter value, // so that if we have to hit it a third (fourth, etc.) time, // it'll have the correct byte counts. inOff += (availInBefore - availInAfter); availInBefore = availInAfter; var newReq = self._binding.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize); newReq.callback = callback; // this same function newReq.buffer = chunk; return; } // finished with the chunk. cb(); } }; util.inherits(Deflate, Zlib); util.inherits(Inflate, Zlib); util.inherits(Gzip, Zlib); util.inherits(Gunzip, Zlib); util.inherits(DeflateRaw, Zlib); util.inherits(InflateRaw, Zlib); util.inherits(Unzip, Zlib); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var binding = process.binding('evals'); module.exports = Script; Script.Script = Script; function Script(code, ctx, filename) { if (!(this instanceof Script)) { return new Script(code, ctx, filename); } var ns = new binding.NodeScript(code, ctx, filename); // bind all methods to this Script object Object.keys(binding.NodeScript.prototype).forEach(function(f) { if (typeof binding.NodeScript.prototype[f] === 'function') { this[f] = function() { if (!(this instanceof Script)) { throw new TypeError('invalid call to ' + f); } return ns[f].apply(ns, arguments); }; } }, this); } Script.createScript = function(code, ctx, name) { return new Script(code, ctx, name); }; Script.createContext = binding.NodeScript.createContext; Script.runInContext = binding.NodeScript.runInContext; Script.runInThisContext = binding.NodeScript.runInThisContext; Script.runInNewContext = binding.NodeScript.runInNewContext; vm// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': return JSON.stringify(args[i++]); default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (x === null || typeof x !== 'object') { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; exports.print = function() { for (var i = 0, len = arguments.length; i < len; ++i) { process.stdout.write(String(arguments[i])); } }; exports.puts = function() { for (var i = 0, len = arguments.length; i < len; ++i) { process.stdout.write(arguments[i] + '\n'); } }; exports.debug = function(x) { process.stderr.write('DEBUG: ' + x + '\n'); }; var error = exports.error = function(x) { for (var i = 0, len = arguments.length; i < len; ++i) { process.stderr.write(arguments[i] + '\n'); } }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (typeof opts === 'boolean') { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (typeof ctx.showHidden === 'undefined') ctx.showHidden = false; if (typeof ctx.depth === 'undefined') ctx.depth = 2; if (typeof ctx.colors === 'undefined') ctx.colors = false; if (typeof ctx.customInspect === 'undefined') ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && typeof value.inspect === 'function' && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { return String(value.inspect(recurseTimes)); } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (typeof value === 'function') { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (typeof value === 'function') { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { switch (typeof value) { case 'undefined': return ctx.stylize('undefined', 'undefined'); case 'string': var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); case 'number': return ctx.stylize('' + value, 'number'); case 'boolean': return ctx.stylize('' + value, 'boolean'); } // For some reason typeof null is "object", so special case here. if (value === null) { return ctx.stylize('null', 'null'); } } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (recurseTimes === null) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (typeof name === 'undefined') { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); } exports.isArray = isArray; function isRegExp(re) { return typeof re === 'object' && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; function isDate(d) { return typeof d === 'object' && objectToString(d) === '[object Date]'; } exports.isDate = isDate; function isError(e) { return typeof e === 'object' && objectToString(e) === '[object Error]'; } exports.isError = isError; function objectToString(o) { return Object.prototype.toString.call(o); } exports.p = exports.deprecate(function() { for (var i = 0, len = arguments.length; i < len; ++i) { error(exports.inspect(arguments[i])); } }, 'util.p: Use console.error() instead.'); function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } exports.log = function(msg) { exports.puts(timestamp() + ' - ' + msg.toString()); }; exports.exec = exports.deprecate(function() { return require('child_process').exec.apply(this, arguments); }, 'util.exec is now called `child_process.exec`.'); function pump(readStream, writeStream, callback) { var callbackCalled = false; function call(a, b, c) { if (callback && !callbackCalled) { callback(a, b, c); callbackCalled = true; } } readStream.addListener('data', function(chunk) { if (writeStream.write(chunk) === false) readStream.pause(); }); writeStream.addListener('drain', function() { readStream.resume(); }); readStream.addListener('end', function() { writeStream.end(); }); readStream.addListener('close', function() { call(); }); readStream.addListener('error', function(err) { writeStream.end(); call(err); }); writeStream.addListener('error', function(err) { readStream.destroy(); call(err); }); } exports.pump = exports.deprecate(pump, 'util.pump() is deprecated. Use readableStream.pipe() instead.'); /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ exports.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; exports._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || typeof add !== 'object') return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } util// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var punycode = require('punycode'); exports.parse = urlParse; exports.resolve = urlResolve; exports.resolveObject = urlResolveObject; exports.format = urlFormat; exports.Url = Url; function Url() { this.protocol = null; this.slashes = null; this.auth = null; this.host = null; this.port = null; this.hostname = null; this.hash = null; this.search = null; this.query = null; this.pathname = null; this.path = null; this.href = null; } // Reference: RFC 3986, RFC 1808, RFC 2396 // define these here so at least they only have to be // compiled once on the first module load. var protocolPattern = /^([a-z0-9.+-]+:)/i, portPattern = /:[0-9]*$/, // RFC 2396: characters reserved for delimiting URLs. // We actually just auto-escape these. delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], // RFC 2396: characters not allowed for various reasons. unwise = ['{', '}', '|', '\\', '^', '~', '`'].concat(delims), // Allowed by RFCs, but cause of XSS attacks. Always escape these. autoEscape = ['\''].concat(delims), // Characters that are never ever allowed in a hostname. // Note that any invalid chars are also handled, but these // are the ones that are *expected* to be seen, so we fast-path // them. nonHostChars = ['%', '/', '?', ';', '#'] .concat(unwise).concat(autoEscape), hostEndingChars = ['/', '?', '#'], hostnameMaxLen = 255, hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, // protocols that can allow "unsafe" and "unwise" chars. unsafeProtocol = { 'javascript': true, 'javascript:': true }, // protocols that never have a hostname. hostlessProtocol = { 'javascript': true, 'javascript:': true }, // protocols that always contain a // bit. slashedProtocol = { 'http': true, 'https': true, 'ftp': true, 'gopher': true, 'file': true, 'http:': true, 'https:': true, 'ftp:': true, 'gopher:': true, 'file:': true }, querystring = require('querystring'); function urlParse(url, parseQueryString, slashesDenoteHost) { if (url && typeof(url) === 'object' && url instanceof Url) return url; var u = new Url; u.parse(url, parseQueryString, slashesDenoteHost); return u; } Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { if (typeof url !== 'string') { throw new TypeError("Parameter 'url' must be a string, not " + typeof url); } var rest = url; // trim before proceeding. // This is to support parse stuff like " http://foo.com \n" rest = rest.trim(); var proto = protocolPattern.exec(rest); if (proto) { proto = proto[0]; var lowerProto = proto.toLowerCase(); this.protocol = lowerProto; rest = rest.substr(proto.length); } // figure out if it's got a host // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { var slashes = rest.substr(0, 2) === '//'; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.substr(2); this.slashes = true; } } if (!hostlessProtocol[proto] && (slashes || (proto && !slashedProtocol[proto]))) { // there's a hostname. // the first instance of /, ?, ;, or # ends the host. // // If there is an @ in the hostname, then non-host chars *are* allowed // to the left of the last @ sign, unless some host-ending character // comes *before* the @-sign. // URLs are obnoxious. // // ex: // http://a@b@c/ => user:a@b host:c // http://a@b?@c => user:a host:c path:/?@c // v0.12 TODO(isaacs): This is not quite how Chrome does things. // Review our test case against browsers more comprehensively. // find the first instance of any hostEndingChars var hostEnd = -1; for (var i = 0; i < hostEndingChars.length; i++) { var hec = rest.indexOf(hostEndingChars[i]); if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec; } // at this point, either we have an explicit point where the // auth portion cannot go past, or the last @ char is the decider. var auth, atSign; if (hostEnd === -1) { // atSign can be anywhere. atSign = rest.lastIndexOf('@'); } else { // atSign must be in auth portion. // http://a@b/c@d => host:b auth:a path:/c@d atSign = rest.lastIndexOf('@', hostEnd); } // Now we have a portion which is definitely the auth. // Pull that off. if (atSign !== -1) { auth = rest.slice(0, atSign); rest = rest.slice(atSign + 1); this.auth = decodeURIComponent(auth); } // the host is the remaining to the left of the first non-host char hostEnd = -1; for (var i = 0; i < nonHostChars.length; i++) { var hec = rest.indexOf(nonHostChars[i]); if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec; } // if we still have not hit it, then the entire thing is a host. if (hostEnd === -1) hostEnd = rest.length; this.host = rest.slice(0, hostEnd); rest = rest.slice(hostEnd); // pull out port. this.parseHost(); // we've indicated that there is a hostname, // so even if it's empty, it has to be present. this.hostname = this.hostname || ''; // if hostname begins with [ and ends with ] // assume that it's an IPv6 address. var ipv6Hostname = this.hostname[0] === '[' && this.hostname[this.hostname.length - 1] === ']'; // validate a little. if (!ipv6Hostname) { var hostparts = this.hostname.split(/\./); for (var i = 0, l = hostparts.length; i < l; i++) { var part = hostparts[i]; if (!part) continue; if (!part.match(hostnamePartPattern)) { var newpart = ''; for (var j = 0, k = part.length; j < k; j++) { if (part.charCodeAt(j) > 127) { // we replace non-ASCII char with a temporary placeholder // we need this to make sure size of hostname is not // broken by replacing non-ASCII by nothing newpart += 'x'; } else { newpart += part[j]; } } // we test again with ASCII char only if (!newpart.match(hostnamePartPattern)) { var validParts = hostparts.slice(0, i); var notHost = hostparts.slice(i + 1); var bit = part.match(hostnamePartStart); if (bit) { validParts.push(bit[1]); notHost.unshift(bit[2]); } if (notHost.length) { rest = '/' + notHost.join('.') + rest; } this.hostname = validParts.join('.'); break; } } } } if (this.hostname.length > hostnameMaxLen) { this.hostname = ''; } else { // hostnames are always lower case. this.hostname = this.hostname.toLowerCase(); } if (!ipv6Hostname) { // IDNA Support: Returns a puny coded representation of "domain". // It only converts the part of the domain name that // has non ASCII characters. I.e. it dosent matter if // you call it with a domain that already is in ASCII. var domainArray = this.hostname.split('.'); var newOut = []; for (var i = 0; i < domainArray.length; ++i) { var s = domainArray[i]; newOut.push(s.match(/[^A-Za-z0-9_-]/) ? 'xn--' + punycode.encode(s) : s); } this.hostname = newOut.join('.'); } var p = this.port ? ':' + this.port : ''; var h = this.hostname || ''; this.host = h + p; this.href += this.host; // strip [ and ] from the hostname // the host field still retains them, though if (ipv6Hostname) { this.hostname = this.hostname.substr(1, this.hostname.length - 2); if (rest[0] !== '/') { rest = '/' + rest; } } } // now rest is set to the post-host stuff. // chop off any delim chars. if (!unsafeProtocol[lowerProto]) { // First, make 100% sure that any "autoEscape" chars get // escaped, even if encodeURIComponent doesn't think they // need to be. for (var i = 0, l = autoEscape.length; i < l; i++) { var ae = autoEscape[i]; var esc = encodeURIComponent(ae); if (esc === ae) { esc = escape(ae); } rest = rest.split(ae).join(esc); } } // chop off from the tail first. var hash = rest.indexOf('#'); if (hash !== -1) { // got a fragment string. this.hash = rest.substr(hash); rest = rest.slice(0, hash); } var qm = rest.indexOf('?'); if (qm !== -1) { this.search = rest.substr(qm); this.query = rest.substr(qm + 1); if (parseQueryString) { this.query = querystring.parse(this.query); } rest = rest.slice(0, qm); } else if (parseQueryString) { // no query string, but parseQueryString still requested this.search = ''; this.query = {}; } if (rest) this.pathname = rest; if (slashedProtocol[proto] && this.hostname && !this.pathname) { this.pathname = '/'; } //to support http.request if (this.pathname || this.search) { var p = this.pathname || ''; var s = this.search || ''; this.path = p + s; } // finally, reconstruct the href based on what has been validated. this.href = this.format(); return this; }; // format a parsed object into a url string function urlFormat(obj) { // ensure it's an object, and not a string url. // If it's an obj, this is a no-op. // this way, you can call url_format() on strings // to clean up potentially wonky urls. if (typeof(obj) === 'string') obj = urlParse(obj); if (!(obj instanceof Url)) return Url.prototype.format.call(obj); return obj.format(); } Url.prototype.format = function() { var auth = this.auth || ''; if (auth) { auth = encodeURIComponent(auth); auth = auth.replace(/%3A/i, ':'); auth += '@'; } var protocol = this.protocol || '', pathname = this.pathname || '', hash = this.hash || '', host = false, query = ''; if (this.host) { host = auth + this.host; } else if (this.hostname) { host = auth + (this.hostname.indexOf(':') === -1 ? this.hostname : '[' + this.hostname + ']'); if (this.port) { host += ':' + this.port; } } if (this.query && typeof this.query === 'object' && Object.keys(this.query).length) { query = querystring.stringify(this.query); } var search = this.search || (query && ('?' + query)) || ''; if (protocol && protocol.substr(-1) !== ':') protocol += ':'; // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. // unless they had them to begin with. if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== false) { host = '//' + (host || ''); if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; } else if (!host) { host = ''; } if (hash && hash.charAt(0) !== '#') hash = '#' + hash; if (search && search.charAt(0) !== '?') search = '?' + search; pathname = pathname.replace(/[?#]/g, function(match) { return encodeURIComponent(match); }); search = search.replace('#', '%23'); return protocol + host + pathname + search + hash; }; function urlResolve(source, relative) { return urlParse(source, false, true).resolve(relative); } Url.prototype.resolve = function(relative) { return this.resolveObject(urlParse(relative, false, true)).format(); }; function urlResolveObject(source, relative) { if (!source) return relative; return urlParse(source, false, true).resolveObject(relative); } Url.prototype.resolveObject = function(relative) { if (typeof relative === 'string') { var rel = new Url(); rel.parse(relative, false, true); relative = rel; } var result = new Url(); Object.keys(this).forEach(function(k) { result[k] = this[k]; }, this); // hash is always overridden, no matter what. // even href="" will remove it. result.hash = relative.hash; // if the relative url is empty, then there's nothing left to do here. if (relative.href === '') { result.href = result.format(); return result; } // hrefs like //foo/bar always cut to the protocol. if (relative.slashes && !relative.protocol) { // take everything except the protocol from relative Object.keys(relative).forEach(function(k) { if (k !== 'protocol') result[k] = relative[k]; }); //urlParse appends trailing / to urls like http://www.example.com if (slashedProtocol[result.protocol] && result.hostname && !result.pathname) { result.path = result.pathname = '/'; } result.href = result.format(); return result; } if (relative.protocol && relative.protocol !== result.protocol) { // if it's a known url protocol, then changing // the protocol does weird things // first, if it's not file:, then we MUST have a host, // and if there was a path // to begin with, then we MUST have a path. // if it is file:, then the host is dropped, // because that's known to be hostless. // anything else is assumed to be absolute. if (!slashedProtocol[relative.protocol]) { Object.keys(relative).forEach(function(k) { result[k] = relative[k]; }); result.href = result.format(); return result; } result.protocol = relative.protocol; if (!relative.host && !hostlessProtocol[relative.protocol]) { var relPath = (relative.pathname || '').split('/'); while (relPath.length && !(relative.host = relPath.shift())); if (!relative.host) relative.host = ''; if (!relative.hostname) relative.hostname = ''; if (relPath[0] !== '') relPath.unshift(''); if (relPath.length < 2) relPath.unshift(''); result.pathname = relPath.join('/'); } else { result.pathname = relative.pathname; } result.search = relative.search; result.query = relative.query; result.host = relative.host || ''; result.auth = relative.auth; result.hostname = relative.hostname || relative.host; result.port = relative.port; // to support http.request if (result.pathname || result.search) { var p = result.pathname || ''; var s = result.search || ''; result.path = p + s; } result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; } var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), isRelAbs = ( relative.host || relative.pathname && relative.pathname.charAt(0) === '/' ), mustEndAbs = (isRelAbs || isSourceAbs || (result.host && relative.pathname)), removeAllDots = mustEndAbs, srcPath = result.pathname && result.pathname.split('/') || [], relPath = relative.pathname && relative.pathname.split('/') || [], psychotic = result.protocol && !slashedProtocol[result.protocol]; // if the url is a non-slashed url, then relative // links like ../.. should be able // to crawl up to the hostname, as well. This is strange. // result.protocol has already been set by now. // Later on, put the first path part into the host field. if (psychotic) { result.hostname = ''; result.port = null; if (result.host) { if (srcPath[0] === '') srcPath[0] = result.host; else srcPath.unshift(result.host); } result.host = ''; if (relative.protocol) { relative.hostname = null; relative.port = null; if (relative.host) { if (relPath[0] === '') relPath[0] = relative.host; else relPath.unshift(relative.host); } relative.host = null; } mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); } if (isRelAbs) { // it's absolute. result.host = (relative.host || relative.host === '') ? relative.host : result.host; result.hostname = (relative.hostname || relative.hostname === '') ? relative.hostname : result.hostname; result.search = relative.search; result.query = relative.query; srcPath = relPath; // fall through to the dot-handling below. } else if (relPath.length) { // it's relative // throw away the existing file, and take the new path instead. if (!srcPath) srcPath = []; srcPath.pop(); srcPath = srcPath.concat(relPath); result.search = relative.search; result.query = relative.query; } else if (relative.search !== null && relative.search !== undefined) { // just pull out the search. // like href='?foo'. // Put this after the other two cases because it simplifies the booleans if (psychotic) { result.hostname = result.host = srcPath.shift(); //occationaly the auth can get stuck only in host //this especialy happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } result.search = relative.search; result.query = relative.query; //to support http.request if (result.pathname !== null || result.search !== null) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.href = result.format(); return result; } if (!srcPath.length) { // no path at all. easy. // we've already handled the other stuff above. result.pathname = null; //to support http.request if (result.search) { result.path = '/' + result.search; } else { result.path = null; } result.href = result.format(); return result; } // if a url ENDs in . or .., then it must get a trailing slash. // however, if it ends in anything else non-slashy, // then it must NOT get a trailing slash. var last = srcPath.slice(-1)[0]; var hasTrailingSlash = ( (result.host || relative.host) && (last === '.' || last === '..') || last === ''); // strip single dots, resolve double dots to parent dir // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = srcPath.length; i >= 0; i--) { last = srcPath[i]; if (last == '.') { srcPath.splice(i, 1); } else if (last === '..') { srcPath.splice(i, 1); up++; } else if (up) { srcPath.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (!mustEndAbs && !removeAllDots) { for (; up--; up) { srcPath.unshift('..'); } } if (mustEndAbs && srcPath[0] !== '' && (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { srcPath.unshift(''); } if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { srcPath.push(''); } var isAbsolute = srcPath[0] === '' || (srcPath[0] && srcPath[0].charAt(0) === '/'); // put the host back if (psychotic) { result.hostname = result.host = isAbsolute ? '' : srcPath.length ? srcPath.shift() : ''; //occationaly the auth can get stuck only in host //this especialy happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } mustEndAbs = mustEndAbs || (result.host && srcPath.length); if (mustEndAbs && !isAbsolute) { srcPath.unshift(''); } if (!srcPath.length) { result.pathname = null; result.path = null; } else { result.pathname = srcPath.join('/'); } //to support request.http if (result.pathname !== null || result.search !== null) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.auth = relative.auth || result.auth; result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; }; Url.prototype.parseHost = function() { var host = this.host; var port = portPattern.exec(host); if (port) { port = port[0]; if (port !== ':') { this.port = port.substr(1); } host = host.substr(0, host.length - port.length); } if (host) this.hostname = host; }; url// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var inherits = require('util').inherits; var net = require('net'); var TTY = process.binding('tty_wrap').TTY; var isTTY = process.binding('tty_wrap').isTTY; var util = require('util'); exports.isatty = function(fd) { return isTTY(fd); }; // backwards-compat exports.setRawMode = util.deprecate(function(flag) { if (!process.stdin.isTTY) { throw new Error('can\'t set raw mode on non-tty'); } process.stdin.setRawMode(flag); }, 'tty.setRawMode: Use `process.stdin.setRawMode()` instead.'); function ReadStream(fd, options) { if (!(this instanceof ReadStream)) return new ReadStream(fd, options); options = util._extend({ highWaterMark: 0, readable: true, writable: false, handle: new TTY(fd, true) }, options); net.Socket.call(this, options); this.isRaw = false; this.isTTY = true; } inherits(ReadStream, net.Socket); exports.ReadStream = ReadStream; ReadStream.prototype.setRawMode = function(flag) { flag = !!flag; this._handle.setRawMode(flag); this.isRaw = flag; }; function WriteStream(fd) { if (!(this instanceof WriteStream)) return new WriteStream(fd); net.Socket.call(this, { handle: new TTY(fd, false), readable: false, writable: true }); var winSize = this._handle.getWindowSize(); if (winSize) { this.columns = winSize[0]; this.rows = winSize[1]; } } inherits(WriteStream, net.Socket); exports.WriteStream = WriteStream; WriteStream.prototype.isTTY = true; WriteStream.prototype._refreshSize = function() { var oldCols = this.columns; var oldRows = this.rows; var winSize = this._handle.getWindowSize(); if (!winSize) { this.emit('error', errnoException(process._errno, 'getWindowSize')); return; } var newCols = winSize[0]; var newRows = winSize[1]; if (oldCols !== newCols || oldRows !== newRows) { this.columns = newCols; this.rows = newRows; this.emit('resize'); } }; // backwards-compat WriteStream.prototype.cursorTo = function(x, y) { require('readline').cursorTo(this, x, y); }; WriteStream.prototype.moveCursor = function(dx, dy) { require('readline').moveCursor(this, dx, dy); }; WriteStream.prototype.clearLine = function(dir) { require('readline').clearLine(this, dir); }; WriteStream.prototype.clearScreenDown = function() { require('readline').clearScreenDown(this); }; WriteStream.prototype.getWindowSize = function() { return [this.columns, this.rows]; }; // TODO share with net_uv and others function errnoException(errorno, syscall) { var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } tty// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var crypto = require('crypto'); var util = require('util'); var net = require('net'); var url = require('url'); var events = require('events'); var stream = require('stream'); var assert = require('assert').ok; var constants = require('constants'); var DEFAULT_CIPHERS = 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' + // TLS 1.2 'RC4:HIGH:!MD5:!aNULL:!EDH'; // TLS 1.0 // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more // renegotations are seen. The settings are applied to all remote client // connections. exports.CLIENT_RENEG_LIMIT = 3; exports.CLIENT_RENEG_WINDOW = 600; exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024; exports.getCiphers = function() { var names = process.binding('crypto').getSSLCiphers(); // Drop all-caps names in favor of their lowercase aliases, var ctx = {}; names.forEach(function(name) { if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); ctx[name] = true; }); return Object.getOwnPropertyNames(ctx).sort(); }; var debug; if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) { debug = function(a) { console.error('TLS:', a); }; } else { debug = function() { }; } var Connection = null; try { Connection = process.binding('crypto').Connection; } catch (e) { throw new Error('node.js not compiled with openssl crypto support.'); } // Convert protocols array into valid OpenSSL protocols list // ("\x06spdy/2\x08http/1.1\x08http/1.0") function convertNPNProtocols(NPNProtocols, out) { // If NPNProtocols is Array - translate it into buffer if (Array.isArray(NPNProtocols)) { var buff = new Buffer(NPNProtocols.reduce(function(p, c) { return p + 1 + Buffer.byteLength(c); }, 0)); NPNProtocols.reduce(function(offset, c) { var clen = Buffer.byteLength(c); buff[offset] = clen; buff.write(c, offset + 1); return offset + 1 + clen; }, 0); NPNProtocols = buff; } // If it's already a Buffer - store it if (Buffer.isBuffer(NPNProtocols)) { out.NPNProtocols = NPNProtocols; } } function checkServerIdentity(host, cert) { // Create regexp to much hostnames function regexpify(host, wildcards) { // Add trailing dot (make hostnames uniform) if (!/\.$/.test(host)) host += '.'; // The same applies to hostname with more than one wildcard, // if hostname has wildcard when wildcards are not allowed, // or if there are less than two dots after wildcard (i.e. *.com or *d.com) // // also // // "The client SHOULD NOT attempt to match a presented identifier in // which the wildcard character comprises a label other than the // left-most label (e.g., do not match bar.*.example.net)." // RFC6125 if (!wildcards && /\*/.test(host) || /[\.\*].*\*/.test(host) || /\*/.test(host) && !/\*.*\..+\..+/.test(host)) { return /$./; } // Replace wildcard chars with regexp's wildcard and // escape all characters that have special meaning in regexps // (i.e. '.', '[', '{', '*', and others) var re = host.replace( /\*([a-z0-9\\-_\.])|[\.,\-\\\^\$+?*\[\]\(\):!\|{}]/g, function(all, sub) { if (sub) return '[a-z0-9\\-_]*' + (sub === '-' ? '\\-' : sub); return '\\' + all; }); return new RegExp('^' + re + '$', 'i'); } var dnsNames = [], uriNames = [], ips = [], matchCN = true, valid = false; // There're several names to perform check against: // CN and altnames in certificate extension // (DNS names, IP addresses, and URIs) // // Walk through altnames and generate lists of those names if (cert.subjectaltname) { cert.subjectaltname.split(/, /g).forEach(function(altname) { if (/^DNS:/.test(altname)) { dnsNames.push(altname.slice(4)); } else if (/^IP Address:/.test(altname)) { ips.push(altname.slice(11)); } else if (/^URI:/.test(altname)) { var uri = url.parse(altname.slice(4)); if (uri) uriNames.push(uri.hostname); } }); } // If hostname is an IP address, it should be present in the list of IP // addresses. if (net.isIP(host)) { valid = ips.some(function(ip) { return ip === host; }); } else { // Transform hostname to canonical form if (!/\.$/.test(host)) host += '.'; // Otherwise check all DNS/URI records from certificate // (with allowed wildcards) dnsNames = dnsNames.map(function(name) { return regexpify(name, true); }); // Wildcards ain't allowed in URI names uriNames = uriNames.map(function(name) { return regexpify(name, false); }); dnsNames = dnsNames.concat(uriNames); if (dnsNames.length > 0) matchCN = false; // Match against Common Name (CN) only if no supported identifiers are // present. // // "As noted, a client MUST NOT seek a match for a reference identifier // of CN-ID if the presented identifiers include a DNS-ID, SRV-ID, // URI-ID, or any application-specific identifier types supported by the // client." // RFC6125 if (matchCN) { var commonNames = cert.subject.CN; if (Array.isArray(commonNames)) { for (var i = 0, k = commonNames.length; i < k; ++i) { dnsNames.push(regexpify(commonNames[i], true)); } } else { dnsNames.push(regexpify(commonNames, true)); } } valid = dnsNames.some(function(re) { return re.test(host); }); } return valid; } exports.checkServerIdentity = checkServerIdentity; function SlabBuffer() { this.create(); } SlabBuffer.prototype.create = function create() { this.isFull = false; this.pool = new Buffer(exports.SLAB_BUFFER_SIZE); this.offset = 0; this.remaining = this.pool.length; }; SlabBuffer.prototype.use = function use(context, fn, size) { if (this.remaining === 0) { this.isFull = true; return 0; } var actualSize = this.remaining; if (size !== null) actualSize = Math.min(size, actualSize); var bytes = fn.call(context, this.pool, this.offset, actualSize); if (bytes > 0) { this.offset += bytes; this.remaining -= bytes; } assert(this.remaining >= 0); return bytes; }; var slabBuffer = null; // Base class of both CleartextStream and EncryptedStream function CryptoStream(pair, options) { stream.Duplex.call(this, options); this.pair = pair; this._pending = null; this._pendingEncoding = ''; this._pendingCallback = null; this._doneFlag = false; this._retryAfterPartial = false; this._halfRead = false; this._sslOutCb = null; this._resumingSession = false; this._reading = true; this._destroyed = false; this._ended = false; this._finished = false; this._opposite = null; if (slabBuffer === null) slabBuffer = new SlabBuffer(); this._buffer = slabBuffer; this.once('finish', onCryptoStreamFinish); // net.Socket calls .onend too this.once('end', onCryptoStreamEnd); } util.inherits(CryptoStream, stream.Duplex); function onCryptoStreamFinish() { this._finished = true; if (this === this.pair.cleartext) { debug('cleartext.onfinish'); if (this.pair.ssl) { // Generate close notify // NOTE: first call checks if client has sent us shutdown, // second call enqueues shutdown into the BIO. if (this.pair.ssl.shutdown() !== 1) { if (this.pair.ssl && this.pair.ssl.error) return this.pair.error(); this.pair.ssl.shutdown(); } if (this.pair.ssl && this.pair.ssl.error) return this.pair.error(); } } else { debug('encrypted.onfinish'); } // Try to read just to get sure that we won't miss EOF if (this._opposite.readable) this._opposite.read(0); if (this._opposite._ended) { this._done(); // No half-close, sorry if (this === this.pair.cleartext) this._opposite._done(); } } function onCryptoStreamEnd() { this._ended = true; if (this === this.pair.cleartext) { debug('cleartext.onend'); } else { debug('encrypted.onend'); } if (this.onend) this.onend(); } // NOTE: Called once `this._opposite` is set. CryptoStream.prototype.init = function init() { var self = this; this._opposite.on('sslOutEnd', function() { if (self._sslOutCb) { var cb = self._sslOutCb; self._sslOutCb = null; cb(null); } }); }; CryptoStream.prototype._write = function write(data, encoding, cb) { assert(this._pending === null); // Black-hole data if (!this.pair.ssl) return cb(null); // When resuming session don't accept any new data. // And do not put too much data into openssl, before writing it from encrypted // side. // // TODO(indutny): Remove magic number, use watermark based limits if (!this._resumingSession && this._opposite._internallyPendingBytes() < 128 * 1024) { // Write current buffer now var written; if (this === this.pair.cleartext) { debug('cleartext.write called with ' + data.length + ' bytes'); written = this.pair.ssl.clearIn(data, 0, data.length); } else { debug('encrypted.write called with ' + data.length + ' bytes'); written = this.pair.ssl.encIn(data, 0, data.length); } // Handle and report errors if (this.pair.ssl && this.pair.ssl.error) { return cb(this.pair.error(true)); } // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); // Cycle encrypted data if (this.pair.encrypted._internallyPendingBytes()) this.pair.encrypted.read(0); // Get NPN and Server name when ready this.pair.maybeInitFinished(); // Whole buffer was written if (written === data.length) { if (this === this.pair.cleartext) { debug('cleartext.write succeed with ' + written + ' bytes'); } else { debug('encrypted.write succeed with ' + written + ' bytes'); } // Invoke callback only when all data read from opposite stream if (this._opposite._halfRead) { assert(this._sslOutCb === null); this._sslOutCb = cb; } else { cb(null); } return; } else if (written !== 0 && written !== -1) { assert(!this._retryAfterPartial); this._retryAfterPartial = true; this._write(data.slice(written), encoding, cb); this._retryAfterPartial = false; return; } } else { debug('cleartext.write queue is full'); // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); } // No write has happened this._pending = data; this._pendingEncoding = encoding; this._pendingCallback = cb; if (this === this.pair.cleartext) { debug('cleartext.write queued with ' + data.length + ' bytes'); } else { debug('encrypted.write queued with ' + data.length + ' bytes'); } }; CryptoStream.prototype._writePending = function writePending() { var data = this._pending, encoding = this._pendingEncoding, cb = this._pendingCallback; this._pending = null; this._pendingEncoding = ''; this._pendingCallback = null; this._write(data, encoding, cb); }; CryptoStream.prototype._read = function read(size) { // XXX: EOF?! if (!this.pair.ssl) return this.push(null); // Wait for session to be resumed // Mark that we're done reading, but don't provide data or EOF if (this._resumingSession || !this._reading) return this.push(''); var out; if (this === this.pair.cleartext) { debug('cleartext.read called with ' + size + ' bytes'); out = this.pair.ssl.clearOut; } else { debug('encrypted.read called with ' + size + ' bytes'); out = this.pair.ssl.encOut; } var bytesRead = 0, start = this._buffer.offset; do { var read = this._buffer.use(this.pair.ssl, out, size); if (read > 0) { bytesRead += read; size -= read; } // Handle and report errors if (this.pair.ssl && this.pair.ssl.error) { this.pair.error(); break; } // Get NPN and Server name when ready this.pair.maybeInitFinished(); } while (read > 0 && !this._buffer.isFull && bytesRead < size); // Create new buffer if previous was filled up var pool = this._buffer.pool; if (this._buffer.isFull) this._buffer.create(); assert(bytesRead >= 0); if (this === this.pair.cleartext) { debug('cleartext.read succeed with ' + bytesRead + ' bytes'); } else { debug('encrypted.read succeed with ' + bytesRead + ' bytes'); } // Try writing pending data if (this._pending !== null) this._writePending(); if (this._opposite._pending !== null) this._opposite._writePending(); if (bytesRead === 0) { // EOF when cleartext has finished and we have nothing to read if (this._opposite._finished && this._internallyPendingBytes() === 0) { // Perform graceful shutdown this._done(); // No half-open, sorry! if (this === this.pair.cleartext) this._opposite._done(); // EOF this.push(null); } else { // Bail out this.push(''); } } else { // Give them requested data if (this.ondata) { var self = this; this.ondata(pool, start, start + bytesRead); // Consume data automatically // simple/test-https-drain fails without it process.nextTick(function() { self.read(bytesRead); }); } this.push(pool.slice(start, start + bytesRead)); } // Let users know that we've some internal data to read var halfRead = this._internallyPendingBytes() !== 0; // Smart check to avoid invoking 'sslOutEnd' in the most of the cases if (this._halfRead !== halfRead) { this._halfRead = halfRead; // Notify listeners about internal data end if (!halfRead) { if (this === this.pair.cleartext) { debug('cleartext.sslOutEnd'); } else { debug('encrypted.sslOutEnd'); } this.emit('sslOutEnd'); } } }; CryptoStream.prototype.setTimeout = function(timeout, callback) { if (this.socket) this.socket.setTimeout(timeout, callback); }; CryptoStream.prototype.setNoDelay = function(noDelay) { if (this.socket) this.socket.setNoDelay(noDelay); }; CryptoStream.prototype.setKeepAlive = function(enable, initialDelay) { if (this.socket) this.socket.setKeepAlive(enable, initialDelay); }; CryptoStream.prototype.__defineGetter__('bytesWritten', function() { return this.socket ? this.socket.bytesWritten : 0; }); // Example: // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org function parseCertString(s) { var out = {}; var parts = s.split('\n'); for (var i = 0, len = parts.length; i < len; i++) { var sepIndex = parts[i].indexOf('='); if (sepIndex > 0) { var key = parts[i].slice(0, sepIndex); var value = parts[i].slice(sepIndex + 1); if (key in out) { if (!Array.isArray(out[key])) { out[key] = [out[key]]; } out[key].push(value); } else { out[key] = value; } } } return out; } CryptoStream.prototype.getPeerCertificate = function() { if (this.pair.ssl) { var c = this.pair.ssl.getPeerCertificate(); if (c) { if (c.issuer) c.issuer = parseCertString(c.issuer); if (c.subject) c.subject = parseCertString(c.subject); return c; } } return null; }; CryptoStream.prototype.getSession = function() { if (this.pair.ssl) { return this.pair.ssl.getSession(); } return null; }; CryptoStream.prototype.isSessionReused = function() { if (this.pair.ssl) { return this.pair.ssl.isSessionReused(); } return null; }; CryptoStream.prototype.getCipher = function(err) { if (this.pair.ssl) { return this.pair.ssl.getCurrentCipher(); } else { return null; } }; CryptoStream.prototype.end = function(chunk, encoding) { if (this === this.pair.cleartext) { debug('cleartext.end'); } else { debug('encrypted.end'); } // Write pending data first if (this._pending !== null) this._writePending(); this.writable = false; stream.Duplex.prototype.end.call(this, chunk, encoding); }; CryptoStream.prototype.destroySoon = function(err) { if (this === this.pair.cleartext) { debug('cleartext.destroySoon'); } else { debug('encrypted.destroySoon'); } if (this.writable) this.end(); if (this._writableState.finished && this._opposite._ended) { this.destroy(); } else { // Wait for both `finish` and `end` events to ensure that all data that // was written on this side was read from the other side. var self = this; var waiting = 2; function finish() { if (--waiting === 0) self.destroy(); } this._opposite.once('end', finish); this.once('finish', finish); } }; CryptoStream.prototype.destroy = function(err) { if (this._destroyed) return; this._destroyed = true; this.readable = this.writable = false; // Destroy both ends if (this === this.pair.cleartext) { debug('cleartext.destroy'); } else { debug('encrypted.destroy'); } this._opposite.destroy(); var self = this; process.nextTick(function() { // Force EOF self.push(null); // Emit 'close' event self.emit('close', err ? true : false); }); }; CryptoStream.prototype._done = function() { this._doneFlag = true; if (this === this.pair.encrypted && !this.pair._secureEstablished) return this.pair.error(); if (this.pair.cleartext._doneFlag && this.pair.encrypted._doneFlag && !this.pair._doneFlag) { // If both streams are done: this.pair.destroy(); } }; // readyState is deprecated. Don't use it. Object.defineProperty(CryptoStream.prototype, 'readyState', { get: function() { if (this._connecting) { return 'opening'; } else if (this.readable && this.writable) { return 'open'; } else if (this.readable && !this.writable) { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; } else { return 'closed'; } } }); function CleartextStream(pair, options) { CryptoStream.call(this, pair, options); // This is a fake kludge to support how the http impl sits // on top of net Sockets var self = this; this._handle = { readStop: function() { self._reading = false; }, readStart: function() { if (self._reading && self._readableState.length > 0) return; self._reading = true; self.read(0); if (self._opposite.readable) self._opposite.read(0); } }; } util.inherits(CleartextStream, CryptoStream); CleartextStream.prototype._internallyPendingBytes = function() { if (this.pair.ssl) { return this.pair.ssl.clearPending(); } else { return 0; } }; CleartextStream.prototype.address = function() { return this.socket && this.socket.address(); }; CleartextStream.prototype.__defineGetter__('remoteAddress', function() { return this.socket && this.socket.remoteAddress; }); CleartextStream.prototype.__defineGetter__('remotePort', function() { return this.socket && this.socket.remotePort; }); function EncryptedStream(pair, options) { CryptoStream.call(this, pair, options); } util.inherits(EncryptedStream, CryptoStream); EncryptedStream.prototype._internallyPendingBytes = function() { if (this.pair.ssl) { return this.pair.ssl.encPending(); } else { return 0; } }; function onhandshakestart() { debug('onhandshakestart'); var self = this; var ssl = self.ssl; var now = Date.now(); assert(now >= ssl.lastHandshakeTime); if ((now - ssl.lastHandshakeTime) >= exports.CLIENT_RENEG_WINDOW * 1000) { ssl.handshakes = 0; } var first = (ssl.lastHandshakeTime === 0); ssl.lastHandshakeTime = now; if (first) return; if (++ssl.handshakes > exports.CLIENT_RENEG_LIMIT) { // Defer the error event to the next tick. We're being called from OpenSSL's // state machine and OpenSSL is not re-entrant. We cannot allow the user's // callback to destroy the connection right now, it would crash and burn. setImmediate(function() { var err = new Error('TLS session renegotiation attack detected.'); if (self.cleartext) self.cleartext.emit('error', err); }); } } function onhandshakedone() { // for future use debug('onhandshakedone'); } function onclienthello(hello) { var self = this, once = false; this._resumingSession = true; function callback(err, session) { if (once) return; once = true; if (err) return self.socket.destroy(err); self.ssl.loadSession(session); // Cycle data self._resumingSession = false; self.cleartext.read(0); self.encrypted.read(0); } if (hello.sessionId.length <= 0 || !this.server || !this.server.emit('resumeSession', hello.sessionId, callback)) { callback(null, null); } } function onnewsession(key, session) { if (!this.server) return; this.server.emit('newSession', key, session); } /** * Provides a pair of streams to do encrypted communication. */ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized, options) { if (!(this instanceof SecurePair)) { return new SecurePair(credentials, isServer, requestCert, rejectUnauthorized, options); } var self = this; options || (options = {}); events.EventEmitter.call(this); this.server = options.server; this._secureEstablished = false; this._isServer = isServer ? true : false; this._encWriteState = true; this._clearWriteState = true; this._doneFlag = false; this._destroying = false; if (!credentials) { this.credentials = crypto.createCredentials(); } else { this.credentials = credentials; } if (!this._isServer) { // For clients, we will always have either a given ca list or be using // default one requestCert = true; } this._rejectUnauthorized = rejectUnauthorized ? true : false; this._requestCert = requestCert ? true : false; this.ssl = new Connection(this.credentials.context, this._isServer ? true : false, this._isServer ? this._requestCert : options.servername, this._rejectUnauthorized); if (this._isServer) { this.ssl.onhandshakestart = onhandshakestart.bind(this); this.ssl.onhandshakedone = onhandshakedone.bind(this); this.ssl.onclienthello = onclienthello.bind(this); this.ssl.onnewsession = onnewsession.bind(this); this.ssl.lastHandshakeTime = 0; this.ssl.handshakes = 0; } if (process.features.tls_sni) { if (this._isServer && options.SNICallback) { this.ssl.setSNICallback(options.SNICallback); } this.servername = null; } if (process.features.tls_npn && options.NPNProtocols) { this.ssl.setNPNProtocols(options.NPNProtocols); this.npnProtocol = null; } /* Acts as a r/w stream to the cleartext side of the stream. */ this.cleartext = new CleartextStream(this, options.cleartext); /* Acts as a r/w stream to the encrypted side of the stream. */ this.encrypted = new EncryptedStream(this, options.encrypted); /* Let streams know about each other */ this.cleartext._opposite = this.encrypted; this.encrypted._opposite = this.cleartext; this.cleartext.init(); this.encrypted.init(); process.nextTick(function() { /* The Connection may be destroyed by an abort call */ if (self.ssl) { self.ssl.start(); } }); } util.inherits(SecurePair, events.EventEmitter); exports.createSecurePair = function(credentials, isServer, requestCert, rejectUnauthorized) { var pair = new SecurePair(credentials, isServer, requestCert, rejectUnauthorized); return pair; }; SecurePair.prototype.maybeInitFinished = function() { if (this.ssl && !this._secureEstablished && this.ssl.isInitFinished()) { if (process.features.tls_npn) { this.npnProtocol = this.ssl.getNegotiatedProtocol(); } if (process.features.tls_sni) { this.servername = this.ssl.getServername(); } this._secureEstablished = true; debug('secure established'); this.emit('secure'); } }; SecurePair.prototype.destroy = function() { if (this._destroying) return; if (!this._doneFlag) { debug('SecurePair.destroy'); this._destroying = true; // SecurePair should be destroyed only after it's streams this.cleartext.destroy(); this.encrypted.destroy(); this._doneFlag = true; this.ssl.error = null; this.ssl.close(); this.ssl = null; } }; SecurePair.prototype.error = function(returnOnly) { var err = this.ssl.error; this.ssl.error = null; if (!this._secureEstablished) { // Emit ECONNRESET instead of zero return if (!err || err.message === 'ZERO_RETURN') { var connReset = new Error('socket hang up'); connReset.code = 'ECONNRESET'; connReset.sslError = err && err.message; err = connReset; } this.destroy(); if (!returnOnly) this.emit('error', err); } else if (this._isServer && this._rejectUnauthorized && /peer did not return a certificate/.test(err.message)) { // Not really an error. this.destroy(); } else { if (!returnOnly) this.cleartext.emit('error', err); } return err; }; // TODO: support anonymous (nocert) and PSK // AUTHENTICATION MODES // // There are several levels of authentication that TLS/SSL supports. // Read more about this in "man SSL_set_verify". // // 1. The server sends a certificate to the client but does not request a // cert from the client. This is common for most HTTPS servers. The browser // can verify the identity of the server, but the server does not know who // the client is. Authenticating the client is usually done over HTTP using // login boxes and cookies and stuff. // // 2. The server sends a cert to the client and requests that the client // also send it a cert. The client knows who the server is and the server is // requesting the client also identify themselves. There are several // outcomes: // // A) verifyError returns null meaning the client's certificate is signed // by one of the server's CAs. The server know's the client idenity now // and the client is authorized. // // B) For some reason the client's certificate is not acceptable - // verifyError returns a string indicating the problem. The server can // either (i) reject the client or (ii) allow the client to connect as an // unauthorized connection. // // The mode is controlled by two boolean variables. // // requestCert // If true the server requests a certificate from client connections. For // the common HTTPS case, users will want this to be false, which is what // it defaults to. // // rejectUnauthorized // If true clients whose certificates are invalid for any reason will not // be allowed to make connections. If false, they will simply be marked as // unauthorized but secure communication will continue. By default this is // true. // // // // Options: // - requestCert. Send verify request. Default to false. // - rejectUnauthorized. Boolean, default to true. // - key. string. // - cert: string. // - ca: string or array of strings. // // emit 'secureConnection' // function (cleartextStream, encryptedStream) { } // // 'cleartextStream' has the boolean property 'authorized' to determine if // it was verified by the CA. If 'authorized' is false, a property // 'authorizationError' is set on cleartextStream and has the possible // values: // // "UNABLE_TO_GET_ISSUER_CERT", "UNABLE_TO_GET_CRL", // "UNABLE_TO_DECRYPT_CERT_SIGNATURE", "UNABLE_TO_DECRYPT_CRL_SIGNATURE", // "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", "CERT_SIGNATURE_FAILURE", // "CRL_SIGNATURE_FAILURE", "CERT_NOT_YET_VALID" "CERT_HAS_EXPIRED", // "CRL_NOT_YET_VALID", "CRL_HAS_EXPIRED" "ERROR_IN_CERT_NOT_BEFORE_FIELD", // "ERROR_IN_CERT_NOT_AFTER_FIELD", "ERROR_IN_CRL_LAST_UPDATE_FIELD", // "ERROR_IN_CRL_NEXT_UPDATE_FIELD", "OUT_OF_MEM", // "DEPTH_ZERO_SELF_SIGNED_CERT", "SELF_SIGNED_CERT_IN_CHAIN", // "UNABLE_TO_GET_ISSUER_CERT_LOCALLY", "UNABLE_TO_VERIFY_LEAF_SIGNATURE", // "CERT_CHAIN_TOO_LONG", "CERT_REVOKED" "INVALID_CA", // "PATH_LENGTH_EXCEEDED", "INVALID_PURPOSE" "CERT_UNTRUSTED", // "CERT_REJECTED" // // // TODO: // cleartext.credentials (by mirroring from pair object) // cleartext.getCertificate() (by mirroring from pair.credentials.context) function Server(/* [options], listener */) { var options, listener; if (typeof arguments[0] == 'object') { options = arguments[0]; listener = arguments[1]; } else if (typeof arguments[0] == 'function') { options = {}; listener = arguments[0]; } if (!(this instanceof Server)) return new Server(options, listener); this._contexts = []; var self = this; // Handle option defaults: this.setOptions(options); if (!self.pfx && (!self.cert || !self.key)) { throw new Error('Missing PFX or certificate + private key.'); } var sharedCreds = crypto.createCredentials({ pfx: self.pfx, key: self.key, passphrase: self.passphrase, cert: self.cert, ca: self.ca, ciphers: self.ciphers || DEFAULT_CIPHERS, secureProtocol: self.secureProtocol, secureOptions: self.secureOptions, crl: self.crl, sessionIdContext: self.sessionIdContext }); var timeout = options.handshakeTimeout || (120 * 1000); if (typeof timeout !== 'number') { throw new TypeError('handshakeTimeout must be a number'); } // constructor call net.Server.call(this, function(socket) { var creds = crypto.createCredentials(null, sharedCreds.context); var pair = new SecurePair(creds, true, self.requestCert, self.rejectUnauthorized, { server: self, NPNProtocols: self.NPNProtocols, SNICallback: self.SNICallback, // Stream options cleartext: self._cleartext, encrypted: self._encrypted }); var cleartext = pipe(pair, socket); cleartext._controlReleased = false; function listener() { pair.emit('error', new Error('TLS handshake timeout')); } if (timeout > 0) { socket.setTimeout(timeout, listener); } pair.once('secure', function() { socket.setTimeout(0, listener); pair.cleartext.authorized = false; pair.cleartext.npnProtocol = pair.npnProtocol; pair.cleartext.servername = pair.servername; if (!self.requestCert) { cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } else { var verifyError = pair.ssl.verifyError(); if (verifyError) { pair.cleartext.authorizationError = verifyError.message; if (self.rejectUnauthorized) { socket.destroy(); pair.destroy(); } else { cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } } else { pair.cleartext.authorized = true; cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } } }); pair.on('error', function(err) { self.emit('clientError', err, this); }); }); if (listener) { this.on('secureConnection', listener); } } util.inherits(Server, net.Server); exports.Server = Server; exports.createServer = function(options, listener) { return new Server(options, listener); }; Server.prototype.setOptions = function(options) { if (typeof options.requestCert == 'boolean') { this.requestCert = options.requestCert; } else { this.requestCert = false; } if (typeof options.rejectUnauthorized == 'boolean') { this.rejectUnauthorized = options.rejectUnauthorized; } else { this.rejectUnauthorized = false; } if (options.pfx) this.pfx = options.pfx; if (options.key) this.key = options.key; if (options.passphrase) this.passphrase = options.passphrase; if (options.cert) this.cert = options.cert; if (options.ca) this.ca = options.ca; if (options.secureProtocol) this.secureProtocol = options.secureProtocol; if (options.crl) this.crl = options.crl; if (options.ciphers) this.ciphers = options.ciphers; var secureOptions = options.secureOptions || 0; if (options.honorCipherOrder) { secureOptions |= constants.SSL_OP_CIPHER_SERVER_PREFERENCE; } if (secureOptions) this.secureOptions = secureOptions; if (options.NPNProtocols) convertNPNProtocols(options.NPNProtocols, this); if (options.SNICallback) { this.SNICallback = options.SNICallback; } else { this.SNICallback = this.SNICallback.bind(this); } if (options.sessionIdContext) { this.sessionIdContext = options.sessionIdContext; } else if (this.requestCert) { this.sessionIdContext = crypto.createHash('md5') .update(process.argv.join(' ')) .digest('hex'); } if (options.cleartext) this.cleartext = options.cleartext; if (options.encrypted) this.encrypted = options.encrypted; }; // SNI Contexts High-Level API Server.prototype.addContext = function(servername, credentials) { if (!servername) { throw 'Servername is required parameter for Server.addContext'; } var re = new RegExp('^' + servername.replace(/([\.^$+?\-\\[\]{}])/g, '\\$1') .replace(/\*/g, '.*') + '$'); this._contexts.push([re, crypto.createCredentials(credentials).context]); }; Server.prototype.SNICallback = function(servername) { var ctx; this._contexts.some(function(elem) { if (servername.match(elem[0]) !== null) { ctx = elem[1]; return true; } }); return ctx; }; // Target API: // // var s = tls.connect({port: 8000, host: "google.com"}, function() { // if (!s.authorized) { // s.destroy(); // return; // } // // // s.socket; // // s.end("hello world\n"); // }); // // function normalizeConnectArgs(listArgs) { var args = net._normalizeConnectArgs(listArgs); var options = args[0]; var cb = args[1]; if (typeof listArgs[1] === 'object') { options = util._extend(options, listArgs[1]); } else if (typeof listArgs[2] === 'object') { options = util._extend(options, listArgs[2]); } return (cb) ? [options, cb] : [options]; } exports.connect = function(/* [port, host], options, cb */) { var args = normalizeConnectArgs(arguments); var options = args[0]; var cb = args[1]; var defaults = { rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED }; options = util._extend(defaults, options || {}); var socket = options.socket ? options.socket : new net.Stream(); var sslcontext = crypto.createCredentials(options); convertNPNProtocols(options.NPNProtocols, this); var hostname = options.servername || options.host || 'localhost', pair = new SecurePair(sslcontext, false, true, options.rejectUnauthorized === true ? true : false, { NPNProtocols: this.NPNProtocols, servername: hostname, cleartext: options.cleartext, encrypted: options.encrypted }); if (options.session) { var session = options.session; if (typeof session === 'string') session = new Buffer(session, 'binary'); pair.ssl.setSession(session); } var cleartext = pipe(pair, socket); if (cb) { cleartext.once('secureConnect', cb); } if (!options.socket) { var connect_opt = (options.path && !options.port) ? {path: options.path} : { port: options.port, host: options.host, localAddress: options.localAddress }; socket.connect(connect_opt); } pair.on('secure', function() { var verifyError = pair.ssl.verifyError(); cleartext.npnProtocol = pair.npnProtocol; // Verify that server's identity matches it's certificate's names if (!verifyError) { var validCert = checkServerIdentity(hostname, pair.cleartext.getPeerCertificate()); if (!validCert) { verifyError = new Error('Hostname/IP doesn\'t match certificate\'s ' + 'altnames'); } } if (verifyError) { cleartext.authorized = false; cleartext.authorizationError = verifyError.message; if (pair._rejectUnauthorized) { cleartext.emit('error', verifyError); pair.destroy(); } else { cleartext.emit('secureConnect'); } } else { cleartext.authorized = true; cleartext.emit('secureConnect'); } }); pair.on('error', function(err) { cleartext.emit('error', err); }); cleartext._controlReleased = true; return cleartext; }; function pipe(pair, socket) { pair.encrypted.pipe(socket); socket.pipe(pair.encrypted); pair.encrypted.on('close', function() { process.nextTick(function() { // Encrypted should be unpiped from socket to prevent possible // write after destroy. pair.encrypted.unpipe(socket); socket.destroy(); }); }); pair.fd = socket.fd; var cleartext = pair.cleartext; cleartext.socket = socket; cleartext.encrypted = pair.encrypted; cleartext.authorized = false; // cycle the data whenever the socket drains, so that // we can pull some more into it. normally this would // be handled by the fact that pipe() triggers read() calls // on writable.drain, but CryptoStreams are a bit more // complicated. Since the encrypted side actually gets // its data from the cleartext side, we have to give it a // light kick to get in motion again. socket.on('drain', function() { if (pair.encrypted._pending) pair.encrypted._writePending(); if (pair.cleartext._pending) pair.cleartext._writePending(); pair.encrypted.read(0); pair.cleartext.read(0); }); function onerror(e) { if (cleartext._controlReleased) { cleartext.emit('error', e); } } function onclose() { socket.removeListener('error', onerror); socket.removeListener('timeout', ontimeout); } function ontimeout() { cleartext.emit('timeout'); } socket.on('error', onerror); socket.on('close', onclose); socket.on('timeout', ontimeout); return cleartext; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Timer = process.binding('timer_wrap').Timer; var L = require('_linklist'); var assert = require('assert').ok; // Timeout values > TIMEOUT_MAX are set to 1. var TIMEOUT_MAX = 2147483647; // 2^31-1 var debug; if (process.env.NODE_DEBUG && /timer/.test(process.env.NODE_DEBUG)) { debug = function() { require('util').error.apply(this, arguments); }; } else { debug = function() { }; } // IDLE TIMEOUTS // // Because often many sockets will have the same idle timeout we will not // use one timeout watcher per item. It is too much overhead. Instead // we'll use a single watcher for all sockets with the same timeout value // and a linked list. This technique is described in the libev manual: // http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts // Object containing all lists, timers // key = time in milliseconds // value = list var lists = {}; // the main function - creates lists on demand and the watchers associated // with them. function insert(item, msecs) { item._idleStart = Date.now(); item._idleTimeout = msecs; if (msecs < 0) return; var list; if (lists[msecs]) { list = lists[msecs]; } else { list = new Timer(); list.start(msecs, 0); L.init(list); lists[msecs] = list; list.msecs = msecs; list.ontimeout = listOnTimeout; } L.append(list, item); assert(!L.isEmpty(list)); // list is not empty } function listOnTimeout() { var msecs = this.msecs; var list = this; debug('timeout callback ' + msecs); var now = Date.now(); debug('now: ' + now); var first; while (first = L.peek(list)) { var diff = now - first._idleStart; if (diff < msecs) { list.start(msecs - diff, 0); debug(msecs + ' list wait because diff is ' + diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the // domain or uncaughtException handler ignore the exception, // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 var domain = first.domain; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; first._onTimeout(); if (domain) domain.exit(); threw = false; } finally { if (threw) { process.nextTick(function() { list.ontimeout(); }); } } } } debug(msecs + ' list empty'); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; } var unenroll = exports.unenroll = function(item) { L.remove(item); var list = lists[item._idleTimeout]; // if empty then stop the watcher debug('unenroll'); if (list && L.isEmpty(list)) { debug('unenroll: list empty'); list.close(); delete lists[item._idleTimeout]; } // if active is called later, then we want to make sure not to insert again item._idleTimeout = -1; }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { // if this item was already in a list somewhere // then we should unenroll it from that if (item._idleNext) unenroll(item); // Ensure that msecs fits into signed int32 if (msecs > 0x7fffffff) { msecs = 0x7fffffff; } item._idleTimeout = msecs; L.init(item); }; // call this whenever the item is active (not idle) // it will reset its timeout. exports.active = function(item) { var msecs = item._idleTimeout; if (msecs >= 0) { var list = lists[msecs]; if (!list || L.isEmpty(list)) { insert(item, msecs); } else { item._idleStart = Date.now(); L.append(list, item); } } }; /* * DOM-style timers */ exports.setTimeout = function(callback, after) { var timer; after *= 1; // coalesce to number or NaN if (!(after >= 1 && after <= TIMEOUT_MAX)) { after = 1; // schedule on next tick, follows browser behaviour } timer = new Timeout(after); if (arguments.length <= 2) { timer._onTimeout = callback; } else { /* * Sometimes setTimeout is called with arguments, EG * * setTimeout(callback, 2000, "hello", "world") * * If that's the case we need to call the callback with * those args. The overhead of an extra closure is not * desired in the normal case. */ var args = Array.prototype.slice.call(arguments, 2); timer._onTimeout = function() { callback.apply(timer, args); } } if (process.domain) timer.domain = process.domain; exports.active(timer); return timer; }; exports.clearTimeout = function(timer) { if (timer && (timer.ontimeout || timer._onTimeout)) { timer.ontimeout = timer._onTimeout = null; if (timer instanceof Timeout) { timer.close(); // for after === 0 } else { exports.unenroll(timer); } } }; exports.setInterval = function(callback, repeat) { repeat *= 1; // coalesce to number or NaN if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { repeat = 1; // schedule on next tick, follows browser behaviour } var timer = new Timeout(repeat); var args = Array.prototype.slice.call(arguments, 2); timer._onTimeout = wrapper; timer._repeat = true; if (process.domain) timer.domain = process.domain; exports.active(timer); return timer; function wrapper() { callback.apply(this, args); // If callback called clearInterval(). if (timer._repeat === false) return; // If timer is unref'd (or was - it's permanently removed from the list.) if (this._handle) { this._handle.start(repeat, 0); } else { timer._idleTimeout = repeat; exports.active(timer); } } }; exports.clearInterval = function(timer) { if (timer && timer._repeat) { timer._repeat = false; clearTimeout(timer); } }; var Timeout = function(after) { this._idleTimeout = after; this._idlePrev = this; this._idleNext = this; this._idleStart = null; this._onTimeout = null; this._repeat = false; }; Timeout.prototype.unref = function() { if (!this._handle) { var now = Date.now(); if (!this._idleStart) this._idleStart = now; var delay = this._idleStart + this._idleTimeout - now; if (delay < 0) delay = 0; exports.unenroll(this); this._handle = new Timer(); this._handle.ontimeout = this._onTimeout; this._handle.start(delay, 0); this._handle.domain = this.domain; this._handle.unref(); } else { this._handle.unref(); } }; Timeout.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Timeout.prototype.close = function() { this._onTimeout = null; if (this._handle) { this._handle.ontimeout = null; this._handle.close(); } else { exports.unenroll(this); } }; var immediateQueue = {}; L.init(immediateQueue); function processImmediate() { var immediate = L.shift(immediateQueue); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } if (immediate._onImmediate) { if (immediate.domain) immediate.domain.enter(); immediate._onImmediate(); if (immediate.domain) immediate.domain.exit(); } } exports.setImmediate = function(callback) { var immediate = {}, args; L.init(immediate); immediate._onImmediate = callback; if (arguments.length > 1) { args = Array.prototype.slice.call(arguments, 1); immediate._onImmediate = function() { callback.apply(immediate, args); }; } if (!process._needImmediateCallback) { process._needImmediateCallback = true; process._immediateCallback = processImmediate; } if (process.domain) immediate.domain = process.domain; L.append(immediateQueue, immediate); return immediate; }; exports.clearImmediate = function(immediate) { if (!immediate) return; immediate._onImmediate = undefined; L.remove(immediate); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } }; // Internal APIs that need timeouts should use timers._unrefActive isntead of // timers.active as internal timeouts shouldn't hold the loop open var unrefList, unrefTimer; function unrefTimeout() { var now = Date.now(); debug('unrefTimer fired'); var first; while (first = L.peek(unrefList)) { var diff = now - first._idleStart; if (diff < first._idleTimeout) { diff = first._idleTimeout - diff; unrefTimer.start(diff, 0); unrefTimer.when = now + diff; debug('unrefTimer rescheudling for later'); return; } L.remove(first); var domain = first.domain; if (!first._onTimeout) continue; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; debug('unreftimer firing timeout'); first._onTimeout(); threw = false; if (domain) domain.exit(); } finally { if (threw) process.nextTick(unrefTimeout); } } debug('unrefList is empty'); unrefTimer.when = -1; } exports._unrefActive = function(item) { var msecs = item._idleTimeout; if (!msecs || msecs < 0) return; assert(msecs >= 0); L.remove(item); if (!unrefList) { debug('unrefList initialized'); unrefList = {}; L.init(unrefList); debug('unrefTimer initialized'); unrefTimer = new Timer(); unrefTimer.unref(); unrefTimer.when = -1; unrefTimer.ontimeout = unrefTimeout; } var now = Date.now(); item._idleStart = now; if (L.isEmpty(unrefList)) { debug('unrefList empty'); L.append(unrefList, item); unrefTimer.start(msecs, 0); unrefTimer.when = now + msecs; debug('unrefTimer scheduled'); return; } var when = now + msecs; debug('unrefList find where we can insert'); var cur, them; for (cur = unrefList._idlePrev; cur != unrefList; cur = cur._idlePrev) { them = cur._idleStart + cur._idleTimeout; if (when < them) { debug('unrefList inserting into middle of list'); L.append(cur, item); if (unrefTimer.when > when) { debug('unrefTimer is scheduled to fire too late, reschedule'); unrefTimer.start(msecs, 0); unrefTimer.when = when; } return; } } debug('unrefList append to end'); L.append(unrefList, item); }; timers// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // the sys module was renamed to 'util'. // this shim remains to keep old programs working. module.exports = require('util'); sys// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. function assertEncoding(encoding) { if (encoding && !Buffer.isEncoding(encoding)) { throw new Error('Unknown encoding: ' + encoding); } } var StringDecoder = exports.StringDecoder = function(encoding) { this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); assertEncoding(encoding); switch (this.encoding) { case 'utf8': // CESU-8 represents each of Surrogate Pair by 3-bytes this.surrogateSize = 3; break; case 'ucs2': case 'utf16le': // UTF-16 represents each of Surrogate Pair by 2-bytes this.surrogateSize = 2; this.detectIncompleteChar = utf16DetectIncompleteChar; break; case 'base64': // Base-64 stores 3 bytes in 4 chars, and pads the remainder. this.surrogateSize = 3; this.detectIncompleteChar = base64DetectIncompleteChar; break; default: this.write = passThroughWrite; return; } this.charBuffer = new Buffer(6); this.charReceived = 0; this.charLength = 0; }; StringDecoder.prototype.write = function(buffer) { var charStr = ''; var offset = 0; // if our last write ended with an incomplete multibyte character while (this.charLength) { // determine how many remaining bytes this buffer has to offer for this char var i = (buffer.length >= this.charLength - this.charReceived) ? this.charLength - this.charReceived : buffer.length; // add the new bytes to the char buffer buffer.copy(this.charBuffer, this.charReceived, offset, i); this.charReceived += (i - offset); offset = i; if (this.charReceived < this.charLength) { // still not enough chars in this buffer? wait for more ... return ''; } // get the character that was split charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); // lead surrogate (D800-DBFF) is also the incomplete character var charCode = charStr.charCodeAt(charStr.length - 1); if (charCode >= 0xD800 && charCode <= 0xDBFF) { this.charLength += this.surrogateSize; charStr = ''; continue; } this.charReceived = this.charLength = 0; // if there are no more bytes in this buffer, just emit our char if (i == buffer.length) return charStr; // otherwise cut off the characters end from the beginning of this buffer buffer = buffer.slice(i, buffer.length); break; } var lenIncomplete = this.detectIncompleteChar(buffer); var end = buffer.length; if (this.charLength) { // buffer the incomplete character bytes we got buffer.copy(this.charBuffer, 0, buffer.length - lenIncomplete, end); this.charReceived = lenIncomplete; end -= lenIncomplete; } charStr += buffer.toString(this.encoding, 0, end); var end = charStr.length - 1; var charCode = charStr.charCodeAt(end); // lead surrogate (D800-DBFF) is also the incomplete character if (charCode >= 0xD800 && charCode <= 0xDBFF) { var size = this.surrogateSize; this.charLength += size; this.charReceived += size; this.charBuffer.copy(this.charBuffer, size, 0, size); this.charBuffer.write(charStr.charAt(charStr.length - 1), this.encoding); return charStr.substring(0, end); } // or just emit the charStr return charStr; }; StringDecoder.prototype.detectIncompleteChar = function(buffer) { // determine how many bytes we have to check at the end of this buffer var i = (buffer.length >= 3) ? 3 : buffer.length; // Figure out if one of the last i bytes of our buffer announces an // incomplete char. for (; i > 0; i--) { var c = buffer[buffer.length - i]; // See http://en.wikipedia.org/wiki/UTF-8#Description // 110XXXXX if (i == 1 && c >> 5 == 0x06) { this.charLength = 2; break; } // 1110XXXX if (i <= 2 && c >> 4 == 0x0E) { this.charLength = 3; break; } // 11110XXX if (i <= 3 && c >> 3 == 0x1E) { this.charLength = 4; break; } } return i; }; StringDecoder.prototype.end = function(buffer) { var res = ''; if (buffer && buffer.length) res = this.write(buffer); if (this.charReceived) { var cr = this.charReceived; var buf = this.charBuffer; var enc = this.encoding; res += buf.slice(0, cr).toString(enc); } return res; }; function passThroughWrite(buffer) { return buffer.toString(this.encoding); } function utf16DetectIncompleteChar(buffer) { var incomplete = this.charReceived = buffer.length % 2; this.charLength = incomplete ? 2 : 0; return incomplete; } function base64DetectIncompleteChar(buffer) { var incomplete = this.charReceived = buffer.length % 3; this.charLength = incomplete ? 3 : 0; return incomplete; } string_decoder// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = Stream; var EE = require('events').EventEmitter; var util = require('util'); util.inherits(Stream, EE); Stream.Readable = require('_stream_readable'); Stream.Writable = require('_stream_writable'); Stream.Duplex = require('_stream_duplex'); Stream.Transform = require('_stream_transform'); Stream.PassThrough = require('_stream_passthrough'); // Backwards-compat with node 0.4.x Stream.Stream = Stream; // old-style streams. Note that the pipe method (the only relevant // part of this class) is overridden in the Readable class. function Stream() { EE.call(this); } Stream.prototype.pipe = function(dest, options) { var source = this; function ondata(chunk) { if (dest.writable) { if (false === dest.write(chunk) && source.pause) { source.pause(); } } } source.on('data', ondata); function ondrain() { if (source.readable && source.resume) { source.resume(); } } dest.on('drain', ondrain); // If the 'end' option is not supplied, dest.end() will be called when // source gets the 'end' or 'close' events. Only dest.end() once. if (!dest._isStdio && (!options || options.end !== false)) { source.on('end', onend); source.on('close', onclose); } var didOnEnd = false; function onend() { if (didOnEnd) return; didOnEnd = true; dest.end(); } function onclose() { if (didOnEnd) return; didOnEnd = true; if (typeof dest.destroy === 'function') dest.destroy(); } // don't leave dangling pipes when there are errors. function onerror(er) { cleanup(); if (EE.listenerCount(this, 'error') === 0) { throw er; // Unhandled stream error in pipe. } } source.on('error', onerror); dest.on('error', onerror); // remove all the event listeners that were added. function cleanup() { source.removeListener('data', ondata); dest.removeListener('drain', ondrain); source.removeListener('end', onend); source.removeListener('close', onclose); source.removeListener('error', onerror); dest.removeListener('error', onerror); source.removeListener('end', cleanup); source.removeListener('close', cleanup); dest.removeListener('close', cleanup); } source.on('end', cleanup); source.on('close', cleanup); dest.on('close', cleanup); dest.emit('pipe', source); // Allow for unix-like usage: A.pipe(B).pipe(C) return dest; }; stream// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* A repl library that you can include in your own code to get a runtime * interface to your program. * * var repl = require("repl"); * // start repl on stdin * repl.start("prompt> "); * * // listen for unix socket connections and start repl on them * net.createServer(function(socket) { * repl.start("node via Unix socket> ", socket); * }).listen("/tmp/node-repl-sock"); * * // listen for TCP socket connections and start repl on them * net.createServer(function(socket) { * repl.start("node via TCP socket> ", socket); * }).listen(5001); * * // expose foo to repl context * repl.start("node > ").context.foo = "stdin is fun"; */ var util = require('util'); var inherits = require('util').inherits; var Stream = require('stream'); var vm = require('vm'); var path = require('path'); var fs = require('fs'); var rl = require('readline'); var Console = require('console').Console; var EventEmitter = require('events').EventEmitter; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } // hack for require.resolve("./relative") to work properly. module.filename = path.resolve('repl'); // hack for repl require to work properly with node_modules folders module.paths = require('module')._nodeModulePaths(module.filename); // Can overridden with custom print functions, such as `probe` or `eyes.js`. // This is the default "writer" value if none is passed in the REPL options. exports.writer = util.inspect; exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'stream', 'string_decoder', 'tls', 'tty', 'url', 'util', 'vm', 'zlib']; function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) { if (!(this instanceof REPLServer)) { return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined); } EventEmitter.call(this); var options, input, output; if (typeof prompt == 'object') { // an options object was given options = prompt; stream = options.stream || options.socket; input = options.input; output = options.output; eval_ = options.eval; useGlobal = options.useGlobal; ignoreUndefined = options.ignoreUndefined; prompt = options.prompt; } else if (typeof prompt != 'string') { throw new Error('An options Object, or a prompt String are required'); } else { options = {}; } var self = this; self.useGlobal = !!useGlobal; self.ignoreUndefined = !!ignoreUndefined; self.eval = eval_ || function(code, context, file, cb) { var err, result; try { if (self.useGlobal) { result = vm.runInThisContext(code, file); } else { result = vm.runInContext(code, context, file); } } catch (e) { err = e; } if (err && process.domain) { process.domain.emit('error', err); process.domain.exit(); } else { cb(err, result); } }; if (!input && !output) { // legacy API, passing a 'stream'/'socket' option if (!stream) { // use stdin and stdout as the default streams if none were given stream = process; } if (stream.stdin && stream.stdout) { // We're given custom object with 2 streams, or the `process` object input = stream.stdin; output = stream.stdout; } else { // We're given a duplex readable/writable Stream, like a `net.Socket` input = stream; output = stream; } } self.inputStream = input; self.outputStream = output; self.resetContext(); self.bufferedCommand = ''; self.prompt = (prompt != undefined ? prompt : '> '); function complete(text, callback) { self.complete(text, callback); } var rli = rl.createInterface({ input: self.inputStream, output: self.outputStream, completer: complete, terminal: options.terminal }); self.rli = rli; this.commands = {}; defineDefaultCommands(this); // figure out which "writer" function to use self.writer = options.writer || exports.writer; if (typeof options.useColors === 'undefined') { options.useColors = rli.terminal; } self.useColors = !!options.useColors; if (self.useColors && self.writer === util.inspect) { // Turn on ANSI coloring. self.writer = function(obj, showHidden, depth) { return util.inspect(obj, showHidden, depth, true); }; } rli.setPrompt(self.prompt); rli.on('close', function() { self.emit('exit'); }); var sawSIGINT = false; rli.on('SIGINT', function() { var empty = rli.line.length === 0; rli.clearLine(); if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) { if (sawSIGINT) { rli.close(); sawSIGINT = false; return; } rli.output.write('(^C again to quit)\n'); sawSIGINT = true; } else { sawSIGINT = false; } self.bufferedCommand = ''; self.displayPrompt(); }); rli.on('line', function(cmd) { sawSIGINT = false; var skipCatchall = false; cmd = trimWhitespace(cmd); // Check to see if a REPL keyword was used. If it returns true, // display next prompt and return. if (cmd && cmd.charAt(0) === '.' && isNaN(parseFloat(cmd))) { var matches = cmd.match(/^(\.[^\s]+)\s*(.*)$/); var keyword = matches && matches[1]; var rest = matches && matches[2]; if (self.parseREPLKeyword(keyword, rest) === true) { return; } else { self.outputStream.write('Invalid REPL keyword\n'); skipCatchall = true; } } if (!skipCatchall) { var evalCmd = self.bufferedCommand + cmd + '\n'; // This try is for determining if the command is complete, or should // continue onto the next line. // We try to evaluate both expressions e.g. // '{ a : 1 }' // and statements e.g. // 'for (var i = 0; i < 10; i++) console.log(i);' // First we attempt to eval as expression with parens. // This catches '{a : 1}' properly. self.eval('(' + evalCmd + ')', self.context, 'repl', function(e, ret) { if (e && !isSyntaxError(e)) return finish(e); if (typeof ret === 'function' && /^[\r\n\s]*function/.test(evalCmd) || e) { // Now as statement without parens. self.eval(evalCmd, self.context, 'repl', finish); } else { finish(null, ret); } }); } else { finish(null); } function finish(e, ret) { self.memory(cmd); // If error was SyntaxError and not JSON.parse error if (isSyntaxError(e)) { if (!self.bufferedCommand && cmd.trim().match(/^npm /)) { self.outputStream.write('npm should be run outside of the ' + 'node repl, in your normal shell.\n' + '(Press Control-D to exit.)\n'); self.bufferedCommand = ''; self.displayPrompt(); return; } // Start buffering data like that: // { // ... x: 1 // ... } self.bufferedCommand += cmd + '\n'; self.displayPrompt(); return; } else if (e) { self.outputStream.write((e.stack || e) + '\n'); } // Clear buffer if no SyntaxErrors self.bufferedCommand = ''; // If we got any output - print it (if no error) if (!e && (!self.ignoreUndefined || ret !== undefined)) { self.context._ = ret; self.outputStream.write(self.writer(ret) + '\n'); } // Display prompt again self.displayPrompt(); }; }); rli.on('SIGCONT', function() { self.displayPrompt(true); }); self.displayPrompt(); } inherits(REPLServer, EventEmitter); exports.REPLServer = REPLServer; // prompt is a string to print on each line for the prompt, // source is a stream to use for I/O, defaulting to stdin/stdout. exports.start = function(prompt, source, eval_, useGlobal, ignoreUndefined) { var repl = new REPLServer(prompt, source, eval_, useGlobal, ignoreUndefined); if (!exports.repl) exports.repl = repl; return repl; }; REPLServer.prototype.createContext = function() { var context; if (this.useGlobal) { context = global; } else { context = vm.createContext(); for (var i in global) context[i] = global[i]; context.console = new Console(this.outputStream); context.global = context; context.global.global = context; } context.module = module; context.require = require; this.lines = []; this.lines.level = []; // make built-in modules available directly // (loaded lazily) exports._builtinLibs.forEach(function(name) { Object.defineProperty(context, name, { get: function() { var lib = require(name); context._ = context[name] = lib; return lib; }, // allow the creation of other globals with this name set: function(val) { delete context[name]; context[name] = val; }, configurable: true }); }); return context; }; REPLServer.prototype.resetContext = function() { this.context = this.createContext(); }; REPLServer.prototype.displayPrompt = function(preserveCursor) { var prompt = this.prompt; if (this.bufferedCommand.length) { prompt = '...'; var levelInd = new Array(this.lines.level.length).join('..'); prompt += levelInd + ' '; } this.rli.setPrompt(prompt); this.rli.prompt(preserveCursor); }; // A stream to push an array into a REPL // used in REPLServer.complete function ArrayStream() { Stream.call(this); this.run = function(data) { var self = this; data.forEach(function(line) { self.emit('data', line + '\n'); }); } } util.inherits(ArrayStream, Stream); ArrayStream.prototype.readable = true; ArrayStream.prototype.writable = true; ArrayStream.prototype.resume = function() {}; ArrayStream.prototype.write = function() {}; var requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/; var simpleExpressionRE = /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/; // Provide a list of completions for the given leading text. This is // given to the readline interface for handling tab completion. // // Example: // complete('var foo = util.') // -> [['util.print', 'util.debug', 'util.log', 'util.inspect', 'util.pump'], // 'util.' ] // // Warning: This eval's code like "foo.bar.baz", so it will run property // getter code. REPLServer.prototype.complete = function(line, callback) { // There may be local variables to evaluate, try a nested REPL if (this.bufferedCommand != undefined && this.bufferedCommand.length) { // Get a new array of inputed lines var tmp = this.lines.slice(); // Kill off all function declarations to push all local variables into // global scope this.lines.level.forEach(function(kill) { if (kill.isFunction) { tmp[kill.line] = ''; } }); var flat = new ArrayStream(); // make a new "input" stream var magic = new REPLServer('', flat); // make a nested REPL magic.context = magic.createContext(); flat.run(tmp); // eval the flattened code // all this is only profitable if the nested REPL // does not have a bufferedCommand if (!magic.bufferedCommand) { return magic.complete(line, callback); } } var completions; // list of completion lists, one for each inheritance "level" var completionGroups = []; var completeOn, match, filter, i, j, group, c; // REPL commands (e.g. ".break"). var match = null; match = line.match(/^\s*(\.\w*)$/); if (match) { completionGroups.push(Object.keys(this.commands)); completeOn = match[1]; if (match[1].length > 1) { filter = match[1]; } completionGroupsLoaded(); } else if (match = line.match(requireRE)) { // require('...') var exts = Object.keys(require.extensions); var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') + ')$'); completeOn = match[1]; var subdir = match[2] || ''; var filter = match[1]; var dir, files, f, name, base, ext, abs, subfiles, s; group = []; var paths = module.paths.concat(require('module').globalPaths); for (i = 0; i < paths.length; i++) { dir = path.resolve(paths[i], subdir); try { files = fs.readdirSync(dir); } catch (e) { continue; } for (f = 0; f < files.length; f++) { name = files[f]; ext = path.extname(name); base = name.slice(0, -ext.length); if (base.match(/-\d+\.\d+(\.\d+)?/) || name === '.npm') { // Exclude versioned names that 'npm' installs. continue; } if (exts.indexOf(ext) !== -1) { if (!subdir || base !== 'index') { group.push(subdir + base); } } else { abs = path.resolve(dir, name); try { if (fs.statSync(abs).isDirectory()) { group.push(subdir + name + '/'); subfiles = fs.readdirSync(abs); for (s = 0; s < subfiles.length; s++) { if (indexRe.test(subfiles[s])) { group.push(subdir + name); } } } } catch (e) {} } } } if (group.length) { completionGroups.push(group); } if (!subdir) { completionGroups.push(exports._builtinLibs); } completionGroupsLoaded(); // Handle variable member lookup. // We support simple chained expressions like the following (no function // calls, etc.). That is for simplicity and also because we *eval* that // leading expression so for safety (see WARNING above) don't want to // eval function calls. // // foo.bar<|> # completions for 'foo' with filter 'bar' // spam.eggs.<|> # completions for 'spam.eggs' with filter '' // foo<|> # all scope vars with filter 'foo' // foo.<|> # completions for 'foo' with filter '' } else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) { match = simpleExpressionRE.exec(line); if (line.length === 0 || match) { var expr; completeOn = (match ? match[0] : ''); if (line.length === 0) { filter = ''; expr = ''; } else if (line[line.length - 1] === '.') { filter = ''; expr = match[0].slice(0, match[0].length - 1); } else { var bits = match[0].split('.'); filter = bits.pop(); expr = bits.join('.'); } // Resolve expr and get its completions. var obj, memberGroups = []; if (!expr) { // If context is instance of vm.ScriptContext // Get global vars synchronously if (this.useGlobal || this.context.constructor && this.context.constructor.name === 'Context') { var contextProto = this.context; while (contextProto = Object.getPrototypeOf(contextProto)) { completionGroups.push(Object.getOwnPropertyNames(contextProto)); } completionGroups.push(Object.getOwnPropertyNames(this.context)); addStandardGlobals(completionGroups, filter); completionGroupsLoaded(); } else { this.eval('.scope', this.context, 'repl', function(err, globals) { if (err || !globals) { addStandardGlobals(completionGroups, filter); } else if (Array.isArray(globals[0])) { // Add grouped globals globals.forEach(function(group) { completionGroups.push(group); }); } else { completionGroups.push(globals); addStandardGlobals(completionGroups, filter); } completionGroupsLoaded(); }); } } else { this.eval(expr, this.context, 'repl', function(e, obj) { // if (e) console.log(e); if (obj != null) { if (typeof obj === 'object' || typeof obj === 'function') { memberGroups.push(Object.getOwnPropertyNames(obj)); } // works for non-objects try { var sentinel = 5; var p; if (typeof obj === 'object' || typeof obj === 'function') { p = Object.getPrototypeOf(obj); } else { p = obj.constructor ? obj.constructor.prototype : null; } while (p !== null) { memberGroups.push(Object.getOwnPropertyNames(p)); p = Object.getPrototypeOf(p); // Circular refs possible? Let's guard against that. sentinel--; if (sentinel <= 0) { break; } } } catch (e) { //console.log("completion error walking prototype chain:" + e); } } if (memberGroups.length) { for (i = 0; i < memberGroups.length; i++) { completionGroups.push(memberGroups[i].map(function(member) { return expr + '.' + member; })); } if (filter) { filter = expr + '.' + filter; } } completionGroupsLoaded(); }); } } else { completionGroupsLoaded(); } } else { completionGroupsLoaded(); } // Will be called when all completionGroups are in place // Useful for async autocompletion function completionGroupsLoaded(err) { if (err) throw err; // Filter, sort (within each group), uniq and merge the completion groups. if (completionGroups.length && filter) { var newCompletionGroups = []; for (i = 0; i < completionGroups.length; i++) { group = completionGroups[i].filter(function(elem) { return elem.indexOf(filter) == 0; }); if (group.length) { newCompletionGroups.push(group); } } completionGroups = newCompletionGroups; } if (completionGroups.length) { var uniq = {}; // unique completions across all groups completions = []; // Completion group 0 is the "closest" // (least far up the inheritance chain) // so we put its completions last: to be closest in the REPL. for (i = completionGroups.length - 1; i >= 0; i--) { group = completionGroups[i]; group.sort(); for (var j = 0; j < group.length; j++) { c = group[j]; if (!hasOwnProperty(c)) { completions.push(c); uniq[c] = true; } } completions.push(''); // separator btwn groups } while (completions.length && completions[completions.length - 1] === '') { completions.pop(); } } callback(null, [completions || [], completeOn]); } }; /** * Used to parse and execute the Node REPL commands. * * @param {keyword} keyword The command entered to check. * @return {Boolean} If true it means don't continue parsing the command. */ REPLServer.prototype.parseREPLKeyword = function(keyword, rest) { var cmd = this.commands[keyword]; if (cmd) { cmd.action.call(this, rest); return true; } return false; }; REPLServer.prototype.defineCommand = function(keyword, cmd) { if (typeof cmd === 'function') { cmd = {action: cmd}; } else if (typeof cmd.action !== 'function') { throw new Error('bad argument, action must be a function'); } this.commands['.' + keyword] = cmd; }; REPLServer.prototype.memory = function memory(cmd) { var self = this; self.lines = self.lines || []; self.lines.level = self.lines.level || []; // save the line so I can do magic later if (cmd) { // TODO should I tab the level? self.lines.push(new Array(self.lines.level.length).join(' ') + cmd); } else { // I don't want to not change the format too much... self.lines.push(''); } // I need to know "depth." // Because I can not tell the difference between a } that // closes an object literal and a } that closes a function if (cmd) { // going down is { and ( e.g. function() { // going up is } and ) var dw = cmd.match(/{|\(/g); var up = cmd.match(/}|\)/g); up = up ? up.length : 0; dw = dw ? dw.length : 0; var depth = dw - up; if (depth) { (function workIt() { if (depth > 0) { // going... down. // push the line#, depth count, and if the line is a function. // Since JS only has functional scope I only need to remove // "function() {" lines, clearly this will not work for // "function() // {" but nothing should break, only tab completion for local // scope will not work for this function. self.lines.level.push({ line: self.lines.length - 1, depth: depth, isFunction: /\s*function\s*/.test(cmd) }); } else if (depth < 0) { // going... up. var curr = self.lines.level.pop(); if (curr) { var tmp = curr.depth + depth; if (tmp < 0) { //more to go, recurse depth += curr.depth; workIt(); } else if (tmp > 0) { //remove and push back curr.depth += depth; self.lines.level.push(curr); } } } }()); } // it is possible to determine a syntax error at this point. // if the REPL still has a bufferedCommand and // self.lines.level.length === 0 // TODO? keep a log of level so that any syntax breaking lines can // be cleared on .break and in the case of a syntax error? // TODO? if a log was kept, then I could clear the bufferedComand and // eval these lines and throw the syntax error } else { self.lines.level = []; } }; function addStandardGlobals(completionGroups, filter) { // Global object properties // (http://www.ecma-international.org/publications/standards/Ecma-262.htm) completionGroups.push(['NaN', 'Infinity', 'undefined', 'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'Object', 'Function', 'Array', 'String', 'Boolean', 'Number', 'Date', 'RegExp', 'Error', 'EvalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'Math', 'JSON']); // Common keywords. Exclude for completion on the empty string, b/c // they just get in the way. if (filter) { completionGroups.push(['break', 'case', 'catch', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'false', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void', 'while', 'with', 'yield']); } } function defineDefaultCommands(repl) { // TODO remove me after 0.3.x repl.defineCommand('break', { help: 'Sometimes you get stuck, this gets you out', action: function() { this.bufferedCommand = ''; this.displayPrompt(); } }); var clearMessage; if (repl.useGlobal) { clearMessage = 'Alias for .break'; } else { clearMessage = 'Break, and also clear the local context'; } repl.defineCommand('clear', { help: clearMessage, action: function() { this.bufferedCommand = ''; if (!this.useGlobal) { this.outputStream.write('Clearing context...\n'); this.resetContext(); } this.displayPrompt(); } }); repl.defineCommand('exit', { help: 'Exit the repl', action: function() { this.rli.close(); } }); repl.defineCommand('help', { help: 'Show repl options', action: function() { var self = this; Object.keys(this.commands).sort().forEach(function(name) { var cmd = self.commands[name]; self.outputStream.write(name + '\t' + (cmd.help || '') + '\n'); }); this.displayPrompt(); } }); repl.defineCommand('save', { help: 'Save all evaluated commands in this REPL session to a file', action: function(file) { try { fs.writeFileSync(file, this.lines.join('\n') + '\n'); this.outputStream.write('Session saved to:' + file + '\n'); } catch (e) { this.outputStream.write('Failed to save:' + file + '\n'); } this.displayPrompt(); } }); repl.defineCommand('load', { help: 'Load JS from a file into the REPL session', action: function(file) { try { var stats = fs.statSync(file); if (stats && stats.isFile()) { var self = this; var data = fs.readFileSync(file, 'utf8'); var lines = data.split('\n'); this.displayPrompt(); lines.forEach(function(line) { if (line) { self.rli.write(line + '\n'); } }); } } catch (e) { this.outputStream.write('Failed to load:' + file + '\n'); } this.displayPrompt(); } }); } function trimWhitespace(cmd) { var trimmer = /^\s*(.+)\s*$/m, matches = trimmer.exec(cmd); if (matches && matches.length === 2) { return matches[1]; } return ''; } function regexpEscape(s) { return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); } /** * Converts commands that use var and function () to use the * local exports.context when evaled. This provides a local context * on the REPL. * * @param {String} cmd The cmd to convert. * @return {String} The converted command. */ REPLServer.prototype.convertToContext = function(cmd) { var self = this, matches, scopeVar = /^\s*var\s*([_\w\$]+)(.*)$/m, scopeFunc = /^\s*function\s*([_\w\$]+)/; // Replaces: var foo = "bar"; with: self.context.foo = bar; matches = scopeVar.exec(cmd); if (matches && matches.length === 3) { return 'self.context.' + matches[1] + matches[2]; } // Replaces: function foo() {}; with: foo = function foo() {}; matches = scopeFunc.exec(self.bufferedCommand); if (matches && matches.length === 2) { return matches[1] + ' = ' + self.bufferedCommand; } return cmd; }; /** * Returns `true` if "e" is a SyntaxError, `false` otherwise. * This function filters out false positives likes JSON.parse() errors and * RegExp syntax errors. */ function isSyntaxError(e) { // Convert error to string e = e && (e.stack || e.toString()); return e && ((e.match(/^SyntaxError/) && // RegExp syntax error !e.match(/^SyntaxError: Invalid regular expression/) && !e.match(/^SyntaxError: Invalid flags supplied to RegExp constructor/) && // "strict mode" syntax errors !e.match(/^SyntaxError: .*strict mode.*/i) && // JSON.parse() error !e.match(/\n {4}at Object.parse \(native\)\n/) && // Regexp errors in chakra: !e.match(/^Error: Expected .* in regular expression/) && !e.match(/^SyntaxError: Syntax error in regular expression/) && // Chakra Json parse error: !e.match(/\n {3}at JsonParse \(_chakra_patch.js/)) || ( (e.match(/^Error: Syntax error/) || e.match(/^Error: Expected/) ) && // RegExp syntax error !e.match(/^Error: Syntax error: Invalid regular expression/) && !e.match( /^Error: Syntax error: Invalid flags supplied to RegExp constructor/ ) && // "strict mode" syntax errors !e.match(/^Error: Syntax error: .*strict mode.*/i) && // JSON.parse() error !e.match(/\n {4}at Object.parse \(native\)\n/) && // Regexp errors in chakra: !e.match(/^Error: Expected .* in regular expression/) && !e.match(/^SyntaxError: Syntax error in regular expression/) && // Chakra Json parse error: !e.match(/\n {3}at JsonParse \(_chakra_patch.js/) )); } repl// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Inspiration for this code comes from Salvatore Sanfilippo's linenoise. // https://github.com/antirez/linenoise // Reference: // * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html // * http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html var kHistorySize = 30; var kBufSize = 10 * 1024; var util = require('util'); var inherits = require('util').inherits; var EventEmitter = require('events').EventEmitter; exports.createInterface = function(input, output, completer, terminal) { var rl; if (arguments.length === 1) { rl = new Interface(input); } else { rl = new Interface(input, output, completer, terminal); } return rl; }; function Interface(input, output, completer, terminal) { if (!(this instanceof Interface)) { return new Interface(input, output, completer, terminal); } this._sawReturn = false; EventEmitter.call(this); if (arguments.length === 1) { // an options object was given output = input.output; completer = input.completer; terminal = input.terminal; input = input.input; } completer = completer || function() { return []; }; if (typeof completer !== 'function') { throw new TypeError('Argument \'completer\' must be a function'); } // backwards compat; check the isTTY prop of the output stream // when `terminal` was not specified if (typeof terminal == 'undefined') { terminal = !!output.isTTY; } var self = this; this.output = output; this.input = input; // Check arity, 2 - for async, 1 for sync this.completer = completer.length === 2 ? completer : function(v, callback) { callback(null, completer(v)); }; this.setPrompt('> '); this.terminal = !!terminal; function ondata(data) { self._normalWrite(data); } function onend() { self.close(); } function onkeypress(s, key) { self._ttyWrite(s, key); } function onresize() { self._refreshLine(); } if (!this.terminal) { input.on('data', ondata); input.on('end', onend); self.once('close', function() { input.removeListener('data', ondata); input.removeListener('end', onend); }); var StringDecoder = require('string_decoder').StringDecoder; // lazy load this._decoder = new StringDecoder('utf8'); } else { exports.emitKeypressEvents(input); // input usually refers to stdin input.on('keypress', onkeypress); // Current line this.line = ''; this._setRawMode(true); this.terminal = true; // Cursor position on the line. this.cursor = 0; this.history = []; this.historyIndex = -1; output.on('resize', onresize); self.once('close', function() { input.removeListener('keypress', onkeypress); output.removeListener('resize', onresize); }); } input.resume(); } inherits(Interface, EventEmitter); Interface.prototype.__defineGetter__('columns', function() { return this.output.columns || Infinity; }); Interface.prototype.setPrompt = function(prompt, length) { this._prompt = prompt; if (length) { this._promptLength = length; } else { var lines = prompt.split(/[\r\n]/); var lastLine = lines[lines.length - 1]; this._promptLength = lastLine.length; } }; Interface.prototype._setRawMode = function(mode) { if (typeof this.input.setRawMode === 'function') { return this.input.setRawMode(mode); } }; Interface.prototype.prompt = function(preserveCursor) { if (this.paused) this.resume(); if (this.terminal) { if (!preserveCursor) this.cursor = 0; this._refreshLine(); } else { this.output.write(this._prompt); } }; Interface.prototype.question = function(query, cb) { if (typeof cb === 'function') { if (this._questionCallback) { this.prompt(); } else { this._oldPrompt = this._prompt; this.setPrompt(query); this._questionCallback = cb; this.prompt(); } } }; Interface.prototype._onLine = function(line) { if (this._questionCallback) { var cb = this._questionCallback; this._questionCallback = null; this.setPrompt(this._oldPrompt); cb(line); } else { this.emit('line', line); } }; Interface.prototype._addHistory = function() { if (this.line.length === 0) return ''; if (this.history.length === 0 || this.history[0] !== this.line) { this.history.unshift(this.line); // Only store so many if (this.history.length > kHistorySize) this.history.pop(); } this.historyIndex = -1; return this.history[0]; }; Interface.prototype._refreshLine = function() { var columns = this.columns; // line length var line = this._prompt + this.line; var lineLength = line.length; var lineCols = lineLength % columns; var lineRows = (lineLength - lineCols) / columns; // cursor position var cursorPos = this._getCursorPos(); // first move to the bottom of the current line, based on cursor pos var prevRows = this.prevRows || 0; if (prevRows > 0) { exports.moveCursor(this.output, 0, -prevRows); } // Cursor to left edge. exports.cursorTo(this.output, 0); // erase data exports.clearScreenDown(this.output); // Write the prompt and the current buffer content. this.output.write(line); // Force terminal to allocate a new line if (lineCols === 0) { this.output.write(' '); } // Move cursor to original position. exports.cursorTo(this.output, cursorPos.cols); var diff = lineRows - cursorPos.rows; if (diff > 0) { exports.moveCursor(this.output, 0, -diff); } this.prevRows = cursorPos.rows; }; Interface.prototype.close = function() { if (this.closed) return; if (this.terminal) { this._setRawMode(false); } this.pause(); this.closed = true; this.emit('close'); }; Interface.prototype.pause = function() { if (this.paused) return; this.input.pause(); this.paused = true; this.emit('pause'); }; Interface.prototype.resume = function() { if (!this.paused) return; this.input.resume(); this.paused = false; this.emit('resume'); }; Interface.prototype.write = function(d, key) { if (this.paused) this.resume(); this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d); }; // \r\n, \n, or \r followed by something other than \n var lineEnding = /\r?\n|\r(?!\n)/; Interface.prototype._normalWrite = function(b) { if (b === undefined) { return; } var string = this._decoder.write(b); if (this._sawReturn) { string = string.replace(/^\n/, ''); this._sawReturn = false; } if (this._line_buffer) { string = this._line_buffer + string; this._line_buffer = null; } if (lineEnding.test(string)) { this._sawReturn = /\r$/.test(string); // got one or more newlines; process into "line" events var lines = string.split(lineEnding); // either '' or (concievably) the unfinished portion of the next line string = lines.pop(); this._line_buffer = string; lines.forEach(function(line) { this._onLine(line); }, this); } else if (string) { // no newlines this time, save what we have for next time this._line_buffer = string; } }; Interface.prototype._insertString = function(c) { //BUG: Problem when adding tabs with following content. // Perhaps the bug is in _refreshLine(). Not sure. // A hack would be to insert spaces instead of literal '\t'. if (this.cursor < this.line.length) { var beg = this.line.slice(0, this.cursor); var end = this.line.slice(this.cursor, this.line.length); this.line = beg + c + end; this.cursor += c.length; this._refreshLine(); } else { this.line += c; this.cursor += c.length; if (this._getCursorPos().cols === 0) { this._refreshLine(); } else { this.output.write(c); } // a hack to get the line refreshed if it's needed this._moveCursor(0); } }; Interface.prototype._tabComplete = function() { var self = this; self.pause(); self.completer(self.line.slice(0, self.cursor), function(err, rv) { self.resume(); if (err) { // XXX Log it somewhere? return; } var completions = rv[0], completeOn = rv[1]; // the text that was completed if (completions && completions.length) { // Apply/show completions. if (completions.length === 1) { self._insertString(completions[0].slice(completeOn.length)); } else { self.output.write('\r\n'); var width = completions.reduce(function(a, b) { return a.length > b.length ? a : b; }).length + 2; // 2 space padding var maxColumns = Math.floor(self.columns / width) || 1; var group = [], c; for (var i = 0, compLen = completions.length; i < compLen; i++) { c = completions[i]; if (c === '') { handleGroup(self, group, width, maxColumns); group = []; } else { group.push(c); } } handleGroup(self, group, width, maxColumns); // If there is a common prefix to all matches, then apply that // portion. var f = completions.filter(function(e) { if (e) return e; }); var prefix = commonPrefix(f); if (prefix.length > completeOn.length) { self._insertString(prefix.slice(completeOn.length)); } } self._refreshLine(); } }); }; // this = Interface instance function handleGroup(self, group, width, maxColumns) { if (group.length == 0) { return; } var minRows = Math.ceil(group.length / maxColumns); for (var row = 0; row < minRows; row++) { for (var col = 0; col < maxColumns; col++) { var idx = row * maxColumns + col; if (idx >= group.length) { break; } var item = group[idx]; self.output.write(item); if (col < maxColumns - 1) { for (var s = 0, itemLen = item.length; s < width - itemLen; s++) { self.output.write(' '); } } } self.output.write('\r\n'); } self.output.write('\r\n'); } function commonPrefix(strings) { if (!strings || strings.length == 0) { return ''; } var sorted = strings.slice().sort(); var min = sorted[0]; var max = sorted[sorted.length - 1]; for (var i = 0, len = min.length; i < len; i++) { if (min[i] != max[i]) { return min.slice(0, i); } } return min; } Interface.prototype._wordLeft = function() { if (this.cursor > 0) { var leading = this.line.slice(0, this.cursor); var match = leading.match(/([^\w\s]+|\w+|)\s*$/); this._moveCursor(-match[0].length); } }; Interface.prototype._wordRight = function() { if (this.cursor < this.line.length) { var trailing = this.line.slice(this.cursor); var match = trailing.match(/^(\s+|\W+|\w+)\s*/); this._moveCursor(match[0].length); } }; Interface.prototype._deleteLeft = function() { if (this.cursor > 0 && this.line.length > 0) { this.line = this.line.slice(0, this.cursor - 1) + this.line.slice(this.cursor, this.line.length); this.cursor--; this._refreshLine(); } }; Interface.prototype._deleteRight = function() { this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1, this.line.length); this._refreshLine(); }; Interface.prototype._deleteWordLeft = function() { if (this.cursor > 0) { var leading = this.line.slice(0, this.cursor); var match = leading.match(/([^\w\s]+|\w+|)\s*$/); leading = leading.slice(0, leading.length - match[0].length); this.line = leading + this.line.slice(this.cursor, this.line.length); this.cursor = leading.length; this._refreshLine(); } }; Interface.prototype._deleteWordRight = function() { if (this.cursor < this.line.length) { var trailing = this.line.slice(this.cursor); var match = trailing.match(/^(\s+|\W+|\w+)\s*/); this.line = this.line.slice(0, this.cursor) + trailing.slice(match[0].length); this._refreshLine(); } }; Interface.prototype._deleteLineLeft = function() { this.line = this.line.slice(this.cursor); this.cursor = 0; this._refreshLine(); }; Interface.prototype._deleteLineRight = function() { this.line = this.line.slice(0, this.cursor); this._refreshLine(); }; Interface.prototype.clearLine = function() { this._moveCursor(+Infinity); this.output.write('\r\n'); this.line = ''; this.cursor = 0; this.prevRows = 0; }; Interface.prototype._line = function() { var line = this._addHistory(); this.clearLine(); this._onLine(line); }; Interface.prototype._historyNext = function() { if (this.historyIndex > 0) { this.historyIndex--; this.line = this.history[this.historyIndex]; this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } else if (this.historyIndex === 0) { this.historyIndex = -1; this.cursor = 0; this.line = ''; this._refreshLine(); } }; Interface.prototype._historyPrev = function() { if (this.historyIndex + 1 < this.history.length) { this.historyIndex++; this.line = this.history[this.historyIndex]; this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } }; // Returns current cursor's position and line Interface.prototype._getCursorPos = function() { var columns = this.columns; var cursorPos = this.cursor + this._promptLength; var cols = cursorPos % columns; var rows = (cursorPos - cols) / columns; return {cols: cols, rows: rows}; }; // This function moves cursor dx places to the right // (-dx for left) and refreshes the line if it is needed Interface.prototype._moveCursor = function(dx) { var oldcursor = this.cursor; var oldPos = this._getCursorPos(); this.cursor += dx; // bounds check if (this.cursor < 0) this.cursor = 0; if (this.cursor > this.line.length) this.cursor = this.line.length; var newPos = this._getCursorPos(); // check if cursors are in the same line if (oldPos.rows === newPos.rows) { exports.moveCursor(this.output, this.cursor - oldcursor, 0); this.prevRows = newPos.rows; } else { this._refreshLine(); } }; // handle a write from the tty Interface.prototype._ttyWrite = function(s, key) { key = key || {}; // Ignore escape key - Fixes #2876 if (key.name == 'escape') return; if (key.ctrl && key.shift) { /* Control and shift pressed */ switch (key.name) { case 'backspace': this._deleteLineLeft(); break; case 'delete': this._deleteLineRight(); break; } } else if (key.ctrl) { /* Control key pressed */ switch (key.name) { case 'c': if (EventEmitter.listenerCount(this, 'SIGINT') > 0) { this.emit('SIGINT'); } else { // This readline instance is finished this.close(); } break; case 'h': // delete left this._deleteLeft(); break; case 'd': // delete right or EOF if (this.cursor === 0 && this.line.length === 0) { // This readline instance is finished this.close(); } else if (this.cursor < this.line.length) { this._deleteRight(); } break; case 'u': // delete the whole line this.cursor = 0; this.line = ''; this._refreshLine(); break; case 'k': // delete from current to end of line this._deleteLineRight(); break; case 'a': // go to the start of the line this._moveCursor(-Infinity); break; case 'e': // go to the end of the line this._moveCursor(+Infinity); break; case 'b': // back one character this._moveCursor(-1); break; case 'f': // forward one character this._moveCursor(+1); break; case 'n': // next history item this._historyNext(); break; case 'p': // previous history item this._historyPrev(); break; case 'z': if (process.platform == 'win32') break; if (EventEmitter.listenerCount(this, 'SIGTSTP') > 0) { this.emit('SIGTSTP'); } else { process.once('SIGCONT', (function(self) { return function() { // Don't raise events if stream has already been abandoned. if (!self.paused) { // Stream must be paused and resumed after SIGCONT to catch // SIGINT, SIGTSTP, and EOF. self.pause(); self.emit('SIGCONT'); } // explictly re-enable "raw mode" and move the cursor to // the correct position. // See https://github.com/joyent/node/issues/3295. self._setRawMode(true); self._refreshLine(); }; })(this)); this._setRawMode(false); process.kill(process.pid, 'SIGTSTP'); } break; case 'w': // delete backwards to a word boundary case 'backspace': this._deleteWordLeft(); break; case 'delete': // delete forward to a word boundary this._deleteWordRight(); break; case 'backspace': this._deleteWordLeft(); break; case 'left': this._wordLeft(); break; case 'right': this._wordRight(); break; } } else if (key.meta) { /* Meta key pressed */ switch (key.name) { case 'b': // backward word this._wordLeft(); break; case 'f': // forward word this._wordRight(); break; case 'd': // delete forward word case 'delete': this._deleteWordRight(); break; case 'backspace': // delete backwards to a word boundary this._deleteWordLeft(); break; } } else { /* No modifier keys used */ // \r bookkeeping is only relevant if a \n comes right after. if (this._sawReturn && key.name !== 'enter') this._sawReturn = false; switch (key.name) { case 'return': // carriage return, i.e. \r this._sawReturn = true; this._line(); break; case 'enter': if (this._sawReturn) this._sawReturn = false; else this._line(); break; case 'backspace': this._deleteLeft(); break; case 'delete': this._deleteRight(); break; case 'tab': // tab completion this._tabComplete(); break; case 'left': this._moveCursor(-1); break; case 'right': this._moveCursor(+1); break; case 'home': this._moveCursor(-Infinity); break; case 'end': this._moveCursor(+Infinity); break; case 'up': this._historyPrev(); break; case 'down': this._historyNext(); break; default: if (Buffer.isBuffer(s)) s = s.toString('utf-8'); if (s) { var lines = s.split(/\r\n|\n|\r/); for (var i = 0, len = lines.length; i < len; i++) { if (i > 0) { this._line(); } this._insertString(lines[i]); } } } } }; exports.Interface = Interface; /** * accepts a readable Stream instance and makes it emit "keypress" events */ function emitKeypressEvents(stream) { if (stream._keypressDecoder) return; var StringDecoder = require('string_decoder').StringDecoder; // lazy load stream._keypressDecoder = new StringDecoder('utf8'); function onData(b) { if (EventEmitter.listenerCount(stream, 'keypress') > 0) { var r = stream._keypressDecoder.write(b); if (r) emitKey(stream, r); } else { // Nobody's watching anyway stream.removeListener('data', onData); stream.on('newListener', onNewListener); } } function onNewListener(event) { if (event == 'keypress') { stream.on('data', onData); stream.removeListener('newListener', onNewListener); } } if (EventEmitter.listenerCount(stream, 'keypress') > 0) { stream.on('data', onData); } else { stream.on('newListener', onNewListener); } } exports.emitKeypressEvents = emitKeypressEvents; /* Some patterns seen in terminal key escape codes, derived from combos seen at http://www.midnight-commander.org/browser/lib/tty/key.c ESC letter ESC [ letter ESC [ modifier letter ESC [ 1 ; modifier letter ESC [ num char ESC [ num ; modifier char ESC O letter ESC O modifier letter ESC O 1 ; modifier letter ESC N letter ESC [ [ num ; modifier char ESC [ [ 1 ; modifier letter ESC ESC [ num char ESC ESC O letter - char is usually ~ but $ and ^ also happen with rxvt - modifier is 1 + (shift * 1) + (left_alt * 2) + (ctrl * 4) + (right_alt * 8) - two leading ESCs apparently mean the same as one leading ESC */ // Regexes used for ansi escape code splitting var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; var functionKeyCodeRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; function emitKey(stream, s) { var ch, key = { name: undefined, ctrl: false, meta: false, shift: false }, parts; if (Buffer.isBuffer(s)) { if (s[0] > 127 && s[1] === undefined) { s[0] -= 128; s = '\x1b' + s.toString(stream.encoding || 'utf-8'); } else { s = s.toString(stream.encoding || 'utf-8'); } } key.sequence = s; if (s === '\r') { // carriage return key.name = 'return'; } else if (s === '\n') { // enter, should have been called linefeed key.name = 'enter'; } else if (s === '\t') { // tab key.name = 'tab'; } else if (s === '\b' || s === '\x7f' || s === '\x1b\x7f' || s === '\x1b\b') { // backspace or ctrl+h key.name = 'backspace'; key.meta = (s.charAt(0) === '\x1b'); } else if (s === '\x1b' || s === '\x1b\x1b') { // escape key key.name = 'escape'; key.meta = (s.length === 2); } else if (s === ' ' || s === '\x1b ') { key.name = 'space'; key.meta = (s.length === 2); } else if (s <= '\x1a') { // ctrl+letter key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); key.ctrl = true; } else if (s.length === 1 && s >= 'a' && s <= 'z') { // lowercase letter key.name = s; } else if (s.length === 1 && s >= 'A' && s <= 'Z') { // shift+letter key.name = s.toLowerCase(); key.shift = true; } else if (parts = metaKeyCodeRe.exec(s)) { // meta+character key key.name = parts[1].toLowerCase(); key.meta = true; key.shift = /^[A-Z]$/.test(parts[1]); } else if (parts = functionKeyCodeRe.exec(s)) { // ansi escape sequence // reassemble the key code leaving out leading \x1b's, // the modifier key bitflag and any meaningless "1;" sequence var code = (parts[1] || '') + (parts[2] || '') + (parts[4] || '') + (parts[6] || ''), modifier = (parts[3] || parts[5] || 1) - 1; // Parse the key modifier key.ctrl = !!(modifier & 4); key.meta = !!(modifier & 10); key.shift = !!(modifier & 1); key.code = code; // Parse the key itself switch (code) { /* xterm/gnome ESC O letter */ case 'OP': key.name = 'f1'; break; case 'OQ': key.name = 'f2'; break; case 'OR': key.name = 'f3'; break; case 'OS': key.name = 'f4'; break; /* xterm/rxvt ESC [ number ~ */ case '[11~': key.name = 'f1'; break; case '[12~': key.name = 'f2'; break; case '[13~': key.name = 'f3'; break; case '[14~': key.name = 'f4'; break; /* from Cygwin and used in libuv */ case '[[A': key.name = 'f1'; break; case '[[B': key.name = 'f2'; break; case '[[C': key.name = 'f3'; break; case '[[D': key.name = 'f4'; break; case '[[E': key.name = 'f5'; break; /* common */ case '[15~': key.name = 'f5'; break; case '[17~': key.name = 'f6'; break; case '[18~': key.name = 'f7'; break; case '[19~': key.name = 'f8'; break; case '[20~': key.name = 'f9'; break; case '[21~': key.name = 'f10'; break; case '[23~': key.name = 'f11'; break; case '[24~': key.name = 'f12'; break; /* xterm ESC [ letter */ case '[A': key.name = 'up'; break; case '[B': key.name = 'down'; break; case '[C': key.name = 'right'; break; case '[D': key.name = 'left'; break; case '[E': key.name = 'clear'; break; case '[F': key.name = 'end'; break; case '[H': key.name = 'home'; break; /* xterm/gnome ESC O letter */ case 'OA': key.name = 'up'; break; case 'OB': key.name = 'down'; break; case 'OC': key.name = 'right'; break; case 'OD': key.name = 'left'; break; case 'OE': key.name = 'clear'; break; case 'OF': key.name = 'end'; break; case 'OH': key.name = 'home'; break; /* xterm/rxvt ESC [ number ~ */ case '[1~': key.name = 'home'; break; case '[2~': key.name = 'insert'; break; case '[3~': key.name = 'delete'; break; case '[4~': key.name = 'end'; break; case '[5~': key.name = 'pageup'; break; case '[6~': key.name = 'pagedown'; break; /* putty */ case '[[5~': key.name = 'pageup'; break; case '[[6~': key.name = 'pagedown'; break; /* rxvt */ case '[7~': key.name = 'home'; break; case '[8~': key.name = 'end'; break; /* rxvt keys with modifiers */ case '[a': key.name = 'up'; key.shift = true; break; case '[b': key.name = 'down'; key.shift = true; break; case '[c': key.name = 'right'; key.shift = true; break; case '[d': key.name = 'left'; key.shift = true; break; case '[e': key.name = 'clear'; key.shift = true; break; case '[2$': key.name = 'insert'; key.shift = true; break; case '[3$': key.name = 'delete'; key.shift = true; break; case '[5$': key.name = 'pageup'; key.shift = true; break; case '[6$': key.name = 'pagedown'; key.shift = true; break; case '[7$': key.name = 'home'; key.shift = true; break; case '[8$': key.name = 'end'; key.shift = true; break; case 'Oa': key.name = 'up'; key.ctrl = true; break; case 'Ob': key.name = 'down'; key.ctrl = true; break; case 'Oc': key.name = 'right'; key.ctrl = true; break; case 'Od': key.name = 'left'; key.ctrl = true; break; case 'Oe': key.name = 'clear'; key.ctrl = true; break; case '[2^': key.name = 'insert'; key.ctrl = true; break; case '[3^': key.name = 'delete'; key.ctrl = true; break; case '[5^': key.name = 'pageup'; key.ctrl = true; break; case '[6^': key.name = 'pagedown'; key.ctrl = true; break; case '[7^': key.name = 'home'; key.ctrl = true; break; case '[8^': key.name = 'end'; key.ctrl = true; break; /* misc. */ case '[Z': key.name = 'tab'; key.shift = true; break; default: key.name = 'undefined'; break; } } else if (s.length > 1 && s[0] !== '\x1b') { // Got a longer-than-one string of characters. // Probably a paste, since it wasn't a control sequence. Array.prototype.forEach.call(s, function(c) { emitKey(stream, c); }); return; } // Don't emit a key if no name was found if (key.name === undefined) { key = undefined; } if (s.length === 1) { ch = s; } if (key || ch) { stream.emit('keypress', ch, key); } } /** * moves the cursor to the x and y coordinate on the given stream */ function cursorTo(stream, x, y) { if (typeof x !== 'number' && typeof y !== 'number') return; if (typeof x !== 'number') throw new Error("Can't set cursor row without also setting it's column"); if (typeof y !== 'number') { stream.write('\x1b[' + (x + 1) + 'G'); } else { stream.write('\x1b[' + (y + 1) + ';' + (x + 1) + 'H'); } } exports.cursorTo = cursorTo; /** * moves the cursor relative to its current location */ function moveCursor(stream, dx, dy) { if (dx < 0) { stream.write('\x1b[' + (-dx) + 'D'); } else if (dx > 0) { stream.write('\x1b[' + dx + 'C'); } if (dy < 0) { stream.write('\x1b[' + (-dy) + 'A'); } else if (dy > 0) { stream.write('\x1b[' + dy + 'B'); } } exports.moveCursor = moveCursor; /** * clears the current line the cursor is on: * -1 for left of the cursor * +1 for right of the cursor * 0 for the entire line */ function clearLine(stream, dir) { if (dir < 0) { // to the beginning stream.write('\x1b[1K'); } else if (dir > 0) { // to the end stream.write('\x1b[0K'); } else { // entire line stream.write('\x1b[2K'); } } exports.clearLine = clearLine; /** * clears the screen from the current position of the cursor down */ function clearScreenDown(stream) { stream.write('\x1b[0J'); } exports.clearScreenDown = clearScreenDown; readline// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Query String Utilities var QueryString = exports; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function charCode(c) { return c.charCodeAt(0); } // a safe fast alternative to decodeURIComponent QueryString.unescapeBuffer = function(s, decodeSpaces) { var out = new Buffer(s.length); var state = 'CHAR'; // states: CHAR, HEX0, HEX1 var n, m, hexchar; for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) { var c = s.charCodeAt(inIndex); switch (state) { case 'CHAR': switch (c) { case charCode('%'): n = 0; m = 0; state = 'HEX0'; break; case charCode('+'): if (decodeSpaces) c = charCode(' '); // pass thru default: out[outIndex++] = c; break; } break; case 'HEX0': state = 'HEX1'; hexchar = c; if (charCode('0') <= c && c <= charCode('9')) { n = c - charCode('0'); } else if (charCode('a') <= c && c <= charCode('f')) { n = c - charCode('a') + 10; } else if (charCode('A') <= c && c <= charCode('F')) { n = c - charCode('A') + 10; } else { out[outIndex++] = charCode('%'); out[outIndex++] = c; state = 'CHAR'; break; } break; case 'HEX1': state = 'CHAR'; if (charCode('0') <= c && c <= charCode('9')) { m = c - charCode('0'); } else if (charCode('a') <= c && c <= charCode('f')) { m = c - charCode('a') + 10; } else if (charCode('A') <= c && c <= charCode('F')) { m = c - charCode('A') + 10; } else { out[outIndex++] = charCode('%'); out[outIndex++] = hexchar; out[outIndex++] = c; break; } out[outIndex++] = 16 * n + m; break; } } // TODO support returning arbitrary buffers. return out.slice(0, outIndex - 1); }; QueryString.unescape = function(s, decodeSpaces) { return QueryString.unescapeBuffer(s, decodeSpaces).toString(); }; QueryString.escape = function(str) { return encodeURIComponent(str); }; var stringifyPrimitive = function(v) { switch (typeof v) { case 'string': return v; case 'boolean': return v ? 'true' : 'false'; case 'number': return isFinite(v) ? v : ''; default: return ''; } }; QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) { sep = sep || '&'; eq = eq || '='; if (obj === null) { obj = undefined; } if (typeof obj === 'object') { return Object.keys(obj).map(function(k) { var ks = QueryString.escape(stringifyPrimitive(k)) + eq; if (Array.isArray(obj[k])) { return obj[k].map(function(v) { return ks + QueryString.escape(stringifyPrimitive(v)); }).join(sep); } else { return ks + QueryString.escape(stringifyPrimitive(obj[k])); } }).join(sep); } if (!name) return ''; return QueryString.escape(stringifyPrimitive(name)) + eq + QueryString.escape(stringifyPrimitive(obj)); }; // Parse a key=val string. QueryString.parse = QueryString.decode = function(qs, sep, eq, options) { sep = sep || '&'; eq = eq || '='; var obj = {}; if (typeof qs !== 'string' || qs.length === 0) { return obj; } var regexp = /\+/g; qs = qs.split(sep); var maxKeys = 1000; if (options && typeof options.maxKeys === 'number') { maxKeys = options.maxKeys; } var len = qs.length; // maxKeys <= 0 means that we should not limit keys count if (maxKeys > 0 && len > maxKeys) { len = maxKeys; } for (var i = 0; i < len; ++i) { var x = qs[i].replace(regexp, '%20'), idx = x.indexOf(eq), kstr, vstr, k, v; if (idx >= 0) { kstr = x.substr(0, idx); vstr = x.substr(idx + 1); } else { kstr = x; vstr = ''; } try { k = decodeURIComponent(kstr); v = decodeURIComponent(vstr); } catch (e) { k = QueryString.unescape(kstr, true); v = QueryString.unescape(vstr, true); } if (!hasOwnProperty(obj, k)) { obj[k] = v; } else if (Array.isArray(obj[k])) { obj[k].push(v); } else { obj[k] = [obj[k], v]; } } return obj; }; querystring// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // Microsoft grants you the right to use these script files for the sole purpose of either: (i) interacting through your browser with the Microsoft website, subject to the website's terms of use; or (ii) using the files as included with a Microsoft product subject to that product's license terms. Microsoft reserves all other rights to the files not expressly granted by Microsoft, whether by implication, estoppel or otherwise. The notices and licenses below are for informational purposes only. // Punycode.js // Copyright 2011 Mathias Bynens // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /*! http://mths.be/punycode v1.2.0 by @mathias */ ;(function(root) { /** * The `punycode` object. * @name punycode * @type Object */ var punycode, /** Detect free variables `define`, `exports`, `module` and `require` */ freeDefine = typeof define == 'function' && typeof define.amd == 'object' && define.amd && define, freeExports = typeof exports == 'object' && exports, freeModule = typeof module == 'object' && module, freeRequire = typeof require == 'function' && require, /** Highest positive signed 32-bit float value */ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 /** Bootstring parameters */ base = 36, tMin = 1, tMax = 26, skew = 38, damp = 700, initialBias = 72, initialN = 128, // 0x80 delimiter = '-', // '\x2D' /** Regular expressions */ regexPunycode = /^xn--/, regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators /** Error messages */ errors = { 'overflow': 'Overflow: input needs wider integers to process', 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 'invalid-input': 'Invalid input' }, /** Convenience shortcuts */ baseMinusTMin = base - tMin, floor = Math.floor, stringFromCharCode = String.fromCharCode, /** Temporary variable */ key; /*--------------------------------------------------------------------------*/ /** * A generic error utility function. * @private * @param {String} type The error type. * @returns {Error} Throws a `RangeError` with the applicable error message. */ function error(type) { throw RangeError(errors[type]); } /** * A generic `Array#map` utility function. * @private * @param {Array} array The array to iterate over. * @param {Function} callback The function that gets called for every array * item. * @returns {Array} A new array of values returned by the callback function. */ function map(array, fn) { var length = array.length; while (length--) { array[length] = fn(array[length]); } return array; } /** * A simple `Array#map`-like wrapper to work with domain name strings. * @private * @param {String} domain The domain name. * @param {Function} callback The function that gets called for every * character. * @returns {Array} A new string of characters returned by the callback * function. */ function mapDomain(string, fn) { return map(string.split(regexSeparators), fn).join('.'); } /** * Creates an array containing the decimal code points of each Unicode * character in the string. While JavaScript uses UCS-2 internally, * this function will convert a pair of surrogate halves (each of which * UCS-2 exposes as separate characters) into a single code point, * matching UTF-16. * @see `punycode.ucs2.encode` * @see * @memberOf punycode.ucs2 * @name decode * @param {String} string The Unicode input string (UCS-2). * @returns {Array} The new array of code points. */ function ucs2decode(string) { var output = [], counter = 0, length = string.length, value, extra; while (counter < length) { value = string.charCodeAt(counter++); if ((value & 0xF800) == 0xD800 && counter < length) { // high surrogate, and there is a next character extra = string.charCodeAt(counter++); if ((extra & 0xFC00) == 0xDC00) { // low surrogate output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); } else { output.push(value, extra); } } else { output.push(value); } } return output; } /** * Creates a string based on an array of decimal code points. * @see `punycode.ucs2.decode` * @memberOf punycode.ucs2 * @name encode * @param {Array} codePoints The array of decimal code points. * @returns {String} The new Unicode string (UCS-2). */ function ucs2encode(array) { return map(array, function(value) { var output = ''; if (value > 0xFFFF) { value -= 0x10000; output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); value = 0xDC00 | value & 0x3FF; } output += stringFromCharCode(value); return output; }).join(''); } /** * Converts a basic code point into a digit/integer. * @see `digitToBasic()` * @private * @param {Number} codePoint The basic (decimal) code point. * @returns {Number} The numeric value of a basic code point (for use in * representing integers) in the range `0` to `base - 1`, or `base` if * the code point does not represent a value. */ function basicToDigit(codePoint) { return codePoint - 48 < 10 ? codePoint - 22 : codePoint - 65 < 26 ? codePoint - 65 : codePoint - 97 < 26 ? codePoint - 97 : base; } /** * Converts a digit/integer into a basic code point. * @see `basicToDigit()` * @private * @param {Number} digit The numeric value of a basic code point. * @returns {Number} The basic code point whose value (when used for * representing integers) is `digit`, which needs to be in the range * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is * used; else, the lowercase form is used. The behavior is undefined * if flag is non-zero and `digit` has no uppercase form. */ function digitToBasic(digit, flag) { // 0..25 map to ASCII a..z or A..Z // 26..35 map to ASCII 0..9 return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); } /** * Bias adaptation function as per section 3.4 of RFC 3492. * http://tools.ietf.org/html/rfc3492#section-3.4 * @private */ function adapt(delta, numPoints, firstTime) { var k = 0; delta = firstTime ? floor(delta / damp) : delta >> 1; delta += floor(delta / numPoints); for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { delta = floor(delta / baseMinusTMin); } return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); } /** * Converts a basic code point to lowercase if `flag` is falsy, or to * uppercase if `flag` is truthy. The code point is unchanged if it's * caseless. The behavior is undefined if `codePoint` is not a basic code * point. * @private * @param {Number} codePoint The numeric value of a basic code point. * @returns {Number} The resulting basic code point. */ function encodeBasic(codePoint, flag) { codePoint -= (codePoint - 97 < 26) << 5; return codePoint + (!flag && codePoint - 65 < 26) << 5; } /** * Converts a Punycode string of ASCII code points to a string of Unicode * code points. * @memberOf punycode * @param {String} input The Punycode string of ASCII code points. * @returns {String} The resulting string of Unicode code points. */ function decode(input) { // Don't use UCS-2 var output = [], inputLength = input.length, out, i = 0, n = initialN, bias = initialBias, basic, j, index, oldi, w, k, digit, t, length, /** Cached calculation results */ baseMinusT; // Handle the basic code points: let `basic` be the number of input code // points before the last delimiter, or `0` if there is none, then copy // the first basic code points to the output. basic = input.lastIndexOf(delimiter); if (basic < 0) { basic = 0; } for (j = 0; j < basic; ++j) { // if it's not a basic code point if (input.charCodeAt(j) >= 0x80) { error('not-basic'); } output.push(input.charCodeAt(j)); } // Main decoding loop: start just after the last delimiter if any basic code // points were copied; start at the beginning otherwise. for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { // `index` is the index of the next character to be consumed. // Decode a generalized variable-length integer into `delta`, // which gets added to `i`. The overflow checking is easier // if we increase `i` as we go, then subtract off its starting // value at the end to obtain `delta`. for (oldi = i, w = 1, k = base; /* no condition */; k += base) { if (index >= inputLength) { error('invalid-input'); } digit = basicToDigit(input.charCodeAt(index++)); if (digit >= base || digit > floor((maxInt - i) / w)) { error('overflow'); } i += digit * w; t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (digit < t) { break; } baseMinusT = base - t; if (w > floor(maxInt / baseMinusT)) { error('overflow'); } w *= baseMinusT; } out = output.length + 1; bias = adapt(i - oldi, out, oldi == 0); // `i` was supposed to wrap around from `out` to `0`, // incrementing `n` each time, so we'll fix that now: if (floor(i / out) > maxInt - n) { error('overflow'); } n += floor(i / out); i %= out; // Insert `n` at position `i` of the output output.splice(i++, 0, n); } return ucs2encode(output); } /** * Converts a string of Unicode code points to a Punycode string of ASCII * code points. * @memberOf punycode * @param {String} input The string of Unicode code points. * @returns {String} The resulting Punycode string of ASCII code points. */ function encode(input) { var n, delta, handledCPCount, basicLength, bias, j, m, q, k, t, currentValue, output = [], /** `inputLength` will hold the number of code points in `input`. */ inputLength, /** Cached calculation results */ handledCPCountPlusOne, baseMinusT, qMinusT; // Convert the input in UCS-2 to Unicode input = ucs2decode(input); // Cache the length inputLength = input.length; // Initialize the state n = initialN; delta = 0; bias = initialBias; // Handle the basic code points for (j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue < 0x80) { output.push(stringFromCharCode(currentValue)); } } handledCPCount = basicLength = output.length; // `handledCPCount` is the number of code points that have been handled; // `basicLength` is the number of basic code points. // Finish the basic string - if it is not empty - with a delimiter if (basicLength) { output.push(delimiter); } // Main encoding loop: while (handledCPCount < inputLength) { // All non-basic code points < n have been handled already. Find the next // larger one: for (m = maxInt, j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue >= n && currentValue < m) { m = currentValue; } } // Increase `delta` enough to advance the decoder's state to , // but guard against overflow handledCPCountPlusOne = handledCPCount + 1; if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { error('overflow'); } delta += (m - n) * handledCPCountPlusOne; n = m; for (j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue < n && ++delta > maxInt) { error('overflow'); } if (currentValue == n) { // Represent delta as a generalized variable-length integer for (q = delta, k = base; /* no condition */; k += base) { t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (q < t) { break; } qMinusT = q - t; baseMinusT = base - t; output.push( stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) ); q = floor(qMinusT / baseMinusT); } output.push(stringFromCharCode(digitToBasic(q, 0))); bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); delta = 0; ++handledCPCount; } } ++delta; ++n; } return output.join(''); } /** * Converts a Punycode string representing a domain name to Unicode. Only the * Punycoded parts of the domain name will be converted, i.e. it doesn't * matter if you call it on a string that has already been converted to * Unicode. * @memberOf punycode * @param {String} domain The Punycode domain name to convert to Unicode. * @returns {String} The Unicode representation of the given Punycode * string. */ function toUnicode(domain) { return mapDomain(domain, function(string) { return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string; }); } /** * Converts a Unicode string representing a domain name to Punycode. Only the * non-ASCII parts of the domain name will be converted, i.e. it doesn't * matter if you call it with a domain that's already in ASCII. * @memberOf punycode * @param {String} domain The domain name to convert, as a Unicode string. * @returns {String} The Punycode representation of the given domain name. */ function toASCII(domain) { return mapDomain(domain, function(string) { return regexNonASCII.test(string) ? 'xn--' + encode(string) : string; }); } /*--------------------------------------------------------------------------*/ /** Define the public API */ punycode = { /** * A string representing the current Punycode.js version number. * @memberOf punycode * @type String */ 'version': '1.2.0', /** * An object of methods to convert from JavaScript's internal character * representation (UCS-2) to decimal Unicode code points, and back. * @see * @memberOf punycode * @type Object */ 'ucs2': { 'decode': ucs2decode, 'encode': ucs2encode }, 'decode': decode, 'encode': encode, 'toASCII': toASCII, 'toUnicode': toUnicode }; /** Expose `punycode` */ if (freeExports) { if (freeModule && freeModule.exports == freeExports) { // in Node.js or Ringo 0.8+ freeModule.exports = punycode; } else { // in Narwhal or Ringo 0.7- for (key in punycode) { punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); } } } else if (freeDefine) { // via curl.js or RequireJS define('punycode', punycode); } else { // in a browser or Rhino root.punycode = punycode; } }(this)); punycode// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var isWindows = process.platform === 'win32'; var util = require('util'); // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } function getDirNameForUNC(path) { if (path.length <= 2) { return path[0]; //return only one slash in that case } //skip slashes at the begining: var i; for (i = 0; i < path.length; ++i) { if(!isCharAtIndexSlash(path, i)) { break; } } var prefix = path.substr(0, i); path = path.substr(i); if (path.indexOf('\\') === -1 && path.indexOf('/') === -1) { //path of type "\\\\server"" return prefix[0]; } //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i > -1; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } if (i === -1) { //path contains only slashes: return prefix[0]; //return one slash. } //loop over the string backwards, until the previoud slash: for (; i >=0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } if (i == -1) { //path of type "\\server\\" return path.substr(0, i); //return slashes at the begining without the first 2. ""///server" -->"/" } var dir = path.substr(0, i); if (dir.indexOf('\\') == -1 && dir.indexOf('/') == -1) { //the path of type "//server/share/" --> retrun with the share return prefix + path; } //in case the path is of type \\\\server\\share\\folder1\\ we need to return \\\server\\share\\ with the slashes at the end //unlike in the case of \\\\server\\share\\folder1\\folder2 we need to return \\\\server\\share\\folder1 without slashes at the end var dir = path.substr(0, i + 1); var foldersCount = 0; for (i = 0; i < dir.length ; i++) { if (!isCharAtIndexSlash(dir, i)) { foldersCount++; while (!isCharAtIndexSlash(dir, i)) { i++; } } } if (foldersCount > 2) { //need to remove slashes at the end for (i = dir.length - 1; isCharAtIndexSlash(dir, i); --i); dir = dir.substr(0, i + 1); } return prefix + dir; } function getDirNameForPartialPath(path) { var prefix; //path of type "../foo/bar" if ((path.length > 2) && (path[0] === '.') && (path[1] === '.') && isCharAtIndexSlash(path, 2)) { prefix = path.substr(0, 3); path = path.substr(3); } //path of type "./foo/bar" or "..foo/bar" else if (((path[0] === '.') && isCharAtIndexSlash(path, 1)) || (path[0] === '.') && (path[1] === '.')) { prefix = path.substr(0, 2); path = path.substr(2); } //path of type ".foo/bar" or "/foo/bar" else if ((path[0] === '.') || (isCharAtIndexSlash(path, 0) && !isCharAtIndexSlash(path, 1))) { prefix = path.substr(0, 1); path = path.substr(1); } else { return '.'; } //if we got here, path is of type "foo/bar/baz..." var i; //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i >= 0; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } //loop over the string backwards, to remove the current folder from the path: for (; i >= 0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } //remove one slash at the end if there's any. //make sure not to remove the first slash in case prefix is empty if (isCharAtIndexSlash(path, i + 1)) { --i; } //actually remove the tail and return the dir: path = path.substr(0, i); //in case path is empty if prefix was "../" needs to return "./", if prefix was "./" needs to return "." if ((path.length == 0) && (prefix.length > 1)) { prefix = prefix.substr(0, prefix.length - 1); } if (prefix) { return prefix + path; } return path; } function getDirNameForDrive(path) { if ((path.length === 2) && (path.charAt(1) === ':')) { return path; } var prefix; if (path.length > 2 && (path.charAt(1) === ':')) { //there's a suffix to the drive name: var endOfDriveInd = isCharAtIndexSlash(path, 2) ? 3 : 2; prefix = path.substr(0, endOfDriveInd); //only the drive name path = path.substr(endOfDriveInd); } else { return '.'; } if (path.indexOf('\\') === -1 && path.indexOf('/') === -1) { //path of type "c:\\file" // return only the drive return prefix; } var i; //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i >=0; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } if (i == -1) { //path contains only slashes: return prefix; //return only the drive } //loop over the string backwards, to remove the current folder from the path: for (; i >=0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } //remove one slash at the end if there's any: if(isCharAtIndexSlash(path, i)) { --i; } //actually remove the tail and return the dir: path = path.substr(0, i + 1); return prefix + path; } function isCharAtIndexSlash(path, index) { return (path.charAt(index) === '/' || path.charAt(index) === '\\'); } // receives path and returns the file name without slashes: function getFileNameFromPath(path) { path = getTailStrFromPathHelper('/', path); path = getTailStrFromPathHelper('\\', path); return path; } //returns the last string in path after the last given delimiter: function getTailStrFromPathHelper(delimiter, path) { if (path.lastIndexOf(delimiter) != -1) { path = path.split(delimiter); var i; for (i = path.length -1; i >=0; --i) { if(path[i] != '' && path[i] != '\\' && path[i] != '/') { break; } } path = path.slice(0, i + 1); return path[i]; } return path; } if (isWindows) { // Regex to split a windows path into three parts: [*, device, slash, // tail] windows-only var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; // Regex to split the tail part of the above into [*, dir, basename, ext] var splitTailRe = /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; // Function to split a filename into [root, dir, basename, ext] // windows version var splitPath = function(filename) { // Separate device+slash from tail var result = splitDeviceRe.exec(filename), device = (result[1] || '') + (result[2] || ''), tail = result[3] || ''; // Split the tail into dir, basename and extension var result2 = splitTailRe.exec(tail), dir = result2[1], basename = result2[2], ext = result2[3]; return [device, dir, basename, ext]; }; var normalizeUNCRoot = function(device) { return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); }; // path.resolve([from ...], to) // windows version exports.resolve = function() { var resolvedDevice = '', resolvedTail = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1; i--) { var path; if (i >= 0) { path = arguments[i]; } else if (!resolvedDevice) { path = process.cwd(); } else { // Windows has the concept of drive-specific current working // directories. If we've resolved a drive letter but not yet an // absolute path, get cwd for that drive. We're sure the device is not // an unc path at this points, because unc paths are always absolute. path = process.env['=' + resolvedDevice]; // Verify that a drive-local cwd was found and that it actually points // to our drive. If not, default to the drive's root. if (!path || path.substr(0, 3).toLowerCase() !== resolvedDevice.toLowerCase() + '\\') { path = resolvedDevice + '\\'; } } // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } var result = splitDeviceRe.exec(path), device = result[1] || '', isUnc = device && device.charAt(1) !== ':', isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute tail = result[3]; if (device && resolvedDevice && device.toLowerCase() !== resolvedDevice.toLowerCase()) { // This path points to another device so it is not applicable continue; } if (!resolvedDevice) { resolvedDevice = device; } if (!resolvedAbsolute) { resolvedTail = tail + '\\' + resolvedTail; resolvedAbsolute = isAbsolute; } if (resolvedDevice && resolvedAbsolute) { break; } } // Convert slashes to backslashes when `resolvedDevice` points to an UNC // root. Also squash multiple slashes into a single one where appropriate. if (isUnc) { resolvedDevice = normalizeUNCRoot(resolvedDevice); } // At this point the path should be resolved to a full absolute path, // but handle relative paths to be safe (might happen when process.cwd() // fails) // Normalize the tail path function f(p) { return !!p; } resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/).filter(f), !resolvedAbsolute).join('\\'); return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || '.'; }; // windows version exports.normalize = function(path) { var result = splitDeviceRe.exec(path), device = result[1] || '', isUnc = device && device.charAt(1) !== ':', isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute tail = result[3], trailingSlash = /[\\\/]$/.test(tail); // Normalize the tail path tail = normalizeArray(tail.split(/[\\\/]+/).filter(function(p) { return !!p; }), !isAbsolute).join('\\'); if (!tail && !isAbsolute) { tail = '.'; } if (tail && trailingSlash) { tail += '\\'; } // Convert slashes to backslashes when `device` points to an UNC root. // Also squash multiple slashes into a single one where appropriate. if (isUnc) { device = normalizeUNCRoot(device); } return device + (isAbsolute ? '\\' : '') + tail; }; // windows version exports.join = function() { function f(p) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; } var paths = Array.prototype.filter.call(arguments, f); var joined = paths.join('\\'); // Make sure that the joined path doesn't start with two slashes, because // normalize() will mistake it for an UNC path then. // // This step is skipped when it is very clear that the user actually // intended to point at an UNC path. This is assumed when the first // non-empty string arguments starts with exactly two slashes followed by // at least one more non-slash character. // // Note that for normalize() to treat a path as an UNC path it needs to // have at least 2 components, so we don't filter for that here. // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: // path.join('//server', 'share') -> '\\\\server\\share\') if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { joined = joined.replace(/^[\\\/]{2,}/, '\\'); } return exports.normalize(joined); }; // path.relative(from, to) // it will solve the relative path from 'from' to 'to', for instance: // from = 'C:\\orandea\\test\\aaa' // to = 'C:\\orandea\\impl\\bbb' // The output of the function should be: '..\\..\\impl\\bbb' // windows version exports.relative = function(from, to) { from = exports.resolve(from); to = exports.resolve(to); // windows is not case sensitive var lowerFrom = from.toLowerCase(); var lowerTo = to.toLowerCase(); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var toParts = trim(to.split('\\')); var lowerFromParts = trim(lowerFrom.split('\\')); var lowerToParts = trim(lowerTo.split('\\')); var length = Math.min(lowerFromParts.length, lowerToParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (lowerFromParts[i] !== lowerToParts[i]) { samePartsLength = i; break; } } if (samePartsLength == 0) { return to; } var outputParts = []; for (var i = samePartsLength; i < lowerFromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('\\'); }; exports.sep = '\\'; exports.delimiter = ';'; } else /* posix */ { // Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = path.charAt(0) === '/', trailingSlash = path.substr(-1) === '/'; // Normalize the path path = normalizeArray(path.split('/').filter(function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(paths.filter(function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; // path.relative(from, to) // posix version exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.sep = '/'; exports.delimiter = ':'; } exports.dirname = function(path) { if (!isWindows) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { // No dirname whatsoever return '.'; } if (dir) { // It has a dirname, strip trailing slash dir = dir.substr(0, dir.length - 1); } return root + dir; } //code below changed from original Node // 1. handle the case of path.length = 1. if (path.length === 1) { if (isCharAtIndexSlash(path, 0)) { return path; } else { return '.'; } } // 2. handle the case of local drive: d:\\aa\\bb var firstChar = path.charAt(0); if ((firstChar <= 'Z' && firstChar >= 'A') || (firstChar <= 'z' && firstChar >= 'a')){ return getDirNameForDrive(path); } if (path.length > 1) { // 3. handle the case of UNC: \\\\server\\share\\folder if (isCharAtIndexSlash(path, 0) && isCharAtIndexSlash(path, 1)) { return getDirNameForUNC(path); } // 3. handle the case of partial path: /aa/bb/cc return getDirNameForPartialPath(path); } // 5. no dir return '.'; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { //code changed from original Node if (!isWindows) { return splitPath(path)[3]; } path = getFileNameFromPath(path); var indDot = path.lastIndexOf('.'); path = (0 >= indDot) || (path === '..') ? '' : path.substr(indDot); return path; }; exports.exists = util.deprecate(function(path, callback) { require('fs').exists(path, callback); }, 'path.exists is now called `fs.exists`.'); exports.existsSync = util.deprecate(function(path) { return require('fs').existsSync(path); }, 'path.existsSync is now called `fs.existsSync`.'); if (isWindows) { exports._makeLong = function(path) { // Note: this will *probably* throw somewhere. if (typeof path !== 'string') return path; if (!path) { return ''; } var resolvedPath = exports.resolve(path); if (/^[a-zA-Z]\:\\/.test(resolvedPath)) { // path is local filesystem path, which needs to be converted // to long UNC path. return '\\\\?\\' + resolvedPath; } else if (/^\\\\[^?.]/.test(resolvedPath)) { // path is network UNC path, which needs to be converted // to long UNC path. return '\\\\?\\UNC\\' + resolvedPath.substring(2); } return path; }; } else { exports._makeLong = function(path) { return path; }; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var binding = process.binding('os'); var util = require('util'); exports.endianness = binding.getEndianness; exports.hostname = binding.getHostname; exports.loadavg = binding.getLoadAvg; exports.uptime = binding.getUptime; exports.freemem = binding.getFreeMem; exports.totalmem = binding.getTotalMem; exports.cpus = binding.getCPUs; exports.type = binding.getOSType; exports.release = binding.getOSRelease; exports.networkInterfaces = binding.getInterfaceAddresses; exports.arch = function() { return process.arch; }; exports.platform = function() { return process.platform; }; exports.tmpdir = function() { return process.env.TMPDIR || process.env.TMP || process.env.TEMP || (process.platform === 'win32' ? 'c:\\windows\\temp' : '/tmp'); }; exports.tmpDir = exports.tmpdir; exports.getNetworkInterfaces = util.deprecate(function() { return exports.networkInterfaces(); }, 'getNetworkInterfaces is now called `os.networkInterfaces`.'); exports.EOL = process.platform === 'win32' ? '\r\n' : '\n'; os// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Hello, and welcome to hacking node.js! // // This file is invoked by node::Load in src/node.cc, and responsible for // bootstrapping the node.js core. Special caution is given to the performance // of the startup process, so many dependencies are invoked lazily. (function(process) { this.global = this; function startup() { var EventEmitter = NativeModule.require('events').EventEmitter; process.__proto__ = Object.create(EventEmitter.prototype, { constructor: { value: process.constructor } }); EventEmitter.call(process); process.EventEmitter = EventEmitter; // process.EventEmitter is deprecated // do this good and early, since it handles errors. startup.processFatal(); startup.globalVariables(); startup.globalTimeouts(); startup.globalConsole(); startup.processAssert(); startup.processConfig(); startup.processNextTick(); startup.processStdio(); startup.processKillAndExit(); startup.processSignalHandlers(); startup.processChannel(); startup.resolveArgv0(); if (NativeModule.exists('_third_party_patch')) { // allow third parties to patch node before any script loading is done NativeModule.require('_third_party_patch'); } // if node is using chakra // load the chakra patch module in order to fix some known issues // caused by incompatbility of chakra and v8 if (process.ischakra) { if (NativeModule.exists('_chakra_patch')) { NativeModule.require('_chakra_patch'); } } // There are various modes that Node can run in. The most common two // are running from a script and running the REPL - but there are a few // others like the debugger or running --eval arguments. Here we decide // which mode we run in. if (NativeModule.exists('_third_party_main')) { // To allow people to extend Node in different ways, this hook allows // one to drop a file lib/_third_party_main.js into the build // directory which will be executed instead of Node's normal loading. process.nextTick(function() { NativeModule.require('_third_party_main'); }); } else if (process.argv[1] == 'debug') { // Start the debugger agent var d = NativeModule.require('_debugger'); d.start(); } else if (process._eval != null) { // User passed '-e' or '--eval' arguments to Node. evalScript('[eval]'); } else if (process.argv[1]) { // make process.argv[1] into a full path var path = NativeModule.require('path'); process.argv[1] = path.resolve(process.argv[1]); // If this is a worker in cluster mode, start up the communiction // channel. if (process.env.NODE_UNIQUE_ID) { var cluster = NativeModule.require('cluster'); cluster._setupWorker(); // Make sure it's not accidentally inherited by child processes. delete process.env.NODE_UNIQUE_ID; } var Module; if (!process.ischakra) { Module = NativeModule.require('module'); } if (global.v8debug && process.execArgv.some(function(arg) { return arg.match(/^--debug-brk(=[0-9]*)?$/); })) { Module = Module || NativeModule.require('module'); // XXX Fix this terrible hack! // // Give the client program a few ticks to connect. // Otherwise, there's a race condition where `node debug foo.js` // will not be able to connect in time to catch the first // breakpoint message on line 1. // // A better fix would be to somehow get a message from the // global.v8debug object about a connection, and runMain when // that occurs. --isaacs var debugTimeout = +process.env.NODE_DEBUG_TIMEOUT || 50; setTimeout(Module.runMain, debugTimeout); } else { // Main entry point into most programs: if (process.ischakra) { Module = NativeModule.require('nativerequire'); } else { Module = NativeModule.require('module'); } Module.runMain(); } } else { // use regular Module for REPL var Module = Module || NativeModule.require('module'); // If -i or --interactive were passed, or stdin is a TTY. if (process._forceRepl || NativeModule.require('tty').isatty(0)) { // REPL var opts = { useGlobal: true, ignoreUndefined: false }; if (parseInt(process.env['NODE_NO_READLINE'], 10)) { opts.terminal = false; } if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { opts.useColors = false; } var repl = Module.requireRepl().start(opts); repl.on('exit', function() { process.exit(); }); } else { // Read all of stdin - execute it. process.stdin.setEncoding('utf8'); var code = ''; process.stdin.on('data', function(d) { code += d; }); process.stdin.on('end', function() { process._eval = code; evalScript('[stdin]'); }); } } } startup.globalVariables = function() { global.process = process; global.global = global; global.GLOBAL = global; global.root = global; global.Buffer = NativeModule.require('buffer').Buffer; process.binding('buffer').setFastBufferConstructor(global.Buffer); process.domain = null; process._exiting = false; // exposing the external events emitter: // the event emitter will be used to fire events from external sources var events = NativeModule.require('events'); global.externalEvents = new events.EventEmitter(); }; startup.globalTimeouts = function() { global.setTimeout = function() { var t = NativeModule.require('timers'); return t.setTimeout.apply(this, arguments); }; global.setInterval = function() { var t = NativeModule.require('timers'); return t.setInterval.apply(this, arguments); }; global.clearTimeout = function() { var t = NativeModule.require('timers'); return t.clearTimeout.apply(this, arguments); }; global.clearInterval = function() { var t = NativeModule.require('timers'); return t.clearInterval.apply(this, arguments); }; global.setImmediate = function() { var t = NativeModule.require('timers'); return t.setImmediate.apply(this, arguments); }; global.clearImmediate = function() { var t = NativeModule.require('timers'); return t.clearImmediate.apply(this, arguments); }; }; startup.globalConsole = function() { var emptyConsole = { log: function() { }, debug: function() { }, info: function() { }, warn: function() { }, warning: function() { }, error: function() { }, }; global.__defineGetter__('console', function() { if (process.ischakra && process.noconsole) { return emptyConsole; } else { return NativeModule.require('console'); } }); }; startup._lazyConstants = null; startup.lazyConstants = function() { if (!startup._lazyConstants) { startup._lazyConstants = process.binding('constants'); } return startup._lazyConstants; }; startup.processFatal = function() { // call into the active domain, or emit uncaughtException, // and exit if there are no listeners. process._fatalException = function(er) { var caught = false; if (process.domain) { var domain = process.domain; var domainModule = NativeModule.require('domain'); var domainStack = domainModule._stack; // ignore errors on disposed domains. // // XXX This is a bit stupid. We should probably get rid of // domain.dispose() altogether. It's almost always a terrible // idea. --isaacs if (domain._disposed) return true; er.domain = domain; er.domainThrown = true; // wrap this in a try/catch so we don't get infinite throwing try { // One of three things will happen here. // // 1. There is a handler, caught = true // 2. There is no handler, caught = false // 3. It throws, caught = false // // If caught is false after this, then there's no need to exit() // the domain, because we're going to crash the process anyway. caught = domain.emit('error', er); // Exit all domains on the stack. Uncaught exceptions end the // current tick and no domains should be left on the stack // between ticks. var domainModule = NativeModule.require('domain'); domainStack.length = 0; domainModule.active = process.domain = null; } catch (er2) { // The domain error handler threw! oh no! // See if another domain can catch THIS error, // or else crash on the original one. // If the user already exited it, then don't double-exit. if (domain === domainModule.active) domainStack.pop(); if (domainStack.length) { var parentDomain = domainStack[domainStack.length - 1]; process.domain = domainModule.active = parentDomain; caught = process._fatalException(er2); } else caught = false; } } else { caught = process.emit('uncaughtException', er); } // if someone handled it, then great. otherwise, die in C++ land // since that means that we'll exit the process, emit the 'exit' event if (!caught) { try { if (!process._exiting) { process._exiting = true; process.emit('exit', 1); } } catch (er) { // nothing to be done about it at this point. } } // if we handled an error, then make sure any ticks get processed if (caught) process._needTickCallback(); return caught; }; }; var assert; startup.processAssert = function() { // Note that calls to assert() are pre-processed out by JS2C for the // normal build of node. They persist only in the node_g build. // Similarly for debug(). assert = process.assert = function(x, msg) { if (!x) throw new Error(msg || 'assertion error'); }; }; startup.processConfig = function () { // used for `process.config`, but not a real module if (process.ischakra) { Object.defineProperty(process, 'config', { get: function () { throw new Error('process.config is removed due to optimizations, please do not use.'); } }); return; } var config = NativeModule._source.config; delete NativeModule._source.config; // strip the gyp comment line at the beginning config = config.split('\n').slice(1).join('\n').replace(/'/g, '"'); process.config = JSON.parse(config, function(key, value) { if (value === 'true') return true; if (value === 'false') return false; return value; }); }; startup.processNextTick = function() { var _needTickCallback = process._needTickCallback; var nextTickQueue = []; var needSpinner = true; var inTick = false; // this infobox thing is used so that the C++ code in src/node.cc // can have easy accesss to our nextTick state, and avoid unnecessary // calls into process._tickCallback. // order is [length, index, depth] // Never write code like this without very good reason! var infoBox = process._tickInfoBox; var length = 0; var index = 1; var depth = 2; process.nextTick = nextTick; // needs to be accessible from cc land process._nextDomainTick = _nextDomainTick; process._tickCallback = _tickCallback; process._tickDomainCallback = _tickDomainCallback; process._tickFromSpinner = _tickFromSpinner; // the maximum number of times it'll process something like // nextTick(function f(){nextTick(f)}) // It's unlikely, but not illegal, to hit this limit. When // that happens, it yields to libuv's tick spinner. // This is a loop counter, not a stack depth, so we aren't using // up lots of memory here. I/O can sneak in before nextTick if this // limit is hit, which is not ideal, but not terrible. process.maxTickDepth = 1000; function tickDone(tickDepth_) { if (infoBox[length] !== 0) { if (infoBox[length] <= infoBox[index]) { nextTickQueue = []; infoBox[length] = 0; } else { nextTickQueue.splice(0, infoBox[index]); infoBox[length] = nextTickQueue.length; if (needSpinner) { _needTickCallback(); needSpinner = false; } } } inTick = false; infoBox[index] = 0; infoBox[depth] = tickDepth_; } function maxTickWarn() { // XXX Remove all this maxTickDepth stuff in 0.11 var msg = '(node) warning: Recursive process.nextTick detected. ' + 'This will break in the next version of node. ' + 'Please use setImmediate for recursive deferral.'; if (process.throwDeprecation) throw new Error(msg); else if (process.traceDeprecation) console.trace(msg); else console.error(msg); } function _tickFromSpinner() { needSpinner = true; // coming from spinner, reset! if (infoBox[depth] !== 0) infoBox[depth] = 0; // no callbacks to run if (infoBox[length] === 0) return infoBox[index] = infoBox[depth] = 0; process._tickCallback(); } // run callbacks that have no domain // using domains will cause this to be overridden function _tickCallback() { var callback, nextTickLength, threw; if (inTick) return; if (infoBox[length] === 0) { infoBox[index] = 0; infoBox[depth] = 0; return; } inTick = true; while (infoBox[depth]++ < process.maxTickDepth) { nextTickLength = infoBox[length]; if (infoBox[index] === nextTickLength) return tickDone(0); while (infoBox[index] < nextTickLength) { callback = nextTickQueue[infoBox[index]++].callback; threw = true; try { callback(); threw = false; } finally { if (threw) tickDone(infoBox[depth]); } } } tickDone(0); } function _tickDomainCallback() { var nextTickLength, tock, callback, threw; // if you add a nextTick in a domain's error handler, then // it's possible to cycle indefinitely. Normally, the tickDone // in the finally{} block below will prevent this, however if // that error handler ALSO triggers multiple MakeCallbacks, then // it'll try to keep clearing the queue, since the finally block // fires *before* the error hits the top level and is handled. if (infoBox[depth] >= process.maxTickDepth) return _needTickCallback(); if (inTick) return; inTick = true; // always do this at least once. otherwise if process.maxTickDepth // is set to some negative value, or if there were repeated errors // preventing depth from being cleared, we'd never process any // of them. while (infoBox[depth]++ < process.maxTickDepth) { nextTickLength = infoBox[length]; if (infoBox[index] === nextTickLength) return tickDone(0); while (infoBox[index] < nextTickLength) { tock = nextTickQueue[infoBox[index]++]; callback = tock.callback; if (tock.domain) { if (tock.domain._disposed) continue; tock.domain.enter(); } threw = true; try { callback(); threw = false; } finally { // finally blocks fire before the error hits the top level, // so we can't clear the depth at this point. if (threw) tickDone(infoBox[depth]); } if (tock.domain) { tock.domain.exit(); } } } tickDone(0); } function nextTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) return; if (infoBox[depth] >= process.maxTickDepth) maxTickWarn(); var obj = { callback: callback, domain: null }; nextTickQueue.push(obj); infoBox[length]++; if (needSpinner) { _needTickCallback(); needSpinner = false; } } function _nextDomainTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) return; if (infoBox[depth] >= process.maxTickDepth) maxTickWarn(); var obj = { callback: callback, domain: process.domain }; nextTickQueue.push(obj); infoBox[length]++; if (needSpinner) { _needTickCallback(); needSpinner = false; } } }; function evalScript(name) { var Module = NativeModule.require('module'); var path = NativeModule.require('path'); var cwd = process.cwd(); var module = new Module(name); module.filename = path.join(cwd, name); module.paths = Module._nodeModulePaths(cwd); var script = process._eval; if (!Module._contextLoad) { var body = script; script = 'global.__filename = ' + JSON.stringify(name) + ';\n' + 'global.exports = exports;\n' + 'global.module = module;\n' + 'global.__dirname = __dirname;\n' + 'global.require = require;\n' + 'return require("vm").runInThisContext(' + JSON.stringify(body) + ', ' + JSON.stringify(name) + ', true);\n'; } var result = module._compile(script, name + '-wrapper'); if (process._print_eval) console.log(result); } function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function createWritableStdioStream(fd) { var stream; var tty_wrap = process.binding('tty_wrap'); // Note stream._type is used for test-module-load-list.js switch (tty_wrap.guessHandleType(fd)) { case 'TTY': var tty = NativeModule.require('tty'); stream = new tty.WriteStream(fd); stream._type = 'tty'; // Hack to have stream not keep the event loop alive. // See https://github.com/joyent/node/issues/1726 if (stream._handle && stream._handle.unref) { stream._handle.unref(); } break; case 'FILE': var fs = NativeModule.require('fs'); stream = new fs.SyncWriteStream(fd); stream._type = 'fs'; break; case 'PIPE': case 'TCP': var net = NativeModule.require('net'); stream = new net.Socket({ fd: fd, readable: false, writable: true }); // FIXME Should probably have an option in net.Socket to create a // stream from an existing fd which is writable only. But for now // we'll just add this hack and set the `readable` member to false. // Test: ./node test/fixtures/echo.js < /etc/passwd stream.readable = false; stream.read = null; stream._type = 'pipe'; // FIXME Hack to have stream not keep the event loop alive. // See https://github.com/joyent/node/issues/1726 if (stream._handle && stream._handle.unref) { stream._handle.unref(); } break; default: // Probably an error on in uv_guess_handle() throw new Error('Implement me. Unknown stream file type!'); } // For supporting legacy API we put the FD here. stream.fd = fd; stream._isStdio = true; return stream; } startup.processStdio = function() { var stdin, stdout, stderr; // TODO: we might want also to add a specific switch for this? if (process.ischakra && process.noconsole) { stdin = { id : '__mock_stdin', write: function() { }, read: function() { }, pipe: function() { } } stdout = { id: '__mock_stdout', write: function() { }, read: function() { }, pipe: function() { } } stderr = { id: '__mock_stderr', write: function() { }, read: function() { }, pipe: function() { } } } process.__defineGetter__('stdout', function() { if (stdout) return stdout; stdout = createWritableStdioStream(1); stdout.destroy = stdout.destroySoon = function(er) { er = er || new Error('process.stdout cannot be closed.'); stdout.emit('error', er); }; if (stdout.isTTY) { process.on('SIGWINCH', function() { stdout._refreshSize(); }); } return stdout; }); process.__defineGetter__('stderr', function() { if (stderr) return stderr; stderr = createWritableStdioStream(2); stderr.destroy = stderr.destroySoon = function(er) { er = er || new Error('process.stderr cannot be closed.'); stderr.emit('error', er); }; return stderr; }); process.__defineGetter__('stdin', function() { if (stdin) return stdin; var tty_wrap = process.binding('tty_wrap'); var fd = 0; switch (tty_wrap.guessHandleType(fd)) { case 'TTY': var tty = NativeModule.require('tty'); stdin = new tty.ReadStream(fd, { highWaterMark: 0, readable: true, writable: false }); break; case 'FILE': var fs = NativeModule.require('fs'); stdin = new fs.ReadStream(null, { fd: fd }); break; case 'PIPE': case 'TCP': var net = NativeModule.require('net'); stdin = new net.Socket({ fd: fd, readable: true, writable: false }); break; default: // Probably an error on in uv_guess_handle() throw new Error('Implement me. Unknown stdin file type!'); } // For supporting legacy API we put the FD here. stdin.fd = fd; // stdin starts out life in a paused state, but node doesn't // know yet. Explicitly to readStop() it to put it in the // not-reading state. if (stdin._handle && stdin._handle.readStop) { stdin._handle.reading = false; stdin._readableState.reading = false; stdin._handle.readStop(); } // if the user calls stdin.pause(), then we need to stop reading // immediately, so that the process can close down. stdin.on('pause', function() { if (!stdin._handle) return; stdin._readableState.reading = false; stdin._handle.reading = false; stdin._handle.readStop(); }); return stdin; }); process.openStdin = function() { process.stdin.resume(); return process.stdin; }; }; startup.processKillAndExit = function() { process.exit = function(code) { if (!process._exiting) { process._exiting = true; process.emit('exit', code || 0); } process.reallyExit(code || 0); }; process.kill = function(pid, sig) { var r; // preserve null signal if (0 === sig) { r = process._kill(pid, 0); } else { sig = sig || 'SIGTERM'; if (startup.lazyConstants()[sig]) { r = process._kill(pid, startup.lazyConstants()[sig]); } else { throw new Error('Unknown signal: ' + sig); } } if (r) { throw errnoException(process._errno, 'kill'); } return true; }; }; startup.processSignalHandlers = function() { // Load events module in order to access prototype elements on process like // process.addListener. var signalWraps = {}; var addListener = process.addListener; var removeListener = process.removeListener; function isSignal(event) { return event.slice(0, 3) === 'SIG' && startup.lazyConstants().hasOwnProperty(event); } // Wrap addListener for the special signal types process.on = process.addListener = function(type, listener) { if (isSignal(type) && !signalWraps.hasOwnProperty(type)) { var Signal = process.binding('signal_wrap').Signal; var wrap = new Signal(); wrap.unref(); wrap.onsignal = function() { process.emit(type); }; var signum = startup.lazyConstants()[type]; var r = wrap.start(signum); if (r) { wrap.close(); throw errnoException(process._errno, 'uv_signal_start'); } signalWraps[type] = wrap; } return addListener.apply(this, arguments); }; process.removeListener = function(type, listener) { var ret = removeListener.apply(this, arguments); if (isSignal(type)) { assert(signalWraps.hasOwnProperty(type)); if (this.listeners(type).length === 0) { signalWraps[type].close(); delete signalWraps[type]; } } return ret; }; }; startup.processChannel = function() { // If we were spawned with env NODE_CHANNEL_FD then load that up and // start parsing data from that stream. if (process.env.NODE_CHANNEL_FD) { var fd = parseInt(process.env.NODE_CHANNEL_FD, 10); assert(fd >= 0); // Make sure it's not accidentally inherited by child processes. delete process.env.NODE_CHANNEL_FD; var cp = NativeModule.require('child_process'); // Load tcp_wrap to avoid situation where we might immediately receive // a message. // FIXME is this really necessary? process.binding('tcp_wrap'); cp._forkChild(fd); assert(process.send); } } startup.resolveArgv0 = function() { var cwd = process.cwd(); var isWindows = process.platform === 'win32'; // Make process.argv[0] into a full path, but only touch argv[0] if it's // not a system $PATH lookup. // TODO: Make this work on Windows as well. Note that "node" might // execute cwd\node.exe, or some %PATH%\node.exe on Windows, // and that every directory has its own cwd, so d:node.exe is valid. var argv0 = process.argv[0]; if (!isWindows && argv0.indexOf('/') !== -1 && argv0.charAt(0) !== '/') { var path = NativeModule.require('path'); process.argv[0] = path.join(cwd, process.argv[0]); } }; // Below you find a minimal module system, which is used to load the node // core modules found in lib/*.js. All core modules are compiled into the // node binary, so they can be loaded faster. var Script = process.binding('evals').NodeScript; var runInThisContext = Script.runInThisContext; function NativeModule(id) { this.filename = id + '.js'; this.id = id; this.exports = {}; this.loaded = false; } NativeModule._source = process.binding('natives'); NativeModule._cache = {}; NativeModule.require = function(id) { if (id == 'native_module') { return NativeModule; } var cached = NativeModule.getCached(id); if (cached) { return cached.exports; } if (!NativeModule.exists(id)) { throw new Error('No such native module ' + id); } process.moduleLoadList.push('NativeModule ' + id); var nativeModule = new NativeModule(id); nativeModule.cache(); nativeModule.compile(); return nativeModule.exports; }; if (process.ischakra) { NativeModule.requireBuiltinModule = process.binding('nativerequire_wrap').requireBuiltinModule; } NativeModule.getCached = function(id) { return NativeModule._cache[id]; } NativeModule.exists = function(id) { return NativeModule._source.hasOwnProperty(id); } NativeModule.getSource = function (id) { if (process.ischakra) { // this will happen only when repl is used return process.lazyBindBuiltinModule(id); } else { return NativeModule._source[id]; } } NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = [ '(function(exports, require, module, __filename, __dirname) { ', '\n});' ]; NativeModule.prototype.compile = function() { if (process.ischakra) { // prevent us from fetching large strings into javascript var fn = NativeModule.requireBuiltinModule(this.id); fn(this.exports, NativeModule.require, this, this.filename); } else { // original node.js code var source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); var fn = runInThisContext(source, this.filename, true); fn(this.exports, NativeModule.require, this, this.filename); } this.loaded = true; }; NativeModule.prototype.cache = function() { NativeModule._cache[this.id] = this; }; startup(); }); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var events = require('events'); var stream = require('stream'); var timers = require('timers'); var util = require('util'); var assert = require('assert'); var cares; var cluster; function noop() {} // constructor for lazy loading function createPipe() { var Pipe = process.binding('pipe_wrap').Pipe; return new Pipe(); } // constructor for lazy loading function createTCP() { var TCP = process.binding('tcp_wrap').TCP; return new TCP(); } function createHandle(fd) { var tty = process.binding('tty_wrap'); var type = tty.guessHandleType(fd); if (type === 'PIPE') return createPipe(); if (type === 'TCP') return createTCP(); throw new TypeError('Unsupported fd type: ' + type); } var debug; if (process.env.NODE_DEBUG && /net/.test(process.env.NODE_DEBUG)) { var pid = process.pid; debug = function(x) { // if console is not set up yet, then skip this. if (!console.error) return; console.error('NET: %d', pid, util.format.apply(util, arguments).slice(0, 500)); }; } else { debug = function() { }; } function isPipeName(s) { return typeof s === 'string' && toNumber(s) === false; } exports.createServer = function() { return new Server(arguments[0], arguments[1]); }; // Target API: // // var s = net.connect({port: 80, host: 'google.com'}, function() { // ... // }); // // There are various forms: // // connect(options, [cb]) // connect(port, [host], [cb]) // connect(path, [cb]); // exports.connect = exports.createConnection = function() { var args = normalizeConnectArgs(arguments); var s = new Socket(args[0]); return Socket.prototype.connect.apply(s, args); }; // Returns an array [options] or [options, cb] // It is the same as the argument of Socket.prototype.connect(). function normalizeConnectArgs(args) { var options = {}; if (typeof args[0] === 'object') { // connect(options, [cb]) options = args[0]; } else if (isPipeName(args[0])) { // connect(path, [cb]); options.path = args[0]; } else { // connect(port, [host], [cb]) options.port = args[0]; if (typeof args[1] === 'string') { options.host = args[1]; } } var cb = args[args.length - 1]; return (typeof cb === 'function') ? [options, cb] : [options]; } exports._normalizeConnectArgs = normalizeConnectArgs; // called when creating new Socket, or when re-using a closed Socket function initSocketHandle(self) { self.destroyed = false; self.errorEmitted = false; self.bytesRead = 0; self._bytesDispatched = 0; // Handle creation may be deferred to bind() or connect() time. if (self._handle) { self._handle.owner = self; self._handle.onread = onread; } } function Socket(options) { if (!(this instanceof Socket)) return new Socket(options); this._connecting = false; this._handle = null; switch (typeof options) { case 'number': options = { fd: options }; // Legacy interface. break; case 'undefined': options = {}; break; } stream.Duplex.call(this, options); if (options.handle) { this._handle = options.handle; // private } else if (typeof options.fd !== 'undefined') { this._handle = createHandle(options.fd); this._handle.open(options.fd); this.readable = options.readable !== false; this.writable = options.writable !== false; } else { // these will be set once there is a connection this.readable = this.writable = false; } this.onend = null; // shut down the socket when we're finished with it. this.on('finish', onSocketFinish); this.on('_socketEnd', onSocketEnd); initSocketHandle(this); this._pendingData = null; this._pendingEncoding = ''; // handle strings directly this._writableState.decodeStrings = false; // default to *not* allowing half open sockets this.allowHalfOpen = options && options.allowHalfOpen || false; // if we have a handle, then start the flow of data into the // buffer. if not, then this will happen when we connect if (this._handle && options.readable !== false) this.read(0); } util.inherits(Socket, stream.Duplex); // the user has called .end(), and all the bytes have been // sent out to the other side. // If allowHalfOpen is false, or if the readable side has // ended already, then destroy. // If allowHalfOpen is true, then we need to do a shutdown, // so that only the writable side will be cleaned up. function onSocketFinish() { // If still connecting - defer handling 'finish' until 'connect' will happen if (this._connecting) { debug('osF: not yet connected'); return this.once('connect', onSocketFinish); } debug('onSocketFinish'); if (!this.readable || this._readableState.ended) { debug('oSF: ended, destroy', this._readableState); return this.destroy(); } debug('oSF: not ended, call shutdown()'); // otherwise, just shutdown, or destroy() if not possible if (!this._handle || !this._handle.shutdown) return this.destroy(); var shutdownReq = this._handle.shutdown(); if (!shutdownReq) return this._destroy(errnoException(process._errno, 'shutdown')); shutdownReq.oncomplete = afterShutdown; } function afterShutdown(status, handle, req) { var self = handle.owner; debug('afterShutdown destroyed=%j', self.destroyed, self._readableState); // callback may come after call to destroy. if (self.destroyed) return; if (self._readableState.ended) { debug('readableState ended, destroying'); self.destroy(); } else { self.once('_socketEnd', self.destroy); } } // the EOF has been received, and no more bytes are coming. // if the writable side has ended already, then clean everything // up. function onSocketEnd() { // XXX Should not have to do as much crap in this function. // ended should already be true, since this is called *after* // the EOF errno and onread has eof'ed debug('onSocketEnd', this._readableState); this._readableState.ended = true; if (this._readableState.endEmitted) { this.readable = false; } else { this.once('end', function() { this.readable = false; }); this.read(0); } if (!this.allowHalfOpen) { this.write = writeAfterFIN; this.destroySoon(); } } // Provide a better error message when we call end() as a result // of the other side sending a FIN. The standard 'write after end' // is overly vague, and makes it seem like the user's code is to blame. function writeAfterFIN(chunk, encoding, cb) { if (typeof encoding === 'function') { cb = encoding; encoding = null; } var er = new Error('This socket has been ended by the other party'); er.code = 'EPIPE'; var self = this; // TODO: defer error events consistently everywhere, not just the cb self.emit('error', er); if (typeof cb === 'function') { process.nextTick(function() { cb(er); }); } } exports.Socket = Socket; exports.Stream = Socket; // Legacy naming. Socket.prototype.read = function(n) { if (n === 0) return stream.Readable.prototype.read.call(this, n); this.read = stream.Readable.prototype.read; this._consuming = true; return this.read(n); }; Socket.prototype.listen = function() { debug('socket.listen'); var self = this; self.on('connection', arguments[0]); listen(self, null, null, null); }; Socket.prototype.setTimeout = function(msecs, callback) { if (msecs > 0 && !isNaN(msecs) && isFinite(msecs)) { timers.enroll(this, msecs); timers._unrefActive(this); if (callback) { this.once('timeout', callback); } } else if (msecs === 0) { timers.unenroll(this); if (callback) { this.removeListener('timeout', callback); } } }; Socket.prototype._onTimeout = function() { debug('_onTimeout'); this.emit('timeout'); }; Socket.prototype.setNoDelay = function(enable) { // backwards compatibility: assume true when `enable` is omitted if (this._handle && this._handle.setNoDelay) this._handle.setNoDelay(typeof enable === 'undefined' ? true : !!enable); }; Socket.prototype.setKeepAlive = function(setting, msecs) { if (this._handle && this._handle.setKeepAlive) this._handle.setKeepAlive(setting, ~~(msecs / 1000)); }; Socket.prototype.address = function() { if (this._handle && this._handle.getsockname) { return this._handle.getsockname(); } return null; }; Object.defineProperty(Socket.prototype, 'readyState', { get: function() { if (this._connecting) { return 'opening'; } else if (this.readable && this.writable) { return 'open'; } else if (this.readable && !this.writable) { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; } else { return 'closed'; } } }); Object.defineProperty(Socket.prototype, 'bufferSize', { get: function() { if (this._handle) { return this._handle.writeQueueSize + this._writableState.length; } } }); // Just call handle.readStart until we have enough in the buffer Socket.prototype._read = function(n) { debug('_read'); if (this._connecting || !this._handle) { debug('_read wait for connection'); this.once('connect', this._read.bind(this, n)); } else if (!this._handle.reading) { // not already reading, start the flow debug('Socket._read readStart'); this._handle.reading = true; var r = this._handle.readStart(); if (r) this._destroy(errnoException(process._errno, 'read')); } }; Socket.prototype.end = function(data, encoding) { stream.Duplex.prototype.end.call(this, data, encoding); this.writable = false; DTRACE_NET_STREAM_END(this); // just in case we're waiting for an EOF. if (this.readable && !this._readableState.endEmitted) this.read(0); return; }; Socket.prototype.destroySoon = function() { if (this.writable) this.end(); if (this._writableState.finished) this.destroy(); else this.once('finish', this.destroy); }; Socket.prototype._destroy = function(exception, cb) { debug('destroy'); var self = this; function fireErrorCallbacks() { if (cb) cb(exception); if (exception && !self.errorEmitted) { process.nextTick(function() { self.emit('error', exception); }); self.errorEmitted = true; } }; if (this.destroyed) { debug('already destroyed, fire error callbacks'); fireErrorCallbacks(); return; } self._connecting = false; this.readable = this.writable = false; timers.unenroll(this); debug('close'); if (this._handle) { if (this !== process.stderr) debug('close handle'); var isException = exception ? true : false; this._handle.close(function() { debug('emit close'); self.emit('close', isException); }); this._handle.onread = noop; this._handle = null; } fireErrorCallbacks(); this.destroyed = true; if (this.server) { COUNTER_NET_SERVER_CONNECTION_CLOSE(this); debug('has server'); this.server._connections--; if (this.server._emitCloseIfDrained) { this.server._emitCloseIfDrained(); } } }; Socket.prototype.destroy = function(exception) { debug('destroy', exception); this._destroy(exception); }; // This function is called whenever the handle gets a // buffer, or when there's an error reading. function onread(buffer, offset, length) { var handle = this; var self = handle.owner; assert(handle === self._handle, 'handle != self._handle'); timers._unrefActive(self); var end = offset + length; debug('onread', process._errno, offset, length, end); if (buffer) { debug('got data'); // read success. // In theory (and in practice) calling readStop right now // will prevent this from being called again until _read() gets // called again. // if we didn't get any bytes, that doesn't necessarily mean EOF. // wait for the next one. if (offset === end) { debug('not any data, keep waiting'); return; } // if it's not enough data, we'll just call handle.readStart() // again right away. self.bytesRead += length; // Optimization: emit the original buffer with end points var ret = true; // nadavbar: back ported the DoS fix issue: https://github.com/joyent/node/commit/653d4db71f569ddc87a0bc21f5ecc5ceaf37f932 if (self.ondata && !self._drain_paused) self.ondata(buffer, offset, end); else ret = self.push(buffer.slice(offset, end)); if (handle.reading && !ret) { handle.reading = false; debug('readStop'); var r = handle.readStop(); if (r) self._destroy(errnoException(process._errno, 'read')); } } else if (process._errno == 'EOF') { debug('EOF'); if (self._readableState.length === 0) self.readable = false; if (self.onend) self.once('end', self.onend); // push a null to signal the end of data. self.push(null); // internal end event so that we know that the actual socket // is no longer readable, and we can start the shutdown // procedure. No need to wait for all the data to be consumed. self.emit('_socketEnd'); } else { debug('error', process._errno); // Error self._destroy(errnoException(process._errno, 'read')); } } Socket.prototype._getpeername = function() { if (!this._handle || !this._handle.getpeername) { return {}; } if (!this._peername) { this._peername = this._handle.getpeername(); // getpeername() returns null on error if (this._peername === null) { return {}; } } return this._peername; }; Socket.prototype.__defineGetter__('remoteAddress', function() { return this._getpeername().address; }); Socket.prototype.__defineGetter__('remotePort', function() { return this._getpeername().port; }); Socket.prototype._getsockname = function() { if (!this._handle || !this._handle.getsockname) { return {}; } if (!this._sockname) { this._sockname = this._handle.getsockname(); if (this._sockname === null) { return {}; } } return this._sockname; }; Socket.prototype.__defineGetter__('localAddress', function() { return this._getsockname().address; }); Socket.prototype.__defineGetter__('localPort', function() { return this._getsockname().port; }); Socket.prototype.write = function(chunk, encoding, cb) { if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) throw new TypeError('invalid data'); return stream.Duplex.prototype.write.apply(this, arguments); }; Socket.prototype._write = function(data, encoding, cb) { // If we are still connecting, then buffer this for later. // The Writable logic will buffer up any more writes while // waiting for this one to be done. if (this._connecting) { this._pendingData = data; this._pendingEncoding = encoding; this.once('connect', function() { this._write(data, encoding, cb); }); return; } this._pendingData = null; this._pendingEncoding = ''; timers._unrefActive(this); if (!this._handle) { this._destroy(new Error('This socket is closed.'), cb); return false; } var enc = Buffer.isBuffer(data) ? 'buffer' : encoding; var writeReq = createWriteReq(this._handle, data, enc); if (!writeReq || typeof writeReq !== 'object') return this._destroy(errnoException(process._errno, 'write'), cb); writeReq.oncomplete = afterWrite; this._bytesDispatched += writeReq.bytes; // If it was entirely flushed, we can write some more right now. // However, if more is left in the queue, then wait until that clears. if (this._handle.writeQueueSize === 0) cb(); else writeReq.cb = cb; }; function createWriteReq(handle, data, encoding) { switch (encoding) { case 'buffer': return handle.writeBuffer(data); case 'utf8': case 'utf-8': return handle.writeUtf8String(data); case 'ascii': return handle.writeAsciiString(data); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return handle.writeUcs2String(data); default: return handle.writeBuffer(new Buffer(data, encoding)); } } Socket.prototype.__defineGetter__('bytesWritten', function() { var bytes = this._bytesDispatched, state = this._writableState, data = this._pendingData, encoding = this._pendingEncoding; state.buffer.forEach(function(el) { if (Buffer.isBuffer(el.chunk)) bytes += el.chunk.length; else bytes += Buffer.byteLength(el.chunk, el.encoding); }); if (data) { if (Buffer.isBuffer(data)) bytes += data.length; else bytes += Buffer.byteLength(data, encoding); } return bytes; }); function afterWrite(status, handle, req) { var self = handle.owner; var state = self._writableState; if (self !== process.stderr && self !== process.stdout) debug('afterWrite', status, req); // callback may come after call to destroy. if (self.destroyed) { debug('afterWrite destroyed'); return; } if (status) { debug('write failure', errnoException(process._errno, 'write')); self._destroy(errnoException(process._errno, 'write'), req.cb); return; } timers._unrefActive(self); if (self !== process.stderr && self !== process.stdout) debug('afterWrite call cb'); if (req.cb) req.cb.call(self); } function connect(self, address, port, addressType, localAddress) { // TODO return promise from Socket.prototype.connect which // wraps _connectReq. assert.ok(self._connecting); if (localAddress) { var r; if (addressType == 6) { r = self._handle.bind6(localAddress); } else { r = self._handle.bind(localAddress); } if (r) { self._destroy(errnoException(process._errno, 'bind')); return; } } var connectReq; if (addressType == 6) { connectReq = self._handle.connect6(address, port); } else if (addressType == 4) { connectReq = self._handle.connect(address, port); } else { connectReq = self._handle.connect(address, afterConnect); } if (connectReq !== null) { connectReq.oncomplete = afterConnect; } else { self._destroy(errnoException(process._errno, 'connect')); } } Socket.prototype.connect = function(options, cb) { if (this.write !== Socket.prototype.write) this.write = Socket.prototype.write; if (typeof options !== 'object') { // Old API: // connect(port, [host], [cb]) // connect(path, [cb]); var args = normalizeConnectArgs(arguments); return Socket.prototype.connect.apply(this, args); } if (this.destroyed) { this._readableState.reading = false; this._readableState.ended = false; this._writableState.ended = false; this._writableState.ending = false; this._writableState.finished = false; this.destroyed = false; this._handle = null; } var self = this; var pipe = !!options.path; if (!this._handle) { this._handle = pipe ? createPipe() : createTCP(); initSocketHandle(this); } if (typeof cb === 'function') { self.once('connect', cb); } timers._unrefActive(this); self._connecting = true; self.writable = true; if (pipe) { connect(self, options.path); } else if (!options.host) { debug('connect: missing host'); connect(self, '127.0.0.1', options.port, 4); } else { var host = options.host; debug('connect: find host ' + host); require('dns').lookup(host, function(err, ip, addressType) { // It's possible we were destroyed while looking this up. // XXX it would be great if we could cancel the promise returned by // the look up. if (!self._connecting) return; if (err) { // net.createConnection() creates a net.Socket object and // immediately calls net.Socket.connect() on it (that's us). // There are no event listeners registered yet so defer the // error event to the next tick. process.nextTick(function() { self.emit('error', err); self._destroy(); }); } else { timers._unrefActive(self); addressType = addressType || 4; // node_net.cc handles null host names graciously but user land // expects remoteAddress to have a meaningful value ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1'); connect(self, ip, options.port, addressType, options.localAddress); } }); } return self; }; Socket.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Socket.prototype.unref = function() { if (this._handle) this._handle.unref(); }; function afterConnect(status, handle, req, readable, writable) { var self = handle.owner; // callback may come after call to destroy if (self.destroyed) { return; } assert(handle === self._handle, 'handle != self._handle'); debug('afterConnect'); assert.ok(self._connecting); self._connecting = false; if (status == 0) { self.readable = readable; self.writable = writable; timers._unrefActive(self); self.emit('connect'); // start the first read, or get an immediate EOF. // this doesn't actually consume any bytes, because len=0. if (readable) self.read(0); } else { self._connecting = false; self._destroy(errnoException(process._errno, 'connect')); } } function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function Server(/* [ options, ] listener */) { if (!(this instanceof Server)) return new Server(arguments[0], arguments[1]); events.EventEmitter.call(this); var self = this; var options; if (typeof arguments[0] == 'function') { options = {}; self.on('connection', arguments[0]); } else { options = arguments[0] || {}; if (typeof arguments[1] == 'function') { self.on('connection', arguments[1]); } } this._connections = 0; Object.defineProperty(this, 'connections', { get: util.deprecate(function() { if (self._usingSlaves) { return null; } return self._connections; }, 'connections property is deprecated. Use getConnections() method'), set: util.deprecate(function(val) { return (self._connections = val); }, 'connections property is deprecated. Use getConnections() method'), configurable: true, enumerable: true }); this._handle = null; this._usingSlaves = false; this._slaves = []; this.allowHalfOpen = options.allowHalfOpen || false; } util.inherits(Server, events.EventEmitter); exports.Server = Server; function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; } var createServerHandle = exports._createServerHandle = function(address, port, addressType, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { var r = 0; // assign handle in listen, and clean up if bind or listen fails var handle; if (typeof fd === 'number' && fd >= 0) { try { handle = createHandle(fd); } catch (e) { // Not a fd we can listen on. This will trigger an error. debug('listen invalid fd=' + fd + ': ' + e.message); process._errno = 'EINVAL'; // hack, callers expect that errno is set return null; } handle.open(fd); handle.readable = true; handle.writable = true; return handle; } else if (port == -1 && addressType == -1) { handle = createPipe(); if (process.platform === 'win32') { var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); if (!isNaN(instances)) { handle.setPendingInstances(instances); } } } else { handle = createTCP(); } if (address || port) { debug('bind to ' + address); if (addressType == 6) { r = handle.bind6(address, port); } else { if (defineSecurityProps) { // Chakra/WP addition if (pipeNameForSecurityDescriptor) { r = handle.bind(address, port, defineSecurityProps, pipeNameForSecurityDescriptor); } else { r = handle.bind(address, port, defineSecurityProps); } } else { r = handle.bind(address, port); } } } if (r) { handle.close(); handle = null; } return handle; }; Server.prototype._listen2 = function (address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { debug('listen2', address, port, addressType, backlog); var self = this; var r = 0; // If there is not yet a handle, we need to create one and bind. // In the case of a server sent via IPC, we don't need to do this. if (!self._handle) { debug('_listen2: create a handle'); self._handle = createServerHandle(address, port, addressType, fd, defineSecurityProps, pipeNameForSecurityDescriptor, pipeNameForSecurityDescriptor); if (!self._handle) { var error = errnoException(process._errno, 'listen'); process.nextTick(function() { self.emit('error', error); }); return; } } else { debug('_listen2: have a handle already'); } self._handle.onconnection = onconnection; self._handle.owner = self; // Use a backlog of 512 entries. We pass 511 to the listen() call because // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); // which will thus give us a backlog of 512 entries. r = self._handle.listen(backlog || 511); if (r) { var ex = errnoException(process._errno, 'listen'); self._handle.close(); self._handle = null; process.nextTick(function() { self.emit('error', ex); }); return; } // generate connection key, this should be unique to the connection this._connectionKey = addressType + ':' + address + ':' + port; process.nextTick(function() { self.emit('listening'); }); }; function listen(self, address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { if (!cluster) cluster = require('cluster'); if (cluster.isMaster) { self._listen2(address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor); return; } cluster._getServer(self, address, port, addressType, fd, function(handle) { // Some operating systems (notably OS X and Solaris) don't report EADDRINUSE // errors right away. libuv mimics that behavior for the sake of platform // consistency but that means we have have a socket on our hands that is // not actually bound. That's why we check if the actual port matches what // we requested and if not, raise an error. The exception is when port == 0 // because that means "any random port". if (port && handle.getsockname && port != handle.getsockname().port) { self.emit('error', errnoException('EADDRINUSE', 'bind')); return; } self._handle = handle; self._listen2(address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor); }); } Server.prototype.listen = function() { var self = this; var lastArg = arguments[arguments.length - 1]; if (typeof lastArg == 'function') { self.once('listening', lastArg); } var port = toNumber(arguments[0]); // The third optional argument is the backlog size. // When the ip is omitted it can be the second argument. var backlog = toNumber(arguments[1]) || toNumber(arguments[2]); var TCP = process.binding('tcp_wrap').TCP; if (arguments.length == 0 || typeof arguments[0] == 'function') { // Bind to a random port. listen(self, '0.0.0.0', 0, null, backlog); } else if (arguments[0] && typeof arguments[0] === 'object') { var h = arguments[0]; if (h._handle) { h = h._handle; } else if (h.handle) { h = h.handle; } if (h instanceof TCP) { self._handle = h; listen(self, null, -1, -1, backlog); } else if (typeof h.fd === 'number' && h.fd >= 0) { listen(self, null, null, null, backlog, h.fd); } else { throw new Error('Invalid listen argument: ' + h); } } else if (isPipeName(arguments[0])) { // UNIX socket or Windows pipe. var pipeName = self._pipeName = arguments[0]; // Chakra/WP addition var defineSecurityProps = false; var pipeNameForSecurityProps = null; var defineSecurityPropsIndex = 1; if (backlog && typeof arguments[defineSecurityPropsIndex] != 'boolean') { defineSecurityPropsIndex = 2; } if (typeof arguments[defineSecurityPropsIndex] == 'boolean') { defineSecurityProps = arguments[defineSecurityPropsIndex]; if (typeof arguments[defineSecurityPropsIndex + 1] == 'string') { pipeNameForSecurityProps = arguments[defineSecurityPropsIndex + 1]; } } // end of Chakra/ WP addition listen(self, pipeName, -1, -1, backlog, null, defineSecurityProps, pipeNameForSecurityProps); } else if (typeof arguments[1] == 'undefined' || typeof arguments[1] == 'function' || typeof arguments[1] == 'number') { // The first argument is the port, no IP given. listen(self, '0.0.0.0', port, 4, backlog); } else { // The first argument is the port, the second an IP. // Chakra/Threshold addition. if (arguments[1] === '127.0.0.1') { listen(self, '127.0.0.1', port, 4, backlog); } else if (arguments[1] === '[::1]' || arguments[1] === '::1') { listen(self, '::1', port, 6, backlog); } else { // End of Chakra/Threshold addition. require('dns').lookup(arguments[1], function(err, ip, addressType) { if (err) { self.emit('error', err); } else { listen(self, ip || '0.0.0.0', port, ip ? addressType : 4, backlog); } }); } } return self; }; Server.prototype.address = function() { if (this._handle && this._handle.getsockname) { return this._handle.getsockname(); } else if (this._pipeName) { return this._pipeName; } else { return null; } }; function onconnection(clientHandle) { var handle = this; var self = handle.owner; debug('onconnection'); if (!clientHandle) { self.emit('error', errnoException(process._errno, 'accept')); return; } if (self.maxConnections && self._connections >= self.maxConnections) { clientHandle.close(); return; } var socket = new Socket({ handle: clientHandle, allowHalfOpen: self.allowHalfOpen }); socket.readable = socket.writable = true; self._connections++; socket.server = self; DTRACE_NET_SERVER_CONNECTION(socket); COUNTER_NET_SERVER_CONNECTION(socket); self.emit('connection', socket); } Server.prototype.getConnections = function(cb) { function end(err, connections) { process.nextTick(function() { cb(err, connections); }); } if (!this._usingSlaves) { return end(null, this._connections); } // Poll slaves var left = this._slaves.length, total = this._connections; function oncount(err, count) { if (err) { left = -1; return end(err); } total += count; if (--left === 0) return end(null, total); } this._slaves.forEach(function(slave) { slave.getConnections(oncount); }); }; Server.prototype.close = function(cb) { function onSlaveClose() { if (--left !== 0) return; self._connections = 0; self._emitCloseIfDrained(); } if (!this._handle) { // Throw error. Follows net_legacy behaviour. throw new Error('Not running'); } if (cb) { this.once('close', cb); } this._handle.close(); this._handle = null; if (this._usingSlaves) { var self = this, left = this._slaves.length; // Increment connections to be sure that, even if all sockets will be closed // during polling of slaves, `close` event will be emitted only once. this._connections++; // Poll slaves this._slaves.forEach(function(slave) { slave.close(onSlaveClose); }); } else { this._emitCloseIfDrained(); } return this; }; Server.prototype._emitCloseIfDrained = function() { debug('SERVER _emitCloseIfDrained'); var self = this; if (self._handle || self._connections) { debug('SERVER handle? %j connections? %d', !!self._handle, self._connections); return; } process.nextTick(function() { debug('SERVER: emit close'); self.emit('close'); }); }; Server.prototype.listenFD = util.deprecate(function(fd, type) { return this.listen({ fd: fd }); }, 'listenFD is deprecated. Use listen({fd: }).'); Server.prototype._setupSlave = function(socketList) { this._usingSlaves = true; this._slaves.push(socketList); }; Server.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Server.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // TODO: isIP should be moved to the DNS code. Putting it here now because // this is what the legacy system did. exports.isIP = function() { cares = cares || process.binding('cares_wrap'); return cares.isIP.apply(this, arguments); } exports.isIPv4 = function(input) { return exports.isIP(input) === 4; }; exports.isIPv6 = function(input) { return exports.isIP(input) === 6; }; if (process.platform === 'win32') { var simultaneousAccepts; exports._setSimultaneousAccepts = function(handle) { if (typeof handle === 'undefined') { return; } if (typeof simultaneousAccepts === 'undefined') { simultaneousAccepts = (process.env.NODE_MANY_ACCEPTS && process.env.NODE_MANY_ACCEPTS !== '0'); } if (handle._simultaneousAccepts !== simultaneousAccepts) { handle.setSimultaneousAccepts(simultaneousAccepts); handle._simultaneousAccepts = simultaneousAccepts; } }; } else { exports._setSimultaneousAccepts = function(handle) {}; } net// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // code was taken from node's module.js and then changed to use the native require var nativerequire = process.binding('nativerequire_wrap'); var NativeModule = require('native_module'); var assert = require('assert').ok; var path = require('path'); var fs; // we have to do this in order to solve the crazy dependancy issues that happend when _stream_readable is required before stream - this happend in several of node tests // the original module.js does not suffer from this since it always loads fs which loads stream var stream = require('stream'); // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all // modules in thier own context. // we don't support context load for now Module._cache = {}; Module._extensions = {}; var modulePaths = []; Module.globalPaths = []; if (process.ischakra) { Module._useScriptsSerialization = false; } // Cache which can be loaded to disk of the relative location of one module to another. function PathCache() { if (!(this instanceof PathCache)) { return new PathCache(); } // true if changed since set. this._dirty = false; // the file the cache read/writes from/to, if this cache originated from a file. this._cacheFile = undefined; // the key --> filename mappings for this cache. this._mappings = {}; // insert a key --> filename mapping. this.insert = function(key, filename) { this._mappings[key] = filename; this._dirty = true; } // remove a key --> filename mapping. this.remove = function(key) { delete this._mappings[key]; this._dirty = true; } // lookup a key --> filename mapping. this.find = function(key) { var filename = this._mappings[key]; if (!filename) { return undefined; } return filename; } // loads the cache from a file. If the file doesn't exist or is corrupt, starts from a clean state. this.load = function(filename) { this._cacheFile = filename; this._dirty = false; this._mappings = {}; if (!nativerequire.fileExistsNotDir(filename)) { return; } fs = fs || require('fs'); try { this._mappings = JSON.parse(fs.readFileSync(filename)); } catch (ex) { console.error('Failed to read json paths cache from file:', filename, ex); } } // Can be used for optimization for saving the native require paths cache // And then used in load. Note that this method is async where load is sync this.save = function(filename, cb) { cb = cb || Function(); var self = this; if (!this._dirty) { return cb(null); } this._dirty = false; if (this._cacheFile !== filename) { return cb(new Error('path cache file changed.')); } fs = fs || require('fs'); return fs.writeFile(this._cacheFile, JSON.stringify(this._mappings), function(err) { if (err) { self._dirty = true; } return cb(err); }); } // removes entries of files which does not exist from the path cache // this may be used by modules which saves/loads the path cache in order to trim the cache if it's get large this.validate = function(flush) { var keys = Object.keys(this._mappings); for (var key in keys) { if (!nativerequire.fileExistsNotDir(this._mappings[key])) { this.remove(key); } } if (this._cacheFile && this._dirty && flush) { fs = fs || require('fs'); fs.writeFileSync(this._cacheFile, JSON.stringify(this._mappings)); this._dirty = false; } } this.size = function() { try { return Object.keys(this._mappings).length; } catch (e) { console.error('failed to get path cache size:', e); return 0; } } }; Module._pathCache = new PathCache(); // Write the cache file back to disk according to the count and interval. function periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval) { if (pathCacheSaves-- == 0) { return; } setTimeout(function() { Module._pathCache.save(filename, function(err) { return periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval); }); }, pathCacheSaveInterval); }; // Loads the path cache from predefined location if the caller of node has enabled // a cache filepath + version in Node::Start. // Starting with writes back to disk at 5, 10, and 15s into the process startup to capture startup paths. function loadGlobalPathCache() { var filename = nativerequire.loadCacheFilePath('npc'); if (!filename) { return; } var pathCacheSaves = 3; var pathCacheSaveInterval = 5000; Module._pathCache.load(filename); periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval); } loadGlobalPathCache(); // bootstrap main module. Module.runMain = function () { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback(); }; Module._debug = function () { }; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { Module._debug = function (x) { console.error(x); }; } // We use this alias for the preprocessor that filters it out var debug = Module._debug; // given a module name, and a list of paths to test, returns the first // matching file in the following precedence. // // require("a.") // -> a. // // require("a") // -> a // -> a. // -> a/index. // check if the directory is a package.json dir var packageCache = {}; function readPackage(requestPath) { if (hasOwnProperty(packageCache, requestPath)) { return packageCache[requestPath]; } try { var jsonPath = path.resolve(requestPath, 'package.json'); if (!nativerequire.fileExistsNotDir(jsonPath)) return undefined; var pkg = nativerequire.readJsonPackage(jsonPath); if (!pkg) { throw new Error("Unable to read package, or properties are missing"); } packageCache[requestPath] = pkg; } catch (e) { e.path = jsonPath; e.message = 'Error parsing ' + jsonPath + ': ' + e.message; throw e; } return pkg; } function tryPackage(requestPath, exts) { var pkg = readPackage(requestPath); if (!pkg || !pkg.main) return false; var filename = path.resolve(requestPath, pkg.main); return tryFile(filename) || tryExtensions(filename, exts) || tryExtensions(path.resolve(filename, 'index'), exts); } // In order to minimize unnecessary lstat() calls, // this cache is a list of known-real paths. // Set to an empty object to reset. Module._realpathCache = {}; // check if the file exists and is not a directory function tryFile(requestPath) { if (nativerequire.fileExistsNotDir(requestPath)) { return requestPath; //not using fs.realpathSync(requestPath, Module._realpathCache); like in original code here. We assume that there are no links // as it turn out, this method can blow up the memory } return false; } // given a path check a the file exists with any of the set extensions function tryExtensions(p, exts) { for (var i = 0, EL = exts.length; i < EL; i++) { var filename = tryFile(p + exts[i]); if (filename) { return filename; } } return false; } Module._tryPath = function (request, basePath, trailingSlash, cacheKey, exts) { var filename; if (!trailingSlash) { // try to join the request to the path filename = tryFile(basePath); if (!filename && !trailingSlash) { // try it with each of the extensions filename = tryExtensions(basePath, exts); } } if (!filename) { filename = tryPackage(basePath, exts); } if (!filename) { // try it with each of the extensions at "index" filename = tryExtensions(path.resolve(basePath, 'index'), exts); } if (filename) { Module._pathCache.insert(cacheKey, filename); } return filename; } Module._findInPaths = function (request, paths, trailingSlash, cacheKey, exts) { var filename; for (var i = 0, PL = paths.length; i < PL; i++) { var basePath = path.resolve(paths[i], request); filename = Module._tryPath(request, basePath, trailingSlash, cacheKey, exts); if (filename) { return filename; } } return filename; }; // this function was re-written in order to allow more efficient search of modules // instead of building the paths table with every possibility of '[sub dir]\node_modules' we // built it incremently and insert the folders which we build to the cache until we find the module // the main difference here is that the original code created many strings that weren't needed since // the modules are often found in the higher levels Module._findPath = function (request, paths, parent) { var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { paths = ['']; } var trailingSlash = (request.slice(-1) === '/'); var cacheKey; // cacheKey is only paths or paths & parent paths if such exist if (!parent || !parent.paths) { cacheKey = JSON.stringify({ request: request, paths: paths }); } else { cacheKey = JSON.stringify({ request: request, parent: parent.paths, paths: paths }); } var filename = Module._pathCache.find(cacheKey); if (filename) { return filename; } filename = Module._findInPaths(request, paths, trailingSlash, cacheKey, exts); if (filename) { return filename; } if (parent) { if (!parent.paths) { parent.paths = []; } else { var filename = Module._findInPaths(request, parent.paths, trailingSlash, cacheKey, exts); if (filename) { return filename; } } var pathToStartFrom = parent.paths.length > 0 ? parent.paths[parent.paths.length - 1] : path.resolve(path.dirname(parent.filename)); var index = pathToStartFrom.length; if (process.platform == 'win32') { pathToStartFrom = pathToStartFrom.replace(/\//g, '\\') } while (index > 0) { var basePath; // TODO: do not check node_modules within node_modules? if (index == pathToStartFrom.length) { basePath = pathToStartFrom + path.sep + 'node_modules'; } else { basePath = pathToStartFrom.substring(0, index) + path.sep + 'node_modules'; } parent.paths.push(basePath); filename = Module._tryPath(request, path.resolve(basePath, request), trailingSlash, cacheKey, exts); if (filename) { return filename; } index = pathToStartFrom.lastIndexOf(path.sep, index - 1); } } filename = Module._findInPaths(request, modulePaths, trailingSlash, cacheKey, exts); if (filename) { return filename; } return filename; }; Module._resolveLookupPaths = function (request, parent) { // if parent is null, this is probably the main module if (!parent) { return [request,[]]; } if (NativeModule.exists(request)) { return [request, []]; } var start = request.substring(0, 2); if (start !== './' && start !== '..') { return [request, []]; } // Is the parent an index module? // We can assume the parent has a valid extension, // as it already has been accepted as a module. var isIndex = /^index\.\w+?$/.test(path.basename(parent.filename)); var parentIdPath = isIndex ? parent.id : path.dirname(parent.id); var id = path.resolve(parentIdPath, request); // make sure require('./path') and require('path') get distinct ids, even // when called from the toplevel js file if (parentIdPath === '.' && id.indexOf('/') === -1) { id = './' + id; } return [id, [path.dirname(parent.filename)]]; }; Module._load = function (request, parent, isMain) { if (parent) { debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id); } var filename; var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } if (NativeModule.exists(filename)) { // REPL is a special case, because it needs the real require. return require(filename); } var module = new Module(filename, parent); if (isMain) { process.mainModule = module; module.id = '.'; } Module._cache[filename] = module; var hadException = true; try { module.load(filename); hadException = false; } finally { if (hadException) { delete Module._cache[filename]; Module._pathCache.validate(true); } } return module.exports; }; Module.require = function require(path, parent) { return Module._load(path, parent); } Module._resolveFilename = function (request, parent) { if (NativeModule.exists(request)) { return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; var filename = Module._findPath(request, paths, parent); if (!filename) { var err = new Error("Cannot find module '" + request + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; } return filename; }; Module.prototype.load = function (filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.paths = Module._nodeModulePaths(path.dirname(filename)); this.filename = filename; var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; }; Module.prototype.require = function (path) { assert(typeof path === 'string', 'path must be a string'); assert(path, 'missing path'); return Module._load(path, this); }; // Resolved path to process.argv[1] will be lazily placed here // (needed for setting breakpoint when called with --debug-brk) var resolvedArgv; // Returns exception if any // this code was mainly taken from compile, we load and compile the js file here using native require Module.prototype._loadJs = function (filename) { var self = this; function require(path) { return self.require(path); } require.resolve = function (request) { return Module._resolveFilename(request, self); }; require.main = process.mainModule; // we throw the same errors that module.js throw, in order to be complaint with module.js Object.defineProperty(require, 'paths', { get: function () { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.'); } }); require.registerExtension = function () { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.'); }; // Enable support to add extra extension types require.extensions = Module._extensions; require.cache = Module._cache; var dirname = path.dirname(filename); var compiledCode; if (process.ischakra && Module._useScriptsSerialization) { compiledCode = nativerequire.require(filename, filename + '.jsbc'); } else { compiledCode = nativerequire.require(filename); } var args = [self.exports, require, self, filename, dirname]; return compiledCode.apply(self.exports, args); }; // Native extension for .js Module._extensions['.js'] = function (module, filename) { module._loadJs(filename); }; function stripBOM(content) { // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) // because the buffer-to-string conversion in `fs.readFileSync()` // translates it to FEFF, the UTF-16 BOM. if (content.charCodeAt(0) === 0xFEFF) { content = content.slice(1); } return content; } // Native extension for .json Module._extensions['.json'] = function (module, filename) { var content = require('fs').readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } }; //Native extension for .node Module._extensions['.node'] = process.dlopen; Module._initPaths = function () { var isWindows = process.platform === 'win32'; if (isWindows) { var homeDir = process.env.USERPROFILE; } else { var homeDir = process.env.HOME; } var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; if (homeDir) { paths.unshift(path.resolve(homeDir, '.node_libraries')); paths.unshift(path.resolve(homeDir, '.node_modules')); } // node.ch specific for now - disable the use of NODE_PATH for security reasons if (!process.disable_node_env_vars) { if (process.env['NODE_PATH']) { var splitter = isWindows ? ';' : ':'; paths = process.env['NODE_PATH'].split(splitter).concat(paths); } } modulePaths = paths; // clone as a read-only copy, for introspection Module.globalPaths = modulePaths.slice(0); }; // 'from' is the __dirname of the module. Module._nodeModulePaths = function (from) { // guarantee that 'from' is absolute. from = path.resolve(from); // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; // yes, '/' works on both, but let's be a little canonical. var joiner = process.platform === 'win32' ? '\\' : '/'; var paths = []; var parts = from.split(splitRe); for (var tip = parts.length - 1; tip >= 0; tip--) { // don't search in .../node_modules/node_modules if (parts[tip] === 'node_modules') continue; var dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner); paths.push(dir); } return paths; }; Module._initPaths(); // backwards compatibility Module.Module = Module; nativerequire// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var NativeModule = require('native_module'); var Script = process.binding('evals').NodeScript; var runInThisContext = Script.runInThisContext; var runInNewContext = Script.runInNewContext; var assert = require('assert').ok; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; if (parent && parent.children) { parent.children.push(this); } this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all // modules in thier own context. if (!process.disable_node_env_vars) { Module._contextLoad = (+process.env['NODE_MODULE_CONTEXTS'] > 0); } Module._cache = {}; Module._pathCache = {}; Module._extensions = {}; var modulePaths = []; Module.globalPaths = []; Module.wrapper = NativeModule.wrapper; Module.wrap = NativeModule.wrap; var path = NativeModule.require('path'); Module._debug = function() {}; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { Module._debug = function(x) { console.error(x); }; } // We use this alias for the preprocessor that filters it out var debug = Module._debug; // given a module name, and a list of paths to test, returns the first // matching file in the following precedence. // // require("a.") // -> a. // // require("a") // -> a // -> a. // -> a/index. function statPath(path) { var fs = NativeModule.require('fs'); try { return fs.statSync(path); } catch (ex) {} return false; } // check if the directory is a package.json dir var packageCache = {}; function readPackage(requestPath) { if (hasOwnProperty(packageCache, requestPath)) { return packageCache[requestPath]; } var fs = NativeModule.require('fs'); try { var jsonPath = path.resolve(requestPath, 'package.json'); var json = fs.readFileSync(jsonPath, 'utf8'); } catch (e) { return false; } try { // nabar: the following line is commented in order to be more memory efficient and disable the package cache // var pkg = packageCache[requestPath] = JSON.parse(json); var pkg = JSON.parse(json); } catch (e) { e.path = jsonPath; e.message = 'Error parsing ' + jsonPath + ': ' + e.message; throw e; } return pkg; } function tryPackage(requestPath, exts) { var pkg = readPackage(requestPath); if (!pkg || !pkg.main) return false; var filename = path.resolve(requestPath, pkg.main); return tryFile(filename) || tryExtensions(filename, exts) || tryExtensions(path.resolve(filename, 'index'), exts); } // In order to minimize unnecessary lstat() calls, // this cache is a list of known-real paths. // Set to an empty object to reset. Module._realpathCache = {}; // check if the file exists and is not a directory function tryFile(requestPath) { var fs = NativeModule.require('fs'); var stats = statPath(requestPath); if (stats && !stats.isDirectory()) { return fs.realpathSync(requestPath, Module._realpathCache); } return false; } // given a path check a the file exists with any of the set extensions function tryExtensions(p, exts) { for (var i = 0, EL = exts.length; i < EL; i++) { var filename = tryFile(p + exts[i]); if (filename) { return filename; } } return false; } Module._findPath = function(request, paths) { var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { paths = ['']; } var trailingSlash = (request.slice(-1) === '/'); var cacheKey = JSON.stringify({request: request, paths: paths}); if (Module._pathCache[cacheKey]) { return Module._pathCache[cacheKey]; } // For each path for (var i = 0, PL = paths.length; i < PL; i++) { var basePath = path.resolve(paths[i], request); var filename; if (!trailingSlash) { // try to join the request to the path filename = tryFile(basePath); if (!filename && !trailingSlash) { // try it with each of the extensions filename = tryExtensions(basePath, exts); } } if (!filename) { filename = tryPackage(basePath, exts); } if (!filename) { // try it with each of the extensions at "index" filename = tryExtensions(path.resolve(basePath, 'index'), exts); } if (filename) { Module._pathCache[cacheKey] = filename; return filename; } } return false; }; // 'from' is the __dirname of the module. Module._nodeModulePaths = function(from) { // guarantee that 'from' is absolute. from = path.resolve(from); // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; // yes, '/' works on both, but let's be a little canonical. var joiner = process.platform === 'win32' ? '\\' : '/'; var paths = []; var parts = from.split(splitRe); for (var tip = parts.length - 1; tip >= 0; tip--) { // don't search in .../node_modules/node_modules if (parts[tip] === 'node_modules') continue; var dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner); paths.push(dir); } return paths; }; Module._resolveLookupPaths = function(request, parent) { if (NativeModule.exists(request)) { return [request, []]; } var start = request.substring(0, 2); if (start !== './' && start !== '..') { var paths = modulePaths; if (parent) { if (!parent.paths) parent.paths = []; paths = parent.paths.concat(paths); } return [request, paths]; } // with --eval, parent.id is not set and parent.filename is null if (!parent || !parent.id || !parent.filename) { // make require('./path/to/foo') work - normally the path is taken // from realpath(__filename) but with eval there is no filename var mainPaths = ['.'].concat(modulePaths); mainPaths = Module._nodeModulePaths('.').concat(mainPaths); return [request, mainPaths]; } // Is the parent an index module? // We can assume the parent has a valid extension, // as it already has been accepted as a module. var isIndex = /^index\.\w+?$/.test(path.basename(parent.filename)); var parentIdPath = isIndex ? parent.id : path.dirname(parent.id); var id = path.resolve(parentIdPath, request); // make sure require('./path') and require('path') get distinct ids, even // when called from the toplevel js file if (parentIdPath === '.' && id.indexOf('/') === -1) { id = './' + id; } debug('RELATIVE: requested:' + request + ' set ID to: ' + id + ' from ' + parent.id); return [id, [path.dirname(parent.filename)]]; }; Module._load = function(request, parent, isMain) { if (parent) { debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id); } var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } if (NativeModule.exists(filename)) { // REPL is a special case, because it needs the real require. if (filename == 'repl') { var replModule = new Module('repl'); replModule._compile(NativeModule.getSource('repl'), 'repl.js'); NativeModule._cache.repl = replModule; return replModule.exports; } debug('load native module ' + request); return NativeModule.require(filename); } var module = new Module(filename, parent); if (isMain) { process.mainModule = module; module.id = '.'; } Module._cache[filename] = module; var hadException = true; try { module.load(filename); hadException = false; } finally { if (hadException) { delete Module._cache[filename]; } } return module.exports; }; Module._resolveFilename = function(request, parent) { if (NativeModule.exists(request)) { return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; // look up the filename first, since that's the cache key. debug('looking for ' + JSON.stringify(id) + ' in ' + JSON.stringify(paths)); var filename = Module._findPath(request, paths); if (!filename) { var err = new Error("Cannot find module '" + request + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; } return filename; }; Module.prototype.load = function(filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.filename = filename; this.paths = Module._nodeModulePaths(path.dirname(filename)); var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; }; Module.prototype.require = function(path) { assert(typeof path === 'string', 'path must be a string'); assert(path, 'missing path'); return Module._load(path, this); }; // Resolved path to process.argv[1] will be lazily placed here // (needed for setting breakpoint when called with --debug-brk) var resolvedArgv; // Returns exception if any Module.prototype._compile = function(content, filename) { var self = this; // remove shebang content = content.replace(/^\#\!.*/, ''); function require(path) { return self.require(path); } require.resolve = function(request) { return Module._resolveFilename(request, self); }; Object.defineProperty(require, 'paths', { get: function() { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.'); }}); require.main = process.mainModule; // Enable support to add extra extension types require.extensions = Module._extensions; require.registerExtension = function() { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.'); }; require.cache = Module._cache; var dirname = path.dirname(filename); if (Module._contextLoad) { if (self.id !== '.') { debug('load submodule'); // not root module var sandbox = {}; for (var k in global) { sandbox[k] = global[k]; } sandbox.require = require; sandbox.exports = self.exports; sandbox.__filename = filename; sandbox.__dirname = dirname; sandbox.module = self; sandbox.global = sandbox; sandbox.root = root; return runInNewContext(content, sandbox, filename, true); } debug('load root module'); // root module global.require = require; global.exports = self.exports; global.__filename = filename; global.__dirname = dirname; global.module = self; return runInThisContext(content, filename, true); } // create wrapper function var wrapper = Module.wrap(content); var compiledWrapper = runInThisContext(wrapper, filename, true); if (global.v8debug) { if (!resolvedArgv) { // we enter the repl if we're not given a filename argument. if (process.argv[1]) { resolvedArgv = Module._resolveFilename(process.argv[1], null); } else { resolvedArgv = 'repl'; } } // Set breakpoint on module start if (filename === resolvedArgv) { global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0); } } var args = [self.exports, require, self, filename, dirname]; return compiledWrapper.apply(self.exports, args); }; function stripBOM(content) { // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) // because the buffer-to-string conversion in `fs.readFileSync()` // translates it to FEFF, the UTF-16 BOM. if (content.charCodeAt(0) === 0xFEFF) { content = content.slice(1); } return content; } // Native extension for .js Module._extensions['.js'] = function(module, filename) { var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); module._compile(stripBOM(content), filename); }; // Native extension for .json Module._extensions['.json'] = function(module, filename) { var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } }; //Native extension for .node Module._extensions['.node'] = process.dlopen; // bootstrap main module. Module.runMain = function() { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback(); }; Module._initPaths = function() { var isWindows = process.platform === 'win32'; if (isWindows) { var homeDir = process.env.USERPROFILE; } else { var homeDir = process.env.HOME; } var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; if (homeDir) { paths.unshift(path.resolve(homeDir, '.node_libraries')); paths.unshift(path.resolve(homeDir, '.node_modules')); } if (!process.disable_node_env_vars) { if (process.env['NODE_PATH']) { var splitter = isWindows ? ';' : ':'; paths = process.env['NODE_PATH'].split(splitter).concat(paths); } } modulePaths = paths; // clone as a read-only copy, for introspection. Module.globalPaths = modulePaths.slice(0); }; // bootstrap repl Module.requireRepl = function() { return Module._load('repl', '.'); }; Module._initPaths(); // backwards compatibility Module.Module = Module; module// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var tls = require('tls'); var http = require('http'); var util = require('util'); var url = require('url'); var inherits = require('util').inherits; function Server(opts, requestListener) { if (!(this instanceof Server)) return new Server(opts, requestListener); if (process.features.tls_npn && !opts.NPNProtocols) { opts.NPNProtocols = ['http/1.1', 'http/1.0']; } tls.Server.call(this, opts, http._connectionListener); this.httpAllowHalfOpen = false; if (requestListener) { this.addListener('request', requestListener); } this.addListener('clientError', function(err, conn) { conn.destroy(err); }); } inherits(Server, tls.Server); exports.Server = Server; exports.createServer = function(opts, requestListener) { return new Server(opts, requestListener); }; // HTTPS agents. function createConnection(port, host, options) { if (typeof port === 'object') { options = port; } else if (typeof host === 'object') { options = host; } else if (typeof options === 'object') { options = options; } else { options = {}; } if (typeof port === 'number') { options.port = port; } if (typeof host === 'string') { options.host = host; } return tls.connect(options); } function Agent(options) { http.Agent.call(this, options); this.createConnection = createConnection; } inherits(Agent, http.Agent); Agent.prototype.defaultPort = 443; var globalAgent = new Agent(); exports.globalAgent = globalAgent; exports.Agent = Agent; exports.request = function(options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'https:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } options = util._extend({ createConnection: createConnection, defaultPort: 443 }, options); if (typeof options.agent === 'undefined') { if (typeof options.ca === 'undefined' && typeof options.cert === 'undefined' && typeof options.ciphers === 'undefined' && typeof options.key === 'undefined' && typeof options.passphrase === 'undefined' && typeof options.pfx === 'undefined' && typeof options.rejectUnauthorized === 'undefined') { options.agent = globalAgent; } else { options.agent = new Agent(options); } } return new http.ClientRequest(options, cb); }; exports.get = function(options, cb) { var req = exports.request(options, cb); req.end(); return req; }; https// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var net = require('net'); var Stream = require('stream'); var url = require('url'); var EventEmitter = require('events').EventEmitter; var FreeList = require('freelist').FreeList; var HTTPParser = process.binding('http_parser').HTTPParser; var assert = require('assert').ok; // an empty buffer for UPGRADE/CONNECT bodyHead compatibility var emptyBuffer = new Buffer(0); var debug; if (process.env.NODE_DEBUG && /http/.test(process.env.NODE_DEBUG)) { debug = function(x) { console.error('HTTP: %s', x); }; } else { debug = function() { }; } function readStart(socket) { if (!socket || !socket._handle || !socket._handle.readStart) return; if (!socket._drain_paused) { socket._handle.readStart(); } } function readStop(socket) { if (!socket || !socket._handle || !socket._handle.readStop) return; socket._handle.readStop(); } // Only called in the slow case where slow means // that the request headers were either fragmented // across multiple TCP packets or too large to be // processed in a single run. This method is also // called to process trailing HTTP headers. function parserOnHeaders(headers, url) { // Once we exceeded headers limit - stop collecting them if (this.maxHeaderPairs <= 0 || this._headers.length < this.maxHeaderPairs) { this._headers = this._headers.concat(headers); } this._url += url; } // info.headers and info.url are set only if .onHeaders() // has not been called for this request. // // info.url is not set for response parsers but that's not // applicable here since all our parsers are request parsers. function parserOnHeadersComplete(info) { var parser = this; var headers = info.headers; var url = info.url; if (!headers) { headers = parser._headers; parser._headers = []; } if (!url) { url = parser._url; parser._url = ''; } parser.incoming = new IncomingMessage(parser.socket); parser.incoming.httpVersionMajor = info.versionMajor; parser.incoming.httpVersionMinor = info.versionMinor; parser.incoming.httpVersion = info.versionMajor + '.' + info.versionMinor; parser.incoming.url = url; var n = headers.length; // If parser.maxHeaderPairs <= 0 - assume that there're no limit if (parser.maxHeaderPairs > 0) { n = Math.min(n, parser.maxHeaderPairs); } for (var i = 0; i < n; i += 2) { var k = headers[i]; var v = headers[i + 1]; parser.incoming._addHeaderLine(k, v); } if (info.method) { // server only parser.incoming.method = info.method; } else { // client only parser.incoming.statusCode = info.statusCode; // CHECKME dead code? we're always a request parser } parser.incoming.upgrade = info.upgrade; var skipBody = false; // response to HEAD or CONNECT if (!info.upgrade) { // For upgraded connections and CONNECT method request, // we'll emit this after parser.execute // so that we can capture the first part of the new protocol skipBody = parser.onIncoming(parser.incoming, info.shouldKeepAlive); } return skipBody; } // XXX This is a mess. // TODO: http.Parser should be a Writable emits request/response events. function parserOnBody(b, start, len) { var parser = this; var stream = parser.incoming; // if the stream has already been removed, then drop it. if (!stream) return; var socket = stream.socket; // pretend this was the result of a stream._read call. if (len > 0 && !stream._dumped) { var slice = b.slice(start, start + len); var ret = stream.push(slice); if (!ret) readStop(socket); } } function parserOnMessageComplete() { var parser = this; var stream = parser.incoming; if (stream) { stream.complete = true; // Emit any trailing headers. var headers = parser._headers; if (headers) { for (var i = 0, n = headers.length; i < n; i += 2) { var k = headers[i]; var v = headers[i + 1]; parser.incoming._addHeaderLine(k, v); } parser._headers = []; parser._url = ''; } if (!stream.upgrade) // For upgraded connections, also emit this after parser.execute stream.push(null); } if (stream && !parser.incoming._pendings.length) { // For emit end event stream.push(null); } if (parser.socket.readable) { // force to read the next incoming message readStart(parser.socket); } } var parsers = new FreeList('parsers', 1000, function() { var parser = new HTTPParser(HTTPParser.REQUEST); parser._headers = []; parser._url = ''; // Only called in the slow case where slow means // that the request headers were either fragmented // across multiple TCP packets or too large to be // processed in a single run. This method is also // called to process trailing HTTP headers. parser.onHeaders = parserOnHeaders; parser.onHeadersComplete = parserOnHeadersComplete; parser.onBody = parserOnBody; parser.onMessageComplete = parserOnMessageComplete; return parser; }); exports.parsers = parsers; var CRLF = '\r\n'; var STATUS_CODES = exports.STATUS_CODES = { 100 : 'Continue', 101 : 'Switching Protocols', 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918 200 : 'OK', 201 : 'Created', 202 : 'Accepted', 203 : 'Non-Authoritative Information', 204 : 'No Content', 205 : 'Reset Content', 206 : 'Partial Content', 207 : 'Multi-Status', // RFC 4918 300 : 'Multiple Choices', 301 : 'Moved Permanently', 302 : 'Moved Temporarily', 303 : 'See Other', 304 : 'Not Modified', 305 : 'Use Proxy', 307 : 'Temporary Redirect', 400 : 'Bad Request', 401 : 'Unauthorized', 402 : 'Payment Required', 403 : 'Forbidden', 404 : 'Not Found', 405 : 'Method Not Allowed', 406 : 'Not Acceptable', 407 : 'Proxy Authentication Required', 408 : 'Request Time-out', 409 : 'Conflict', 410 : 'Gone', 411 : 'Length Required', 412 : 'Precondition Failed', 413 : 'Request Entity Too Large', 414 : 'Request-URI Too Large', 415 : 'Unsupported Media Type', 416 : 'Requested Range Not Satisfiable', 417 : 'Expectation Failed', 418 : 'I\'m a teapot', // RFC 2324 422 : 'Unprocessable Entity', // RFC 4918 423 : 'Locked', // RFC 4918 424 : 'Failed Dependency', // RFC 4918 425 : 'Unordered Collection', // RFC 4918 426 : 'Upgrade Required', // RFC 2817 428 : 'Precondition Required', // RFC 6585 429 : 'Too Many Requests', // RFC 6585 431 : 'Request Header Fields Too Large',// RFC 6585 500 : 'Internal Server Error', 501 : 'Not Implemented', 502 : 'Bad Gateway', 503 : 'Service Unavailable', 504 : 'Gateway Time-out', 505 : 'HTTP Version Not Supported', 506 : 'Variant Also Negotiates', // RFC 2295 507 : 'Insufficient Storage', // RFC 4918 509 : 'Bandwidth Limit Exceeded', 510 : 'Not Extended', // RFC 2774 511 : 'Network Authentication Required' // RFC 6585 }; var connectionExpression = /Connection/i; var transferEncodingExpression = /Transfer-Encoding/i; var closeExpression = /close/i; var chunkExpression = /chunk/i; var contentLengthExpression = /Content-Length/i; var dateExpression = /Date/i; var expectExpression = /Expect/i; var continueExpression = /100-continue/i; var dateCache; function utcDate() { if (!dateCache) { var d = new Date(); dateCache = d.toUTCString(); setTimeout(function() { dateCache = undefined; }, 1000 - d.getMilliseconds()); } return dateCache; } /* Abstract base class for ServerRequest and ClientResponse. */ function IncomingMessage(socket) { Stream.Readable.call(this); // XXX This implementation is kind of all over the place // When the parser emits body chunks, they go in this list. // _read() pulls them out, and when it finds EOF, it ends. this.socket = socket; this.connection = socket; this.httpVersion = null; this.complete = false; this.headers = {}; this.trailers = {}; this.readable = true; this._pendings = []; this._pendingIndex = 0; // request (server) only this.url = ''; this.method = null; // response (client) only this.statusCode = null; this.client = this.socket; // flag for backwards compatibility grossness. this._consuming = false; // flag for when we decide that this message cannot possibly be // read by the user, so there's no point continuing to handle it. this._dumped = false; } util.inherits(IncomingMessage, Stream.Readable); exports.IncomingMessage = IncomingMessage; IncomingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); this.socket.setTimeout(msecs); }; IncomingMessage.prototype.read = function(n) { this._consuming = true; this.read = Stream.Readable.prototype.read; return this.read(n); }; IncomingMessage.prototype._read = function(n) { // We actually do almost nothing here, because the parserOnBody // function fills up our internal buffer directly. However, we // do need to unpause the underlying socket so that it flows. if (!this.socket.readable) this.push(null); else readStart(this.socket); }; // It's possible that the socket will be destroyed, and removed from // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. IncomingMessage.prototype.destroy = function(error) { if (this.socket) this.socket.destroy(error); }; // Add the given (field, value) pair to the message // // Per RFC2616, section 4.2 it is acceptable to join multiple instances of the // same header with a ', ' if the header in question supports specification of // multiple values this way. If not, we declare the first instance the winner // and drop the second. Extended header fields (those beginning with 'x-') are // always joined. IncomingMessage.prototype._addHeaderLine = function(field, value) { var dest = this.complete ? this.trailers : this.headers; field = field.toLowerCase(); switch (field) { // Array headers: case 'set-cookie': if (dest[field] !== undefined) { dest[field].push(value); } else { dest[field] = [value]; } break; // Comma separate. Maybe make these arrays? case 'accept': case 'accept-charset': case 'accept-encoding': case 'accept-language': case 'connection': case 'cookie': case 'pragma': case 'link': case 'www-authenticate': case 'proxy-authenticate': case 'sec-websocket-extensions': case 'sec-websocket-protocol': if (dest[field] !== undefined) { dest[field] += ', ' + value; } else { dest[field] = value; } break; default: if (field.slice(0, 2) == 'x-') { // except for x- if (dest[field] !== undefined) { dest[field] += ', ' + value; } else { dest[field] = value; } } else { // drop duplicates if (dest[field] === undefined) dest[field] = value; } break; } }; // Call this instead of resume() if we want to just // dump all the data to /dev/null IncomingMessage.prototype._dump = function() { if (!this._dumped) { this._dumped = true; if (this.socket.parser) this.socket.parser.incoming = null; this.push(null); readStart(this.socket); this.read(); } }; function OutgoingMessage() { Stream.call(this); this.output = []; this.outputEncodings = []; this.writable = true; this._last = false; this.chunkedEncoding = false; this.shouldKeepAlive = true; this.useChunkedEncodingByDefault = true; this.sendDate = false; this._hasBody = true; this._trailer = ''; this.finished = false; this._hangupClose = false; this.socket = null; this.connection = null; } util.inherits(OutgoingMessage, Stream); exports.OutgoingMessage = OutgoingMessage; OutgoingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); if (!this.socket) { this.once('socket', function(socket) { socket.setTimeout(msecs); }); } else this.socket.setTimeout(msecs); }; // It's possible that the socket will be destroyed, and removed from // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. OutgoingMessage.prototype.destroy = function(error) { if (this.socket) this.socket.destroy(error); else this.once('socket', function(socket) { socket.destroy(error); }); }; // This abstract either writing directly to the socket or buffering it. OutgoingMessage.prototype._send = function(data, encoding) { // This is a shameful hack to get the headers and first body chunk onto // the same packet. Future versions of Node are going to take care of // this at a lower level and in a more general way. if (!this._headerSent) { if (typeof data === 'string') { data = this._header + data; } else { this.output.unshift(this._header); this.outputEncodings.unshift('ascii'); } this._headerSent = true; } return this._writeRaw(data, encoding); }; OutgoingMessage.prototype._writeRaw = function(data, encoding) { if (data.length === 0) { return true; } if (this.connection && this.connection._httpMessage === this && this.connection.writable && !this.connection.destroyed) { // There might be pending data in the this.output buffer. while (this.output.length) { if (!this.connection.writable) { this._buffer(data, encoding); return false; } var c = this.output.shift(); var e = this.outputEncodings.shift(); this.connection.write(c, e); } // Directly write to socket. return this.connection.write(data, encoding); } else if (this.connection && this.connection.destroyed) { // The socket was destroyed. If we're still trying to write to it, // then we haven't gotten the 'close' event yet. return false; } else { // buffer, as long as we're not destroyed. this._buffer(data, encoding); return false; } }; OutgoingMessage.prototype._buffer = function(data, encoding) { if (data.length === 0) return; var length = this.output.length; if (length === 0 || typeof data != 'string') { this.output.push(data); this.outputEncodings.push(encoding); return false; } var lastEncoding = this.outputEncodings[length - 1]; var lastData = this.output[length - 1]; if ((encoding && lastEncoding === encoding) || (!encoding && data.constructor === lastData.constructor)) { this.output[length - 1] = lastData + data; return false; } this.output.push(data); this.outputEncodings.push(encoding); return false; }; OutgoingMessage.prototype._storeHeader = function(firstLine, headers) { // firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n' // in the case of response it is: 'HTTP/1.1 200 OK\r\n' var state = { sentConnectionHeader: false, sentContentLengthHeader: false, sentTransferEncodingHeader: false, sentDateHeader: false, sentExpect: false, messageHeader: firstLine }; var field, value; var self = this; if (headers) { var keys = Object.keys(headers); var isArray = (Array.isArray(headers)); var field, value; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; } else { field = key; value = headers[key]; } if (Array.isArray(value)) { for (var j = 0; j < value.length; j++) { storeHeader(this, state, field, value[j]); } } else { storeHeader(this, state, field, value); } } } // Date header if (this.sendDate == true && state.sentDateHeader == false) { state.messageHeader += 'Date: ' + utcDate() + CRLF; } // Force the connection to close when the response is a 204 No Content or // a 304 Not Modified and the user has set a "Transfer-Encoding: chunked" // header. // // RFC 2616 mandates that 204 and 304 responses MUST NOT have a body but // node.js used to send out a zero chunk anyway to accommodate clients // that don't have special handling for those responses. // // It was pointed out that this might confuse reverse proxies to the point // of creating security liabilities, so suppress the zero chunk and force // the connection to close. var statusCode = this.statusCode; if ((statusCode == 204 || statusCode === 304) && this.chunkedEncoding === true) { debug(statusCode + ' response should not use chunked encoding,' + ' closing connection.'); this.chunkedEncoding = false; this.shouldKeepAlive = false; } // keep-alive logic if (state.sentConnectionHeader === false) { var shouldSendKeepAlive = this.shouldKeepAlive && (state.sentContentLengthHeader || this.useChunkedEncodingByDefault || this.agent); if (shouldSendKeepAlive) { state.messageHeader += 'Connection: keep-alive\r\n'; } else { this._last = true; state.messageHeader += 'Connection: close\r\n'; } } if (state.sentContentLengthHeader == false && state.sentTransferEncodingHeader == false) { if (this._hasBody) { if (this.useChunkedEncodingByDefault) { state.messageHeader += 'Transfer-Encoding: chunked\r\n'; this.chunkedEncoding = true; } else { this._last = true; } } else { // Make sure we don't end the 0\r\n\r\n at the end of the message. this.chunkedEncoding = false; } } this._header = state.messageHeader + CRLF; this._headerSent = false; // wait until the first body chunk, or close(), is sent to flush, // UNLESS we're sending Expect: 100-continue. if (state.sentExpect) this._send(''); }; function storeHeader(self, state, field, value) { // Protect against response splitting. The if statement is there to // minimize the performance impact in the common case. if (/[\r\n]/.test(value)) value = value.replace(/[\r\n]+[ \t]*/g, ''); state.messageHeader += field + ': ' + value + CRLF; if (connectionExpression.test(field)) { state.sentConnectionHeader = true; if (closeExpression.test(value)) { self._last = true; } else { self.shouldKeepAlive = true; } } else if (transferEncodingExpression.test(field)) { state.sentTransferEncodingHeader = true; if (chunkExpression.test(value)) self.chunkedEncoding = true; } else if (contentLengthExpression.test(field)) { state.sentContentLengthHeader = true; } else if (dateExpression.test(field)) { state.sentDateHeader = true; } else if (expectExpression.test(field)) { state.sentExpect = true; } } OutgoingMessage.prototype.setHeader = function(name, value) { if (arguments.length < 2) { throw new Error('`name` and `value` are required for setHeader().'); } if (this._header) { throw new Error('Can\'t set headers after they are sent.'); } var key = name.toLowerCase(); this._headers = this._headers || {}; this._headerNames = this._headerNames || {}; this._headers[key] = value; this._headerNames[key] = name; }; OutgoingMessage.prototype.getHeader = function(name) { if (arguments.length < 1) { throw new Error('`name` is required for getHeader().'); } if (!this._headers) return; var key = name.toLowerCase(); return this._headers[key]; }; OutgoingMessage.prototype.removeHeader = function(name) { if (arguments.length < 1) { throw new Error('`name` is required for removeHeader().'); } if (this._header) { throw new Error('Can\'t remove headers after they are sent.'); } if (!this._headers) return; var key = name.toLowerCase(); delete this._headers[key]; delete this._headerNames[key]; }; OutgoingMessage.prototype._renderHeaders = function() { if (this._header) { throw new Error('Can\'t render headers after they are sent to the client.'); } if (!this._headers) return {}; var headers = {}; var keys = Object.keys(this._headers); for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; headers[this._headerNames[key]] = this._headers[key]; } return headers; }; Object.defineProperty(OutgoingMessage.prototype, 'headersSent', { configurable: true, enumerable: true, get: function() { return !!this._header; } }); OutgoingMessage.prototype.write = function(chunk, encoding) { if (!this._header) { this._implicitHeader(); } if (!this._hasBody) { debug('This type of response MUST NOT have a body. ' + 'Ignoring write() calls.'); return true; } if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) { throw new TypeError('first argument must be a string or Buffer'); } // If we get an empty string or buffer, then just do nothing, and // signal the user to keep writing. if (chunk.length === 0) return true; // TODO(bnoordhuis) Temporary optimization hack, remove in v0.11. We only // want to convert the buffer when we're sending: // // a) Transfer-Encoding chunks, because it lets us pack the chunk header // and the chunk into a single write(), or // // b) the first chunk of a fixed-length request, because it lets us pack // the request headers and the chunk into a single write(). // // Converting to strings is expensive, CPU-wise, but reducing the number // of write() calls more than makes up for that because we're dramatically // reducing the number of TCP roundtrips. if (chunk instanceof Buffer && (this.chunkedEncoding || !this._headerSent)) { chunk = chunk.toString('binary'); encoding = 'binary'; } var len, ret; if (this.chunkedEncoding) { if (typeof(chunk) === 'string' && encoding !== 'hex' && encoding !== 'base64') { len = Buffer.byteLength(chunk, encoding); chunk = len.toString(16) + CRLF + chunk + CRLF; ret = this._send(chunk, encoding); } else { // buffer, or a non-toString-friendly encoding len = chunk.length; this._send(len.toString(16) + CRLF); this._send(chunk, encoding); ret = this._send(CRLF); } } else { ret = this._send(chunk, encoding); } debug('write ret = ' + ret); return ret; }; OutgoingMessage.prototype.addTrailers = function(headers) { this._trailer = ''; var keys = Object.keys(headers); var isArray = (Array.isArray(headers)); var field, value; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; } else { field = key; value = headers[key]; } this._trailer += field + ': ' + value + CRLF; } }; var zero_chunk_buf = new Buffer('\r\n0\r\n'); var crlf_buf = new Buffer('\r\n'); OutgoingMessage.prototype.end = function(data, encoding) { if (this.finished) { return false; } if (!this._header) { this._implicitHeader(); } if (data && !this._hasBody) { debug('This type of response MUST NOT have a body. ' + 'Ignoring data passed to end().'); data = false; } var ret; var hot = this._headerSent === false && (data && data.length > 0) && this.output.length === 0 && this.connection && this.connection.writable && this.connection._httpMessage === this; // The benefits of the hot-path optimization below start to fall // off when the buffer size gets up near 128KB, because the cost // of the copy is more than the cost of the extra write() call. // Switch to the write/end method at that point. Heuristics and // magic numbers are awful, but slow http responses are worse. if (hot && Buffer.isBuffer(data) && data.length > 120 * 1024) hot = false; if (hot) { // Hot path. They're doing // res.writeHead(); // res.end(blah); // HACKY. if (typeof data === 'string') { if (this.chunkedEncoding) { var l = Buffer.byteLength(data, encoding).toString(16); ret = this.connection.write(this._header + l + CRLF + data + '\r\n0\r\n' + this._trailer + '\r\n', encoding); } else { ret = this.connection.write(this._header + data, encoding); } } else if (Buffer.isBuffer(data)) { if (this.chunkedEncoding) { var chunk_size = data.length.toString(16); // Skip expensive Buffer.byteLength() calls; only ISO-8859-1 characters // are allowed in HTTP headers. Therefore: // // this._header.length == Buffer.byteLength(this._header.length) // this._trailer.length == Buffer.byteLength(this._trailer.length) // var header_len = this._header.length; var chunk_size_len = chunk_size.length; var data_len = data.length; var trailer_len = this._trailer.length; var len = header_len + chunk_size_len + 2 + // '\r\n'.length data_len + 5 + // '\r\n0\r\n'.length trailer_len + 2; // '\r\n'.length var buf = new Buffer(len); var off = 0; buf.write(this._header, off, header_len, 'ascii'); off += header_len; buf.write(chunk_size, off, chunk_size_len, 'ascii'); off += chunk_size_len; crlf_buf.copy(buf, off); off += 2; data.copy(buf, off); off += data_len; zero_chunk_buf.copy(buf, off); off += 5; if (trailer_len > 0) { buf.write(this._trailer, off, trailer_len, 'ascii'); off += trailer_len; } crlf_buf.copy(buf, off); ret = this.connection.write(buf); } else { var header_len = this._header.length; var buf = new Buffer(header_len + data.length); buf.write(this._header, 0, header_len, 'ascii'); data.copy(buf, header_len); ret = this.connection.write(buf); } } else { throw new TypeError('first argument must be a string or Buffer'); } this._headerSent = true; } else if (data) { // Normal body write. ret = this.write(data, encoding); } if (!hot) { if (this.chunkedEncoding) { ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk. } else { // Force a flush, HACK. ret = this._send(''); } } this.finished = true; // There is the first message on the outgoing queue, and we've sent // everything to the socket. debug('outgoing message end.'); if (this.output.length === 0 && this.connection._httpMessage === this) { this._finish(); } return ret; }; OutgoingMessage.prototype._finish = function() { assert(this.connection); if (this instanceof ServerResponse) { DTRACE_HTTP_SERVER_RESPONSE(this.connection); COUNTER_HTTP_SERVER_RESPONSE(); } else { assert(this instanceof ClientRequest); DTRACE_HTTP_CLIENT_REQUEST(this, this.connection); COUNTER_HTTP_CLIENT_REQUEST(); } this.emit('finish'); }; OutgoingMessage.prototype._flush = function() { // This logic is probably a bit confusing. Let me explain a bit: // // In both HTTP servers and clients it is possible to queue up several // outgoing messages. This is easiest to imagine in the case of a client. // Take the following situation: // // req1 = client.request('GET', '/'); // req2 = client.request('POST', '/'); // // When the user does // // req2.write('hello world\n'); // // it's possible that the first request has not been completely flushed to // the socket yet. Thus the outgoing messages need to be prepared to queue // up data internally before sending it on further to the socket's queue. // // This function, outgoingFlush(), is called by both the Server and Client // to attempt to flush any pending messages out to the socket. if (!this.socket) return; var ret; while (this.output.length) { if (!this.socket.writable) return; // XXX Necessary? var data = this.output.shift(); var encoding = this.outputEncodings.shift(); ret = this.socket.write(data, encoding); } if (this.finished) { // This is a queue to the server or client to bring in the next this. this._finish(); } else if (ret) { // This is necessary to prevent https from breaking this.emit('drain'); } }; function ServerResponse(req) { OutgoingMessage.call(this); if (req.method === 'HEAD') this._hasBody = false; this.sendDate = true; if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) { this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te); this.shouldKeepAlive = false; } } util.inherits(ServerResponse, OutgoingMessage); exports.ServerResponse = ServerResponse; ServerResponse.prototype.statusCode = 200; function onServerResponseClose() { // EventEmitter.emit makes a copy of the 'close' listeners array before // calling the listeners. detachSocket() unregisters onServerResponseClose // but if detachSocket() is called, directly or indirectly, by a 'close' // listener, onServerResponseClose is still in that copy of the listeners // array. That is, in the example below, b still gets called even though // it's been removed by a: // // var obj = new events.EventEmitter; // obj.on('event', a); // obj.on('event', b); // function a() { obj.removeListener('event', b) } // function b() { throw "BAM!" } // obj.emit('event'); // throws // // Ergo, we need to deal with stale 'close' events and handle the case // where the ServerResponse object has already been deconstructed. // Fortunately, that requires only a single if check. :-) if (this._httpMessage) this._httpMessage.emit('close'); } ServerResponse.prototype.assignSocket = function(socket) { assert(!socket._httpMessage); socket._httpMessage = this; socket.on('close', onServerResponseClose); this.socket = socket; this.connection = socket; this.emit('socket', socket); this._flush(); }; ServerResponse.prototype.detachSocket = function(socket) { assert(socket._httpMessage == this); socket.removeListener('close', onServerResponseClose); socket._httpMessage = null; this.socket = this.connection = null; }; ServerResponse.prototype.writeContinue = function() { this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii'); this._sent100 = true; }; ServerResponse.prototype._implicitHeader = function() { this.writeHead(this.statusCode); }; ServerResponse.prototype.writeHead = function(statusCode) { var reasonPhrase, headers, headerIndex; if (typeof arguments[1] == 'string') { reasonPhrase = arguments[1]; headerIndex = 2; } else { reasonPhrase = STATUS_CODES[statusCode] || 'unknown'; headerIndex = 1; } this.statusCode = statusCode; var obj = arguments[headerIndex]; if (obj && this._headers) { // Slow-case: when progressive API and header fields are passed. headers = this._renderHeaders(); if (Array.isArray(obj)) { // handle array case // TODO: remove when array is no longer accepted var field; for (var i = 0, len = obj.length; i < len; ++i) { field = obj[i][0]; if (headers[field] !== undefined) { obj.push([field, headers[field]]); } } headers = obj; } else { // handle object case var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { var k = keys[i]; if (k) headers[k] = obj[k]; } } } else if (this._headers) { // only progressive api is used headers = this._renderHeaders(); } else { // only writeHead() called headers = obj; } var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' + reasonPhrase + CRLF; if (statusCode === 204 || statusCode === 304 || (100 <= statusCode && statusCode <= 199)) { // RFC 2616, 10.2.5: // The 204 response MUST NOT include a message-body, and thus is always // terminated by the first empty line after the header fields. // RFC 2616, 10.3.5: // The 304 response MUST NOT contain a message-body, and thus is always // terminated by the first empty line after the header fields. // RFC 2616, 10.1 Informational 1xx: // This class of status code indicates a provisional response, // consisting only of the Status-Line and optional headers, and is // terminated by an empty line. this._hasBody = false; } // don't keep alive connections where the client expects 100 Continue // but we sent a final status; they may put extra bytes on the wire. if (this._expect_continue && !this._sent100) { this.shouldKeepAlive = false; } this._storeHeader(statusLine, headers); }; ServerResponse.prototype.writeHeader = function() { this.writeHead.apply(this, arguments); }; // New Agent code. // The largest departure from the previous implementation is that // an Agent instance holds connections for a variable number of host:ports. // Surprisingly, this is still API compatible as far as third parties are // concerned. The only code that really notices the difference is the // request object. // Another departure is that all code related to HTTP parsing is in // ClientRequest.onSocket(). The Agent is now *strictly* // concerned with managing a connection pool. function Agent(options) { EventEmitter.call(this); var self = this; self.options = options || {}; self.requests = {}; self.sockets = {}; self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets; self.on('free', function(socket, host, port, localAddress) { var name = host + ':' + port; if (localAddress) { name += ':' + localAddress; } if (!socket.destroyed && self.requests[name] && self.requests[name].length) { self.requests[name].shift().onSocket(socket); if (self.requests[name].length === 0) { // don't leak delete self.requests[name]; } } else { // If there are no pending requests just destroy the // socket and it will get removed from the pool. This // gets us out of timeout issues and allows us to // default to Connection:keep-alive. socket.destroy(); } }); self.createConnection = net.createConnection; } util.inherits(Agent, EventEmitter); exports.Agent = Agent; Agent.defaultMaxSockets = 5; Agent.prototype.defaultPort = 80; Agent.prototype.addRequest = function(req, host, port, localAddress) { var name = host + ':' + port; if (localAddress) { name += ':' + localAddress; } if (!this.sockets[name]) { this.sockets[name] = []; } if (this.sockets[name].length < this.maxSockets) { // If we are under maxSockets create a new one. req.onSocket(this.createSocket(name, host, port, localAddress, req)); } else { // We are over limit so we'll add it to the queue. if (!this.requests[name]) { this.requests[name] = []; } this.requests[name].push(req); } }; Agent.prototype.createSocket = function(name, host, port, localAddress, req) { var self = this; var options = util._extend({}, self.options); options.port = port; options.host = host; options.localAddress = localAddress; options.servername = host; if (req) { var hostHeader = req.getHeader('host'); if (hostHeader) { options.servername = hostHeader.replace(/:.*$/, ''); } } var s = self.createConnection(options); if (!self.sockets[name]) { self.sockets[name] = []; } this.sockets[name].push(s); var onFree = function() { self.emit('free', s, host, port, localAddress); } s.on('free', onFree); var onClose = function(err) { // This is the only place where sockets get removed from the Agent. // If you want to remove a socket from the pool, just close it. // All socket errors end in a close event anyway. self.removeSocket(s, name, host, port, localAddress); } s.on('close', onClose); var onRemove = function() { // We need this function for cases like HTTP 'upgrade' // (defined by WebSockets) where we need to remove a socket from the pool // because it'll be locked up indefinitely self.removeSocket(s, name, host, port, localAddress); s.removeListener('close', onClose); s.removeListener('free', onFree); s.removeListener('agentRemove', onRemove); } s.on('agentRemove', onRemove); return s; }; Agent.prototype.removeSocket = function(s, name, host, port, localAddress) { if (this.sockets[name]) { var index = this.sockets[name].indexOf(s); if (index !== -1) { this.sockets[name].splice(index, 1); if (this.sockets[name].length === 0) { // don't leak delete this.sockets[name]; } } } if (this.requests[name] && this.requests[name].length) { var req = this.requests[name][0]; // If we have pending requests and a socket gets closed a new one this.createSocket(name, host, port, localAddress, req).emit('free'); } }; var globalAgent = new Agent(); exports.globalAgent = globalAgent; function ClientRequest(options, cb) { var self = this; OutgoingMessage.call(self); self.agent = options.agent === undefined ? globalAgent : options.agent; var defaultPort = options.defaultPort || 80; var port = options.port || defaultPort; var host = options.hostname || options.host || 'localhost'; if (options.setHost === undefined) { var setHost = true; } self.socketPath = options.socketPath; var method = self.method = (options.method || 'GET').toUpperCase(); self.path = options.path || '/'; if (cb) { self.once('response', cb); } if (!Array.isArray(options.headers)) { if (options.headers) { var keys = Object.keys(options.headers); for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; self.setHeader(key, options.headers[key]); } } if (host && !this.getHeader('host') && setHost) { var hostHeader = host; if (port && +port !== defaultPort) { hostHeader += ':' + port; } this.setHeader('Host', hostHeader); } } if (options.auth && !this.getHeader('Authorization')) { //basic auth this.setHeader('Authorization', 'Basic ' + new Buffer(options.auth).toString('base64')); } if (method === 'GET' || method === 'HEAD' || method === 'CONNECT') { self.useChunkedEncodingByDefault = false; } else { self.useChunkedEncodingByDefault = true; } if (Array.isArray(options.headers)) { self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', options.headers); } else if (self.getHeader('expect')) { self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', self._renderHeaders()); } if (self.socketPath) { self._last = true; self.shouldKeepAlive = false; if (options.createConnection) { self.onSocket(options.createConnection(self.socketPath)); } else { self.onSocket(net.createConnection(self.socketPath)); } } else if (self.agent) { // If there is an agent we should default to Connection:keep-alive. self._last = false; self.shouldKeepAlive = true; self.agent.addRequest(self, host, port, options.localAddress); } else { // No agent, default to Connection:close. self._last = true; self.shouldKeepAlive = false; if (options.createConnection) { options.port = port; options.host = host; var conn = options.createConnection(options); } else { var conn = net.createConnection({ port: port, host: host, localAddress: options.localAddress }); } self.onSocket(conn); } self._deferToConnect(null, null, function() { self._flush(); self = null; }); } util.inherits(ClientRequest, OutgoingMessage); exports.ClientRequest = ClientRequest; ClientRequest.prototype._implicitHeader = function() { this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', this._renderHeaders()); }; ClientRequest.prototype.abort = function() { if (this.socket) { // in-progress this.socket.destroy(); } else { // haven't been assigned a socket yet. // this could be more efficient, it could // remove itself from the pending requests this._deferToConnect('destroy', []); } }; function createHangUpError() { var error = new Error('socket hang up'); error.code = 'ECONNRESET'; return error; } // Free the parser and also break any links that it // might have to any other things. // TODO: All parser data should be attached to a // single object, so that it can be easily cleaned // up by doing `parser.data = {}`, which should // be done in FreeList.free. `parsers.free(parser)` // should be all that is needed. function freeParser(parser, req) { if (parser) { parser._headers = []; parser.onIncoming = null; if (parser.socket) { parser.socket.onend = null; parser.socket.ondata = null; parser.socket.parser = null; } parser.socket = null; parser.incoming = null; parsers.free(parser); parser = null; } if (req) { req.parser = null; } } function socketCloseListener() { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP socket close'); req.emit('close'); if (req.res && req.res.readable) { // Socket closed before we emitted 'end' below. req.res.emit('aborted'); var res = req.res; res.on('end', function() { res.emit('close'); }); res.push(null); } else if (!req.res && !req._hadError) { // This socket error fired before we started to // receive a response. The error needs to // fire on the request. req.emit('error', createHangUpError()); req._hadError = true; } // Too bad. That output wasn't getting written. // This is pretty terrible that it doesn't raise an error. // Fixed better in v0.10 if (req.output) req.output.length = 0; if (req.outputEncodings) req.outputEncodings.length = 0; if (parser) { parser.finish(); freeParser(parser, req); } } function socketErrorListener(err) { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP SOCKET ERROR: ' + err.message + '\n' + err.stack); if (req) { req.emit('error', err); // For Safety. Some additional errors might fire later on // and we need to make sure we don't double-fire the error event. req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } function socketOnEnd() { var socket = this; var req = this._httpMessage; var parser = this.parser; if (!req.res) { // If we don't have a response then we know that the socket // ended prematurely and we need to emit an error on the request. req.emit('error', createHangUpError()); req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } function socketOnData(d, start, end) { var socket = this; var req = this._httpMessage; var parser = this.parser; var ret = parser.execute(d, start, end - start); if (ret instanceof Error) { debug('parse error'); freeParser(parser, req); socket.destroy(); req.emit('error', ret); req._hadError = true; } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT var bytesParsed = ret; var res = parser.incoming; req.res = res; socket.ondata = null; socket.onend = null; parser.finish(); // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (EventEmitter.listenerCount(req, eventName) > 0) { req.upgradeOrConnect = true; // detach the socket socket.emit('agentRemove'); socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); socket.unshift(bodyHead); req.emit(eventName, res, socket, emptyBuffer); req.emit('close'); } else { // Got Upgrade header or CONNECT method, but have no handler. socket.destroy(); } freeParser(parser, req); } else if (parser.incoming && parser.incoming.complete && // When the status code is 100 (Continue), the server will // send a final response after this client sends a request // body. So, we must not free the parser. parser.incoming.statusCode !== 100) { freeParser(parser, req); } } // client function parserOnIncomingClient(res, shouldKeepAlive) { var parser = this; var socket = this.socket; var req = socket._httpMessage; // propogate "domain" setting... if (req.domain && !res.domain) { debug('setting "res.domain"'); res.domain = req.domain; } debug('AGENT incoming response!'); if (req.res) { // We already have a response object, this means the server // sent a double response. socket.destroy(); return; } req.res = res; // Responses to CONNECT request is handled as Upgrade. if (req.method === 'CONNECT') { res.upgrade = true; return true; // skip body } // Responses to HEAD requests are crazy. // HEAD responses aren't allowed to have an entity-body // but *can* have a content-length which actually corresponds // to the content-length of the entity-body had the request // been a GET. var isHeadResponse = req.method == 'HEAD'; debug('AGENT isHeadResponse ' + isHeadResponse); if (res.statusCode == 100) { // restart the parser, as this is a continue message. delete req.res; // Clear res so that we don't hit double-responses. req.emit('continue'); return true; } if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) { // Server MUST respond with Connection:keep-alive for us to enable it. // If we've been upgraded (via WebSockets) we also shouldn't try to // keep the connection open. req.shouldKeepAlive = false; } DTRACE_HTTP_CLIENT_RESPONSE(socket, req); COUNTER_HTTP_CLIENT_RESPONSE(); req.res = res; res.req = req; // add our listener first, so that we guarantee socket cleanup res.on('end', responseOnEnd); var handled = req.emit('response', res); // If the user did not listen for the 'response' event, then they // can't possibly read the data, so we ._dump() it into the void // so that the socket doesn't hang there in a paused state. if (!handled) res._dump(); return isHeadResponse; } // client function responseOnEnd() { var res = this; var req = res.req; var socket = req.socket; if (!req.shouldKeepAlive) { if (socket.writable) { debug('AGENT socket.destroySoon()'); socket.destroySoon(); } assert(!socket.writable); } else { debug('AGENT socket keep-alive'); if (req.timeoutCb) { socket.setTimeout(0, req.timeoutCb); req.timeoutCb = null; } socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); // Mark this socket as available, AFTER user-added end // handlers have a chance to run. process.nextTick(function() { socket.emit('free'); }); } } ClientRequest.prototype.onSocket = function(socket) { var req = this; process.nextTick(function() { var parser = parsers.alloc(); req.socket = socket; req.connection = socket; parser.reinitialize(HTTPParser.RESPONSE); parser.socket = socket; parser.incoming = null; req.parser = parser; socket.parser = parser; socket._httpMessage = req; // Setup "drain" propogation. httpSocketSetup(socket); // Propagate headers limit from request object to parser if (typeof req.maxHeadersCount === 'number') { parser.maxHeaderPairs = req.maxHeadersCount << 1; } else { // Set default value because parser may be reused from FreeList parser.maxHeaderPairs = 2000; } socket.on('error', socketErrorListener); socket.ondata = socketOnData; socket.onend = socketOnEnd; socket.on('close', socketCloseListener); parser.onIncoming = parserOnIncomingClient; req.emit('socket', socket); }); }; ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) { // This function is for calls that need to happen once the socket is // connected and writable. It's an important promisy thing for all the socket // calls that happen either now (when a socket is assigned) or // in the future (when a socket gets assigned out of the pool and is // eventually writable). var self = this; var onSocket = function() { if (self.socket.writable) { if (method) { self.socket[method].apply(self.socket, arguments_); } if (cb) { cb(); } } else { self.socket.once('connect', function() { if (method) { self.socket[method].apply(self.socket, arguments_); } if (cb) { cb(); } }); } } if (!self.socket) { self.once('socket', onSocket); } else { onSocket(); } }; ClientRequest.prototype.setTimeout = function(msecs, callback) { if (callback) this.once('timeout', callback); var self = this; function emitTimeout() { self.emit('timeout'); } if (this.socket && this.socket.writable) { if (this.timeoutCb) this.socket.setTimeout(0, this.timeoutCb); this.timeoutCb = emitTimeout; this.socket.setTimeout(msecs, emitTimeout); return; } // Set timeoutCb so that it'll get cleaned up on request end this.timeoutCb = emitTimeout; if (this.socket) { var sock = this.socket; this.socket.once('connect', function() { sock.setTimeout(msecs, emitTimeout); }); return; } this.once('socket', function(sock) { sock.setTimeout(msecs, emitTimeout); }); }; ClientRequest.prototype.setNoDelay = function() { this._deferToConnect('setNoDelay', arguments); }; ClientRequest.prototype.setSocketKeepAlive = function() { this._deferToConnect('setKeepAlive', arguments); }; ClientRequest.prototype.clearTimeout = function(cb) { this.setTimeout(0, cb); }; exports.request = function(options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'http:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } return new ClientRequest(options, cb); }; exports.get = function(options, cb) { var req = exports.request(options, cb); req.end(); return req; }; function ondrain() { if (this._httpMessage) this._httpMessage.emit('drain'); } function httpSocketSetup(socket) { socket.removeListener('drain', ondrain); socket.on('drain', ondrain); } function Server(requestListener) { if (!(this instanceof Server)) return new Server(requestListener); net.Server.call(this, { allowHalfOpen: true }); if (requestListener) { this.addListener('request', requestListener); } // Similar option to this. Too lazy to write my own docs. // http://www.squid-cache.org/Doc/config/half_closed_clients/ // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F this.httpAllowHalfOpen = false; this.addListener('connection', connectionListener); this.addListener('clientError', function(err, conn) { conn.destroy(err); }); this.timeout = 2 * 60 * 1000; } util.inherits(Server, net.Server); Server.prototype.setTimeout = function(msecs, callback) { this.timeout = msecs; if (callback) this.on('timeout', callback); }; exports.Server = Server; exports.createServer = function(requestListener) { return new Server(requestListener); }; function connectionListener(socket) { var self = this; var outgoing = []; var incoming = []; function abortIncoming() { while (incoming.length) { var req = incoming.shift(); req.emit('aborted'); req.emit('close'); } // abort socket._httpMessage ? } function serverSocketCloseListener() { debug('server socket close'); // mark this parser as reusable if (this.parser) freeParser(this.parser); abortIncoming(); } debug('SERVER new http connection'); httpSocketSetup(socket); // If the user has added a listener to the server, // request, or response, then it's their responsibility. // otherwise, destroy on timeout by default if (self.timeout) socket.setTimeout(self.timeout); socket.on('timeout', function() { var req = socket.parser && socket.parser.incoming; var reqTimeout = req && !req.complete && req.emit('timeout', socket); var res = socket._httpMessage; var resTimeout = res && res.emit('timeout', socket); var serverTimeout = self.emit('timeout', socket); if (!reqTimeout && !resTimeout && !serverTimeout) socket.destroy(); }); var parser = parsers.alloc(); parser.reinitialize(HTTPParser.REQUEST); parser.socket = socket; socket.parser = parser; parser.incoming = null; // Propagate headers limit from server instance to parser if (typeof this.maxHeadersCount === 'number') { parser.maxHeaderPairs = this.maxHeadersCount << 1; } else { // Set default value because parser may be reused from FreeList parser.maxHeaderPairs = 2000; } socket.addListener('error', function(e) { self.emit('clientError', e, this); }); socket.ondata = function (d, start, end) { assert(!socket._drain_paused); var ret = parser.execute(d, start, end - start); if (ret instanceof Error) { debug('parse error'); socket.destroy(ret); } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT var bytesParsed = ret; var req = parser.incoming; socket.ondata = null; socket.onend = null; socket.removeListener('close', serverSocketCloseListener); parser.finish(); freeParser(parser, req); // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (EventEmitter.listenerCount(self, eventName) > 0) { socket.unshift(bodyHead); self.emit(eventName, req, req.socket, emptyBuffer); } else { // Got upgrade header or CONNECT method, but have no handler. socket.destroy(); } if (socket._drain_paused) { // onIncoming paused the socket, we should pause the parser as well debug('pause parser'); socket.parser.pause(); } } }; socket.onend = function() { var ret = parser.finish(); if (ret instanceof Error) { debug('parse error'); socket.destroy(ret); return; } if (!self.httpAllowHalfOpen) { abortIncoming(); if (socket.writable) socket.end(); } else if (outgoing.length) { outgoing[outgoing.length - 1]._last = true; } else if (socket._httpMessage) { socket._httpMessage._last = true; } else { if (socket.writable) socket.end(); } }; socket.addListener('close', serverSocketCloseListener); socket._drain_paused = false; function socketOnDrain() { // If we previously paused, then start reading again. if (socket._drain_paused) { socket._drain_paused = false; socket.parser.resume(); socket.resume(); } } socket.on('drain', socketOnDrain); // The following callback is issued after the headers have been read on a // new message. In this callback we setup the response object and pass it // to the user. parser.onIncoming = function(req, shouldKeepAlive) { incoming.push(req); // If the writable end isn't consuming, then stop reading // so that we don't become overwhelmed by a flood of // pipelined requests that may never be resolved. if (!socket._drain_paused && socket._handle) { var needPause = socket._handle.writeQueueSize > 0; if (needPause) { socket._drain_paused = true; // We also need to pause the parser, but don't do that until after // the call to execute, because we may still be processing the last // chunk. socket.pause(); } } var res = new ServerResponse(req); res.shouldKeepAlive = shouldKeepAlive; DTRACE_HTTP_SERVER_REQUEST(req, socket); COUNTER_HTTP_SERVER_REQUEST(); if (socket._httpMessage) { // There are already pending outgoing res, append. outgoing.push(res); } else { res.assignSocket(socket); } // When we're finished writing the response, check if this is the last // respose, if so destroy the socket. res.on('finish', function() { // Usually the first incoming element should be our request. it may // be that in the case abortIncoming() was called that the incoming // array will be empty. assert(incoming.length == 0 || incoming[0] === req); incoming.shift(); // if the user never called req.read(), and didn't pipe() or // .resume() or .on('data'), then we call req._dump() so that the // bytes will be pulled off the wire. if (!req._consuming) req._dump(); res.detachSocket(socket); if (res._last) { socket.destroySoon(); } else { // start sending the next message var m = outgoing.shift(); if (m) { m.assignSocket(socket); } } }); if (req.headers.expect !== undefined && (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) && continueExpression.test(req.headers['expect'])) { res._expect_continue = true; if (EventEmitter.listenerCount(self, 'checkContinue') > 0) { self.emit('checkContinue', req, res); } else { res.writeContinue(); self.emit('request', req, res); } } else { self.emit('request', req, res); } return false; // Not a HEAD response. (Not even a response!) }; } exports._connectionListener = connectionListener; // Legacy Interface function Client(port, host) { if (!(this instanceof Client)) return new Client(port, host); EventEmitter.call(this); host = host || 'localhost'; port = port || 80; this.host = host; this.port = port; this.agent = new Agent({ host: host, port: port, maxSockets: 1 }); } util.inherits(Client, EventEmitter); Client.prototype.request = function(method, path, headers) { var self = this; var options = {}; options.host = self.host; options.port = self.port; if (method[0] === '/') { headers = path; path = method; method = 'GET'; } options.method = method; options.path = path; options.headers = headers; options.agent = self.agent; var c = new ClientRequest(options); c.on('error', function(e) { self.emit('error', e); }); // The old Client interface emitted 'end' on socket end. // This doesn't map to how we want things to operate in the future // but it will get removed when we remove this legacy interface. c.on('socket', function(s) { s.on('end', function() { if (self._decoder) { var ret = self._decoder.end(); if (ret) self.emit('data', ret); } self.emit('end'); }); }); return c; }; exports.Client = util.deprecate(Client, 'http.Client will be removed soon. Do not use it.'); exports.createClient = util.deprecate(function(port, host) { return new Client(port, host); }, 'http.createClient is deprecated. Use `http.request` instead.'); http// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Maintainers, keep in mind that octal literals are not allowed // in strict mode. Use the decimal value and add a comment with // the octal value. Example: // // var mode = 438; /* mode=0666 */ var util = require('util'); var pathModule = require('path'); var binding = process.binding('fs'); var constants = process.binding('constants'); var fs = exports; var Stream = require('stream').Stream; var EventEmitter = require('events').EventEmitter; var Readable = Stream.Readable; var Writable = Stream.Writable; var kMinPoolSpace = 128; var O_APPEND = constants.O_APPEND || 0; var O_CREAT = constants.O_CREAT || 0; var O_DIRECTORY = constants.O_DIRECTORY || 0; var O_EXCL = constants.O_EXCL || 0; var O_NOCTTY = constants.O_NOCTTY || 0; var O_NOFOLLOW = constants.O_NOFOLLOW || 0; var O_RDONLY = constants.O_RDONLY || 0; var O_RDWR = constants.O_RDWR || 0; var O_SYMLINK = constants.O_SYMLINK || 0; var O_SYNC = constants.O_SYNC || 0; var O_TRUNC = constants.O_TRUNC || 0; var O_WRONLY = constants.O_WRONLY || 0; var isWindows = process.platform === 'win32'; var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); function rethrow() { // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and // is fairly slow to generate. var callback; if (DEBUG) { var backtrace = new Error; callback = debugCallback; } else callback = missingCallback; return callback; function debugCallback(err) { if (err) { backtrace.message = err.message; err = backtrace; missingCallback(err); } } function missingCallback(err) { if (err) { if (process.throwDeprecation) throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs else if (!process.noDeprecation) { var msg = 'fs: missing callback ' + (err.stack || err.message); if (process.traceDeprecation) console.trace(msg); else console.error(msg); } } } } function maybeCallback(cb) { return typeof cb === 'function' ? cb : rethrow(); } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { if (typeof cb !== 'function') { return rethrow(); } return function() { return cb.apply(null, arguments); }; } function assertEncoding(encoding) { if (encoding && !Buffer.isEncoding(encoding)) { throw new Error('Unknown encoding: ' + encoding); } } function nullCheck(path, callback) { if (('' + path).indexOf('\u0000') !== -1) { var er = new Error('Path must be a string without null bytes.'); if (!callback) throw er; process.nextTick(function() { callback(er); }); return false; } return true; } fs.Stats = binding.Stats; fs.Stats.prototype._checkModeProperty = function(property) { return ((this.mode & constants.S_IFMT) === property); }; fs.Stats.prototype.isDirectory = function() { return this._checkModeProperty(constants.S_IFDIR); }; fs.Stats.prototype.isFile = function() { return this._checkModeProperty(constants.S_IFREG); }; fs.Stats.prototype.isBlockDevice = function() { return this._checkModeProperty(constants.S_IFBLK); }; fs.Stats.prototype.isCharacterDevice = function() { return this._checkModeProperty(constants.S_IFCHR); }; fs.Stats.prototype.isSymbolicLink = function() { return this._checkModeProperty(constants.S_IFLNK); }; fs.Stats.prototype.isFIFO = function() { return this._checkModeProperty(constants.S_IFIFO); }; fs.Stats.prototype.isSocket = function() { return this._checkModeProperty(constants.S_IFSOCK); }; fs.exists = function(path, callback) { if (!nullCheck(path, cb)) return; binding.stat(pathModule._makeLong(path), cb); function cb(err, stats) { if (callback) callback(err ? false : true); } }; fs.existsSync = function(path) { try { nullCheck(path); binding.stat(pathModule._makeLong(path)); return true; } catch (e) { return false; } }; fs.readFile = function(path, options, callback_) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: null, flag: 'r' }; } else if (typeof options === 'string') { options = { encoding: options, flag: 'r' }; } else if (!options) { options = { encoding: null, flag: 'r' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } var encoding = options.encoding; assertEncoding(encoding); // first, stat the file, so we know the size. var size; var buffer; // single buffer with file data var buffers; // list for when size is unknown var pos = 0; var fd; var flag = options.flag || 'r'; fs.open(path, flag, 438 /*=0666*/, function(er, fd_) { if (er) return callback(er); fd = fd_; fs.fstat(fd, function(er, st) { if (er) return callback(er); size = st.size; if (size === 0) { // the kernel lies about many files. // Go ahead and try to read some bytes. buffers = []; return read(); } buffer = new Buffer(size); read(); }); }); function read() { if (size === 0) { buffer = new Buffer(8192); fs.read(fd, buffer, 0, 8192, -1, afterRead); } else { fs.read(fd, buffer, pos, size - pos, -1, afterRead); } } function afterRead(er, bytesRead) { if (er) { return fs.close(fd, function(er2) { return callback(er); }); } if (bytesRead === 0) { return close(); } pos += bytesRead; if (size !== 0) { if (pos === size) close(); else read(); } else { // unknown size, just read until we don't get bytes. buffers.push(buffer.slice(0, bytesRead)); read(); } } function close() { fs.close(fd, function(er) { if (size === 0) { // collected the data into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (encoding) buffer = buffer.toString(encoding); return callback(er, buffer); }); } }; fs.readFileSync = function(path, options) { if (!options) { options = { encoding: null, flag: 'r' }; } else if (typeof options === 'string') { options = { encoding: options, flag: 'r' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } var encoding = options.encoding; assertEncoding(encoding); var flag = options.flag || 'r'; var fd = fs.openSync(path, flag, 438 /*=0666*/); var size; var threw = true; try { size = fs.fstatSync(fd).size; threw = false; } finally { if (threw) fs.closeSync(fd); } var pos = 0; var buffer; // single buffer with file data var buffers; // list for when size is unknown if (size === 0) { buffers = []; } else { buffer = new Buffer(size); } var done = false; while (!done) { var threw = true; try { if (size !== 0) { var bytesRead = fs.readSync(fd, buffer, pos, size - pos); } else { // the kernel lies about many files. // Go ahead and try to read some bytes. buffer = new Buffer(8192); var bytesRead = fs.readSync(fd, buffer, 0, 8192); if (bytesRead) { buffers.push(buffer.slice(0, bytesRead)); } } threw = false; } finally { if (threw) fs.closeSync(fd); } pos += bytesRead; done = (bytesRead === 0) || (size !== 0 && pos >= size); } fs.closeSync(fd); if (size === 0) { // data was collected into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (encoding) buffer = buffer.toString(encoding); return buffer; }; // Used by binding.open and friends function stringToFlags(flag) { // Only mess with strings if (typeof flag !== 'string') { return flag; } // O_EXCL is mandated by POSIX, Windows supports it too. // Let's add a check anyway, just in case. if (!O_EXCL && ~flag.indexOf('x')) { throw errnoException('ENOSYS', 'fs.open(O_EXCL)'); } switch (flag) { case 'r' : return O_RDONLY; case 'rs' : return O_RDONLY | O_SYNC; case 'r+' : return O_RDWR; case 'rs+' : return O_RDWR | O_SYNC; case 'w' : return O_TRUNC | O_CREAT | O_WRONLY; case 'wx' : // fall through case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL; case 'w+' : return O_TRUNC | O_CREAT | O_RDWR; case 'wx+': // fall through case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL; case 'a' : return O_APPEND | O_CREAT | O_WRONLY; case 'ax' : // fall through case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; case 'a+' : return O_APPEND | O_CREAT | O_RDWR; case 'ax+': // fall through case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL; } throw new Error('Unknown file open flag: ' + flag); } // exported but hidden, only used by test/simple/test-fs-open-flags.js Object.defineProperty(exports, '_stringToFlags', { enumerable: false, value: stringToFlags }); // Yes, the follow could be easily DRYed up but I provide the explicit // list to make the arguments clear. fs.close = function(fd, callback) { binding.close(fd, makeCallback(callback)); }; fs.closeSync = function(fd) { return binding.close(fd); }; function modeNum(m, def) { switch (typeof m) { case 'number': return m; case 'string': return parseInt(m, 8); default: if (def) { return modeNum(def); } else { return undefined; } } } fs.open = function(path, flags, mode, callback) { callback = makeCallback(arguments[arguments.length - 1]); mode = modeNum(mode, 438 /*=0666*/); if (!nullCheck(path, callback)) return; binding.open(pathModule._makeLong(path), stringToFlags(flags), mode, callback); }; fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 438 /*=0666*/); nullCheck(path); return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode); }; fs.read = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, length, position, encoding, callback) var cb = arguments[4], encoding = arguments[3]; assertEncoding(encoding); position = arguments[2]; length = arguments[1]; buffer = new Buffer(length); offset = 0; callback = function(err, bytesRead) { if (!cb) return; var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : ''; (cb)(err, str, bytesRead); }; } function wrapper(err, bytesRead) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback && callback(err, bytesRead || 0, buffer); } binding.read(fd, buffer, offset, length, position, wrapper); }; fs.readSync = function(fd, buffer, offset, length, position) { var legacy = false; if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, length, position, encoding, callback) legacy = true; var encoding = arguments[3]; assertEncoding(encoding); position = arguments[2]; length = arguments[1]; buffer = new Buffer(length); offset = 0; } var r = binding.read(fd, buffer, offset, length, position); if (!legacy) { return r; } var str = (r > 0) ? buffer.toString(encoding, 0, r) : ''; return [str, r]; }; fs.write = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, data, position, encoding, callback) callback = arguments[4]; position = arguments[2]; assertEncoding(arguments[3]); buffer = new Buffer('' + arguments[1], arguments[3]); offset = 0; length = buffer.length; } if (!length) { if (typeof callback == 'function') { process.nextTick(function() { callback(undefined, 0); }); } return; } callback = maybeCallback(callback); function wrapper(err, written) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback(err, written || 0, buffer); } binding.write(fd, buffer, offset, length, position, wrapper); }; fs.writeSync = function(fd, buffer, offset, length, position) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, data, position, encoding) position = arguments[2]; assertEncoding(arguments[3]); buffer = new Buffer('' + arguments[1], arguments[3]); offset = 0; length = buffer.length; } if (!length) return 0; return binding.write(fd, buffer, offset, length, position); }; fs.rename = function(oldPath, newPath, callback) { callback = makeCallback(callback); if (!nullCheck(oldPath, callback)) return; if (!nullCheck(newPath, callback)) return; binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath), callback); }; fs.renameSync = function(oldPath, newPath) { nullCheck(oldPath); nullCheck(newPath); return binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath)); }; fs.truncate = function(path, len, callback) { if (typeof path === 'number') { // legacy return fs.ftruncate(path, len, callback); } if (typeof len === 'function') { callback = len; len = 0; } else if (typeof len === 'undefined') { len = 0; } callback = maybeCallback(callback); fs.open(path, 'w', function(er, fd) { if (er) return callback(er); binding.ftruncate(fd, len, function(er) { fs.close(fd, function(er2) { callback(er || er2); }); }); }); }; fs.truncateSync = function(path, len) { if (typeof path === 'number') { // legacy return fs.ftruncateSync(path, len); } if (typeof len === 'undefined') { len = 0; } // allow error to be thrown, but still close fd. var fd = fs.openSync(path, 'w'); try { var ret = fs.ftruncateSync(fd, len); } finally { fs.closeSync(fd); } return ret; }; fs.ftruncate = function(fd, len, callback) { if (typeof len === 'function') { callback = len; len = 0; } else if (typeof len === 'undefined') { len = 0; } binding.ftruncate(fd, len, makeCallback(callback)); }; fs.ftruncateSync = function(fd, len) { if (typeof len === 'undefined') { len = 0; } return binding.ftruncate(fd, len); }; fs.rmdir = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.rmdir(pathModule._makeLong(path), callback); }; fs.rmdirSync = function(path) { nullCheck(path); return binding.rmdir(pathModule._makeLong(path)); }; fs.fdatasync = function(fd, callback) { binding.fdatasync(fd, makeCallback(callback)); }; fs.fdatasyncSync = function(fd) { return binding.fdatasync(fd); }; fs.fsync = function(fd, callback) { binding.fsync(fd, makeCallback(callback)); }; fs.fsyncSync = function(fd) { return binding.fsync(fd); }; fs.mkdir = function(path, mode, callback) { if (typeof mode === 'function') callback = mode; callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/), callback); }; fs.mkdirSync = function(path, mode) { nullCheck(path); return binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/)); }; fs.readdir = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.readdir(pathModule._makeLong(path), callback); }; fs.readdirSync = function(path) { nullCheck(path); return binding.readdir(pathModule._makeLong(path)); }; fs.fstat = function(fd, callback) { binding.fstat(fd, makeCallback(callback)); }; fs.lstat = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.lstat(pathModule._makeLong(path), callback); }; fs.stat = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.stat(pathModule._makeLong(path), callback); }; fs.fstatSync = function(fd) { return binding.fstat(fd); }; fs.lstatSync = function(path) { nullCheck(path); return binding.lstat(pathModule._makeLong(path)); }; fs.statSync = function(path) { nullCheck(path); return binding.stat(pathModule._makeLong(path)); }; fs.readlink = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.readlink(pathModule._makeLong(path), callback); }; fs.readlinkSync = function(path) { nullCheck(path); return binding.readlink(pathModule._makeLong(path)); }; function preprocessSymlinkDestination(path, type) { if (!isWindows) { // No preprocessing is needed on Unix. return path; } else if (type === 'junction') { // Junctions paths need to be absolute and \\?\-prefixed. return pathModule._makeLong(path); } else { // Windows symlinks don't tolerate forward slashes. return ('' + path).replace(/\//g, '\\'); } } fs.symlink = function(destination, path, type_, callback) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); if (!nullCheck(destination, callback)) return; if (!nullCheck(path, callback)) return; binding.symlink(preprocessSymlinkDestination(destination, type), pathModule._makeLong(path), type, callback); }; fs.symlinkSync = function(destination, path, type) { type = (typeof type === 'string' ? type : null); nullCheck(destination); nullCheck(path); return binding.symlink(preprocessSymlinkDestination(destination, type), pathModule._makeLong(path), type); }; fs.link = function(srcpath, dstpath, callback) { callback = makeCallback(callback); if (!nullCheck(srcpath, callback)) return; if (!nullCheck(dstpath, callback)) return; binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath), callback); }; fs.linkSync = function(srcpath, dstpath) { nullCheck(srcpath); nullCheck(dstpath); return binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath)); }; fs.unlink = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.unlink(pathModule._makeLong(path), callback); }; fs.unlinkSync = function(path) { nullCheck(path); return binding.unlink(pathModule._makeLong(path)); }; fs.fchmod = function(fd, mode, callback) { binding.fchmod(fd, modeNum(mode), makeCallback(callback)); }; fs.fchmodSync = function(fd, mode) { return binding.fchmod(fd, modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchmod = function(path, mode, callback) { callback = maybeCallback(callback); fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) { if (err) { callback(err); return; } // prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. fs.fchmod(fd, mode, function(err) { fs.close(fd, function(err2) { callback(err || err2); }); }); }); }; fs.lchmodSync = function(path, mode) { var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK); // prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. var err, err2; try { var ret = fs.fchmodSync(fd, mode); } catch (er) { err = er; } try { fs.closeSync(fd); } catch (er) { err2 = er; } if (err || err2) throw (err || err2); return ret; }; } fs.chmod = function(path, mode, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.chmod(pathModule._makeLong(path), modeNum(mode), callback); }; fs.chmodSync = function(path, mode) { nullCheck(path); return binding.chmod(pathModule._makeLong(path), modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchown = function(path, uid, gid, callback) { callback = maybeCallback(callback); fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) { if (err) { callback(err); return; } fs.fchown(fd, uid, gid, callback); }); }; fs.lchownSync = function(path, uid, gid) { var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK); return fs.fchownSync(fd, uid, gid); }; } fs.fchown = function(fd, uid, gid, callback) { binding.fchown(fd, uid, gid, makeCallback(callback)); }; fs.fchownSync = function(fd, uid, gid) { return binding.fchown(fd, uid, gid); }; fs.chown = function(path, uid, gid, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.chown(pathModule._makeLong(path), uid, gid, callback); }; fs.chownSync = function(path, uid, gid) { nullCheck(path); return binding.chown(pathModule._makeLong(path), uid, gid); }; // converts Date or number to a fractional UNIX timestamp function toUnixTimestamp(time) { if (typeof time == 'number') { return time; } if (time instanceof Date) { // convert to 123.456 UNIX timestamp return time.getTime() / 1000; } throw new Error('Cannot parse time: ' + time); } // exported for unit tests, not for public consumption fs._toUnixTimestamp = toUnixTimestamp; fs.utimes = function(path, atime, mtime, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.utimes(pathModule._makeLong(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), callback); }; fs.utimesSync = function(path, atime, mtime) { nullCheck(path); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.utimes(pathModule._makeLong(path), atime, mtime); }; fs.futimes = function(fd, atime, mtime, callback) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime, makeCallback(callback)); }; fs.futimesSync = function(fd, atime, mtime) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime); }; function writeAll(fd, buffer, offset, length, position, callback) { callback = maybeCallback(arguments[arguments.length - 1]); // write(fd, buffer, offset, length, position, callback) fs.write(fd, buffer, offset, length, position, function(writeErr, written) { if (writeErr) { fs.close(fd, function() { if (callback) callback(writeErr); }); } else { if (written === length) { fs.close(fd, callback); } else { offset += written; length -= written; position += written; writeAll(fd, buffer, offset, length, position, callback); } } }); } fs.writeFile = function(path, data, options, callback) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'w' }; } else if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } assertEncoding(options.encoding); var flag = options.flag || 'w'; fs.open(path, options.flag || 'w', options.mode, function(openErr, fd) { if (openErr) { if (callback) callback(openErr); } else { var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data, options.encoding || 'utf8'); var position = /a/.test(flag) ? null : 0; writeAll(fd, buffer, 0, buffer.length, position, callback); } }); }; fs.writeFileSync = function(path, data, options) { if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'w' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } assertEncoding(options.encoding); var flag = options.flag || 'w'; var fd = fs.openSync(path, flag, options.mode); if (!Buffer.isBuffer(data)) { data = new Buffer('' + data, options.encoding || 'utf8'); } var written = 0; var length = data.length; var position = /a/.test(flag) ? null : 0; try { while (written < length) { written += fs.writeSync(fd, data, written, length - written, position); position += written; } } finally { fs.closeSync(fd); } }; fs.appendFile = function(path, data, options, callback_) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'a' }; } else if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } if (!options.flag) options = util._extend({ flag: 'a' }, options); fs.writeFile(path, data, options, callback); }; fs.appendFileSync = function(path, data, options) { if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'a' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } if (!options.flag) options = util._extend({ flag: 'a' }, options); fs.writeFileSync(path, data, options); }; function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function FSWatcher() { EventEmitter.call(this); var self = this; var FSEvent = process.binding('fs_event_wrap').FSEvent; this._handle = new FSEvent(); this._handle.owner = this; this._handle.onchange = function(status, event, filename) { if (status) { self._handle.close(); self.emit('error', errnoException(process._errno, 'watch')); } else { self.emit('change', event, filename); } }; } util.inherits(FSWatcher, EventEmitter); FSWatcher.prototype.start = function(filename, persistent) { nullCheck(filename); var r = this._handle.start(pathModule._makeLong(filename), persistent); if (r) { this._handle.close(); throw errnoException(process._errno, 'watch'); } }; FSWatcher.prototype.close = function() { this._handle.close(); }; fs.watch = function(filename) { nullCheck(filename); var watcher; var options; var listener; if ('object' == typeof arguments[1]) { options = arguments[1]; listener = arguments[2]; } else { options = {}; listener = arguments[1]; } if (options.persistent === undefined) options.persistent = true; watcher = new FSWatcher(); watcher.start(filename, options.persistent); if (listener) { watcher.addListener('change', listener); } return watcher; }; // Stat Change Watchers function StatWatcher() { EventEmitter.call(this); var self = this; this._handle = new binding.StatWatcher(); // uv_fs_poll is a little more powerful than ev_stat but we curb it for // the sake of backwards compatibility var oldStatus = -1; this._handle.onchange = function(current, previous, newStatus) { if (oldStatus === -1 && newStatus === -1 && current.nlink === previous.nlink) return; oldStatus = newStatus; self.emit('change', current, previous); }; this._handle.onstop = function() { self.emit('stop'); }; } util.inherits(StatWatcher, EventEmitter); StatWatcher.prototype.start = function(filename, persistent, interval) { nullCheck(filename); this._handle.start(pathModule._makeLong(filename), persistent, interval); }; StatWatcher.prototype.stop = function() { this._handle.stop(); }; var statWatchers = {}; function inStatWatchers(filename) { return Object.prototype.hasOwnProperty.call(statWatchers, filename) && statWatchers[filename]; } fs.watchFile = function(filename) { nullCheck(filename); var stat; var listener; var options = { // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. interval: 5007, persistent: true }; if ('object' == typeof arguments[1]) { options = util._extend(options, arguments[1]); listener = arguments[2]; } else { listener = arguments[1]; } if (!listener) { throw new Error('watchFile requires a listener function'); } if (inStatWatchers(filename)) { stat = statWatchers[filename]; } else { stat = statWatchers[filename] = new StatWatcher(); stat.start(filename, options.persistent, options.interval); } stat.addListener('change', listener); return stat; }; fs.unwatchFile = function(filename, listener) { nullCheck(filename); if (!inStatWatchers(filename)) return; var stat = statWatchers[filename]; if (typeof listener === 'function') { stat.removeListener('change', listener); } else { stat.removeAllListeners('change'); } if (EventEmitter.listenerCount(stat, 'change') === 0) { stat.stop(); statWatchers[filename] = undefined; } }; // Realpath // Not using realpath(2) because it's bad. // See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html var normalize = pathModule.normalize; // Regexp that finds the next partion of a (partial) path // result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] if (isWindows) { var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; } else { var nextPartRe = /(.*?)(?:[\/]+|$)/g; } // Regex to find the device root, including trailing slash. E.g. 'c:\\'. if (isWindows) { var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; } else { var splitRootRe = /^[\/]*/; } fs.realpathSync = function realpathSync(p, cache) { // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return cache[p]; } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstatSync(base); knownHard[base] = true; } knownHard[base] = true; } // walk down the path, swapping out linked pathparts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { continue; } var resolvedLink; if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // some known symbolic link. no need to stat again. resolvedLink = cache[base]; } else { var stat = fs.lstatSync(base); if (!stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; continue; } // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); } resolvedLink = pathModule.resolve(previous, linkTarget); // track this, if given a cache. if (cache) cache[base] = resolvedLink; if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } if (cache) cache[original] = p; return p; }; fs.realpath = function realpath(p, cache, cb) { if (typeof cb !== 'function') { cb = maybeCallback(cache); cache = null; } // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return process.nextTick(cb.bind(null, null, cache[p])); } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function(err) { if (err) return cb(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } // walk down the path, swapping out linked pathparts for their real // values function LOOP() { // stop if scanned past end of path if (pos >= p.length) { if (cache) cache[original] = p; return cb(null, p); } // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { return process.nextTick(LOOP); } if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // known symbolic link. no need to stat again. return gotResolvedLink(cache[base]); } return fs.lstat(base, gotStat); } function gotStat(err, stat) { if (err) return cb(err); // if not a symlink, skip to the next path part if (!stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; return process.nextTick(LOOP); } // stat & read the link if not read before // call gotTarget as soon as the link target is known // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } fs.stat(base, function(err) { if (err) return cb(err); fs.readlink(base, function(err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target, base) { if (err) return cb(err); var resolvedLink = pathModule.resolve(previous, target); if (cache) cache[base] = resolvedLink; gotResolvedLink(resolvedLink); } function gotResolvedLink(resolvedLink) { // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } }; var pool; function allocNewPool(poolSize) { pool = new Buffer(poolSize); pool.used = 0; } fs.createReadStream = function(path, options) { return new ReadStream(path, options); }; util.inherits(ReadStream, Readable); fs.ReadStream = ReadStream; function ReadStream(path, options) { if (!(this instanceof ReadStream)) return new ReadStream(path, options); // a little bit bigger buffer and water marks by default options = util._extend({ highWaterMark: 64 * 1024 }, options || {}); Readable.call(this, options); this.path = path; this.fd = options.hasOwnProperty('fd') ? options.fd : null; this.flags = options.hasOwnProperty('flags') ? options.flags : 'r'; this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ this.start = options.hasOwnProperty('start') ? options.start : undefined; this.end = options.hasOwnProperty('end') ? options.end : undefined; this.autoClose = options.hasOwnProperty('autoClose') ? options.autoClose : true; this.pos = undefined; if (this.start !== undefined) { if ('number' !== typeof this.start) { throw TypeError('start must be a Number'); } if (this.end === undefined) { this.end = Infinity; } else if ('number' !== typeof this.end) { throw TypeError('end must be a Number'); } if (this.start > this.end) { throw new Error('start must be <= end'); } this.pos = this.start; } if (typeof this.fd !== 'number') this.open(); this.on('end', function() { if (this.autoClose) { this.destroy(); } }); } fs.FileReadStream = fs.ReadStream; // support the legacy name ReadStream.prototype.open = function() { var self = this; fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { if (this.autoClose) { self.destroy(); } self.emit('error', er); return; } self.fd = fd; self.emit('open', fd); // start the flow of data. self.read(); }); }; ReadStream.prototype._read = function(n) { if (typeof this.fd !== 'number') return this.once('open', function() { this._read(n); }); if (this.destroyed) return; if (!pool || pool.length - pool.used < kMinPoolSpace) { // discard the old pool. pool = null; allocNewPool(this._readableState.highWaterMark); } // Grab another reference to the pool in the case that while we're // in the thread pool another read() finishes up the pool, and // allocates a new one. var thisPool = pool; var toRead = Math.min(pool.length - pool.used, n); var start = pool.used; if (this.pos !== undefined) toRead = Math.min(this.end - this.pos + 1, toRead); // already read everything we were supposed to read! // treat as EOF. if (toRead <= 0) return this.push(null); // the actual read. var self = this; fs.read(this.fd, pool, pool.used, toRead, this.pos, onread); // move the pool positions, and internal position for reading. if (this.pos !== undefined) this.pos += toRead; pool.used += toRead; function onread(er, bytesRead) { if (er) { if (self.autoClose) { self.destroy(); } self.emit('error', er); } else { var b = null; if (bytesRead > 0) b = thisPool.slice(start, start + bytesRead); self.push(b); } } }; ReadStream.prototype.destroy = function() { if (this.destroyed) return; this.destroyed = true; if ('number' === typeof this.fd) this.close(); }; ReadStream.prototype.close = function(cb) { var self = this; if (cb) this.once('close', cb); if (this.closed || 'number' !== typeof this.fd) { if ('number' !== typeof this.fd) { this.once('open', close); return; } return process.nextTick(this.emit.bind(this, 'close')); } this.closed = true; close(); function close(fd) { fs.close(fd || self.fd, function(er) { if (er) self.emit('error', er); else self.emit('close'); }); self.fd = null; } }; fs.createWriteStream = function(path, options) { return new WriteStream(path, options); }; util.inherits(WriteStream, Writable); fs.WriteStream = WriteStream; function WriteStream(path, options) { if (!(this instanceof WriteStream)) return new WriteStream(path, options); options = options || {}; Writable.call(this, options); this.path = path; this.fd = null; this.fd = options.hasOwnProperty('fd') ? options.fd : null; this.flags = options.hasOwnProperty('flags') ? options.flags : 'w'; this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ this.start = options.hasOwnProperty('start') ? options.start : undefined; this.pos = undefined; this.bytesWritten = 0; if (this.start !== undefined) { if ('number' !== typeof this.start) { throw TypeError('start must be a Number'); } if (this.start < 0) { throw new Error('start must be >= zero'); } this.pos = this.start; } if ('number' !== typeof this.fd) this.open(); // dispose on finish. this.once('finish', this.close); } fs.FileWriteStream = fs.WriteStream; // support the legacy name WriteStream.prototype.open = function() { fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { this.destroy(); this.emit('error', er); return; } this.fd = fd; this.emit('open', fd); }.bind(this)); }; WriteStream.prototype._write = function(data, encoding, cb) { if (!Buffer.isBuffer(data)) return this.emit('error', new Error('Invalid data')); if (typeof this.fd !== 'number') return this.once('open', function() { this._write(data, encoding, cb); }); var self = this; fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) { if (er) { self.destroy(); return cb(er); } self.bytesWritten += bytes; cb(); }); if (this.pos !== undefined) this.pos += data.length; }; WriteStream.prototype.destroy = ReadStream.prototype.destroy; WriteStream.prototype.close = ReadStream.prototype.close; // There is no shutdown() for files. WriteStream.prototype.destroySoon = WriteStream.prototype.end; // SyncWriteStream is internal. DO NOT USE. // Temporary hack for process.stdout and process.stderr when piped to files. function SyncWriteStream(fd) { Stream.call(this); this.fd = fd; this.writable = true; this.readable = false; } util.inherits(SyncWriteStream, Stream); // Export fs.SyncWriteStream = SyncWriteStream; SyncWriteStream.prototype.write = function(data, arg1, arg2) { var encoding, cb; // parse arguments if (arg1) { if (typeof arg1 === 'string') { encoding = arg1; cb = arg2; } else if (typeof arg1 === 'function') { cb = arg1; } else { throw new Error('bad arg'); } } assertEncoding(encoding); // Change strings to buffers. SLOW if (typeof data == 'string') { data = new Buffer(data, encoding); } fs.writeSync(this.fd, data, 0, data.length); if (cb) { process.nextTick(cb); } return true; }; SyncWriteStream.prototype.end = function(data, arg1, arg2) { if (data) { this.write(data, arg1, arg2); } this.destroy(); }; SyncWriteStream.prototype.destroy = function() { fs.closeSync(this.fd); this.fd = null; this.emit('close'); return true; }; SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy; fs// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This is a free list to avoid creating so many of the same object. exports.FreeList = function(name, max, constructor) { this.name = name; this.constructor = constructor; this.max = max; this.list = []; }; exports.FreeList.prototype.alloc = function() { //debug("alloc " + this.name + " " + this.list.length); return this.list.length ? this.list.shift() : this.constructor.apply(this, arguments); }; exports.FreeList.prototype.free = function(obj) { //debug("free " + this.name + " " + this.list.length); if (this.list.length < this.max) { this.list.push(obj); } }; freelist// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var domain; exports.usingDomains = false; function EventEmitter() { this.domain = null; if (exports.usingDomains) { // if there is an active domain, then attach to it. domain = domain || require('domain'); if (domain.active && !(this instanceof domain.Domain)) { this.domain = domain.active; } } this._events = this._events || {}; this._maxListeners = this._maxListeners || defaultMaxListeners; } exports.EventEmitter = EventEmitter; // By default EventEmitters will print a warning if more than // 10 listeners are added to it. This is a useful default which // helps finding memory leaks. // // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. var defaultMaxListeners = 10; EventEmitter.prototype.setMaxListeners = function(n) { if (typeof n !== 'number' || n < 0) throw TypeError('n must be a positive number'); this._maxListeners = n; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (typeof this._events.error === 'object' && !this._events.error.length)) { er = arguments[1]; if (this.domain) { if (!er) er = new TypeError('Uncaught, unspecified "error" event.'); er.domainEmitter = this; er.domain = this.domain; er.domainThrown = false; this.domain.emit('error', er); } else if (er instanceof Error) { throw er; // Unhandled 'error' event } else { throw TypeError('Uncaught, unspecified "error" event.'); } return false; } } handler = this._events[type]; if (typeof handler === 'undefined') return false; if (this.domain && this !== process) this.domain.enter(); if (typeof handler === 'function') { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } } else if (typeof handler === 'object') { len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } if (this.domain && this !== process) this.domain.exit(); return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (typeof listener !== 'function') throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, typeof listener.listener === 'function' ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (typeof this._events[type] === 'object') // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (typeof this._events[type] === 'object' && !this._events[type].warned) { m = this._maxListeners; if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); console.trace(); } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (typeof listener !== 'function') throw TypeError('listener must be a function'); function g() { this.removeListener(type, g); listener.apply(this, arguments); } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (typeof listener !== 'function') throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (typeof list.listener === 'function' && list.listener === listener)) { this._events[type] = undefined; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (typeof list === 'object') { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; this._events[type] = undefined; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) this._events[type] = undefined; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } this._events[type] = undefined; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (typeof this._events[type] === 'function') ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.listenerCount = function(emitter, type) { var ret; if (!emitter._events || !emitter._events[type]) ret = 0; else if (typeof emitter._events[type] === 'function') ret = 1; else ret = emitter._events[type].length; return ret; }; events// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var events = require('events'); var EventEmitter = events.EventEmitter; var inherits = util.inherits; // methods that are called when trying to shut down expliclitly bound EEs var endMethods = ['end', 'abort', 'destroy', 'destroySoon']; // communicate with events module, but don't require that // module to have to load this one, since this module has // a few side effects. events.usingDomains = true; // let the process know we're using domains process._usingDomains(); exports.Domain = Domain; exports.create = exports.createDomain = function(cb) { return new Domain(cb); }; // it's possible to enter one domain while already inside // another one. the stack is each entered domain. var stack = []; exports._stack = stack; // the active domain is always the one that we're currently in. exports.active = null; inherits(Domain, EventEmitter); function Domain() { EventEmitter.call(this); this.members = []; } Domain.prototype.enter = function() { if (this._disposed) return; // note that this might be a no-op, but we still need // to push it onto the stack so that we can pop it later. exports.active = process.domain = this; stack.push(this); }; Domain.prototype.exit = function() { if (this._disposed) return; // exit all domains until this one. var d; do { d = stack.pop(); } while (d && d !== this); exports.active = stack[stack.length - 1]; process.domain = exports.active; }; // note: this works for timers as well. Domain.prototype.add = function(ee) { // disposed domains can't be used for new things. if (this._disposed) return; // already added to this domain. if (ee.domain === this) return; // has a domain already - remove it first. if (ee.domain) { ee.domain.remove(ee); } // check for circular Domain->Domain links. // This causes bad insanity! // // For example: // var d = domain.create(); // var e = domain.create(); // d.add(e); // e.add(d); // e.emit('error', er); // RangeError, stack overflow! if (this.domain && (ee instanceof Domain)) { for (var d = this.domain; d; d = d.domain) { if (ee === d) return; } } ee.domain = this; this.members.push(ee); }; Domain.prototype.remove = function(ee) { ee.domain = null; var index = this.members.indexOf(ee); if (index !== -1) { this.members.splice(index, 1); } }; Domain.prototype.run = function(fn) { return this.bind(fn)(); }; Domain.prototype.intercept = function(cb) { return this.bind(cb, true); }; Domain.prototype.bind = function(cb, interceptError) { // if cb throws, catch it here. var self = this; var b = function() { // disposing turns functions into no-ops if (self._disposed) return; if (this instanceof Domain) { return cb.apply(this, arguments); } // only intercept first-arg errors if explicitly requested. if (interceptError && arguments[0] && (arguments[0] instanceof Error)) { var er = arguments[0]; util._extend(er, { domainBound: cb, domainThrown: false, domain: self }); self.emit('error', er); return; } // remove first-arg if intercept as assumed to be the error-arg if (interceptError) { var len = arguments.length; var args; switch (len) { case 0: case 1: // no args that we care about. args = []; break; case 2: // optimization for most common case: cb(er, data) args = [arguments[1]]; break; default: // slower for less common case: cb(er, foo, bar, baz, ...) args = new Array(len - 1); for (var i = 1; i < len; i++) { args[i - 1] = arguments[i]; } break; } self.enter(); var ret = cb.apply(this, args); self.exit(); return ret; } self.enter(); var ret = cb.apply(this, arguments); self.exit(); return ret; }; b.domain = this; return b; }; Domain.prototype.dispose = function() { if (this._disposed) return; // if we're the active domain, then get out now. this.exit(); this.emit('dispose'); // remove error handlers. this.removeAllListeners(); this.on('error', function() {}); // try to kill all the members. // XXX There should be more consistent ways // to shut down things! this.members.forEach(function(m) { // if it's a timeout or interval, cancel it. clearTimeout(m); // drop all event listeners. if (m instanceof EventEmitter) { m.removeAllListeners(); // swallow errors m.on('error', function() {}); } // Be careful! // By definition, we're likely in error-ridden territory here, // so it's quite possible that calling some of these methods // might cause additional exceptions to be thrown. endMethods.forEach(function(method) { if (typeof m[method] === 'function') { try { m[method](); } catch (er) {} } }); }); // remove from parent domain, if there is one. if (this.domain) this.domain.remove(this); // kill the references so that they can be properly gc'ed. this.members.length = 0; // finally, mark this domain as 'no longer relevant' // so that it can't be entered or activated. this._disposed = true; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var cares, net = require('net'); function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. // For backwards compatibility. libuv returns ENOENT on NXDOMAIN. if (errorno == 'ENOENT') { errorno = 'ENOTFOUND'; } var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // c-ares invokes a callback either synchronously or asynchronously, // but the dns API should always invoke a callback asynchronously. // // This function makes sure that the callback is invoked asynchronously. // It returns a function that invokes the callback within nextTick(). // // To avoid invoking unnecessary nextTick(), `immediately` property of // returned function should be set to true after c-ares returned. // // Usage: // // function someAPI(callback) { // callback = makeAsync(callback); // channel.someAPI(..., callback); // callback.immediately = true; // } function makeAsync(callback) { if (typeof callback !== 'function') { return callback; } return function asyncCallback() { if (asyncCallback.immediately) { // The API already returned, we can invoke the callback immediately. callback.apply(null, arguments); } else { var args = arguments; process.nextTick(function() { callback.apply(null, args); }); } }; } // Easy DNS A/AAAA look up // lookup(domain, [family,] callback) exports.lookup = function(domain, family, callback) { // parse arguments if (arguments.length === 2) { callback = family; family = 0; } else if (!family) { family = 0; } else { family = +family; if (family !== 4 && family !== 6) { throw new Error('invalid argument: `family` must be 4 or 6'); } } callback = makeAsync(callback); if (!domain) { callback(null, null, family === 6 ? 6 : 4); return {}; } // Hack required for Windows because Win7 removed the // localhost entry from c:\WINDOWS\system32\drivers\etc\hosts // See http://daniel.haxx.se/blog/2011/02/21/localhost-hack-on-windows/ // TODO Remove this once c-ares handles this problem. if (process.platform == 'win32' && domain == 'localhost') { callback(null, '127.0.0.1', 4); return {}; } var matchedFamily = net.isIP(domain); if (matchedFamily) { callback(null, domain, matchedFamily); return {}; } function onanswer(addresses) { if (addresses) { if (family) { callback(null, addresses[0], family); } else { callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4); } } else { callback(errnoException(process._errno, 'getaddrinfo')); } } cares = cares || process.binding('cares_wrap'); var wrap = cares.getaddrinfo(domain, family); if (!wrap) { throw errnoException(process._errno, 'getaddrinfo'); } wrap.oncomplete = onanswer; callback.immediately = true; return wrap; }; function resolver(bindingName) { cares = cares || process.binding('cares_wrap'); var binding = cares[bindingName]; return function query(name, callback) { function onanswer(status, result) { if (!status) { callback(null, result); } else { callback(errnoException(process._errno, bindingName)); } } callback = makeAsync(callback); var wrap = binding(name, onanswer); if (!wrap) { throw errnoException(process._errno, bindingName); } callback.immediately = true; return wrap; } } var resolveMap = {}; exports.resolve4 = resolveMap.A = resolver('queryA'); exports.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); exports.resolveCname = resolveMap.CNAME = resolver('queryCname'); exports.resolveMx = resolveMap.MX = resolver('queryMx'); exports.resolveNs = resolveMap.NS = resolver('queryNs'); exports.resolveTxt = resolveMap.TXT = resolver('queryTxt'); exports.resolveSrv = resolveMap.SRV = resolver('querySrv'); exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr'); exports.reverse = resolveMap.PTR = resolver('getHostByAddr'); exports.resolve = function(domain, type_, callback_) { var resolver, callback; if (typeof type_ == 'string') { resolver = resolveMap[type_]; callback = callback_; } else { resolver = exports.resolve4; callback = type_; } if (typeof resolver === 'function') { return resolver(domain, callback); } else { throw new Error('Unknown type "' + type_ + '"'); } }; // ERROR CODES exports.NODATA = 'ENODATA'; exports.FORMERR = 'EFORMERR'; exports.SERVFAIL = 'ESERVFAIL'; exports.NOTFOUND = 'ENOTFOUND'; exports.NOTIMP = 'ENOTIMP'; exports.REFUSED = 'EREFUSED'; exports.BADQUERY = 'EBADQUERY'; exports.ADNAME = 'EADNAME'; exports.BADFAMILY = 'EBADFAMILY'; exports.BADRESP = 'EBADRESP'; exports.CONNREFUSED = 'ECONNREFUSED'; exports.TIMEOUT = 'ETIMEOUT'; exports.EOF = 'EOF'; exports.FILE = 'EFILE'; exports.NOMEM = 'ENOMEM'; exports.DESTRUCTION = 'EDESTRUCTION'; exports.BADSTR = 'EBADSTR'; exports.BADFLAGS = 'EBADFLAGS'; exports.NONAME = 'ENONAME'; exports.BADHINTS = 'EBADHINTS'; exports.NOTINITIALIZED = 'ENOTINITIALIZED'; exports.LOADIPHLPAPI = 'ELOADIPHLPAPI'; exports.ADDRGETNETWORKPARAMS = 'EADDRGETNETWORKPARAMS'; exports.CANCELLED = 'ECANCELLED'; dns// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var util = require('util'); var events = require('events'); var UDP = process.binding('udp_wrap').UDP; var BIND_STATE_UNBOUND = 0; var BIND_STATE_BINDING = 1; var BIND_STATE_BOUND = 2; // lazily loaded var cluster = null; var dns = null; var net = null; // no-op callback function noop() { } function isIP(address) { if (!net) net = require('net'); return net.isIP(address); } function lookup(address, family, callback) { if (!dns) dns = require('dns'); return dns.lookup(address, family, callback); } function lookup4(address, callback) { return lookup(address || '0.0.0.0', 4, callback); } function lookup6(address, callback) { return lookup(address || '::0', 6, callback); } function newHandle(type) { if (type == 'udp4') { var handle = new UDP; handle.lookup = lookup4; return handle; } if (type == 'udp6') { var handle = new UDP; handle.lookup = lookup6; handle.bind = handle.bind6; handle.send = handle.send6; return handle; } if (type == 'unix_dgram') throw new Error('unix_dgram sockets are not supported any more.'); throw new Error('Bad socket type specified. Valid types are: udp4, udp6'); } exports._createSocketHandle = function(address, port, addressType, fd) { // Opening an existing fd is not supported for UDP handles. assert(typeof fd !== 'number' || fd < 0); var handle = newHandle(addressType); if (port || address) { var r = handle.bind(address, port || 0, 0); if (r == -1) { handle.close(); handle = null; } } return handle; }; function Socket(type, listener) { events.EventEmitter.call(this); var handle = newHandle(type); handle.owner = this; this._handle = handle; this._receiving = false; this._bindState = BIND_STATE_UNBOUND; this.type = type; this.fd = null; // compatibility hack if (typeof listener === 'function') this.on('message', listener); } util.inherits(Socket, events.EventEmitter); exports.Socket = Socket; exports.createSocket = function(type, listener) { return new Socket(type, listener); }; function startListening(socket) { socket._handle.onmessage = onMessage; // Todo: handle errors socket._handle.recvStart(); socket._receiving = true; socket._bindState = BIND_STATE_BOUND; socket.fd = -42; // compatibility hack socket.emit('listening'); } function replaceHandle(self, newHandle) { // Set up the handle that we got from master. newHandle.lookup = self._handle.lookup; newHandle.bind = self._handle.bind; newHandle.send = self._handle.send; newHandle.owner = self; // Replace the existing handle by the handle we got from master. self._handle.close(); self._handle = newHandle; } Socket.prototype.bind = function(/*port, address, callback*/) { var self = this; self._healthCheck(); if (this._bindState != BIND_STATE_UNBOUND) throw new Error('Socket is already bound'); this._bindState = BIND_STATE_BINDING; if (typeof arguments[arguments.length - 1] === 'function') self.once('listening', arguments[arguments.length - 1]); var UDP = process.binding('udp_wrap').UDP; if (arguments[0] instanceof UDP) { replaceHandle(self, arguments[0]); startListening(self); return; } var port = arguments[0]; var address = arguments[1]; if (typeof address === 'function') address = ''; // a.k.a. "any address" // resolve address first self._handle.lookup(address, function(err, ip) { if (err) { self._bindState = BIND_STATE_UNBOUND; self.emit('error', err); return; } if (!cluster) cluster = require('cluster'); if (cluster.isWorker) { cluster._getServer(self, ip, port, self.type, -1, function(handle) { if (!self._handle) // handle has been closed in the mean time. return handle.close(); replaceHandle(self, handle); startListening(self); }); } else { if (!self._handle) return; // handle has been closed in the mean time if (self._handle.bind(ip, port || 0, /*flags=*/ 0)) { self.emit('error', errnoException(process._errno, 'bind')); self._bindState = BIND_STATE_UNBOUND; // Todo: close? return; } startListening(self); } }); }; // thin wrapper around `send`, here for compatibility with dgram_legacy.js Socket.prototype.sendto = function(buffer, offset, length, port, address, callback) { if (typeof offset !== 'number' || typeof length !== 'number') throw new Error('send takes offset and length as args 2 and 3'); if (typeof address !== 'string') throw new Error(this.type + ' sockets must send to port, address'); this.send(buffer, offset, length, port, address, callback); }; Socket.prototype.send = function(buffer, offset, length, port, address, callback) { var self = this; if (!Buffer.isBuffer(buffer)) throw new TypeError('First argument must be a buffer object.'); if (offset >= buffer.length) throw new Error('Offset into buffer too large'); if (offset + length > buffer.length) throw new Error('Offset + length beyond buffer length'); callback = callback || noop; self._healthCheck(); if (self._bindState == BIND_STATE_UNBOUND) self.bind(0, null); // If the socket hasn't been bound yet, push the outbound packet onto the // send queue and send after binding is complete. if (self._bindState != BIND_STATE_BOUND) { // If the send queue hasn't been initialized yet, do it, and install an // event handler that flushes the send queue after binding is done. if (!self._sendQueue) { self._sendQueue = []; self.once('listening', function() { // Flush the send queue. for (var i = 0; i < self._sendQueue.length; i++) self.send.apply(self, self._sendQueue[i]); self._sendQueue = undefined; }); } self._sendQueue.push([buffer, offset, length, port, address, callback]); return; } self._handle.lookup(address, function(err, ip) { if (err) { if (callback) callback(err); self.emit('error', err); } else if (self._handle) { var req = self._handle.send(buffer, offset, length, port, ip); if (req) { req.oncomplete = afterSend; req.cb = callback; } else { // don't emit as error, dgram_legacy.js compatibility var err = errnoException(process._errno, 'send'); process.nextTick(function() { callback(err); }); } } }); }; function afterSend(status, handle, req, buffer) { var self = handle.owner; if (req.cb) req.cb(null, buffer.length); // compatibility with dgram_legacy.js } Socket.prototype.close = function() { this._healthCheck(); this._stopReceiving(); this._handle.close(); this._handle = null; this.emit('close'); }; Socket.prototype.address = function() { this._healthCheck(); var address = this._handle.getsockname(); if (!address) throw errnoException(process._errno, 'getsockname'); return address; }; Socket.prototype.setBroadcast = function(arg) { if (this._handle.setBroadcast((arg) ? 1 : 0)) { throw errnoException(process._errno, 'setBroadcast'); } }; Socket.prototype.setTTL = function(arg) { if (typeof arg !== 'number') { throw new TypeError('Argument must be a number'); } if (this._handle.setTTL(arg)) { throw errnoException(process._errno, 'setTTL'); } return arg; }; Socket.prototype.setMulticastTTL = function(arg) { if (typeof arg !== 'number') { throw new TypeError('Argument must be a number'); } if (this._handle.setMulticastTTL(arg)) { throw errnoException(process._errno, 'setMulticastTTL'); } return arg; }; Socket.prototype.setMulticastLoopback = function(arg) { arg = arg ? 1 : 0; if (this._handle.setMulticastLoopback(arg)) { throw errnoException(process._errno, 'setMulticastLoopback'); } return arg; // 0.4 compatibility }; Socket.prototype.addMembership = function(multicastAddress, interfaceAddress) { this._healthCheck(); if (!multicastAddress) { throw new Error('multicast address must be specified'); } if (this._handle.addMembership(multicastAddress, interfaceAddress)) { throw new errnoException(process._errno, 'addMembership'); } }; Socket.prototype.dropMembership = function(multicastAddress, interfaceAddress) { this._healthCheck(); if (!multicastAddress) { throw new Error('multicast address must be specified'); } if (this._handle.dropMembership(multicastAddress, interfaceAddress)) { throw new errnoException(process._errno, 'dropMembership'); } }; Socket.prototype._healthCheck = function() { if (!this._handle) throw new Error('Not running'); // error message from dgram_legacy.js }; Socket.prototype._stopReceiving = function() { if (!this._receiving) return; this._handle.recvStop(); this._receiving = false; this.fd = null; // compatibility hack }; function onMessage(handle, slab, start, len, rinfo) { var self = handle.owner; if (!slab) { return self.emit('error', errnoException(process._errno, 'recvmsg')); } rinfo.size = len; // compatibility self.emit('message', slab.slice(start, start + len), rinfo); } Socket.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Socket.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // TODO share with net_uv and others function errnoException(errorno, syscall) { var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } dgram// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Note: In 0.8 and before, crypto functions all defaulted to using // binary-encoded strings rather than buffers. exports.DEFAULT_ENCODING = 'buffer'; try { var binding = process.binding('crypto'); var SecureContext = binding.SecureContext; var randomBytes = binding.randomBytes; var pseudoRandomBytes = binding.pseudoRandomBytes; var getCiphers = binding.getCiphers; var getHashes = binding.getHashes; var crypto = true; } catch (e) { var crypto = false; } var stream = require('stream'); var util = require('util'); // This is here because many functions accepted binary strings without // any explicit encoding in older versions of node, and we don't want // to break them unnecessarily. function toBuf(str, encoding) { encoding = encoding || 'binary'; if (typeof str === 'string') { if (encoding === 'buffer') encoding = 'binary'; str = new Buffer(str, encoding); } return str; } var assert = require('assert'); var StringDecoder = require('string_decoder').StringDecoder; function Credentials(secureProtocol, flags, context) { if (!(this instanceof Credentials)) { return new Credentials(secureProtocol, flags, context); } if (!crypto) { throw new Error('node.js not compiled with openssl crypto support.'); } if (context) { this.context = context; } else { this.context = new SecureContext(); if (secureProtocol) { this.context.init(secureProtocol); } else { this.context.init(); } } if (flags) this.context.setOptions(flags); } exports.Credentials = Credentials; exports.createCredentials = function(options, context) { if (!options) options = {}; var c = new Credentials(options.secureProtocol, options.secureOptions, context); if (context) return c; if (options.key) { if (options.passphrase) { c.context.setKey(options.key, options.passphrase); } else { c.context.setKey(options.key); } } if (options.cert) c.context.setCert(options.cert); if (options.ciphers) c.context.setCiphers(options.ciphers); if (options.ca) { if (Array.isArray(options.ca)) { for (var i = 0, len = options.ca.length; i < len; i++) { c.context.addCACert(options.ca[i]); } } else { c.context.addCACert(options.ca); } } else { c.context.addRootCerts(); } if (options.crl) { if (Array.isArray(options.crl)) { for (var i = 0, len = options.crl.length; i < len; i++) { c.context.addCRL(options.crl[i]); } } else { c.context.addCRL(options.crl); } } if (options.sessionIdContext) { c.context.setSessionIdContext(options.sessionIdContext); } if (options.pfx) { var pfx = options.pfx; var passphrase = options.passphrase; pfx = toBuf(pfx); if (passphrase) passphrase = toBuf(passphrase); if (passphrase) { c.context.loadPKCS12(pfx, passphrase); } else { c.context.loadPKCS12(pfx); } } return c; }; function LazyTransform(options) { this._options = options; } util.inherits(LazyTransform, stream.Transform); [ '_readableState', '_writableState', '_transformState' ].forEach(function(prop, i, props) { Object.defineProperty(LazyTransform.prototype, prop, { get: function() { stream.Transform.call(this, this._options); this._writableState.decodeStrings = false; this._writableState.defaultEncoding = 'binary'; return this[prop]; }, set: function(val) { Object.defineProperty(this, prop, { value: val, enumerable: true, configurable: true, writable: true }); }, configurable: true, enumerable: true }); }); exports.createHash = exports.Hash = Hash; function Hash(algorithm, options) { if (!(this instanceof Hash)) return new Hash(algorithm, options); this._binding = new binding.Hash(algorithm); LazyTransform.call(this, options); } util.inherits(Hash, LazyTransform); Hash.prototype._transform = function(chunk, encoding, callback) { this._binding.update(chunk, encoding); callback(); }; Hash.prototype._flush = function(callback) { var encoding = this._readableState.encoding || 'buffer'; this.push(this._binding.digest(encoding), encoding); callback(); }; Hash.prototype.update = function(data, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; if (encoding === 'buffer' && typeof data === 'string') encoding = 'binary'; this._binding.update(data, encoding); return this; }; Hash.prototype.digest = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; return this._binding.digest(outputEncoding); }; exports.createHmac = exports.Hmac = Hmac; function Hmac(hmac, key, options) { if (!(this instanceof Hmac)) return new Hmac(hmac, key, options); this._binding = new binding.Hmac(); this._binding.init(hmac, toBuf(key)); LazyTransform.call(this, options); } util.inherits(Hmac, LazyTransform); Hmac.prototype.update = Hash.prototype.update; Hmac.prototype.digest = Hash.prototype.digest; Hmac.prototype._flush = Hash.prototype._flush; Hmac.prototype._transform = Hash.prototype._transform; function getDecoder(decoder, encoding) { decoder = decoder || new StringDecoder(encoding); assert(decoder.encoding === encoding, 'Cannot change encoding'); return decoder; } exports.createCipher = exports.Cipher = Cipher; function Cipher(cipher, password, options) { if (!(this instanceof Cipher)) return new Cipher(cipher, password, options); this._binding = new binding.Cipher; this._binding.init(cipher, toBuf(password)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Cipher, LazyTransform); Cipher.prototype._transform = function(chunk, encoding, callback) { this.push(this._binding.update(chunk, encoding)); callback(); }; Cipher.prototype._flush = function(callback) { this.push(this._binding.final()); callback(); }; Cipher.prototype.update = function(data, inputEncoding, outputEncoding) { inputEncoding = inputEncoding || exports.DEFAULT_ENCODING; outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; var ret = this._binding.update(data, inputEncoding); if (outputEncoding && outputEncoding !== 'buffer') { this._decoder = getDecoder(this._decoder, outputEncoding); ret = this._decoder.write(ret); } return ret; }; Cipher.prototype.final = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; var ret = this._binding.final(); if (outputEncoding && outputEncoding !== 'buffer') { this._decoder = getDecoder(this._decoder, outputEncoding); ret = this._decoder.end(ret); } return ret; }; Cipher.prototype.setAutoPadding = function(ap) { this._binding.setAutoPadding(ap); return this; }; exports.createCipheriv = exports.Cipheriv = Cipheriv; function Cipheriv(cipher, key, iv, options) { if (!(this instanceof Cipheriv)) return new Cipheriv(cipher, key, iv, options); this._binding = new binding.Cipher(); this._binding.initiv(cipher, toBuf(key), toBuf(iv)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Cipheriv, LazyTransform); Cipheriv.prototype._transform = Cipher.prototype._transform; Cipheriv.prototype._flush = Cipher.prototype._flush; Cipheriv.prototype.update = Cipher.prototype.update; Cipheriv.prototype.final = Cipher.prototype.final; Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createDecipher = exports.Decipher = Decipher; function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) return new Decipher(cipher, password, options); this._binding = new binding.Decipher; this._binding.init(cipher, toBuf(password)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Decipher, LazyTransform); Decipher.prototype._transform = Cipher.prototype._transform; Decipher.prototype._flush = Cipher.prototype._flush; Decipher.prototype.update = Cipher.prototype.update; Decipher.prototype.final = Cipher.prototype.final; Decipher.prototype.finaltol = Cipher.prototype.final; Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createDecipheriv = exports.Decipheriv = Decipheriv; function Decipheriv(cipher, key, iv, options) { if (!(this instanceof Decipheriv)) return new Decipheriv(cipher, key, iv, options); this._binding = new binding.Decipher; this._binding.initiv(cipher, toBuf(key), toBuf(iv)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Decipheriv, LazyTransform); Decipheriv.prototype._transform = Cipher.prototype._transform; Decipheriv.prototype._flush = Cipher.prototype._flush; Decipheriv.prototype.update = Cipher.prototype.update; Decipheriv.prototype.final = Cipher.prototype.final; Decipheriv.prototype.finaltol = Cipher.prototype.final; Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createSign = exports.Sign = Sign; function Sign(algorithm, options) { if (!(this instanceof Sign)) return new Sign(algorithm, options); this._binding = new binding.Sign(); this._binding.init(algorithm); stream.Writable.call(this, options); } util.inherits(Sign, stream.Writable); Sign.prototype._write = function(chunk, encoding, callback) { this._binding.update(chunk, encoding); callback(); }; Sign.prototype.update = Hash.prototype.update; Sign.prototype.sign = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; var ret = this._binding.sign(toBuf(key)); if (encoding && encoding !== 'buffer') ret = ret.toString(encoding); return ret; }; exports.createVerify = exports.Verify = Verify; function Verify(algorithm, options) { if (!(this instanceof Verify)) return new Verify(algorithm, options); this._binding = new binding.Verify; this._binding.init(algorithm); stream.Writable.call(this, options); } util.inherits(Verify, stream.Writable); Verify.prototype._write = Sign.prototype._write; Verify.prototype.update = Sign.prototype.update; Verify.prototype.verify = function(object, signature, sigEncoding) { sigEncoding = sigEncoding || exports.DEFAULT_ENCODING; return this._binding.verify(toBuf(object), toBuf(signature, sigEncoding)); }; exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman; function DiffieHellman(sizeOrKey, encoding) { if (!(this instanceof DiffieHellman)) return new DiffieHellman(sizeOrKey, encoding); if (!sizeOrKey) this._binding = new binding.DiffieHellman(); else { encoding = encoding || exports.DEFAULT_ENCODING; sizeOrKey = toBuf(sizeOrKey, encoding); this._binding = new binding.DiffieHellman(sizeOrKey); } } exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = DiffieHellmanGroup; function DiffieHellmanGroup(name) { if (!(this instanceof DiffieHellmanGroup)) return new DiffieHellmanGroup(name); this._binding = new binding.DiffieHellmanGroup(name); } DiffieHellmanGroup.prototype.generateKeys = DiffieHellman.prototype.generateKeys = dhGenerateKeys; function dhGenerateKeys(encoding) { var keys = this._binding.generateKeys(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') keys = keys.toString(encoding); return keys; } DiffieHellmanGroup.prototype.computeSecret = DiffieHellman.prototype.computeSecret = dhComputeSecret; function dhComputeSecret(key, inEnc, outEnc) { inEnc = inEnc || exports.DEFAULT_ENCODING; outEnc = outEnc || exports.DEFAULT_ENCODING; var ret = this._binding.computeSecret(toBuf(key, inEnc)); if (outEnc && outEnc !== 'buffer') ret = ret.toString(outEnc); return ret; } DiffieHellmanGroup.prototype.getPrime = DiffieHellman.prototype.getPrime = dhGetPrime; function dhGetPrime(encoding) { var prime = this._binding.getPrime(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') prime = prime.toString(encoding); return prime; } DiffieHellmanGroup.prototype.getGenerator = DiffieHellman.prototype.getGenerator = dhGetGenerator; function dhGetGenerator(encoding) { var generator = this._binding.getGenerator(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') generator = generator.toString(encoding); return generator; } DiffieHellmanGroup.prototype.getPublicKey = DiffieHellman.prototype.getPublicKey = dhGetPublicKey; function dhGetPublicKey(encoding) { var key = this._binding.getPublicKey(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') key = key.toString(encoding); return key; } DiffieHellmanGroup.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey = dhGetPrivateKey; function dhGetPrivateKey(encoding) { var key = this._binding.getPrivateKey(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') key = key.toString(encoding); return key; } DiffieHellman.prototype.setPublicKey = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; this._binding.setPublicKey(toBuf(key, encoding)); return this; }; DiffieHellman.prototype.setPrivateKey = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; this._binding.setPrivateKey(toBuf(key, encoding)); return this; }; exports.pbkdf2 = function(password, salt, iterations, keylen, callback) { if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2'); return pbkdf2(password, salt, iterations, keylen, callback); }; exports.pbkdf2Sync = function(password, salt, iterations, keylen) { return pbkdf2(password, salt, iterations, keylen); }; function pbkdf2(password, salt, iterations, keylen, callback) { password = toBuf(password); salt = toBuf(salt); if (exports.DEFAULT_ENCODING === 'buffer') return binding.PBKDF2(password, salt, iterations, keylen, callback); // at this point, we need to handle encodings. var encoding = exports.DEFAULT_ENCODING; if (callback) { binding.PBKDF2(password, salt, iterations, keylen, function(er, ret) { if (ret) ret = ret.toString(encoding); callback(er, ret); }); } else { var ret = binding.PBKDF2(password, salt, iterations, keylen); return ret.toString(encoding); } } exports.randomBytes = randomBytes; exports.pseudoRandomBytes = pseudoRandomBytes; exports.rng = randomBytes; exports.prng = pseudoRandomBytes; exports.getCiphers = function() { return filterDuplicates(getCiphers.call(null, arguments)); }; exports.getHashes = function() { return filterDuplicates(getHashes.call(null, arguments)); }; function filterDuplicates(names) { // Drop all-caps names in favor of their lowercase aliases, // for example, 'sha1' instead of 'SHA1'. var ctx = {}; names.forEach(function(name) { if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); ctx[name] = true; }); return Object.getOwnPropertyNames(ctx).sort(); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = process.binding('constants'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); function Console(stdout, stderr) { if (!(this instanceof Console)) { return new Console(stdout, stderr); } if (!stdout || typeof stdout.write !== 'function') { throw new TypeError('Console expects a writable stream instance'); } if (!stderr) { stderr = stdout; } var prop = { writable: true, enumerable: false, configurable: true }; prop.value = stdout; Object.defineProperty(this, '_stdout', prop); prop.value = stderr; Object.defineProperty(this, '_stderr', prop); prop.value = {}; Object.defineProperty(this, '_times', prop); // bind the prototype functions to this Console instance Object.keys(Console.prototype).forEach(function(k) { this[k] = this[k].bind(this); }, this); } Console.prototype.log = function() { this._stdout.write(util.format.apply(this, arguments) + '\n'); }; Console.prototype.info = Console.prototype.log; Console.prototype.warn = function() { this._stderr.write(util.format.apply(this, arguments) + '\n'); }; Console.prototype.error = Console.prototype.warn; Console.prototype.dir = function(object) { this._stdout.write(util.inspect(object) + '\n'); }; Console.prototype.time = function(label) { this._times[label] = Date.now(); }; Console.prototype.timeEnd = function(label) { var time = this._times[label]; if (!time) { throw new Error('No such label: ' + label); } var duration = Date.now() - time; this.log('%s: %dms', label, duration); }; Console.prototype.trace = function() { // TODO probably can to do this better with V8's debug object once that is // exposed. var err = new Error; err.name = 'Trace'; err.message = util.format.apply(this, arguments); Error.captureStackTrace(err, arguments.callee); this.error(err.stack); }; Console.prototype.assert = function(expression) { if (!expression) { var arr = Array.prototype.slice.call(arguments, 1); require('assert').ok(false, util.format.apply(this, arr)); } }; module.exports = new Console(process.stdout, process.stderr); module.exports.Console = Console; console// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var fork = require('child_process').fork; var net = require('net'); var EventEmitter = require('events').EventEmitter; var util = require('util'); function isObject(o) { return (typeof o === 'object' && o !== null); } var debug; if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) { debug = function(x) { var prefix = process.pid + ',' + (process.env.NODE_UNIQUE_ID ? 'Worker' : 'Master'); console.error(prefix, x); }; } else { debug = function() { }; } // cluster object: function Cluster() { EventEmitter.call(this); } util.inherits(Cluster, EventEmitter); var cluster = module.exports = new Cluster(); // Used in the master: var masterStarted = false; var ids = 0; var serverHandlers = {}; // Used in the worker: var serverListeners = {}; var queryIds = 0; var queryCallbacks = {}; // Define isWorker and isMaster cluster.isWorker = 'NODE_UNIQUE_ID' in process.env; cluster.isMaster = ! cluster.isWorker; // The worker object is only used in a worker cluster.worker = cluster.isWorker ? {} : null; // The workers array is only used in the master cluster.workers = cluster.isMaster ? {} : null; // Settings object var settings = cluster.settings = {}; // Simple function to call a function on each worker function eachWorker(cb) { // Go through all workers for (var id in cluster.workers) { if (cluster.workers.hasOwnProperty(id)) { cb(cluster.workers[id]); } } } // Extremely simple progress tracker function ProgressTracker(missing, callback) { this.missing = missing; this.callback = callback; } ProgressTracker.prototype.done = function() { this.missing -= 1; this.check(); }; ProgressTracker.prototype.check = function() { if (this.missing === 0) this.callback(); }; cluster.setupMaster = function(options) { // This can only be called from the master. assert(cluster.isMaster); // Don't allow this function to run more than once if (masterStarted) return; masterStarted = true; // Get filename and arguments options = options || {}; // By default, V8 writes the profile data of all processes to a single // v8.log. // // Running that log file through a tick processor produces bogus numbers // because many events won't match up with the recorded memory mappings // and you end up with graphs where 80+% of ticks is unaccounted for. // // Fixing the tick processor to deal with multi-process output is not very // useful because the processes may be running wildly disparate workloads. // // That's why we fix up the command line arguments to include // a "--logfile=v8-%p.log" argument (where %p is expanded to the PID) // unless it already contains a --logfile argument. var execArgv = options.execArgv || process.execArgv; if (execArgv.some(function(s) { return /^--prof/.test(s); }) && !execArgv.some(function(s) { return /^--logfile=/.test(s); })) { execArgv = execArgv.slice(); execArgv.push('--logfile=v8-%p.log'); } // Set settings object settings = cluster.settings = { exec: options.exec || process.argv[1], execArgv: execArgv, args: options.args || process.argv.slice(2), silent: options.silent || false }; // emit setup event cluster.emit('setup'); }; // Check if a message is internal only var INTERNAL_PREFIX = 'NODE_CLUSTER_'; function isInternalMessage(message) { return isObject(message) && typeof message.cmd === 'string' && message.cmd.length > INTERNAL_PREFIX.length && message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX; } // Modify message object to be internal function internalMessage(inMessage) { var outMessage = util._extend({}, inMessage); // Add internal prefix to cmd outMessage.cmd = INTERNAL_PREFIX + (outMessage.cmd || ''); return outMessage; } // Handle callback messages function handleResponse(outMessage, outHandle, inMessage, inHandle, worker) { // The message there will be sent var message = internalMessage(outMessage); // callback id - will be undefined if not set message._queryEcho = inMessage._requestEcho; // Call callback if a query echo is received if (inMessage._queryEcho) { queryCallbacks[inMessage._queryEcho](inMessage.content, inHandle); delete queryCallbacks[inMessage._queryEcho]; } // Send if outWrap contains something useful if (!(outMessage === undefined && message._queryEcho === undefined)) { sendInternalMessage(worker, message, outHandle); } } // Handle messages from both master and workers var messageHandler = {}; function handleMessage(worker, inMessage, inHandle) { // Remove internal prefix var message = util._extend({}, inMessage); message.cmd = inMessage.cmd.substr(INTERNAL_PREFIX.length); var respondUsed = false; function respond(outMessage, outHandler) { respondUsed = true; handleResponse(outMessage, outHandler, inMessage, inHandle, worker); } // Run handler if it exists if (messageHandler[message.cmd]) { messageHandler[message.cmd](message, worker, respond); } // Send respond if it hasn't been called yet if (respondUsed === false) { respond(); } } // Messages to the master will be handled using these methods if (cluster.isMaster) { // Handle online messages from workers messageHandler.online = function(message, worker) { worker.state = 'online'; debug('Worker ' + worker.process.pid + ' online'); worker.emit('online'); cluster.emit('online', worker); }; // Handle queryServer messages from workers messageHandler.queryServer = function(message, worker, send) { // This sequence of information is unique to the connection // but not to the worker var args = [message.address, message.port, message.addressType, message.fd]; var key = args.join(':'); var handler; if (serverHandlers.hasOwnProperty(key)) { handler = serverHandlers[key]; } else if (message.addressType === 'udp4' || message.addressType === 'udp6') { var dgram = require('dgram'); handler = dgram._createSocketHandle.apply(net, args); serverHandlers[key] = handler; } else { handler = net._createServerHandle.apply(net, args); serverHandlers[key] = handler; } // echo callback with the fd handler associated with it send({}, handler); }; // Handle listening messages from workers messageHandler.listening = function(message, worker) { worker.state = 'listening'; // Emit listening, now that we know the worker is listening worker.emit('listening', { address: message.address, port: message.port, addressType: message.addressType, fd: message.fd }); cluster.emit('listening', worker, { address: message.address, port: message.port, addressType: message.addressType, fd: message.fd }); }; // Handle suicide messages from workers messageHandler.suicide = function(message, worker) { worker.suicide = true; }; } // Messages to a worker will be handled using these methods else if (cluster.isWorker) { // Handle worker.disconnect from master messageHandler.disconnect = function(message, worker) { worker.disconnect(); }; } function toDecInt(value) { value = parseInt(value, 10); return isNaN(value) ? null : value; } // Create a worker object, that works both for master and worker function Worker(customEnv) { if (!(this instanceof Worker)) return new Worker(); EventEmitter.call(this); var self = this; var env = process.env; // Assign a unique id, default null this.id = cluster.isMaster ? ++ids : toDecInt(env.NODE_UNIQUE_ID); // XXX: Legacy. Remove in 0.9 this.workerID = this.uniqueID = this.id; // Assign state this.state = 'none'; // Create or get process if (cluster.isMaster) { // Create env object // first: copy and add id property var envCopy = util._extend({}, env); envCopy['NODE_UNIQUE_ID'] = this.id; // second: extend envCopy with the env argument if (isObject(customEnv)) { envCopy = util._extend(envCopy, customEnv); } // fork worker this.process = fork(settings.exec, settings.args, { 'env': envCopy, 'silent': settings.silent, 'execArgv': settings.execArgv }); } else { this.process = process; } if (cluster.isMaster) { // Save worker in the cluster.workers array cluster.workers[this.id] = this; // Emit a fork event, on next tick // There is no worker.fork event since this has no real purpose process.nextTick(function() { cluster.emit('fork', self); }); } // handle internalMessage, exit and disconnect event this.process.on('internalMessage', handleMessage.bind(null, this)); this.process.once('exit', function(exitCode, signalCode) { prepareExit(self, 'dead'); self.emit('exit', exitCode, signalCode); cluster.emit('exit', self, exitCode, signalCode); }); this.process.once('disconnect', function() { prepareExit(self, 'disconnected'); self.emit('disconnect'); cluster.emit('disconnect', self); }); // relay message and error this.process.on('message', this.emit.bind(this, 'message')); this.process.on('error', this.emit.bind(this, 'error')); } util.inherits(Worker, EventEmitter); cluster.Worker = Worker; function prepareExit(worker, state) { // set state to disconnect worker.state = state; // Make suicide a boolean worker.suicide = !!worker.suicide; // Remove from workers in the master if (cluster.isMaster) { delete cluster.workers[worker.id]; } } // Send internal message function sendInternalMessage(worker, message/*, handler, callback*/) { // Exist callback var callback = arguments[arguments.length - 1]; if (typeof callback !== 'function') { callback = undefined; } // exist handler var handler = arguments[2] !== callback ? arguments[2] : undefined; if (!isInternalMessage(message)) { message = internalMessage(message); } // Store callback for later if (callback) { message._requestEcho = worker.id + ':' + (++queryIds); queryCallbacks[message._requestEcho] = callback; } worker.send(message, handler); } // Send message to worker or master Worker.prototype.send = function() { // You could also just use process.send in a worker this.process.send.apply(this.process, arguments); }; // Kill the worker without restarting Worker.prototype.kill = Worker.prototype.destroy = function(signal) { if (!signal) signal = 'SIGTERM'; var self = this; this.suicide = true; if (cluster.isMaster) { // Disconnect IPC channel // this way the worker won't need to propagate suicide state to master if (self.process.connected) { self.process.once('disconnect', function() { self.process.kill(signal); }); self.process.disconnect(); } else { self.process.kill(signal); } } else { // Channel is open if (this.process.connected) { // Inform master to suicide and then kill sendInternalMessage(this, {cmd: 'suicide'}, function() { process.exit(0); }); // When channel is closed, terminate the process this.process.once('disconnect', function() { process.exit(0); }); } else { process.exit(0); } } }; // The .disconnect function will close all servers // and then disconnect the IPC channel. if (cluster.isMaster) { // Used in master Worker.prototype.disconnect = function() { this.suicide = true; sendInternalMessage(this, {cmd: 'disconnect'}); }; } else { // Used in workers Worker.prototype.disconnect = function() { var self = this; this.suicide = true; // keep track of open servers var servers = Object.keys(serverListeners).length; var progress = new ProgressTracker(servers, function() { // There are no more servers open so we will close the IPC channel. // Closing the IPC channel will emit a disconnect event // in both master and worker on the process object. // This event will be handled by prepareExit. self.process.disconnect(); }); // depending on where this function was called from (master or worker) // The suicide state has already been set, // but it doesn't really matter if we set it again. sendInternalMessage(this, {cmd: 'suicide'}, function() { // in case there are no servers progress.check(); // closing all servers gracefully var server; for (var key in serverListeners) { server = serverListeners[key]; // in case the server is closed we won't close it again if (server._handle === null) { progress.done(); continue; } server.on('close', progress.done.bind(progress)); server.close(); } }); }; } // Fork a new worker cluster.fork = function(env) { // This can only be called from the master. assert(cluster.isMaster); // Make sure that the master has been initialized cluster.setupMaster(); return (new cluster.Worker(env)); }; // execute .disconnect on all workers and close handlers when done cluster.disconnect = function(callback) { // This can only be called from the master. assert(cluster.isMaster); // Close all TCP handlers when all workers are disconnected var workers = Object.keys(cluster.workers).length; var progress = new ProgressTracker(workers, function() { for (var key in serverHandlers) { serverHandlers[key].close(); delete serverHandlers[key]; } // call callback when done if (callback) callback(); }); // begin disconnecting all workers eachWorker(function(worker) { worker.once('disconnect', progress.done.bind(progress)); worker.disconnect(); }); // in case there weren't any workers progress.check(); }; // Internal function. Called from src/node.js when worker process starts. cluster._setupWorker = function() { // Get worker class var worker = cluster.worker = new Worker(); // we will terminate the worker // when the worker is disconnected from the parent accidentally process.once('disconnect', function() { if (worker.suicide !== true) { process.exit(0); } }); // Tell master that the worker is online worker.state = 'online'; sendInternalMessage(worker, { cmd: 'online' }); }; // Internal function. Called by net.js and dgram.js when attempting to bind a // TCP server or UDP socket. cluster._getServer = function(tcpSelf, address, port, addressType, fd, cb) { // This can only be called from a worker. assert(cluster.isWorker); // Store tcp instance for later use var key = [address, port, addressType, fd].join(':'); serverListeners[key] = tcpSelf; // Send a listening message to the master tcpSelf.once('listening', function() { cluster.worker.state = 'listening'; sendInternalMessage(cluster.worker, { cmd: 'listening', address: address, port: tcpSelf.address().port || port, addressType: addressType, fd: fd }); }); // Request the fd handler from the master process var message = { cmd: 'queryServer', address: address, port: port, addressType: addressType, fd: fd }; // The callback will be stored until the master has responded sendInternalMessage(cluster.worker, message, function(msg, handle) { cb(handle); }); }; cluster// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var StringDecoder = require('string_decoder').StringDecoder; var EventEmitter = require('events').EventEmitter; var net = require('net'); var dgram = require('dgram'); var Process = process.binding('process_wrap').Process; var assert = require('assert'); var util = require('util'); var constants; // if (!constants) constants = process.binding('constants'); var handleWraps = {}; function handleWrapGetter(name, callback) { var cons; Object.defineProperty(handleWraps, name, { get: function() { if (cons !== undefined) return cons; return cons = callback(); } }); } handleWrapGetter('Pipe', function() { return process.binding('pipe_wrap').Pipe; }); handleWrapGetter('TTY', function() { return process.binding('tty_wrap').TTY; }); handleWrapGetter('TCP', function() { return process.binding('tcp_wrap').TCP; }); handleWrapGetter('UDP', function() { return process.binding('udp_wrap').UDP; }); // constructors for lazy loading function createPipe(ipc) { return new handleWraps.Pipe(ipc); } function createSocket(pipe, readable) { var s = new net.Socket({ handle: pipe }); if (readable) { s.writable = false; s.readable = true; } else { s.writable = true; s.readable = false; } return s; } // this object contain function to convert TCP objects to native handle objects // and back again. var handleConversion = { 'net.Native': { simultaneousAccepts: true, send: function(message, handle) { return handle; }, got: function(message, handle, emit) { emit(handle); } }, 'net.Server': { simultaneousAccepts: true, send: function(message, server) { return server._handle; }, got: function(message, handle, emit) { var self = this; var server = new net.Server(); server.listen(handle, function() { emit(server); }); } }, 'net.Socket': { send: function(message, socket) { // if the socket was created by net.Server if (socket.server) { // the slave should keep track of the socket message.key = socket.server._connectionKey; var firstTime = !this._channel.sockets.send[message.key]; var socketList = getSocketList('send', this, message.key); // the server should no longer expose a .connection property // and when asked to close it should query the socket status from // the slaves if (firstTime) socket.server._setupSlave(socketList); // Act like socket is detached socket.server._connections--; } // remove handle from socket object, it will be closed when the socket // will be sent var handle = socket._handle; handle.onread = function() {}; socket._handle = null; return handle; }, postSend: function(handle) { // Close the Socket handle after sending it handle.close(); }, got: function(message, handle, emit) { var socket = new net.Socket({handle: handle}); socket.readable = socket.writable = true; // if the socket was created by net.Server we will track the socket if (message.key) { // add socket to connections list var socketList = getSocketList('got', this, message.key); socketList.add({ socket: socket }); } emit(socket); } }, 'dgram.Native': { simultaneousAccepts: false, send: function(message, handle) { return handle; }, got: function(message, handle, emit) { emit(handle); } }, 'dgram.Socket': { simultaneousAccepts: false, send: function(message, socket) { message.dgramType = socket.type; return socket._handle; }, got: function(message, handle, emit) { var socket = new dgram.Socket(message.dgramType); socket.bind(handle, function() { emit(socket); }); } } }; // This object keep track of the socket there are sended function SocketListSend(slave, key) { EventEmitter.call(this); var self = this; this.key = key; this.slave = slave; } util.inherits(SocketListSend, EventEmitter); SocketListSend.prototype._request = function(msg, cmd, callback) { var self = this; if (!this.slave.connected) return onclose(); this.slave.send(msg); function onclose() { self.slave.removeListener('internalMessage', onreply); callback(new Error('Slave closed before reply')); }; function onreply(msg) { if (!(msg.cmd === cmd && msg.key === self.key)) return; self.slave.removeListener('disconnect', onclose); self.slave.removeListener('internalMessage', onreply); callback(null, msg); }; this.slave.once('disconnect', onclose); this.slave.on('internalMessage', onreply); }; SocketListSend.prototype.close = function close(callback) { this._request({ cmd: 'NODE_SOCKET_NOTIFY_CLOSE', key: this.key }, 'NODE_SOCKET_ALL_CLOSED', callback); }; SocketListSend.prototype.getConnections = function getConnections(callback) { this._request({ cmd: 'NODE_SOCKET_GET_COUNT', key: this.key }, 'NODE_SOCKET_COUNT', function(err, msg) { if (err) return callback(err); callback(null, msg.count); }); }; // This object keep track of the socket there are received function SocketListReceive(slave, key) { EventEmitter.call(this); var self = this; this.connections = 0; this.key = key; this.slave = slave; function onempty() { if (!self.slave.connected) return; self.slave.send({ cmd: 'NODE_SOCKET_ALL_CLOSED', key: self.key }); } this.slave.on('internalMessage', function(msg) { if (msg.key !== self.key) return; if (msg.cmd === 'NODE_SOCKET_NOTIFY_CLOSE') { // Already empty if (self.connections === 0) return onempty(); // Wait for sockets to get closed self.once('empty', onempty); } else if (msg.cmd === 'NODE_SOCKET_GET_COUNT') { if (!self.slave.connected) return; self.slave.send({ cmd: 'NODE_SOCKET_COUNT', key: self.key, count: self.connections }); } }); } util.inherits(SocketListReceive, EventEmitter); SocketListReceive.prototype.add = function(obj) { var self = this; this.connections++; // Notify previous owner of socket about its state change obj.socket.once('close', function() { self.connections--; if (self.connections === 0) self.emit('empty'); }); }; function getSocketList(type, slave, key) { var sockets = slave._channel.sockets[type]; var socketList = sockets[key]; if (!socketList) { var Construct = type === 'send' ? SocketListSend : SocketListReceive; socketList = sockets[key] = new Construct(slave, key); } return socketList; } var INTERNAL_PREFIX = 'NODE_'; function handleMessage(target, message, handle) { var eventName = 'message'; if (message !== null && typeof message === 'object' && typeof message.cmd === 'string' && message.cmd.length > INTERNAL_PREFIX.length && message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX) { eventName = 'internalMessage'; } target.emit(eventName, message, handle); } function setupChannel(target, channel) { target._channel = channel; target._handleQueue = null; var decoder = new StringDecoder('utf8'); var jsonBuffer = ''; channel.buffering = false; channel.onread = function(pool, offset, length, recvHandle) { if (pool) { jsonBuffer += decoder.write(pool.slice(offset, offset + length)); var i, start = 0; //Linebreak is used as a message end sign while ((i = jsonBuffer.indexOf('\n', start)) >= 0) { var json = jsonBuffer.slice(start, i); var message = JSON.parse(json); // There will be at most one NODE_HANDLE message in every chunk we // read because SCM_RIGHTS messages don't get coalesced. Make sure // that we deliver the handle with the right message however. if (message && message.cmd === 'NODE_HANDLE') handleMessage(target, message, recvHandle); else handleMessage(target, message, undefined); start = i + 1; } jsonBuffer = jsonBuffer.slice(start); this.buffering = jsonBuffer.length !== 0; } else { this.buffering = false; target.disconnect(); channel.onread = nop; channel.close(); maybeClose(target); } }; // object where socket lists will live channel.sockets = { got: {}, send: {} }; // handlers will go through this target.on('internalMessage', function(message, handle) { // Once acknowledged - continue sending handles. if (message.cmd === 'NODE_HANDLE_ACK') { assert(Array.isArray(target._handleQueue)); var queue = target._handleQueue; target._handleQueue = null; queue.forEach(function(args) { target.send(args.message, args.handle); }); return; } if (message.cmd !== 'NODE_HANDLE') return; // Acknowledge handle receival. target.send({ cmd: 'NODE_HANDLE_ACK' }); var obj = handleConversion[message.type]; // Update simultaneous accepts on Windows if (process.platform === 'win32') { handle._simultaneousAccepts = false; net._setSimultaneousAccepts(handle); } // Convert handle object obj.got.call(this, message, handle, function(handle) { handleMessage(target, message.msg, handle); }); }); target.send = function(message, handle) { if (typeof message === 'undefined') { throw new TypeError('message cannot be undefined'); } if (!this.connected) { this.emit('error', new Error('channel closed')); return; } // package messages with a handle object if (handle) { // this message will be handled by an internalMessage event handler message = { cmd: 'NODE_HANDLE', type: null, msg: message }; if (handle instanceof net.Socket) { message.type = 'net.Socket'; } else if (handle instanceof net.Server) { message.type = 'net.Server'; } else if (handle instanceof process.binding('tcp_wrap').TCP || handle instanceof process.binding('pipe_wrap').Pipe) { message.type = 'net.Native'; } else if (handle instanceof dgram.Socket) { message.type = 'dgram.Socket'; } else if (handle instanceof process.binding('udp_wrap').UDP) { message.type = 'dgram.Native'; } else { throw new TypeError("This handle type can't be sent"); } // Queue-up message and handle if we haven't received ACK yet. if (this._handleQueue) { this._handleQueue.push({ message: message.msg, handle: handle }); return; } var obj = handleConversion[message.type]; // convert TCP object to native handle object handle = handleConversion[message.type].send.apply(target, arguments); // Update simultaneous accepts on Windows if (obj.simultaneousAccepts) { net._setSimultaneousAccepts(handle); } } else if (this._handleQueue) { // Queue request anyway to avoid out-of-order messages. this._handleQueue.push({ message: message, handle: null }); return; } var string = JSON.stringify(message) + '\n'; var writeReq = channel.writeUtf8String(string, handle); if (!writeReq) { var er = errnoException(process._errno, 'write', 'cannot write to IPC channel.'); this.emit('error', er); } else if (handle && !this._handleQueue) { this._handleQueue = []; } if (obj && obj.postSend) { writeReq.oncomplete = obj.postSend.bind(null, handle); } else { writeReq.oncomplete = nop; } /* If the master is > 2 read() calls behind, please stop sending. */ return channel.writeQueueSize < (65536 * 2); }; target.connected = true; target.disconnect = function() { if (!this.connected) { this.emit('error', new Error('IPC channel is already disconnected')); return; } // do not allow messages to be written this.connected = false; this._channel = null; var fired = false; function finish() { if (fired) return; fired = true; channel.close(); target.emit('disconnect'); } // If a message is being read, then wait for it to complete. if (channel.buffering) { this.once('message', finish); this.once('internalMessage', finish); return; } finish(); }; channel.readStart(); } function nop() { } exports.fork = function(modulePath /*, args, options*/) { // Get options and args arguments. var options, args, execArgv; if (Array.isArray(arguments[1])) { args = arguments[1]; options = util._extend({}, arguments[2]); } else { args = []; options = util._extend({}, arguments[1]); } // Prepare arguments for fork: execArgv = options.execArgv || process.execArgv; args = execArgv.concat([modulePath], args); // Leave stdin open for the IPC channel. stdout and stderr should be the // same as the parent's if silent isn't set. options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] : [0, 1, 2, 'ipc']; options.execPath = options.execPath || process.execPath; return spawn(options.execPath, args, options); }; exports._forkChild = function(fd) { // set process.send() var p = createPipe(true); p.open(fd); p.unref(); setupChannel(process, p); var refs = 0; process.on('newListener', function(name) { if (name !== 'message' && name !== 'disconnect') return; if (++refs === 1) p.ref(); }); process.on('removeListener', function(name) { if (name !== 'message' && name !== 'disconnect') return; if (--refs === 0) p.unref(); }); }; exports.exec = function(command /*, options, callback */) { var file, args, options, callback; if (typeof arguments[1] === 'function') { options = undefined; callback = arguments[1]; } else { options = arguments[1]; callback = arguments[2]; } if (process.platform === 'win32') { file = 'cmd.exe'; args = ['/s', '/c', '"' + command + '"']; // Make a shallow copy before patching so we don't clobber the user's // options object. options = util._extend({}, options); options.windowsVerbatimArguments = true; } else { file = '/bin/sh'; args = ['-c', command]; } return exports.execFile(file, args, options, callback); }; exports.execFile = function(file /* args, options, callback */) { var args, optionArg, callback; var options = { encoding: 'utf8', timeout: 0, maxBuffer: 200 * 1024, killSignal: 'SIGTERM', cwd: null, env: null }; // Parse the parameters. if (typeof arguments[arguments.length - 1] === 'function') { callback = arguments[arguments.length - 1]; } if (Array.isArray(arguments[1])) { args = arguments[1]; options = util._extend(options, arguments[2]); } else { args = []; options = util._extend(options, arguments[1]); } var child = spawn(file, args, { cwd: options.cwd, env: options.env, windowsVerbatimArguments: !!options.windowsVerbatimArguments }); var stdout = ''; var stderr = ''; var killed = false; var exited = false; var timeoutId; var err; function exithandler(code, signal) { if (exited) return; exited = true; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } if (!callback) return; if (err) { callback(err, stdout, stderr); } else if (code === 0 && signal === null) { callback(null, stdout, stderr); } else { var e = new Error('Command failed: ' + stderr); e.killed = child.killed || killed; e.code = code; e.signal = signal; callback(e, stdout, stderr); } } function errorhandler(e) { err = e; child.stdout.destroy(); child.stderr.destroy(); exithandler(); } function kill() { child.stdout.destroy(); child.stderr.destroy(); killed = true; try { child.kill(options.killSignal); } catch (e) { err = e; exithandler(); } } if (options.timeout > 0) { timeoutId = setTimeout(function() { kill(); timeoutId = null; }, options.timeout); } child.stdout.setEncoding(options.encoding); child.stderr.setEncoding(options.encoding); child.stdout.addListener('data', function(chunk) { stdout += chunk; if (stdout.length > options.maxBuffer) { err = new Error('stdout maxBuffer exceeded.'); kill(); } }); child.stderr.addListener('data', function(chunk) { stderr += chunk; if (stderr.length > options.maxBuffer) { err = new Error('stderr maxBuffer exceeded.'); kill(); } }); child.addListener('close', exithandler); child.addListener('error', errorhandler); return child; }; var spawn = exports.spawn = function(file, args, options) { args = args ? args.slice(0) : []; args.unshift(file); var env = (options ? options.env : null) || process.env; var envPairs = []; for (var key in env) { envPairs.push(key + '=' + env[key]); } var child = new ChildProcess(); if (options && options.customFds && !options.stdio) { options.stdio = options.customFds.map(function(fd) { return fd === -1 ? 'pipe' : fd; }); } child.spawn({ file: file, args: args, cwd: options ? options.cwd : null, windowsVerbatimArguments: !!(options && options.windowsVerbatimArguments), detached: !!(options && options.detached), envPairs: envPairs, stdio: options ? options.stdio : null, uid: options ? options.uid : null, gid: options ? options.gid : null }); return child; }; function maybeClose(subprocess) { subprocess._closesGot++; if (subprocess._closesGot == subprocess._closesNeeded) { subprocess.emit('close', subprocess.exitCode, subprocess.signalCode); } } function ChildProcess() { EventEmitter.call(this); // Initialize TCPWrap and PipeWrap process.binding('tcp_wrap'); process.binding('pipe_wrap'); var self = this; this._closesNeeded = 1; this._closesGot = 0; this.connected = false; this.signalCode = null; this.exitCode = null; this.killed = false; this._handle = new Process(); this._handle.owner = this; this._handle.onexit = function(exitCode, signalCode) { // // follow 0.4.x behaviour: // // - normally terminated processes don't touch this.signalCode // - signaled processes don't touch this.exitCode // // new in 0.9.x: // // - spawn failures are reported with exitCode == -1 // var err = (exitCode == -1) ? errnoException(process._errno, 'spawn') : null; if (signalCode) { self.signalCode = signalCode; } else { self.exitCode = exitCode; } if (self.stdin) { self.stdin.destroy(); } self._handle.close(); self._handle = null; if (exitCode == -1) { self.emit('error', err); } else { self.emit('exit', self.exitCode, self.signalCode); } // if any of the stdio streams have not been touched, // then pull all the data through so that it can get the // eof and emit a 'close' event. // Do it on nextTick so that the user has one last chance // to consume the output, if for example they only want to // start reading the data once the process exits. process.nextTick(function() { flushStdio(self); }); maybeClose(self); }; } util.inherits(ChildProcess, EventEmitter); function flushStdio(subprocess) { subprocess.stdio.forEach(function(stream, fd, stdio) { if (!stream || !stream.readable || stream._consuming || stream._readableState.flowing) return; stream.resume(); }); } function getHandleWrapType(stream) { if (stream instanceof handleWraps.Pipe) return 'pipe'; if (stream instanceof handleWraps.TTY) return 'tty'; if (stream instanceof handleWraps.TCP) return 'tcp'; if (stream instanceof handleWraps.UDP) return 'udp'; return false; } ChildProcess.prototype.spawn = function(options) { var self = this, ipc, ipcFd, // If no `stdio` option was given - use default stdio = options.stdio || 'pipe'; // Replace shortcut with an array if (typeof stdio === 'string') { switch (stdio) { case 'ignore': stdio = ['ignore', 'ignore', 'ignore']; break; case 'pipe': stdio = ['pipe', 'pipe', 'pipe']; break; case 'inherit': stdio = [0, 1, 2]; break; default: throw new TypeError('Incorrect value of stdio option: ' + stdio); } } else if (!Array.isArray(stdio)) { throw new TypeError('Incorrect value of stdio option: ' + stdio); } // At least 3 stdio will be created // Don't concat() a new Array() because it would be sparse, and // stdio.reduce() would skip the sparse elements of stdio. // See http://stackoverflow.com/a/5501711/3561 while (stdio.length < 3) stdio.push(undefined); // Translate stdio into C++-readable form // (i.e. PipeWraps or fds) stdio = stdio.reduce(function(acc, stdio, i) { function cleanup() { acc.filter(function(stdio) { return stdio.type === 'pipe' || stdio.type === 'ipc'; }).forEach(function(stdio) { stdio.handle.close(); }); } // Defaults if (stdio === undefined || stdio === null) { stdio = i < 3 ? 'pipe' : 'ignore'; } if (stdio === 'ignore') { acc.push({type: 'ignore'}); } else if (stdio === 'pipe' || typeof stdio === 'number' && stdio < 0) { acc.push({type: 'pipe', handle: createPipe()}); } else if (stdio === 'ipc') { if (ipc !== undefined) { // Cleanup previously created pipes cleanup(); throw Error('Child process can have only one IPC pipe'); } ipc = createPipe(true); ipcFd = i; acc.push({ type: 'pipe', handle: ipc, ipc: true }); } else if (typeof stdio === 'number' || typeof stdio.fd === 'number') { acc.push({ type: 'fd', fd: stdio.fd || stdio }); } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) || getHandleWrapType(stdio._handle)) { var handle = getHandleWrapType(stdio) ? stdio : getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle; acc.push({ type: 'wrap', wrapType: getHandleWrapType(handle), handle: handle }); } else { // Cleanup cleanup(); throw new TypeError('Incorrect value for stdio stream: ' + stdio); } return acc; }, []); options.stdio = stdio; if (ipc !== undefined) { // Let child process know about opened IPC channel options.envPairs = options.envPairs || []; options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd); } var r = this._handle.spawn(options); if (r) { // Close all opened fds on error stdio.forEach(function(stdio) { if (stdio.type === 'pipe') { stdio.handle.close(); } }); this._handle.close(); this._handle = null; throw errnoException(process._errno, 'spawn'); } this.pid = this._handle.pid; stdio.forEach(function(stdio, i) { if (stdio.type === 'ignore') return; if (stdio.ipc) { self._closesNeeded++; return; } if (stdio.handle) { // when i === 0 - we're dealing with stdin // (which is the only one writable pipe) stdio.socket = createSocket(self.pid !== 0 ? stdio.handle : null, i > 0); if (i > 0 && self.pid !== 0) { self._closesNeeded++; stdio.socket.on('close', function() { maybeClose(self); }); } } }); this.stdin = stdio.length >= 1 && stdio[0].socket !== undefined ? stdio[0].socket : null; this.stdout = stdio.length >= 2 && stdio[1].socket !== undefined ? stdio[1].socket : null; this.stderr = stdio.length >= 3 && stdio[2].socket !== undefined ? stdio[2].socket : null; this.stdio = stdio.map(function(stdio) { return stdio.socket === undefined ? null : stdio.socket; }); // Add .send() method and start listening for IPC data if (ipc !== undefined) setupChannel(this, ipc); return r; }; function errnoException(errorno, syscall, errmsg) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var message = syscall + ' ' + errorno; if (errmsg) { message += ' - ' + errmsg; } var e = new Error(message); e.errno = e.code = errorno; e.syscall = syscall; return e; } ChildProcess.prototype.kill = function(sig) { var signal; if (!constants) { constants = process.binding('constants'); } if (sig === 0) { signal = 0; } else if (!sig) { signal = constants['SIGTERM']; } else { signal = constants[sig]; } if (signal === undefined) { throw new Error('Unknown signal: ' + sig); } if (this._handle) { var r = this._handle.kill(signal); if (r == 0) { /* Success. */ this.killed = true; return true; } else if (process._errno == 'ESRCH') { /* Already dead. */ } else if (process._errno == 'EINVAL' || process._errno == 'ENOSYS') { /* The underlying platform doesn't support this signal. */ throw errnoException(process._errno, 'kill'); } else { /* Other error, almost certainly EPERM. */ this.emit('error', errnoException(process._errno, 'kill')); } } /* Kill didn't succeed. */ return false; }; ChildProcess.prototype.ref = function() { if (this._handle) this._handle.ref(); }; ChildProcess.prototype.unref = function() { if (this._handle) this._handle.unref(); }; child_process// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var SlowBuffer = process.binding('buffer').SlowBuffer; var assert = require('assert'); exports.INSPECT_MAX_BYTES = 50; // Make SlowBuffer inherit from Buffer. // This is an exception to the rule that __proto__ is not allowed in core. SlowBuffer.prototype.__proto__ = Buffer.prototype; function clamp(index, len, defaultValue) { if (typeof index !== 'number') return defaultValue; index = ~~index; // Coerce to integer. if (index >= len) return len; if (index >= 0) return index; index += len; if (index >= 0) return index; return 0; } function toHex(n) { if (n < 16) return '0' + n.toString(16); return n.toString(16); } SlowBuffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); start = +start || 0; if (typeof end !== 'number') end = this.length; // Fastpath empty strings if (+end == start) { return ''; } switch (encoding) { case 'hex': return this.hexSlice(start, end); case 'utf8': case 'utf-8': return this.utf8Slice(start, end); case 'ascii': return this.asciiSlice(start, end); case 'binary': return this.binarySlice(start, end); case 'base64': return this.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.ucs2Slice(start, end); default: throw new TypeError('Unknown encoding: ' + encoding); } }; SlowBuffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); switch (encoding) { case 'hex': return this.hexWrite(string, offset, length); case 'utf8': case 'utf-8': return this.utf8Write(string, offset, length); case 'ascii': return this.asciiWrite(string, offset, length); case 'binary': return this.binaryWrite(string, offset, length); case 'base64': return this.base64Write(string, offset, length); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.ucs2Write(string, offset, length); default: throw new TypeError('Unknown encoding: ' + encoding); } }; // slice(start, end) SlowBuffer.prototype.slice = function(start, end) { var len = this.length; start = clamp(start, len, 0); end = clamp(end, len, len); return new Buffer(this, end - start, start); }; var zeroBuffer = new SlowBuffer(0); // Buffer function Buffer(subject, encoding, offset) { if (!(this instanceof Buffer)) { return new Buffer(subject, encoding, offset); } var buffer = this; // chakra-specific code if (SlowBuffer.makeFastBufferObject !== undefined) { buffer = SlowBuffer.makeFastBufferObject(); buffer.__proto__ = this.__proto__; } var type; // Are we slicing? if (typeof offset === 'number') { if (!Buffer.isBuffer(subject)) { throw new TypeError('First argument must be a Buffer when slicing'); } buffer.length = +encoding > 0 ? Math.ceil(encoding) : 0; buffer.parent = subject.parent ? subject.parent : subject; buffer.offset = offset; } else { // Find the length switch (type = typeof subject) { case 'number': buffer.length = +subject > 0 ? Math.ceil(subject) : 0; break; case 'string': buffer.length = Buffer.byteLength(subject, encoding); break; case 'object': // Assume object is array-ish buffer.length = +subject.length > 0 ? Math.ceil(subject.length) : 0; break; default: throw new TypeError('First argument needs to be a number, ' + 'array or string.'); } if (buffer.length > Buffer.poolSize) { // Big buffer, just alloc one. buffer.parent = new SlowBuffer(buffer.length); buffer.offset = 0; } else if (buffer.length > 0) { // Small buffer. if (!pool || pool.length - pool.used < buffer.length) allocPool(); buffer.parent = pool; buffer.offset = pool.used; pool.used += buffer.length; if (pool.used & 7) pool.used = (pool.used + 8) & ~7; } else { // Zero-length buffer buffer.parent = zeroBuffer; buffer.offset = 0; } // optimize by branching logic for new allocations if (typeof subject !== 'number') { if (type === 'string') { // We are a string buffer.length = buffer.write(subject, 0, encoding); // if subject is buffer then use built-in copy method } else if (Buffer.isBuffer(subject)) { if (subject.parent) subject.parent.copy(buffer.parent, buffer.offset, subject.offset, buffer.length + subject.offset); else subject.copy(buffer.parent, buffer.offset, 0, buffer.length); } else if (isArrayIsh(subject)) { for (var i = 0; i < buffer.length; i++) buffer.parent[i + buffer.offset] = subject[i]; } } } SlowBuffer.makeFastBuffer( buffer.parent, buffer, buffer.offset, buffer.length); return buffer; } function isArrayIsh(subject) { return Array.isArray(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number'; } exports.SlowBuffer = SlowBuffer; exports.Buffer = Buffer; Buffer.isEncoding = function(encoding) { switch (encoding && encoding.toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; default: return false; } }; Buffer.poolSize = 8 * 1024; var pool; function allocPool() { pool = new SlowBuffer(Buffer.poolSize); pool.used = 0; } // Static methods Buffer.isBuffer = function isBuffer(b) { return b instanceof Buffer; }; // Inspect Buffer.prototype.inspect = function inspect() { var out = [], len = this.length, name = this.constructor.name; for (var i = 0; i < len; i++) { out[i] = toHex(this[i]); if (i == exports.INSPECT_MAX_BYTES) { out[i + 1] = '...'; break; } } return '<' + name + ' ' + out.join(' ') + '>'; }; Buffer.prototype.get = function get(offset) { if (offset < 0 || offset >= this.length) throw new RangeError('offset is out of bounds'); return this.parent[this.offset + offset]; }; Buffer.prototype.set = function set(offset, v) { if (offset < 0 || offset >= this.length) throw new RangeError('offset is out of bounds'); return this.parent[this.offset + offset] = v; }; // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8') Buffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); if (string.length > 0 && (length < 0 || offset < 0)) throw new RangeError('attempt to write beyond buffer bounds'); var ret; switch (encoding) { case 'hex': ret = this.parent.hexWrite(string, this.offset + offset, length); break; case 'utf8': case 'utf-8': ret = this.parent.utf8Write(string, this.offset + offset, length); break; case 'ascii': ret = this.parent.asciiWrite(string, this.offset + offset, length); break; case 'binary': ret = this.parent.binaryWrite(string, this.offset + offset, length); break; case 'base64': // Warning: maxLength not taken into account in base64Write ret = this.parent.base64Write(string, this.offset + offset, length); break; case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': ret = this.parent.ucs2Write(string, this.offset + offset, length); break; default: throw new TypeError('Unknown encoding: ' + encoding); } Buffer._charsWritten = SlowBuffer._charsWritten; return ret; }; Buffer.prototype.toJSON = function () { // CHAKRA: since buffer is a Proxy object we are seeing Array.prototype.slice.call retunring an arrays of nulls // not sure if it's a bug or not, but this is a workaround for this issue if (process.ischakra) { var arr = new Array(this.length); for (var i = 0; i < this.length; i++) { // this will make sure that we are retreiving the value through the proxy arr[i] = this[i]; } return arr; } else { return Array.prototype.slice.call(this, 0); } }; // toString(encoding, start=0, end=buffer.length) Buffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); if (typeof start !== 'number' || start < 0) { start = 0; } else if (start > this.length) { start = this.length; } if (typeof end !== 'number' || end > this.length) { end = this.length; } else if (end < 0) { end = 0; } start = start + this.offset; end = end + this.offset; switch (encoding) { case 'hex': return this.parent.hexSlice(start, end); case 'utf8': case 'utf-8': return this.parent.utf8Slice(start, end); case 'ascii': return this.parent.asciiSlice(start, end); case 'binary': return this.parent.binarySlice(start, end); case 'base64': return this.parent.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.parent.ucs2Slice(start, end); default: throw new TypeError('Unknown encoding: ' + encoding); } }; // byteLength Buffer.byteLength = SlowBuffer.byteLength; // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function fill(value, start, end) { value || (value = 0); start || (start = 0); end || (end = this.length); if (typeof value === 'string') { value = value.charCodeAt(0); } if (typeof value !== 'number' || isNaN(value)) { throw new TypeError('value is not a number'); } if (end < start) throw new RangeError('end < start'); // Fill 0 bytes; we're done if (end === start) return 0; if (this.length == 0) return 0; if (start < 0 || start >= this.length) { throw new RangeError('start out of bounds'); } if (end < 0 || end > this.length) { throw new RangeError('end out of bounds'); } return this.parent.fill(value, start + this.offset, end + this.offset); }; Buffer.concat = function(list, length) { if (!Array.isArray(list)) { throw new TypeError('Usage: Buffer.concat(list, [length])'); } if (list.length === 0) { return new Buffer(0); } else if (list.length === 1) { return list[0]; } if (typeof length !== 'number') { length = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; length += buf.length; } } var buffer = new Buffer(length); var pos = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; buf.copy(buffer, pos); pos += buf.length; } return buffer; }; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function(target, target_start, start, end) { // set undefined/NaN or out of bounds values equal to their default if (!(target_start >= 0)) target_start = 0; if (!(start >= 0)) start = 0; if (!(end < this.length)) end = this.length; // Copy 0 bytes; we're done if (end === start || target.length === 0 || this.length === 0 || start > this.length) return 0; if (end < start) throw new RangeError('sourceEnd < sourceStart'); if (target_start >= target.length) throw new RangeError('targetStart out of bounds'); if (target.length - target_start < end - start) end = target.length - target_start + start; return this.parent.copy(target.parent || target, target_start + (target.offset || 0), start + this.offset, end + this.offset); }; // slice(start, end) Buffer.prototype.slice = function(start, end) { var len = this.length; start = clamp(start, len, 0); end = clamp(end, len, len); return new Buffer(this.parent, end - start, start + this.offset); }; // Legacy methods for backwards compatibility. Buffer.prototype.utf8Slice = function(start, end) { return this.toString('utf8', start, end); }; Buffer.prototype.binarySlice = function(start, end) { return this.toString('binary', start, end); }; Buffer.prototype.asciiSlice = function(start, end) { return this.toString('ascii', start, end); }; Buffer.prototype.utf8Write = function(string, offset) { return this.write(string, offset, 'utf8'); }; Buffer.prototype.binaryWrite = function(string, offset) { return this.write(string, offset, 'binary'); }; Buffer.prototype.asciiWrite = function(string, offset) { return this.write(string, offset, 'ascii'); }; /* * Need to make sure that buffer isn't trying to write out of bounds. * This check is far too slow internally for fast buffers. */ function checkOffset(offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint'); if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length'); } Buffer.prototype.readUInt8 = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length); return this[offset]; }; function readUInt16(buffer, offset, isBigEndian) { var val = 0; if (isBigEndian) { val = buffer[offset] << 8; val |= buffer[offset + 1]; } else { val = buffer[offset]; val |= buffer[offset + 1] << 8; } return val; } Buffer.prototype.readUInt16LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readUInt16(this, offset, false, noAssert); }; Buffer.prototype.readUInt16BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readUInt16(this, offset, true, noAssert); }; function readUInt32(buffer, offset, isBigEndian, noAssert) { var val = 0; if (isBigEndian) { val = buffer[offset + 1] << 16; val |= buffer[offset + 2] << 8; val |= buffer[offset + 3]; val = val + (buffer[offset] << 24 >>> 0); } else { val = buffer[offset + 2] << 16; val |= buffer[offset + 1] << 8; val |= buffer[offset]; val = val + (buffer[offset + 3] << 24 >>> 0); } return val; } Buffer.prototype.readUInt32LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readUInt32(this, offset, false, noAssert); }; Buffer.prototype.readUInt32BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readUInt32(this, offset, true, noAssert); }; /* * Signed integer types, yay team! A reminder on how two's complement actually * works. The first bit is the signed bit, i.e. tells us whether or not the * number should be positive or negative. If the two's complement value is * positive, then we're done, as it's equivalent to the unsigned representation. * * Now if the number is positive, you're pretty much done, you can just leverage * the unsigned translations and return those. Unfortunately, negative numbers * aren't quite that straightforward. * * At first glance, one might be inclined to use the traditional formula to * translate binary numbers between the positive and negative values in two's * complement. (Though it doesn't quite work for the most negative value) * Mainly: * - invert all the bits * - add one to the result * * Of course, this doesn't quite work in Javascript. Take for example the value * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of * course, Javascript will do the following: * * > ~0xff80 * -65409 * * Whoh there, Javascript, that's not quite right. But wait, according to * Javascript that's perfectly correct. When Javascript ends up seeing the * constant 0xff80, it has no notion that it is actually a signed number. It * assumes that we've input the unsigned value 0xff80. Thus, when it does the * binary negation, it casts it into a signed value, (positive 0xff80). Then * when you perform binary negation on that, it turns it into a negative number. * * Instead, we're going to have to use the following general formula, that works * in a rather Javascript friendly way. I'm glad we don't support this kind of * weird numbering scheme in the kernel. * * (BIT-MAX - (unsigned)val + 1) * -1 * * The astute observer, may think that this doesn't make sense for 8-bit numbers * (really it isn't necessary for them). However, when you get 16-bit numbers, * you do. Let's go back to our prior example and see how this will look: * * (0xffff - 0xff80 + 1) * -1 * (0x007f + 1) * -1 * (0x0080) * -1 */ Buffer.prototype.readInt8 = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length); if (!(this[offset] & 0x80)) return (this[offset]); return ((0xff - this[offset] + 1) * -1); }; function readInt16(buffer, offset, isBigEndian) { var val = readUInt16(buffer, offset, isBigEndian); if (!(val & 0x8000)) return val; return (0xffff - val + 1) * -1; } Buffer.prototype.readInt16LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readInt16(this, offset, false); }; Buffer.prototype.readInt16BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readInt16(this, offset, true); }; function readInt32(buffer, offset, isBigEndian) { var val = readUInt32(buffer, offset, isBigEndian); if (!(val & 0x80000000)) return (val); return (0xffffffff - val + 1) * -1; } Buffer.prototype.readInt32LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readInt32(this, offset, false); }; Buffer.prototype.readInt32BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readInt32(this, offset, true); }; Buffer.prototype.readFloatLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatLE(this.offset + offset, !!noAssert); }; Buffer.prototype.readFloatBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatBE(this.offset + offset, !!noAssert); }; Buffer.prototype.readDoubleLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleLE(this.offset + offset, !!noAssert); }; Buffer.prototype.readDoubleBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleBE(this.offset + offset, !!noAssert); }; function checkInt(buffer, value, offset, ext, max, min) { if ((value % 1) !== 0 || value > max || value < min) throw TypeError('value is out of bounds'); if ((offset % 1) !== 0 || offset < 0) throw TypeError('offset is not uint'); if (offset + ext > buffer.length || buffer.length + offset < 0) throw RangeError('Trying to write outside buffer length'); } Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); this[offset] = value; }; function writeUInt16(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value & 0xff00) >>> 8; buffer[offset + 1] = value & 0x00ff; } else { buffer[offset + 1] = (value & 0xff00) >>> 8; buffer[offset] = value & 0x00ff; } } Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); writeUInt16(this, value, offset, false); }; Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); writeUInt16(this, value, offset, true); }; function writeUInt32(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value >>> 24) & 0xff; buffer[offset + 1] = (value >>> 16) & 0xff; buffer[offset + 2] = (value >>> 8) & 0xff; buffer[offset + 3] = value & 0xff; } else { buffer[offset + 3] = (value >>> 24) & 0xff; buffer[offset + 2] = (value >>> 16) & 0xff; buffer[offset + 1] = (value >>> 8) & 0xff; buffer[offset] = value & 0xff; } } Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); writeUInt32(this, value, offset, false); }; Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); writeUInt32(this, value, offset, true); }; /* * We now move onto our friends in the signed number category. Unlike unsigned * numbers, we're going to have to worry a bit more about how we put values into * arrays. Since we are only worrying about signed 32-bit values, we're in * slightly better shape. Unfortunately, we really can't do our favorite binary * & in this system. It really seems to do the wrong thing. For example: * * > -32 & 0xff * 224 * * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of * this aren't treated as a signed number. Ultimately a bad thing. * * What we're going to want to do is basically create the unsigned equivalent of * our representation and pass that off to the wuint* functions. To do that * we're going to do the following: * * - if the value is positive * we can pass it directly off to the equivalent wuint * - if the value is negative * we do the following computation: * mb + val + 1, where * mb is the maximum unsigned value in that byte size * val is the Javascript negative integer * * * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If * you do out the computations: * * 0xffff - 128 + 1 * 0xffff - 127 * 0xff80 * * You can then encode this value as the signed version. This is really rather * hacky, but it should work and get the job done which is our goal here. */ Buffer.prototype.writeInt8 = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); if (value < 0) value = 0xff + value + 1; this[offset] = value; }; Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (value < 0) value = 0xffff + value + 1; writeUInt16(this, value, offset, false); }; Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (value < 0) value = 0xffff + value + 1; writeUInt16(this, value, offset, true); }; Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; writeUInt32(this, value, offset, false); }; Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; writeUInt32(this, value, offset, true); }; Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatLE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatBE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleLE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleBE(value, this.offset + offset, !!noAssert); }; buffer// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! // // UTILITY var util = require('util'); var pSlice = Array.prototype.slice; // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) assert.AssertionError = function AssertionError(options) { this.name = 'AssertionError'; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; this.message = options.message || getMessage(this); var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) Error.captureStackTrace(this, stackStartFunction); }; // assert.AssertionError instanceof Error util.inherits(assert.AssertionError, Error); function replacer(key, value) { if (value === undefined) { return '' + value; } if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) { return value.toString(); } if (typeof value === 'function' || value instanceof RegExp) { return value.toString(); } return value; } function truncate(s, n) { if (typeof s == 'string') { return s.length < n ? s : s.slice(0, n); } else { return s; } } function getMessage(self) { return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + self.operator + ' ' + truncate(JSON.stringify(self.expected, replacer), 128); } // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new assert.AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!!!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected)) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; function _deepEqual(actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { if (actual[i] !== expected[i]) return false; } return true; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (actual instanceof Date && expected instanceof Date) { return actual.getTime() === expected.getTime(); // 7.3 If the expected value is a RegExp object, the actual value is // equivalent if it is also a RegExp object with the same source and // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). } else if (actual instanceof RegExp && expected instanceof RegExp) { return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; // 7.4. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if (typeof actual != 'object' && typeof expected != 'object') { return actual == expected; // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else { return objEquiv(actual, expected); } } function isUndefinedOrNull(value) { return value === null || value === undefined; } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b) { if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false; // an identical 'prototype' property. if (a.prototype !== b.prototype) return false; //~~~I've managed to break Object.keys through screwy arguments passing. // Converting to array solves the problem. if (isArguments(a)) { if (!isArguments(b)) { return false; } a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b); } try { var ka = Object.keys(a), kb = Object.keys(b), key, i; } catch (e) {//happens when one is a string literal and the other isn't return false; } // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] != kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key])) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected)) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } else if (actual instanceof expected) { return true; } else if (expected.call({}, actual) === true) { return true; } return false; } function _throws(shouldThrow, block, expected, message) { var actual; if (typeof expected === 'string') { message = expected; expected = null; } try { block(); } catch (e) { actual = e; } message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } if (!shouldThrow && expectedException(actual, expected)) { fail(actual, expected, 'Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [true].concat(pSlice.call(arguments))); }; // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = function(block, /*optional*/message) { _throws.apply(this, [false].concat(pSlice.call(arguments))); }; assert.ifError = function(err) { if (err) {throw err;}}; assert// Copyright (c) Microsoft Corporation. All rights reserved. // Patch classes for chakra var extend = function (dest, from) { var props = Object.getOwnPropertyNames(from); props.forEach(function (name) { var destination = Object.getOwnPropertyDescriptor(from, name); try { Object.defineProperty(dest, name, destination); } catch (e) { // ignore errors } }); }; if (!global.__chakra_wp_patched) { // patch fs.js to ignore handling of symbolic links var pathModule = require('path'); var fs = require('fs'); var isWindows = process.platform === 'win32'; // Regex to find the device root, including trailing slash. E.g. 'c:\\'. if (isWindows) { var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; } else { var splitRootRe = /^[\/]*/; } if (isWindows) { var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; } else { var nextPartRe = /(.*?)(?:[\/]+|$)/g; } fs.realpathSync = function realpathSync(p, cache) { // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return cache[p]; } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { knownHard[base] = true; } } // walk down the path, swapping out linked pathparts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { continue; } var resolvedLink; if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // some known symbolic link. no need to stat again. resolvedLink = cache[base]; } else { var permError = false; var stat; try { stat = fs.lstatSync(base); } catch (e) { if (e.errno == 50) { permError = true; stat = null; } else { throw e; } } if (permError || !stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; continue; } // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); } resolvedLink = pathModule.resolve(previous, linkTarget); // track this, if given a cache. if (cache) cache[base] = resolvedLink; if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } if (cache) cache[original] = p; return p; }; function maybeCallback(cb) { return typeof cb === 'function' ? cb : rethrow(); } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { if (typeof cb !== 'function') { return rethrow(); } return function () { return cb.apply(null, arguments); }; } // path fs.realpath: fs.realpath = function realpath(p, cache, cb) { if (typeof cb !== 'function') { cb = maybeCallback(cache); cache = null; } // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return process.nextTick(cb.bind(null, null, cache[p])); } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function (err) { // PATCH: we ignore permissions error, path exists in this case if (err && err.errno != 50) return cb(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } // walk down the path, swapping out linked pathparts for their real // values function LOOP() { // stop if scanned past end of path if (pos >= p.length) { if (cache) cache[original] = p; return cb(null, p); } // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { return process.nextTick(LOOP); } if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // known symbolic link. no need to stat again. return gotResolvedLink(cache[base]); } return fs.lstat(base, gotStat); } function gotStat(err, stat) { // PATCH: we ignore permissions error, path exists in this case if (err && err.errno != 50) return cb(err); // PATCH: we ignore permissions error, path exists in this case // if not a symlink, skip to the next path part if ((err && err.errno == 50) || !stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; return process.nextTick(LOOP); } // stat & read the link if not read before // call gotTarget as soon as the link target is known // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } fs.stat(base, function (err) { if (err) return cb(err); fs.readlink(base, function (err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target, base) { if (err) return cb(err); var resolvedLink = pathModule.resolve(previous, target); if (cache) cache[base] = resolvedLink; gotResolvedLink(resolvedLink); } function gotResolvedLink(resolvedLink) { // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } }; Object.defineProperty(global, '__chakra_wp_patched', { enumerable: false, value: true }); }// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // A bit simpler than readable streams. // Implement an async ._write(chunk, cb), and it'll handle all // the drain event emission and buffering. module.exports = Writable; Writable.WritableState = WritableState; var util = require('util'); var assert = require('assert'); var Stream = require('stream'); util.inherits(Writable, Stream); function WriteReq(chunk, encoding, cb) { this.chunk = chunk; this.encoding = encoding; this.callback = cb; } function WritableState(options, stream) { options = options || {}; // the point at which write() starts returning false // Note: 0 is a valid value, means that we always return false if // the entire buffer is not flushed immediately on write() var hwm = options.highWaterMark; this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; // object stream flag to indicate whether or not this stream // contains buffers or objects. this.objectMode = !!options.objectMode; // cast to ints. this.highWaterMark = ~~this.highWaterMark; this.needDrain = false; // at the start of calling end() this.ending = false; // when end() has been called, and returned this.ended = false; // when 'finish' is emitted this.finished = false; // should we decode strings into buffers before passing to _write? // this is here so that some node-core streams can optimize string // handling at a lower level. var noDecode = options.decodeStrings === false; this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. // Everything else in the universe uses 'utf8', though. this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement // of how much we're waiting to get pushed to some underlying // socket or file. this.length = 0; // a flag to see when we're in the middle of a write. this.writing = false; // a flag to be able to tell if the onwrite cb is called immediately, // or on a later tick. We set this to true at first, becuase any // actions that shouldn't happen until "later" should generally also // not happen before the first write call. this.sync = true; // a flag to know if we're processing previously buffered items, which // may call the _write() callback in the same tick, so that we don't // end up in an overlapped onwrite situation. this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) this.onwrite = function(er) { onwrite(stream, er); }; // the callback that the user supplies to write(chunk,encoding,cb) this.writecb = null; // the amount that is being written when _write is called. this.writelen = 0; this.buffer = []; } function Writable(options) { // Writable ctor is applied to Duplexes, though they're not // instanceof Writable, they're instanceof Readable. if (!(this instanceof Writable) && !(this instanceof Stream.Duplex)) return new Writable(options); this._writableState = new WritableState(options, this); // legacy. this.writable = true; Stream.call(this); } // Otherwise people can pipe Writable streams, which is just wrong. Writable.prototype.pipe = function() { this.emit('error', new Error('Cannot pipe. Not readable.')); }; function writeAfterEnd(stream, state, cb) { var er = new Error('write after end'); // TODO: defer error events consistently everywhere, not just the cb stream.emit('error', er); process.nextTick(function() { cb(er); }); } // If we get something that is not a buffer, string, null, or undefined, // and we're not in objectMode, then that's an error. // Otherwise stream chunks are all considered to be of length=1, and the // watermarks determine how many objects to keep in the buffer, rather than // how many bytes or characters. function validChunk(stream, state, chunk, cb) { var valid = true; if (!Buffer.isBuffer(chunk) && 'string' !== typeof chunk && chunk !== null && chunk !== undefined && !state.objectMode) { var er = new TypeError('Invalid non-string/buffer chunk'); stream.emit('error', er); process.nextTick(function() { cb(er); }); valid = false; } return valid; } Writable.prototype.write = function(chunk, encoding, cb) { var state = this._writableState; var ret = false; if (typeof encoding === 'function') { cb = encoding; encoding = null; } if (Buffer.isBuffer(chunk)) encoding = 'buffer'; else if (!encoding) encoding = state.defaultEncoding; if (typeof cb !== 'function') cb = function() {}; if (state.ended) writeAfterEnd(this, state, cb); else if (validChunk(this, state, chunk, cb)) ret = writeOrBuffer(this, state, chunk, encoding, cb); return ret; }; function decodeChunk(state, chunk, encoding) { if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { chunk = new Buffer(chunk, encoding); } return chunk; } // if we're already writing something, then just put this // in the queue, and wait our turn. Otherwise, call _write // If we return false, then we need a drain event, so set that flag. function writeOrBuffer(stream, state, chunk, encoding, cb) { chunk = decodeChunk(state, chunk, encoding); var len = state.objectMode ? 1 : chunk.length; state.length += len; var ret = state.length < state.highWaterMark; state.needDrain = !ret; if (state.writing) state.buffer.push(new WriteReq(chunk, encoding, cb)); else doWrite(stream, state, len, chunk, encoding, cb); return ret; } function doWrite(stream, state, len, chunk, encoding, cb) { state.writelen = len; state.writecb = cb; state.writing = true; state.sync = true; stream._write(chunk, encoding, state.onwrite); state.sync = false; } function onwriteError(stream, state, sync, er, cb) { if (sync) process.nextTick(function() { cb(er); }); else cb(er); stream.emit('error', er); } function onwriteStateUpdate(state) { state.writing = false; state.writecb = null; state.length -= state.writelen; state.writelen = 0; } function onwrite(stream, er) { var state = stream._writableState; var sync = state.sync; var cb = state.writecb; onwriteStateUpdate(state); if (er) onwriteError(stream, state, sync, er, cb); else { // Check if we're actually ready to finish, but don't emit yet var finished = needFinish(stream, state); if (!finished && !state.bufferProcessing && state.buffer.length) clearBuffer(stream, state); if (sync) { process.nextTick(function() { afterWrite(stream, state, finished, cb); }); } else { afterWrite(stream, state, finished, cb); } } } function afterWrite(stream, state, finished, cb) { if (!finished) onwriteDrain(stream, state); cb(); if (finished) finishMaybe(stream, state); } // Must force callback to be called on nextTick, so that we don't // emit 'drain' before the write() consumer gets the 'false' return // value, and has a chance to attach a 'drain' listener. function onwriteDrain(stream, state) { if (state.length === 0 && state.needDrain) { state.needDrain = false; stream.emit('drain'); } } // if there's something in the buffer waiting, then process it function clearBuffer(stream, state) { state.bufferProcessing = true; for (var c = 0; c < state.buffer.length; c++) { var entry = state.buffer[c]; var chunk = entry.chunk; var encoding = entry.encoding; var cb = entry.callback; var len = state.objectMode ? 1 : chunk.length; doWrite(stream, state, len, chunk, encoding, cb); // if we didn't call the onwrite immediately, then // it means that we need to wait until it does. // also, that means that the chunk and cb are currently // being processed, so move the buffer counter past them. if (state.writing) { c++; break; } } state.bufferProcessing = false; if (c < state.buffer.length) state.buffer = state.buffer.slice(c); else state.buffer.length = 0; } Writable.prototype._write = function(chunk, encoding, cb) { cb(new Error('not implemented')); }; Writable.prototype.end = function(chunk, encoding, cb) { var state = this._writableState; if (typeof chunk === 'function') { cb = chunk; chunk = null; encoding = null; } else if (typeof encoding === 'function') { cb = encoding; encoding = null; } if (typeof chunk !== 'undefined' && chunk !== null) this.write(chunk, encoding); // ignore unnecessary end() calls. if (!state.ending && !state.finished) endWritable(this, state, cb); }; function needFinish(stream, state) { return (state.ending && state.length === 0 && !state.finished && !state.writing); } function finishMaybe(stream, state) { var need = needFinish(stream, state); if (need) { state.finished = true; stream.emit('finish'); } return need; } function endWritable(stream, state, cb) { state.ending = true; finishMaybe(stream, state); if (cb) { if (state.finished) process.nextTick(cb); else stream.once('finish', cb); } state.ended = true; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a transform stream is a readable/writable stream where you do // something with the data. Sometimes it's called a "filter", // but that's not a great name for it, since that implies a thing where // some bits pass through, and others are simply ignored. (That would // be a valid example of a transform, of course.) // // While the output is causally related to the input, it's not a // necessarily symmetric or synchronous transformation. For example, // a zlib stream might take multiple plain-text writes(), and then // emit a single compressed chunk some time in the future. // // Here's how this works: // // The Transform stream has all the aspects of the readable and writable // stream classes. When you write(chunk), that calls _write(chunk,cb) // internally, and returns false if there's a lot of pending writes // buffered up. When you call read(), that calls _read(n) until // there's enough pending readable data buffered up. // // In a transform stream, the written data is placed in a buffer. When // _read(n) is called, it transforms the queued up data, calling the // buffered _write cb's as it consumes chunks. If consuming a single // written chunk would result in multiple output chunks, then the first // outputted bit calls the readcb, and subsequent chunks just go into // the read buffer, and will cause it to emit 'readable' if necessary. // // This way, back-pressure is actually determined by the reading side, // since _read has to be called to start processing a new chunk. However, // a pathological inflate type of transform can cause excessive buffering // here. For example, imagine a stream where every byte of input is // interpreted as an integer from 0-255, and then results in that many // bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in // 1kb of data being output. In this case, you could write a very small // amount of input, and end up with a very large amount of output. In // such a pathological inflating mechanism, there'd be no way to tell // the system to stop doing the transform. A single 4MB write could // cause the system to run out of memory. // // However, even in such a pathological case, only a single written chunk // would be consumed, and then the rest would wait (un-transformed) until // the results of the previous transformed chunk were consumed. module.exports = Transform; var Duplex = require('_stream_duplex'); var util = require('util'); util.inherits(Transform, Duplex); function TransformState(options, stream) { this.afterTransform = function(er, data) { return afterTransform(stream, er, data); }; this.needTransform = false; this.transforming = false; this.writecb = null; this.writechunk = null; } function afterTransform(stream, er, data) { var ts = stream._transformState; ts.transforming = false; var cb = ts.writecb; if (!cb) return stream.emit('error', new Error('no writecb in Transform class')); ts.writechunk = null; ts.writecb = null; if (data !== null && data !== undefined) stream.push(data); if (cb) cb(er); var rs = stream._readableState; rs.reading = false; if (rs.needReadable || rs.length < rs.highWaterMark) { stream._read(rs.highWaterMark); } } function Transform(options) { if (!(this instanceof Transform)) return new Transform(options); Duplex.call(this, options); var ts = this._transformState = new TransformState(options, this); // when the writable side finishes, then flush out anything remaining. var stream = this; // start out asking for a readable event once data is transformed. this._readableState.needReadable = true; // we have implemented the _read method, and done the other things // that Readable wants before the first _read call, so unset the // sync guard flag. this._readableState.sync = false; this.once('finish', function() { if ('function' === typeof this._flush) this._flush(function(er) { done(stream, er); }); else done(stream); }); } Transform.prototype.push = function(chunk, encoding) { this._transformState.needTransform = false; return Duplex.prototype.push.call(this, chunk, encoding); }; // This is the part where you do stuff! // override this function in implementation classes. // 'chunk' is an input chunk. // // Call `push(newChunk)` to pass along transformed output // to the readable side. You may call 'push' zero or more times. // // Call `cb(err)` when you are done with this chunk. If you pass // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. Transform.prototype._transform = function(chunk, encoding, cb) { throw new Error('not implemented'); }; Transform.prototype._write = function(chunk, encoding, cb) { var ts = this._transformState; ts.writecb = cb; ts.writechunk = chunk; ts.writeencoding = encoding; if (!ts.transforming) { var rs = this._readableState; if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); } }; // Doesn't matter what the args are here. // _transform does all the work. // That we got here means that the readable side wants more data. Transform.prototype._read = function(n) { var ts = this._transformState; if (ts.writechunk && ts.writecb && !ts.transforming) { ts.transforming = true; this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); } else { // mark that we need a transform, so that any data that comes in // will get processed, now that we've asked for it. ts.needTransform = true; } }; function done(stream, er) { if (er) return stream.emit('error', er); // if there's nothing in the write buffer, then that means // that nothing more will ever be provided var ws = stream._writableState; var rs = stream._readableState; var ts = stream._transformState; if (ws.length) throw new Error('calling transform done when ws.length != 0'); if (ts.transforming) throw new Error('calling transform done when still transforming'); return stream.push(null); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = Readable; Readable.ReadableState = ReadableState; var EE = require('events').EventEmitter; var Stream = require('stream'); var util = require('util'); var StringDecoder; util.inherits(Readable, Stream); function ReadableState(options, stream) { options = options || {}; // the point at which it stops calling _read() to fill the buffer // Note: 0 is a valid value, means "don't call _read preemptively ever" var hwm = options.highWaterMark; this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; // cast to ints. this.highWaterMark = ~~this.highWaterMark; this.buffer = []; this.length = 0; this.pipes = null; this.pipesCount = 0; this.flowing = false; this.ended = false; this.endEmitted = false; this.reading = false; // In streams that never have any data, and do push(null) right away, // the consumer can miss the 'end' event if they do some I/O before // consuming the stream. So, we don't emit('end') until some reading // happens. this.calledRead = false; // a flag to be able to tell if the onwrite cb is called immediately, // or on a later tick. We set this to true at first, becuase any // actions that shouldn't happen until "later" should generally also // not happen before the first write call. this.sync = true; // whenever we return null, then we set a flag to say // that we're awaiting a 'readable' event emission. this.needReadable = false; this.emittedReadable = false; this.readableListening = false; // object stream flag. Used to make read(n) ignore n and to // make all the buffer merging and length checks go away this.objectMode = !!options.objectMode; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. // Everything else in the universe uses 'utf8', though. this.defaultEncoding = options.defaultEncoding || 'utf8'; // when piping, we only care about 'readable' events that happen // after read()ing all the bytes and not getting any pushback. this.ranOut = false; // the number of writers that are awaiting a drain event in .pipe()s this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled this.readingMore = false; this.decoder = null; this.encoding = null; if (options.encoding) { if (!StringDecoder) StringDecoder = require('string_decoder').StringDecoder; this.decoder = new StringDecoder(options.encoding); this.encoding = options.encoding; } } function Readable(options) { if (!(this instanceof Readable)) return new Readable(options); this._readableState = new ReadableState(options, this); // legacy this.readable = true; Stream.call(this); } // Manually shove something into the read() buffer. // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should // write() some more. Readable.prototype.push = function(chunk, encoding) { var state = this._readableState; if (typeof chunk === 'string' && !state.objectMode) { encoding = encoding || state.defaultEncoding; if (encoding !== state.encoding) { chunk = new Buffer(chunk, encoding); encoding = ''; } } return readableAddChunk(this, state, chunk, encoding, false); }; // Unshift should *always* be something directly out of read() Readable.prototype.unshift = function(chunk) { var state = this._readableState; return readableAddChunk(this, state, chunk, '', true); }; function readableAddChunk(stream, state, chunk, encoding, addToFront) { var er = chunkInvalid(state, chunk); if (er) { stream.emit('error', er); } else if (chunk === null || chunk === undefined) { state.reading = false; if (!state.ended) onEofChunk(stream, state); } else if (state.objectMode || chunk && chunk.length > 0) { if (state.ended && !addToFront) { var e = new Error('stream.push() after EOF'); stream.emit('error', e); } else if (state.endEmitted && addToFront) { var e = new Error('stream.unshift() after end event'); stream.emit('error', e); } else { if (state.decoder && !addToFront && !encoding) chunk = state.decoder.write(chunk); // update the buffer info. state.length += state.objectMode ? 1 : chunk.length; if (addToFront) { state.buffer.unshift(chunk); } else { state.reading = false; state.buffer.push(chunk); } if (state.needReadable) emitReadable(stream); maybeReadMore(stream, state); } } else if (!addToFront) { state.reading = false; } return needMoreData(state); } // if it's past the high water mark, we can push in some more. // Also, if we have no data yet, we can stand some // more bytes. This is to work around cases where hwm=0, // such as the repl. Also, if the push() triggered a // readable event, and the user called read(largeNumber) such that // needReadable was set, then we ought to push more, so that another // 'readable' event will be triggered. function needMoreData(state) { return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); } // backwards compatibility. Readable.prototype.setEncoding = function(enc) { if (!StringDecoder) StringDecoder = require('string_decoder').StringDecoder; this._readableState.decoder = new StringDecoder(enc); this._readableState.encoding = enc; }; // Don't raise the hwm > 128MB var MAX_HWM = 0x800000; function roundUpToNextPowerOf2(n) { if (n >= MAX_HWM) { n = MAX_HWM; } else { // Get the next highest power of 2 n--; for (var p = 1; p < 32; p <<= 1) n |= n >> p; n++; } return n; } function howMuchToRead(n, state) { if (state.length === 0 && state.ended) return 0; if (state.objectMode) return n === 0 ? 0 : 1; if (isNaN(n) || n === null) { // only flow one buffer at a time if (state.flowing && state.buffer.length) return state.buffer[0].length; else return state.length; } if (n <= 0) return 0; // If we're asking for more than the target buffer level, // then raise the water mark. Bump up to the next highest // power of 2, to prevent increasing it excessively in tiny // amounts. if (n > state.highWaterMark) state.highWaterMark = roundUpToNextPowerOf2(n); // don't have that much. return null, unless we've ended. if (n > state.length) { if (!state.ended) { state.needReadable = true; return 0; } else return state.length; } return n; } // you can override either this method, or the async _read(n) below. Readable.prototype.read = function(n) { var state = this._readableState; state.calledRead = true; var nOrig = n; if (typeof n !== 'number' || n > 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we // already have a bunch of data in the buffer, then just trigger // the 'readable' event and move on. if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { emitReadable(this); return null; } n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up. if (n === 0 && state.ended) { if (state.length === 0) endReadable(this); return null; } // All the actual chunk generation logic needs to be // *below* the call to _read. The reason is that in certain // synthetic stream cases, such as passthrough streams, _read // may be a completely synchronous operation which may change // the state of the read buffer, providing enough data when // before there was *not* enough. // // So, the steps are: // 1. Figure out what the state of things will be after we do // a read from the buffer. // // 2. If that resulting state will trigger a _read, then call _read. // Note that this may be asynchronous, or synchronous. Yes, it is // deeply ugly to write APIs this way, but that still doesn't mean // that the Readable class should behave improperly, as streams are // designed to be sync/async agnostic. // Take note if the _read call is sync or async (ie, if the read call // has returned yet), so that we know whether or not it's safe to emit // 'readable' etc. // // 3. Actually pull the requested chunks out of the buffer and return. // if we need a readable event, then we need to do some reading. var doRead = state.needReadable; // if we currently have less than the highWaterMark, then also read some if (state.length - n <= state.highWaterMark) doRead = true; // however, if we've ended, then there's no point, and if we're already // reading, then it's unnecessary. if (state.ended || state.reading) doRead = false; if (doRead) { state.reading = true; state.sync = true; // if the length is currently zero, then we *need* a readable event. if (state.length === 0) state.needReadable = true; // call internal read method this._read(state.highWaterMark); state.sync = false; } // If _read called its callback synchronously, then `reading` // will be false, and we need to re-evaluate how much data we // can return to the user. if (doRead && !state.reading) n = howMuchToRead(nOrig, state); var ret; if (n > 0) ret = fromList(n, state); else ret = null; if (ret === null) { state.needReadable = true; n = 0; } state.length -= n; // If we have nothing in the buffer, then we want to know // as soon as we *do* get something into the buffer. if (state.length === 0 && !state.ended) state.needReadable = true; // If we happened to read() exactly the remaining amount in the // buffer, and the EOF has been seen at this point, then make sure // that we emit 'end' on the very next tick. if (state.ended && !state.endEmitted && state.length === 0) endReadable(this); return ret; }; function chunkInvalid(state, chunk) { var er = null; if (!Buffer.isBuffer(chunk) && 'string' !== typeof chunk && chunk !== null && chunk !== undefined && !state.objectMode && !er) { er = new TypeError('Invalid non-string/buffer chunk'); } return er; } function onEofChunk(stream, state) { if (state.decoder && !state.ended) { var chunk = state.decoder.end(); if (chunk && chunk.length) { state.buffer.push(chunk); state.length += state.objectMode ? 1 : chunk.length; } } state.ended = true; // if we've ended and we have some data left, then emit // 'readable' now to make sure it gets picked up. if (state.length > 0) emitReadable(stream); else endReadable(stream); } // Don't emit readable right away in sync mode, because this can trigger // another read() call => stack overflow. This way, it might trigger // a nextTick recursion warning, but that's not so bad. function emitReadable(stream) { var state = stream._readableState; state.needReadable = false; if (state.emittedReadable) return; state.emittedReadable = true; if (state.sync) process.nextTick(function() { emitReadable_(stream); }); else emitReadable_(stream); } function emitReadable_(stream) { stream.emit('readable'); } // at this point, the user has presumably seen the 'readable' event, // and called read() to consume some data. that may have triggered // in turn another _read(n) call, in which case reading = true if // it's in progress. // However, if we're not ended, or reading, and the length < hwm, // then go ahead and try to read some more preemptively. function maybeReadMore(stream, state) { if (!state.readingMore) { state.readingMore = true; process.nextTick(function() { maybeReadMore_(stream, state); }); } } function maybeReadMore_(stream, state) { var len = state.length; while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { stream.read(0); if (len === state.length) // didn't get any data, stop spinning. break; else len = state.length; } state.readingMore = false; } // abstract method. to be overridden in specific implementation classes. // call cb(er, data) where data is <= n in length. // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. Readable.prototype._read = function(n) { this.emit('error', new Error('not implemented')); }; Readable.prototype.pipe = function(dest, pipeOpts) { var src = this; var state = this._readableState; switch (state.pipesCount) { case 0: state.pipes = dest; break; case 1: state.pipes = [state.pipes, dest]; break; default: state.pipes.push(dest); break; } state.pipesCount += 1; var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; var endFn = doEnd ? onend : cleanup; if (state.endEmitted) process.nextTick(endFn); else src.once('end', endFn); dest.on('unpipe', onunpipe); function onunpipe(readable) { if (readable !== src) return; cleanup(); } function onend() { dest.end(); } // when the dest drains, it reduces the awaitDrain counter // on the source. This would be more elegant with a .once() // handler in flow(), but adding and removing repeatedly is // too slow. var ondrain = pipeOnDrain(src); dest.on('drain', ondrain); function cleanup() { // cleanup event handlers once the pipe is broken dest.removeListener('close', onclose); dest.removeListener('finish', onfinish); dest.removeListener('drain', ondrain); dest.removeListener('error', onerror); dest.removeListener('unpipe', onunpipe); src.removeListener('end', onend); src.removeListener('end', cleanup); // if the reader is waiting for a drain event from this // specific writer, then it would cause it to never start // flowing again. // So, if this is awaiting a drain, then we just call it now. // If we don't know, then assume that we are waiting for one. if (!dest._writableState || dest._writableState.needDrain) ondrain(); } // if the dest has an error, then stop piping into it. // however, don't suppress the throwing behavior for this. function onerror(er) { unpipe(); if (EE.listenerCount(dest, 'error') === 0) dest.emit('error', er); } dest.once('error', onerror); // Both close and finish should trigger unpipe, but only once. function onclose() { dest.removeListener('finish', onfinish); unpipe(); } dest.once('close', onclose); function onfinish() { dest.removeListener('close', onclose); unpipe(); } dest.once('finish', onfinish); function unpipe() { src.unpipe(dest); } // tell the dest that it's being piped to dest.emit('pipe', src); // start the flow if it hasn't been started already. if (!state.flowing) { // the handler that waits for readable events after all // the data gets sucked out in flow. // This would be easier to follow with a .once() handler // in flow(), but that is too slow. this.on('readable', pipeOnReadable); state.flowing = true; process.nextTick(function() { flow(src); }); } return dest; }; function pipeOnDrain(src) { return function() { var dest = this; var state = src._readableState; state.awaitDrain--; if (state.awaitDrain === 0) flow(src); }; } function flow(src) { var state = src._readableState; var chunk; state.awaitDrain = 0; function write(dest, i, list) { var written = dest.write(chunk); if (false === written) { state.awaitDrain++; } } while (state.pipesCount && null !== (chunk = src.read())) { if (state.pipesCount === 1) write(state.pipes, 0, null); else state.pipes.forEach(write); src.emit('data', chunk); // if anyone needs a drain, then we have to wait for that. if (state.awaitDrain > 0) return; } // if every destination was unpiped, either before entering this // function, or in the while loop, then stop flowing. // // NB: This is a pretty rare edge case. if (state.pipesCount === 0) { state.flowing = false; // if there were data event listeners added, then switch to old mode. if (EE.listenerCount(src, 'data') > 0) emitDataEvents(src); return; } // at this point, no one needed a drain, so we just ran out of data // on the next readable event, start it over again. state.ranOut = true; } function pipeOnReadable() { if (this._readableState.ranOut) { this._readableState.ranOut = false; flow(this); } } Readable.prototype.unpipe = function(dest) { var state = this._readableState; // if we're not piping anywhere, then do nothing. if (state.pipesCount === 0) return this; // just one destination. most common case. if (state.pipesCount === 1) { // passed in one, but it's not the right one. if (dest && dest !== state.pipes) return this; if (!dest) dest = state.pipes; // got a match. state.pipes = null; state.pipesCount = 0; this.removeListener('readable', pipeOnReadable); state.flowing = false; if (dest) dest.emit('unpipe', this); return this; } // slow case. multiple pipe destinations. if (!dest) { // remove all. var dests = state.pipes; var len = state.pipesCount; state.pipes = null; state.pipesCount = 0; this.removeListener('readable', pipeOnReadable); state.flowing = false; for (var i = 0; i < len; i++) dests[i].emit('unpipe', this); return this; } // try to find the right one. var i = state.pipes.indexOf(dest); if (i === -1) return this; state.pipes.splice(i, 1); state.pipesCount -= 1; if (state.pipesCount === 1) state.pipes = state.pipes[0]; dest.emit('unpipe', this); return this; }; // set up data events if they are asked for // Ensure readable listeners eventually get something Readable.prototype.on = function(ev, fn) { var res = Stream.prototype.on.call(this, ev, fn); if (ev === 'data' && !this._readableState.flowing) emitDataEvents(this); if (ev === 'readable' && this.readable) { var state = this._readableState; if (!state.readableListening) { state.readableListening = true; state.emittedReadable = false; state.needReadable = true; if (!state.reading) { this.read(0); } else if (state.length) { emitReadable(this, state); } } } return res; }; Readable.prototype.addListener = Readable.prototype.on; // pause() and resume() are remnants of the legacy readable stream API // If the user uses them, then switch into old mode. Readable.prototype.resume = function() { emitDataEvents(this); this.read(0); this.emit('resume'); }; Readable.prototype.pause = function() { emitDataEvents(this, true); this.emit('pause'); }; function emitDataEvents(stream, startPaused) { var state = stream._readableState; if (state.flowing) { // https://github.com/isaacs/readable-stream/issues/16 throw new Error('Cannot switch to old mode now.'); } var paused = startPaused || false; var readable = false; // convert to an old-style stream. stream.readable = true; stream.pipe = Stream.prototype.pipe; stream.on = stream.addListener = Stream.prototype.on; stream.on('readable', function() { readable = true; var c; while (!paused && (null !== (c = stream.read()))) stream.emit('data', c); if (c === null) { readable = false; stream._readableState.needReadable = true; } }); stream.pause = function() { paused = true; this.emit('pause'); }; stream.resume = function() { paused = false; if (readable) process.nextTick(function() { stream.emit('readable'); }); else this.read(0); this.emit('resume'); }; // now make it start, just in case it hadn't already. stream.emit('readable'); } // wrap an old-style stream as the async data source. // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. Readable.prototype.wrap = function(stream) { var state = this._readableState; var paused = false; var self = this; stream.on('end', function() { if (state.decoder && !state.ended) { var chunk = state.decoder.end(); if (chunk && chunk.length) self.push(chunk); } self.push(null); }); stream.on('data', function(chunk) { if (state.decoder) chunk = state.decoder.write(chunk); if (!chunk || !state.objectMode && !chunk.length) return; var ret = self.push(chunk); if (!ret) { paused = true; stream.pause(); } }); // proxy all the other methods. // important when wrapping filters and duplexes. for (var i in stream) { if (typeof stream[i] === 'function' && typeof this[i] === 'undefined') { this[i] = function(method) { return function() { return stream[method].apply(stream, arguments); }}(i); } } // proxy certain important events. var events = ['error', 'close', 'destroy', 'pause', 'resume']; events.forEach(function(ev) { stream.on(ev, self.emit.bind(self, ev)); }); // when we try to consume some more bytes, simply unpause the // underlying stream. self._read = function(n) { if (paused) { paused = false; stream.resume(); } }; return self; }; // exposed for testing purposes only. Readable._fromList = fromList; // Pluck off n bytes from an array of buffers. // Length is the combined lengths of all the buffers in the list. function fromList(n, state) { var list = state.buffer; var length = state.length; var stringMode = !!state.decoder; var objectMode = !!state.objectMode; var ret; // nothing in the list, definitely empty. if (list.length === 0) return null; if (length === 0) ret = null; else if (objectMode) ret = list.shift(); else if (!n || n >= length) { // read it all, truncate the array. if (stringMode) ret = list.join(''); else ret = Buffer.concat(list, length); list.length = 0; } else { // read just some of it. if (n < list[0].length) { // just take a part of the first list item. // slice is the same for buffers and strings. var buf = list[0]; ret = buf.slice(0, n); list[0] = buf.slice(n); } else if (n === list[0].length) { // first list is a perfect match ret = list.shift(); } else { // complex case. // we have enough to cover it, but it spans past the first buffer. if (stringMode) ret = ''; else ret = new Buffer(n); var c = 0; for (var i = 0, l = list.length; i < l && c < n; i++) { var buf = list[0]; var cpy = Math.min(n - c, buf.length); if (stringMode) ret += buf.slice(0, cpy); else buf.copy(ret, c, 0, cpy); if (cpy < buf.length) list[0] = buf.slice(cpy); else list.shift(); c += cpy; } } } return ret; } function endReadable(stream) { var state = stream._readableState; // If we get here before consuming all the bytes, then that is a // bug in node. Should never happen. if (state.length > 0) throw new Error('endReadable called on non-empty stream'); if (!state.endEmitted && state.calledRead) { state.ended = true; process.nextTick(function() { // Check that we didn't get one last unshift. if (!state.endEmitted && state.length === 0) { state.endEmitted = true; stream.readable = false; stream.emit('end'); } }); } } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a passthrough stream. // basically just the most minimal sort of Transform stream. // Every written chunk gets output as-is. module.exports = PassThrough; var Transform = require('_stream_transform'); var util = require('util'); util.inherits(PassThrough, Transform); function PassThrough(options) { if (!(this instanceof PassThrough)) return new PassThrough(options); Transform.call(this, options); } PassThrough.prototype._transform = function(chunk, encoding, cb) { cb(null, chunk); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a duplex stream is just a stream that is both readable and writable. // Since JS doesn't have multiple prototypal inheritance, this class // prototypally inherits from Readable, and then parasitically from // Writable. module.exports = Duplex; var util = require('util'); var Readable = require('_stream_readable'); var Writable = require('_stream_writable'); util.inherits(Duplex, Readable); Object.keys(Writable.prototype).forEach(function(method) { if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; }); function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); Readable.call(this, options); Writable.call(this, options); if (options && options.readable === false) this.readable = false; if (options && options.writable === false) this.writable = false; this.allowHalfOpen = true; if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; this.once('end', onend); } // the no-half-open enforcer function onend() { // if we allow half-open state, or if the writable side ended, // then we're ok. if (this.allowHalfOpen || this._writableState.ended) return; // no more data can be written. // But allow more writes to happen in this tick. process.nextTick(this.end.bind(this)); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. function init(list) { list._idleNext = list; list._idlePrev = list; } exports.init = init; // show the most idle item function peek(list) { if (list._idlePrev == list) return null; return list._idlePrev; } exports.peek = peek; // remove the most idle item from the list function shift(list) { var first = list._idlePrev; remove(first); return first; } exports.shift = shift; // remove a item from its list function remove(item) { if (item._idleNext) { item._idleNext._idlePrev = item._idlePrev; } if (item._idlePrev) { item._idlePrev._idleNext = item._idleNext; } item._idleNext = null; item._idlePrev = null; } exports.remove = remove; // remove a item from its list and place at the end. function append(list, item) { remove(item); item._idleNext = list._idleNext; list._idleNext._idlePrev = item; item._idlePrev = list; list._idleNext = item; } exports.append = append; function isEmpty(list) { return list._idleNext === list; } exports.isEmpty = isEmpty; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'), path = require('path'), net = require('net'), vm = require('vm'), repl = require('repl'), inherits = util.inherits, spawn = require('child_process').spawn; exports.start = function(argv, stdin, stdout) { argv || (argv = process.argv.slice(2)); if (argv.length < 1) { console.error('Usage: node debug script.js'); process.exit(1); } // Setup input/output streams stdin = stdin || process.stdin; stdout = stdout || process.stdout; var args = ['--debug-brk'].concat(argv), interface_ = new Interface(stdin, stdout, args); stdin.resume(); process.on('uncaughtException', function(e) { console.error("There was an internal error in Node's debugger. " + 'Please report this bug.'); console.error(e.message); console.error(e.stack); if (interface_.child) interface_.child.kill(); process.exit(1); }); }; exports.port = 5858; // // Parser/Serializer for V8 debugger protocol // http://code.google.com/p/v8/wiki/DebuggerProtocol // // Usage: // p = new Protocol(); // // p.onResponse = function(res) { // // do stuff with response from V8 // }; // // socket.setEncoding('utf8'); // socket.on('data', function(s) { // // Pass strings into the protocol // p.execute(s); // }); // // function Protocol() { this._newRes(); } exports.Protocol = Protocol; Protocol.prototype._newRes = function(raw) { this.res = { raw: raw || '', headers: {} }; this.state = 'headers'; this.reqSeq = 1; this.execute(''); }; Protocol.prototype.execute = function(d) { var res = this.res; res.raw += d; switch (this.state) { case 'headers': var endHeaderIndex = res.raw.indexOf('\r\n\r\n'); if (endHeaderIndex < 0) break; var rawHeader = res.raw.slice(0, endHeaderIndex); var endHeaderByteIndex = Buffer.byteLength(rawHeader, 'utf8'); var lines = rawHeader.split('\r\n'); for (var i = 0; i < lines.length; i++) { var kv = lines[i].split(/: +/); res.headers[kv[0]] = kv[1]; } this.contentLength = +res.headers['Content-Length']; this.bodyStartByteIndex = endHeaderByteIndex + 4; this.state = 'body'; var len = Buffer.byteLength(res.raw, 'utf8'); if (len - this.bodyStartByteIndex < this.contentLength) { break; } // pass thru case 'body': var resRawByteLength = Buffer.byteLength(res.raw, 'utf8'); if (resRawByteLength - this.bodyStartByteIndex >= this.contentLength) { var buf = new Buffer(resRawByteLength); buf.write(res.raw, 0, resRawByteLength, 'utf8'); res.body = buf.slice(this.bodyStartByteIndex, this.bodyStartByteIndex + this.contentLength).toString('utf8'); // JSON parse body? res.body = res.body.length ? JSON.parse(res.body) : {}; // Done! this.onResponse(res); this._newRes(buf.slice(this.bodyStartByteIndex + this.contentLength).toString('utf8')); } break; default: throw new Error('Unknown state'); break; } }; Protocol.prototype.serialize = function(req) { req.type = 'request'; req.seq = this.reqSeq++; var json = JSON.stringify(req); return 'Content-Length: ' + Buffer.byteLength(json, 'utf8') + '\r\n\r\n' + json; }; var NO_FRAME = -1; function Client() { net.Stream.call(this); var protocol = this.protocol = new Protocol(this); this._reqCallbacks = []; var socket = this; this.currentFrame = NO_FRAME; this.currentSourceLine = -1; this.currentSource = null; this.handles = {}; this.scripts = {}; this.breakpoints = []; // Note that 'Protocol' requires strings instead of Buffers. socket.setEncoding('utf8'); socket.on('data', function(d) { protocol.execute(d); }); protocol.onResponse = this._onResponse.bind(this); } inherits(Client, net.Stream); exports.Client = Client; Client.prototype._addHandle = function(desc) { if (typeof desc != 'object' || typeof desc.handle != 'number') { return; } this.handles[desc.handle] = desc; if (desc.type == 'script') { this._addScript(desc); } }; var natives = process.binding('natives'); Client.prototype._addScript = function(desc) { this.scripts[desc.id] = desc; if (desc.name) { desc.isNative = (desc.name.replace('.js', '') in natives) || desc.name == 'node.js'; } }; Client.prototype._removeScript = function(desc) { this.scripts[desc.id] = undefined; }; Client.prototype._onResponse = function(res) { var cb, index = -1; this._reqCallbacks.some(function(fn, i) { if (fn.request_seq == res.body.request_seq) { cb = fn; index = i; return true; } }); var self = this; var handled = false; if (res.headers.Type == 'connect') { // Request a list of scripts for our own storage. self.reqScripts(); self.emit('ready'); handled = true; } else if (res.body && res.body.event == 'break') { this.emit('break', res.body); handled = true; } else if (res.body && res.body.event == 'exception') { this.emit('exception', res.body); handled = true; } else if (res.body && res.body.event == 'afterCompile') { this._addHandle(res.body.body.script); handled = true; } else if (res.body && res.body.event == 'scriptCollected') { // ??? this._removeScript(res.body.body.script); handled = true; } if (cb) { this._reqCallbacks.splice(index, 1); handled = true; var err = res.success === false && (res.message || true) || res.body.success === false && (res.body.message || true); cb(err, res.body && res.body.body || res.body, res); } if (!handled) this.emit('unhandledResponse', res.body); }; Client.prototype.req = function(req, cb) { this.write(this.protocol.serialize(req)); cb.request_seq = req.seq; this._reqCallbacks.push(cb); }; Client.prototype.reqVersion = function(cb) { cb = cb || function() {}; this.req({ command: 'version' } , function(err, body, res) { if (err) return cb(err); cb(null, res.body.body.V8Version, res.body.running); }); }; Client.prototype.reqLookup = function(refs, cb) { var self = this; // TODO: We have a cache of handle's we've already seen in this.handles // This can be used if we're careful. var req = { command: 'lookup', arguments: { handles: refs } }; cb = cb || function() {}; this.req(req, function(err, res) { if (err) return cb(err); for (var ref in res) { if (typeof res[ref] == 'object') { self._addHandle(res[ref]); } } cb(null, res); }); }; Client.prototype.reqScopes = function(cb) { var self = this, req = { command: 'scopes', arguments: {} }; cb = cb || function() {}; this.req(req, function(err, res) { if (err) return cb(err); var refs = res.scopes.map(function(scope) { return scope.object.ref; }); self.reqLookup(refs, function(err, res) { if (err) return cb(err); var globals = Object.keys(res).map(function(key) { return res[key].properties.map(function(prop) { return prop.name; }); }); cb(null, globals.reverse()); }); }); }; // This is like reqEval, except it will look up the expression in each of the // scopes associated with the current frame. Client.prototype.reqEval = function(expression, cb) { var self = this; if (this.currentFrame == NO_FRAME) { // Only need to eval in global scope. this.reqFrameEval(expression, NO_FRAME, cb); return; } cb = cb || function() {}; // Otherwise we need to get the current frame to see which scopes it has. this.reqBacktrace(function(err, bt) { if (err || !bt.frames) { // ?? return cb(null, {}); } var frame = bt.frames[self.currentFrame]; var evalFrames = frame.scopes.map(function(s) { if (!s) return; var x = bt.frames[s.index]; if (!x) return; return x.index; }); self._reqFramesEval(expression, evalFrames, cb); }); }; // Finds the first scope in the array in which the epxression evals. Client.prototype._reqFramesEval = function(expression, evalFrames, cb) { if (evalFrames.length == 0) { // Just eval in global scope. this.reqFrameEval(expression, NO_FRAME, cb); return; } var self = this; var i = evalFrames.shift(); cb = cb || function() {}; this.reqFrameEval(expression, i, function(err, res) { if (!err) return cb(null, res); self._reqFramesEval(expression, evalFrames, cb); }); }; Client.prototype.reqFrameEval = function(expression, frame, cb) { var self = this; var req = { command: 'evaluate', arguments: { expression: expression } }; if (frame == NO_FRAME) { req.arguments.global = true; } else { req.arguments.frame = frame; } cb = cb || function() {}; this.req(req, function(err, res) { if (!err) self._addHandle(res); cb(err, res); }); }; // reqBacktrace(cb) // TODO: from, to, bottom Client.prototype.reqBacktrace = function(cb) { this.req({ command: 'backtrace', arguments: { inlineRefs: true } } , cb); }; // reqSetExceptionBreak(type, cb) // TODO: from, to, bottom Client.prototype.reqSetExceptionBreak = function(type, cb) { this.req({ command: 'setexceptionbreak', arguments: { type: type, enabled: true } }, cb); }; // Returns an array of objects like this: // // { handle: 11, // type: 'script', // name: 'node.js', // id: 14, // lineOffset: 0, // columnOffset: 0, // lineCount: 562, // sourceStart: '(function(process) {\n\n ', // sourceLength: 15939, // scriptType: 2, // compilationType: 0, // context: { ref: 10 }, // text: 'node.js (lines: 562)' } // Client.prototype.reqScripts = function(cb) { var self = this; cb = cb || function() {}; this.req({ command: 'scripts' } , function(err, res) { if (err) return cb(err); for (var i = 0; i < res.length; i++) { self._addHandle(res[i]); } cb(null); }); }; Client.prototype.reqContinue = function(cb) { this.currentFrame = NO_FRAME; this.req({ command: 'continue' }, cb); }; Client.prototype.listbreakpoints = function(cb) { this.req({ command: 'listbreakpoints' }, cb); }; Client.prototype.setBreakpoint = function(req, cb) { req = { command: 'setbreakpoint', arguments: req }; this.req(req, cb); }; Client.prototype.clearBreakpoint = function(req, cb) { var req = { command: 'clearbreakpoint', arguments: req }; this.req(req, cb); }; Client.prototype.reqSource = function(from, to, cb) { var req = { command: 'source', fromLine: from, toLine: to }; this.req(req, cb); }; // client.next(1, cb); Client.prototype.step = function(action, count, cb) { var req = { command: 'continue', arguments: { stepaction: action, stepcount: count } }; this.currentFrame = NO_FRAME; this.req(req, cb); }; Client.prototype.mirrorObject = function(handle, depth, cb) { var self = this; var val; if (handle.type === 'object') { // The handle looks something like this: // { handle: 8, // type: 'object', // className: 'Object', // constructorFunction: { ref: 9 }, // protoObject: { ref: 4 }, // prototypeObject: { ref: 2 }, // properties: [ { name: 'hello', propertyType: 1, ref: 10 } ], // text: '#' } // For now ignore the className and constructor and prototype. // TJ's method of object inspection would probably be good for this: // https://groups.google.com/forum/?pli=1#!topic/nodejs-dev/4gkWBOimiOg var propertyRefs = handle.properties.map(function(p) { return p.ref; }); cb = cb || function() {}; this.reqLookup(propertyRefs, function(err, res) { if (err) { console.error('problem with reqLookup'); cb(null, handle); return; } var mirror, waiting = 1; if (handle.className == 'Array') { mirror = []; } else if (handle.className == 'Date') { mirror = new Date(handle.value); } else { mirror = {}; } var keyValues = []; handle.properties.forEach(function(prop, i) { var value = res[prop.ref]; var mirrorValue; if (value) { mirrorValue = value.value ? value.value : value.text; } else { mirrorValue = '[?]'; } if (Array.isArray(mirror) && typeof prop.name != 'number') { // Skip the 'length' property. return; } keyValues[i] = { name: prop.name, value: mirrorValue }; if (value && value.handle && depth > 0) { waiting++; self.mirrorObject(value, depth - 1, function(err, result) { if (!err) keyValues[i].value = result; waitForOthers(); }); } }); waitForOthers(); function waitForOthers() { if (--waiting === 0 && cb) { keyValues.forEach(function(kv) { mirror[kv.name] = kv.value; }); cb(null, mirror); } }; }); return; } else if (handle.type === 'function') { val = function() {}; } else if (handle.type === 'null') { val = null; } else if (handle.value !== undefined) { val = handle.value; } else if (handle.type === 'undefined') { val = undefined; } else { val = handle; } process.nextTick(function() { cb(null, val); }); }; Client.prototype.fullTrace = function(cb) { var self = this; cb = cb || function() {}; this.reqBacktrace(function(err, trace) { if (err) return cb(err); if (trace.totalFrames <= 0) return cb(Error('No frames')); var refs = []; for (var i = 0; i < trace.frames.length; i++) { var frame = trace.frames[i]; // looks like this: // { type: 'frame', // index: 0, // receiver: { ref: 1 }, // func: { ref: 0 }, // script: { ref: 7 }, // constructCall: false, // atReturn: false, // debuggerFrame: false, // arguments: [], // locals: [], // position: 160, // line: 7, // column: 2, // sourceLineText: ' debugger;', // scopes: [ { type: 1, index: 0 }, { type: 0, index: 1 } ], // text: '#00 blah() /home/ryan/projects/node/test-debug.js l...' } refs.push(frame.script.ref); refs.push(frame.func.ref); refs.push(frame.receiver.ref); } self.reqLookup(refs, function(err, res) { if (err) return cb(err); for (var i = 0; i < trace.frames.length; i++) { var frame = trace.frames[i]; frame.script = res[frame.script.ref]; frame.func = res[frame.func.ref]; frame.receiver = res[frame.receiver.ref]; } cb(null, trace); }); }); }; var commands = [ [ 'run (r)', 'cont (c)', 'next (n)', 'step (s)', 'out (o)', 'backtrace (bt)', 'setBreakpoint (sb)', 'clearBreakpoint (cb)' ], [ 'watch', 'unwatch', 'watchers', 'repl', 'restart', 'kill', 'list', 'scripts', 'breakOnException', 'breakpoints', 'version' ] ]; var helpMessage = 'Commands: ' + commands.map(function(group) { return group.join(', '); }).join(',\n'); function SourceUnderline(sourceText, position, repl) { if (!sourceText) return ''; var head = sourceText.slice(0, position), tail = sourceText.slice(position); // Colourize char if stdout supports colours if (repl.useColors) { tail = tail.replace(/(.+?)([^\w]|$)/, '\u001b[32m$1\u001b[39m$2'); } // Return source line with coloured char at `position` return [ head, tail ].join(''); } function SourceInfo(body) { var result = body.exception ? 'exception in ' : 'break in '; if (body.script) { if (body.script.name) { var name = body.script.name, dir = path.resolve() + '/'; // Change path to relative, if possible if (name.indexOf(dir) === 0) { name = name.slice(dir.length); } result += name; } else { result += '[unnamed]'; } } result += ':'; result += body.sourceLine + 1; if (body.exception) result += '\n' + body.exception.text; return result; } // This class is the repl-enabled debugger interface which is invoked on // "node debug" function Interface(stdin, stdout, args) { var self = this, child; this.stdin = stdin; this.stdout = stdout; this.args = args; // Two eval modes are available: controlEval and debugEval // But controlEval is used by default var opts = { prompt: 'debug> ', input: this.stdin, output: this.stdout, eval: this.controlEval.bind(this), useGlobal: false, ignoreUndefined: true }; if (parseInt(process.env['NODE_NO_READLINE'], 10)) { opts.terminal = false; } else if (parseInt(process.env['NODE_FORCE_READLINE'], 10)) { opts.terminal = true; // Emulate Ctrl+C if we're emulating terminal if (!this.stdout.isTTY) { process.on('SIGINT', function() { self.repl.rli.emit('SIGINT'); }); } } if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { opts.useColors = false; } this.repl = repl.start(opts); // Do not print useless warning repl._builtinLibs.splice(repl._builtinLibs.indexOf('repl'), 1); // Kill child process when main process dies this.repl.on('exit', function() { process.exit(0); }); // Handle all possible exits process.on('exit', this.killChild.bind(this)); process.once('SIGTERM', process.exit.bind(process, 0)); process.once('SIGHUP', process.exit.bind(process, 0)); var proto = Interface.prototype, ignored = ['pause', 'resume', 'exitRepl', 'handleBreak', 'requireConnection', 'killChild', 'trySpawn', 'controlEval', 'debugEval', 'print', 'childPrint', 'clearline'], shortcut = { 'run': 'r', 'cont': 'c', 'next': 'n', 'step': 's', 'out': 'o', 'backtrace': 'bt', 'setBreakpoint': 'sb', 'clearBreakpoint': 'cb', 'pause_': 'pause' }; function defineProperty(key, protoKey) { // Check arity var fn = proto[protoKey].bind(self); if (proto[protoKey].length === 0) { Object.defineProperty(self.repl.context, key, { get: fn, enumerable: true, configurable: false }); } else { self.repl.context[key] = fn; } }; // Copy all prototype methods in repl context // Setup them as getters if possible for (var i in proto) { if (Object.prototype.hasOwnProperty.call(proto, i) && ignored.indexOf(i) === -1) { defineProperty(i, i); if (shortcut[i]) defineProperty(shortcut[i], i); } } this.killed = false; this.waiting = null; this.paused = 0; this.context = this.repl.context; this.history = { debug: [], control: [] }; this.breakpoints = []; this._watchers = []; // Run script automatically this.pause(); // XXX Need to figure out why we need this delay setTimeout(function() { self.run(function() { self.resume(); }); }, 10); } // Stream control Interface.prototype.pause = function() { if (this.killed || this.paused++ > 0) return false; this.repl.rli.pause(); this.stdin.pause(); }; Interface.prototype.resume = function(silent) { if (this.killed || this.paused === 0 || --this.paused !== 0) return false; this.repl.rli.resume(); if (silent !== true) { this.repl.displayPrompt(); } this.stdin.resume(); if (this.waiting) { this.waiting(); this.waiting = null; } }; // Clear current line Interface.prototype.clearline = function() { if (this.stdout.isTTY) { this.stdout.cursorTo(0); this.stdout.clearLine(1); } else { this.stdout.write('\b'); } }; // Print text to output stream Interface.prototype.print = function(text, oneline) { if (this.killed) return; this.clearline(); this.stdout.write(typeof text === 'string' ? text : util.inspect(text)); if (oneline !== true) { this.stdout.write('\n'); } }; // Format and print text from child process Interface.prototype.childPrint = function(text) { this.print(text.toString().split(/\r\n|\r|\n/g).filter(function(chunk) { return chunk; }).map(function(chunk) { return '< ' + chunk; }).join('\n')); this.repl.displayPrompt(true); }; // Errors formatting Interface.prototype.error = function(text) { this.print(text); this.resume(); }; // Debugger's `break` event handler Interface.prototype.handleBreak = function(r) { var self = this; this.pause(); // Save execution context's data this.client.currentSourceLine = r.sourceLine; this.client.currentSourceLineText = r.sourceLineText; this.client.currentSourceColumn = r.sourceColumn; this.client.currentFrame = 0; this.client.currentScript = r.script && r.script.name; // Print break data this.print(SourceInfo(r)); // Show watchers' values this.watchers(true, function(err) { if (err) return self.error(err); // And list source self.list(2); self.resume(true); }); }; // Internal method for checking connection state Interface.prototype.requireConnection = function() { if (!this.client) { this.error('App isn\'t running... Try `run` instead'); return false; } return true; }; // Evals // Used for debugger's commands evaluation and execution Interface.prototype.controlEval = function(code, context, filename, callback) { try { // Repeat last command if empty line are going to be evaluated if (this.repl.rli.history && this.repl.rli.history.length > 0) { if (code === '(\n)') { code = '(' + this.repl.rli.history[0] + '\n)'; } } var result = vm.runInContext(code, context, filename); // Repl should not ask for next command // if current one was asynchronous. if (this.paused === 0) return callback(null, result); // Add a callback for asynchronous command // (it will be automatically invoked by .resume() method this.waiting = function() { callback(null, result); }; } catch (e) { callback(e); } }; // Used for debugger's remote evaluation (`repl`) commands Interface.prototype.debugEval = function(code, context, filename, callback) { if (!this.requireConnection()) return; var self = this, client = this.client; // Repl asked for scope variables if (code === '.scope') { client.reqScopes(callback); return; } var frame = client.currentFrame === NO_FRAME ? frame : undefined; self.pause(); // Request remote evaluation globally or in current frame client.reqFrameEval(code, frame, function(err, res) { if (err) { callback(err); self.resume(true); return; } // Request object by handles (and it's sub-properties) client.mirrorObject(res, 3, function(err, mirror) { callback(null, mirror); self.resume(true); }); }); }; // Utils // Returns number of digits (+1) function intChars(n) { // TODO dumb: if (n < 50) { return 3; } else if (n < 950) { return 4; } else if (n < 9950) { return 5; } else { return 6; } } // Adds spaces and prefix to number function leftPad(n, prefix) { var s = n.toString(), nchars = intChars(n), nspaces = nchars - s.length - 1; prefix || (prefix = ' '); for (var i = 0; i < nspaces; i++) { prefix += ' '; } return prefix + s; } // Commands // Print help message Interface.prototype.help = function() { this.print(helpMessage); }; // Run script Interface.prototype.run = function() { var callback = arguments[0]; if (this.child) { this.error('App is already running... Try `restart` instead'); callback && callback(true); } else { this.trySpawn(callback); } }; // Restart script Interface.prototype.restart = function() { if (!this.requireConnection()) return; var self = this; self.pause(); self.killChild(); // XXX need to wait a little bit for the restart to work? setTimeout(function() { self.trySpawn(); self.resume(); }, 1000); }; // Print version Interface.prototype.version = function() { if (!this.requireConnection()) return; var self = this; this.pause(); this.client.reqVersion(function(err, v) { if (err) { self.error(err); } else { self.print(v); } self.resume(); }); }; // List source code Interface.prototype.list = function(delta) { if (!this.requireConnection()) return; delta || (delta = 5); var self = this, client = this.client, from = client.currentSourceLine - delta + 1, to = client.currentSourceLine + delta + 1; self.pause(); client.reqSource(from, to, function(err, res) { if (err || !res) { self.error('You can\'t list source code right now'); self.resume(); return; } var lines = res.source.split('\n'); for (var i = 0; i < lines.length; i++) { var lineno = res.fromLine + i + 1; if (lineno < from || lineno > to) continue; var current = lineno == 1 + client.currentSourceLine, breakpoint = client.breakpoints.some(function(bp) { return bp.script === client.currentScript && bp.line == lineno; }); if (lineno == 1) { // The first line needs to have the module wrapper filtered out of // it. var wrapper = require('module').wrapper[0]; lines[i] = lines[i].slice(wrapper.length); client.currentSourceColumn -= wrapper.length; } // Highlight executing statement var line; if (current) { line = SourceUnderline(lines[i], client.currentSourceColumn, self.repl); } else { line = lines[i]; } self.print(leftPad(lineno, breakpoint && '*') + ' ' + line); } self.resume(); }); }; // Print backtrace Interface.prototype.backtrace = function() { if (!this.requireConnection()) return; var self = this, client = this.client; self.pause(); client.fullTrace(function(err, bt) { if (err) { self.error('Can\'t request backtrace now'); self.resume(); return; } if (bt.totalFrames == 0) { self.print('(empty stack)'); } else { var trace = [], firstFrameNative = bt.frames[0].script.isNative; for (var i = 0; i < bt.frames.length; i++) { var frame = bt.frames[i]; if (!firstFrameNative && frame.script.isNative) break; var text = '#' + i + ' '; if (frame.func.inferredName && frame.func.inferredName.length > 0) { text += frame.func.inferredName + ' '; } text += path.basename(frame.script.name) + ':'; text += (frame.line + 1) + ':' + (frame.column + 1); trace.push(text); } self.print(trace.join('\n')); } self.resume(); }); }; // First argument tells if it should display internal node scripts or not // (available only for internal debugger's functions) Interface.prototype.scripts = function() { if (!this.requireConnection()) return; var client = this.client, displayNatives = arguments[0] || false, scripts = []; this.pause(); for (var id in client.scripts) { var script = client.scripts[id]; if (typeof script == 'object' && script.name) { if (displayNatives || script.name == client.currentScript || !script.isNative) { scripts.push( (script.name == client.currentScript ? '* ' : ' ') + id + ': ' + path.basename(script.name) ); } } } this.print(scripts.join('\n')); this.resume(); }; // Continue execution of script Interface.prototype.cont = function() { if (!this.requireConnection()) return; this.pause(); var self = this; this.client.reqContinue(function(err) { if (err) self.error(err); self.resume(); }); }; // Step commands generator Interface.stepGenerator = function(type, count) { return function() { if (!this.requireConnection()) return; var self = this; self.pause(); self.client.step(type, count, function(err, res) { if (err) self.error(err); self.resume(); }); }; }; // Jump to next command Interface.prototype.next = Interface.stepGenerator('next', 1); // Step in Interface.prototype.step = Interface.stepGenerator('in', 1); // Step out Interface.prototype.out = Interface.stepGenerator('out', 1); // Watch Interface.prototype.watch = function(expr) { this._watchers.push(expr); }; // Unwatch Interface.prototype.unwatch = function(expr) { var index = this._watchers.indexOf(expr); // Unwatch by expression // or // Unwatch by watcher number this._watchers.splice(index !== -1 ? index : +expr, 1); }; // List watchers Interface.prototype.watchers = function() { var self = this, verbose = arguments[0] || false, callback = arguments[1] || function() {}, waiting = this._watchers.length, values = []; this.pause(); if (!waiting) { this.resume(); return callback(); } this._watchers.forEach(function(watcher, i) { self.debugEval(watcher, null, null, function(err, value) { values[i] = err ? '' : value; wait(); }); }); function wait() { if (--waiting === 0) { if (verbose) self.print('Watchers:'); self._watchers.forEach(function(watcher, i) { self.print(leftPad(i, ' ') + ': ' + watcher + ' = ' + JSON.stringify(values[i])); }); if (verbose) self.print(''); self.resume(); callback(null); } } }; // Break on exception Interface.prototype.breakOnException = function breakOnException() { if (!this.requireConnection()) return; var self = this; // Break on exceptions this.pause(); this.client.reqSetExceptionBreak('all', function(err, res) { self.resume(); }); }; // Add breakpoint Interface.prototype.setBreakpoint = function(script, line, condition, silent) { if (!this.requireConnection()) return; var self = this, scriptId, ambiguous; // setBreakpoint() should insert breakpoint on current line if (script === undefined) { script = this.client.currentScript; line = this.client.currentSourceLine + 1; } // setBreakpoint(line-number) should insert breakpoint in current script if (line === undefined && typeof script === 'number') { line = script; script = this.client.currentScript; } if (/\(\)$/.test(script)) { // setBreakpoint('functionname()'); var req = { type: 'function', target: script.replace(/\(\)$/, ''), condition: condition }; } else { // setBreakpoint('scriptname') if (script != +script && !this.client.scripts[script]) { var scripts = this.client.scripts; Object.keys(scripts).forEach(function(id) { if (scripts[id] && scripts[id].name.indexOf(script) !== -1) { if (scriptId) { ambiguous = true; } scriptId = id; } }); } else { scriptId = script; } if (ambiguous) return this.error('Script name is ambiguous'); if (line <= 0) return this.error('Line should be a positive value'); var req; if (scriptId) { req = { type: 'scriptId', target: scriptId, line: line - 1, condition: condition }; } else { this.print('Warning: script \'' + script + '\' was not loaded yet.'); var escapedPath = script.replace(/([/\\.?*()^${}|[\]])/g, '\\$1'); var scriptPathRegex = '^(.*[\\/\\\\])?' + escapedPath + '$'; req = { type: 'scriptRegExp', target: scriptPathRegex, line: line - 1, condition: condition }; } } self.pause(); self.client.setBreakpoint(req, function(err, res) { if (err) { if (!silent) { self.error(err); } } else { if (!silent) { self.list(5); } // Try load scriptId and line from response if (!scriptId) { scriptId = res.script_id; line = res.line + 1; } // Remember this breakpoint even if scriptId is not resolved yet self.client.breakpoints.push({ id: res.breakpoint, scriptId: scriptId, script: (self.client.scripts[scriptId] || {}).name, line: line, condition: condition, scriptReq: script }); } self.resume(); }); }; // Clear breakpoint Interface.prototype.clearBreakpoint = function(script, line) { if (!this.requireConnection()) return; var ambiguous, breakpoint, index; this.client.breakpoints.some(function(bp, i) { if (bp.scriptId === script || bp.scriptReq === script || (bp.script && bp.script.indexOf(script) !== -1)) { if (index !== undefined) { ambiguous = true; } if (bp.line === line) { index = i; breakpoint = bp.id; return true; } } }); if (ambiguous) return this.error('Script name is ambiguous'); if (breakpoint === undefined) { return this.error('Script : ' + script + ' not found'); } var self = this, req = { breakpoint: breakpoint }; self.pause(); self.client.clearBreakpoint(req, function(err, res) { if (err) { self.error(err); } else { self.client.breakpoints.splice(index, 1); self.list(5); } self.resume(); }); }; // Show breakpoints Interface.prototype.breakpoints = function() { if (!this.requireConnection()) return; this.pause(); var self = this; this.client.listbreakpoints(function(err, res) { if (err) { self.error(err); } else { self.print(res); self.resume(); } }); }; // Pause child process Interface.prototype.pause_ = function() { if (!this.requireConnection()) return; var self = this, cmd = 'process._debugPause();'; this.pause(); this.client.reqFrameEval(cmd, NO_FRAME, function(err, res) { if (err) { self.error(err); } else { self.resume(); } }); }; // Kill child process Interface.prototype.kill = function() { if (!this.child) return; this.killChild(); }; // Activate debug repl Interface.prototype.repl = function() { if (!this.requireConnection()) return; var self = this; self.print('Press Ctrl + C to leave debug repl'); // Don't display any default messages var listeners = this.repl.rli.listeners('SIGINT').slice(0); this.repl.rli.removeAllListeners('SIGINT'); // Exit debug repl on Ctrl + C this.repl.rli.once('SIGINT', function() { // Restore all listeners process.nextTick(function() { listeners.forEach(function(listener) { self.repl.rli.on('SIGINT', listener); }); }); // Exit debug repl self.exitRepl(); }); // Set new this.repl.eval = this.debugEval.bind(this); this.repl.context = {}; // Swap history this.history.control = this.repl.rli.history; this.repl.rli.history = this.history.debug; this.repl.prompt = '> '; this.repl.rli.setPrompt('> '); this.repl.displayPrompt(); }; // Exit debug repl Interface.prototype.exitRepl = function() { // Restore eval this.repl.eval = this.controlEval.bind(this); // Swap history this.history.debug = this.repl.rli.history; this.repl.rli.history = this.history.control; this.repl.context = this.context; this.repl.prompt = 'debug> '; this.repl.rli.setPrompt('debug> '); this.repl.displayPrompt(); }; // Quit Interface.prototype.quit = function() { this.killChild(); process.exit(0); }; // Kills child process Interface.prototype.killChild = function() { if (this.child) { this.child.kill(); this.child = null; } if (this.client) { // Save breakpoints this.breakpoints = this.client.breakpoints; this.client.destroy(); this.client = null; } }; // Spawns child process (and restores breakpoints) Interface.prototype.trySpawn = function(cb) { var self = this, breakpoints = this.breakpoints || [], port = exports.port, host = 'localhost', childArgs = this.args; this.killChild(); if (this.args.length === 2) { var match = this.args[1].match(/^([^:]+):(\d+)$/); if (match) { // Connecting to remote debugger // `node debug localhost:5858` host = match[1]; port = parseInt(match[2], 10); this.child = { kill: function() { // TODO Do we really need to handle it? } }; } } else if (this.args.length === 3) { // `node debug -p pid` if (this.args[1] === '-p' && /^\d+$/.test(this.args[2])) { this.child = { kill: function() { // TODO Do we really need to handle it? } }; process._debugProcess(parseInt(this.args[2], 10)); } else { var match = this.args[1].match(/^--port=(\d+)$/); if (match) { // Start debugger on custom port // `node debug --port=5858 app.js` port = parseInt(match[1], 10); childArgs = ['--debug-brk=' + port].concat(this.args.slice(2)); } } } if (!this.child) { this.child = spawn(process.execPath, childArgs); this.child.stdout.on('data', this.childPrint.bind(this)); this.child.stderr.on('data', this.childPrint.bind(this)); } this.pause(); var client = self.client = new Client(), connectionAttempts = 0; client.once('ready', function() { self.stdout.write(' ok\n'); // Restore breakpoints breakpoints.forEach(function(bp) { self.print('Restoring breakpoint ' + bp.scriptReq + ':' + bp.line); self.setBreakpoint(bp.scriptReq, bp.line, bp.condition, true); }); client.on('close', function() { self.pause(); self.print('program terminated'); self.resume(); self.client = null; self.killChild(); }); if (cb) cb(); self.resume(); }); client.on('unhandledResponse', function(res) { self.pause(); self.print('\nunhandled res:' + JSON.stringify(res)); self.resume(); }); client.on('break', function(res) { self.handleBreak(res.body); }); client.on('exception', function(res) { self.handleBreak(res.body); }); client.on('error', connectError); function connectError() { // If it's failed to connect 4 times then don't catch the next error if (connectionAttempts >= 10) { client.removeListener('error', connectError); } setTimeout(attemptConnect, 500); } function attemptConnect() { ++connectionAttempts; self.stdout.write('.'); client.connect(port, host); } setTimeout(function() { self.print('connecting..', true); attemptConnect(); }, 50); }; // Copyright (c) Microsoft Corporation. All rights reserved. // Patch classes for chakra var extend = function(dest, from) { var props = Object.getOwnPropertyNames(from); props.forEach(function(name) { var destination = Object.getOwnPropertyDescriptor(from, name); try { Object.defineProperty(dest, name, destination); } catch (e) { // ignore errors } }); }; function patchErrorStack() { var util = require('util'); // the 2nd argument is ignored for now Error.__proto__.captureStackTrace = function(err, func) { var currentStack; try { throw new Error; } catch (e) { currentStack = e.stack; } // remove the first line so this function won't be seen var splittedStack = currentStack.split('\n'); var firstLine = splittedStack[0]; splittedStack.splice(0, 3); if (err.name) { firstLine = err.name + ': ' + err.message; } err.stack = firstLine + '\n' + splittedStack.join('\n'); } } function patchTypedArrays() { ArrayBuffer.prototype.slice = function(begin, end) { if (!begin) { throw new Error('Wrong number of arguments.'); } // boundary/arguments check - we do exactly the same ones as in node's // ArrayBuffer if (!end) { end = this.byteLength; } if (begin < 0) { begin = this.byteLength + begin; } if (begin < 0) { begin = 0; } if (begin > this.byteLength) { begin = this.byteLength; } if (end < 0) { end = this.byteLength + end; } if (end < 0) { end = 0; } if (end > this.byteLength) { end = this.byteLength; } if (begin > end) { begin = end; } var slice_length = end - begin; var slicedBuffer = new ArrayBuffer(slice_length); var sourceDataView = new DataView(this); var destDataView = new DataView(slicedBuffer); for (var i = 0; i < slice_length; i++) { destDataView.setInt8(i, sourceDataView.getInt8(begin + i)); } return slicedBuffer; }; // patch slice method for each type: [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array].forEach(function(item) { item.prototype.slice = item.prototype.subarray; item.prototype.get = function(i) { return this[i]; }; item.prototype.set = function(first, second) { if (first instanceof Array) { // in this case - first is an array of values, second is the offset for (var j = 0; j < first.length; j++) { this[j + second] = first[j]; } } else { this[first] = second; } } }); } // this patch fix some failing tests which rely on the stack trace // this little patch adds "JsonParse" to the stack trace function patchJsonParse() { var JsonParseOriginal = JSON.parse; var JsonParse = function() { return JsonParseOriginal.apply(this, arguments); } JSON.parse = JsonParse; } if (!global.__chakra_patched) { // patch console patchErrorStack(); patchTypedArrays(); patchJsonParse(); Object.defineProperty( global, '__chakra_patched', { enumerable: false, value: true }); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Transform = require('_stream_transform'); var binding = process.binding('zlib'); var util = require('util'); var assert = require('assert').ok; // zlib doesn't provide these, so kludge them in following the same // const naming scheme zlib uses. binding.Z_MIN_WINDOWBITS = 8; binding.Z_MAX_WINDOWBITS = 15; binding.Z_DEFAULT_WINDOWBITS = 15; // fewer than 64 bytes per chunk is stupid. // technically it could work with as few as 8, but even 64 bytes // is absurdly low. Usually a MB or more is best. binding.Z_MIN_CHUNK = 64; binding.Z_MAX_CHUNK = Infinity; binding.Z_DEFAULT_CHUNK = (16 * 1024); binding.Z_MIN_MEMLEVEL = 1; binding.Z_MAX_MEMLEVEL = 9; binding.Z_DEFAULT_MEMLEVEL = 8; binding.Z_MIN_LEVEL = -1; binding.Z_MAX_LEVEL = 9; binding.Z_DEFAULT_LEVEL = binding.Z_DEFAULT_COMPRESSION; // expose all the zlib constants Object.keys(binding).forEach(function(k) { if (k.match(/^Z/)) exports[k] = binding[k]; }); // translation table for return codes. exports.codes = { Z_OK: binding.Z_OK, Z_STREAM_END: binding.Z_STREAM_END, Z_NEED_DICT: binding.Z_NEED_DICT, Z_ERRNO: binding.Z_ERRNO, Z_STREAM_ERROR: binding.Z_STREAM_ERROR, Z_DATA_ERROR: binding.Z_DATA_ERROR, Z_MEM_ERROR: binding.Z_MEM_ERROR, Z_BUF_ERROR: binding.Z_BUF_ERROR, Z_VERSION_ERROR: binding.Z_VERSION_ERROR }; Object.keys(exports.codes).forEach(function(k) { exports.codes[exports.codes[k]] = k; }); exports.Deflate = Deflate; exports.Inflate = Inflate; exports.Gzip = Gzip; exports.Gunzip = Gunzip; exports.DeflateRaw = DeflateRaw; exports.InflateRaw = InflateRaw; exports.Unzip = Unzip; exports.createDeflate = function(o) { return new Deflate(o); }; exports.createInflate = function(o) { return new Inflate(o); }; exports.createDeflateRaw = function(o) { return new DeflateRaw(o); }; exports.createInflateRaw = function(o) { return new InflateRaw(o); }; exports.createGzip = function(o) { return new Gzip(o); }; exports.createGunzip = function(o) { return new Gunzip(o); }; exports.createUnzip = function(o) { return new Unzip(o); }; // Convenience methods. // compress/decompress a string or buffer in one step. exports.deflate = function(buffer, callback) { zlibBuffer(new Deflate(), buffer, callback); }; exports.gzip = function(buffer, callback) { zlibBuffer(new Gzip(), buffer, callback); }; exports.deflateRaw = function(buffer, callback) { zlibBuffer(new DeflateRaw(), buffer, callback); }; exports.unzip = function(buffer, callback) { zlibBuffer(new Unzip(), buffer, callback); }; exports.inflate = function(buffer, callback) { zlibBuffer(new Inflate(), buffer, callback); }; exports.gunzip = function(buffer, callback) { zlibBuffer(new Gunzip(), buffer, callback); }; exports.inflateRaw = function(buffer, callback) { zlibBuffer(new InflateRaw(), buffer, callback); }; function zlibBuffer(engine, buffer, callback) { var buffers = []; var nread = 0; engine.on('error', onError); engine.on('end', onEnd); engine.end(buffer); flow(); function flow() { var chunk; while (null !== (chunk = engine.read())) { buffers.push(chunk); nread += chunk.length; } engine.once('readable', flow); } function onError(err) { engine.removeListener('end', onEnd); engine.removeListener('readable', flow); callback(err); } function onEnd() { var buf = Buffer.concat(buffers, nread); buffers = []; callback(null, buf); engine.close(); } } // generic zlib // minimal 2-byte header function Deflate(opts) { if (!(this instanceof Deflate)) return new Deflate(opts); Zlib.call(this, opts, binding.DEFLATE); } function Inflate(opts) { if (!(this instanceof Inflate)) return new Inflate(opts); Zlib.call(this, opts, binding.INFLATE); } // gzip - bigger header, same deflate compression function Gzip(opts) { if (!(this instanceof Gzip)) return new Gzip(opts); Zlib.call(this, opts, binding.GZIP); } function Gunzip(opts) { if (!(this instanceof Gunzip)) return new Gunzip(opts); Zlib.call(this, opts, binding.GUNZIP); } // raw - no header function DeflateRaw(opts) { if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); Zlib.call(this, opts, binding.DEFLATERAW); } function InflateRaw(opts) { if (!(this instanceof InflateRaw)) return new InflateRaw(opts); Zlib.call(this, opts, binding.INFLATERAW); } // auto-detect header. function Unzip(opts) { if (!(this instanceof Unzip)) return new Unzip(opts); Zlib.call(this, opts, binding.UNZIP); } // the Zlib class they all inherit from // This thing manages the queue of requests, and returns // true or false if there is anything in the queue when // you call the .write() method. function Zlib(opts, mode) { this._opts = opts = opts || {}; this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK; Transform.call(this, opts); if (opts.flush) { if (opts.flush !== binding.Z_NO_FLUSH && opts.flush !== binding.Z_PARTIAL_FLUSH && opts.flush !== binding.Z_SYNC_FLUSH && opts.flush !== binding.Z_FULL_FLUSH && opts.flush !== binding.Z_FINISH && opts.flush !== binding.Z_BLOCK) { throw new Error('Invalid flush flag: ' + opts.flush); } } this._flushFlag = opts.flush || binding.Z_NO_FLUSH; if (opts.chunkSize) { if (opts.chunkSize < exports.Z_MIN_CHUNK || opts.chunkSize > exports.Z_MAX_CHUNK) { throw new Error('Invalid chunk size: ' + opts.chunkSize); } } if (opts.windowBits) { if (opts.windowBits < exports.Z_MIN_WINDOWBITS || opts.windowBits > exports.Z_MAX_WINDOWBITS) { throw new Error('Invalid windowBits: ' + opts.windowBits); } } if (opts.level) { if (opts.level < exports.Z_MIN_LEVEL || opts.level > exports.Z_MAX_LEVEL) { throw new Error('Invalid compression level: ' + opts.level); } } if (opts.memLevel) { if (opts.memLevel < exports.Z_MIN_MEMLEVEL || opts.memLevel > exports.Z_MAX_MEMLEVEL) { throw new Error('Invalid memLevel: ' + opts.memLevel); } } if (opts.strategy) { if (opts.strategy != exports.Z_FILTERED && opts.strategy != exports.Z_HUFFMAN_ONLY && opts.strategy != exports.Z_RLE && opts.strategy != exports.Z_FIXED && opts.strategy != exports.Z_DEFAULT_STRATEGY) { throw new Error('Invalid strategy: ' + opts.strategy); } } if (opts.dictionary) { if (!Buffer.isBuffer(opts.dictionary)) { throw new Error('Invalid dictionary: it should be a Buffer instance'); } } this._binding = new binding.Zlib(mode); var self = this; this._hadError = false; this._binding.onerror = function(message, errno) { // there is no way to cleanly recover. // continuing only obscures problems. self._binding = null; self._hadError = true; var error = new Error(message); error.errno = errno; error.code = exports.codes[errno]; self.emit('error', error); }; this._binding.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, opts.level || exports.Z_DEFAULT_COMPRESSION, opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, opts.strategy || exports.Z_DEFAULT_STRATEGY, opts.dictionary); this._buffer = new Buffer(this._chunkSize); this._offset = 0; this._closed = false; this.once('end', this.close); } util.inherits(Zlib, Transform); Zlib.prototype.reset = function reset() { return this._binding.reset(); }; // This is the _flush function called by the transform class, // internally, when the last chunk has been written. Zlib.prototype._flush = function(callback) { this._transform(new Buffer(0), '', callback); }; Zlib.prototype.flush = function(callback) { var ws = this._writableState; if (ws.ended) { if (callback) process.nextTick(callback); } else if (ws.ending) { if (callback) this.once('end', callback); } else if (ws.needDrain) { var self = this; this.once('drain', function() { self.flush(callback); }); } else { this._flushFlag = binding.Z_FULL_FLUSH; this.write(new Buffer(0), '', callback); } }; Zlib.prototype.close = function(callback) { if (callback) process.nextTick(callback); if (this._closed) return; this._closed = true; this._binding.close(); var self = this; process.nextTick(function() { self.emit('close'); }); }; Zlib.prototype._transform = function(chunk, encoding, cb) { var flushFlag; var ws = this._writableState; var ending = ws.ending || ws.ended; var last = ending && (!chunk || ws.length === chunk.length); if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input')); // If it's the last chunk, or a final flush, we use the Z_FINISH flush flag. // If it's explicitly flushing at some other time, then we use // Z_FULL_FLUSH. Otherwise, use Z_NO_FLUSH for maximum compression // goodness. if (last) flushFlag = binding.Z_FINISH; else { flushFlag = this._flushFlag; // once we've flushed the last of the queue, stop flushing and // go back to the normal behavior. if (chunk.length >= ws.length) { this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH; } } var availInBefore = chunk && chunk.length; var availOutBefore = this._chunkSize - this._offset; var inOff = 0; var req = this._binding.write(flushFlag, chunk, // in inOff, // in_off availInBefore, // in_len this._buffer, // out this._offset, //out_off availOutBefore); // out_len req.buffer = chunk; req.callback = callback; var self = this; function callback(availInAfter, availOutAfter, buffer) { if (self._hadError) return; var have = availOutBefore - availOutAfter; assert(have >= 0, 'have should not go down'); if (have > 0) { var out = self._buffer.slice(self._offset, self._offset + have); self._offset += have; // serve some output to the consumer. self.push(out); } // exhausted the output buffer, or used all the input create a new one. if (availOutAfter === 0 || self._offset >= self._chunkSize) { availOutBefore = self._chunkSize; self._offset = 0; self._buffer = new Buffer(self._chunkSize); } if (availOutAfter === 0) { // Not actually done. Need to reprocess. // Also, update the availInBefore to the availInAfter value, // so that if we have to hit it a third (fourth, etc.) time, // it'll have the correct byte counts. inOff += (availInBefore - availInAfter); availInBefore = availInAfter; var newReq = self._binding.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize); newReq.callback = callback; // this same function newReq.buffer = chunk; return; } // finished with the chunk. cb(); } }; util.inherits(Deflate, Zlib); util.inherits(Inflate, Zlib); util.inherits(Gzip, Zlib); util.inherits(Gunzip, Zlib); util.inherits(DeflateRaw, Zlib); util.inherits(InflateRaw, Zlib); util.inherits(Unzip, Zlib); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var binding = process.binding('evals'); module.exports = Script; Script.Script = Script; function Script(code, ctx, filename) { if (!(this instanceof Script)) { return new Script(code, ctx, filename); } var ns = new binding.NodeScript(code, ctx, filename); // bind all methods to this Script object Object.keys(binding.NodeScript.prototype).forEach(function(f) { if (typeof binding.NodeScript.prototype[f] === 'function') { this[f] = function() { if (!(this instanceof Script)) { throw new TypeError('invalid call to ' + f); } return ns[f].apply(ns, arguments); }; } }, this); } Script.createScript = function(code, ctx, name) { return new Script(code, ctx, name); }; Script.createContext = binding.NodeScript.createContext; Script.runInContext = binding.NodeScript.runInContext; Script.runInThisContext = binding.NodeScript.runInThisContext; Script.runInNewContext = binding.NodeScript.runInNewContext; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': return JSON.stringify(args[i++]); default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (x === null || typeof x !== 'object') { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; exports.print = function() { for (var i = 0, len = arguments.length; i < len; ++i) { process.stdout.write(String(arguments[i])); } }; exports.puts = function() { for (var i = 0, len = arguments.length; i < len; ++i) { process.stdout.write(arguments[i] + '\n'); } }; exports.debug = function(x) { process.stderr.write('DEBUG: ' + x + '\n'); }; var error = exports.error = function(x) { for (var i = 0, len = arguments.length; i < len; ++i) { process.stderr.write(arguments[i] + '\n'); } }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (typeof opts === 'boolean') { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (typeof ctx.showHidden === 'undefined') ctx.showHidden = false; if (typeof ctx.depth === 'undefined') ctx.depth = 2; if (typeof ctx.colors === 'undefined') ctx.colors = false; if (typeof ctx.customInspect === 'undefined') ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && typeof value.inspect === 'function' && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { return String(value.inspect(recurseTimes)); } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (typeof value === 'function') { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (typeof value === 'function') { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { switch (typeof value) { case 'undefined': return ctx.stylize('undefined', 'undefined'); case 'string': var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); case 'number': return ctx.stylize('' + value, 'number'); case 'boolean': return ctx.stylize('' + value, 'boolean'); } // For some reason typeof null is "object", so special case here. if (value === null) { return ctx.stylize('null', 'null'); } } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (recurseTimes === null) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (typeof name === 'undefined') { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); } exports.isArray = isArray; function isRegExp(re) { return typeof re === 'object' && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; function isDate(d) { return typeof d === 'object' && objectToString(d) === '[object Date]'; } exports.isDate = isDate; function isError(e) { return typeof e === 'object' && objectToString(e) === '[object Error]'; } exports.isError = isError; function objectToString(o) { return Object.prototype.toString.call(o); } exports.p = exports.deprecate(function() { for (var i = 0, len = arguments.length; i < len; ++i) { error(exports.inspect(arguments[i])); } }, 'util.p: Use console.error() instead.'); function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } exports.log = function(msg) { exports.puts(timestamp() + ' - ' + msg.toString()); }; exports.exec = exports.deprecate(function() { return require('child_process').exec.apply(this, arguments); }, 'util.exec is now called `child_process.exec`.'); function pump(readStream, writeStream, callback) { var callbackCalled = false; function call(a, b, c) { if (callback && !callbackCalled) { callback(a, b, c); callbackCalled = true; } } readStream.addListener('data', function(chunk) { if (writeStream.write(chunk) === false) readStream.pause(); }); writeStream.addListener('drain', function() { readStream.resume(); }); readStream.addListener('end', function() { writeStream.end(); }); readStream.addListener('close', function() { call(); }); readStream.addListener('error', function(err) { writeStream.end(); call(err); }); writeStream.addListener('error', function(err) { readStream.destroy(); call(err); }); } exports.pump = exports.deprecate(pump, 'util.pump() is deprecated. Use readableStream.pipe() instead.'); /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ exports.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; exports._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || typeof add !== 'object') return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var punycode = require('punycode'); exports.parse = urlParse; exports.resolve = urlResolve; exports.resolveObject = urlResolveObject; exports.format = urlFormat; exports.Url = Url; function Url() { this.protocol = null; this.slashes = null; this.auth = null; this.host = null; this.port = null; this.hostname = null; this.hash = null; this.search = null; this.query = null; this.pathname = null; this.path = null; this.href = null; } // Reference: RFC 3986, RFC 1808, RFC 2396 // define these here so at least they only have to be // compiled once on the first module load. var protocolPattern = /^([a-z0-9.+-]+:)/i, portPattern = /:[0-9]*$/, // RFC 2396: characters reserved for delimiting URLs. // We actually just auto-escape these. delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], // RFC 2396: characters not allowed for various reasons. unwise = ['{', '}', '|', '\\', '^', '~', '`'].concat(delims), // Allowed by RFCs, but cause of XSS attacks. Always escape these. autoEscape = ['\''].concat(delims), // Characters that are never ever allowed in a hostname. // Note that any invalid chars are also handled, but these // are the ones that are *expected* to be seen, so we fast-path // them. nonHostChars = ['%', '/', '?', ';', '#'] .concat(unwise).concat(autoEscape), hostEndingChars = ['/', '?', '#'], hostnameMaxLen = 255, hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, // protocols that can allow "unsafe" and "unwise" chars. unsafeProtocol = { 'javascript': true, 'javascript:': true }, // protocols that never have a hostname. hostlessProtocol = { 'javascript': true, 'javascript:': true }, // protocols that always contain a // bit. slashedProtocol = { 'http': true, 'https': true, 'ftp': true, 'gopher': true, 'file': true, 'http:': true, 'https:': true, 'ftp:': true, 'gopher:': true, 'file:': true }, querystring = require('querystring'); function urlParse(url, parseQueryString, slashesDenoteHost) { if (url && typeof(url) === 'object' && url instanceof Url) return url; var u = new Url; u.parse(url, parseQueryString, slashesDenoteHost); return u; } Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { if (typeof url !== 'string') { throw new TypeError("Parameter 'url' must be a string, not " + typeof url); } var rest = url; // trim before proceeding. // This is to support parse stuff like " http://foo.com \n" rest = rest.trim(); var proto = protocolPattern.exec(rest); if (proto) { proto = proto[0]; var lowerProto = proto.toLowerCase(); this.protocol = lowerProto; rest = rest.substr(proto.length); } // figure out if it's got a host // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { var slashes = rest.substr(0, 2) === '//'; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.substr(2); this.slashes = true; } } if (!hostlessProtocol[proto] && (slashes || (proto && !slashedProtocol[proto]))) { // there's a hostname. // the first instance of /, ?, ;, or # ends the host. // // If there is an @ in the hostname, then non-host chars *are* allowed // to the left of the last @ sign, unless some host-ending character // comes *before* the @-sign. // URLs are obnoxious. // // ex: // http://a@b@c/ => user:a@b host:c // http://a@b?@c => user:a host:c path:/?@c // v0.12 TODO(isaacs): This is not quite how Chrome does things. // Review our test case against browsers more comprehensively. // find the first instance of any hostEndingChars var hostEnd = -1; for (var i = 0; i < hostEndingChars.length; i++) { var hec = rest.indexOf(hostEndingChars[i]); if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec; } // at this point, either we have an explicit point where the // auth portion cannot go past, or the last @ char is the decider. var auth, atSign; if (hostEnd === -1) { // atSign can be anywhere. atSign = rest.lastIndexOf('@'); } else { // atSign must be in auth portion. // http://a@b/c@d => host:b auth:a path:/c@d atSign = rest.lastIndexOf('@', hostEnd); } // Now we have a portion which is definitely the auth. // Pull that off. if (atSign !== -1) { auth = rest.slice(0, atSign); rest = rest.slice(atSign + 1); this.auth = decodeURIComponent(auth); } // the host is the remaining to the left of the first non-host char hostEnd = -1; for (var i = 0; i < nonHostChars.length; i++) { var hec = rest.indexOf(nonHostChars[i]); if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec; } // if we still have not hit it, then the entire thing is a host. if (hostEnd === -1) hostEnd = rest.length; this.host = rest.slice(0, hostEnd); rest = rest.slice(hostEnd); // pull out port. this.parseHost(); // we've indicated that there is a hostname, // so even if it's empty, it has to be present. this.hostname = this.hostname || ''; // if hostname begins with [ and ends with ] // assume that it's an IPv6 address. var ipv6Hostname = this.hostname[0] === '[' && this.hostname[this.hostname.length - 1] === ']'; // validate a little. if (!ipv6Hostname) { var hostparts = this.hostname.split(/\./); for (var i = 0, l = hostparts.length; i < l; i++) { var part = hostparts[i]; if (!part) continue; if (!part.match(hostnamePartPattern)) { var newpart = ''; for (var j = 0, k = part.length; j < k; j++) { if (part.charCodeAt(j) > 127) { // we replace non-ASCII char with a temporary placeholder // we need this to make sure size of hostname is not // broken by replacing non-ASCII by nothing newpart += 'x'; } else { newpart += part[j]; } } // we test again with ASCII char only if (!newpart.match(hostnamePartPattern)) { var validParts = hostparts.slice(0, i); var notHost = hostparts.slice(i + 1); var bit = part.match(hostnamePartStart); if (bit) { validParts.push(bit[1]); notHost.unshift(bit[2]); } if (notHost.length) { rest = '/' + notHost.join('.') + rest; } this.hostname = validParts.join('.'); break; } } } } if (this.hostname.length > hostnameMaxLen) { this.hostname = ''; } else { // hostnames are always lower case. this.hostname = this.hostname.toLowerCase(); } if (!ipv6Hostname) { // IDNA Support: Returns a puny coded representation of "domain". // It only converts the part of the domain name that // has non ASCII characters. I.e. it dosent matter if // you call it with a domain that already is in ASCII. var domainArray = this.hostname.split('.'); var newOut = []; for (var i = 0; i < domainArray.length; ++i) { var s = domainArray[i]; newOut.push(s.match(/[^A-Za-z0-9_-]/) ? 'xn--' + punycode.encode(s) : s); } this.hostname = newOut.join('.'); } var p = this.port ? ':' + this.port : ''; var h = this.hostname || ''; this.host = h + p; this.href += this.host; // strip [ and ] from the hostname // the host field still retains them, though if (ipv6Hostname) { this.hostname = this.hostname.substr(1, this.hostname.length - 2); if (rest[0] !== '/') { rest = '/' + rest; } } } // now rest is set to the post-host stuff. // chop off any delim chars. if (!unsafeProtocol[lowerProto]) { // First, make 100% sure that any "autoEscape" chars get // escaped, even if encodeURIComponent doesn't think they // need to be. for (var i = 0, l = autoEscape.length; i < l; i++) { var ae = autoEscape[i]; var esc = encodeURIComponent(ae); if (esc === ae) { esc = escape(ae); } rest = rest.split(ae).join(esc); } } // chop off from the tail first. var hash = rest.indexOf('#'); if (hash !== -1) { // got a fragment string. this.hash = rest.substr(hash); rest = rest.slice(0, hash); } var qm = rest.indexOf('?'); if (qm !== -1) { this.search = rest.substr(qm); this.query = rest.substr(qm + 1); if (parseQueryString) { this.query = querystring.parse(this.query); } rest = rest.slice(0, qm); } else if (parseQueryString) { // no query string, but parseQueryString still requested this.search = ''; this.query = {}; } if (rest) this.pathname = rest; if (slashedProtocol[proto] && this.hostname && !this.pathname) { this.pathname = '/'; } //to support http.request if (this.pathname || this.search) { var p = this.pathname || ''; var s = this.search || ''; this.path = p + s; } // finally, reconstruct the href based on what has been validated. this.href = this.format(); return this; }; // format a parsed object into a url string function urlFormat(obj) { // ensure it's an object, and not a string url. // If it's an obj, this is a no-op. // this way, you can call url_format() on strings // to clean up potentially wonky urls. if (typeof(obj) === 'string') obj = urlParse(obj); if (!(obj instanceof Url)) return Url.prototype.format.call(obj); return obj.format(); } Url.prototype.format = function() { var auth = this.auth || ''; if (auth) { auth = encodeURIComponent(auth); auth = auth.replace(/%3A/i, ':'); auth += '@'; } var protocol = this.protocol || '', pathname = this.pathname || '', hash = this.hash || '', host = false, query = ''; if (this.host) { host = auth + this.host; } else if (this.hostname) { host = auth + (this.hostname.indexOf(':') === -1 ? this.hostname : '[' + this.hostname + ']'); if (this.port) { host += ':' + this.port; } } if (this.query && typeof this.query === 'object' && Object.keys(this.query).length) { query = querystring.stringify(this.query); } var search = this.search || (query && ('?' + query)) || ''; if (protocol && protocol.substr(-1) !== ':') protocol += ':'; // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. // unless they had them to begin with. if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== false) { host = '//' + (host || ''); if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; } else if (!host) { host = ''; } if (hash && hash.charAt(0) !== '#') hash = '#' + hash; if (search && search.charAt(0) !== '?') search = '?' + search; pathname = pathname.replace(/[?#]/g, function(match) { return encodeURIComponent(match); }); search = search.replace('#', '%23'); return protocol + host + pathname + search + hash; }; function urlResolve(source, relative) { return urlParse(source, false, true).resolve(relative); } Url.prototype.resolve = function(relative) { return this.resolveObject(urlParse(relative, false, true)).format(); }; function urlResolveObject(source, relative) { if (!source) return relative; return urlParse(source, false, true).resolveObject(relative); } Url.prototype.resolveObject = function(relative) { if (typeof relative === 'string') { var rel = new Url(); rel.parse(relative, false, true); relative = rel; } var result = new Url(); Object.keys(this).forEach(function(k) { result[k] = this[k]; }, this); // hash is always overridden, no matter what. // even href="" will remove it. result.hash = relative.hash; // if the relative url is empty, then there's nothing left to do here. if (relative.href === '') { result.href = result.format(); return result; } // hrefs like //foo/bar always cut to the protocol. if (relative.slashes && !relative.protocol) { // take everything except the protocol from relative Object.keys(relative).forEach(function(k) { if (k !== 'protocol') result[k] = relative[k]; }); //urlParse appends trailing / to urls like http://www.example.com if (slashedProtocol[result.protocol] && result.hostname && !result.pathname) { result.path = result.pathname = '/'; } result.href = result.format(); return result; } if (relative.protocol && relative.protocol !== result.protocol) { // if it's a known url protocol, then changing // the protocol does weird things // first, if it's not file:, then we MUST have a host, // and if there was a path // to begin with, then we MUST have a path. // if it is file:, then the host is dropped, // because that's known to be hostless. // anything else is assumed to be absolute. if (!slashedProtocol[relative.protocol]) { Object.keys(relative).forEach(function(k) { result[k] = relative[k]; }); result.href = result.format(); return result; } result.protocol = relative.protocol; if (!relative.host && !hostlessProtocol[relative.protocol]) { var relPath = (relative.pathname || '').split('/'); while (relPath.length && !(relative.host = relPath.shift())); if (!relative.host) relative.host = ''; if (!relative.hostname) relative.hostname = ''; if (relPath[0] !== '') relPath.unshift(''); if (relPath.length < 2) relPath.unshift(''); result.pathname = relPath.join('/'); } else { result.pathname = relative.pathname; } result.search = relative.search; result.query = relative.query; result.host = relative.host || ''; result.auth = relative.auth; result.hostname = relative.hostname || relative.host; result.port = relative.port; // to support http.request if (result.pathname || result.search) { var p = result.pathname || ''; var s = result.search || ''; result.path = p + s; } result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; } var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), isRelAbs = ( relative.host || relative.pathname && relative.pathname.charAt(0) === '/' ), mustEndAbs = (isRelAbs || isSourceAbs || (result.host && relative.pathname)), removeAllDots = mustEndAbs, srcPath = result.pathname && result.pathname.split('/') || [], relPath = relative.pathname && relative.pathname.split('/') || [], psychotic = result.protocol && !slashedProtocol[result.protocol]; // if the url is a non-slashed url, then relative // links like ../.. should be able // to crawl up to the hostname, as well. This is strange. // result.protocol has already been set by now. // Later on, put the first path part into the host field. if (psychotic) { result.hostname = ''; result.port = null; if (result.host) { if (srcPath[0] === '') srcPath[0] = result.host; else srcPath.unshift(result.host); } result.host = ''; if (relative.protocol) { relative.hostname = null; relative.port = null; if (relative.host) { if (relPath[0] === '') relPath[0] = relative.host; else relPath.unshift(relative.host); } relative.host = null; } mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); } if (isRelAbs) { // it's absolute. result.host = (relative.host || relative.host === '') ? relative.host : result.host; result.hostname = (relative.hostname || relative.hostname === '') ? relative.hostname : result.hostname; result.search = relative.search; result.query = relative.query; srcPath = relPath; // fall through to the dot-handling below. } else if (relPath.length) { // it's relative // throw away the existing file, and take the new path instead. if (!srcPath) srcPath = []; srcPath.pop(); srcPath = srcPath.concat(relPath); result.search = relative.search; result.query = relative.query; } else if (relative.search !== null && relative.search !== undefined) { // just pull out the search. // like href='?foo'. // Put this after the other two cases because it simplifies the booleans if (psychotic) { result.hostname = result.host = srcPath.shift(); //occationaly the auth can get stuck only in host //this especialy happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } result.search = relative.search; result.query = relative.query; //to support http.request if (result.pathname !== null || result.search !== null) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.href = result.format(); return result; } if (!srcPath.length) { // no path at all. easy. // we've already handled the other stuff above. result.pathname = null; //to support http.request if (result.search) { result.path = '/' + result.search; } else { result.path = null; } result.href = result.format(); return result; } // if a url ENDs in . or .., then it must get a trailing slash. // however, if it ends in anything else non-slashy, // then it must NOT get a trailing slash. var last = srcPath.slice(-1)[0]; var hasTrailingSlash = ( (result.host || relative.host) && (last === '.' || last === '..') || last === ''); // strip single dots, resolve double dots to parent dir // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = srcPath.length; i >= 0; i--) { last = srcPath[i]; if (last == '.') { srcPath.splice(i, 1); } else if (last === '..') { srcPath.splice(i, 1); up++; } else if (up) { srcPath.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (!mustEndAbs && !removeAllDots) { for (; up--; up) { srcPath.unshift('..'); } } if (mustEndAbs && srcPath[0] !== '' && (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { srcPath.unshift(''); } if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { srcPath.push(''); } var isAbsolute = srcPath[0] === '' || (srcPath[0] && srcPath[0].charAt(0) === '/'); // put the host back if (psychotic) { result.hostname = result.host = isAbsolute ? '' : srcPath.length ? srcPath.shift() : ''; //occationaly the auth can get stuck only in host //this especialy happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } mustEndAbs = mustEndAbs || (result.host && srcPath.length); if (mustEndAbs && !isAbsolute) { srcPath.unshift(''); } if (!srcPath.length) { result.pathname = null; result.path = null; } else { result.pathname = srcPath.join('/'); } //to support request.http if (result.pathname !== null || result.search !== null) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.auth = relative.auth || result.auth; result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; }; Url.prototype.parseHost = function() { var host = this.host; var port = portPattern.exec(host); if (port) { port = port[0]; if (port !== ':') { this.port = port.substr(1); } host = host.substr(0, host.length - port.length); } if (host) this.hostname = host; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var inherits = require('util').inherits; var net = require('net'); var TTY = process.binding('tty_wrap').TTY; var isTTY = process.binding('tty_wrap').isTTY; var util = require('util'); exports.isatty = function(fd) { return isTTY(fd); }; // backwards-compat exports.setRawMode = util.deprecate(function(flag) { if (!process.stdin.isTTY) { throw new Error('can\'t set raw mode on non-tty'); } process.stdin.setRawMode(flag); }, 'tty.setRawMode: Use `process.stdin.setRawMode()` instead.'); function ReadStream(fd, options) { if (!(this instanceof ReadStream)) return new ReadStream(fd, options); options = util._extend({ highWaterMark: 0, readable: true, writable: false, handle: new TTY(fd, true) }, options); net.Socket.call(this, options); this.isRaw = false; this.isTTY = true; } inherits(ReadStream, net.Socket); exports.ReadStream = ReadStream; ReadStream.prototype.setRawMode = function(flag) { flag = !!flag; this._handle.setRawMode(flag); this.isRaw = flag; }; function WriteStream(fd) { if (!(this instanceof WriteStream)) return new WriteStream(fd); net.Socket.call(this, { handle: new TTY(fd, false), readable: false, writable: true }); var winSize = this._handle.getWindowSize(); if (winSize) { this.columns = winSize[0]; this.rows = winSize[1]; } } inherits(WriteStream, net.Socket); exports.WriteStream = WriteStream; WriteStream.prototype.isTTY = true; WriteStream.prototype._refreshSize = function() { var oldCols = this.columns; var oldRows = this.rows; var winSize = this._handle.getWindowSize(); if (!winSize) { this.emit('error', errnoException(process._errno, 'getWindowSize')); return; } var newCols = winSize[0]; var newRows = winSize[1]; if (oldCols !== newCols || oldRows !== newRows) { this.columns = newCols; this.rows = newRows; this.emit('resize'); } }; // backwards-compat WriteStream.prototype.cursorTo = function(x, y) { require('readline').cursorTo(this, x, y); }; WriteStream.prototype.moveCursor = function(dx, dy) { require('readline').moveCursor(this, dx, dy); }; WriteStream.prototype.clearLine = function(dir) { require('readline').clearLine(this, dir); }; WriteStream.prototype.clearScreenDown = function() { require('readline').clearScreenDown(this); }; WriteStream.prototype.getWindowSize = function() { return [this.columns, this.rows]; }; // TODO share with net_uv and others function errnoException(errorno, syscall) { var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var crypto = require('crypto'); var util = require('util'); var net = require('net'); var url = require('url'); var events = require('events'); var stream = require('stream'); var assert = require('assert').ok; var constants = require('constants'); var DEFAULT_CIPHERS = 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' + // TLS 1.2 'RC4:HIGH:!MD5:!aNULL:!EDH'; // TLS 1.0 // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more // renegotations are seen. The settings are applied to all remote client // connections. exports.CLIENT_RENEG_LIMIT = 3; exports.CLIENT_RENEG_WINDOW = 600; exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024; exports.getCiphers = function() { var names = process.binding('crypto').getSSLCiphers(); // Drop all-caps names in favor of their lowercase aliases, var ctx = {}; names.forEach(function(name) { if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); ctx[name] = true; }); return Object.getOwnPropertyNames(ctx).sort(); }; var debug; if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) { debug = function(a) { console.error('TLS:', a); }; } else { debug = function() { }; } var Connection = null; try { Connection = process.binding('crypto').Connection; } catch (e) { throw new Error('node.js not compiled with openssl crypto support.'); } // Convert protocols array into valid OpenSSL protocols list // ("\x06spdy/2\x08http/1.1\x08http/1.0") function convertNPNProtocols(NPNProtocols, out) { // If NPNProtocols is Array - translate it into buffer if (Array.isArray(NPNProtocols)) { var buff = new Buffer(NPNProtocols.reduce(function(p, c) { return p + 1 + Buffer.byteLength(c); }, 0)); NPNProtocols.reduce(function(offset, c) { var clen = Buffer.byteLength(c); buff[offset] = clen; buff.write(c, offset + 1); return offset + 1 + clen; }, 0); NPNProtocols = buff; } // If it's already a Buffer - store it if (Buffer.isBuffer(NPNProtocols)) { out.NPNProtocols = NPNProtocols; } } function checkServerIdentity(host, cert) { // Create regexp to much hostnames function regexpify(host, wildcards) { // Add trailing dot (make hostnames uniform) if (!/\.$/.test(host)) host += '.'; // The same applies to hostname with more than one wildcard, // if hostname has wildcard when wildcards are not allowed, // or if there are less than two dots after wildcard (i.e. *.com or *d.com) // // also // // "The client SHOULD NOT attempt to match a presented identifier in // which the wildcard character comprises a label other than the // left-most label (e.g., do not match bar.*.example.net)." // RFC6125 if (!wildcards && /\*/.test(host) || /[\.\*].*\*/.test(host) || /\*/.test(host) && !/\*.*\..+\..+/.test(host)) { return /$./; } // Replace wildcard chars with regexp's wildcard and // escape all characters that have special meaning in regexps // (i.e. '.', '[', '{', '*', and others) var re = host.replace( /\*([a-z0-9\\-_\.])|[\.,\-\\\^\$+?*\[\]\(\):!\|{}]/g, function(all, sub) { if (sub) return '[a-z0-9\\-_]*' + (sub === '-' ? '\\-' : sub); return '\\' + all; }); return new RegExp('^' + re + '$', 'i'); } var dnsNames = [], uriNames = [], ips = [], matchCN = true, valid = false; // There're several names to perform check against: // CN and altnames in certificate extension // (DNS names, IP addresses, and URIs) // // Walk through altnames and generate lists of those names if (cert.subjectaltname) { cert.subjectaltname.split(/, /g).forEach(function(altname) { if (/^DNS:/.test(altname)) { dnsNames.push(altname.slice(4)); } else if (/^IP Address:/.test(altname)) { ips.push(altname.slice(11)); } else if (/^URI:/.test(altname)) { var uri = url.parse(altname.slice(4)); if (uri) uriNames.push(uri.hostname); } }); } // If hostname is an IP address, it should be present in the list of IP // addresses. if (net.isIP(host)) { valid = ips.some(function(ip) { return ip === host; }); } else { // Transform hostname to canonical form if (!/\.$/.test(host)) host += '.'; // Otherwise check all DNS/URI records from certificate // (with allowed wildcards) dnsNames = dnsNames.map(function(name) { return regexpify(name, true); }); // Wildcards ain't allowed in URI names uriNames = uriNames.map(function(name) { return regexpify(name, false); }); dnsNames = dnsNames.concat(uriNames); if (dnsNames.length > 0) matchCN = false; // Match against Common Name (CN) only if no supported identifiers are // present. // // "As noted, a client MUST NOT seek a match for a reference identifier // of CN-ID if the presented identifiers include a DNS-ID, SRV-ID, // URI-ID, or any application-specific identifier types supported by the // client." // RFC6125 if (matchCN) { var commonNames = cert.subject.CN; if (Array.isArray(commonNames)) { for (var i = 0, k = commonNames.length; i < k; ++i) { dnsNames.push(regexpify(commonNames[i], true)); } } else { dnsNames.push(regexpify(commonNames, true)); } } valid = dnsNames.some(function(re) { return re.test(host); }); } return valid; } exports.checkServerIdentity = checkServerIdentity; function SlabBuffer() { this.create(); } SlabBuffer.prototype.create = function create() { this.isFull = false; this.pool = new Buffer(exports.SLAB_BUFFER_SIZE); this.offset = 0; this.remaining = this.pool.length; }; SlabBuffer.prototype.use = function use(context, fn, size) { if (this.remaining === 0) { this.isFull = true; return 0; } var actualSize = this.remaining; if (size !== null) actualSize = Math.min(size, actualSize); var bytes = fn.call(context, this.pool, this.offset, actualSize); if (bytes > 0) { this.offset += bytes; this.remaining -= bytes; } assert(this.remaining >= 0); return bytes; }; var slabBuffer = null; // Base class of both CleartextStream and EncryptedStream function CryptoStream(pair, options) { stream.Duplex.call(this, options); this.pair = pair; this._pending = null; this._pendingEncoding = ''; this._pendingCallback = null; this._doneFlag = false; this._retryAfterPartial = false; this._halfRead = false; this._sslOutCb = null; this._resumingSession = false; this._reading = true; this._destroyed = false; this._ended = false; this._finished = false; this._opposite = null; if (slabBuffer === null) slabBuffer = new SlabBuffer(); this._buffer = slabBuffer; this.once('finish', onCryptoStreamFinish); // net.Socket calls .onend too this.once('end', onCryptoStreamEnd); } util.inherits(CryptoStream, stream.Duplex); function onCryptoStreamFinish() { this._finished = true; if (this === this.pair.cleartext) { debug('cleartext.onfinish'); if (this.pair.ssl) { // Generate close notify // NOTE: first call checks if client has sent us shutdown, // second call enqueues shutdown into the BIO. if (this.pair.ssl.shutdown() !== 1) { if (this.pair.ssl && this.pair.ssl.error) return this.pair.error(); this.pair.ssl.shutdown(); } if (this.pair.ssl && this.pair.ssl.error) return this.pair.error(); } } else { debug('encrypted.onfinish'); } // Try to read just to get sure that we won't miss EOF if (this._opposite.readable) this._opposite.read(0); if (this._opposite._ended) { this._done(); // No half-close, sorry if (this === this.pair.cleartext) this._opposite._done(); } } function onCryptoStreamEnd() { this._ended = true; if (this === this.pair.cleartext) { debug('cleartext.onend'); } else { debug('encrypted.onend'); } if (this.onend) this.onend(); } // NOTE: Called once `this._opposite` is set. CryptoStream.prototype.init = function init() { var self = this; this._opposite.on('sslOutEnd', function() { if (self._sslOutCb) { var cb = self._sslOutCb; self._sslOutCb = null; cb(null); } }); }; CryptoStream.prototype._write = function write(data, encoding, cb) { assert(this._pending === null); // Black-hole data if (!this.pair.ssl) return cb(null); // When resuming session don't accept any new data. // And do not put too much data into openssl, before writing it from encrypted // side. // // TODO(indutny): Remove magic number, use watermark based limits if (!this._resumingSession && this._opposite._internallyPendingBytes() < 128 * 1024) { // Write current buffer now var written; if (this === this.pair.cleartext) { debug('cleartext.write called with ' + data.length + ' bytes'); written = this.pair.ssl.clearIn(data, 0, data.length); } else { debug('encrypted.write called with ' + data.length + ' bytes'); written = this.pair.ssl.encIn(data, 0, data.length); } // Handle and report errors if (this.pair.ssl && this.pair.ssl.error) { return cb(this.pair.error(true)); } // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); // Cycle encrypted data if (this.pair.encrypted._internallyPendingBytes()) this.pair.encrypted.read(0); // Get NPN and Server name when ready this.pair.maybeInitFinished(); // Whole buffer was written if (written === data.length) { if (this === this.pair.cleartext) { debug('cleartext.write succeed with ' + written + ' bytes'); } else { debug('encrypted.write succeed with ' + written + ' bytes'); } // Invoke callback only when all data read from opposite stream if (this._opposite._halfRead) { assert(this._sslOutCb === null); this._sslOutCb = cb; } else { cb(null); } return; } else if (written !== 0 && written !== -1) { assert(!this._retryAfterPartial); this._retryAfterPartial = true; this._write(data.slice(written), encoding, cb); this._retryAfterPartial = false; return; } } else { debug('cleartext.write queue is full'); // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); } // No write has happened this._pending = data; this._pendingEncoding = encoding; this._pendingCallback = cb; if (this === this.pair.cleartext) { debug('cleartext.write queued with ' + data.length + ' bytes'); } else { debug('encrypted.write queued with ' + data.length + ' bytes'); } }; CryptoStream.prototype._writePending = function writePending() { var data = this._pending, encoding = this._pendingEncoding, cb = this._pendingCallback; this._pending = null; this._pendingEncoding = ''; this._pendingCallback = null; this._write(data, encoding, cb); }; CryptoStream.prototype._read = function read(size) { // XXX: EOF?! if (!this.pair.ssl) return this.push(null); // Wait for session to be resumed // Mark that we're done reading, but don't provide data or EOF if (this._resumingSession || !this._reading) return this.push(''); var out; if (this === this.pair.cleartext) { debug('cleartext.read called with ' + size + ' bytes'); out = this.pair.ssl.clearOut; } else { debug('encrypted.read called with ' + size + ' bytes'); out = this.pair.ssl.encOut; } var bytesRead = 0, start = this._buffer.offset; do { var read = this._buffer.use(this.pair.ssl, out, size); if (read > 0) { bytesRead += read; size -= read; } // Handle and report errors if (this.pair.ssl && this.pair.ssl.error) { this.pair.error(); break; } // Get NPN and Server name when ready this.pair.maybeInitFinished(); } while (read > 0 && !this._buffer.isFull && bytesRead < size); // Create new buffer if previous was filled up var pool = this._buffer.pool; if (this._buffer.isFull) this._buffer.create(); assert(bytesRead >= 0); if (this === this.pair.cleartext) { debug('cleartext.read succeed with ' + bytesRead + ' bytes'); } else { debug('encrypted.read succeed with ' + bytesRead + ' bytes'); } // Try writing pending data if (this._pending !== null) this._writePending(); if (this._opposite._pending !== null) this._opposite._writePending(); if (bytesRead === 0) { // EOF when cleartext has finished and we have nothing to read if (this._opposite._finished && this._internallyPendingBytes() === 0) { // Perform graceful shutdown this._done(); // No half-open, sorry! if (this === this.pair.cleartext) this._opposite._done(); // EOF this.push(null); } else { // Bail out this.push(''); } } else { // Give them requested data if (this.ondata) { var self = this; this.ondata(pool, start, start + bytesRead); // Consume data automatically // simple/test-https-drain fails without it process.nextTick(function() { self.read(bytesRead); }); } this.push(pool.slice(start, start + bytesRead)); } // Let users know that we've some internal data to read var halfRead = this._internallyPendingBytes() !== 0; // Smart check to avoid invoking 'sslOutEnd' in the most of the cases if (this._halfRead !== halfRead) { this._halfRead = halfRead; // Notify listeners about internal data end if (!halfRead) { if (this === this.pair.cleartext) { debug('cleartext.sslOutEnd'); } else { debug('encrypted.sslOutEnd'); } this.emit('sslOutEnd'); } } }; CryptoStream.prototype.setTimeout = function(timeout, callback) { if (this.socket) this.socket.setTimeout(timeout, callback); }; CryptoStream.prototype.setNoDelay = function(noDelay) { if (this.socket) this.socket.setNoDelay(noDelay); }; CryptoStream.prototype.setKeepAlive = function(enable, initialDelay) { if (this.socket) this.socket.setKeepAlive(enable, initialDelay); }; CryptoStream.prototype.__defineGetter__('bytesWritten', function() { return this.socket ? this.socket.bytesWritten : 0; }); // Example: // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org function parseCertString(s) { var out = {}; var parts = s.split('\n'); for (var i = 0, len = parts.length; i < len; i++) { var sepIndex = parts[i].indexOf('='); if (sepIndex > 0) { var key = parts[i].slice(0, sepIndex); var value = parts[i].slice(sepIndex + 1); if (key in out) { if (!Array.isArray(out[key])) { out[key] = [out[key]]; } out[key].push(value); } else { out[key] = value; } } } return out; } CryptoStream.prototype.getPeerCertificate = function() { if (this.pair.ssl) { var c = this.pair.ssl.getPeerCertificate(); if (c) { if (c.issuer) c.issuer = parseCertString(c.issuer); if (c.subject) c.subject = parseCertString(c.subject); return c; } } return null; }; CryptoStream.prototype.getSession = function() { if (this.pair.ssl) { return this.pair.ssl.getSession(); } return null; }; CryptoStream.prototype.isSessionReused = function() { if (this.pair.ssl) { return this.pair.ssl.isSessionReused(); } return null; }; CryptoStream.prototype.getCipher = function(err) { if (this.pair.ssl) { return this.pair.ssl.getCurrentCipher(); } else { return null; } }; CryptoStream.prototype.end = function(chunk, encoding) { if (this === this.pair.cleartext) { debug('cleartext.end'); } else { debug('encrypted.end'); } // Write pending data first if (this._pending !== null) this._writePending(); this.writable = false; stream.Duplex.prototype.end.call(this, chunk, encoding); }; CryptoStream.prototype.destroySoon = function(err) { if (this === this.pair.cleartext) { debug('cleartext.destroySoon'); } else { debug('encrypted.destroySoon'); } if (this.writable) this.end(); if (this._writableState.finished && this._opposite._ended) { this.destroy(); } else { // Wait for both `finish` and `end` events to ensure that all data that // was written on this side was read from the other side. var self = this; var waiting = 2; function finish() { if (--waiting === 0) self.destroy(); } this._opposite.once('end', finish); this.once('finish', finish); } }; CryptoStream.prototype.destroy = function(err) { if (this._destroyed) return; this._destroyed = true; this.readable = this.writable = false; // Destroy both ends if (this === this.pair.cleartext) { debug('cleartext.destroy'); } else { debug('encrypted.destroy'); } this._opposite.destroy(); var self = this; process.nextTick(function() { // Force EOF self.push(null); // Emit 'close' event self.emit('close', err ? true : false); }); }; CryptoStream.prototype._done = function() { this._doneFlag = true; if (this === this.pair.encrypted && !this.pair._secureEstablished) return this.pair.error(); if (this.pair.cleartext._doneFlag && this.pair.encrypted._doneFlag && !this.pair._doneFlag) { // If both streams are done: this.pair.destroy(); } }; // readyState is deprecated. Don't use it. Object.defineProperty(CryptoStream.prototype, 'readyState', { get: function() { if (this._connecting) { return 'opening'; } else if (this.readable && this.writable) { return 'open'; } else if (this.readable && !this.writable) { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; } else { return 'closed'; } } }); function CleartextStream(pair, options) { CryptoStream.call(this, pair, options); // This is a fake kludge to support how the http impl sits // on top of net Sockets var self = this; this._handle = { readStop: function() { self._reading = false; }, readStart: function() { if (self._reading && self._readableState.length > 0) return; self._reading = true; self.read(0); if (self._opposite.readable) self._opposite.read(0); } }; } util.inherits(CleartextStream, CryptoStream); CleartextStream.prototype._internallyPendingBytes = function() { if (this.pair.ssl) { return this.pair.ssl.clearPending(); } else { return 0; } }; CleartextStream.prototype.address = function() { return this.socket && this.socket.address(); }; CleartextStream.prototype.__defineGetter__('remoteAddress', function() { return this.socket && this.socket.remoteAddress; }); CleartextStream.prototype.__defineGetter__('remotePort', function() { return this.socket && this.socket.remotePort; }); function EncryptedStream(pair, options) { CryptoStream.call(this, pair, options); } util.inherits(EncryptedStream, CryptoStream); EncryptedStream.prototype._internallyPendingBytes = function() { if (this.pair.ssl) { return this.pair.ssl.encPending(); } else { return 0; } }; function onhandshakestart() { debug('onhandshakestart'); var self = this; var ssl = self.ssl; var now = Date.now(); assert(now >= ssl.lastHandshakeTime); if ((now - ssl.lastHandshakeTime) >= exports.CLIENT_RENEG_WINDOW * 1000) { ssl.handshakes = 0; } var first = (ssl.lastHandshakeTime === 0); ssl.lastHandshakeTime = now; if (first) return; if (++ssl.handshakes > exports.CLIENT_RENEG_LIMIT) { // Defer the error event to the next tick. We're being called from OpenSSL's // state machine and OpenSSL is not re-entrant. We cannot allow the user's // callback to destroy the connection right now, it would crash and burn. setImmediate(function() { var err = new Error('TLS session renegotiation attack detected.'); if (self.cleartext) self.cleartext.emit('error', err); }); } } function onhandshakedone() { // for future use debug('onhandshakedone'); } function onclienthello(hello) { var self = this, once = false; this._resumingSession = true; function callback(err, session) { if (once) return; once = true; if (err) return self.socket.destroy(err); self.ssl.loadSession(session); // Cycle data self._resumingSession = false; self.cleartext.read(0); self.encrypted.read(0); } if (hello.sessionId.length <= 0 || !this.server || !this.server.emit('resumeSession', hello.sessionId, callback)) { callback(null, null); } } function onnewsession(key, session) { if (!this.server) return; this.server.emit('newSession', key, session); } /** * Provides a pair of streams to do encrypted communication. */ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized, options) { if (!(this instanceof SecurePair)) { return new SecurePair(credentials, isServer, requestCert, rejectUnauthorized, options); } var self = this; options || (options = {}); events.EventEmitter.call(this); this.server = options.server; this._secureEstablished = false; this._isServer = isServer ? true : false; this._encWriteState = true; this._clearWriteState = true; this._doneFlag = false; this._destroying = false; if (!credentials) { this.credentials = crypto.createCredentials(); } else { this.credentials = credentials; } if (!this._isServer) { // For clients, we will always have either a given ca list or be using // default one requestCert = true; } this._rejectUnauthorized = rejectUnauthorized ? true : false; this._requestCert = requestCert ? true : false; this.ssl = new Connection(this.credentials.context, this._isServer ? true : false, this._isServer ? this._requestCert : options.servername, this._rejectUnauthorized); if (this._isServer) { this.ssl.onhandshakestart = onhandshakestart.bind(this); this.ssl.onhandshakedone = onhandshakedone.bind(this); this.ssl.onclienthello = onclienthello.bind(this); this.ssl.onnewsession = onnewsession.bind(this); this.ssl.lastHandshakeTime = 0; this.ssl.handshakes = 0; } if (process.features.tls_sni) { if (this._isServer && options.SNICallback) { this.ssl.setSNICallback(options.SNICallback); } this.servername = null; } if (process.features.tls_npn && options.NPNProtocols) { this.ssl.setNPNProtocols(options.NPNProtocols); this.npnProtocol = null; } /* Acts as a r/w stream to the cleartext side of the stream. */ this.cleartext = new CleartextStream(this, options.cleartext); /* Acts as a r/w stream to the encrypted side of the stream. */ this.encrypted = new EncryptedStream(this, options.encrypted); /* Let streams know about each other */ this.cleartext._opposite = this.encrypted; this.encrypted._opposite = this.cleartext; this.cleartext.init(); this.encrypted.init(); process.nextTick(function() { /* The Connection may be destroyed by an abort call */ if (self.ssl) { self.ssl.start(); } }); } util.inherits(SecurePair, events.EventEmitter); exports.createSecurePair = function(credentials, isServer, requestCert, rejectUnauthorized) { var pair = new SecurePair(credentials, isServer, requestCert, rejectUnauthorized); return pair; }; SecurePair.prototype.maybeInitFinished = function() { if (this.ssl && !this._secureEstablished && this.ssl.isInitFinished()) { if (process.features.tls_npn) { this.npnProtocol = this.ssl.getNegotiatedProtocol(); } if (process.features.tls_sni) { this.servername = this.ssl.getServername(); } this._secureEstablished = true; debug('secure established'); this.emit('secure'); } }; SecurePair.prototype.destroy = function() { if (this._destroying) return; if (!this._doneFlag) { debug('SecurePair.destroy'); this._destroying = true; // SecurePair should be destroyed only after it's streams this.cleartext.destroy(); this.encrypted.destroy(); this._doneFlag = true; this.ssl.error = null; this.ssl.close(); this.ssl = null; } }; SecurePair.prototype.error = function(returnOnly) { var err = this.ssl.error; this.ssl.error = null; if (!this._secureEstablished) { // Emit ECONNRESET instead of zero return if (!err || err.message === 'ZERO_RETURN') { var connReset = new Error('socket hang up'); connReset.code = 'ECONNRESET'; connReset.sslError = err && err.message; err = connReset; } this.destroy(); if (!returnOnly) this.emit('error', err); } else if (this._isServer && this._rejectUnauthorized && /peer did not return a certificate/.test(err.message)) { // Not really an error. this.destroy(); } else { if (!returnOnly) this.cleartext.emit('error', err); } return err; }; // TODO: support anonymous (nocert) and PSK // AUTHENTICATION MODES // // There are several levels of authentication that TLS/SSL supports. // Read more about this in "man SSL_set_verify". // // 1. The server sends a certificate to the client but does not request a // cert from the client. This is common for most HTTPS servers. The browser // can verify the identity of the server, but the server does not know who // the client is. Authenticating the client is usually done over HTTP using // login boxes and cookies and stuff. // // 2. The server sends a cert to the client and requests that the client // also send it a cert. The client knows who the server is and the server is // requesting the client also identify themselves. There are several // outcomes: // // A) verifyError returns null meaning the client's certificate is signed // by one of the server's CAs. The server know's the client idenity now // and the client is authorized. // // B) For some reason the client's certificate is not acceptable - // verifyError returns a string indicating the problem. The server can // either (i) reject the client or (ii) allow the client to connect as an // unauthorized connection. // // The mode is controlled by two boolean variables. // // requestCert // If true the server requests a certificate from client connections. For // the common HTTPS case, users will want this to be false, which is what // it defaults to. // // rejectUnauthorized // If true clients whose certificates are invalid for any reason will not // be allowed to make connections. If false, they will simply be marked as // unauthorized but secure communication will continue. By default this is // true. // // // // Options: // - requestCert. Send verify request. Default to false. // - rejectUnauthorized. Boolean, default to true. // - key. string. // - cert: string. // - ca: string or array of strings. // // emit 'secureConnection' // function (cleartextStream, encryptedStream) { } // // 'cleartextStream' has the boolean property 'authorized' to determine if // it was verified by the CA. If 'authorized' is false, a property // 'authorizationError' is set on cleartextStream and has the possible // values: // // "UNABLE_TO_GET_ISSUER_CERT", "UNABLE_TO_GET_CRL", // "UNABLE_TO_DECRYPT_CERT_SIGNATURE", "UNABLE_TO_DECRYPT_CRL_SIGNATURE", // "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", "CERT_SIGNATURE_FAILURE", // "CRL_SIGNATURE_FAILURE", "CERT_NOT_YET_VALID" "CERT_HAS_EXPIRED", // "CRL_NOT_YET_VALID", "CRL_HAS_EXPIRED" "ERROR_IN_CERT_NOT_BEFORE_FIELD", // "ERROR_IN_CERT_NOT_AFTER_FIELD", "ERROR_IN_CRL_LAST_UPDATE_FIELD", // "ERROR_IN_CRL_NEXT_UPDATE_FIELD", "OUT_OF_MEM", // "DEPTH_ZERO_SELF_SIGNED_CERT", "SELF_SIGNED_CERT_IN_CHAIN", // "UNABLE_TO_GET_ISSUER_CERT_LOCALLY", "UNABLE_TO_VERIFY_LEAF_SIGNATURE", // "CERT_CHAIN_TOO_LONG", "CERT_REVOKED" "INVALID_CA", // "PATH_LENGTH_EXCEEDED", "INVALID_PURPOSE" "CERT_UNTRUSTED", // "CERT_REJECTED" // // // TODO: // cleartext.credentials (by mirroring from pair object) // cleartext.getCertificate() (by mirroring from pair.credentials.context) function Server(/* [options], listener */) { var options, listener; if (typeof arguments[0] == 'object') { options = arguments[0]; listener = arguments[1]; } else if (typeof arguments[0] == 'function') { options = {}; listener = arguments[0]; } if (!(this instanceof Server)) return new Server(options, listener); this._contexts = []; var self = this; // Handle option defaults: this.setOptions(options); if (!self.pfx && (!self.cert || !self.key)) { throw new Error('Missing PFX or certificate + private key.'); } var sharedCreds = crypto.createCredentials({ pfx: self.pfx, key: self.key, passphrase: self.passphrase, cert: self.cert, ca: self.ca, ciphers: self.ciphers || DEFAULT_CIPHERS, secureProtocol: self.secureProtocol, secureOptions: self.secureOptions, crl: self.crl, sessionIdContext: self.sessionIdContext }); var timeout = options.handshakeTimeout || (120 * 1000); if (typeof timeout !== 'number') { throw new TypeError('handshakeTimeout must be a number'); } // constructor call net.Server.call(this, function(socket) { var creds = crypto.createCredentials(null, sharedCreds.context); var pair = new SecurePair(creds, true, self.requestCert, self.rejectUnauthorized, { server: self, NPNProtocols: self.NPNProtocols, SNICallback: self.SNICallback, // Stream options cleartext: self._cleartext, encrypted: self._encrypted }); var cleartext = pipe(pair, socket); cleartext._controlReleased = false; function listener() { pair.emit('error', new Error('TLS handshake timeout')); } if (timeout > 0) { socket.setTimeout(timeout, listener); } pair.once('secure', function() { socket.setTimeout(0, listener); pair.cleartext.authorized = false; pair.cleartext.npnProtocol = pair.npnProtocol; pair.cleartext.servername = pair.servername; if (!self.requestCert) { cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } else { var verifyError = pair.ssl.verifyError(); if (verifyError) { pair.cleartext.authorizationError = verifyError.message; if (self.rejectUnauthorized) { socket.destroy(); pair.destroy(); } else { cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } } else { pair.cleartext.authorized = true; cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } } }); pair.on('error', function(err) { self.emit('clientError', err, this); }); }); if (listener) { this.on('secureConnection', listener); } } util.inherits(Server, net.Server); exports.Server = Server; exports.createServer = function(options, listener) { return new Server(options, listener); }; Server.prototype.setOptions = function(options) { if (typeof options.requestCert == 'boolean') { this.requestCert = options.requestCert; } else { this.requestCert = false; } if (typeof options.rejectUnauthorized == 'boolean') { this.rejectUnauthorized = options.rejectUnauthorized; } else { this.rejectUnauthorized = false; } if (options.pfx) this.pfx = options.pfx; if (options.key) this.key = options.key; if (options.passphrase) this.passphrase = options.passphrase; if (options.cert) this.cert = options.cert; if (options.ca) this.ca = options.ca; if (options.secureProtocol) this.secureProtocol = options.secureProtocol; if (options.crl) this.crl = options.crl; if (options.ciphers) this.ciphers = options.ciphers; var secureOptions = options.secureOptions || 0; if (options.honorCipherOrder) { secureOptions |= constants.SSL_OP_CIPHER_SERVER_PREFERENCE; } if (secureOptions) this.secureOptions = secureOptions; if (options.NPNProtocols) convertNPNProtocols(options.NPNProtocols, this); if (options.SNICallback) { this.SNICallback = options.SNICallback; } else { this.SNICallback = this.SNICallback.bind(this); } if (options.sessionIdContext) { this.sessionIdContext = options.sessionIdContext; } else if (this.requestCert) { this.sessionIdContext = crypto.createHash('md5') .update(process.argv.join(' ')) .digest('hex'); } if (options.cleartext) this.cleartext = options.cleartext; if (options.encrypted) this.encrypted = options.encrypted; }; // SNI Contexts High-Level API Server.prototype.addContext = function(servername, credentials) { if (!servername) { throw 'Servername is required parameter for Server.addContext'; } var re = new RegExp('^' + servername.replace(/([\.^$+?\-\\[\]{}])/g, '\\$1') .replace(/\*/g, '.*') + '$'); this._contexts.push([re, crypto.createCredentials(credentials).context]); }; Server.prototype.SNICallback = function(servername) { var ctx; this._contexts.some(function(elem) { if (servername.match(elem[0]) !== null) { ctx = elem[1]; return true; } }); return ctx; }; // Target API: // // var s = tls.connect({port: 8000, host: "google.com"}, function() { // if (!s.authorized) { // s.destroy(); // return; // } // // // s.socket; // // s.end("hello world\n"); // }); // // function normalizeConnectArgs(listArgs) { var args = net._normalizeConnectArgs(listArgs); var options = args[0]; var cb = args[1]; if (typeof listArgs[1] === 'object') { options = util._extend(options, listArgs[1]); } else if (typeof listArgs[2] === 'object') { options = util._extend(options, listArgs[2]); } return (cb) ? [options, cb] : [options]; } exports.connect = function(/* [port, host], options, cb */) { var args = normalizeConnectArgs(arguments); var options = args[0]; var cb = args[1]; var defaults = { rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED }; options = util._extend(defaults, options || {}); var socket = options.socket ? options.socket : new net.Stream(); var sslcontext = crypto.createCredentials(options); convertNPNProtocols(options.NPNProtocols, this); var hostname = options.servername || options.host || 'localhost', pair = new SecurePair(sslcontext, false, true, options.rejectUnauthorized === true ? true : false, { NPNProtocols: this.NPNProtocols, servername: hostname, cleartext: options.cleartext, encrypted: options.encrypted }); if (options.session) { var session = options.session; if (typeof session === 'string') session = new Buffer(session, 'binary'); pair.ssl.setSession(session); } var cleartext = pipe(pair, socket); if (cb) { cleartext.once('secureConnect', cb); } if (!options.socket) { var connect_opt = (options.path && !options.port) ? {path: options.path} : { port: options.port, host: options.host, localAddress: options.localAddress }; socket.connect(connect_opt); } pair.on('secure', function() { var verifyError = pair.ssl.verifyError(); cleartext.npnProtocol = pair.npnProtocol; // Verify that server's identity matches it's certificate's names if (!verifyError) { var validCert = checkServerIdentity(hostname, pair.cleartext.getPeerCertificate()); if (!validCert) { verifyError = new Error('Hostname/IP doesn\'t match certificate\'s ' + 'altnames'); } } if (verifyError) { cleartext.authorized = false; cleartext.authorizationError = verifyError.message; if (pair._rejectUnauthorized) { cleartext.emit('error', verifyError); pair.destroy(); } else { cleartext.emit('secureConnect'); } } else { cleartext.authorized = true; cleartext.emit('secureConnect'); } }); pair.on('error', function(err) { cleartext.emit('error', err); }); cleartext._controlReleased = true; return cleartext; }; function pipe(pair, socket) { pair.encrypted.pipe(socket); socket.pipe(pair.encrypted); pair.encrypted.on('close', function() { process.nextTick(function() { // Encrypted should be unpiped from socket to prevent possible // write after destroy. pair.encrypted.unpipe(socket); socket.destroy(); }); }); pair.fd = socket.fd; var cleartext = pair.cleartext; cleartext.socket = socket; cleartext.encrypted = pair.encrypted; cleartext.authorized = false; // cycle the data whenever the socket drains, so that // we can pull some more into it. normally this would // be handled by the fact that pipe() triggers read() calls // on writable.drain, but CryptoStreams are a bit more // complicated. Since the encrypted side actually gets // its data from the cleartext side, we have to give it a // light kick to get in motion again. socket.on('drain', function() { if (pair.encrypted._pending) pair.encrypted._writePending(); if (pair.cleartext._pending) pair.cleartext._writePending(); pair.encrypted.read(0); pair.cleartext.read(0); }); function onerror(e) { if (cleartext._controlReleased) { cleartext.emit('error', e); } } function onclose() { socket.removeListener('error', onerror); socket.removeListener('timeout', ontimeout); } function ontimeout() { cleartext.emit('timeout'); } socket.on('error', onerror); socket.on('close', onclose); socket.on('timeout', ontimeout); return cleartext; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Timer = process.binding('timer_wrap').Timer; var L = require('_linklist'); var assert = require('assert').ok; // Timeout values > TIMEOUT_MAX are set to 1. var TIMEOUT_MAX = 2147483647; // 2^31-1 var debug; if (process.env.NODE_DEBUG && /timer/.test(process.env.NODE_DEBUG)) { debug = function() { require('util').error.apply(this, arguments); }; } else { debug = function() { }; } // IDLE TIMEOUTS // // Because often many sockets will have the same idle timeout we will not // use one timeout watcher per item. It is too much overhead. Instead // we'll use a single watcher for all sockets with the same timeout value // and a linked list. This technique is described in the libev manual: // http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts // Object containing all lists, timers // key = time in milliseconds // value = list var lists = {}; // the main function - creates lists on demand and the watchers associated // with them. function insert(item, msecs) { item._idleStart = Date.now(); item._idleTimeout = msecs; if (msecs < 0) return; var list; if (lists[msecs]) { list = lists[msecs]; } else { list = new Timer(); list.start(msecs, 0); L.init(list); lists[msecs] = list; list.msecs = msecs; list.ontimeout = listOnTimeout; } L.append(list, item); assert(!L.isEmpty(list)); // list is not empty } function listOnTimeout() { var msecs = this.msecs; var list = this; debug('timeout callback ' + msecs); var now = Date.now(); debug('now: ' + now); var first; while (first = L.peek(list)) { var diff = now - first._idleStart; if (diff < msecs) { list.start(msecs - diff, 0); debug(msecs + ' list wait because diff is ' + diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the // domain or uncaughtException handler ignore the exception, // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 var domain = first.domain; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; first._onTimeout(); if (domain) domain.exit(); threw = false; } finally { if (threw) { process.nextTick(function() { list.ontimeout(); }); } } } } debug(msecs + ' list empty'); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; } var unenroll = exports.unenroll = function(item) { L.remove(item); var list = lists[item._idleTimeout]; // if empty then stop the watcher debug('unenroll'); if (list && L.isEmpty(list)) { debug('unenroll: list empty'); list.close(); delete lists[item._idleTimeout]; } // if active is called later, then we want to make sure not to insert again item._idleTimeout = -1; }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { // if this item was already in a list somewhere // then we should unenroll it from that if (item._idleNext) unenroll(item); // Ensure that msecs fits into signed int32 if (msecs > 0x7fffffff) { msecs = 0x7fffffff; } item._idleTimeout = msecs; L.init(item); }; // call this whenever the item is active (not idle) // it will reset its timeout. exports.active = function(item) { var msecs = item._idleTimeout; if (msecs >= 0) { var list = lists[msecs]; if (!list || L.isEmpty(list)) { insert(item, msecs); } else { item._idleStart = Date.now(); L.append(list, item); } } }; /* * DOM-style timers */ exports.setTimeout = function(callback, after) { var timer; after *= 1; // coalesce to number or NaN if (!(after >= 1 && after <= TIMEOUT_MAX)) { after = 1; // schedule on next tick, follows browser behaviour } timer = new Timeout(after); if (arguments.length <= 2) { timer._onTimeout = callback; } else { /* * Sometimes setTimeout is called with arguments, EG * * setTimeout(callback, 2000, "hello", "world") * * If that's the case we need to call the callback with * those args. The overhead of an extra closure is not * desired in the normal case. */ var args = Array.prototype.slice.call(arguments, 2); timer._onTimeout = function() { callback.apply(timer, args); } } if (process.domain) timer.domain = process.domain; exports.active(timer); return timer; }; exports.clearTimeout = function(timer) { if (timer && (timer.ontimeout || timer._onTimeout)) { timer.ontimeout = timer._onTimeout = null; if (timer instanceof Timeout) { timer.close(); // for after === 0 } else { exports.unenroll(timer); } } }; exports.setInterval = function(callback, repeat) { repeat *= 1; // coalesce to number or NaN if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { repeat = 1; // schedule on next tick, follows browser behaviour } var timer = new Timeout(repeat); var args = Array.prototype.slice.call(arguments, 2); timer._onTimeout = wrapper; timer._repeat = true; if (process.domain) timer.domain = process.domain; exports.active(timer); return timer; function wrapper() { callback.apply(this, args); // If callback called clearInterval(). if (timer._repeat === false) return; // If timer is unref'd (or was - it's permanently removed from the list.) if (this._handle) { this._handle.start(repeat, 0); } else { timer._idleTimeout = repeat; exports.active(timer); } } }; exports.clearInterval = function(timer) { if (timer && timer._repeat) { timer._repeat = false; clearTimeout(timer); } }; var Timeout = function(after) { this._idleTimeout = after; this._idlePrev = this; this._idleNext = this; this._idleStart = null; this._onTimeout = null; this._repeat = false; }; Timeout.prototype.unref = function() { if (!this._handle) { var now = Date.now(); if (!this._idleStart) this._idleStart = now; var delay = this._idleStart + this._idleTimeout - now; if (delay < 0) delay = 0; exports.unenroll(this); this._handle = new Timer(); this._handle.ontimeout = this._onTimeout; this._handle.start(delay, 0); this._handle.domain = this.domain; this._handle.unref(); } else { this._handle.unref(); } }; Timeout.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Timeout.prototype.close = function() { this._onTimeout = null; if (this._handle) { this._handle.ontimeout = null; this._handle.close(); } else { exports.unenroll(this); } }; var immediateQueue = {}; L.init(immediateQueue); function processImmediate() { var immediate = L.shift(immediateQueue); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } if (immediate._onImmediate) { if (immediate.domain) immediate.domain.enter(); immediate._onImmediate(); if (immediate.domain) immediate.domain.exit(); } } exports.setImmediate = function(callback) { var immediate = {}, args; L.init(immediate); immediate._onImmediate = callback; if (arguments.length > 1) { args = Array.prototype.slice.call(arguments, 1); immediate._onImmediate = function() { callback.apply(immediate, args); }; } if (!process._needImmediateCallback) { process._needImmediateCallback = true; process._immediateCallback = processImmediate; } if (process.domain) immediate.domain = process.domain; L.append(immediateQueue, immediate); return immediate; }; exports.clearImmediate = function(immediate) { if (!immediate) return; immediate._onImmediate = undefined; L.remove(immediate); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } }; // Internal APIs that need timeouts should use timers._unrefActive isntead of // timers.active as internal timeouts shouldn't hold the loop open var unrefList, unrefTimer; function unrefTimeout() { var now = Date.now(); debug('unrefTimer fired'); var first; while (first = L.peek(unrefList)) { var diff = now - first._idleStart; if (diff < first._idleTimeout) { diff = first._idleTimeout - diff; unrefTimer.start(diff, 0); unrefTimer.when = now + diff; debug('unrefTimer rescheudling for later'); return; } L.remove(first); var domain = first.domain; if (!first._onTimeout) continue; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; debug('unreftimer firing timeout'); first._onTimeout(); threw = false; if (domain) domain.exit(); } finally { if (threw) process.nextTick(unrefTimeout); } } debug('unrefList is empty'); unrefTimer.when = -1; } exports._unrefActive = function(item) { var msecs = item._idleTimeout; if (!msecs || msecs < 0) return; assert(msecs >= 0); L.remove(item); if (!unrefList) { debug('unrefList initialized'); unrefList = {}; L.init(unrefList); debug('unrefTimer initialized'); unrefTimer = new Timer(); unrefTimer.unref(); unrefTimer.when = -1; unrefTimer.ontimeout = unrefTimeout; } var now = Date.now(); item._idleStart = now; if (L.isEmpty(unrefList)) { debug('unrefList empty'); L.append(unrefList, item); unrefTimer.start(msecs, 0); unrefTimer.when = now + msecs; debug('unrefTimer scheduled'); return; } var when = now + msecs; debug('unrefList find where we can insert'); var cur, them; for (cur = unrefList._idlePrev; cur != unrefList; cur = cur._idlePrev) { them = cur._idleStart + cur._idleTimeout; if (when < them) { debug('unrefList inserting into middle of list'); L.append(cur, item); if (unrefTimer.when > when) { debug('unrefTimer is scheduled to fire too late, reschedule'); unrefTimer.start(msecs, 0); unrefTimer.when = when; } return; } } debug('unrefList append to end'); L.append(unrefList, item); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // the sys module was renamed to 'util'. // this shim remains to keep old programs working. module.exports = require('util'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. function assertEncoding(encoding) { if (encoding && !Buffer.isEncoding(encoding)) { throw new Error('Unknown encoding: ' + encoding); } } var StringDecoder = exports.StringDecoder = function(encoding) { this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); assertEncoding(encoding); switch (this.encoding) { case 'utf8': // CESU-8 represents each of Surrogate Pair by 3-bytes this.surrogateSize = 3; break; case 'ucs2': case 'utf16le': // UTF-16 represents each of Surrogate Pair by 2-bytes this.surrogateSize = 2; this.detectIncompleteChar = utf16DetectIncompleteChar; break; case 'base64': // Base-64 stores 3 bytes in 4 chars, and pads the remainder. this.surrogateSize = 3; this.detectIncompleteChar = base64DetectIncompleteChar; break; default: this.write = passThroughWrite; return; } this.charBuffer = new Buffer(6); this.charReceived = 0; this.charLength = 0; }; StringDecoder.prototype.write = function(buffer) { var charStr = ''; var offset = 0; // if our last write ended with an incomplete multibyte character while (this.charLength) { // determine how many remaining bytes this buffer has to offer for this char var i = (buffer.length >= this.charLength - this.charReceived) ? this.charLength - this.charReceived : buffer.length; // add the new bytes to the char buffer buffer.copy(this.charBuffer, this.charReceived, offset, i); this.charReceived += (i - offset); offset = i; if (this.charReceived < this.charLength) { // still not enough chars in this buffer? wait for more ... return ''; } // get the character that was split charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); // lead surrogate (D800-DBFF) is also the incomplete character var charCode = charStr.charCodeAt(charStr.length - 1); if (charCode >= 0xD800 && charCode <= 0xDBFF) { this.charLength += this.surrogateSize; charStr = ''; continue; } this.charReceived = this.charLength = 0; // if there are no more bytes in this buffer, just emit our char if (i == buffer.length) return charStr; // otherwise cut off the characters end from the beginning of this buffer buffer = buffer.slice(i, buffer.length); break; } var lenIncomplete = this.detectIncompleteChar(buffer); var end = buffer.length; if (this.charLength) { // buffer the incomplete character bytes we got buffer.copy(this.charBuffer, 0, buffer.length - lenIncomplete, end); this.charReceived = lenIncomplete; end -= lenIncomplete; } charStr += buffer.toString(this.encoding, 0, end); var end = charStr.length - 1; var charCode = charStr.charCodeAt(end); // lead surrogate (D800-DBFF) is also the incomplete character if (charCode >= 0xD800 && charCode <= 0xDBFF) { var size = this.surrogateSize; this.charLength += size; this.charReceived += size; this.charBuffer.copy(this.charBuffer, size, 0, size); this.charBuffer.write(charStr.charAt(charStr.length - 1), this.encoding); return charStr.substring(0, end); } // or just emit the charStr return charStr; }; StringDecoder.prototype.detectIncompleteChar = function(buffer) { // determine how many bytes we have to check at the end of this buffer var i = (buffer.length >= 3) ? 3 : buffer.length; // Figure out if one of the last i bytes of our buffer announces an // incomplete char. for (; i > 0; i--) { var c = buffer[buffer.length - i]; // See http://en.wikipedia.org/wiki/UTF-8#Description // 110XXXXX if (i == 1 && c >> 5 == 0x06) { this.charLength = 2; break; } // 1110XXXX if (i <= 2 && c >> 4 == 0x0E) { this.charLength = 3; break; } // 11110XXX if (i <= 3 && c >> 3 == 0x1E) { this.charLength = 4; break; } } return i; }; StringDecoder.prototype.end = function(buffer) { var res = ''; if (buffer && buffer.length) res = this.write(buffer); if (this.charReceived) { var cr = this.charReceived; var buf = this.charBuffer; var enc = this.encoding; res += buf.slice(0, cr).toString(enc); } return res; }; function passThroughWrite(buffer) { return buffer.toString(this.encoding); } function utf16DetectIncompleteChar(buffer) { var incomplete = this.charReceived = buffer.length % 2; this.charLength = incomplete ? 2 : 0; return incomplete; } function base64DetectIncompleteChar(buffer) { var incomplete = this.charReceived = buffer.length % 3; this.charLength = incomplete ? 3 : 0; return incomplete; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = Stream; var EE = require('events').EventEmitter; var util = require('util'); util.inherits(Stream, EE); Stream.Readable = require('_stream_readable'); Stream.Writable = require('_stream_writable'); Stream.Duplex = require('_stream_duplex'); Stream.Transform = require('_stream_transform'); Stream.PassThrough = require('_stream_passthrough'); // Backwards-compat with node 0.4.x Stream.Stream = Stream; // old-style streams. Note that the pipe method (the only relevant // part of this class) is overridden in the Readable class. function Stream() { EE.call(this); } Stream.prototype.pipe = function(dest, options) { var source = this; function ondata(chunk) { if (dest.writable) { if (false === dest.write(chunk) && source.pause) { source.pause(); } } } source.on('data', ondata); function ondrain() { if (source.readable && source.resume) { source.resume(); } } dest.on('drain', ondrain); // If the 'end' option is not supplied, dest.end() will be called when // source gets the 'end' or 'close' events. Only dest.end() once. if (!dest._isStdio && (!options || options.end !== false)) { source.on('end', onend); source.on('close', onclose); } var didOnEnd = false; function onend() { if (didOnEnd) return; didOnEnd = true; dest.end(); } function onclose() { if (didOnEnd) return; didOnEnd = true; if (typeof dest.destroy === 'function') dest.destroy(); } // don't leave dangling pipes when there are errors. function onerror(er) { cleanup(); if (EE.listenerCount(this, 'error') === 0) { throw er; // Unhandled stream error in pipe. } } source.on('error', onerror); dest.on('error', onerror); // remove all the event listeners that were added. function cleanup() { source.removeListener('data', ondata); dest.removeListener('drain', ondrain); source.removeListener('end', onend); source.removeListener('close', onclose); source.removeListener('error', onerror); dest.removeListener('error', onerror); source.removeListener('end', cleanup); source.removeListener('close', cleanup); dest.removeListener('close', cleanup); } source.on('end', cleanup); source.on('close', cleanup); dest.on('close', cleanup); dest.emit('pipe', source); // Allow for unix-like usage: A.pipe(B).pipe(C) return dest; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* A repl library that you can include in your own code to get a runtime * interface to your program. * * var repl = require("repl"); * // start repl on stdin * repl.start("prompt> "); * * // listen for unix socket connections and start repl on them * net.createServer(function(socket) { * repl.start("node via Unix socket> ", socket); * }).listen("/tmp/node-repl-sock"); * * // listen for TCP socket connections and start repl on them * net.createServer(function(socket) { * repl.start("node via TCP socket> ", socket); * }).listen(5001); * * // expose foo to repl context * repl.start("node > ").context.foo = "stdin is fun"; */ var util = require('util'); var inherits = require('util').inherits; var Stream = require('stream'); var vm = require('vm'); var path = require('path'); var fs = require('fs'); var rl = require('readline'); var Console = require('console').Console; var EventEmitter = require('events').EventEmitter; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } // hack for require.resolve("./relative") to work properly. module.filename = path.resolve('repl'); // hack for repl require to work properly with node_modules folders module.paths = require('module')._nodeModulePaths(module.filename); // Can overridden with custom print functions, such as `probe` or `eyes.js`. // This is the default "writer" value if none is passed in the REPL options. exports.writer = util.inspect; exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'stream', 'string_decoder', 'tls', 'tty', 'url', 'util', 'vm', 'zlib']; function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) { if (!(this instanceof REPLServer)) { return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined); } EventEmitter.call(this); var options, input, output; if (typeof prompt == 'object') { // an options object was given options = prompt; stream = options.stream || options.socket; input = options.input; output = options.output; eval_ = options.eval; useGlobal = options.useGlobal; ignoreUndefined = options.ignoreUndefined; prompt = options.prompt; } else if (typeof prompt != 'string') { throw new Error('An options Object, or a prompt String are required'); } else { options = {}; } var self = this; self.useGlobal = !!useGlobal; self.ignoreUndefined = !!ignoreUndefined; self.eval = eval_ || function(code, context, file, cb) { var err, result; try { if (self.useGlobal) { result = vm.runInThisContext(code, file); } else { result = vm.runInContext(code, context, file); } } catch (e) { err = e; } if (err && process.domain) { process.domain.emit('error', err); process.domain.exit(); } else { cb(err, result); } }; if (!input && !output) { // legacy API, passing a 'stream'/'socket' option if (!stream) { // use stdin and stdout as the default streams if none were given stream = process; } if (stream.stdin && stream.stdout) { // We're given custom object with 2 streams, or the `process` object input = stream.stdin; output = stream.stdout; } else { // We're given a duplex readable/writable Stream, like a `net.Socket` input = stream; output = stream; } } self.inputStream = input; self.outputStream = output; self.resetContext(); self.bufferedCommand = ''; self.prompt = (prompt != undefined ? prompt : '> '); function complete(text, callback) { self.complete(text, callback); } var rli = rl.createInterface({ input: self.inputStream, output: self.outputStream, completer: complete, terminal: options.terminal }); self.rli = rli; this.commands = {}; defineDefaultCommands(this); // figure out which "writer" function to use self.writer = options.writer || exports.writer; if (typeof options.useColors === 'undefined') { options.useColors = rli.terminal; } self.useColors = !!options.useColors; if (self.useColors && self.writer === util.inspect) { // Turn on ANSI coloring. self.writer = function(obj, showHidden, depth) { return util.inspect(obj, showHidden, depth, true); }; } rli.setPrompt(self.prompt); rli.on('close', function() { self.emit('exit'); }); var sawSIGINT = false; rli.on('SIGINT', function() { var empty = rli.line.length === 0; rli.clearLine(); if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) { if (sawSIGINT) { rli.close(); sawSIGINT = false; return; } rli.output.write('(^C again to quit)\n'); sawSIGINT = true; } else { sawSIGINT = false; } self.bufferedCommand = ''; self.displayPrompt(); }); rli.on('line', function(cmd) { sawSIGINT = false; var skipCatchall = false; cmd = trimWhitespace(cmd); // Check to see if a REPL keyword was used. If it returns true, // display next prompt and return. if (cmd && cmd.charAt(0) === '.' && isNaN(parseFloat(cmd))) { var matches = cmd.match(/^(\.[^\s]+)\s*(.*)$/); var keyword = matches && matches[1]; var rest = matches && matches[2]; if (self.parseREPLKeyword(keyword, rest) === true) { return; } else { self.outputStream.write('Invalid REPL keyword\n'); skipCatchall = true; } } if (!skipCatchall) { var evalCmd = self.bufferedCommand + cmd + '\n'; // This try is for determining if the command is complete, or should // continue onto the next line. // We try to evaluate both expressions e.g. // '{ a : 1 }' // and statements e.g. // 'for (var i = 0; i < 10; i++) console.log(i);' // First we attempt to eval as expression with parens. // This catches '{a : 1}' properly. self.eval('(' + evalCmd + ')', self.context, 'repl', function(e, ret) { if (e && !isSyntaxError(e)) return finish(e); if (typeof ret === 'function' && /^[\r\n\s]*function/.test(evalCmd) || e) { // Now as statement without parens. self.eval(evalCmd, self.context, 'repl', finish); } else { finish(null, ret); } }); } else { finish(null); } function finish(e, ret) { self.memory(cmd); // If error was SyntaxError and not JSON.parse error if (isSyntaxError(e)) { if (!self.bufferedCommand && cmd.trim().match(/^npm /)) { self.outputStream.write('npm should be run outside of the ' + 'node repl, in your normal shell.\n' + '(Press Control-D to exit.)\n'); self.bufferedCommand = ''; self.displayPrompt(); return; } // Start buffering data like that: // { // ... x: 1 // ... } self.bufferedCommand += cmd + '\n'; self.displayPrompt(); return; } else if (e) { self.outputStream.write((e.stack || e) + '\n'); } // Clear buffer if no SyntaxErrors self.bufferedCommand = ''; // If we got any output - print it (if no error) if (!e && (!self.ignoreUndefined || ret !== undefined)) { self.context._ = ret; self.outputStream.write(self.writer(ret) + '\n'); } // Display prompt again self.displayPrompt(); }; }); rli.on('SIGCONT', function() { self.displayPrompt(true); }); self.displayPrompt(); } inherits(REPLServer, EventEmitter); exports.REPLServer = REPLServer; // prompt is a string to print on each line for the prompt, // source is a stream to use for I/O, defaulting to stdin/stdout. exports.start = function(prompt, source, eval_, useGlobal, ignoreUndefined) { var repl = new REPLServer(prompt, source, eval_, useGlobal, ignoreUndefined); if (!exports.repl) exports.repl = repl; return repl; }; REPLServer.prototype.createContext = function() { var context; if (this.useGlobal) { context = global; } else { context = vm.createContext(); for (var i in global) context[i] = global[i]; context.console = new Console(this.outputStream); context.global = context; context.global.global = context; } context.module = module; context.require = require; this.lines = []; this.lines.level = []; // make built-in modules available directly // (loaded lazily) exports._builtinLibs.forEach(function(name) { Object.defineProperty(context, name, { get: function() { var lib = require(name); context._ = context[name] = lib; return lib; }, // allow the creation of other globals with this name set: function(val) { delete context[name]; context[name] = val; }, configurable: true }); }); return context; }; REPLServer.prototype.resetContext = function() { this.context = this.createContext(); }; REPLServer.prototype.displayPrompt = function(preserveCursor) { var prompt = this.prompt; if (this.bufferedCommand.length) { prompt = '...'; var levelInd = new Array(this.lines.level.length).join('..'); prompt += levelInd + ' '; } this.rli.setPrompt(prompt); this.rli.prompt(preserveCursor); }; // A stream to push an array into a REPL // used in REPLServer.complete function ArrayStream() { Stream.call(this); this.run = function(data) { var self = this; data.forEach(function(line) { self.emit('data', line + '\n'); }); } } util.inherits(ArrayStream, Stream); ArrayStream.prototype.readable = true; ArrayStream.prototype.writable = true; ArrayStream.prototype.resume = function() {}; ArrayStream.prototype.write = function() {}; var requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/; var simpleExpressionRE = /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/; // Provide a list of completions for the given leading text. This is // given to the readline interface for handling tab completion. // // Example: // complete('var foo = util.') // -> [['util.print', 'util.debug', 'util.log', 'util.inspect', 'util.pump'], // 'util.' ] // // Warning: This eval's code like "foo.bar.baz", so it will run property // getter code. REPLServer.prototype.complete = function(line, callback) { // There may be local variables to evaluate, try a nested REPL if (this.bufferedCommand != undefined && this.bufferedCommand.length) { // Get a new array of inputed lines var tmp = this.lines.slice(); // Kill off all function declarations to push all local variables into // global scope this.lines.level.forEach(function(kill) { if (kill.isFunction) { tmp[kill.line] = ''; } }); var flat = new ArrayStream(); // make a new "input" stream var magic = new REPLServer('', flat); // make a nested REPL magic.context = magic.createContext(); flat.run(tmp); // eval the flattened code // all this is only profitable if the nested REPL // does not have a bufferedCommand if (!magic.bufferedCommand) { return magic.complete(line, callback); } } var completions; // list of completion lists, one for each inheritance "level" var completionGroups = []; var completeOn, match, filter, i, j, group, c; // REPL commands (e.g. ".break"). var match = null; match = line.match(/^\s*(\.\w*)$/); if (match) { completionGroups.push(Object.keys(this.commands)); completeOn = match[1]; if (match[1].length > 1) { filter = match[1]; } completionGroupsLoaded(); } else if (match = line.match(requireRE)) { // require('...') var exts = Object.keys(require.extensions); var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') + ')$'); completeOn = match[1]; var subdir = match[2] || ''; var filter = match[1]; var dir, files, f, name, base, ext, abs, subfiles, s; group = []; var paths = module.paths.concat(require('module').globalPaths); for (i = 0; i < paths.length; i++) { dir = path.resolve(paths[i], subdir); try { files = fs.readdirSync(dir); } catch (e) { continue; } for (f = 0; f < files.length; f++) { name = files[f]; ext = path.extname(name); base = name.slice(0, -ext.length); if (base.match(/-\d+\.\d+(\.\d+)?/) || name === '.npm') { // Exclude versioned names that 'npm' installs. continue; } if (exts.indexOf(ext) !== -1) { if (!subdir || base !== 'index') { group.push(subdir + base); } } else { abs = path.resolve(dir, name); try { if (fs.statSync(abs).isDirectory()) { group.push(subdir + name + '/'); subfiles = fs.readdirSync(abs); for (s = 0; s < subfiles.length; s++) { if (indexRe.test(subfiles[s])) { group.push(subdir + name); } } } } catch (e) {} } } } if (group.length) { completionGroups.push(group); } if (!subdir) { completionGroups.push(exports._builtinLibs); } completionGroupsLoaded(); // Handle variable member lookup. // We support simple chained expressions like the following (no function // calls, etc.). That is for simplicity and also because we *eval* that // leading expression so for safety (see WARNING above) don't want to // eval function calls. // // foo.bar<|> # completions for 'foo' with filter 'bar' // spam.eggs.<|> # completions for 'spam.eggs' with filter '' // foo<|> # all scope vars with filter 'foo' // foo.<|> # completions for 'foo' with filter '' } else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) { match = simpleExpressionRE.exec(line); if (line.length === 0 || match) { var expr; completeOn = (match ? match[0] : ''); if (line.length === 0) { filter = ''; expr = ''; } else if (line[line.length - 1] === '.') { filter = ''; expr = match[0].slice(0, match[0].length - 1); } else { var bits = match[0].split('.'); filter = bits.pop(); expr = bits.join('.'); } // Resolve expr and get its completions. var obj, memberGroups = []; if (!expr) { // If context is instance of vm.ScriptContext // Get global vars synchronously if (this.useGlobal || this.context.constructor && this.context.constructor.name === 'Context') { var contextProto = this.context; while (contextProto = Object.getPrototypeOf(contextProto)) { completionGroups.push(Object.getOwnPropertyNames(contextProto)); } completionGroups.push(Object.getOwnPropertyNames(this.context)); addStandardGlobals(completionGroups, filter); completionGroupsLoaded(); } else { this.eval('.scope', this.context, 'repl', function(err, globals) { if (err || !globals) { addStandardGlobals(completionGroups, filter); } else if (Array.isArray(globals[0])) { // Add grouped globals globals.forEach(function(group) { completionGroups.push(group); }); } else { completionGroups.push(globals); addStandardGlobals(completionGroups, filter); } completionGroupsLoaded(); }); } } else { this.eval(expr, this.context, 'repl', function(e, obj) { // if (e) console.log(e); if (obj != null) { if (typeof obj === 'object' || typeof obj === 'function') { memberGroups.push(Object.getOwnPropertyNames(obj)); } // works for non-objects try { var sentinel = 5; var p; if (typeof obj === 'object' || typeof obj === 'function') { p = Object.getPrototypeOf(obj); } else { p = obj.constructor ? obj.constructor.prototype : null; } while (p !== null) { memberGroups.push(Object.getOwnPropertyNames(p)); p = Object.getPrototypeOf(p); // Circular refs possible? Let's guard against that. sentinel--; if (sentinel <= 0) { break; } } } catch (e) { //console.log("completion error walking prototype chain:" + e); } } if (memberGroups.length) { for (i = 0; i < memberGroups.length; i++) { completionGroups.push(memberGroups[i].map(function(member) { return expr + '.' + member; })); } if (filter) { filter = expr + '.' + filter; } } completionGroupsLoaded(); }); } } else { completionGroupsLoaded(); } } else { completionGroupsLoaded(); } // Will be called when all completionGroups are in place // Useful for async autocompletion function completionGroupsLoaded(err) { if (err) throw err; // Filter, sort (within each group), uniq and merge the completion groups. if (completionGroups.length && filter) { var newCompletionGroups = []; for (i = 0; i < completionGroups.length; i++) { group = completionGroups[i].filter(function(elem) { return elem.indexOf(filter) == 0; }); if (group.length) { newCompletionGroups.push(group); } } completionGroups = newCompletionGroups; } if (completionGroups.length) { var uniq = {}; // unique completions across all groups completions = []; // Completion group 0 is the "closest" // (least far up the inheritance chain) // so we put its completions last: to be closest in the REPL. for (i = completionGroups.length - 1; i >= 0; i--) { group = completionGroups[i]; group.sort(); for (var j = 0; j < group.length; j++) { c = group[j]; if (!hasOwnProperty(c)) { completions.push(c); uniq[c] = true; } } completions.push(''); // separator btwn groups } while (completions.length && completions[completions.length - 1] === '') { completions.pop(); } } callback(null, [completions || [], completeOn]); } }; /** * Used to parse and execute the Node REPL commands. * * @param {keyword} keyword The command entered to check. * @return {Boolean} If true it means don't continue parsing the command. */ REPLServer.prototype.parseREPLKeyword = function(keyword, rest) { var cmd = this.commands[keyword]; if (cmd) { cmd.action.call(this, rest); return true; } return false; }; REPLServer.prototype.defineCommand = function(keyword, cmd) { if (typeof cmd === 'function') { cmd = {action: cmd}; } else if (typeof cmd.action !== 'function') { throw new Error('bad argument, action must be a function'); } this.commands['.' + keyword] = cmd; }; REPLServer.prototype.memory = function memory(cmd) { var self = this; self.lines = self.lines || []; self.lines.level = self.lines.level || []; // save the line so I can do magic later if (cmd) { // TODO should I tab the level? self.lines.push(new Array(self.lines.level.length).join(' ') + cmd); } else { // I don't want to not change the format too much... self.lines.push(''); } // I need to know "depth." // Because I can not tell the difference between a } that // closes an object literal and a } that closes a function if (cmd) { // going down is { and ( e.g. function() { // going up is } and ) var dw = cmd.match(/{|\(/g); var up = cmd.match(/}|\)/g); up = up ? up.length : 0; dw = dw ? dw.length : 0; var depth = dw - up; if (depth) { (function workIt() { if (depth > 0) { // going... down. // push the line#, depth count, and if the line is a function. // Since JS only has functional scope I only need to remove // "function() {" lines, clearly this will not work for // "function() // {" but nothing should break, only tab completion for local // scope will not work for this function. self.lines.level.push({ line: self.lines.length - 1, depth: depth, isFunction: /\s*function\s*/.test(cmd) }); } else if (depth < 0) { // going... up. var curr = self.lines.level.pop(); if (curr) { var tmp = curr.depth + depth; if (tmp < 0) { //more to go, recurse depth += curr.depth; workIt(); } else if (tmp > 0) { //remove and push back curr.depth += depth; self.lines.level.push(curr); } } } }()); } // it is possible to determine a syntax error at this point. // if the REPL still has a bufferedCommand and // self.lines.level.length === 0 // TODO? keep a log of level so that any syntax breaking lines can // be cleared on .break and in the case of a syntax error? // TODO? if a log was kept, then I could clear the bufferedComand and // eval these lines and throw the syntax error } else { self.lines.level = []; } }; function addStandardGlobals(completionGroups, filter) { // Global object properties // (http://www.ecma-international.org/publications/standards/Ecma-262.htm) completionGroups.push(['NaN', 'Infinity', 'undefined', 'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'Object', 'Function', 'Array', 'String', 'Boolean', 'Number', 'Date', 'RegExp', 'Error', 'EvalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'Math', 'JSON']); // Common keywords. Exclude for completion on the empty string, b/c // they just get in the way. if (filter) { completionGroups.push(['break', 'case', 'catch', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'false', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void', 'while', 'with', 'yield']); } } function defineDefaultCommands(repl) { // TODO remove me after 0.3.x repl.defineCommand('break', { help: 'Sometimes you get stuck, this gets you out', action: function() { this.bufferedCommand = ''; this.displayPrompt(); } }); var clearMessage; if (repl.useGlobal) { clearMessage = 'Alias for .break'; } else { clearMessage = 'Break, and also clear the local context'; } repl.defineCommand('clear', { help: clearMessage, action: function() { this.bufferedCommand = ''; if (!this.useGlobal) { this.outputStream.write('Clearing context...\n'); this.resetContext(); } this.displayPrompt(); } }); repl.defineCommand('exit', { help: 'Exit the repl', action: function() { this.rli.close(); } }); repl.defineCommand('help', { help: 'Show repl options', action: function() { var self = this; Object.keys(this.commands).sort().forEach(function(name) { var cmd = self.commands[name]; self.outputStream.write(name + '\t' + (cmd.help || '') + '\n'); }); this.displayPrompt(); } }); repl.defineCommand('save', { help: 'Save all evaluated commands in this REPL session to a file', action: function(file) { try { fs.writeFileSync(file, this.lines.join('\n') + '\n'); this.outputStream.write('Session saved to:' + file + '\n'); } catch (e) { this.outputStream.write('Failed to save:' + file + '\n'); } this.displayPrompt(); } }); repl.defineCommand('load', { help: 'Load JS from a file into the REPL session', action: function(file) { try { var stats = fs.statSync(file); if (stats && stats.isFile()) { var self = this; var data = fs.readFileSync(file, 'utf8'); var lines = data.split('\n'); this.displayPrompt(); lines.forEach(function(line) { if (line) { self.rli.write(line + '\n'); } }); } } catch (e) { this.outputStream.write('Failed to load:' + file + '\n'); } this.displayPrompt(); } }); } function trimWhitespace(cmd) { var trimmer = /^\s*(.+)\s*$/m, matches = trimmer.exec(cmd); if (matches && matches.length === 2) { return matches[1]; } return ''; } function regexpEscape(s) { return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); } /** * Converts commands that use var and function () to use the * local exports.context when evaled. This provides a local context * on the REPL. * * @param {String} cmd The cmd to convert. * @return {String} The converted command. */ REPLServer.prototype.convertToContext = function(cmd) { var self = this, matches, scopeVar = /^\s*var\s*([_\w\$]+)(.*)$/m, scopeFunc = /^\s*function\s*([_\w\$]+)/; // Replaces: var foo = "bar"; with: self.context.foo = bar; matches = scopeVar.exec(cmd); if (matches && matches.length === 3) { return 'self.context.' + matches[1] + matches[2]; } // Replaces: function foo() {}; with: foo = function foo() {}; matches = scopeFunc.exec(self.bufferedCommand); if (matches && matches.length === 2) { return matches[1] + ' = ' + self.bufferedCommand; } return cmd; }; /** * Returns `true` if "e" is a SyntaxError, `false` otherwise. * This function filters out false positives likes JSON.parse() errors and * RegExp syntax errors. */ function isSyntaxError(e) { // Convert error to string e = e && (e.stack || e.toString()); return e && ((e.match(/^SyntaxError/) && // RegExp syntax error !e.match(/^SyntaxError: Invalid regular expression/) && !e.match(/^SyntaxError: Invalid flags supplied to RegExp constructor/) && // "strict mode" syntax errors !e.match(/^SyntaxError: .*strict mode.*/i) && // JSON.parse() error !e.match(/\n {4}at Object.parse \(native\)\n/) && // Regexp errors in chakra: !e.match(/^Error: Expected .* in regular expression/) && !e.match(/^SyntaxError: Syntax error in regular expression/) && // Chakra Json parse error: !e.match(/\n {3}at JsonParse \(_chakra_patch.js/)) || ( (e.match(/^Error: Syntax error/) || e.match(/^Error: Expected/) ) && // RegExp syntax error !e.match(/^Error: Syntax error: Invalid regular expression/) && !e.match( /^Error: Syntax error: Invalid flags supplied to RegExp constructor/ ) && // "strict mode" syntax errors !e.match(/^Error: Syntax error: .*strict mode.*/i) && // JSON.parse() error !e.match(/\n {4}at Object.parse \(native\)\n/) && // Regexp errors in chakra: !e.match(/^Error: Expected .* in regular expression/) && !e.match(/^SyntaxError: Syntax error in regular expression/) && // Chakra Json parse error: !e.match(/\n {3}at JsonParse \(_chakra_patch.js/) )); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Inspiration for this code comes from Salvatore Sanfilippo's linenoise. // https://github.com/antirez/linenoise // Reference: // * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html // * http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html var kHistorySize = 30; var kBufSize = 10 * 1024; var util = require('util'); var inherits = require('util').inherits; var EventEmitter = require('events').EventEmitter; exports.createInterface = function(input, output, completer, terminal) { var rl; if (arguments.length === 1) { rl = new Interface(input); } else { rl = new Interface(input, output, completer, terminal); } return rl; }; function Interface(input, output, completer, terminal) { if (!(this instanceof Interface)) { return new Interface(input, output, completer, terminal); } this._sawReturn = false; EventEmitter.call(this); if (arguments.length === 1) { // an options object was given output = input.output; completer = input.completer; terminal = input.terminal; input = input.input; } completer = completer || function() { return []; }; if (typeof completer !== 'function') { throw new TypeError('Argument \'completer\' must be a function'); } // backwards compat; check the isTTY prop of the output stream // when `terminal` was not specified if (typeof terminal == 'undefined') { terminal = !!output.isTTY; } var self = this; this.output = output; this.input = input; // Check arity, 2 - for async, 1 for sync this.completer = completer.length === 2 ? completer : function(v, callback) { callback(null, completer(v)); }; this.setPrompt('> '); this.terminal = !!terminal; function ondata(data) { self._normalWrite(data); } function onend() { self.close(); } function onkeypress(s, key) { self._ttyWrite(s, key); } function onresize() { self._refreshLine(); } if (!this.terminal) { input.on('data', ondata); input.on('end', onend); self.once('close', function() { input.removeListener('data', ondata); input.removeListener('end', onend); }); var StringDecoder = require('string_decoder').StringDecoder; // lazy load this._decoder = new StringDecoder('utf8'); } else { exports.emitKeypressEvents(input); // input usually refers to stdin input.on('keypress', onkeypress); // Current line this.line = ''; this._setRawMode(true); this.terminal = true; // Cursor position on the line. this.cursor = 0; this.history = []; this.historyIndex = -1; output.on('resize', onresize); self.once('close', function() { input.removeListener('keypress', onkeypress); output.removeListener('resize', onresize); }); } input.resume(); } inherits(Interface, EventEmitter); Interface.prototype.__defineGetter__('columns', function() { return this.output.columns || Infinity; }); Interface.prototype.setPrompt = function(prompt, length) { this._prompt = prompt; if (length) { this._promptLength = length; } else { var lines = prompt.split(/[\r\n]/); var lastLine = lines[lines.length - 1]; this._promptLength = lastLine.length; } }; Interface.prototype._setRawMode = function(mode) { if (typeof this.input.setRawMode === 'function') { return this.input.setRawMode(mode); } }; Interface.prototype.prompt = function(preserveCursor) { if (this.paused) this.resume(); if (this.terminal) { if (!preserveCursor) this.cursor = 0; this._refreshLine(); } else { this.output.write(this._prompt); } }; Interface.prototype.question = function(query, cb) { if (typeof cb === 'function') { if (this._questionCallback) { this.prompt(); } else { this._oldPrompt = this._prompt; this.setPrompt(query); this._questionCallback = cb; this.prompt(); } } }; Interface.prototype._onLine = function(line) { if (this._questionCallback) { var cb = this._questionCallback; this._questionCallback = null; this.setPrompt(this._oldPrompt); cb(line); } else { this.emit('line', line); } }; Interface.prototype._addHistory = function() { if (this.line.length === 0) return ''; if (this.history.length === 0 || this.history[0] !== this.line) { this.history.unshift(this.line); // Only store so many if (this.history.length > kHistorySize) this.history.pop(); } this.historyIndex = -1; return this.history[0]; }; Interface.prototype._refreshLine = function() { var columns = this.columns; // line length var line = this._prompt + this.line; var lineLength = line.length; var lineCols = lineLength % columns; var lineRows = (lineLength - lineCols) / columns; // cursor position var cursorPos = this._getCursorPos(); // first move to the bottom of the current line, based on cursor pos var prevRows = this.prevRows || 0; if (prevRows > 0) { exports.moveCursor(this.output, 0, -prevRows); } // Cursor to left edge. exports.cursorTo(this.output, 0); // erase data exports.clearScreenDown(this.output); // Write the prompt and the current buffer content. this.output.write(line); // Force terminal to allocate a new line if (lineCols === 0) { this.output.write(' '); } // Move cursor to original position. exports.cursorTo(this.output, cursorPos.cols); var diff = lineRows - cursorPos.rows; if (diff > 0) { exports.moveCursor(this.output, 0, -diff); } this.prevRows = cursorPos.rows; }; Interface.prototype.close = function() { if (this.closed) return; if (this.terminal) { this._setRawMode(false); } this.pause(); this.closed = true; this.emit('close'); }; Interface.prototype.pause = function() { if (this.paused) return; this.input.pause(); this.paused = true; this.emit('pause'); }; Interface.prototype.resume = function() { if (!this.paused) return; this.input.resume(); this.paused = false; this.emit('resume'); }; Interface.prototype.write = function(d, key) { if (this.paused) this.resume(); this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d); }; // \r\n, \n, or \r followed by something other than \n var lineEnding = /\r?\n|\r(?!\n)/; Interface.prototype._normalWrite = function(b) { if (b === undefined) { return; } var string = this._decoder.write(b); if (this._sawReturn) { string = string.replace(/^\n/, ''); this._sawReturn = false; } if (this._line_buffer) { string = this._line_buffer + string; this._line_buffer = null; } if (lineEnding.test(string)) { this._sawReturn = /\r$/.test(string); // got one or more newlines; process into "line" events var lines = string.split(lineEnding); // either '' or (concievably) the unfinished portion of the next line string = lines.pop(); this._line_buffer = string; lines.forEach(function(line) { this._onLine(line); }, this); } else if (string) { // no newlines this time, save what we have for next time this._line_buffer = string; } }; Interface.prototype._insertString = function(c) { //BUG: Problem when adding tabs with following content. // Perhaps the bug is in _refreshLine(). Not sure. // A hack would be to insert spaces instead of literal '\t'. if (this.cursor < this.line.length) { var beg = this.line.slice(0, this.cursor); var end = this.line.slice(this.cursor, this.line.length); this.line = beg + c + end; this.cursor += c.length; this._refreshLine(); } else { this.line += c; this.cursor += c.length; if (this._getCursorPos().cols === 0) { this._refreshLine(); } else { this.output.write(c); } // a hack to get the line refreshed if it's needed this._moveCursor(0); } }; Interface.prototype._tabComplete = function() { var self = this; self.pause(); self.completer(self.line.slice(0, self.cursor), function(err, rv) { self.resume(); if (err) { // XXX Log it somewhere? return; } var completions = rv[0], completeOn = rv[1]; // the text that was completed if (completions && completions.length) { // Apply/show completions. if (completions.length === 1) { self._insertString(completions[0].slice(completeOn.length)); } else { self.output.write('\r\n'); var width = completions.reduce(function(a, b) { return a.length > b.length ? a : b; }).length + 2; // 2 space padding var maxColumns = Math.floor(self.columns / width) || 1; var group = [], c; for (var i = 0, compLen = completions.length; i < compLen; i++) { c = completions[i]; if (c === '') { handleGroup(self, group, width, maxColumns); group = []; } else { group.push(c); } } handleGroup(self, group, width, maxColumns); // If there is a common prefix to all matches, then apply that // portion. var f = completions.filter(function(e) { if (e) return e; }); var prefix = commonPrefix(f); if (prefix.length > completeOn.length) { self._insertString(prefix.slice(completeOn.length)); } } self._refreshLine(); } }); }; // this = Interface instance function handleGroup(self, group, width, maxColumns) { if (group.length == 0) { return; } var minRows = Math.ceil(group.length / maxColumns); for (var row = 0; row < minRows; row++) { for (var col = 0; col < maxColumns; col++) { var idx = row * maxColumns + col; if (idx >= group.length) { break; } var item = group[idx]; self.output.write(item); if (col < maxColumns - 1) { for (var s = 0, itemLen = item.length; s < width - itemLen; s++) { self.output.write(' '); } } } self.output.write('\r\n'); } self.output.write('\r\n'); } function commonPrefix(strings) { if (!strings || strings.length == 0) { return ''; } var sorted = strings.slice().sort(); var min = sorted[0]; var max = sorted[sorted.length - 1]; for (var i = 0, len = min.length; i < len; i++) { if (min[i] != max[i]) { return min.slice(0, i); } } return min; } Interface.prototype._wordLeft = function() { if (this.cursor > 0) { var leading = this.line.slice(0, this.cursor); var match = leading.match(/([^\w\s]+|\w+|)\s*$/); this._moveCursor(-match[0].length); } }; Interface.prototype._wordRight = function() { if (this.cursor < this.line.length) { var trailing = this.line.slice(this.cursor); var match = trailing.match(/^(\s+|\W+|\w+)\s*/); this._moveCursor(match[0].length); } }; Interface.prototype._deleteLeft = function() { if (this.cursor > 0 && this.line.length > 0) { this.line = this.line.slice(0, this.cursor - 1) + this.line.slice(this.cursor, this.line.length); this.cursor--; this._refreshLine(); } }; Interface.prototype._deleteRight = function() { this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1, this.line.length); this._refreshLine(); }; Interface.prototype._deleteWordLeft = function() { if (this.cursor > 0) { var leading = this.line.slice(0, this.cursor); var match = leading.match(/([^\w\s]+|\w+|)\s*$/); leading = leading.slice(0, leading.length - match[0].length); this.line = leading + this.line.slice(this.cursor, this.line.length); this.cursor = leading.length; this._refreshLine(); } }; Interface.prototype._deleteWordRight = function() { if (this.cursor < this.line.length) { var trailing = this.line.slice(this.cursor); var match = trailing.match(/^(\s+|\W+|\w+)\s*/); this.line = this.line.slice(0, this.cursor) + trailing.slice(match[0].length); this._refreshLine(); } }; Interface.prototype._deleteLineLeft = function() { this.line = this.line.slice(this.cursor); this.cursor = 0; this._refreshLine(); }; Interface.prototype._deleteLineRight = function() { this.line = this.line.slice(0, this.cursor); this._refreshLine(); }; Interface.prototype.clearLine = function() { this._moveCursor(+Infinity); this.output.write('\r\n'); this.line = ''; this.cursor = 0; this.prevRows = 0; }; Interface.prototype._line = function() { var line = this._addHistory(); this.clearLine(); this._onLine(line); }; Interface.prototype._historyNext = function() { if (this.historyIndex > 0) { this.historyIndex--; this.line = this.history[this.historyIndex]; this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } else if (this.historyIndex === 0) { this.historyIndex = -1; this.cursor = 0; this.line = ''; this._refreshLine(); } }; Interface.prototype._historyPrev = function() { if (this.historyIndex + 1 < this.history.length) { this.historyIndex++; this.line = this.history[this.historyIndex]; this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } }; // Returns current cursor's position and line Interface.prototype._getCursorPos = function() { var columns = this.columns; var cursorPos = this.cursor + this._promptLength; var cols = cursorPos % columns; var rows = (cursorPos - cols) / columns; return {cols: cols, rows: rows}; }; // This function moves cursor dx places to the right // (-dx for left) and refreshes the line if it is needed Interface.prototype._moveCursor = function(dx) { var oldcursor = this.cursor; var oldPos = this._getCursorPos(); this.cursor += dx; // bounds check if (this.cursor < 0) this.cursor = 0; if (this.cursor > this.line.length) this.cursor = this.line.length; var newPos = this._getCursorPos(); // check if cursors are in the same line if (oldPos.rows === newPos.rows) { exports.moveCursor(this.output, this.cursor - oldcursor, 0); this.prevRows = newPos.rows; } else { this._refreshLine(); } }; // handle a write from the tty Interface.prototype._ttyWrite = function(s, key) { key = key || {}; // Ignore escape key - Fixes #2876 if (key.name == 'escape') return; if (key.ctrl && key.shift) { /* Control and shift pressed */ switch (key.name) { case 'backspace': this._deleteLineLeft(); break; case 'delete': this._deleteLineRight(); break; } } else if (key.ctrl) { /* Control key pressed */ switch (key.name) { case 'c': if (EventEmitter.listenerCount(this, 'SIGINT') > 0) { this.emit('SIGINT'); } else { // This readline instance is finished this.close(); } break; case 'h': // delete left this._deleteLeft(); break; case 'd': // delete right or EOF if (this.cursor === 0 && this.line.length === 0) { // This readline instance is finished this.close(); } else if (this.cursor < this.line.length) { this._deleteRight(); } break; case 'u': // delete the whole line this.cursor = 0; this.line = ''; this._refreshLine(); break; case 'k': // delete from current to end of line this._deleteLineRight(); break; case 'a': // go to the start of the line this._moveCursor(-Infinity); break; case 'e': // go to the end of the line this._moveCursor(+Infinity); break; case 'b': // back one character this._moveCursor(-1); break; case 'f': // forward one character this._moveCursor(+1); break; case 'n': // next history item this._historyNext(); break; case 'p': // previous history item this._historyPrev(); break; case 'z': if (process.platform == 'win32') break; if (EventEmitter.listenerCount(this, 'SIGTSTP') > 0) { this.emit('SIGTSTP'); } else { process.once('SIGCONT', (function(self) { return function() { // Don't raise events if stream has already been abandoned. if (!self.paused) { // Stream must be paused and resumed after SIGCONT to catch // SIGINT, SIGTSTP, and EOF. self.pause(); self.emit('SIGCONT'); } // explictly re-enable "raw mode" and move the cursor to // the correct position. // See https://github.com/joyent/node/issues/3295. self._setRawMode(true); self._refreshLine(); }; })(this)); this._setRawMode(false); process.kill(process.pid, 'SIGTSTP'); } break; case 'w': // delete backwards to a word boundary case 'backspace': this._deleteWordLeft(); break; case 'delete': // delete forward to a word boundary this._deleteWordRight(); break; case 'backspace': this._deleteWordLeft(); break; case 'left': this._wordLeft(); break; case 'right': this._wordRight(); break; } } else if (key.meta) { /* Meta key pressed */ switch (key.name) { case 'b': // backward word this._wordLeft(); break; case 'f': // forward word this._wordRight(); break; case 'd': // delete forward word case 'delete': this._deleteWordRight(); break; case 'backspace': // delete backwards to a word boundary this._deleteWordLeft(); break; } } else { /* No modifier keys used */ // \r bookkeeping is only relevant if a \n comes right after. if (this._sawReturn && key.name !== 'enter') this._sawReturn = false; switch (key.name) { case 'return': // carriage return, i.e. \r this._sawReturn = true; this._line(); break; case 'enter': if (this._sawReturn) this._sawReturn = false; else this._line(); break; case 'backspace': this._deleteLeft(); break; case 'delete': this._deleteRight(); break; case 'tab': // tab completion this._tabComplete(); break; case 'left': this._moveCursor(-1); break; case 'right': this._moveCursor(+1); break; case 'home': this._moveCursor(-Infinity); break; case 'end': this._moveCursor(+Infinity); break; case 'up': this._historyPrev(); break; case 'down': this._historyNext(); break; default: if (Buffer.isBuffer(s)) s = s.toString('utf-8'); if (s) { var lines = s.split(/\r\n|\n|\r/); for (var i = 0, len = lines.length; i < len; i++) { if (i > 0) { this._line(); } this._insertString(lines[i]); } } } } }; exports.Interface = Interface; /** * accepts a readable Stream instance and makes it emit "keypress" events */ function emitKeypressEvents(stream) { if (stream._keypressDecoder) return; var StringDecoder = require('string_decoder').StringDecoder; // lazy load stream._keypressDecoder = new StringDecoder('utf8'); function onData(b) { if (EventEmitter.listenerCount(stream, 'keypress') > 0) { var r = stream._keypressDecoder.write(b); if (r) emitKey(stream, r); } else { // Nobody's watching anyway stream.removeListener('data', onData); stream.on('newListener', onNewListener); } } function onNewListener(event) { if (event == 'keypress') { stream.on('data', onData); stream.removeListener('newListener', onNewListener); } } if (EventEmitter.listenerCount(stream, 'keypress') > 0) { stream.on('data', onData); } else { stream.on('newListener', onNewListener); } } exports.emitKeypressEvents = emitKeypressEvents; /* Some patterns seen in terminal key escape codes, derived from combos seen at http://www.midnight-commander.org/browser/lib/tty/key.c ESC letter ESC [ letter ESC [ modifier letter ESC [ 1 ; modifier letter ESC [ num char ESC [ num ; modifier char ESC O letter ESC O modifier letter ESC O 1 ; modifier letter ESC N letter ESC [ [ num ; modifier char ESC [ [ 1 ; modifier letter ESC ESC [ num char ESC ESC O letter - char is usually ~ but $ and ^ also happen with rxvt - modifier is 1 + (shift * 1) + (left_alt * 2) + (ctrl * 4) + (right_alt * 8) - two leading ESCs apparently mean the same as one leading ESC */ // Regexes used for ansi escape code splitting var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; var functionKeyCodeRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; function emitKey(stream, s) { var ch, key = { name: undefined, ctrl: false, meta: false, shift: false }, parts; if (Buffer.isBuffer(s)) { if (s[0] > 127 && s[1] === undefined) { s[0] -= 128; s = '\x1b' + s.toString(stream.encoding || 'utf-8'); } else { s = s.toString(stream.encoding || 'utf-8'); } } key.sequence = s; if (s === '\r') { // carriage return key.name = 'return'; } else if (s === '\n') { // enter, should have been called linefeed key.name = 'enter'; } else if (s === '\t') { // tab key.name = 'tab'; } else if (s === '\b' || s === '\x7f' || s === '\x1b\x7f' || s === '\x1b\b') { // backspace or ctrl+h key.name = 'backspace'; key.meta = (s.charAt(0) === '\x1b'); } else if (s === '\x1b' || s === '\x1b\x1b') { // escape key key.name = 'escape'; key.meta = (s.length === 2); } else if (s === ' ' || s === '\x1b ') { key.name = 'space'; key.meta = (s.length === 2); } else if (s <= '\x1a') { // ctrl+letter key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); key.ctrl = true; } else if (s.length === 1 && s >= 'a' && s <= 'z') { // lowercase letter key.name = s; } else if (s.length === 1 && s >= 'A' && s <= 'Z') { // shift+letter key.name = s.toLowerCase(); key.shift = true; } else if (parts = metaKeyCodeRe.exec(s)) { // meta+character key key.name = parts[1].toLowerCase(); key.meta = true; key.shift = /^[A-Z]$/.test(parts[1]); } else if (parts = functionKeyCodeRe.exec(s)) { // ansi escape sequence // reassemble the key code leaving out leading \x1b's, // the modifier key bitflag and any meaningless "1;" sequence var code = (parts[1] || '') + (parts[2] || '') + (parts[4] || '') + (parts[6] || ''), modifier = (parts[3] || parts[5] || 1) - 1; // Parse the key modifier key.ctrl = !!(modifier & 4); key.meta = !!(modifier & 10); key.shift = !!(modifier & 1); key.code = code; // Parse the key itself switch (code) { /* xterm/gnome ESC O letter */ case 'OP': key.name = 'f1'; break; case 'OQ': key.name = 'f2'; break; case 'OR': key.name = 'f3'; break; case 'OS': key.name = 'f4'; break; /* xterm/rxvt ESC [ number ~ */ case '[11~': key.name = 'f1'; break; case '[12~': key.name = 'f2'; break; case '[13~': key.name = 'f3'; break; case '[14~': key.name = 'f4'; break; /* from Cygwin and used in libuv */ case '[[A': key.name = 'f1'; break; case '[[B': key.name = 'f2'; break; case '[[C': key.name = 'f3'; break; case '[[D': key.name = 'f4'; break; case '[[E': key.name = 'f5'; break; /* common */ case '[15~': key.name = 'f5'; break; case '[17~': key.name = 'f6'; break; case '[18~': key.name = 'f7'; break; case '[19~': key.name = 'f8'; break; case '[20~': key.name = 'f9'; break; case '[21~': key.name = 'f10'; break; case '[23~': key.name = 'f11'; break; case '[24~': key.name = 'f12'; break; /* xterm ESC [ letter */ case '[A': key.name = 'up'; break; case '[B': key.name = 'down'; break; case '[C': key.name = 'right'; break; case '[D': key.name = 'left'; break; case '[E': key.name = 'clear'; break; case '[F': key.name = 'end'; break; case '[H': key.name = 'home'; break; /* xterm/gnome ESC O letter */ case 'OA': key.name = 'up'; break; case 'OB': key.name = 'down'; break; case 'OC': key.name = 'right'; break; case 'OD': key.name = 'left'; break; case 'OE': key.name = 'clear'; break; case 'OF': key.name = 'end'; break; case 'OH': key.name = 'home'; break; /* xterm/rxvt ESC [ number ~ */ case '[1~': key.name = 'home'; break; case '[2~': key.name = 'insert'; break; case '[3~': key.name = 'delete'; break; case '[4~': key.name = 'end'; break; case '[5~': key.name = 'pageup'; break; case '[6~': key.name = 'pagedown'; break; /* putty */ case '[[5~': key.name = 'pageup'; break; case '[[6~': key.name = 'pagedown'; break; /* rxvt */ case '[7~': key.name = 'home'; break; case '[8~': key.name = 'end'; break; /* rxvt keys with modifiers */ case '[a': key.name = 'up'; key.shift = true; break; case '[b': key.name = 'down'; key.shift = true; break; case '[c': key.name = 'right'; key.shift = true; break; case '[d': key.name = 'left'; key.shift = true; break; case '[e': key.name = 'clear'; key.shift = true; break; case '[2$': key.name = 'insert'; key.shift = true; break; case '[3$': key.name = 'delete'; key.shift = true; break; case '[5$': key.name = 'pageup'; key.shift = true; break; case '[6$': key.name = 'pagedown'; key.shift = true; break; case '[7$': key.name = 'home'; key.shift = true; break; case '[8$': key.name = 'end'; key.shift = true; break; case 'Oa': key.name = 'up'; key.ctrl = true; break; case 'Ob': key.name = 'down'; key.ctrl = true; break; case 'Oc': key.name = 'right'; key.ctrl = true; break; case 'Od': key.name = 'left'; key.ctrl = true; break; case 'Oe': key.name = 'clear'; key.ctrl = true; break; case '[2^': key.name = 'insert'; key.ctrl = true; break; case '[3^': key.name = 'delete'; key.ctrl = true; break; case '[5^': key.name = 'pageup'; key.ctrl = true; break; case '[6^': key.name = 'pagedown'; key.ctrl = true; break; case '[7^': key.name = 'home'; key.ctrl = true; break; case '[8^': key.name = 'end'; key.ctrl = true; break; /* misc. */ case '[Z': key.name = 'tab'; key.shift = true; break; default: key.name = 'undefined'; break; } } else if (s.length > 1 && s[0] !== '\x1b') { // Got a longer-than-one string of characters. // Probably a paste, since it wasn't a control sequence. Array.prototype.forEach.call(s, function(c) { emitKey(stream, c); }); return; } // Don't emit a key if no name was found if (key.name === undefined) { key = undefined; } if (s.length === 1) { ch = s; } if (key || ch) { stream.emit('keypress', ch, key); } } /** * moves the cursor to the x and y coordinate on the given stream */ function cursorTo(stream, x, y) { if (typeof x !== 'number' && typeof y !== 'number') return; if (typeof x !== 'number') throw new Error("Can't set cursor row without also setting it's column"); if (typeof y !== 'number') { stream.write('\x1b[' + (x + 1) + 'G'); } else { stream.write('\x1b[' + (y + 1) + ';' + (x + 1) + 'H'); } } exports.cursorTo = cursorTo; /** * moves the cursor relative to its current location */ function moveCursor(stream, dx, dy) { if (dx < 0) { stream.write('\x1b[' + (-dx) + 'D'); } else if (dx > 0) { stream.write('\x1b[' + dx + 'C'); } if (dy < 0) { stream.write('\x1b[' + (-dy) + 'A'); } else if (dy > 0) { stream.write('\x1b[' + dy + 'B'); } } exports.moveCursor = moveCursor; /** * clears the current line the cursor is on: * -1 for left of the cursor * +1 for right of the cursor * 0 for the entire line */ function clearLine(stream, dir) { if (dir < 0) { // to the beginning stream.write('\x1b[1K'); } else if (dir > 0) { // to the end stream.write('\x1b[0K'); } else { // entire line stream.write('\x1b[2K'); } } exports.clearLine = clearLine; /** * clears the screen from the current position of the cursor down */ function clearScreenDown(stream) { stream.write('\x1b[0J'); } exports.clearScreenDown = clearScreenDown; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Query String Utilities var QueryString = exports; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function charCode(c) { return c.charCodeAt(0); } // a safe fast alternative to decodeURIComponent QueryString.unescapeBuffer = function(s, decodeSpaces) { var out = new Buffer(s.length); var state = 'CHAR'; // states: CHAR, HEX0, HEX1 var n, m, hexchar; for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) { var c = s.charCodeAt(inIndex); switch (state) { case 'CHAR': switch (c) { case charCode('%'): n = 0; m = 0; state = 'HEX0'; break; case charCode('+'): if (decodeSpaces) c = charCode(' '); // pass thru default: out[outIndex++] = c; break; } break; case 'HEX0': state = 'HEX1'; hexchar = c; if (charCode('0') <= c && c <= charCode('9')) { n = c - charCode('0'); } else if (charCode('a') <= c && c <= charCode('f')) { n = c - charCode('a') + 10; } else if (charCode('A') <= c && c <= charCode('F')) { n = c - charCode('A') + 10; } else { out[outIndex++] = charCode('%'); out[outIndex++] = c; state = 'CHAR'; break; } break; case 'HEX1': state = 'CHAR'; if (charCode('0') <= c && c <= charCode('9')) { m = c - charCode('0'); } else if (charCode('a') <= c && c <= charCode('f')) { m = c - charCode('a') + 10; } else if (charCode('A') <= c && c <= charCode('F')) { m = c - charCode('A') + 10; } else { out[outIndex++] = charCode('%'); out[outIndex++] = hexchar; out[outIndex++] = c; break; } out[outIndex++] = 16 * n + m; break; } } // TODO support returning arbitrary buffers. return out.slice(0, outIndex - 1); }; QueryString.unescape = function(s, decodeSpaces) { return QueryString.unescapeBuffer(s, decodeSpaces).toString(); }; QueryString.escape = function(str) { return encodeURIComponent(str); }; var stringifyPrimitive = function(v) { switch (typeof v) { case 'string': return v; case 'boolean': return v ? 'true' : 'false'; case 'number': return isFinite(v) ? v : ''; default: return ''; } }; QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) { sep = sep || '&'; eq = eq || '='; if (obj === null) { obj = undefined; } if (typeof obj === 'object') { return Object.keys(obj).map(function(k) { var ks = QueryString.escape(stringifyPrimitive(k)) + eq; if (Array.isArray(obj[k])) { return obj[k].map(function(v) { return ks + QueryString.escape(stringifyPrimitive(v)); }).join(sep); } else { return ks + QueryString.escape(stringifyPrimitive(obj[k])); } }).join(sep); } if (!name) return ''; return QueryString.escape(stringifyPrimitive(name)) + eq + QueryString.escape(stringifyPrimitive(obj)); }; // Parse a key=val string. QueryString.parse = QueryString.decode = function(qs, sep, eq, options) { sep = sep || '&'; eq = eq || '='; var obj = {}; if (typeof qs !== 'string' || qs.length === 0) { return obj; } var regexp = /\+/g; qs = qs.split(sep); var maxKeys = 1000; if (options && typeof options.maxKeys === 'number') { maxKeys = options.maxKeys; } var len = qs.length; // maxKeys <= 0 means that we should not limit keys count if (maxKeys > 0 && len > maxKeys) { len = maxKeys; } for (var i = 0; i < len; ++i) { var x = qs[i].replace(regexp, '%20'), idx = x.indexOf(eq), kstr, vstr, k, v; if (idx >= 0) { kstr = x.substr(0, idx); vstr = x.substr(idx + 1); } else { kstr = x; vstr = ''; } try { k = decodeURIComponent(kstr); v = decodeURIComponent(vstr); } catch (e) { k = QueryString.unescape(kstr, true); v = QueryString.unescape(vstr, true); } if (!hasOwnProperty(obj, k)) { obj[k] = v; } else if (Array.isArray(obj[k])) { obj[k].push(v); } else { obj[k] = [obj[k], v]; } } return obj; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // Microsoft grants you the right to use these script files for the sole purpose of either: (i) interacting through your browser with the Microsoft website, subject to the website's terms of use; or (ii) using the files as included with a Microsoft product subject to that product's license terms. Microsoft reserves all other rights to the files not expressly granted by Microsoft, whether by implication, estoppel or otherwise. The notices and licenses below are for informational purposes only. // Punycode.js // Copyright 2011 Mathias Bynens // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /*! http://mths.be/punycode v1.2.0 by @mathias */ ;(function(root) { /** * The `punycode` object. * @name punycode * @type Object */ var punycode, /** Detect free variables `define`, `exports`, `module` and `require` */ freeDefine = typeof define == 'function' && typeof define.amd == 'object' && define.amd && define, freeExports = typeof exports == 'object' && exports, freeModule = typeof module == 'object' && module, freeRequire = typeof require == 'function' && require, /** Highest positive signed 32-bit float value */ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 /** Bootstring parameters */ base = 36, tMin = 1, tMax = 26, skew = 38, damp = 700, initialBias = 72, initialN = 128, // 0x80 delimiter = '-', // '\x2D' /** Regular expressions */ regexPunycode = /^xn--/, regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators /** Error messages */ errors = { 'overflow': 'Overflow: input needs wider integers to process', 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 'invalid-input': 'Invalid input' }, /** Convenience shortcuts */ baseMinusTMin = base - tMin, floor = Math.floor, stringFromCharCode = String.fromCharCode, /** Temporary variable */ key; /*--------------------------------------------------------------------------*/ /** * A generic error utility function. * @private * @param {String} type The error type. * @returns {Error} Throws a `RangeError` with the applicable error message. */ function error(type) { throw RangeError(errors[type]); } /** * A generic `Array#map` utility function. * @private * @param {Array} array The array to iterate over. * @param {Function} callback The function that gets called for every array * item. * @returns {Array} A new array of values returned by the callback function. */ function map(array, fn) { var length = array.length; while (length--) { array[length] = fn(array[length]); } return array; } /** * A simple `Array#map`-like wrapper to work with domain name strings. * @private * @param {String} domain The domain name. * @param {Function} callback The function that gets called for every * character. * @returns {Array} A new string of characters returned by the callback * function. */ function mapDomain(string, fn) { return map(string.split(regexSeparators), fn).join('.'); } /** * Creates an array containing the decimal code points of each Unicode * character in the string. While JavaScript uses UCS-2 internally, * this function will convert a pair of surrogate halves (each of which * UCS-2 exposes as separate characters) into a single code point, * matching UTF-16. * @see `punycode.ucs2.encode` * @see * @memberOf punycode.ucs2 * @name decode * @param {String} string The Unicode input string (UCS-2). * @returns {Array} The new array of code points. */ function ucs2decode(string) { var output = [], counter = 0, length = string.length, value, extra; while (counter < length) { value = string.charCodeAt(counter++); if ((value & 0xF800) == 0xD800 && counter < length) { // high surrogate, and there is a next character extra = string.charCodeAt(counter++); if ((extra & 0xFC00) == 0xDC00) { // low surrogate output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); } else { output.push(value, extra); } } else { output.push(value); } } return output; } /** * Creates a string based on an array of decimal code points. * @see `punycode.ucs2.decode` * @memberOf punycode.ucs2 * @name encode * @param {Array} codePoints The array of decimal code points. * @returns {String} The new Unicode string (UCS-2). */ function ucs2encode(array) { return map(array, function(value) { var output = ''; if (value > 0xFFFF) { value -= 0x10000; output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); value = 0xDC00 | value & 0x3FF; } output += stringFromCharCode(value); return output; }).join(''); } /** * Converts a basic code point into a digit/integer. * @see `digitToBasic()` * @private * @param {Number} codePoint The basic (decimal) code point. * @returns {Number} The numeric value of a basic code point (for use in * representing integers) in the range `0` to `base - 1`, or `base` if * the code point does not represent a value. */ function basicToDigit(codePoint) { return codePoint - 48 < 10 ? codePoint - 22 : codePoint - 65 < 26 ? codePoint - 65 : codePoint - 97 < 26 ? codePoint - 97 : base; } /** * Converts a digit/integer into a basic code point. * @see `basicToDigit()` * @private * @param {Number} digit The numeric value of a basic code point. * @returns {Number} The basic code point whose value (when used for * representing integers) is `digit`, which needs to be in the range * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is * used; else, the lowercase form is used. The behavior is undefined * if flag is non-zero and `digit` has no uppercase form. */ function digitToBasic(digit, flag) { // 0..25 map to ASCII a..z or A..Z // 26..35 map to ASCII 0..9 return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); } /** * Bias adaptation function as per section 3.4 of RFC 3492. * http://tools.ietf.org/html/rfc3492#section-3.4 * @private */ function adapt(delta, numPoints, firstTime) { var k = 0; delta = firstTime ? floor(delta / damp) : delta >> 1; delta += floor(delta / numPoints); for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { delta = floor(delta / baseMinusTMin); } return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); } /** * Converts a basic code point to lowercase if `flag` is falsy, or to * uppercase if `flag` is truthy. The code point is unchanged if it's * caseless. The behavior is undefined if `codePoint` is not a basic code * point. * @private * @param {Number} codePoint The numeric value of a basic code point. * @returns {Number} The resulting basic code point. */ function encodeBasic(codePoint, flag) { codePoint -= (codePoint - 97 < 26) << 5; return codePoint + (!flag && codePoint - 65 < 26) << 5; } /** * Converts a Punycode string of ASCII code points to a string of Unicode * code points. * @memberOf punycode * @param {String} input The Punycode string of ASCII code points. * @returns {String} The resulting string of Unicode code points. */ function decode(input) { // Don't use UCS-2 var output = [], inputLength = input.length, out, i = 0, n = initialN, bias = initialBias, basic, j, index, oldi, w, k, digit, t, length, /** Cached calculation results */ baseMinusT; // Handle the basic code points: let `basic` be the number of input code // points before the last delimiter, or `0` if there is none, then copy // the first basic code points to the output. basic = input.lastIndexOf(delimiter); if (basic < 0) { basic = 0; } for (j = 0; j < basic; ++j) { // if it's not a basic code point if (input.charCodeAt(j) >= 0x80) { error('not-basic'); } output.push(input.charCodeAt(j)); } // Main decoding loop: start just after the last delimiter if any basic code // points were copied; start at the beginning otherwise. for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { // `index` is the index of the next character to be consumed. // Decode a generalized variable-length integer into `delta`, // which gets added to `i`. The overflow checking is easier // if we increase `i` as we go, then subtract off its starting // value at the end to obtain `delta`. for (oldi = i, w = 1, k = base; /* no condition */; k += base) { if (index >= inputLength) { error('invalid-input'); } digit = basicToDigit(input.charCodeAt(index++)); if (digit >= base || digit > floor((maxInt - i) / w)) { error('overflow'); } i += digit * w; t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (digit < t) { break; } baseMinusT = base - t; if (w > floor(maxInt / baseMinusT)) { error('overflow'); } w *= baseMinusT; } out = output.length + 1; bias = adapt(i - oldi, out, oldi == 0); // `i` was supposed to wrap around from `out` to `0`, // incrementing `n` each time, so we'll fix that now: if (floor(i / out) > maxInt - n) { error('overflow'); } n += floor(i / out); i %= out; // Insert `n` at position `i` of the output output.splice(i++, 0, n); } return ucs2encode(output); } /** * Converts a string of Unicode code points to a Punycode string of ASCII * code points. * @memberOf punycode * @param {String} input The string of Unicode code points. * @returns {String} The resulting Punycode string of ASCII code points. */ function encode(input) { var n, delta, handledCPCount, basicLength, bias, j, m, q, k, t, currentValue, output = [], /** `inputLength` will hold the number of code points in `input`. */ inputLength, /** Cached calculation results */ handledCPCountPlusOne, baseMinusT, qMinusT; // Convert the input in UCS-2 to Unicode input = ucs2decode(input); // Cache the length inputLength = input.length; // Initialize the state n = initialN; delta = 0; bias = initialBias; // Handle the basic code points for (j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue < 0x80) { output.push(stringFromCharCode(currentValue)); } } handledCPCount = basicLength = output.length; // `handledCPCount` is the number of code points that have been handled; // `basicLength` is the number of basic code points. // Finish the basic string - if it is not empty - with a delimiter if (basicLength) { output.push(delimiter); } // Main encoding loop: while (handledCPCount < inputLength) { // All non-basic code points < n have been handled already. Find the next // larger one: for (m = maxInt, j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue >= n && currentValue < m) { m = currentValue; } } // Increase `delta` enough to advance the decoder's state to , // but guard against overflow handledCPCountPlusOne = handledCPCount + 1; if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { error('overflow'); } delta += (m - n) * handledCPCountPlusOne; n = m; for (j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue < n && ++delta > maxInt) { error('overflow'); } if (currentValue == n) { // Represent delta as a generalized variable-length integer for (q = delta, k = base; /* no condition */; k += base) { t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (q < t) { break; } qMinusT = q - t; baseMinusT = base - t; output.push( stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) ); q = floor(qMinusT / baseMinusT); } output.push(stringFromCharCode(digitToBasic(q, 0))); bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); delta = 0; ++handledCPCount; } } ++delta; ++n; } return output.join(''); } /** * Converts a Punycode string representing a domain name to Unicode. Only the * Punycoded parts of the domain name will be converted, i.e. it doesn't * matter if you call it on a string that has already been converted to * Unicode. * @memberOf punycode * @param {String} domain The Punycode domain name to convert to Unicode. * @returns {String} The Unicode representation of the given Punycode * string. */ function toUnicode(domain) { return mapDomain(domain, function(string) { return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string; }); } /** * Converts a Unicode string representing a domain name to Punycode. Only the * non-ASCII parts of the domain name will be converted, i.e. it doesn't * matter if you call it with a domain that's already in ASCII. * @memberOf punycode * @param {String} domain The domain name to convert, as a Unicode string. * @returns {String} The Punycode representation of the given domain name. */ function toASCII(domain) { return mapDomain(domain, function(string) { return regexNonASCII.test(string) ? 'xn--' + encode(string) : string; }); } /*--------------------------------------------------------------------------*/ /** Define the public API */ punycode = { /** * A string representing the current Punycode.js version number. * @memberOf punycode * @type String */ 'version': '1.2.0', /** * An object of methods to convert from JavaScript's internal character * representation (UCS-2) to decimal Unicode code points, and back. * @see * @memberOf punycode * @type Object */ 'ucs2': { 'decode': ucs2decode, 'encode': ucs2encode }, 'decode': decode, 'encode': encode, 'toASCII': toASCII, 'toUnicode': toUnicode }; /** Expose `punycode` */ if (freeExports) { if (freeModule && freeModule.exports == freeExports) { // in Node.js or Ringo 0.8+ freeModule.exports = punycode; } else { // in Narwhal or Ringo 0.7- for (key in punycode) { punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); } } } else if (freeDefine) { // via curl.js or RequireJS define('punycode', punycode); } else { // in a browser or Rhino root.punycode = punycode; } }(this)); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var isWindows = process.platform === 'win32'; var util = require('util'); // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } function getDirNameForUNC(path) { if (path.length <= 2) { return path[0]; //return only one slash in that case } //skip slashes at the begining: var i; for (i = 0; i < path.length; ++i) { if(!isCharAtIndexSlash(path, i)) { break; } } var prefix = path.substr(0, i); path = path.substr(i); if (path.indexOf('\\') === -1 && path.indexOf('/') === -1) { //path of type "\\\\server"" return prefix[0]; } //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i > -1; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } if (i === -1) { //path contains only slashes: return prefix[0]; //return one slash. } //loop over the string backwards, until the previoud slash: for (; i >=0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } if (i == -1) { //path of type "\\server\\" return path.substr(0, i); //return slashes at the begining without the first 2. ""///server" -->"/" } var dir = path.substr(0, i); if (dir.indexOf('\\') == -1 && dir.indexOf('/') == -1) { //the path of type "//server/share/" --> retrun with the share return prefix + path; } //in case the path is of type \\\\server\\share\\folder1\\ we need to return \\\server\\share\\ with the slashes at the end //unlike in the case of \\\\server\\share\\folder1\\folder2 we need to return \\\\server\\share\\folder1 without slashes at the end var dir = path.substr(0, i + 1); var foldersCount = 0; for (i = 0; i < dir.length ; i++) { if (!isCharAtIndexSlash(dir, i)) { foldersCount++; while (!isCharAtIndexSlash(dir, i)) { i++; } } } if (foldersCount > 2) { //need to remove slashes at the end for (i = dir.length - 1; isCharAtIndexSlash(dir, i); --i); dir = dir.substr(0, i + 1); } return prefix + dir; } function getDirNameForPartialPath(path) { var prefix; //path of type "../foo/bar" if ((path.length > 2) && (path[0] === '.') && (path[1] === '.') && isCharAtIndexSlash(path, 2)) { prefix = path.substr(0, 3); path = path.substr(3); } //path of type "./foo/bar" or "..foo/bar" else if (((path[0] === '.') && isCharAtIndexSlash(path, 1)) || (path[0] === '.') && (path[1] === '.')) { prefix = path.substr(0, 2); path = path.substr(2); } //path of type ".foo/bar" or "/foo/bar" else if ((path[0] === '.') || (isCharAtIndexSlash(path, 0) && !isCharAtIndexSlash(path, 1))) { prefix = path.substr(0, 1); path = path.substr(1); } else { return '.'; } //if we got here, path is of type "foo/bar/baz..." var i; //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i >= 0; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } //loop over the string backwards, to remove the current folder from the path: for (; i >= 0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } //remove one slash at the end if there's any. //make sure not to remove the first slash in case prefix is empty if (isCharAtIndexSlash(path, i + 1)) { --i; } //actually remove the tail and return the dir: path = path.substr(0, i); //in case path is empty if prefix was "../" needs to return "./", if prefix was "./" needs to return "." if ((path.length == 0) && (prefix.length > 1)) { prefix = prefix.substr(0, prefix.length - 1); } if (prefix) { return prefix + path; } return path; } function getDirNameForDrive(path) { if ((path.length === 2) && (path.charAt(1) === ':')) { return path; } var prefix; if (path.length > 2 && (path.charAt(1) === ':')) { //there's a suffix to the drive name: var endOfDriveInd = isCharAtIndexSlash(path, 2) ? 3 : 2; prefix = path.substr(0, endOfDriveInd); //only the drive name path = path.substr(endOfDriveInd); } else { return '.'; } if (path.indexOf('\\') === -1 && path.indexOf('/') === -1) { //path of type "c:\\file" // return only the drive return prefix; } var i; //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i >=0; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } if (i == -1) { //path contains only slashes: return prefix; //return only the drive } //loop over the string backwards, to remove the current folder from the path: for (; i >=0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } //remove one slash at the end if there's any: if(isCharAtIndexSlash(path, i)) { --i; } //actually remove the tail and return the dir: path = path.substr(0, i + 1); return prefix + path; } function isCharAtIndexSlash(path, index) { return (path.charAt(index) === '/' || path.charAt(index) === '\\'); } // receives path and returns the file name without slashes: function getFileNameFromPath(path) { path = getTailStrFromPathHelper('/', path); path = getTailStrFromPathHelper('\\', path); return path; } //returns the last string in path after the last given delimiter: function getTailStrFromPathHelper(delimiter, path) { if (path.lastIndexOf(delimiter) != -1) { path = path.split(delimiter); var i; for (i = path.length -1; i >=0; --i) { if(path[i] != '' && path[i] != '\\' && path[i] != '/') { break; } } path = path.slice(0, i + 1); return path[i]; } return path; } if (isWindows) { // Regex to split a windows path into three parts: [*, device, slash, // tail] windows-only var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; // Regex to split the tail part of the above into [*, dir, basename, ext] var splitTailRe = /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; // Function to split a filename into [root, dir, basename, ext] // windows version var splitPath = function(filename) { // Separate device+slash from tail var result = splitDeviceRe.exec(filename), device = (result[1] || '') + (result[2] || ''), tail = result[3] || ''; // Split the tail into dir, basename and extension var result2 = splitTailRe.exec(tail), dir = result2[1], basename = result2[2], ext = result2[3]; return [device, dir, basename, ext]; }; var normalizeUNCRoot = function(device) { return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); }; // path.resolve([from ...], to) // windows version exports.resolve = function() { var resolvedDevice = '', resolvedTail = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1; i--) { var path; if (i >= 0) { path = arguments[i]; } else if (!resolvedDevice) { path = process.cwd(); } else { // Windows has the concept of drive-specific current working // directories. If we've resolved a drive letter but not yet an // absolute path, get cwd for that drive. We're sure the device is not // an unc path at this points, because unc paths are always absolute. path = process.env['=' + resolvedDevice]; // Verify that a drive-local cwd was found and that it actually points // to our drive. If not, default to the drive's root. if (!path || path.substr(0, 3).toLowerCase() !== resolvedDevice.toLowerCase() + '\\') { path = resolvedDevice + '\\'; } } // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } var result = splitDeviceRe.exec(path), device = result[1] || '', isUnc = device && device.charAt(1) !== ':', isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute tail = result[3]; if (device && resolvedDevice && device.toLowerCase() !== resolvedDevice.toLowerCase()) { // This path points to another device so it is not applicable continue; } if (!resolvedDevice) { resolvedDevice = device; } if (!resolvedAbsolute) { resolvedTail = tail + '\\' + resolvedTail; resolvedAbsolute = isAbsolute; } if (resolvedDevice && resolvedAbsolute) { break; } } // Convert slashes to backslashes when `resolvedDevice` points to an UNC // root. Also squash multiple slashes into a single one where appropriate. if (isUnc) { resolvedDevice = normalizeUNCRoot(resolvedDevice); } // At this point the path should be resolved to a full absolute path, // but handle relative paths to be safe (might happen when process.cwd() // fails) // Normalize the tail path function f(p) { return !!p; } resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/).filter(f), !resolvedAbsolute).join('\\'); return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || '.'; }; // windows version exports.normalize = function(path) { var result = splitDeviceRe.exec(path), device = result[1] || '', isUnc = device && device.charAt(1) !== ':', isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute tail = result[3], trailingSlash = /[\\\/]$/.test(tail); // Normalize the tail path tail = normalizeArray(tail.split(/[\\\/]+/).filter(function(p) { return !!p; }), !isAbsolute).join('\\'); if (!tail && !isAbsolute) { tail = '.'; } if (tail && trailingSlash) { tail += '\\'; } // Convert slashes to backslashes when `device` points to an UNC root. // Also squash multiple slashes into a single one where appropriate. if (isUnc) { device = normalizeUNCRoot(device); } return device + (isAbsolute ? '\\' : '') + tail; }; // windows version exports.join = function() { function f(p) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; } var paths = Array.prototype.filter.call(arguments, f); var joined = paths.join('\\'); // Make sure that the joined path doesn't start with two slashes, because // normalize() will mistake it for an UNC path then. // // This step is skipped when it is very clear that the user actually // intended to point at an UNC path. This is assumed when the first // non-empty string arguments starts with exactly two slashes followed by // at least one more non-slash character. // // Note that for normalize() to treat a path as an UNC path it needs to // have at least 2 components, so we don't filter for that here. // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: // path.join('//server', 'share') -> '\\\\server\\share\') if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { joined = joined.replace(/^[\\\/]{2,}/, '\\'); } return exports.normalize(joined); }; // path.relative(from, to) // it will solve the relative path from 'from' to 'to', for instance: // from = 'C:\\orandea\\test\\aaa' // to = 'C:\\orandea\\impl\\bbb' // The output of the function should be: '..\\..\\impl\\bbb' // windows version exports.relative = function(from, to) { from = exports.resolve(from); to = exports.resolve(to); // windows is not case sensitive var lowerFrom = from.toLowerCase(); var lowerTo = to.toLowerCase(); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var toParts = trim(to.split('\\')); var lowerFromParts = trim(lowerFrom.split('\\')); var lowerToParts = trim(lowerTo.split('\\')); var length = Math.min(lowerFromParts.length, lowerToParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (lowerFromParts[i] !== lowerToParts[i]) { samePartsLength = i; break; } } if (samePartsLength == 0) { return to; } var outputParts = []; for (var i = samePartsLength; i < lowerFromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('\\'); }; exports.sep = '\\'; exports.delimiter = ';'; } else /* posix */ { // Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = path.charAt(0) === '/', trailingSlash = path.substr(-1) === '/'; // Normalize the path path = normalizeArray(path.split('/').filter(function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(paths.filter(function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; // path.relative(from, to) // posix version exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.sep = '/'; exports.delimiter = ':'; } exports.dirname = function(path) { if (!isWindows) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { // No dirname whatsoever return '.'; } if (dir) { // It has a dirname, strip trailing slash dir = dir.substr(0, dir.length - 1); } return root + dir; } //code below changed from original Node // 1. handle the case of path.length = 1. if (path.length === 1) { if (isCharAtIndexSlash(path, 0)) { return path; } else { return '.'; } } // 2. handle the case of local drive: d:\\aa\\bb var firstChar = path.charAt(0); if ((firstChar <= 'Z' && firstChar >= 'A') || (firstChar <= 'z' && firstChar >= 'a')){ return getDirNameForDrive(path); } if (path.length > 1) { // 3. handle the case of UNC: \\\\server\\share\\folder if (isCharAtIndexSlash(path, 0) && isCharAtIndexSlash(path, 1)) { return getDirNameForUNC(path); } // 3. handle the case of partial path: /aa/bb/cc return getDirNameForPartialPath(path); } // 5. no dir return '.'; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { //code changed from original Node if (!isWindows) { return splitPath(path)[3]; } path = getFileNameFromPath(path); var indDot = path.lastIndexOf('.'); path = (0 >= indDot) || (path === '..') ? '' : path.substr(indDot); return path; }; exports.exists = util.deprecate(function(path, callback) { require('fs').exists(path, callback); }, 'path.exists is now called `fs.exists`.'); exports.existsSync = util.deprecate(function(path) { return require('fs').existsSync(path); }, 'path.existsSync is now called `fs.existsSync`.'); if (isWindows) { exports._makeLong = function(path) { // Note: this will *probably* throw somewhere. if (typeof path !== 'string') return path; if (!path) { return ''; } var resolvedPath = exports.resolve(path); if (/^[a-zA-Z]\:\\/.test(resolvedPath)) { // path is local filesystem path, which needs to be converted // to long UNC path. return '\\\\?\\' + resolvedPath; } else if (/^\\\\[^?.]/.test(resolvedPath)) { // path is network UNC path, which needs to be converted // to long UNC path. return '\\\\?\\UNC\\' + resolvedPath.substring(2); } return path; }; } else { exports._makeLong = function(path) { return path; }; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var binding = process.binding('os'); var util = require('util'); exports.endianness = binding.getEndianness; exports.hostname = binding.getHostname; exports.loadavg = binding.getLoadAvg; exports.uptime = binding.getUptime; exports.freemem = binding.getFreeMem; exports.totalmem = binding.getTotalMem; exports.cpus = binding.getCPUs; exports.type = binding.getOSType; exports.release = binding.getOSRelease; exports.networkInterfaces = binding.getInterfaceAddresses; exports.arch = function() { return process.arch; }; exports.platform = function() { return process.platform; }; exports.tmpdir = function() { return process.env.TMPDIR || process.env.TMP || process.env.TEMP || (process.platform === 'win32' ? 'c:\\windows\\temp' : '/tmp'); }; exports.tmpDir = exports.tmpdir; exports.getNetworkInterfaces = util.deprecate(function() { return exports.networkInterfaces(); }, 'getNetworkInterfaces is now called `os.networkInterfaces`.'); exports.EOL = process.platform === 'win32' ? '\r\n' : '\n'; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var events = require('events'); var stream = require('stream'); var timers = require('timers'); var util = require('util'); var assert = require('assert'); var cares; var cluster; function noop() {} // constructor for lazy loading function createPipe() { var Pipe = process.binding('pipe_wrap').Pipe; return new Pipe(); } // constructor for lazy loading function createTCP() { var TCP = process.binding('tcp_wrap').TCP; return new TCP(); } function createHandle(fd) { var tty = process.binding('tty_wrap'); var type = tty.guessHandleType(fd); if (type === 'PIPE') return createPipe(); if (type === 'TCP') return createTCP(); throw new TypeError('Unsupported fd type: ' + type); } var debug; if (process.env.NODE_DEBUG && /net/.test(process.env.NODE_DEBUG)) { var pid = process.pid; debug = function(x) { // if console is not set up yet, then skip this. if (!console.error) return; console.error('NET: %d', pid, util.format.apply(util, arguments).slice(0, 500)); }; } else { debug = function() { }; } function isPipeName(s) { return typeof s === 'string' && toNumber(s) === false; } exports.createServer = function() { return new Server(arguments[0], arguments[1]); }; // Target API: // // var s = net.connect({port: 80, host: 'google.com'}, function() { // ... // }); // // There are various forms: // // connect(options, [cb]) // connect(port, [host], [cb]) // connect(path, [cb]); // exports.connect = exports.createConnection = function() { var args = normalizeConnectArgs(arguments); var s = new Socket(args[0]); return Socket.prototype.connect.apply(s, args); }; // Returns an array [options] or [options, cb] // It is the same as the argument of Socket.prototype.connect(). function normalizeConnectArgs(args) { var options = {}; if (typeof args[0] === 'object') { // connect(options, [cb]) options = args[0]; } else if (isPipeName(args[0])) { // connect(path, [cb]); options.path = args[0]; } else { // connect(port, [host], [cb]) options.port = args[0]; if (typeof args[1] === 'string') { options.host = args[1]; } } var cb = args[args.length - 1]; return (typeof cb === 'function') ? [options, cb] : [options]; } exports._normalizeConnectArgs = normalizeConnectArgs; // called when creating new Socket, or when re-using a closed Socket function initSocketHandle(self) { self.destroyed = false; self.errorEmitted = false; self.bytesRead = 0; self._bytesDispatched = 0; // Handle creation may be deferred to bind() or connect() time. if (self._handle) { self._handle.owner = self; self._handle.onread = onread; } } function Socket(options) { if (!(this instanceof Socket)) return new Socket(options); this._connecting = false; this._handle = null; switch (typeof options) { case 'number': options = { fd: options }; // Legacy interface. break; case 'undefined': options = {}; break; } stream.Duplex.call(this, options); if (options.handle) { this._handle = options.handle; // private } else if (typeof options.fd !== 'undefined') { this._handle = createHandle(options.fd); this._handle.open(options.fd); this.readable = options.readable !== false; this.writable = options.writable !== false; } else { // these will be set once there is a connection this.readable = this.writable = false; } this.onend = null; // shut down the socket when we're finished with it. this.on('finish', onSocketFinish); this.on('_socketEnd', onSocketEnd); initSocketHandle(this); this._pendingData = null; this._pendingEncoding = ''; // handle strings directly this._writableState.decodeStrings = false; // default to *not* allowing half open sockets this.allowHalfOpen = options && options.allowHalfOpen || false; // if we have a handle, then start the flow of data into the // buffer. if not, then this will happen when we connect if (this._handle && options.readable !== false) this.read(0); } util.inherits(Socket, stream.Duplex); // the user has called .end(), and all the bytes have been // sent out to the other side. // If allowHalfOpen is false, or if the readable side has // ended already, then destroy. // If allowHalfOpen is true, then we need to do a shutdown, // so that only the writable side will be cleaned up. function onSocketFinish() { // If still connecting - defer handling 'finish' until 'connect' will happen if (this._connecting) { debug('osF: not yet connected'); return this.once('connect', onSocketFinish); } debug('onSocketFinish'); if (!this.readable || this._readableState.ended) { debug('oSF: ended, destroy', this._readableState); return this.destroy(); } debug('oSF: not ended, call shutdown()'); // otherwise, just shutdown, or destroy() if not possible if (!this._handle || !this._handle.shutdown) return this.destroy(); var shutdownReq = this._handle.shutdown(); if (!shutdownReq) return this._destroy(errnoException(process._errno, 'shutdown')); shutdownReq.oncomplete = afterShutdown; } function afterShutdown(status, handle, req) { var self = handle.owner; debug('afterShutdown destroyed=%j', self.destroyed, self._readableState); // callback may come after call to destroy. if (self.destroyed) return; if (self._readableState.ended) { debug('readableState ended, destroying'); self.destroy(); } else { self.once('_socketEnd', self.destroy); } } // the EOF has been received, and no more bytes are coming. // if the writable side has ended already, then clean everything // up. function onSocketEnd() { // XXX Should not have to do as much crap in this function. // ended should already be true, since this is called *after* // the EOF errno and onread has eof'ed debug('onSocketEnd', this._readableState); this._readableState.ended = true; if (this._readableState.endEmitted) { this.readable = false; } else { this.once('end', function() { this.readable = false; }); this.read(0); } if (!this.allowHalfOpen) { this.write = writeAfterFIN; this.destroySoon(); } } // Provide a better error message when we call end() as a result // of the other side sending a FIN. The standard 'write after end' // is overly vague, and makes it seem like the user's code is to blame. function writeAfterFIN(chunk, encoding, cb) { if (typeof encoding === 'function') { cb = encoding; encoding = null; } var er = new Error('This socket has been ended by the other party'); er.code = 'EPIPE'; var self = this; // TODO: defer error events consistently everywhere, not just the cb self.emit('error', er); if (typeof cb === 'function') { process.nextTick(function() { cb(er); }); } } exports.Socket = Socket; exports.Stream = Socket; // Legacy naming. Socket.prototype.read = function(n) { if (n === 0) return stream.Readable.prototype.read.call(this, n); this.read = stream.Readable.prototype.read; this._consuming = true; return this.read(n); }; Socket.prototype.listen = function() { debug('socket.listen'); var self = this; self.on('connection', arguments[0]); listen(self, null, null, null); }; Socket.prototype.setTimeout = function(msecs, callback) { if (msecs > 0 && !isNaN(msecs) && isFinite(msecs)) { timers.enroll(this, msecs); timers._unrefActive(this); if (callback) { this.once('timeout', callback); } } else if (msecs === 0) { timers.unenroll(this); if (callback) { this.removeListener('timeout', callback); } } }; Socket.prototype._onTimeout = function() { debug('_onTimeout'); this.emit('timeout'); }; Socket.prototype.setNoDelay = function(enable) { // backwards compatibility: assume true when `enable` is omitted if (this._handle && this._handle.setNoDelay) this._handle.setNoDelay(typeof enable === 'undefined' ? true : !!enable); }; Socket.prototype.setKeepAlive = function(setting, msecs) { if (this._handle && this._handle.setKeepAlive) this._handle.setKeepAlive(setting, ~~(msecs / 1000)); }; Socket.prototype.address = function() { if (this._handle && this._handle.getsockname) { return this._handle.getsockname(); } return null; }; Object.defineProperty(Socket.prototype, 'readyState', { get: function() { if (this._connecting) { return 'opening'; } else if (this.readable && this.writable) { return 'open'; } else if (this.readable && !this.writable) { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; } else { return 'closed'; } } }); Object.defineProperty(Socket.prototype, 'bufferSize', { get: function() { if (this._handle) { return this._handle.writeQueueSize + this._writableState.length; } } }); // Just call handle.readStart until we have enough in the buffer Socket.prototype._read = function(n) { debug('_read'); if (this._connecting || !this._handle) { debug('_read wait for connection'); this.once('connect', this._read.bind(this, n)); } else if (!this._handle.reading) { // not already reading, start the flow debug('Socket._read readStart'); this._handle.reading = true; var r = this._handle.readStart(); if (r) this._destroy(errnoException(process._errno, 'read')); } }; Socket.prototype.end = function(data, encoding) { stream.Duplex.prototype.end.call(this, data, encoding); this.writable = false; DTRACE_NET_STREAM_END(this); // just in case we're waiting for an EOF. if (this.readable && !this._readableState.endEmitted) this.read(0); return; }; Socket.prototype.destroySoon = function() { if (this.writable) this.end(); if (this._writableState.finished) this.destroy(); else this.once('finish', this.destroy); }; Socket.prototype._destroy = function(exception, cb) { debug('destroy'); var self = this; function fireErrorCallbacks() { if (cb) cb(exception); if (exception && !self.errorEmitted) { process.nextTick(function() { self.emit('error', exception); }); self.errorEmitted = true; } }; if (this.destroyed) { debug('already destroyed, fire error callbacks'); fireErrorCallbacks(); return; } self._connecting = false; this.readable = this.writable = false; timers.unenroll(this); debug('close'); if (this._handle) { if (this !== process.stderr) debug('close handle'); var isException = exception ? true : false; this._handle.close(function() { debug('emit close'); self.emit('close', isException); }); this._handle.onread = noop; this._handle = null; } fireErrorCallbacks(); this.destroyed = true; if (this.server) { COUNTER_NET_SERVER_CONNECTION_CLOSE(this); debug('has server'); this.server._connections--; if (this.server._emitCloseIfDrained) { this.server._emitCloseIfDrained(); } } }; Socket.prototype.destroy = function(exception) { debug('destroy', exception); this._destroy(exception); }; // This function is called whenever the handle gets a // buffer, or when there's an error reading. function onread(buffer, offset, length) { var handle = this; var self = handle.owner; assert(handle === self._handle, 'handle != self._handle'); timers._unrefActive(self); var end = offset + length; debug('onread', process._errno, offset, length, end); if (buffer) { debug('got data'); // read success. // In theory (and in practice) calling readStop right now // will prevent this from being called again until _read() gets // called again. // if we didn't get any bytes, that doesn't necessarily mean EOF. // wait for the next one. if (offset === end) { debug('not any data, keep waiting'); return; } // if it's not enough data, we'll just call handle.readStart() // again right away. self.bytesRead += length; // Optimization: emit the original buffer with end points var ret = true; // nadavbar: back ported the DoS fix issue: https://github.com/joyent/node/commit/653d4db71f569ddc87a0bc21f5ecc5ceaf37f932 if (self.ondata && !self._drain_paused) self.ondata(buffer, offset, end); else ret = self.push(buffer.slice(offset, end)); if (handle.reading && !ret) { handle.reading = false; debug('readStop'); var r = handle.readStop(); if (r) self._destroy(errnoException(process._errno, 'read')); } } else if (process._errno == 'EOF') { debug('EOF'); if (self._readableState.length === 0) self.readable = false; if (self.onend) self.once('end', self.onend); // push a null to signal the end of data. self.push(null); // internal end event so that we know that the actual socket // is no longer readable, and we can start the shutdown // procedure. No need to wait for all the data to be consumed. self.emit('_socketEnd'); } else { debug('error', process._errno); // Error self._destroy(errnoException(process._errno, 'read')); } } Socket.prototype._getpeername = function() { if (!this._handle || !this._handle.getpeername) { return {}; } if (!this._peername) { this._peername = this._handle.getpeername(); // getpeername() returns null on error if (this._peername === null) { return {}; } } return this._peername; }; Socket.prototype.__defineGetter__('remoteAddress', function() { return this._getpeername().address; }); Socket.prototype.__defineGetter__('remotePort', function() { return this._getpeername().port; }); Socket.prototype._getsockname = function() { if (!this._handle || !this._handle.getsockname) { return {}; } if (!this._sockname) { this._sockname = this._handle.getsockname(); if (this._sockname === null) { return {}; } } return this._sockname; }; Socket.prototype.__defineGetter__('localAddress', function() { return this._getsockname().address; }); Socket.prototype.__defineGetter__('localPort', function() { return this._getsockname().port; }); Socket.prototype.write = function(chunk, encoding, cb) { if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) throw new TypeError('invalid data'); return stream.Duplex.prototype.write.apply(this, arguments); }; Socket.prototype._write = function(data, encoding, cb) { // If we are still connecting, then buffer this for later. // The Writable logic will buffer up any more writes while // waiting for this one to be done. if (this._connecting) { this._pendingData = data; this._pendingEncoding = encoding; this.once('connect', function() { this._write(data, encoding, cb); }); return; } this._pendingData = null; this._pendingEncoding = ''; timers._unrefActive(this); if (!this._handle) { this._destroy(new Error('This socket is closed.'), cb); return false; } var enc = Buffer.isBuffer(data) ? 'buffer' : encoding; var writeReq = createWriteReq(this._handle, data, enc); if (!writeReq || typeof writeReq !== 'object') return this._destroy(errnoException(process._errno, 'write'), cb); writeReq.oncomplete = afterWrite; this._bytesDispatched += writeReq.bytes; // If it was entirely flushed, we can write some more right now. // However, if more is left in the queue, then wait until that clears. if (this._handle.writeQueueSize === 0) cb(); else writeReq.cb = cb; }; function createWriteReq(handle, data, encoding) { switch (encoding) { case 'buffer': return handle.writeBuffer(data); case 'utf8': case 'utf-8': return handle.writeUtf8String(data); case 'ascii': return handle.writeAsciiString(data); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return handle.writeUcs2String(data); default: return handle.writeBuffer(new Buffer(data, encoding)); } } Socket.prototype.__defineGetter__('bytesWritten', function() { var bytes = this._bytesDispatched, state = this._writableState, data = this._pendingData, encoding = this._pendingEncoding; state.buffer.forEach(function(el) { if (Buffer.isBuffer(el.chunk)) bytes += el.chunk.length; else bytes += Buffer.byteLength(el.chunk, el.encoding); }); if (data) { if (Buffer.isBuffer(data)) bytes += data.length; else bytes += Buffer.byteLength(data, encoding); } return bytes; }); function afterWrite(status, handle, req) { var self = handle.owner; var state = self._writableState; if (self !== process.stderr && self !== process.stdout) debug('afterWrite', status, req); // callback may come after call to destroy. if (self.destroyed) { debug('afterWrite destroyed'); return; } if (status) { debug('write failure', errnoException(process._errno, 'write')); self._destroy(errnoException(process._errno, 'write'), req.cb); return; } timers._unrefActive(self); if (self !== process.stderr && self !== process.stdout) debug('afterWrite call cb'); if (req.cb) req.cb.call(self); } function connect(self, address, port, addressType, localAddress) { // TODO return promise from Socket.prototype.connect which // wraps _connectReq. assert.ok(self._connecting); if (localAddress) { var r; if (addressType == 6) { r = self._handle.bind6(localAddress); } else { r = self._handle.bind(localAddress); } if (r) { self._destroy(errnoException(process._errno, 'bind')); return; } } var connectReq; if (addressType == 6) { connectReq = self._handle.connect6(address, port); } else if (addressType == 4) { connectReq = self._handle.connect(address, port); } else { connectReq = self._handle.connect(address, afterConnect); } if (connectReq !== null) { connectReq.oncomplete = afterConnect; } else { self._destroy(errnoException(process._errno, 'connect')); } } Socket.prototype.connect = function(options, cb) { if (this.write !== Socket.prototype.write) this.write = Socket.prototype.write; if (typeof options !== 'object') { // Old API: // connect(port, [host], [cb]) // connect(path, [cb]); var args = normalizeConnectArgs(arguments); return Socket.prototype.connect.apply(this, args); } if (this.destroyed) { this._readableState.reading = false; this._readableState.ended = false; this._writableState.ended = false; this._writableState.ending = false; this._writableState.finished = false; this.destroyed = false; this._handle = null; } var self = this; var pipe = !!options.path; if (!this._handle) { this._handle = pipe ? createPipe() : createTCP(); initSocketHandle(this); } if (typeof cb === 'function') { self.once('connect', cb); } timers._unrefActive(this); self._connecting = true; self.writable = true; if (pipe) { connect(self, options.path); } else if (!options.host) { debug('connect: missing host'); connect(self, '127.0.0.1', options.port, 4); } else { var host = options.host; debug('connect: find host ' + host); require('dns').lookup(host, function(err, ip, addressType) { // It's possible we were destroyed while looking this up. // XXX it would be great if we could cancel the promise returned by // the look up. if (!self._connecting) return; if (err) { // net.createConnection() creates a net.Socket object and // immediately calls net.Socket.connect() on it (that's us). // There are no event listeners registered yet so defer the // error event to the next tick. process.nextTick(function() { self.emit('error', err); self._destroy(); }); } else { timers._unrefActive(self); addressType = addressType || 4; // node_net.cc handles null host names graciously but user land // expects remoteAddress to have a meaningful value ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1'); connect(self, ip, options.port, addressType, options.localAddress); } }); } return self; }; Socket.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Socket.prototype.unref = function() { if (this._handle) this._handle.unref(); }; function afterConnect(status, handle, req, readable, writable) { var self = handle.owner; // callback may come after call to destroy if (self.destroyed) { return; } assert(handle === self._handle, 'handle != self._handle'); debug('afterConnect'); assert.ok(self._connecting); self._connecting = false; if (status == 0) { self.readable = readable; self.writable = writable; timers._unrefActive(self); self.emit('connect'); // start the first read, or get an immediate EOF. // this doesn't actually consume any bytes, because len=0. if (readable) self.read(0); } else { self._connecting = false; self._destroy(errnoException(process._errno, 'connect')); } } function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function Server(/* [ options, ] listener */) { if (!(this instanceof Server)) return new Server(arguments[0], arguments[1]); events.EventEmitter.call(this); var self = this; var options; if (typeof arguments[0] == 'function') { options = {}; self.on('connection', arguments[0]); } else { options = arguments[0] || {}; if (typeof arguments[1] == 'function') { self.on('connection', arguments[1]); } } this._connections = 0; Object.defineProperty(this, 'connections', { get: util.deprecate(function() { if (self._usingSlaves) { return null; } return self._connections; }, 'connections property is deprecated. Use getConnections() method'), set: util.deprecate(function(val) { return (self._connections = val); }, 'connections property is deprecated. Use getConnections() method'), configurable: true, enumerable: true }); this._handle = null; this._usingSlaves = false; this._slaves = []; this.allowHalfOpen = options.allowHalfOpen || false; } util.inherits(Server, events.EventEmitter); exports.Server = Server; function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; } var createServerHandle = exports._createServerHandle = function(address, port, addressType, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { var r = 0; // assign handle in listen, and clean up if bind or listen fails var handle; if (typeof fd === 'number' && fd >= 0) { try { handle = createHandle(fd); } catch (e) { // Not a fd we can listen on. This will trigger an error. debug('listen invalid fd=' + fd + ': ' + e.message); process._errno = 'EINVAL'; // hack, callers expect that errno is set return null; } handle.open(fd); handle.readable = true; handle.writable = true; return handle; } else if (port == -1 && addressType == -1) { handle = createPipe(); if (process.platform === 'win32') { var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); if (!isNaN(instances)) { handle.setPendingInstances(instances); } } } else { handle = createTCP(); } if (address || port) { debug('bind to ' + address); if (addressType == 6) { r = handle.bind6(address, port); } else { if (defineSecurityProps) { // Chakra/WP addition if (pipeNameForSecurityDescriptor) { r = handle.bind(address, port, defineSecurityProps, pipeNameForSecurityDescriptor); } else { r = handle.bind(address, port, defineSecurityProps); } } else { r = handle.bind(address, port); } } } if (r) { handle.close(); handle = null; } return handle; }; Server.prototype._listen2 = function (address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { debug('listen2', address, port, addressType, backlog); var self = this; var r = 0; // If there is not yet a handle, we need to create one and bind. // In the case of a server sent via IPC, we don't need to do this. if (!self._handle) { debug('_listen2: create a handle'); self._handle = createServerHandle(address, port, addressType, fd, defineSecurityProps, pipeNameForSecurityDescriptor, pipeNameForSecurityDescriptor); if (!self._handle) { var error = errnoException(process._errno, 'listen'); process.nextTick(function() { self.emit('error', error); }); return; } } else { debug('_listen2: have a handle already'); } self._handle.onconnection = onconnection; self._handle.owner = self; // Use a backlog of 512 entries. We pass 511 to the listen() call because // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); // which will thus give us a backlog of 512 entries. r = self._handle.listen(backlog || 511); if (r) { var ex = errnoException(process._errno, 'listen'); self._handle.close(); self._handle = null; process.nextTick(function() { self.emit('error', ex); }); return; } // generate connection key, this should be unique to the connection this._connectionKey = addressType + ':' + address + ':' + port; process.nextTick(function() { self.emit('listening'); }); }; function listen(self, address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { if (!cluster) cluster = require('cluster'); if (cluster.isMaster) { self._listen2(address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor); return; } cluster._getServer(self, address, port, addressType, fd, function(handle) { // Some operating systems (notably OS X and Solaris) don't report EADDRINUSE // errors right away. libuv mimics that behavior for the sake of platform // consistency but that means we have have a socket on our hands that is // not actually bound. That's why we check if the actual port matches what // we requested and if not, raise an error. The exception is when port == 0 // because that means "any random port". if (port && handle.getsockname && port != handle.getsockname().port) { self.emit('error', errnoException('EADDRINUSE', 'bind')); return; } self._handle = handle; self._listen2(address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor); }); } Server.prototype.listen = function() { var self = this; var lastArg = arguments[arguments.length - 1]; if (typeof lastArg == 'function') { self.once('listening', lastArg); } var port = toNumber(arguments[0]); // The third optional argument is the backlog size. // When the ip is omitted it can be the second argument. var backlog = toNumber(arguments[1]) || toNumber(arguments[2]); var TCP = process.binding('tcp_wrap').TCP; if (arguments.length == 0 || typeof arguments[0] == 'function') { // Bind to a random port. listen(self, '0.0.0.0', 0, null, backlog); } else if (arguments[0] && typeof arguments[0] === 'object') { var h = arguments[0]; if (h._handle) { h = h._handle; } else if (h.handle) { h = h.handle; } if (h instanceof TCP) { self._handle = h; listen(self, null, -1, -1, backlog); } else if (typeof h.fd === 'number' && h.fd >= 0) { listen(self, null, null, null, backlog, h.fd); } else { throw new Error('Invalid listen argument: ' + h); } } else if (isPipeName(arguments[0])) { // UNIX socket or Windows pipe. var pipeName = self._pipeName = arguments[0]; // Chakra/WP addition var defineSecurityProps = false; var pipeNameForSecurityProps = null; var defineSecurityPropsIndex = 1; if (backlog && typeof arguments[defineSecurityPropsIndex] != 'boolean') { defineSecurityPropsIndex = 2; } if (typeof arguments[defineSecurityPropsIndex] == 'boolean') { defineSecurityProps = arguments[defineSecurityPropsIndex]; if (typeof arguments[defineSecurityPropsIndex + 1] == 'string') { pipeNameForSecurityProps = arguments[defineSecurityPropsIndex + 1]; } } // end of Chakra/ WP addition listen(self, pipeName, -1, -1, backlog, null, defineSecurityProps, pipeNameForSecurityProps); } else if (typeof arguments[1] == 'undefined' || typeof arguments[1] == 'function' || typeof arguments[1] == 'number') { // The first argument is the port, no IP given. listen(self, '0.0.0.0', port, 4, backlog); } else { // The first argument is the port, the second an IP. // Chakra/Threshold addition. if (arguments[1] === '127.0.0.1') { listen(self, '127.0.0.1', port, 4, backlog); } else if (arguments[1] === '[::1]' || arguments[1] === '::1') { listen(self, '::1', port, 6, backlog); } else { // End of Chakra/Threshold addition. require('dns').lookup(arguments[1], function(err, ip, addressType) { if (err) { self.emit('error', err); } else { listen(self, ip || '0.0.0.0', port, ip ? addressType : 4, backlog); } }); } } return self; }; Server.prototype.address = function() { if (this._handle && this._handle.getsockname) { return this._handle.getsockname(); } else if (this._pipeName) { return this._pipeName; } else { return null; } }; function onconnection(clientHandle) { var handle = this; var self = handle.owner; debug('onconnection'); if (!clientHandle) { self.emit('error', errnoException(process._errno, 'accept')); return; } if (self.maxConnections && self._connections >= self.maxConnections) { clientHandle.close(); return; } var socket = new Socket({ handle: clientHandle, allowHalfOpen: self.allowHalfOpen }); socket.readable = socket.writable = true; self._connections++; socket.server = self; DTRACE_NET_SERVER_CONNECTION(socket); COUNTER_NET_SERVER_CONNECTION(socket); self.emit('connection', socket); } Server.prototype.getConnections = function(cb) { function end(err, connections) { process.nextTick(function() { cb(err, connections); }); } if (!this._usingSlaves) { return end(null, this._connections); } // Poll slaves var left = this._slaves.length, total = this._connections; function oncount(err, count) { if (err) { left = -1; return end(err); } total += count; if (--left === 0) return end(null, total); } this._slaves.forEach(function(slave) { slave.getConnections(oncount); }); }; Server.prototype.close = function(cb) { function onSlaveClose() { if (--left !== 0) return; self._connections = 0; self._emitCloseIfDrained(); } if (!this._handle) { // Throw error. Follows net_legacy behaviour. throw new Error('Not running'); } if (cb) { this.once('close', cb); } this._handle.close(); this._handle = null; if (this._usingSlaves) { var self = this, left = this._slaves.length; // Increment connections to be sure that, even if all sockets will be closed // during polling of slaves, `close` event will be emitted only once. this._connections++; // Poll slaves this._slaves.forEach(function(slave) { slave.close(onSlaveClose); }); } else { this._emitCloseIfDrained(); } return this; }; Server.prototype._emitCloseIfDrained = function() { debug('SERVER _emitCloseIfDrained'); var self = this; if (self._handle || self._connections) { debug('SERVER handle? %j connections? %d', !!self._handle, self._connections); return; } process.nextTick(function() { debug('SERVER: emit close'); self.emit('close'); }); }; Server.prototype.listenFD = util.deprecate(function(fd, type) { return this.listen({ fd: fd }); }, 'listenFD is deprecated. Use listen({fd: }).'); Server.prototype._setupSlave = function(socketList) { this._usingSlaves = true; this._slaves.push(socketList); }; Server.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Server.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // TODO: isIP should be moved to the DNS code. Putting it here now because // this is what the legacy system did. exports.isIP = function() { cares = cares || process.binding('cares_wrap'); return cares.isIP.apply(this, arguments); } exports.isIPv4 = function(input) { return exports.isIP(input) === 4; }; exports.isIPv6 = function(input) { return exports.isIP(input) === 6; }; if (process.platform === 'win32') { var simultaneousAccepts; exports._setSimultaneousAccepts = function(handle) { if (typeof handle === 'undefined') { return; } if (typeof simultaneousAccepts === 'undefined') { simultaneousAccepts = (process.env.NODE_MANY_ACCEPTS && process.env.NODE_MANY_ACCEPTS !== '0'); } if (handle._simultaneousAccepts !== simultaneousAccepts) { handle.setSimultaneousAccepts(simultaneousAccepts); handle._simultaneousAccepts = simultaneousAccepts; } }; } else { exports._setSimultaneousAccepts = function(handle) {}; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // code was taken from node's module.js and then changed to use the native require var nativerequire = process.binding('nativerequire_wrap'); var NativeModule = require('native_module'); var assert = require('assert').ok; var path = require('path'); var fs; // we have to do this in order to solve the crazy dependancy issues that happend when _stream_readable is required before stream - this happend in several of node tests // the original module.js does not suffer from this since it always loads fs which loads stream var stream = require('stream'); // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all // modules in thier own context. // we don't support context load for now Module._cache = {}; Module._extensions = {}; var modulePaths = []; Module.globalPaths = []; if (process.ischakra) { Module._useScriptsSerialization = false; } // Cache which can be loaded to disk of the relative location of one module to another. function PathCache() { if (!(this instanceof PathCache)) { return new PathCache(); } // true if changed since set. this._dirty = false; // the file the cache read/writes from/to, if this cache originated from a file. this._cacheFile = undefined; // the key --> filename mappings for this cache. this._mappings = {}; // insert a key --> filename mapping. this.insert = function(key, filename) { this._mappings[key] = filename; this._dirty = true; } // remove a key --> filename mapping. this.remove = function(key) { delete this._mappings[key]; this._dirty = true; } // lookup a key --> filename mapping. this.find = function(key) { var filename = this._mappings[key]; if (!filename) { return undefined; } return filename; } // loads the cache from a file. If the file doesn't exist or is corrupt, starts from a clean state. this.load = function(filename) { this._cacheFile = filename; this._dirty = false; this._mappings = {}; if (!nativerequire.fileExistsNotDir(filename)) { return; } fs = fs || require('fs'); try { this._mappings = JSON.parse(fs.readFileSync(filename)); } catch (ex) { console.error('Failed to read json paths cache from file:', filename, ex); } } // Can be used for optimization for saving the native require paths cache // And then used in load. Note that this method is async where load is sync this.save = function(filename, cb) { cb = cb || Function(); var self = this; if (!this._dirty) { return cb(null); } this._dirty = false; if (this._cacheFile !== filename) { return cb(new Error('path cache file changed.')); } fs = fs || require('fs'); return fs.writeFile(this._cacheFile, JSON.stringify(this._mappings), function(err) { if (err) { self._dirty = true; } return cb(err); }); } // removes entries of files which does not exist from the path cache // this may be used by modules which saves/loads the path cache in order to trim the cache if it's get large this.validate = function(flush) { var keys = Object.keys(this._mappings); for (var key in keys) { if (!nativerequire.fileExistsNotDir(this._mappings[key])) { this.remove(key); } } if (this._cacheFile && this._dirty && flush) { fs = fs || require('fs'); fs.writeFileSync(this._cacheFile, JSON.stringify(this._mappings)); this._dirty = false; } } this.size = function() { try { return Object.keys(this._mappings).length; } catch (e) { console.error('failed to get path cache size:', e); return 0; } } }; Module._pathCache = new PathCache(); // Write the cache file back to disk according to the count and interval. function periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval) { if (pathCacheSaves-- == 0) { return; } setTimeout(function() { Module._pathCache.save(filename, function(err) { return periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval); }); }, pathCacheSaveInterval); }; // Loads the path cache from predefined location if the caller of node has enabled // a cache filepath + version in Node::Start. // Starting with writes back to disk at 5, 10, and 15s into the process startup to capture startup paths. function loadGlobalPathCache() { var filename = nativerequire.loadCacheFilePath('npc'); if (!filename) { return; } var pathCacheSaves = 3; var pathCacheSaveInterval = 5000; Module._pathCache.load(filename); periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval); } loadGlobalPathCache(); // bootstrap main module. Module.runMain = function () { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback(); }; Module._debug = function () { }; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { Module._debug = function (x) { console.error(x); }; } // We use this alias for the preprocessor that filters it out var debug = Module._debug; // given a module name, and a list of paths to test, returns the first // matching file in the following precedence. // // require("a.") // -> a. // // require("a") // -> a // -> a. // -> a/index. // check if the directory is a package.json dir var packageCache = {}; function readPackage(requestPath) { if (hasOwnProperty(packageCache, requestPath)) { return packageCache[requestPath]; } try { var jsonPath = path.resolve(requestPath, 'package.json'); if (!nativerequire.fileExistsNotDir(jsonPath)) return undefined; var pkg = nativerequire.readJsonPackage(jsonPath); if (!pkg) { throw new Error("Unable to read package, or properties are missing"); } packageCache[requestPath] = pkg; } catch (e) { e.path = jsonPath; e.message = 'Error parsing ' + jsonPath + ': ' + e.message; throw e; } return pkg; } function tryPackage(requestPath, exts) { var pkg = readPackage(requestPath); if (!pkg || !pkg.main) return false; var filename = path.resolve(requestPath, pkg.main); return tryFile(filename) || tryExtensions(filename, exts) || tryExtensions(path.resolve(filename, 'index'), exts); } // In order to minimize unnecessary lstat() calls, // this cache is a list of known-real paths. // Set to an empty object to reset. Module._realpathCache = {}; // check if the file exists and is not a directory function tryFile(requestPath) { if (nativerequire.fileExistsNotDir(requestPath)) { return requestPath; //not using fs.realpathSync(requestPath, Module._realpathCache); like in original code here. We assume that there are no links // as it turn out, this method can blow up the memory } return false; } // given a path check a the file exists with any of the set extensions function tryExtensions(p, exts) { for (var i = 0, EL = exts.length; i < EL; i++) { var filename = tryFile(p + exts[i]); if (filename) { return filename; } } return false; } Module._tryPath = function (request, basePath, trailingSlash, cacheKey, exts) { var filename; if (!trailingSlash) { // try to join the request to the path filename = tryFile(basePath); if (!filename && !trailingSlash) { // try it with each of the extensions filename = tryExtensions(basePath, exts); } } if (!filename) { filename = tryPackage(basePath, exts); } if (!filename) { // try it with each of the extensions at "index" filename = tryExtensions(path.resolve(basePath, 'index'), exts); } if (filename) { Module._pathCache.insert(cacheKey, filename); } return filename; } Module._findInPaths = function (request, paths, trailingSlash, cacheKey, exts) { var filename; for (var i = 0, PL = paths.length; i < PL; i++) { var basePath = path.resolve(paths[i], request); filename = Module._tryPath(request, basePath, trailingSlash, cacheKey, exts); if (filename) { return filename; } } return filename; }; // this function was re-written in order to allow more efficient search of modules // instead of building the paths table with every possibility of '[sub dir]\node_modules' we // built it incremently and insert the folders which we build to the cache until we find the module // the main difference here is that the original code created many strings that weren't needed since // the modules are often found in the higher levels Module._findPath = function (request, paths, parent) { var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { paths = ['']; } var trailingSlash = (request.slice(-1) === '/'); var cacheKey; // cacheKey is only paths or paths & parent paths if such exist if (!parent || !parent.paths) { cacheKey = JSON.stringify({ request: request, paths: paths }); } else { cacheKey = JSON.stringify({ request: request, parent: parent.paths, paths: paths }); } var filename = Module._pathCache.find(cacheKey); if (filename) { return filename; } filename = Module._findInPaths(request, paths, trailingSlash, cacheKey, exts); if (filename) { return filename; } if (parent) { if (!parent.paths) { parent.paths = []; } else { var filename = Module._findInPaths(request, parent.paths, trailingSlash, cacheKey, exts); if (filename) { return filename; } } var pathToStartFrom = parent.paths.length > 0 ? parent.paths[parent.paths.length - 1] : path.resolve(path.dirname(parent.filename)); var index = pathToStartFrom.length; if (process.platform == 'win32') { pathToStartFrom = pathToStartFrom.replace(/\//g, '\\') } while (index > 0) { var basePath; // TODO: do not check node_modules within node_modules? if (index == pathToStartFrom.length) { basePath = pathToStartFrom + path.sep + 'node_modules'; } else { basePath = pathToStartFrom.substring(0, index) + path.sep + 'node_modules'; } parent.paths.push(basePath); filename = Module._tryPath(request, path.resolve(basePath, request), trailingSlash, cacheKey, exts); if (filename) { return filename; } index = pathToStartFrom.lastIndexOf(path.sep, index - 1); } } filename = Module._findInPaths(request, modulePaths, trailingSlash, cacheKey, exts); if (filename) { return filename; } return filename; }; Module._resolveLookupPaths = function (request, parent) { // if parent is null, this is probably the main module if (!parent) { return [request,[]]; } if (NativeModule.exists(request)) { return [request, []]; } var start = request.substring(0, 2); if (start !== './' && start !== '..') { return [request, []]; } // Is the parent an index module? // We can assume the parent has a valid extension, // as it already has been accepted as a module. var isIndex = /^index\.\w+?$/.test(path.basename(parent.filename)); var parentIdPath = isIndex ? parent.id : path.dirname(parent.id); var id = path.resolve(parentIdPath, request); // make sure require('./path') and require('path') get distinct ids, even // when called from the toplevel js file if (parentIdPath === '.' && id.indexOf('/') === -1) { id = './' + id; } return [id, [path.dirname(parent.filename)]]; }; Module._load = function (request, parent, isMain) { if (parent) { debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id); } var filename; var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } if (NativeModule.exists(filename)) { // REPL is a special case, because it needs the real require. return require(filename); } var module = new Module(filename, parent); if (isMain) { process.mainModule = module; module.id = '.'; } Module._cache[filename] = module; var hadException = true; try { module.load(filename); hadException = false; } finally { if (hadException) { delete Module._cache[filename]; Module._pathCache.validate(true); } } return module.exports; }; Module.require = function require(path, parent) { return Module._load(path, parent); } Module._resolveFilename = function (request, parent) { if (NativeModule.exists(request)) { return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; var filename = Module._findPath(request, paths, parent); if (!filename) { var err = new Error("Cannot find module '" + request + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; } return filename; }; Module.prototype.load = function (filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.paths = Module._nodeModulePaths(path.dirname(filename)); this.filename = filename; var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; }; Module.prototype.require = function (path) { assert(typeof path === 'string', 'path must be a string'); assert(path, 'missing path'); return Module._load(path, this); }; // Resolved path to process.argv[1] will be lazily placed here // (needed for setting breakpoint when called with --debug-brk) var resolvedArgv; // Returns exception if any // this code was mainly taken from compile, we load and compile the js file here using native require Module.prototype._loadJs = function (filename) { var self = this; function require(path) { return self.require(path); } require.resolve = function (request) { return Module._resolveFilename(request, self); }; require.main = process.mainModule; // we throw the same errors that module.js throw, in order to be complaint with module.js Object.defineProperty(require, 'paths', { get: function () { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.'); } }); require.registerExtension = function () { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.'); }; // Enable support to add extra extension types require.extensions = Module._extensions; require.cache = Module._cache; var dirname = path.dirname(filename); var compiledCode; if (process.ischakra && Module._useScriptsSerialization) { compiledCode = nativerequire.require(filename, filename + '.jsbc'); } else { compiledCode = nativerequire.require(filename); } var args = [self.exports, require, self, filename, dirname]; return compiledCode.apply(self.exports, args); }; // Native extension for .js Module._extensions['.js'] = function (module, filename) { module._loadJs(filename); }; function stripBOM(content) { // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) // because the buffer-to-string conversion in `fs.readFileSync()` // translates it to FEFF, the UTF-16 BOM. if (content.charCodeAt(0) === 0xFEFF) { content = content.slice(1); } return content; } // Native extension for .json Module._extensions['.json'] = function (module, filename) { var content = require('fs').readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } }; //Native extension for .node Module._extensions['.node'] = process.dlopen; Module._initPaths = function () { var isWindows = process.platform === 'win32'; if (isWindows) { var homeDir = process.env.USERPROFILE; } else { var homeDir = process.env.HOME; } var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; if (homeDir) { paths.unshift(path.resolve(homeDir, '.node_libraries')); paths.unshift(path.resolve(homeDir, '.node_modules')); } // node.ch specific for now - disable the use of NODE_PATH for security reasons if (!process.disable_node_env_vars) { if (process.env['NODE_PATH']) { var splitter = isWindows ? ';' : ':'; paths = process.env['NODE_PATH'].split(splitter).concat(paths); } } modulePaths = paths; // clone as a read-only copy, for introspection Module.globalPaths = modulePaths.slice(0); }; // 'from' is the __dirname of the module. Module._nodeModulePaths = function (from) { // guarantee that 'from' is absolute. from = path.resolve(from); // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; // yes, '/' works on both, but let's be a little canonical. var joiner = process.platform === 'win32' ? '\\' : '/'; var paths = []; var parts = from.split(splitRe); for (var tip = parts.length - 1; tip >= 0; tip--) { // don't search in .../node_modules/node_modules if (parts[tip] === 'node_modules') continue; var dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner); paths.push(dir); } return paths; }; Module._initPaths(); // backwards compatibility Module.Module = Module; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var NativeModule = require('native_module'); var Script = process.binding('evals').NodeScript; var runInThisContext = Script.runInThisContext; var runInNewContext = Script.runInNewContext; var assert = require('assert').ok; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; if (parent && parent.children) { parent.children.push(this); } this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all // modules in thier own context. if (!process.disable_node_env_vars) { Module._contextLoad = (+process.env['NODE_MODULE_CONTEXTS'] > 0); } Module._cache = {}; Module._pathCache = {}; Module._extensions = {}; var modulePaths = []; Module.globalPaths = []; Module.wrapper = NativeModule.wrapper; Module.wrap = NativeModule.wrap; var path = NativeModule.require('path'); Module._debug = function() {}; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { Module._debug = function(x) { console.error(x); }; } // We use this alias for the preprocessor that filters it out var debug = Module._debug; // given a module name, and a list of paths to test, returns the first // matching file in the following precedence. // // require("a.") // -> a. // // require("a") // -> a // -> a. // -> a/index. function statPath(path) { var fs = NativeModule.require('fs'); try { return fs.statSync(path); } catch (ex) {} return false; } // check if the directory is a package.json dir var packageCache = {}; function readPackage(requestPath) { if (hasOwnProperty(packageCache, requestPath)) { return packageCache[requestPath]; } var fs = NativeModule.require('fs'); try { var jsonPath = path.resolve(requestPath, 'package.json'); var json = fs.readFileSync(jsonPath, 'utf8'); } catch (e) { return false; } try { // nabar: the following line is commented in order to be more memory efficient and disable the package cache // var pkg = packageCache[requestPath] = JSON.parse(json); var pkg = JSON.parse(json); } catch (e) { e.path = jsonPath; e.message = 'Error parsing ' + jsonPath + ': ' + e.message; throw e; } return pkg; } function tryPackage(requestPath, exts) { var pkg = readPackage(requestPath); if (!pkg || !pkg.main) return false; var filename = path.resolve(requestPath, pkg.main); return tryFile(filename) || tryExtensions(filename, exts) || tryExtensions(path.resolve(filename, 'index'), exts); } // In order to minimize unnecessary lstat() calls, // this cache is a list of known-real paths. // Set to an empty object to reset. Module._realpathCache = {}; // check if the file exists and is not a directory function tryFile(requestPath) { var fs = NativeModule.require('fs'); var stats = statPath(requestPath); if (stats && !stats.isDirectory()) { return fs.realpathSync(requestPath, Module._realpathCache); } return false; } // given a path check a the file exists with any of the set extensions function tryExtensions(p, exts) { for (var i = 0, EL = exts.length; i < EL; i++) { var filename = tryFile(p + exts[i]); if (filename) { return filename; } } return false; } Module._findPath = function(request, paths) { var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { paths = ['']; } var trailingSlash = (request.slice(-1) === '/'); var cacheKey = JSON.stringify({request: request, paths: paths}); if (Module._pathCache[cacheKey]) { return Module._pathCache[cacheKey]; } // For each path for (var i = 0, PL = paths.length; i < PL; i++) { var basePath = path.resolve(paths[i], request); var filename; if (!trailingSlash) { // try to join the request to the path filename = tryFile(basePath); if (!filename && !trailingSlash) { // try it with each of the extensions filename = tryExtensions(basePath, exts); } } if (!filename) { filename = tryPackage(basePath, exts); } if (!filename) { // try it with each of the extensions at "index" filename = tryExtensions(path.resolve(basePath, 'index'), exts); } if (filename) { Module._pathCache[cacheKey] = filename; return filename; } } return false; }; // 'from' is the __dirname of the module. Module._nodeModulePaths = function(from) { // guarantee that 'from' is absolute. from = path.resolve(from); // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; // yes, '/' works on both, but let's be a little canonical. var joiner = process.platform === 'win32' ? '\\' : '/'; var paths = []; var parts = from.split(splitRe); for (var tip = parts.length - 1; tip >= 0; tip--) { // don't search in .../node_modules/node_modules if (parts[tip] === 'node_modules') continue; var dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner); paths.push(dir); } return paths; }; Module._resolveLookupPaths = function(request, parent) { if (NativeModule.exists(request)) { return [request, []]; } var start = request.substring(0, 2); if (start !== './' && start !== '..') { var paths = modulePaths; if (parent) { if (!parent.paths) parent.paths = []; paths = parent.paths.concat(paths); } return [request, paths]; } // with --eval, parent.id is not set and parent.filename is null if (!parent || !parent.id || !parent.filename) { // make require('./path/to/foo') work - normally the path is taken // from realpath(__filename) but with eval there is no filename var mainPaths = ['.'].concat(modulePaths); mainPaths = Module._nodeModulePaths('.').concat(mainPaths); return [request, mainPaths]; } // Is the parent an index module? // We can assume the parent has a valid extension, // as it already has been accepted as a module. var isIndex = /^index\.\w+?$/.test(path.basename(parent.filename)); var parentIdPath = isIndex ? parent.id : path.dirname(parent.id); var id = path.resolve(parentIdPath, request); // make sure require('./path') and require('path') get distinct ids, even // when called from the toplevel js file if (parentIdPath === '.' && id.indexOf('/') === -1) { id = './' + id; } debug('RELATIVE: requested:' + request + ' set ID to: ' + id + ' from ' + parent.id); return [id, [path.dirname(parent.filename)]]; }; Module._load = function(request, parent, isMain) { if (parent) { debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id); } var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } if (NativeModule.exists(filename)) { // REPL is a special case, because it needs the real require. if (filename == 'repl') { var replModule = new Module('repl'); replModule._compile(NativeModule.getSource('repl'), 'repl.js'); NativeModule._cache.repl = replModule; return replModule.exports; } debug('load native module ' + request); return NativeModule.require(filename); } var module = new Module(filename, parent); if (isMain) { process.mainModule = module; module.id = '.'; } Module._cache[filename] = module; var hadException = true; try { module.load(filename); hadException = false; } finally { if (hadException) { delete Module._cache[filename]; } } return module.exports; }; Module._resolveFilename = function(request, parent) { if (NativeModule.exists(request)) { return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; // look up the filename first, since that's the cache key. debug('looking for ' + JSON.stringify(id) + ' in ' + JSON.stringify(paths)); var filename = Module._findPath(request, paths); if (!filename) { var err = new Error("Cannot find module '" + request + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; } return filename; }; Module.prototype.load = function(filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.filename = filename; this.paths = Module._nodeModulePaths(path.dirname(filename)); var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; }; Module.prototype.require = function(path) { assert(typeof path === 'string', 'path must be a string'); assert(path, 'missing path'); return Module._load(path, this); }; // Resolved path to process.argv[1] will be lazily placed here // (needed for setting breakpoint when called with --debug-brk) var resolvedArgv; // Returns exception if any Module.prototype._compile = function(content, filename) { var self = this; // remove shebang content = content.replace(/^\#\!.*/, ''); function require(path) { return self.require(path); } require.resolve = function(request) { return Module._resolveFilename(request, self); }; Object.defineProperty(require, 'paths', { get: function() { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.'); }}); require.main = process.mainModule; // Enable support to add extra extension types require.extensions = Module._extensions; require.registerExtension = function() { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.'); }; require.cache = Module._cache; var dirname = path.dirname(filename); if (Module._contextLoad) { if (self.id !== '.') { debug('load submodule'); // not root module var sandbox = {}; for (var k in global) { sandbox[k] = global[k]; } sandbox.require = require; sandbox.exports = self.exports; sandbox.__filename = filename; sandbox.__dirname = dirname; sandbox.module = self; sandbox.global = sandbox; sandbox.root = root; return runInNewContext(content, sandbox, filename, true); } debug('load root module'); // root module global.require = require; global.exports = self.exports; global.__filename = filename; global.__dirname = dirname; global.module = self; return runInThisContext(content, filename, true); } // create wrapper function var wrapper = Module.wrap(content); var compiledWrapper = runInThisContext(wrapper, filename, true); if (global.v8debug) { if (!resolvedArgv) { // we enter the repl if we're not given a filename argument. if (process.argv[1]) { resolvedArgv = Module._resolveFilename(process.argv[1], null); } else { resolvedArgv = 'repl'; } } // Set breakpoint on module start if (filename === resolvedArgv) { global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0); } } var args = [self.exports, require, self, filename, dirname]; return compiledWrapper.apply(self.exports, args); }; function stripBOM(content) { // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) // because the buffer-to-string conversion in `fs.readFileSync()` // translates it to FEFF, the UTF-16 BOM. if (content.charCodeAt(0) === 0xFEFF) { content = content.slice(1); } return content; } // Native extension for .js Module._extensions['.js'] = function(module, filename) { var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); module._compile(stripBOM(content), filename); }; // Native extension for .json Module._extensions['.json'] = function(module, filename) { var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } }; //Native extension for .node Module._extensions['.node'] = process.dlopen; // bootstrap main module. Module.runMain = function() { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback(); }; Module._initPaths = function() { var isWindows = process.platform === 'win32'; if (isWindows) { var homeDir = process.env.USERPROFILE; } else { var homeDir = process.env.HOME; } var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; if (homeDir) { paths.unshift(path.resolve(homeDir, '.node_libraries')); paths.unshift(path.resolve(homeDir, '.node_modules')); } if (!process.disable_node_env_vars) { if (process.env['NODE_PATH']) { var splitter = isWindows ? ';' : ':'; paths = process.env['NODE_PATH'].split(splitter).concat(paths); } } modulePaths = paths; // clone as a read-only copy, for introspection. Module.globalPaths = modulePaths.slice(0); }; // bootstrap repl Module.requireRepl = function() { return Module._load('repl', '.'); }; Module._initPaths(); // backwards compatibility Module.Module = Module; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var tls = require('tls'); var http = require('http'); var util = require('util'); var url = require('url'); var inherits = require('util').inherits; function Server(opts, requestListener) { if (!(this instanceof Server)) return new Server(opts, requestListener); if (process.features.tls_npn && !opts.NPNProtocols) { opts.NPNProtocols = ['http/1.1', 'http/1.0']; } tls.Server.call(this, opts, http._connectionListener); this.httpAllowHalfOpen = false; if (requestListener) { this.addListener('request', requestListener); } this.addListener('clientError', function(err, conn) { conn.destroy(err); }); } inherits(Server, tls.Server); exports.Server = Server; exports.createServer = function(opts, requestListener) { return new Server(opts, requestListener); }; // HTTPS agents. function createConnection(port, host, options) { if (typeof port === 'object') { options = port; } else if (typeof host === 'object') { options = host; } else if (typeof options === 'object') { options = options; } else { options = {}; } if (typeof port === 'number') { options.port = port; } if (typeof host === 'string') { options.host = host; } return tls.connect(options); } function Agent(options) { http.Agent.call(this, options); this.createConnection = createConnection; } inherits(Agent, http.Agent); Agent.prototype.defaultPort = 443; var globalAgent = new Agent(); exports.globalAgent = globalAgent; exports.Agent = Agent; exports.request = function(options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'https:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } options = util._extend({ createConnection: createConnection, defaultPort: 443 }, options); if (typeof options.agent === 'undefined') { if (typeof options.ca === 'undefined' && typeof options.cert === 'undefined' && typeof options.ciphers === 'undefined' && typeof options.key === 'undefined' && typeof options.passphrase === 'undefined' && typeof options.pfx === 'undefined' && typeof options.rejectUnauthorized === 'undefined') { options.agent = globalAgent; } else { options.agent = new Agent(options); } } return new http.ClientRequest(options, cb); }; exports.get = function(options, cb) { var req = exports.request(options, cb); req.end(); return req; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var net = require('net'); var Stream = require('stream'); var url = require('url'); var EventEmitter = require('events').EventEmitter; var FreeList = require('freelist').FreeList; var HTTPParser = process.binding('http_parser').HTTPParser; var assert = require('assert').ok; // an empty buffer for UPGRADE/CONNECT bodyHead compatibility var emptyBuffer = new Buffer(0); var debug; if (process.env.NODE_DEBUG && /http/.test(process.env.NODE_DEBUG)) { debug = function(x) { console.error('HTTP: %s', x); }; } else { debug = function() { }; } function readStart(socket) { if (!socket || !socket._handle || !socket._handle.readStart) return; if (!socket._drain_paused) { socket._handle.readStart(); } } function readStop(socket) { if (!socket || !socket._handle || !socket._handle.readStop) return; socket._handle.readStop(); } // Only called in the slow case where slow means // that the request headers were either fragmented // across multiple TCP packets or too large to be // processed in a single run. This method is also // called to process trailing HTTP headers. function parserOnHeaders(headers, url) { // Once we exceeded headers limit - stop collecting them if (this.maxHeaderPairs <= 0 || this._headers.length < this.maxHeaderPairs) { this._headers = this._headers.concat(headers); } this._url += url; } // info.headers and info.url are set only if .onHeaders() // has not been called for this request. // // info.url is not set for response parsers but that's not // applicable here since all our parsers are request parsers. function parserOnHeadersComplete(info) { var parser = this; var headers = info.headers; var url = info.url; if (!headers) { headers = parser._headers; parser._headers = []; } if (!url) { url = parser._url; parser._url = ''; } parser.incoming = new IncomingMessage(parser.socket); parser.incoming.httpVersionMajor = info.versionMajor; parser.incoming.httpVersionMinor = info.versionMinor; parser.incoming.httpVersion = info.versionMajor + '.' + info.versionMinor; parser.incoming.url = url; var n = headers.length; // If parser.maxHeaderPairs <= 0 - assume that there're no limit if (parser.maxHeaderPairs > 0) { n = Math.min(n, parser.maxHeaderPairs); } for (var i = 0; i < n; i += 2) { var k = headers[i]; var v = headers[i + 1]; parser.incoming._addHeaderLine(k, v); } if (info.method) { // server only parser.incoming.method = info.method; } else { // client only parser.incoming.statusCode = info.statusCode; // CHECKME dead code? we're always a request parser } parser.incoming.upgrade = info.upgrade; var skipBody = false; // response to HEAD or CONNECT if (!info.upgrade) { // For upgraded connections and CONNECT method request, // we'll emit this after parser.execute // so that we can capture the first part of the new protocol skipBody = parser.onIncoming(parser.incoming, info.shouldKeepAlive); } return skipBody; } // XXX This is a mess. // TODO: http.Parser should be a Writable emits request/response events. function parserOnBody(b, start, len) { var parser = this; var stream = parser.incoming; // if the stream has already been removed, then drop it. if (!stream) return; var socket = stream.socket; // pretend this was the result of a stream._read call. if (len > 0 && !stream._dumped) { var slice = b.slice(start, start + len); var ret = stream.push(slice); if (!ret) readStop(socket); } } function parserOnMessageComplete() { var parser = this; var stream = parser.incoming; if (stream) { stream.complete = true; // Emit any trailing headers. var headers = parser._headers; if (headers) { for (var i = 0, n = headers.length; i < n; i += 2) { var k = headers[i]; var v = headers[i + 1]; parser.incoming._addHeaderLine(k, v); } parser._headers = []; parser._url = ''; } if (!stream.upgrade) // For upgraded connections, also emit this after parser.execute stream.push(null); } if (stream && !parser.incoming._pendings.length) { // For emit end event stream.push(null); } if (parser.socket.readable) { // force to read the next incoming message readStart(parser.socket); } } var parsers = new FreeList('parsers', 1000, function() { var parser = new HTTPParser(HTTPParser.REQUEST); parser._headers = []; parser._url = ''; // Only called in the slow case where slow means // that the request headers were either fragmented // across multiple TCP packets or too large to be // processed in a single run. This method is also // called to process trailing HTTP headers. parser.onHeaders = parserOnHeaders; parser.onHeadersComplete = parserOnHeadersComplete; parser.onBody = parserOnBody; parser.onMessageComplete = parserOnMessageComplete; return parser; }); exports.parsers = parsers; var CRLF = '\r\n'; var STATUS_CODES = exports.STATUS_CODES = { 100 : 'Continue', 101 : 'Switching Protocols', 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918 200 : 'OK', 201 : 'Created', 202 : 'Accepted', 203 : 'Non-Authoritative Information', 204 : 'No Content', 205 : 'Reset Content', 206 : 'Partial Content', 207 : 'Multi-Status', // RFC 4918 300 : 'Multiple Choices', 301 : 'Moved Permanently', 302 : 'Moved Temporarily', 303 : 'See Other', 304 : 'Not Modified', 305 : 'Use Proxy', 307 : 'Temporary Redirect', 400 : 'Bad Request', 401 : 'Unauthorized', 402 : 'Payment Required', 403 : 'Forbidden', 404 : 'Not Found', 405 : 'Method Not Allowed', 406 : 'Not Acceptable', 407 : 'Proxy Authentication Required', 408 : 'Request Time-out', 409 : 'Conflict', 410 : 'Gone', 411 : 'Length Required', 412 : 'Precondition Failed', 413 : 'Request Entity Too Large', 414 : 'Request-URI Too Large', 415 : 'Unsupported Media Type', 416 : 'Requested Range Not Satisfiable', 417 : 'Expectation Failed', 418 : 'I\'m a teapot', // RFC 2324 422 : 'Unprocessable Entity', // RFC 4918 423 : 'Locked', // RFC 4918 424 : 'Failed Dependency', // RFC 4918 425 : 'Unordered Collection', // RFC 4918 426 : 'Upgrade Required', // RFC 2817 428 : 'Precondition Required', // RFC 6585 429 : 'Too Many Requests', // RFC 6585 431 : 'Request Header Fields Too Large',// RFC 6585 500 : 'Internal Server Error', 501 : 'Not Implemented', 502 : 'Bad Gateway', 503 : 'Service Unavailable', 504 : 'Gateway Time-out', 505 : 'HTTP Version Not Supported', 506 : 'Variant Also Negotiates', // RFC 2295 507 : 'Insufficient Storage', // RFC 4918 509 : 'Bandwidth Limit Exceeded', 510 : 'Not Extended', // RFC 2774 511 : 'Network Authentication Required' // RFC 6585 }; var connectionExpression = /Connection/i; var transferEncodingExpression = /Transfer-Encoding/i; var closeExpression = /close/i; var chunkExpression = /chunk/i; var contentLengthExpression = /Content-Length/i; var dateExpression = /Date/i; var expectExpression = /Expect/i; var continueExpression = /100-continue/i; var dateCache; function utcDate() { if (!dateCache) { var d = new Date(); dateCache = d.toUTCString(); setTimeout(function() { dateCache = undefined; }, 1000 - d.getMilliseconds()); } return dateCache; } /* Abstract base class for ServerRequest and ClientResponse. */ function IncomingMessage(socket) { Stream.Readable.call(this); // XXX This implementation is kind of all over the place // When the parser emits body chunks, they go in this list. // _read() pulls them out, and when it finds EOF, it ends. this.socket = socket; this.connection = socket; this.httpVersion = null; this.complete = false; this.headers = {}; this.trailers = {}; this.readable = true; this._pendings = []; this._pendingIndex = 0; // request (server) only this.url = ''; this.method = null; // response (client) only this.statusCode = null; this.client = this.socket; // flag for backwards compatibility grossness. this._consuming = false; // flag for when we decide that this message cannot possibly be // read by the user, so there's no point continuing to handle it. this._dumped = false; } util.inherits(IncomingMessage, Stream.Readable); exports.IncomingMessage = IncomingMessage; IncomingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); this.socket.setTimeout(msecs); }; IncomingMessage.prototype.read = function(n) { this._consuming = true; this.read = Stream.Readable.prototype.read; return this.read(n); }; IncomingMessage.prototype._read = function(n) { // We actually do almost nothing here, because the parserOnBody // function fills up our internal buffer directly. However, we // do need to unpause the underlying socket so that it flows. if (!this.socket.readable) this.push(null); else readStart(this.socket); }; // It's possible that the socket will be destroyed, and removed from // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. IncomingMessage.prototype.destroy = function(error) { if (this.socket) this.socket.destroy(error); }; // Add the given (field, value) pair to the message // // Per RFC2616, section 4.2 it is acceptable to join multiple instances of the // same header with a ', ' if the header in question supports specification of // multiple values this way. If not, we declare the first instance the winner // and drop the second. Extended header fields (those beginning with 'x-') are // always joined. IncomingMessage.prototype._addHeaderLine = function(field, value) { var dest = this.complete ? this.trailers : this.headers; field = field.toLowerCase(); switch (field) { // Array headers: case 'set-cookie': if (dest[field] !== undefined) { dest[field].push(value); } else { dest[field] = [value]; } break; // Comma separate. Maybe make these arrays? case 'accept': case 'accept-charset': case 'accept-encoding': case 'accept-language': case 'connection': case 'cookie': case 'pragma': case 'link': case 'www-authenticate': case 'proxy-authenticate': case 'sec-websocket-extensions': case 'sec-websocket-protocol': if (dest[field] !== undefined) { dest[field] += ', ' + value; } else { dest[field] = value; } break; default: if (field.slice(0, 2) == 'x-') { // except for x- if (dest[field] !== undefined) { dest[field] += ', ' + value; } else { dest[field] = value; } } else { // drop duplicates if (dest[field] === undefined) dest[field] = value; } break; } }; // Call this instead of resume() if we want to just // dump all the data to /dev/null IncomingMessage.prototype._dump = function() { if (!this._dumped) { this._dumped = true; if (this.socket.parser) this.socket.parser.incoming = null; this.push(null); readStart(this.socket); this.read(); } }; function OutgoingMessage() { Stream.call(this); this.output = []; this.outputEncodings = []; this.writable = true; this._last = false; this.chunkedEncoding = false; this.shouldKeepAlive = true; this.useChunkedEncodingByDefault = true; this.sendDate = false; this._hasBody = true; this._trailer = ''; this.finished = false; this._hangupClose = false; this.socket = null; this.connection = null; } util.inherits(OutgoingMessage, Stream); exports.OutgoingMessage = OutgoingMessage; OutgoingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); if (!this.socket) { this.once('socket', function(socket) { socket.setTimeout(msecs); }); } else this.socket.setTimeout(msecs); }; // It's possible that the socket will be destroyed, and removed from // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. OutgoingMessage.prototype.destroy = function(error) { if (this.socket) this.socket.destroy(error); else this.once('socket', function(socket) { socket.destroy(error); }); }; // This abstract either writing directly to the socket or buffering it. OutgoingMessage.prototype._send = function(data, encoding) { // This is a shameful hack to get the headers and first body chunk onto // the same packet. Future versions of Node are going to take care of // this at a lower level and in a more general way. if (!this._headerSent) { if (typeof data === 'string') { data = this._header + data; } else { this.output.unshift(this._header); this.outputEncodings.unshift('ascii'); } this._headerSent = true; } return this._writeRaw(data, encoding); }; OutgoingMessage.prototype._writeRaw = function(data, encoding) { if (data.length === 0) { return true; } if (this.connection && this.connection._httpMessage === this && this.connection.writable && !this.connection.destroyed) { // There might be pending data in the this.output buffer. while (this.output.length) { if (!this.connection.writable) { this._buffer(data, encoding); return false; } var c = this.output.shift(); var e = this.outputEncodings.shift(); this.connection.write(c, e); } // Directly write to socket. return this.connection.write(data, encoding); } else if (this.connection && this.connection.destroyed) { // The socket was destroyed. If we're still trying to write to it, // then we haven't gotten the 'close' event yet. return false; } else { // buffer, as long as we're not destroyed. this._buffer(data, encoding); return false; } }; OutgoingMessage.prototype._buffer = function(data, encoding) { if (data.length === 0) return; var length = this.output.length; if (length === 0 || typeof data != 'string') { this.output.push(data); this.outputEncodings.push(encoding); return false; } var lastEncoding = this.outputEncodings[length - 1]; var lastData = this.output[length - 1]; if ((encoding && lastEncoding === encoding) || (!encoding && data.constructor === lastData.constructor)) { this.output[length - 1] = lastData + data; return false; } this.output.push(data); this.outputEncodings.push(encoding); return false; }; OutgoingMessage.prototype._storeHeader = function(firstLine, headers) { // firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n' // in the case of response it is: 'HTTP/1.1 200 OK\r\n' var state = { sentConnectionHeader: false, sentContentLengthHeader: false, sentTransferEncodingHeader: false, sentDateHeader: false, sentExpect: false, messageHeader: firstLine }; var field, value; var self = this; if (headers) { var keys = Object.keys(headers); var isArray = (Array.isArray(headers)); var field, value; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; } else { field = key; value = headers[key]; } if (Array.isArray(value)) { for (var j = 0; j < value.length; j++) { storeHeader(this, state, field, value[j]); } } else { storeHeader(this, state, field, value); } } } // Date header if (this.sendDate == true && state.sentDateHeader == false) { state.messageHeader += 'Date: ' + utcDate() + CRLF; } // Force the connection to close when the response is a 204 No Content or // a 304 Not Modified and the user has set a "Transfer-Encoding: chunked" // header. // // RFC 2616 mandates that 204 and 304 responses MUST NOT have a body but // node.js used to send out a zero chunk anyway to accommodate clients // that don't have special handling for those responses. // // It was pointed out that this might confuse reverse proxies to the point // of creating security liabilities, so suppress the zero chunk and force // the connection to close. var statusCode = this.statusCode; if ((statusCode == 204 || statusCode === 304) && this.chunkedEncoding === true) { debug(statusCode + ' response should not use chunked encoding,' + ' closing connection.'); this.chunkedEncoding = false; this.shouldKeepAlive = false; } // keep-alive logic if (state.sentConnectionHeader === false) { var shouldSendKeepAlive = this.shouldKeepAlive && (state.sentContentLengthHeader || this.useChunkedEncodingByDefault || this.agent); if (shouldSendKeepAlive) { state.messageHeader += 'Connection: keep-alive\r\n'; } else { this._last = true; state.messageHeader += 'Connection: close\r\n'; } } if (state.sentContentLengthHeader == false && state.sentTransferEncodingHeader == false) { if (this._hasBody) { if (this.useChunkedEncodingByDefault) { state.messageHeader += 'Transfer-Encoding: chunked\r\n'; this.chunkedEncoding = true; } else { this._last = true; } } else { // Make sure we don't end the 0\r\n\r\n at the end of the message. this.chunkedEncoding = false; } } this._header = state.messageHeader + CRLF; this._headerSent = false; // wait until the first body chunk, or close(), is sent to flush, // UNLESS we're sending Expect: 100-continue. if (state.sentExpect) this._send(''); }; function storeHeader(self, state, field, value) { // Protect against response splitting. The if statement is there to // minimize the performance impact in the common case. if (/[\r\n]/.test(value)) value = value.replace(/[\r\n]+[ \t]*/g, ''); state.messageHeader += field + ': ' + value + CRLF; if (connectionExpression.test(field)) { state.sentConnectionHeader = true; if (closeExpression.test(value)) { self._last = true; } else { self.shouldKeepAlive = true; } } else if (transferEncodingExpression.test(field)) { state.sentTransferEncodingHeader = true; if (chunkExpression.test(value)) self.chunkedEncoding = true; } else if (contentLengthExpression.test(field)) { state.sentContentLengthHeader = true; } else if (dateExpression.test(field)) { state.sentDateHeader = true; } else if (expectExpression.test(field)) { state.sentExpect = true; } } OutgoingMessage.prototype.setHeader = function(name, value) { if (arguments.length < 2) { throw new Error('`name` and `value` are required for setHeader().'); } if (this._header) { throw new Error('Can\'t set headers after they are sent.'); } var key = name.toLowerCase(); this._headers = this._headers || {}; this._headerNames = this._headerNames || {}; this._headers[key] = value; this._headerNames[key] = name; }; OutgoingMessage.prototype.getHeader = function(name) { if (arguments.length < 1) { throw new Error('`name` is required for getHeader().'); } if (!this._headers) return; var key = name.toLowerCase(); return this._headers[key]; }; OutgoingMessage.prototype.removeHeader = function(name) { if (arguments.length < 1) { throw new Error('`name` is required for removeHeader().'); } if (this._header) { throw new Error('Can\'t remove headers after they are sent.'); } if (!this._headers) return; var key = name.toLowerCase(); delete this._headers[key]; delete this._headerNames[key]; }; OutgoingMessage.prototype._renderHeaders = function() { if (this._header) { throw new Error('Can\'t render headers after they are sent to the client.'); } if (!this._headers) return {}; var headers = {}; var keys = Object.keys(this._headers); for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; headers[this._headerNames[key]] = this._headers[key]; } return headers; }; Object.defineProperty(OutgoingMessage.prototype, 'headersSent', { configurable: true, enumerable: true, get: function() { return !!this._header; } }); OutgoingMessage.prototype.write = function(chunk, encoding) { if (!this._header) { this._implicitHeader(); } if (!this._hasBody) { debug('This type of response MUST NOT have a body. ' + 'Ignoring write() calls.'); return true; } if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) { throw new TypeError('first argument must be a string or Buffer'); } // If we get an empty string or buffer, then just do nothing, and // signal the user to keep writing. if (chunk.length === 0) return true; // TODO(bnoordhuis) Temporary optimization hack, remove in v0.11. We only // want to convert the buffer when we're sending: // // a) Transfer-Encoding chunks, because it lets us pack the chunk header // and the chunk into a single write(), or // // b) the first chunk of a fixed-length request, because it lets us pack // the request headers and the chunk into a single write(). // // Converting to strings is expensive, CPU-wise, but reducing the number // of write() calls more than makes up for that because we're dramatically // reducing the number of TCP roundtrips. if (chunk instanceof Buffer && (this.chunkedEncoding || !this._headerSent)) { chunk = chunk.toString('binary'); encoding = 'binary'; } var len, ret; if (this.chunkedEncoding) { if (typeof(chunk) === 'string' && encoding !== 'hex' && encoding !== 'base64') { len = Buffer.byteLength(chunk, encoding); chunk = len.toString(16) + CRLF + chunk + CRLF; ret = this._send(chunk, encoding); } else { // buffer, or a non-toString-friendly encoding len = chunk.length; this._send(len.toString(16) + CRLF); this._send(chunk, encoding); ret = this._send(CRLF); } } else { ret = this._send(chunk, encoding); } debug('write ret = ' + ret); return ret; }; OutgoingMessage.prototype.addTrailers = function(headers) { this._trailer = ''; var keys = Object.keys(headers); var isArray = (Array.isArray(headers)); var field, value; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; } else { field = key; value = headers[key]; } this._trailer += field + ': ' + value + CRLF; } }; var zero_chunk_buf = new Buffer('\r\n0\r\n'); var crlf_buf = new Buffer('\r\n'); OutgoingMessage.prototype.end = function(data, encoding) { if (this.finished) { return false; } if (!this._header) { this._implicitHeader(); } if (data && !this._hasBody) { debug('This type of response MUST NOT have a body. ' + 'Ignoring data passed to end().'); data = false; } var ret; var hot = this._headerSent === false && (data && data.length > 0) && this.output.length === 0 && this.connection && this.connection.writable && this.connection._httpMessage === this; // The benefits of the hot-path optimization below start to fall // off when the buffer size gets up near 128KB, because the cost // of the copy is more than the cost of the extra write() call. // Switch to the write/end method at that point. Heuristics and // magic numbers are awful, but slow http responses are worse. if (hot && Buffer.isBuffer(data) && data.length > 120 * 1024) hot = false; if (hot) { // Hot path. They're doing // res.writeHead(); // res.end(blah); // HACKY. if (typeof data === 'string') { if (this.chunkedEncoding) { var l = Buffer.byteLength(data, encoding).toString(16); ret = this.connection.write(this._header + l + CRLF + data + '\r\n0\r\n' + this._trailer + '\r\n', encoding); } else { ret = this.connection.write(this._header + data, encoding); } } else if (Buffer.isBuffer(data)) { if (this.chunkedEncoding) { var chunk_size = data.length.toString(16); // Skip expensive Buffer.byteLength() calls; only ISO-8859-1 characters // are allowed in HTTP headers. Therefore: // // this._header.length == Buffer.byteLength(this._header.length) // this._trailer.length == Buffer.byteLength(this._trailer.length) // var header_len = this._header.length; var chunk_size_len = chunk_size.length; var data_len = data.length; var trailer_len = this._trailer.length; var len = header_len + chunk_size_len + 2 + // '\r\n'.length data_len + 5 + // '\r\n0\r\n'.length trailer_len + 2; // '\r\n'.length var buf = new Buffer(len); var off = 0; buf.write(this._header, off, header_len, 'ascii'); off += header_len; buf.write(chunk_size, off, chunk_size_len, 'ascii'); off += chunk_size_len; crlf_buf.copy(buf, off); off += 2; data.copy(buf, off); off += data_len; zero_chunk_buf.copy(buf, off); off += 5; if (trailer_len > 0) { buf.write(this._trailer, off, trailer_len, 'ascii'); off += trailer_len; } crlf_buf.copy(buf, off); ret = this.connection.write(buf); } else { var header_len = this._header.length; var buf = new Buffer(header_len + data.length); buf.write(this._header, 0, header_len, 'ascii'); data.copy(buf, header_len); ret = this.connection.write(buf); } } else { throw new TypeError('first argument must be a string or Buffer'); } this._headerSent = true; } else if (data) { // Normal body write. ret = this.write(data, encoding); } if (!hot) { if (this.chunkedEncoding) { ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk. } else { // Force a flush, HACK. ret = this._send(''); } } this.finished = true; // There is the first message on the outgoing queue, and we've sent // everything to the socket. debug('outgoing message end.'); if (this.output.length === 0 && this.connection._httpMessage === this) { this._finish(); } return ret; }; OutgoingMessage.prototype._finish = function() { assert(this.connection); if (this instanceof ServerResponse) { DTRACE_HTTP_SERVER_RESPONSE(this.connection); COUNTER_HTTP_SERVER_RESPONSE(); } else { assert(this instanceof ClientRequest); DTRACE_HTTP_CLIENT_REQUEST(this, this.connection); COUNTER_HTTP_CLIENT_REQUEST(); } this.emit('finish'); }; OutgoingMessage.prototype._flush = function() { // This logic is probably a bit confusing. Let me explain a bit: // // In both HTTP servers and clients it is possible to queue up several // outgoing messages. This is easiest to imagine in the case of a client. // Take the following situation: // // req1 = client.request('GET', '/'); // req2 = client.request('POST', '/'); // // When the user does // // req2.write('hello world\n'); // // it's possible that the first request has not been completely flushed to // the socket yet. Thus the outgoing messages need to be prepared to queue // up data internally before sending it on further to the socket's queue. // // This function, outgoingFlush(), is called by both the Server and Client // to attempt to flush any pending messages out to the socket. if (!this.socket) return; var ret; while (this.output.length) { if (!this.socket.writable) return; // XXX Necessary? var data = this.output.shift(); var encoding = this.outputEncodings.shift(); ret = this.socket.write(data, encoding); } if (this.finished) { // This is a queue to the server or client to bring in the next this. this._finish(); } else if (ret) { // This is necessary to prevent https from breaking this.emit('drain'); } }; function ServerResponse(req) { OutgoingMessage.call(this); if (req.method === 'HEAD') this._hasBody = false; this.sendDate = true; if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) { this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te); this.shouldKeepAlive = false; } } util.inherits(ServerResponse, OutgoingMessage); exports.ServerResponse = ServerResponse; ServerResponse.prototype.statusCode = 200; function onServerResponseClose() { // EventEmitter.emit makes a copy of the 'close' listeners array before // calling the listeners. detachSocket() unregisters onServerResponseClose // but if detachSocket() is called, directly or indirectly, by a 'close' // listener, onServerResponseClose is still in that copy of the listeners // array. That is, in the example below, b still gets called even though // it's been removed by a: // // var obj = new events.EventEmitter; // obj.on('event', a); // obj.on('event', b); // function a() { obj.removeListener('event', b) } // function b() { throw "BAM!" } // obj.emit('event'); // throws // // Ergo, we need to deal with stale 'close' events and handle the case // where the ServerResponse object has already been deconstructed. // Fortunately, that requires only a single if check. :-) if (this._httpMessage) this._httpMessage.emit('close'); } ServerResponse.prototype.assignSocket = function(socket) { assert(!socket._httpMessage); socket._httpMessage = this; socket.on('close', onServerResponseClose); this.socket = socket; this.connection = socket; this.emit('socket', socket); this._flush(); }; ServerResponse.prototype.detachSocket = function(socket) { assert(socket._httpMessage == this); socket.removeListener('close', onServerResponseClose); socket._httpMessage = null; this.socket = this.connection = null; }; ServerResponse.prototype.writeContinue = function() { this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii'); this._sent100 = true; }; ServerResponse.prototype._implicitHeader = function() { this.writeHead(this.statusCode); }; ServerResponse.prototype.writeHead = function(statusCode) { var reasonPhrase, headers, headerIndex; if (typeof arguments[1] == 'string') { reasonPhrase = arguments[1]; headerIndex = 2; } else { reasonPhrase = STATUS_CODES[statusCode] || 'unknown'; headerIndex = 1; } this.statusCode = statusCode; var obj = arguments[headerIndex]; if (obj && this._headers) { // Slow-case: when progressive API and header fields are passed. headers = this._renderHeaders(); if (Array.isArray(obj)) { // handle array case // TODO: remove when array is no longer accepted var field; for (var i = 0, len = obj.length; i < len; ++i) { field = obj[i][0]; if (headers[field] !== undefined) { obj.push([field, headers[field]]); } } headers = obj; } else { // handle object case var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { var k = keys[i]; if (k) headers[k] = obj[k]; } } } else if (this._headers) { // only progressive api is used headers = this._renderHeaders(); } else { // only writeHead() called headers = obj; } var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' + reasonPhrase + CRLF; if (statusCode === 204 || statusCode === 304 || (100 <= statusCode && statusCode <= 199)) { // RFC 2616, 10.2.5: // The 204 response MUST NOT include a message-body, and thus is always // terminated by the first empty line after the header fields. // RFC 2616, 10.3.5: // The 304 response MUST NOT contain a message-body, and thus is always // terminated by the first empty line after the header fields. // RFC 2616, 10.1 Informational 1xx: // This class of status code indicates a provisional response, // consisting only of the Status-Line and optional headers, and is // terminated by an empty line. this._hasBody = false; } // don't keep alive connections where the client expects 100 Continue // but we sent a final status; they may put extra bytes on the wire. if (this._expect_continue && !this._sent100) { this.shouldKeepAlive = false; } this._storeHeader(statusLine, headers); }; ServerResponse.prototype.writeHeader = function() { this.writeHead.apply(this, arguments); }; // New Agent code. // The largest departure from the previous implementation is that // an Agent instance holds connections for a variable number of host:ports. // Surprisingly, this is still API compatible as far as third parties are // concerned. The only code that really notices the difference is the // request object. // Another departure is that all code related to HTTP parsing is in // ClientRequest.onSocket(). The Agent is now *strictly* // concerned with managing a connection pool. function Agent(options) { EventEmitter.call(this); var self = this; self.options = options || {}; self.requests = {}; self.sockets = {}; self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets; self.on('free', function(socket, host, port, localAddress) { var name = host + ':' + port; if (localAddress) { name += ':' + localAddress; } if (!socket.destroyed && self.requests[name] && self.requests[name].length) { self.requests[name].shift().onSocket(socket); if (self.requests[name].length === 0) { // don't leak delete self.requests[name]; } } else { // If there are no pending requests just destroy the // socket and it will get removed from the pool. This // gets us out of timeout issues and allows us to // default to Connection:keep-alive. socket.destroy(); } }); self.createConnection = net.createConnection; } util.inherits(Agent, EventEmitter); exports.Agent = Agent; Agent.defaultMaxSockets = 5; Agent.prototype.defaultPort = 80; Agent.prototype.addRequest = function(req, host, port, localAddress) { var name = host + ':' + port; if (localAddress) { name += ':' + localAddress; } if (!this.sockets[name]) { this.sockets[name] = []; } if (this.sockets[name].length < this.maxSockets) { // If we are under maxSockets create a new one. req.onSocket(this.createSocket(name, host, port, localAddress, req)); } else { // We are over limit so we'll add it to the queue. if (!this.requests[name]) { this.requests[name] = []; } this.requests[name].push(req); } }; Agent.prototype.createSocket = function(name, host, port, localAddress, req) { var self = this; var options = util._extend({}, self.options); options.port = port; options.host = host; options.localAddress = localAddress; options.servername = host; if (req) { var hostHeader = req.getHeader('host'); if (hostHeader) { options.servername = hostHeader.replace(/:.*$/, ''); } } var s = self.createConnection(options); if (!self.sockets[name]) { self.sockets[name] = []; } this.sockets[name].push(s); var onFree = function() { self.emit('free', s, host, port, localAddress); } s.on('free', onFree); var onClose = function(err) { // This is the only place where sockets get removed from the Agent. // If you want to remove a socket from the pool, just close it. // All socket errors end in a close event anyway. self.removeSocket(s, name, host, port, localAddress); } s.on('close', onClose); var onRemove = function() { // We need this function for cases like HTTP 'upgrade' // (defined by WebSockets) where we need to remove a socket from the pool // because it'll be locked up indefinitely self.removeSocket(s, name, host, port, localAddress); s.removeListener('close', onClose); s.removeListener('free', onFree); s.removeListener('agentRemove', onRemove); } s.on('agentRemove', onRemove); return s; }; Agent.prototype.removeSocket = function(s, name, host, port, localAddress) { if (this.sockets[name]) { var index = this.sockets[name].indexOf(s); if (index !== -1) { this.sockets[name].splice(index, 1); if (this.sockets[name].length === 0) { // don't leak delete this.sockets[name]; } } } if (this.requests[name] && this.requests[name].length) { var req = this.requests[name][0]; // If we have pending requests and a socket gets closed a new one this.createSocket(name, host, port, localAddress, req).emit('free'); } }; var globalAgent = new Agent(); exports.globalAgent = globalAgent; function ClientRequest(options, cb) { var self = this; OutgoingMessage.call(self); self.agent = options.agent === undefined ? globalAgent : options.agent; var defaultPort = options.defaultPort || 80; var port = options.port || defaultPort; var host = options.hostname || options.host || 'localhost'; if (options.setHost === undefined) { var setHost = true; } self.socketPath = options.socketPath; var method = self.method = (options.method || 'GET').toUpperCase(); self.path = options.path || '/'; if (cb) { self.once('response', cb); } if (!Array.isArray(options.headers)) { if (options.headers) { var keys = Object.keys(options.headers); for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; self.setHeader(key, options.headers[key]); } } if (host && !this.getHeader('host') && setHost) { var hostHeader = host; if (port && +port !== defaultPort) { hostHeader += ':' + port; } this.setHeader('Host', hostHeader); } } if (options.auth && !this.getHeader('Authorization')) { //basic auth this.setHeader('Authorization', 'Basic ' + new Buffer(options.auth).toString('base64')); } if (method === 'GET' || method === 'HEAD' || method === 'CONNECT') { self.useChunkedEncodingByDefault = false; } else { self.useChunkedEncodingByDefault = true; } if (Array.isArray(options.headers)) { self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', options.headers); } else if (self.getHeader('expect')) { self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', self._renderHeaders()); } if (self.socketPath) { self._last = true; self.shouldKeepAlive = false; if (options.createConnection) { self.onSocket(options.createConnection(self.socketPath)); } else { self.onSocket(net.createConnection(self.socketPath)); } } else if (self.agent) { // If there is an agent we should default to Connection:keep-alive. self._last = false; self.shouldKeepAlive = true; self.agent.addRequest(self, host, port, options.localAddress); } else { // No agent, default to Connection:close. self._last = true; self.shouldKeepAlive = false; if (options.createConnection) { options.port = port; options.host = host; var conn = options.createConnection(options); } else { var conn = net.createConnection({ port: port, host: host, localAddress: options.localAddress }); } self.onSocket(conn); } self._deferToConnect(null, null, function() { self._flush(); self = null; }); } util.inherits(ClientRequest, OutgoingMessage); exports.ClientRequest = ClientRequest; ClientRequest.prototype._implicitHeader = function() { this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', this._renderHeaders()); }; ClientRequest.prototype.abort = function() { if (this.socket) { // in-progress this.socket.destroy(); } else { // haven't been assigned a socket yet. // this could be more efficient, it could // remove itself from the pending requests this._deferToConnect('destroy', []); } }; function createHangUpError() { var error = new Error('socket hang up'); error.code = 'ECONNRESET'; return error; } // Free the parser and also break any links that it // might have to any other things. // TODO: All parser data should be attached to a // single object, so that it can be easily cleaned // up by doing `parser.data = {}`, which should // be done in FreeList.free. `parsers.free(parser)` // should be all that is needed. function freeParser(parser, req) { if (parser) { parser._headers = []; parser.onIncoming = null; if (parser.socket) { parser.socket.onend = null; parser.socket.ondata = null; parser.socket.parser = null; } parser.socket = null; parser.incoming = null; parsers.free(parser); parser = null; } if (req) { req.parser = null; } } function socketCloseListener() { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP socket close'); req.emit('close'); if (req.res && req.res.readable) { // Socket closed before we emitted 'end' below. req.res.emit('aborted'); var res = req.res; res.on('end', function() { res.emit('close'); }); res.push(null); } else if (!req.res && !req._hadError) { // This socket error fired before we started to // receive a response. The error needs to // fire on the request. req.emit('error', createHangUpError()); req._hadError = true; } // Too bad. That output wasn't getting written. // This is pretty terrible that it doesn't raise an error. // Fixed better in v0.10 if (req.output) req.output.length = 0; if (req.outputEncodings) req.outputEncodings.length = 0; if (parser) { parser.finish(); freeParser(parser, req); } } function socketErrorListener(err) { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP SOCKET ERROR: ' + err.message + '\n' + err.stack); if (req) { req.emit('error', err); // For Safety. Some additional errors might fire later on // and we need to make sure we don't double-fire the error event. req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } function socketOnEnd() { var socket = this; var req = this._httpMessage; var parser = this.parser; if (!req.res) { // If we don't have a response then we know that the socket // ended prematurely and we need to emit an error on the request. req.emit('error', createHangUpError()); req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } function socketOnData(d, start, end) { var socket = this; var req = this._httpMessage; var parser = this.parser; var ret = parser.execute(d, start, end - start); if (ret instanceof Error) { debug('parse error'); freeParser(parser, req); socket.destroy(); req.emit('error', ret); req._hadError = true; } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT var bytesParsed = ret; var res = parser.incoming; req.res = res; socket.ondata = null; socket.onend = null; parser.finish(); // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (EventEmitter.listenerCount(req, eventName) > 0) { req.upgradeOrConnect = true; // detach the socket socket.emit('agentRemove'); socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); socket.unshift(bodyHead); req.emit(eventName, res, socket, emptyBuffer); req.emit('close'); } else { // Got Upgrade header or CONNECT method, but have no handler. socket.destroy(); } freeParser(parser, req); } else if (parser.incoming && parser.incoming.complete && // When the status code is 100 (Continue), the server will // send a final response after this client sends a request // body. So, we must not free the parser. parser.incoming.statusCode !== 100) { freeParser(parser, req); } } // client function parserOnIncomingClient(res, shouldKeepAlive) { var parser = this; var socket = this.socket; var req = socket._httpMessage; // propogate "domain" setting... if (req.domain && !res.domain) { debug('setting "res.domain"'); res.domain = req.domain; } debug('AGENT incoming response!'); if (req.res) { // We already have a response object, this means the server // sent a double response. socket.destroy(); return; } req.res = res; // Responses to CONNECT request is handled as Upgrade. if (req.method === 'CONNECT') { res.upgrade = true; return true; // skip body } // Responses to HEAD requests are crazy. // HEAD responses aren't allowed to have an entity-body // but *can* have a content-length which actually corresponds // to the content-length of the entity-body had the request // been a GET. var isHeadResponse = req.method == 'HEAD'; debug('AGENT isHeadResponse ' + isHeadResponse); if (res.statusCode == 100) { // restart the parser, as this is a continue message. delete req.res; // Clear res so that we don't hit double-responses. req.emit('continue'); return true; } if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) { // Server MUST respond with Connection:keep-alive for us to enable it. // If we've been upgraded (via WebSockets) we also shouldn't try to // keep the connection open. req.shouldKeepAlive = false; } DTRACE_HTTP_CLIENT_RESPONSE(socket, req); COUNTER_HTTP_CLIENT_RESPONSE(); req.res = res; res.req = req; // add our listener first, so that we guarantee socket cleanup res.on('end', responseOnEnd); var handled = req.emit('response', res); // If the user did not listen for the 'response' event, then they // can't possibly read the data, so we ._dump() it into the void // so that the socket doesn't hang there in a paused state. if (!handled) res._dump(); return isHeadResponse; } // client function responseOnEnd() { var res = this; var req = res.req; var socket = req.socket; if (!req.shouldKeepAlive) { if (socket.writable) { debug('AGENT socket.destroySoon()'); socket.destroySoon(); } assert(!socket.writable); } else { debug('AGENT socket keep-alive'); if (req.timeoutCb) { socket.setTimeout(0, req.timeoutCb); req.timeoutCb = null; } socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); // Mark this socket as available, AFTER user-added end // handlers have a chance to run. process.nextTick(function() { socket.emit('free'); }); } } ClientRequest.prototype.onSocket = function(socket) { var req = this; process.nextTick(function() { var parser = parsers.alloc(); req.socket = socket; req.connection = socket; parser.reinitialize(HTTPParser.RESPONSE); parser.socket = socket; parser.incoming = null; req.parser = parser; socket.parser = parser; socket._httpMessage = req; // Setup "drain" propogation. httpSocketSetup(socket); // Propagate headers limit from request object to parser if (typeof req.maxHeadersCount === 'number') { parser.maxHeaderPairs = req.maxHeadersCount << 1; } else { // Set default value because parser may be reused from FreeList parser.maxHeaderPairs = 2000; } socket.on('error', socketErrorListener); socket.ondata = socketOnData; socket.onend = socketOnEnd; socket.on('close', socketCloseListener); parser.onIncoming = parserOnIncomingClient; req.emit('socket', socket); }); }; ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) { // This function is for calls that need to happen once the socket is // connected and writable. It's an important promisy thing for all the socket // calls that happen either now (when a socket is assigned) or // in the future (when a socket gets assigned out of the pool and is // eventually writable). var self = this; var onSocket = function() { if (self.socket.writable) { if (method) { self.socket[method].apply(self.socket, arguments_); } if (cb) { cb(); } } else { self.socket.once('connect', function() { if (method) { self.socket[method].apply(self.socket, arguments_); } if (cb) { cb(); } }); } } if (!self.socket) { self.once('socket', onSocket); } else { onSocket(); } }; ClientRequest.prototype.setTimeout = function(msecs, callback) { if (callback) this.once('timeout', callback); var self = this; function emitTimeout() { self.emit('timeout'); } if (this.socket && this.socket.writable) { if (this.timeoutCb) this.socket.setTimeout(0, this.timeoutCb); this.timeoutCb = emitTimeout; this.socket.setTimeout(msecs, emitTimeout); return; } // Set timeoutCb so that it'll get cleaned up on request end this.timeoutCb = emitTimeout; if (this.socket) { var sock = this.socket; this.socket.once('connect', function() { sock.setTimeout(msecs, emitTimeout); }); return; } this.once('socket', function(sock) { sock.setTimeout(msecs, emitTimeout); }); }; ClientRequest.prototype.setNoDelay = function() { this._deferToConnect('setNoDelay', arguments); }; ClientRequest.prototype.setSocketKeepAlive = function() { this._deferToConnect('setKeepAlive', arguments); }; ClientRequest.prototype.clearTimeout = function(cb) { this.setTimeout(0, cb); }; exports.request = function(options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'http:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } return new ClientRequest(options, cb); }; exports.get = function(options, cb) { var req = exports.request(options, cb); req.end(); return req; }; function ondrain() { if (this._httpMessage) this._httpMessage.emit('drain'); } function httpSocketSetup(socket) { socket.removeListener('drain', ondrain); socket.on('drain', ondrain); } function Server(requestListener) { if (!(this instanceof Server)) return new Server(requestListener); net.Server.call(this, { allowHalfOpen: true }); if (requestListener) { this.addListener('request', requestListener); } // Similar option to this. Too lazy to write my own docs. // http://www.squid-cache.org/Doc/config/half_closed_clients/ // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F this.httpAllowHalfOpen = false; this.addListener('connection', connectionListener); this.addListener('clientError', function(err, conn) { conn.destroy(err); }); this.timeout = 2 * 60 * 1000; } util.inherits(Server, net.Server); Server.prototype.setTimeout = function(msecs, callback) { this.timeout = msecs; if (callback) this.on('timeout', callback); }; exports.Server = Server; exports.createServer = function(requestListener) { return new Server(requestListener); }; function connectionListener(socket) { var self = this; var outgoing = []; var incoming = []; function abortIncoming() { while (incoming.length) { var req = incoming.shift(); req.emit('aborted'); req.emit('close'); } // abort socket._httpMessage ? } function serverSocketCloseListener() { debug('server socket close'); // mark this parser as reusable if (this.parser) freeParser(this.parser); abortIncoming(); } debug('SERVER new http connection'); httpSocketSetup(socket); // If the user has added a listener to the server, // request, or response, then it's their responsibility. // otherwise, destroy on timeout by default if (self.timeout) socket.setTimeout(self.timeout); socket.on('timeout', function() { var req = socket.parser && socket.parser.incoming; var reqTimeout = req && !req.complete && req.emit('timeout', socket); var res = socket._httpMessage; var resTimeout = res && res.emit('timeout', socket); var serverTimeout = self.emit('timeout', socket); if (!reqTimeout && !resTimeout && !serverTimeout) socket.destroy(); }); var parser = parsers.alloc(); parser.reinitialize(HTTPParser.REQUEST); parser.socket = socket; socket.parser = parser; parser.incoming = null; // Propagate headers limit from server instance to parser if (typeof this.maxHeadersCount === 'number') { parser.maxHeaderPairs = this.maxHeadersCount << 1; } else { // Set default value because parser may be reused from FreeList parser.maxHeaderPairs = 2000; } socket.addListener('error', function(e) { self.emit('clientError', e, this); }); socket.ondata = function (d, start, end) { assert(!socket._drain_paused); var ret = parser.execute(d, start, end - start); if (ret instanceof Error) { debug('parse error'); socket.destroy(ret); } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT var bytesParsed = ret; var req = parser.incoming; socket.ondata = null; socket.onend = null; socket.removeListener('close', serverSocketCloseListener); parser.finish(); freeParser(parser, req); // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (EventEmitter.listenerCount(self, eventName) > 0) { socket.unshift(bodyHead); self.emit(eventName, req, req.socket, emptyBuffer); } else { // Got upgrade header or CONNECT method, but have no handler. socket.destroy(); } if (socket._drain_paused) { // onIncoming paused the socket, we should pause the parser as well debug('pause parser'); socket.parser.pause(); } } }; socket.onend = function() { var ret = parser.finish(); if (ret instanceof Error) { debug('parse error'); socket.destroy(ret); return; } if (!self.httpAllowHalfOpen) { abortIncoming(); if (socket.writable) socket.end(); } else if (outgoing.length) { outgoing[outgoing.length - 1]._last = true; } else if (socket._httpMessage) { socket._httpMessage._last = true; } else { if (socket.writable) socket.end(); } }; socket.addListener('close', serverSocketCloseListener); socket._drain_paused = false; function socketOnDrain() { // If we previously paused, then start reading again. if (socket._drain_paused) { socket._drain_paused = false; socket.parser.resume(); socket.resume(); } } socket.on('drain', socketOnDrain); // The following callback is issued after the headers have been read on a // new message. In this callback we setup the response object and pass it // to the user. parser.onIncoming = function(req, shouldKeepAlive) { incoming.push(req); // If the writable end isn't consuming, then stop reading // so that we don't become overwhelmed by a flood of // pipelined requests that may never be resolved. if (!socket._drain_paused && socket._handle) { var needPause = socket._handle.writeQueueSize > 0; if (needPause) { socket._drain_paused = true; // We also need to pause the parser, but don't do that until after // the call to execute, because we may still be processing the last // chunk. socket.pause(); } } var res = new ServerResponse(req); res.shouldKeepAlive = shouldKeepAlive; DTRACE_HTTP_SERVER_REQUEST(req, socket); COUNTER_HTTP_SERVER_REQUEST(); if (socket._httpMessage) { // There are already pending outgoing res, append. outgoing.push(res); } else { res.assignSocket(socket); } // When we're finished writing the response, check if this is the last // respose, if so destroy the socket. res.on('finish', function() { // Usually the first incoming element should be our request. it may // be that in the case abortIncoming() was called that the incoming // array will be empty. assert(incoming.length == 0 || incoming[0] === req); incoming.shift(); // if the user never called req.read(), and didn't pipe() or // .resume() or .on('data'), then we call req._dump() so that the // bytes will be pulled off the wire. if (!req._consuming) req._dump(); res.detachSocket(socket); if (res._last) { socket.destroySoon(); } else { // start sending the next message var m = outgoing.shift(); if (m) { m.assignSocket(socket); } } }); if (req.headers.expect !== undefined && (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) && continueExpression.test(req.headers['expect'])) { res._expect_continue = true; if (EventEmitter.listenerCount(self, 'checkContinue') > 0) { self.emit('checkContinue', req, res); } else { res.writeContinue(); self.emit('request', req, res); } } else { self.emit('request', req, res); } return false; // Not a HEAD response. (Not even a response!) }; } exports._connectionListener = connectionListener; // Legacy Interface function Client(port, host) { if (!(this instanceof Client)) return new Client(port, host); EventEmitter.call(this); host = host || 'localhost'; port = port || 80; this.host = host; this.port = port; this.agent = new Agent({ host: host, port: port, maxSockets: 1 }); } util.inherits(Client, EventEmitter); Client.prototype.request = function(method, path, headers) { var self = this; var options = {}; options.host = self.host; options.port = self.port; if (method[0] === '/') { headers = path; path = method; method = 'GET'; } options.method = method; options.path = path; options.headers = headers; options.agent = self.agent; var c = new ClientRequest(options); c.on('error', function(e) { self.emit('error', e); }); // The old Client interface emitted 'end' on socket end. // This doesn't map to how we want things to operate in the future // but it will get removed when we remove this legacy interface. c.on('socket', function(s) { s.on('end', function() { if (self._decoder) { var ret = self._decoder.end(); if (ret) self.emit('data', ret); } self.emit('end'); }); }); return c; }; exports.Client = util.deprecate(Client, 'http.Client will be removed soon. Do not use it.'); exports.createClient = util.deprecate(function(port, host) { return new Client(port, host); }, 'http.createClient is deprecated. Use `http.request` instead.'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Maintainers, keep in mind that octal literals are not allowed // in strict mode. Use the decimal value and add a comment with // the octal value. Example: // // var mode = 438; /* mode=0666 */ var util = require('util'); var pathModule = require('path'); var binding = process.binding('fs'); var constants = process.binding('constants'); var fs = exports; var Stream = require('stream').Stream; var EventEmitter = require('events').EventEmitter; var Readable = Stream.Readable; var Writable = Stream.Writable; var kMinPoolSpace = 128; var O_APPEND = constants.O_APPEND || 0; var O_CREAT = constants.O_CREAT || 0; var O_DIRECTORY = constants.O_DIRECTORY || 0; var O_EXCL = constants.O_EXCL || 0; var O_NOCTTY = constants.O_NOCTTY || 0; var O_NOFOLLOW = constants.O_NOFOLLOW || 0; var O_RDONLY = constants.O_RDONLY || 0; var O_RDWR = constants.O_RDWR || 0; var O_SYMLINK = constants.O_SYMLINK || 0; var O_SYNC = constants.O_SYNC || 0; var O_TRUNC = constants.O_TRUNC || 0; var O_WRONLY = constants.O_WRONLY || 0; var isWindows = process.platform === 'win32'; var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); function rethrow() { // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and // is fairly slow to generate. var callback; if (DEBUG) { var backtrace = new Error; callback = debugCallback; } else callback = missingCallback; return callback; function debugCallback(err) { if (err) { backtrace.message = err.message; err = backtrace; missingCallback(err); } } function missingCallback(err) { if (err) { if (process.throwDeprecation) throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs else if (!process.noDeprecation) { var msg = 'fs: missing callback ' + (err.stack || err.message); if (process.traceDeprecation) console.trace(msg); else console.error(msg); } } } } function maybeCallback(cb) { return typeof cb === 'function' ? cb : rethrow(); } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { if (typeof cb !== 'function') { return rethrow(); } return function() { return cb.apply(null, arguments); }; } function assertEncoding(encoding) { if (encoding && !Buffer.isEncoding(encoding)) { throw new Error('Unknown encoding: ' + encoding); } } function nullCheck(path, callback) { if (('' + path).indexOf('\u0000') !== -1) { var er = new Error('Path must be a string without null bytes.'); if (!callback) throw er; process.nextTick(function() { callback(er); }); return false; } return true; } fs.Stats = binding.Stats; fs.Stats.prototype._checkModeProperty = function(property) { return ((this.mode & constants.S_IFMT) === property); }; fs.Stats.prototype.isDirectory = function() { return this._checkModeProperty(constants.S_IFDIR); }; fs.Stats.prototype.isFile = function() { return this._checkModeProperty(constants.S_IFREG); }; fs.Stats.prototype.isBlockDevice = function() { return this._checkModeProperty(constants.S_IFBLK); }; fs.Stats.prototype.isCharacterDevice = function() { return this._checkModeProperty(constants.S_IFCHR); }; fs.Stats.prototype.isSymbolicLink = function() { return this._checkModeProperty(constants.S_IFLNK); }; fs.Stats.prototype.isFIFO = function() { return this._checkModeProperty(constants.S_IFIFO); }; fs.Stats.prototype.isSocket = function() { return this._checkModeProperty(constants.S_IFSOCK); }; fs.exists = function(path, callback) { if (!nullCheck(path, cb)) return; binding.stat(pathModule._makeLong(path), cb); function cb(err, stats) { if (callback) callback(err ? false : true); } }; fs.existsSync = function(path) { try { nullCheck(path); binding.stat(pathModule._makeLong(path)); return true; } catch (e) { return false; } }; fs.readFile = function(path, options, callback_) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: null, flag: 'r' }; } else if (typeof options === 'string') { options = { encoding: options, flag: 'r' }; } else if (!options) { options = { encoding: null, flag: 'r' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } var encoding = options.encoding; assertEncoding(encoding); // first, stat the file, so we know the size. var size; var buffer; // single buffer with file data var buffers; // list for when size is unknown var pos = 0; var fd; var flag = options.flag || 'r'; fs.open(path, flag, 438 /*=0666*/, function(er, fd_) { if (er) return callback(er); fd = fd_; fs.fstat(fd, function(er, st) { if (er) return callback(er); size = st.size; if (size === 0) { // the kernel lies about many files. // Go ahead and try to read some bytes. buffers = []; return read(); } buffer = new Buffer(size); read(); }); }); function read() { if (size === 0) { buffer = new Buffer(8192); fs.read(fd, buffer, 0, 8192, -1, afterRead); } else { fs.read(fd, buffer, pos, size - pos, -1, afterRead); } } function afterRead(er, bytesRead) { if (er) { return fs.close(fd, function(er2) { return callback(er); }); } if (bytesRead === 0) { return close(); } pos += bytesRead; if (size !== 0) { if (pos === size) close(); else read(); } else { // unknown size, just read until we don't get bytes. buffers.push(buffer.slice(0, bytesRead)); read(); } } function close() { fs.close(fd, function(er) { if (size === 0) { // collected the data into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (encoding) buffer = buffer.toString(encoding); return callback(er, buffer); }); } }; fs.readFileSync = function(path, options) { if (!options) { options = { encoding: null, flag: 'r' }; } else if (typeof options === 'string') { options = { encoding: options, flag: 'r' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } var encoding = options.encoding; assertEncoding(encoding); var flag = options.flag || 'r'; var fd = fs.openSync(path, flag, 438 /*=0666*/); var size; var threw = true; try { size = fs.fstatSync(fd).size; threw = false; } finally { if (threw) fs.closeSync(fd); } var pos = 0; var buffer; // single buffer with file data var buffers; // list for when size is unknown if (size === 0) { buffers = []; } else { buffer = new Buffer(size); } var done = false; while (!done) { var threw = true; try { if (size !== 0) { var bytesRead = fs.readSync(fd, buffer, pos, size - pos); } else { // the kernel lies about many files. // Go ahead and try to read some bytes. buffer = new Buffer(8192); var bytesRead = fs.readSync(fd, buffer, 0, 8192); if (bytesRead) { buffers.push(buffer.slice(0, bytesRead)); } } threw = false; } finally { if (threw) fs.closeSync(fd); } pos += bytesRead; done = (bytesRead === 0) || (size !== 0 && pos >= size); } fs.closeSync(fd); if (size === 0) { // data was collected into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (encoding) buffer = buffer.toString(encoding); return buffer; }; // Used by binding.open and friends function stringToFlags(flag) { // Only mess with strings if (typeof flag !== 'string') { return flag; } // O_EXCL is mandated by POSIX, Windows supports it too. // Let's add a check anyway, just in case. if (!O_EXCL && ~flag.indexOf('x')) { throw errnoException('ENOSYS', 'fs.open(O_EXCL)'); } switch (flag) { case 'r' : return O_RDONLY; case 'rs' : return O_RDONLY | O_SYNC; case 'r+' : return O_RDWR; case 'rs+' : return O_RDWR | O_SYNC; case 'w' : return O_TRUNC | O_CREAT | O_WRONLY; case 'wx' : // fall through case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL; case 'w+' : return O_TRUNC | O_CREAT | O_RDWR; case 'wx+': // fall through case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL; case 'a' : return O_APPEND | O_CREAT | O_WRONLY; case 'ax' : // fall through case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; case 'a+' : return O_APPEND | O_CREAT | O_RDWR; case 'ax+': // fall through case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL; } throw new Error('Unknown file open flag: ' + flag); } // exported but hidden, only used by test/simple/test-fs-open-flags.js Object.defineProperty(exports, '_stringToFlags', { enumerable: false, value: stringToFlags }); // Yes, the follow could be easily DRYed up but I provide the explicit // list to make the arguments clear. fs.close = function(fd, callback) { binding.close(fd, makeCallback(callback)); }; fs.closeSync = function(fd) { return binding.close(fd); }; function modeNum(m, def) { switch (typeof m) { case 'number': return m; case 'string': return parseInt(m, 8); default: if (def) { return modeNum(def); } else { return undefined; } } } fs.open = function(path, flags, mode, callback) { callback = makeCallback(arguments[arguments.length - 1]); mode = modeNum(mode, 438 /*=0666*/); if (!nullCheck(path, callback)) return; binding.open(pathModule._makeLong(path), stringToFlags(flags), mode, callback); }; fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 438 /*=0666*/); nullCheck(path); return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode); }; fs.read = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, length, position, encoding, callback) var cb = arguments[4], encoding = arguments[3]; assertEncoding(encoding); position = arguments[2]; length = arguments[1]; buffer = new Buffer(length); offset = 0; callback = function(err, bytesRead) { if (!cb) return; var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : ''; (cb)(err, str, bytesRead); }; } function wrapper(err, bytesRead) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback && callback(err, bytesRead || 0, buffer); } binding.read(fd, buffer, offset, length, position, wrapper); }; fs.readSync = function(fd, buffer, offset, length, position) { var legacy = false; if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, length, position, encoding, callback) legacy = true; var encoding = arguments[3]; assertEncoding(encoding); position = arguments[2]; length = arguments[1]; buffer = new Buffer(length); offset = 0; } var r = binding.read(fd, buffer, offset, length, position); if (!legacy) { return r; } var str = (r > 0) ? buffer.toString(encoding, 0, r) : ''; return [str, r]; }; fs.write = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, data, position, encoding, callback) callback = arguments[4]; position = arguments[2]; assertEncoding(arguments[3]); buffer = new Buffer('' + arguments[1], arguments[3]); offset = 0; length = buffer.length; } if (!length) { if (typeof callback == 'function') { process.nextTick(function() { callback(undefined, 0); }); } return; } callback = maybeCallback(callback); function wrapper(err, written) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback(err, written || 0, buffer); } binding.write(fd, buffer, offset, length, position, wrapper); }; fs.writeSync = function(fd, buffer, offset, length, position) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, data, position, encoding) position = arguments[2]; assertEncoding(arguments[3]); buffer = new Buffer('' + arguments[1], arguments[3]); offset = 0; length = buffer.length; } if (!length) return 0; return binding.write(fd, buffer, offset, length, position); }; fs.rename = function(oldPath, newPath, callback) { callback = makeCallback(callback); if (!nullCheck(oldPath, callback)) return; if (!nullCheck(newPath, callback)) return; binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath), callback); }; fs.renameSync = function(oldPath, newPath) { nullCheck(oldPath); nullCheck(newPath); return binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath)); }; fs.truncate = function(path, len, callback) { if (typeof path === 'number') { // legacy return fs.ftruncate(path, len, callback); } if (typeof len === 'function') { callback = len; len = 0; } else if (typeof len === 'undefined') { len = 0; } callback = maybeCallback(callback); fs.open(path, 'w', function(er, fd) { if (er) return callback(er); binding.ftruncate(fd, len, function(er) { fs.close(fd, function(er2) { callback(er || er2); }); }); }); }; fs.truncateSync = function(path, len) { if (typeof path === 'number') { // legacy return fs.ftruncateSync(path, len); } if (typeof len === 'undefined') { len = 0; } // allow error to be thrown, but still close fd. var fd = fs.openSync(path, 'w'); try { var ret = fs.ftruncateSync(fd, len); } finally { fs.closeSync(fd); } return ret; }; fs.ftruncate = function(fd, len, callback) { if (typeof len === 'function') { callback = len; len = 0; } else if (typeof len === 'undefined') { len = 0; } binding.ftruncate(fd, len, makeCallback(callback)); }; fs.ftruncateSync = function(fd, len) { if (typeof len === 'undefined') { len = 0; } return binding.ftruncate(fd, len); }; fs.rmdir = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.rmdir(pathModule._makeLong(path), callback); }; fs.rmdirSync = function(path) { nullCheck(path); return binding.rmdir(pathModule._makeLong(path)); }; fs.fdatasync = function(fd, callback) { binding.fdatasync(fd, makeCallback(callback)); }; fs.fdatasyncSync = function(fd) { return binding.fdatasync(fd); }; fs.fsync = function(fd, callback) { binding.fsync(fd, makeCallback(callback)); }; fs.fsyncSync = function(fd) { return binding.fsync(fd); }; fs.mkdir = function(path, mode, callback) { if (typeof mode === 'function') callback = mode; callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/), callback); }; fs.mkdirSync = function(path, mode) { nullCheck(path); return binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/)); }; fs.readdir = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.readdir(pathModule._makeLong(path), callback); }; fs.readdirSync = function(path) { nullCheck(path); return binding.readdir(pathModule._makeLong(path)); }; fs.fstat = function(fd, callback) { binding.fstat(fd, makeCallback(callback)); }; fs.lstat = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.lstat(pathModule._makeLong(path), callback); }; fs.stat = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.stat(pathModule._makeLong(path), callback); }; fs.fstatSync = function(fd) { return binding.fstat(fd); }; fs.lstatSync = function(path) { nullCheck(path); return binding.lstat(pathModule._makeLong(path)); }; fs.statSync = function(path) { nullCheck(path); return binding.stat(pathModule._makeLong(path)); }; fs.readlink = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.readlink(pathModule._makeLong(path), callback); }; fs.readlinkSync = function(path) { nullCheck(path); return binding.readlink(pathModule._makeLong(path)); }; function preprocessSymlinkDestination(path, type) { if (!isWindows) { // No preprocessing is needed on Unix. return path; } else if (type === 'junction') { // Junctions paths need to be absolute and \\?\-prefixed. return pathModule._makeLong(path); } else { // Windows symlinks don't tolerate forward slashes. return ('' + path).replace(/\//g, '\\'); } } fs.symlink = function(destination, path, type_, callback) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); if (!nullCheck(destination, callback)) return; if (!nullCheck(path, callback)) return; binding.symlink(preprocessSymlinkDestination(destination, type), pathModule._makeLong(path), type, callback); }; fs.symlinkSync = function(destination, path, type) { type = (typeof type === 'string' ? type : null); nullCheck(destination); nullCheck(path); return binding.symlink(preprocessSymlinkDestination(destination, type), pathModule._makeLong(path), type); }; fs.link = function(srcpath, dstpath, callback) { callback = makeCallback(callback); if (!nullCheck(srcpath, callback)) return; if (!nullCheck(dstpath, callback)) return; binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath), callback); }; fs.linkSync = function(srcpath, dstpath) { nullCheck(srcpath); nullCheck(dstpath); return binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath)); }; fs.unlink = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.unlink(pathModule._makeLong(path), callback); }; fs.unlinkSync = function(path) { nullCheck(path); return binding.unlink(pathModule._makeLong(path)); }; fs.fchmod = function(fd, mode, callback) { binding.fchmod(fd, modeNum(mode), makeCallback(callback)); }; fs.fchmodSync = function(fd, mode) { return binding.fchmod(fd, modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchmod = function(path, mode, callback) { callback = maybeCallback(callback); fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) { if (err) { callback(err); return; } // prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. fs.fchmod(fd, mode, function(err) { fs.close(fd, function(err2) { callback(err || err2); }); }); }); }; fs.lchmodSync = function(path, mode) { var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK); // prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. var err, err2; try { var ret = fs.fchmodSync(fd, mode); } catch (er) { err = er; } try { fs.closeSync(fd); } catch (er) { err2 = er; } if (err || err2) throw (err || err2); return ret; }; } fs.chmod = function(path, mode, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.chmod(pathModule._makeLong(path), modeNum(mode), callback); }; fs.chmodSync = function(path, mode) { nullCheck(path); return binding.chmod(pathModule._makeLong(path), modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchown = function(path, uid, gid, callback) { callback = maybeCallback(callback); fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) { if (err) { callback(err); return; } fs.fchown(fd, uid, gid, callback); }); }; fs.lchownSync = function(path, uid, gid) { var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK); return fs.fchownSync(fd, uid, gid); }; } fs.fchown = function(fd, uid, gid, callback) { binding.fchown(fd, uid, gid, makeCallback(callback)); }; fs.fchownSync = function(fd, uid, gid) { return binding.fchown(fd, uid, gid); }; fs.chown = function(path, uid, gid, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.chown(pathModule._makeLong(path), uid, gid, callback); }; fs.chownSync = function(path, uid, gid) { nullCheck(path); return binding.chown(pathModule._makeLong(path), uid, gid); }; // converts Date or number to a fractional UNIX timestamp function toUnixTimestamp(time) { if (typeof time == 'number') { return time; } if (time instanceof Date) { // convert to 123.456 UNIX timestamp return time.getTime() / 1000; } throw new Error('Cannot parse time: ' + time); } // exported for unit tests, not for public consumption fs._toUnixTimestamp = toUnixTimestamp; fs.utimes = function(path, atime, mtime, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.utimes(pathModule._makeLong(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), callback); }; fs.utimesSync = function(path, atime, mtime) { nullCheck(path); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.utimes(pathModule._makeLong(path), atime, mtime); }; fs.futimes = function(fd, atime, mtime, callback) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime, makeCallback(callback)); }; fs.futimesSync = function(fd, atime, mtime) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime); }; function writeAll(fd, buffer, offset, length, position, callback) { callback = maybeCallback(arguments[arguments.length - 1]); // write(fd, buffer, offset, length, position, callback) fs.write(fd, buffer, offset, length, position, function(writeErr, written) { if (writeErr) { fs.close(fd, function() { if (callback) callback(writeErr); }); } else { if (written === length) { fs.close(fd, callback); } else { offset += written; length -= written; position += written; writeAll(fd, buffer, offset, length, position, callback); } } }); } fs.writeFile = function(path, data, options, callback) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'w' }; } else if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } assertEncoding(options.encoding); var flag = options.flag || 'w'; fs.open(path, options.flag || 'w', options.mode, function(openErr, fd) { if (openErr) { if (callback) callback(openErr); } else { var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data, options.encoding || 'utf8'); var position = /a/.test(flag) ? null : 0; writeAll(fd, buffer, 0, buffer.length, position, callback); } }); }; fs.writeFileSync = function(path, data, options) { if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'w' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } assertEncoding(options.encoding); var flag = options.flag || 'w'; var fd = fs.openSync(path, flag, options.mode); if (!Buffer.isBuffer(data)) { data = new Buffer('' + data, options.encoding || 'utf8'); } var written = 0; var length = data.length; var position = /a/.test(flag) ? null : 0; try { while (written < length) { written += fs.writeSync(fd, data, written, length - written, position); position += written; } } finally { fs.closeSync(fd); } }; fs.appendFile = function(path, data, options, callback_) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'a' }; } else if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } if (!options.flag) options = util._extend({ flag: 'a' }, options); fs.writeFile(path, data, options, callback); }; fs.appendFileSync = function(path, data, options) { if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'a' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } if (!options.flag) options = util._extend({ flag: 'a' }, options); fs.writeFileSync(path, data, options); }; function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function FSWatcher() { EventEmitter.call(this); var self = this; var FSEvent = process.binding('fs_event_wrap').FSEvent; this._handle = new FSEvent(); this._handle.owner = this; this._handle.onchange = function(status, event, filename) { if (status) { self._handle.close(); self.emit('error', errnoException(process._errno, 'watch')); } else { self.emit('change', event, filename); } }; } util.inherits(FSWatcher, EventEmitter); FSWatcher.prototype.start = function(filename, persistent) { nullCheck(filename); var r = this._handle.start(pathModule._makeLong(filename), persistent); if (r) { this._handle.close(); throw errnoException(process._errno, 'watch'); } }; FSWatcher.prototype.close = function() { this._handle.close(); }; fs.watch = function(filename) { nullCheck(filename); var watcher; var options; var listener; if ('object' == typeof arguments[1]) { options = arguments[1]; listener = arguments[2]; } else { options = {}; listener = arguments[1]; } if (options.persistent === undefined) options.persistent = true; watcher = new FSWatcher(); watcher.start(filename, options.persistent); if (listener) { watcher.addListener('change', listener); } return watcher; }; // Stat Change Watchers function StatWatcher() { EventEmitter.call(this); var self = this; this._handle = new binding.StatWatcher(); // uv_fs_poll is a little more powerful than ev_stat but we curb it for // the sake of backwards compatibility var oldStatus = -1; this._handle.onchange = function(current, previous, newStatus) { if (oldStatus === -1 && newStatus === -1 && current.nlink === previous.nlink) return; oldStatus = newStatus; self.emit('change', current, previous); }; this._handle.onstop = function() { self.emit('stop'); }; } util.inherits(StatWatcher, EventEmitter); StatWatcher.prototype.start = function(filename, persistent, interval) { nullCheck(filename); this._handle.start(pathModule._makeLong(filename), persistent, interval); }; StatWatcher.prototype.stop = function() { this._handle.stop(); }; var statWatchers = {}; function inStatWatchers(filename) { return Object.prototype.hasOwnProperty.call(statWatchers, filename) && statWatchers[filename]; } fs.watchFile = function(filename) { nullCheck(filename); var stat; var listener; var options = { // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. interval: 5007, persistent: true }; if ('object' == typeof arguments[1]) { options = util._extend(options, arguments[1]); listener = arguments[2]; } else { listener = arguments[1]; } if (!listener) { throw new Error('watchFile requires a listener function'); } if (inStatWatchers(filename)) { stat = statWatchers[filename]; } else { stat = statWatchers[filename] = new StatWatcher(); stat.start(filename, options.persistent, options.interval); } stat.addListener('change', listener); return stat; }; fs.unwatchFile = function(filename, listener) { nullCheck(filename); if (!inStatWatchers(filename)) return; var stat = statWatchers[filename]; if (typeof listener === 'function') { stat.removeListener('change', listener); } else { stat.removeAllListeners('change'); } if (EventEmitter.listenerCount(stat, 'change') === 0) { stat.stop(); statWatchers[filename] = undefined; } }; // Realpath // Not using realpath(2) because it's bad. // See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html var normalize = pathModule.normalize; // Regexp that finds the next partion of a (partial) path // result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] if (isWindows) { var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; } else { var nextPartRe = /(.*?)(?:[\/]+|$)/g; } // Regex to find the device root, including trailing slash. E.g. 'c:\\'. if (isWindows) { var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; } else { var splitRootRe = /^[\/]*/; } fs.realpathSync = function realpathSync(p, cache) { // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return cache[p]; } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstatSync(base); knownHard[base] = true; } knownHard[base] = true; } // walk down the path, swapping out linked pathparts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { continue; } var resolvedLink; if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // some known symbolic link. no need to stat again. resolvedLink = cache[base]; } else { var stat = fs.lstatSync(base); if (!stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; continue; } // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); } resolvedLink = pathModule.resolve(previous, linkTarget); // track this, if given a cache. if (cache) cache[base] = resolvedLink; if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } if (cache) cache[original] = p; return p; }; fs.realpath = function realpath(p, cache, cb) { if (typeof cb !== 'function') { cb = maybeCallback(cache); cache = null; } // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return process.nextTick(cb.bind(null, null, cache[p])); } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function(err) { if (err) return cb(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } // walk down the path, swapping out linked pathparts for their real // values function LOOP() { // stop if scanned past end of path if (pos >= p.length) { if (cache) cache[original] = p; return cb(null, p); } // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { return process.nextTick(LOOP); } if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // known symbolic link. no need to stat again. return gotResolvedLink(cache[base]); } return fs.lstat(base, gotStat); } function gotStat(err, stat) { if (err) return cb(err); // if not a symlink, skip to the next path part if (!stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; return process.nextTick(LOOP); } // stat & read the link if not read before // call gotTarget as soon as the link target is known // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } fs.stat(base, function(err) { if (err) return cb(err); fs.readlink(base, function(err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target, base) { if (err) return cb(err); var resolvedLink = pathModule.resolve(previous, target); if (cache) cache[base] = resolvedLink; gotResolvedLink(resolvedLink); } function gotResolvedLink(resolvedLink) { // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } }; var pool; function allocNewPool(poolSize) { pool = new Buffer(poolSize); pool.used = 0; } fs.createReadStream = function(path, options) { return new ReadStream(path, options); }; util.inherits(ReadStream, Readable); fs.ReadStream = ReadStream; function ReadStream(path, options) { if (!(this instanceof ReadStream)) return new ReadStream(path, options); // a little bit bigger buffer and water marks by default options = util._extend({ highWaterMark: 64 * 1024 }, options || {}); Readable.call(this, options); this.path = path; this.fd = options.hasOwnProperty('fd') ? options.fd : null; this.flags = options.hasOwnProperty('flags') ? options.flags : 'r'; this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ this.start = options.hasOwnProperty('start') ? options.start : undefined; this.end = options.hasOwnProperty('end') ? options.end : undefined; this.autoClose = options.hasOwnProperty('autoClose') ? options.autoClose : true; this.pos = undefined; if (this.start !== undefined) { if ('number' !== typeof this.start) { throw TypeError('start must be a Number'); } if (this.end === undefined) { this.end = Infinity; } else if ('number' !== typeof this.end) { throw TypeError('end must be a Number'); } if (this.start > this.end) { throw new Error('start must be <= end'); } this.pos = this.start; } if (typeof this.fd !== 'number') this.open(); this.on('end', function() { if (this.autoClose) { this.destroy(); } }); } fs.FileReadStream = fs.ReadStream; // support the legacy name ReadStream.prototype.open = function() { var self = this; fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { if (this.autoClose) { self.destroy(); } self.emit('error', er); return; } self.fd = fd; self.emit('open', fd); // start the flow of data. self.read(); }); }; ReadStream.prototype._read = function(n) { if (typeof this.fd !== 'number') return this.once('open', function() { this._read(n); }); if (this.destroyed) return; if (!pool || pool.length - pool.used < kMinPoolSpace) { // discard the old pool. pool = null; allocNewPool(this._readableState.highWaterMark); } // Grab another reference to the pool in the case that while we're // in the thread pool another read() finishes up the pool, and // allocates a new one. var thisPool = pool; var toRead = Math.min(pool.length - pool.used, n); var start = pool.used; if (this.pos !== undefined) toRead = Math.min(this.end - this.pos + 1, toRead); // already read everything we were supposed to read! // treat as EOF. if (toRead <= 0) return this.push(null); // the actual read. var self = this; fs.read(this.fd, pool, pool.used, toRead, this.pos, onread); // move the pool positions, and internal position for reading. if (this.pos !== undefined) this.pos += toRead; pool.used += toRead; function onread(er, bytesRead) { if (er) { if (self.autoClose) { self.destroy(); } self.emit('error', er); } else { var b = null; if (bytesRead > 0) b = thisPool.slice(start, start + bytesRead); self.push(b); } } }; ReadStream.prototype.destroy = function() { if (this.destroyed) return; this.destroyed = true; if ('number' === typeof this.fd) this.close(); }; ReadStream.prototype.close = function(cb) { var self = this; if (cb) this.once('close', cb); if (this.closed || 'number' !== typeof this.fd) { if ('number' !== typeof this.fd) { this.once('open', close); return; } return process.nextTick(this.emit.bind(this, 'close')); } this.closed = true; close(); function close(fd) { fs.close(fd || self.fd, function(er) { if (er) self.emit('error', er); else self.emit('close'); }); self.fd = null; } }; fs.createWriteStream = function(path, options) { return new WriteStream(path, options); }; util.inherits(WriteStream, Writable); fs.WriteStream = WriteStream; function WriteStream(path, options) { if (!(this instanceof WriteStream)) return new WriteStream(path, options); options = options || {}; Writable.call(this, options); this.path = path; this.fd = null; this.fd = options.hasOwnProperty('fd') ? options.fd : null; this.flags = options.hasOwnProperty('flags') ? options.flags : 'w'; this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ this.start = options.hasOwnProperty('start') ? options.start : undefined; this.pos = undefined; this.bytesWritten = 0; if (this.start !== undefined) { if ('number' !== typeof this.start) { throw TypeError('start must be a Number'); } if (this.start < 0) { throw new Error('start must be >= zero'); } this.pos = this.start; } if ('number' !== typeof this.fd) this.open(); // dispose on finish. this.once('finish', this.close); } fs.FileWriteStream = fs.WriteStream; // support the legacy name WriteStream.prototype.open = function() { fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { this.destroy(); this.emit('error', er); return; } this.fd = fd; this.emit('open', fd); }.bind(this)); }; WriteStream.prototype._write = function(data, encoding, cb) { if (!Buffer.isBuffer(data)) return this.emit('error', new Error('Invalid data')); if (typeof this.fd !== 'number') return this.once('open', function() { this._write(data, encoding, cb); }); var self = this; fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) { if (er) { self.destroy(); return cb(er); } self.bytesWritten += bytes; cb(); }); if (this.pos !== undefined) this.pos += data.length; }; WriteStream.prototype.destroy = ReadStream.prototype.destroy; WriteStream.prototype.close = ReadStream.prototype.close; // There is no shutdown() for files. WriteStream.prototype.destroySoon = WriteStream.prototype.end; // SyncWriteStream is internal. DO NOT USE. // Temporary hack for process.stdout and process.stderr when piped to files. function SyncWriteStream(fd) { Stream.call(this); this.fd = fd; this.writable = true; this.readable = false; } util.inherits(SyncWriteStream, Stream); // Export fs.SyncWriteStream = SyncWriteStream; SyncWriteStream.prototype.write = function(data, arg1, arg2) { var encoding, cb; // parse arguments if (arg1) { if (typeof arg1 === 'string') { encoding = arg1; cb = arg2; } else if (typeof arg1 === 'function') { cb = arg1; } else { throw new Error('bad arg'); } } assertEncoding(encoding); // Change strings to buffers. SLOW if (typeof data == 'string') { data = new Buffer(data, encoding); } fs.writeSync(this.fd, data, 0, data.length); if (cb) { process.nextTick(cb); } return true; }; SyncWriteStream.prototype.end = function(data, arg1, arg2) { if (data) { this.write(data, arg1, arg2); } this.destroy(); }; SyncWriteStream.prototype.destroy = function() { fs.closeSync(this.fd); this.fd = null; this.emit('close'); return true; }; SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This is a free list to avoid creating so many of the same object. exports.FreeList = function(name, max, constructor) { this.name = name; this.constructor = constructor; this.max = max; this.list = []; }; exports.FreeList.prototype.alloc = function() { //debug("alloc " + this.name + " " + this.list.length); return this.list.length ? this.list.shift() : this.constructor.apply(this, arguments); }; exports.FreeList.prototype.free = function(obj) { //debug("free " + this.name + " " + this.list.length); if (this.list.length < this.max) { this.list.push(obj); } }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var domain; exports.usingDomains = false; function EventEmitter() { this.domain = null; if (exports.usingDomains) { // if there is an active domain, then attach to it. domain = domain || require('domain'); if (domain.active && !(this instanceof domain.Domain)) { this.domain = domain.active; } } this._events = this._events || {}; this._maxListeners = this._maxListeners || defaultMaxListeners; } exports.EventEmitter = EventEmitter; // By default EventEmitters will print a warning if more than // 10 listeners are added to it. This is a useful default which // helps finding memory leaks. // // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. var defaultMaxListeners = 10; EventEmitter.prototype.setMaxListeners = function(n) { if (typeof n !== 'number' || n < 0) throw TypeError('n must be a positive number'); this._maxListeners = n; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (typeof this._events.error === 'object' && !this._events.error.length)) { er = arguments[1]; if (this.domain) { if (!er) er = new TypeError('Uncaught, unspecified "error" event.'); er.domainEmitter = this; er.domain = this.domain; er.domainThrown = false; this.domain.emit('error', er); } else if (er instanceof Error) { throw er; // Unhandled 'error' event } else { throw TypeError('Uncaught, unspecified "error" event.'); } return false; } } handler = this._events[type]; if (typeof handler === 'undefined') return false; if (this.domain && this !== process) this.domain.enter(); if (typeof handler === 'function') { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } } else if (typeof handler === 'object') { len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } if (this.domain && this !== process) this.domain.exit(); return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (typeof listener !== 'function') throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, typeof listener.listener === 'function' ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (typeof this._events[type] === 'object') // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (typeof this._events[type] === 'object' && !this._events[type].warned) { m = this._maxListeners; if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); console.trace(); } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (typeof listener !== 'function') throw TypeError('listener must be a function'); function g() { this.removeListener(type, g); listener.apply(this, arguments); } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (typeof listener !== 'function') throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (typeof list.listener === 'function' && list.listener === listener)) { this._events[type] = undefined; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (typeof list === 'object') { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; this._events[type] = undefined; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) this._events[type] = undefined; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } this._events[type] = undefined; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (typeof this._events[type] === 'function') ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.listenerCount = function(emitter, type) { var ret; if (!emitter._events || !emitter._events[type]) ret = 0; else if (typeof emitter._events[type] === 'function') ret = 1; else ret = emitter._events[type].length; return ret; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var events = require('events'); var EventEmitter = events.EventEmitter; var inherits = util.inherits; // methods that are called when trying to shut down expliclitly bound EEs var endMethods = ['end', 'abort', 'destroy', 'destroySoon']; // communicate with events module, but don't require that // module to have to load this one, since this module has // a few side effects. events.usingDomains = true; // let the process know we're using domains process._usingDomains(); exports.Domain = Domain; exports.create = exports.createDomain = function(cb) { return new Domain(cb); }; // it's possible to enter one domain while already inside // another one. the stack is each entered domain. var stack = []; exports._stack = stack; // the active domain is always the one that we're currently in. exports.active = null; inherits(Domain, EventEmitter); function Domain() { EventEmitter.call(this); this.members = []; } Domain.prototype.enter = function() { if (this._disposed) return; // note that this might be a no-op, but we still need // to push it onto the stack so that we can pop it later. exports.active = process.domain = this; stack.push(this); }; Domain.prototype.exit = function() { if (this._disposed) return; // exit all domains until this one. var d; do { d = stack.pop(); } while (d && d !== this); exports.active = stack[stack.length - 1]; process.domain = exports.active; }; // note: this works for timers as well. Domain.prototype.add = function(ee) { // disposed domains can't be used for new things. if (this._disposed) return; // already added to this domain. if (ee.domain === this) return; // has a domain already - remove it first. if (ee.domain) { ee.domain.remove(ee); } // check for circular Domain->Domain links. // This causes bad insanity! // // For example: // var d = domain.create(); // var e = domain.create(); // d.add(e); // e.add(d); // e.emit('error', er); // RangeError, stack overflow! if (this.domain && (ee instanceof Domain)) { for (var d = this.domain; d; d = d.domain) { if (ee === d) return; } } ee.domain = this; this.members.push(ee); }; Domain.prototype.remove = function(ee) { ee.domain = null; var index = this.members.indexOf(ee); if (index !== -1) { this.members.splice(index, 1); } }; Domain.prototype.run = function(fn) { return this.bind(fn)(); }; Domain.prototype.intercept = function(cb) { return this.bind(cb, true); }; Domain.prototype.bind = function(cb, interceptError) { // if cb throws, catch it here. var self = this; var b = function() { // disposing turns functions into no-ops if (self._disposed) return; if (this instanceof Domain) { return cb.apply(this, arguments); } // only intercept first-arg errors if explicitly requested. if (interceptError && arguments[0] && (arguments[0] instanceof Error)) { var er = arguments[0]; util._extend(er, { domainBound: cb, domainThrown: false, domain: self }); self.emit('error', er); return; } // remove first-arg if intercept as assumed to be the error-arg if (interceptError) { var len = arguments.length; var args; switch (len) { case 0: case 1: // no args that we care about. args = []; break; case 2: // optimization for most common case: cb(er, data) args = [arguments[1]]; break; default: // slower for less common case: cb(er, foo, bar, baz, ...) args = new Array(len - 1); for (var i = 1; i < len; i++) { args[i - 1] = arguments[i]; } break; } self.enter(); var ret = cb.apply(this, args); self.exit(); return ret; } self.enter(); var ret = cb.apply(this, arguments); self.exit(); return ret; }; b.domain = this; return b; }; Domain.prototype.dispose = function() { if (this._disposed) return; // if we're the active domain, then get out now. this.exit(); this.emit('dispose'); // remove error handlers. this.removeAllListeners(); this.on('error', function() {}); // try to kill all the members. // XXX There should be more consistent ways // to shut down things! this.members.forEach(function(m) { // if it's a timeout or interval, cancel it. clearTimeout(m); // drop all event listeners. if (m instanceof EventEmitter) { m.removeAllListeners(); // swallow errors m.on('error', function() {}); } // Be careful! // By definition, we're likely in error-ridden territory here, // so it's quite possible that calling some of these methods // might cause additional exceptions to be thrown. endMethods.forEach(function(method) { if (typeof m[method] === 'function') { try { m[method](); } catch (er) {} } }); }); // remove from parent domain, if there is one. if (this.domain) this.domain.remove(this); // kill the references so that they can be properly gc'ed. this.members.length = 0; // finally, mark this domain as 'no longer relevant' // so that it can't be entered or activated. this._disposed = true; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var cares, net = require('net'); function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. // For backwards compatibility. libuv returns ENOENT on NXDOMAIN. if (errorno == 'ENOENT') { errorno = 'ENOTFOUND'; } var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // c-ares invokes a callback either synchronously or asynchronously, // but the dns API should always invoke a callback asynchronously. // // This function makes sure that the callback is invoked asynchronously. // It returns a function that invokes the callback within nextTick(). // // To avoid invoking unnecessary nextTick(), `immediately` property of // returned function should be set to true after c-ares returned. // // Usage: // // function someAPI(callback) { // callback = makeAsync(callback); // channel.someAPI(..., callback); // callback.immediately = true; // } function makeAsync(callback) { if (typeof callback !== 'function') { return callback; } return function asyncCallback() { if (asyncCallback.immediately) { // The API already returned, we can invoke the callback immediately. callback.apply(null, arguments); } else { var args = arguments; process.nextTick(function() { callback.apply(null, args); }); } }; } // Easy DNS A/AAAA look up // lookup(domain, [family,] callback) exports.lookup = function(domain, family, callback) { // parse arguments if (arguments.length === 2) { callback = family; family = 0; } else if (!family) { family = 0; } else { family = +family; if (family !== 4 && family !== 6) { throw new Error('invalid argument: `family` must be 4 or 6'); } } callback = makeAsync(callback); if (!domain) { callback(null, null, family === 6 ? 6 : 4); return {}; } // Hack required for Windows because Win7 removed the // localhost entry from c:\WINDOWS\system32\drivers\etc\hosts // See http://daniel.haxx.se/blog/2011/02/21/localhost-hack-on-windows/ // TODO Remove this once c-ares handles this problem. if (process.platform == 'win32' && domain == 'localhost') { callback(null, '127.0.0.1', 4); return {}; } var matchedFamily = net.isIP(domain); if (matchedFamily) { callback(null, domain, matchedFamily); return {}; } function onanswer(addresses) { if (addresses) { if (family) { callback(null, addresses[0], family); } else { callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4); } } else { callback(errnoException(process._errno, 'getaddrinfo')); } } cares = cares || process.binding('cares_wrap'); var wrap = cares.getaddrinfo(domain, family); if (!wrap) { throw errnoException(process._errno, 'getaddrinfo'); } wrap.oncomplete = onanswer; callback.immediately = true; return wrap; }; function resolver(bindingName) { cares = cares || process.binding('cares_wrap'); var binding = cares[bindingName]; return function query(name, callback) { function onanswer(status, result) { if (!status) { callback(null, result); } else { callback(errnoException(process._errno, bindingName)); } } callback = makeAsync(callback); var wrap = binding(name, onanswer); if (!wrap) { throw errnoException(process._errno, bindingName); } callback.immediately = true; return wrap; } } var resolveMap = {}; exports.resolve4 = resolveMap.A = resolver('queryA'); exports.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); exports.resolveCname = resolveMap.CNAME = resolver('queryCname'); exports.resolveMx = resolveMap.MX = resolver('queryMx'); exports.resolveNs = resolveMap.NS = resolver('queryNs'); exports.resolveTxt = resolveMap.TXT = resolver('queryTxt'); exports.resolveSrv = resolveMap.SRV = resolver('querySrv'); exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr'); exports.reverse = resolveMap.PTR = resolver('getHostByAddr'); exports.resolve = function(domain, type_, callback_) { var resolver, callback; if (typeof type_ == 'string') { resolver = resolveMap[type_]; callback = callback_; } else { resolver = exports.resolve4; callback = type_; } if (typeof resolver === 'function') { return resolver(domain, callback); } else { throw new Error('Unknown type "' + type_ + '"'); } }; // ERROR CODES exports.NODATA = 'ENODATA'; exports.FORMERR = 'EFORMERR'; exports.SERVFAIL = 'ESERVFAIL'; exports.NOTFOUND = 'ENOTFOUND'; exports.NOTIMP = 'ENOTIMP'; exports.REFUSED = 'EREFUSED'; exports.BADQUERY = 'EBADQUERY'; exports.ADNAME = 'EADNAME'; exports.BADFAMILY = 'EBADFAMILY'; exports.BADRESP = 'EBADRESP'; exports.CONNREFUSED = 'ECONNREFUSED'; exports.TIMEOUT = 'ETIMEOUT'; exports.EOF = 'EOF'; exports.FILE = 'EFILE'; exports.NOMEM = 'ENOMEM'; exports.DESTRUCTION = 'EDESTRUCTION'; exports.BADSTR = 'EBADSTR'; exports.BADFLAGS = 'EBADFLAGS'; exports.NONAME = 'ENONAME'; exports.BADHINTS = 'EBADHINTS'; exports.NOTINITIALIZED = 'ENOTINITIALIZED'; exports.LOADIPHLPAPI = 'ELOADIPHLPAPI'; exports.ADDRGETNETWORKPARAMS = 'EADDRGETNETWORKPARAMS'; exports.CANCELLED = 'ECANCELLED'; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var util = require('util'); var events = require('events'); var UDP = process.binding('udp_wrap').UDP; var BIND_STATE_UNBOUND = 0; var BIND_STATE_BINDING = 1; var BIND_STATE_BOUND = 2; // lazily loaded var cluster = null; var dns = null; var net = null; // no-op callback function noop() { } function isIP(address) { if (!net) net = require('net'); return net.isIP(address); } function lookup(address, family, callback) { if (!dns) dns = require('dns'); return dns.lookup(address, family, callback); } function lookup4(address, callback) { return lookup(address || '0.0.0.0', 4, callback); } function lookup6(address, callback) { return lookup(address || '::0', 6, callback); } function newHandle(type) { if (type == 'udp4') { var handle = new UDP; handle.lookup = lookup4; return handle; } if (type == 'udp6') { var handle = new UDP; handle.lookup = lookup6; handle.bind = handle.bind6; handle.send = handle.send6; return handle; } if (type == 'unix_dgram') throw new Error('unix_dgram sockets are not supported any more.'); throw new Error('Bad socket type specified. Valid types are: udp4, udp6'); } exports._createSocketHandle = function(address, port, addressType, fd) { // Opening an existing fd is not supported for UDP handles. assert(typeof fd !== 'number' || fd < 0); var handle = newHandle(addressType); if (port || address) { var r = handle.bind(address, port || 0, 0); if (r == -1) { handle.close(); handle = null; } } return handle; }; function Socket(type, listener) { events.EventEmitter.call(this); var handle = newHandle(type); handle.owner = this; this._handle = handle; this._receiving = false; this._bindState = BIND_STATE_UNBOUND; this.type = type; this.fd = null; // compatibility hack if (typeof listener === 'function') this.on('message', listener); } util.inherits(Socket, events.EventEmitter); exports.Socket = Socket; exports.createSocket = function(type, listener) { return new Socket(type, listener); }; function startListening(socket) { socket._handle.onmessage = onMessage; // Todo: handle errors socket._handle.recvStart(); socket._receiving = true; socket._bindState = BIND_STATE_BOUND; socket.fd = -42; // compatibility hack socket.emit('listening'); } function replaceHandle(self, newHandle) { // Set up the handle that we got from master. newHandle.lookup = self._handle.lookup; newHandle.bind = self._handle.bind; newHandle.send = self._handle.send; newHandle.owner = self; // Replace the existing handle by the handle we got from master. self._handle.close(); self._handle = newHandle; } Socket.prototype.bind = function(/*port, address, callback*/) { var self = this; self._healthCheck(); if (this._bindState != BIND_STATE_UNBOUND) throw new Error('Socket is already bound'); this._bindState = BIND_STATE_BINDING; if (typeof arguments[arguments.length - 1] === 'function') self.once('listening', arguments[arguments.length - 1]); var UDP = process.binding('udp_wrap').UDP; if (arguments[0] instanceof UDP) { replaceHandle(self, arguments[0]); startListening(self); return; } var port = arguments[0]; var address = arguments[1]; if (typeof address === 'function') address = ''; // a.k.a. "any address" // resolve address first self._handle.lookup(address, function(err, ip) { if (err) { self._bindState = BIND_STATE_UNBOUND; self.emit('error', err); return; } if (!cluster) cluster = require('cluster'); if (cluster.isWorker) { cluster._getServer(self, ip, port, self.type, -1, function(handle) { if (!self._handle) // handle has been closed in the mean time. return handle.close(); replaceHandle(self, handle); startListening(self); }); } else { if (!self._handle) return; // handle has been closed in the mean time if (self._handle.bind(ip, port || 0, /*flags=*/ 0)) { self.emit('error', errnoException(process._errno, 'bind')); self._bindState = BIND_STATE_UNBOUND; // Todo: close? return; } startListening(self); } }); }; // thin wrapper around `send`, here for compatibility with dgram_legacy.js Socket.prototype.sendto = function(buffer, offset, length, port, address, callback) { if (typeof offset !== 'number' || typeof length !== 'number') throw new Error('send takes offset and length as args 2 and 3'); if (typeof address !== 'string') throw new Error(this.type + ' sockets must send to port, address'); this.send(buffer, offset, length, port, address, callback); }; Socket.prototype.send = function(buffer, offset, length, port, address, callback) { var self = this; if (!Buffer.isBuffer(buffer)) throw new TypeError('First argument must be a buffer object.'); if (offset >= buffer.length) throw new Error('Offset into buffer too large'); if (offset + length > buffer.length) throw new Error('Offset + length beyond buffer length'); callback = callback || noop; self._healthCheck(); if (self._bindState == BIND_STATE_UNBOUND) self.bind(0, null); // If the socket hasn't been bound yet, push the outbound packet onto the // send queue and send after binding is complete. if (self._bindState != BIND_STATE_BOUND) { // If the send queue hasn't been initialized yet, do it, and install an // event handler that flushes the send queue after binding is done. if (!self._sendQueue) { self._sendQueue = []; self.once('listening', function() { // Flush the send queue. for (var i = 0; i < self._sendQueue.length; i++) self.send.apply(self, self._sendQueue[i]); self._sendQueue = undefined; }); } self._sendQueue.push([buffer, offset, length, port, address, callback]); return; } self._handle.lookup(address, function(err, ip) { if (err) { if (callback) callback(err); self.emit('error', err); } else if (self._handle) { var req = self._handle.send(buffer, offset, length, port, ip); if (req) { req.oncomplete = afterSend; req.cb = callback; } else { // don't emit as error, dgram_legacy.js compatibility var err = errnoException(process._errno, 'send'); process.nextTick(function() { callback(err); }); } } }); }; function afterSend(status, handle, req, buffer) { var self = handle.owner; if (req.cb) req.cb(null, buffer.length); // compatibility with dgram_legacy.js } Socket.prototype.close = function() { this._healthCheck(); this._stopReceiving(); this._handle.close(); this._handle = null; this.emit('close'); }; Socket.prototype.address = function() { this._healthCheck(); var address = this._handle.getsockname(); if (!address) throw errnoException(process._errno, 'getsockname'); return address; }; Socket.prototype.setBroadcast = function(arg) { if (this._handle.setBroadcast((arg) ? 1 : 0)) { throw errnoException(process._errno, 'setBroadcast'); } }; Socket.prototype.setTTL = function(arg) { if (typeof arg !== 'number') { throw new TypeError('Argument must be a number'); } if (this._handle.setTTL(arg)) { throw errnoException(process._errno, 'setTTL'); } return arg; }; Socket.prototype.setMulticastTTL = function(arg) { if (typeof arg !== 'number') { throw new TypeError('Argument must be a number'); } if (this._handle.setMulticastTTL(arg)) { throw errnoException(process._errno, 'setMulticastTTL'); } return arg; }; Socket.prototype.setMulticastLoopback = function(arg) { arg = arg ? 1 : 0; if (this._handle.setMulticastLoopback(arg)) { throw errnoException(process._errno, 'setMulticastLoopback'); } return arg; // 0.4 compatibility }; Socket.prototype.addMembership = function(multicastAddress, interfaceAddress) { this._healthCheck(); if (!multicastAddress) { throw new Error('multicast address must be specified'); } if (this._handle.addMembership(multicastAddress, interfaceAddress)) { throw new errnoException(process._errno, 'addMembership'); } }; Socket.prototype.dropMembership = function(multicastAddress, interfaceAddress) { this._healthCheck(); if (!multicastAddress) { throw new Error('multicast address must be specified'); } if (this._handle.dropMembership(multicastAddress, interfaceAddress)) { throw new errnoException(process._errno, 'dropMembership'); } }; Socket.prototype._healthCheck = function() { if (!this._handle) throw new Error('Not running'); // error message from dgram_legacy.js }; Socket.prototype._stopReceiving = function() { if (!this._receiving) return; this._handle.recvStop(); this._receiving = false; this.fd = null; // compatibility hack }; function onMessage(handle, slab, start, len, rinfo) { var self = handle.owner; if (!slab) { return self.emit('error', errnoException(process._errno, 'recvmsg')); } rinfo.size = len; // compatibility self.emit('message', slab.slice(start, start + len), rinfo); } Socket.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Socket.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // TODO share with net_uv and others function errnoException(errorno, syscall) { var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Note: In 0.8 and before, crypto functions all defaulted to using // binary-encoded strings rather than buffers. exports.DEFAULT_ENCODING = 'buffer'; try { var binding = process.binding('crypto'); var SecureContext = binding.SecureContext; var randomBytes = binding.randomBytes; var pseudoRandomBytes = binding.pseudoRandomBytes; var getCiphers = binding.getCiphers; var getHashes = binding.getHashes; var crypto = true; } catch (e) { var crypto = false; } var stream = require('stream'); var util = require('util'); // This is here because many functions accepted binary strings without // any explicit encoding in older versions of node, and we don't want // to break them unnecessarily. function toBuf(str, encoding) { encoding = encoding || 'binary'; if (typeof str === 'string') { if (encoding === 'buffer') encoding = 'binary'; str = new Buffer(str, encoding); } return str; } var assert = require('assert'); var StringDecoder = require('string_decoder').StringDecoder; function Credentials(secureProtocol, flags, context) { if (!(this instanceof Credentials)) { return new Credentials(secureProtocol, flags, context); } if (!crypto) { throw new Error('node.js not compiled with openssl crypto support.'); } if (context) { this.context = context; } else { this.context = new SecureContext(); if (secureProtocol) { this.context.init(secureProtocol); } else { this.context.init(); } } if (flags) this.context.setOptions(flags); } exports.Credentials = Credentials; exports.createCredentials = function(options, context) { if (!options) options = {}; var c = new Credentials(options.secureProtocol, options.secureOptions, context); if (context) return c; if (options.key) { if (options.passphrase) { c.context.setKey(options.key, options.passphrase); } else { c.context.setKey(options.key); } } if (options.cert) c.context.setCert(options.cert); if (options.ciphers) c.context.setCiphers(options.ciphers); if (options.ca) { if (Array.isArray(options.ca)) { for (var i = 0, len = options.ca.length; i < len; i++) { c.context.addCACert(options.ca[i]); } } else { c.context.addCACert(options.ca); } } else { c.context.addRootCerts(); } if (options.crl) { if (Array.isArray(options.crl)) { for (var i = 0, len = options.crl.length; i < len; i++) { c.context.addCRL(options.crl[i]); } } else { c.context.addCRL(options.crl); } } if (options.sessionIdContext) { c.context.setSessionIdContext(options.sessionIdContext); } if (options.pfx) { var pfx = options.pfx; var passphrase = options.passphrase; pfx = toBuf(pfx); if (passphrase) passphrase = toBuf(passphrase); if (passphrase) { c.context.loadPKCS12(pfx, passphrase); } else { c.context.loadPKCS12(pfx); } } return c; }; function LazyTransform(options) { this._options = options; } util.inherits(LazyTransform, stream.Transform); [ '_readableState', '_writableState', '_transformState' ].forEach(function(prop, i, props) { Object.defineProperty(LazyTransform.prototype, prop, { get: function() { stream.Transform.call(this, this._options); this._writableState.decodeStrings = false; this._writableState.defaultEncoding = 'binary'; return this[prop]; }, set: function(val) { Object.defineProperty(this, prop, { value: val, enumerable: true, configurable: true, writable: true }); }, configurable: true, enumerable: true }); }); exports.createHash = exports.Hash = Hash; function Hash(algorithm, options) { if (!(this instanceof Hash)) return new Hash(algorithm, options); this._binding = new binding.Hash(algorithm); LazyTransform.call(this, options); } util.inherits(Hash, LazyTransform); Hash.prototype._transform = function(chunk, encoding, callback) { this._binding.update(chunk, encoding); callback(); }; Hash.prototype._flush = function(callback) { var encoding = this._readableState.encoding || 'buffer'; this.push(this._binding.digest(encoding), encoding); callback(); }; Hash.prototype.update = function(data, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; if (encoding === 'buffer' && typeof data === 'string') encoding = 'binary'; this._binding.update(data, encoding); return this; }; Hash.prototype.digest = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; return this._binding.digest(outputEncoding); }; exports.createHmac = exports.Hmac = Hmac; function Hmac(hmac, key, options) { if (!(this instanceof Hmac)) return new Hmac(hmac, key, options); this._binding = new binding.Hmac(); this._binding.init(hmac, toBuf(key)); LazyTransform.call(this, options); } util.inherits(Hmac, LazyTransform); Hmac.prototype.update = Hash.prototype.update; Hmac.prototype.digest = Hash.prototype.digest; Hmac.prototype._flush = Hash.prototype._flush; Hmac.prototype._transform = Hash.prototype._transform; function getDecoder(decoder, encoding) { decoder = decoder || new StringDecoder(encoding); assert(decoder.encoding === encoding, 'Cannot change encoding'); return decoder; } exports.createCipher = exports.Cipher = Cipher; function Cipher(cipher, password, options) { if (!(this instanceof Cipher)) return new Cipher(cipher, password, options); this._binding = new binding.Cipher; this._binding.init(cipher, toBuf(password)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Cipher, LazyTransform); Cipher.prototype._transform = function(chunk, encoding, callback) { this.push(this._binding.update(chunk, encoding)); callback(); }; Cipher.prototype._flush = function(callback) { this.push(this._binding.final()); callback(); }; Cipher.prototype.update = function(data, inputEncoding, outputEncoding) { inputEncoding = inputEncoding || exports.DEFAULT_ENCODING; outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; var ret = this._binding.update(data, inputEncoding); if (outputEncoding && outputEncoding !== 'buffer') { this._decoder = getDecoder(this._decoder, outputEncoding); ret = this._decoder.write(ret); } return ret; }; Cipher.prototype.final = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; var ret = this._binding.final(); if (outputEncoding && outputEncoding !== 'buffer') { this._decoder = getDecoder(this._decoder, outputEncoding); ret = this._decoder.end(ret); } return ret; }; Cipher.prototype.setAutoPadding = function(ap) { this._binding.setAutoPadding(ap); return this; }; exports.createCipheriv = exports.Cipheriv = Cipheriv; function Cipheriv(cipher, key, iv, options) { if (!(this instanceof Cipheriv)) return new Cipheriv(cipher, key, iv, options); this._binding = new binding.Cipher(); this._binding.initiv(cipher, toBuf(key), toBuf(iv)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Cipheriv, LazyTransform); Cipheriv.prototype._transform = Cipher.prototype._transform; Cipheriv.prototype._flush = Cipher.prototype._flush; Cipheriv.prototype.update = Cipher.prototype.update; Cipheriv.prototype.final = Cipher.prototype.final; Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createDecipher = exports.Decipher = Decipher; function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) return new Decipher(cipher, password, options); this._binding = new binding.Decipher; this._binding.init(cipher, toBuf(password)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Decipher, LazyTransform); Decipher.prototype._transform = Cipher.prototype._transform; Decipher.prototype._flush = Cipher.prototype._flush; Decipher.prototype.update = Cipher.prototype.update; Decipher.prototype.final = Cipher.prototype.final; Decipher.prototype.finaltol = Cipher.prototype.final; Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createDecipheriv = exports.Decipheriv = Decipheriv; function Decipheriv(cipher, key, iv, options) { if (!(this instanceof Decipheriv)) return new Decipheriv(cipher, key, iv, options); this._binding = new binding.Decipher; this._binding.initiv(cipher, toBuf(key), toBuf(iv)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Decipheriv, LazyTransform); Decipheriv.prototype._transform = Cipher.prototype._transform; Decipheriv.prototype._flush = Cipher.prototype._flush; Decipheriv.prototype.update = Cipher.prototype.update; Decipheriv.prototype.final = Cipher.prototype.final; Decipheriv.prototype.finaltol = Cipher.prototype.final; Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createSign = exports.Sign = Sign; function Sign(algorithm, options) { if (!(this instanceof Sign)) return new Sign(algorithm, options); this._binding = new binding.Sign(); this._binding.init(algorithm); stream.Writable.call(this, options); } util.inherits(Sign, stream.Writable); Sign.prototype._write = function(chunk, encoding, callback) { this._binding.update(chunk, encoding); callback(); }; Sign.prototype.update = Hash.prototype.update; Sign.prototype.sign = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; var ret = this._binding.sign(toBuf(key)); if (encoding && encoding !== 'buffer') ret = ret.toString(encoding); return ret; }; exports.createVerify = exports.Verify = Verify; function Verify(algorithm, options) { if (!(this instanceof Verify)) return new Verify(algorithm, options); this._binding = new binding.Verify; this._binding.init(algorithm); stream.Writable.call(this, options); } util.inherits(Verify, stream.Writable); Verify.prototype._write = Sign.prototype._write; Verify.prototype.update = Sign.prototype.update; Verify.prototype.verify = function(object, signature, sigEncoding) { sigEncoding = sigEncoding || exports.DEFAULT_ENCODING; return this._binding.verify(toBuf(object), toBuf(signature, sigEncoding)); }; exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman; function DiffieHellman(sizeOrKey, encoding) { if (!(this instanceof DiffieHellman)) return new DiffieHellman(sizeOrKey, encoding); if (!sizeOrKey) this._binding = new binding.DiffieHellman(); else { encoding = encoding || exports.DEFAULT_ENCODING; sizeOrKey = toBuf(sizeOrKey, encoding); this._binding = new binding.DiffieHellman(sizeOrKey); } } exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = DiffieHellmanGroup; function DiffieHellmanGroup(name) { if (!(this instanceof DiffieHellmanGroup)) return new DiffieHellmanGroup(name); this._binding = new binding.DiffieHellmanGroup(name); } DiffieHellmanGroup.prototype.generateKeys = DiffieHellman.prototype.generateKeys = dhGenerateKeys; function dhGenerateKeys(encoding) { var keys = this._binding.generateKeys(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') keys = keys.toString(encoding); return keys; } DiffieHellmanGroup.prototype.computeSecret = DiffieHellman.prototype.computeSecret = dhComputeSecret; function dhComputeSecret(key, inEnc, outEnc) { inEnc = inEnc || exports.DEFAULT_ENCODING; outEnc = outEnc || exports.DEFAULT_ENCODING; var ret = this._binding.computeSecret(toBuf(key, inEnc)); if (outEnc && outEnc !== 'buffer') ret = ret.toString(outEnc); return ret; } DiffieHellmanGroup.prototype.getPrime = DiffieHellman.prototype.getPrime = dhGetPrime; function dhGetPrime(encoding) { var prime = this._binding.getPrime(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') prime = prime.toString(encoding); return prime; } DiffieHellmanGroup.prototype.getGenerator = DiffieHellman.prototype.getGenerator = dhGetGenerator; function dhGetGenerator(encoding) { var generator = this._binding.getGenerator(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') generator = generator.toString(encoding); return generator; } DiffieHellmanGroup.prototype.getPublicKey = DiffieHellman.prototype.getPublicKey = dhGetPublicKey; function dhGetPublicKey(encoding) { var key = this._binding.getPublicKey(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') key = key.toString(encoding); return key; } DiffieHellmanGroup.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey = dhGetPrivateKey; function dhGetPrivateKey(encoding) { var key = this._binding.getPrivateKey(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') key = key.toString(encoding); return key; } DiffieHellman.prototype.setPublicKey = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; this._binding.setPublicKey(toBuf(key, encoding)); return this; }; DiffieHellman.prototype.setPrivateKey = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; this._binding.setPrivateKey(toBuf(key, encoding)); return this; }; exports.pbkdf2 = function(password, salt, iterations, keylen, callback) { if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2'); return pbkdf2(password, salt, iterations, keylen, callback); }; exports.pbkdf2Sync = function(password, salt, iterations, keylen) { return pbkdf2(password, salt, iterations, keylen); }; function pbkdf2(password, salt, iterations, keylen, callback) { password = toBuf(password); salt = toBuf(salt); if (exports.DEFAULT_ENCODING === 'buffer') return binding.PBKDF2(password, salt, iterations, keylen, callback); // at this point, we need to handle encodings. var encoding = exports.DEFAULT_ENCODING; if (callback) { binding.PBKDF2(password, salt, iterations, keylen, function(er, ret) { if (ret) ret = ret.toString(encoding); callback(er, ret); }); } else { var ret = binding.PBKDF2(password, salt, iterations, keylen); return ret.toString(encoding); } } exports.randomBytes = randomBytes; exports.pseudoRandomBytes = pseudoRandomBytes; exports.rng = randomBytes; exports.prng = pseudoRandomBytes; exports.getCiphers = function() { return filterDuplicates(getCiphers.call(null, arguments)); }; exports.getHashes = function() { return filterDuplicates(getHashes.call(null, arguments)); }; function filterDuplicates(names) { // Drop all-caps names in favor of their lowercase aliases, // for example, 'sha1' instead of 'SHA1'. var ctx = {}; names.forEach(function(name) { if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); ctx[name] = true; }); return Object.getOwnPropertyNames(ctx).sort(); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = process.binding('constants'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); function Console(stdout, stderr) { if (!(this instanceof Console)) { return new Console(stdout, stderr); } if (!stdout || typeof stdout.write !== 'function') { throw new TypeError('Console expects a writable stream instance'); } if (!stderr) { stderr = stdout; } var prop = { writable: true, enumerable: false, configurable: true }; prop.value = stdout; Object.defineProperty(this, '_stdout', prop); prop.value = stderr; Object.defineProperty(this, '_stderr', prop); prop.value = {}; Object.defineProperty(this, '_times', prop); // bind the prototype functions to this Console instance Object.keys(Console.prototype).forEach(function(k) { this[k] = this[k].bind(this); }, this); } Console.prototype.log = function() { this._stdout.write(util.format.apply(this, arguments) + '\n'); }; Console.prototype.info = Console.prototype.log; Console.prototype.warn = function() { this._stderr.write(util.format.apply(this, arguments) + '\n'); }; Console.prototype.error = Console.prototype.warn; Console.prototype.dir = function(object) { this._stdout.write(util.inspect(object) + '\n'); }; Console.prototype.time = function(label) { this._times[label] = Date.now(); }; Console.prototype.timeEnd = function(label) { var time = this._times[label]; if (!time) { throw new Error('No such label: ' + label); } var duration = Date.now() - time; this.log('%s: %dms', label, duration); }; Console.prototype.trace = function() { // TODO probably can to do this better with V8's debug object once that is // exposed. var err = new Error; err.name = 'Trace'; err.message = util.format.apply(this, arguments); Error.captureStackTrace(err, arguments.callee); this.error(err.stack); }; Console.prototype.assert = function(expression) { if (!expression) { var arr = Array.prototype.slice.call(arguments, 1); require('assert').ok(false, util.format.apply(this, arr)); } }; module.exports = new Console(process.stdout, process.stderr); module.exports.Console = Console; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var fork = require('child_process').fork; var net = require('net'); var EventEmitter = require('events').EventEmitter; var util = require('util'); function isObject(o) { return (typeof o === 'object' && o !== null); } var debug; if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) { debug = function(x) { var prefix = process.pid + ',' + (process.env.NODE_UNIQUE_ID ? 'Worker' : 'Master'); console.error(prefix, x); }; } else { debug = function() { }; } // cluster object: function Cluster() { EventEmitter.call(this); } util.inherits(Cluster, EventEmitter); var cluster = module.exports = new Cluster(); // Used in the master: var masterStarted = false; var ids = 0; var serverHandlers = {}; // Used in the worker: var serverListeners = {}; var queryIds = 0; var queryCallbacks = {}; // Define isWorker and isMaster cluster.isWorker = 'NODE_UNIQUE_ID' in process.env; cluster.isMaster = ! cluster.isWorker; // The worker object is only used in a worker cluster.worker = cluster.isWorker ? {} : null; // The workers array is only used in the master cluster.workers = cluster.isMaster ? {} : null; // Settings object var settings = cluster.settings = {}; // Simple function to call a function on each worker function eachWorker(cb) { // Go through all workers for (var id in cluster.workers) { if (cluster.workers.hasOwnProperty(id)) { cb(cluster.workers[id]); } } } // Extremely simple progress tracker function ProgressTracker(missing, callback) { this.missing = missing; this.callback = callback; } ProgressTracker.prototype.done = function() { this.missing -= 1; this.check(); }; ProgressTracker.prototype.check = function() { if (this.missing === 0) this.callback(); }; cluster.setupMaster = function(options) { // This can only be called from the master. assert(cluster.isMaster); // Don't allow this function to run more than once if (masterStarted) return; masterStarted = true; // Get filename and arguments options = options || {}; // By default, V8 writes the profile data of all processes to a single // v8.log. // // Running that log file through a tick processor produces bogus numbers // because many events won't match up with the recorded memory mappings // and you end up with graphs where 80+% of ticks is unaccounted for. // // Fixing the tick processor to deal with multi-process output is not very // useful because the processes may be running wildly disparate workloads. // // That's why we fix up the command line arguments to include // a "--logfile=v8-%p.log" argument (where %p is expanded to the PID) // unless it already contains a --logfile argument. var execArgv = options.execArgv || process.execArgv; if (execArgv.some(function(s) { return /^--prof/.test(s); }) && !execArgv.some(function(s) { return /^--logfile=/.test(s); })) { execArgv = execArgv.slice(); execArgv.push('--logfile=v8-%p.log'); } // Set settings object settings = cluster.settings = { exec: options.exec || process.argv[1], execArgv: execArgv, args: options.args || process.argv.slice(2), silent: options.silent || false }; // emit setup event cluster.emit('setup'); }; // Check if a message is internal only var INTERNAL_PREFIX = 'NODE_CLUSTER_'; function isInternalMessage(message) { return isObject(message) && typeof message.cmd === 'string' && message.cmd.length > INTERNAL_PREFIX.length && message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX; } // Modify message object to be internal function internalMessage(inMessage) { var outMessage = util._extend({}, inMessage); // Add internal prefix to cmd outMessage.cmd = INTERNAL_PREFIX + (outMessage.cmd || ''); return outMessage; } // Handle callback messages function handleResponse(outMessage, outHandle, inMessage, inHandle, worker) { // The message there will be sent var message = internalMessage(outMessage); // callback id - will be undefined if not set message._queryEcho = inMessage._requestEcho; // Call callback if a query echo is received if (inMessage._queryEcho) { queryCallbacks[inMessage._queryEcho](inMessage.content, inHandle); delete queryCallbacks[inMessage._queryEcho]; } // Send if outWrap contains something useful if (!(outMessage === undefined && message._queryEcho === undefined)) { sendInternalMessage(worker, message, outHandle); } } // Handle messages from both master and workers var messageHandler = {}; function handleMessage(worker, inMessage, inHandle) { // Remove internal prefix var message = util._extend({}, inMessage); message.cmd = inMessage.cmd.substr(INTERNAL_PREFIX.length); var respondUsed = false; function respond(outMessage, outHandler) { respondUsed = true; handleResponse(outMessage, outHandler, inMessage, inHandle, worker); } // Run handler if it exists if (messageHandler[message.cmd]) { messageHandler[message.cmd](message, worker, respond); } // Send respond if it hasn't been called yet if (respondUsed === false) { respond(); } } // Messages to the master will be handled using these methods if (cluster.isMaster) { // Handle online messages from workers messageHandler.online = function(message, worker) { worker.state = 'online'; debug('Worker ' + worker.process.pid + ' online'); worker.emit('online'); cluster.emit('online', worker); }; // Handle queryServer messages from workers messageHandler.queryServer = function(message, worker, send) { // This sequence of information is unique to the connection // but not to the worker var args = [message.address, message.port, message.addressType, message.fd]; var key = args.join(':'); var handler; if (serverHandlers.hasOwnProperty(key)) { handler = serverHandlers[key]; } else if (message.addressType === 'udp4' || message.addressType === 'udp6') { var dgram = require('dgram'); handler = dgram._createSocketHandle.apply(net, args); serverHandlers[key] = handler; } else { handler = net._createServerHandle.apply(net, args); serverHandlers[key] = handler; } // echo callback with the fd handler associated with it send({}, handler); }; // Handle listening messages from workers messageHandler.listening = function(message, worker) { worker.state = 'listening'; // Emit listening, now that we know the worker is listening worker.emit('listening', { address: message.address, port: message.port, addressType: message.addressType, fd: message.fd }); cluster.emit('listening', worker, { address: message.address, port: message.port, addressType: message.addressType, fd: message.fd }); }; // Handle suicide messages from workers messageHandler.suicide = function(message, worker) { worker.suicide = true; }; } // Messages to a worker will be handled using these methods else if (cluster.isWorker) { // Handle worker.disconnect from master messageHandler.disconnect = function(message, worker) { worker.disconnect(); }; } function toDecInt(value) { value = parseInt(value, 10); return isNaN(value) ? null : value; } // Create a worker object, that works both for master and worker function Worker(customEnv) { if (!(this instanceof Worker)) return new Worker(); EventEmitter.call(this); var self = this; var env = process.env; // Assign a unique id, default null this.id = cluster.isMaster ? ++ids : toDecInt(env.NODE_UNIQUE_ID); // XXX: Legacy. Remove in 0.9 this.workerID = this.uniqueID = this.id; // Assign state this.state = 'none'; // Create or get process if (cluster.isMaster) { // Create env object // first: copy and add id property var envCopy = util._extend({}, env); envCopy['NODE_UNIQUE_ID'] = this.id; // second: extend envCopy with the env argument if (isObject(customEnv)) { envCopy = util._extend(envCopy, customEnv); } // fork worker this.process = fork(settings.exec, settings.args, { 'env': envCopy, 'silent': settings.silent, 'execArgv': settings.execArgv }); } else { this.process = process; } if (cluster.isMaster) { // Save worker in the cluster.workers array cluster.workers[this.id] = this; // Emit a fork event, on next tick // There is no worker.fork event since this has no real purpose process.nextTick(function() { cluster.emit('fork', self); }); } // handle internalMessage, exit and disconnect event this.process.on('internalMessage', handleMessage.bind(null, this)); this.process.once('exit', function(exitCode, signalCode) { prepareExit(self, 'dead'); self.emit('exit', exitCode, signalCode); cluster.emit('exit', self, exitCode, signalCode); }); this.process.once('disconnect', function() { prepareExit(self, 'disconnected'); self.emit('disconnect'); cluster.emit('disconnect', self); }); // relay message and error this.process.on('message', this.emit.bind(this, 'message')); this.process.on('error', this.emit.bind(this, 'error')); } util.inherits(Worker, EventEmitter); cluster.Worker = Worker; function prepareExit(worker, state) { // set state to disconnect worker.state = state; // Make suicide a boolean worker.suicide = !!worker.suicide; // Remove from workers in the master if (cluster.isMaster) { delete cluster.workers[worker.id]; } } // Send internal message function sendInternalMessage(worker, message/*, handler, callback*/) { // Exist callback var callback = arguments[arguments.length - 1]; if (typeof callback !== 'function') { callback = undefined; } // exist handler var handler = arguments[2] !== callback ? arguments[2] : undefined; if (!isInternalMessage(message)) { message = internalMessage(message); } // Store callback for later if (callback) { message._requestEcho = worker.id + ':' + (++queryIds); queryCallbacks[message._requestEcho] = callback; } worker.send(message, handler); } // Send message to worker or master Worker.prototype.send = function() { // You could also just use process.send in a worker this.process.send.apply(this.process, arguments); }; // Kill the worker without restarting Worker.prototype.kill = Worker.prototype.destroy = function(signal) { if (!signal) signal = 'SIGTERM'; var self = this; this.suicide = true; if (cluster.isMaster) { // Disconnect IPC channel // this way the worker won't need to propagate suicide state to master if (self.process.connected) { self.process.once('disconnect', function() { self.process.kill(signal); }); self.process.disconnect(); } else { self.process.kill(signal); } } else { // Channel is open if (this.process.connected) { // Inform master to suicide and then kill sendInternalMessage(this, {cmd: 'suicide'}, function() { process.exit(0); }); // When channel is closed, terminate the process this.process.once('disconnect', function() { process.exit(0); }); } else { process.exit(0); } } }; // The .disconnect function will close all servers // and then disconnect the IPC channel. if (cluster.isMaster) { // Used in master Worker.prototype.disconnect = function() { this.suicide = true; sendInternalMessage(this, {cmd: 'disconnect'}); }; } else { // Used in workers Worker.prototype.disconnect = function() { var self = this; this.suicide = true; // keep track of open servers var servers = Object.keys(serverListeners).length; var progress = new ProgressTracker(servers, function() { // There are no more servers open so we will close the IPC channel. // Closing the IPC channel will emit a disconnect event // in both master and worker on the process object. // This event will be handled by prepareExit. self.process.disconnect(); }); // depending on where this function was called from (master or worker) // The suicide state has already been set, // but it doesn't really matter if we set it again. sendInternalMessage(this, {cmd: 'suicide'}, function() { // in case there are no servers progress.check(); // closing all servers gracefully var server; for (var key in serverListeners) { server = serverListeners[key]; // in case the server is closed we won't close it again if (server._handle === null) { progress.done(); continue; } server.on('close', progress.done.bind(progress)); server.close(); } }); }; } // Fork a new worker cluster.fork = function(env) { // This can only be called from the master. assert(cluster.isMaster); // Make sure that the master has been initialized cluster.setupMaster(); return (new cluster.Worker(env)); }; // execute .disconnect on all workers and close handlers when done cluster.disconnect = function(callback) { // This can only be called from the master. assert(cluster.isMaster); // Close all TCP handlers when all workers are disconnected var workers = Object.keys(cluster.workers).length; var progress = new ProgressTracker(workers, function() { for (var key in serverHandlers) { serverHandlers[key].close(); delete serverHandlers[key]; } // call callback when done if (callback) callback(); }); // begin disconnecting all workers eachWorker(function(worker) { worker.once('disconnect', progress.done.bind(progress)); worker.disconnect(); }); // in case there weren't any workers progress.check(); }; // Internal function. Called from src/node.js when worker process starts. cluster._setupWorker = function() { // Get worker class var worker = cluster.worker = new Worker(); // we will terminate the worker // when the worker is disconnected from the parent accidentally process.once('disconnect', function() { if (worker.suicide !== true) { process.exit(0); } }); // Tell master that the worker is online worker.state = 'online'; sendInternalMessage(worker, { cmd: 'online' }); }; // Internal function. Called by net.js and dgram.js when attempting to bind a // TCP server or UDP socket. cluster._getServer = function(tcpSelf, address, port, addressType, fd, cb) { // This can only be called from a worker. assert(cluster.isWorker); // Store tcp instance for later use var key = [address, port, addressType, fd].join(':'); serverListeners[key] = tcpSelf; // Send a listening message to the master tcpSelf.once('listening', function() { cluster.worker.state = 'listening'; sendInternalMessage(cluster.worker, { cmd: 'listening', address: address, port: tcpSelf.address().port || port, addressType: addressType, fd: fd }); }); // Request the fd handler from the master process var message = { cmd: 'queryServer', address: address, port: port, addressType: addressType, fd: fd }; // The callback will be stored until the master has responded sendInternalMessage(cluster.worker, message, function(msg, handle) { cb(handle); }); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var StringDecoder = require('string_decoder').StringDecoder; var EventEmitter = require('events').EventEmitter; var net = require('net'); var dgram = require('dgram'); var Process = process.binding('process_wrap').Process; var assert = require('assert'); var util = require('util'); var constants; // if (!constants) constants = process.binding('constants'); var handleWraps = {}; function handleWrapGetter(name, callback) { var cons; Object.defineProperty(handleWraps, name, { get: function() { if (cons !== undefined) return cons; return cons = callback(); } }); } handleWrapGetter('Pipe', function() { return process.binding('pipe_wrap').Pipe; }); handleWrapGetter('TTY', function() { return process.binding('tty_wrap').TTY; }); handleWrapGetter('TCP', function() { return process.binding('tcp_wrap').TCP; }); handleWrapGetter('UDP', function() { return process.binding('udp_wrap').UDP; }); // constructors for lazy loading function createPipe(ipc) { return new handleWraps.Pipe(ipc); } function createSocket(pipe, readable) { var s = new net.Socket({ handle: pipe }); if (readable) { s.writable = false; s.readable = true; } else { s.writable = true; s.readable = false; } return s; } // this object contain function to convert TCP objects to native handle objects // and back again. var handleConversion = { 'net.Native': { simultaneousAccepts: true, send: function(message, handle) { return handle; }, got: function(message, handle, emit) { emit(handle); } }, 'net.Server': { simultaneousAccepts: true, send: function(message, server) { return server._handle; }, got: function(message, handle, emit) { var self = this; var server = new net.Server(); server.listen(handle, function() { emit(server); }); } }, 'net.Socket': { send: function(message, socket) { // if the socket was created by net.Server if (socket.server) { // the slave should keep track of the socket message.key = socket.server._connectionKey; var firstTime = !this._channel.sockets.send[message.key]; var socketList = getSocketList('send', this, message.key); // the server should no longer expose a .connection property // and when asked to close it should query the socket status from // the slaves if (firstTime) socket.server._setupSlave(socketList); // Act like socket is detached socket.server._connections--; } // remove handle from socket object, it will be closed when the socket // will be sent var handle = socket._handle; handle.onread = function() {}; socket._handle = null; return handle; }, postSend: function(handle) { // Close the Socket handle after sending it handle.close(); }, got: function(message, handle, emit) { var socket = new net.Socket({handle: handle}); socket.readable = socket.writable = true; // if the socket was created by net.Server we will track the socket if (message.key) { // add socket to connections list var socketList = getSocketList('got', this, message.key); socketList.add({ socket: socket }); } emit(socket); } }, 'dgram.Native': { simultaneousAccepts: false, send: function(message, handle) { return handle; }, got: function(message, handle, emit) { emit(handle); } }, 'dgram.Socket': { simultaneousAccepts: false, send: function(message, socket) { message.dgramType = socket.type; return socket._handle; }, got: function(message, handle, emit) { var socket = new dgram.Socket(message.dgramType); socket.bind(handle, function() { emit(socket); }); } } }; // This object keep track of the socket there are sended function SocketListSend(slave, key) { EventEmitter.call(this); var self = this; this.key = key; this.slave = slave; } util.inherits(SocketListSend, EventEmitter); SocketListSend.prototype._request = function(msg, cmd, callback) { var self = this; if (!this.slave.connected) return onclose(); this.slave.send(msg); function onclose() { self.slave.removeListener('internalMessage', onreply); callback(new Error('Slave closed before reply')); }; function onreply(msg) { if (!(msg.cmd === cmd && msg.key === self.key)) return; self.slave.removeListener('disconnect', onclose); self.slave.removeListener('internalMessage', onreply); callback(null, msg); }; this.slave.once('disconnect', onclose); this.slave.on('internalMessage', onreply); }; SocketListSend.prototype.close = function close(callback) { this._request({ cmd: 'NODE_SOCKET_NOTIFY_CLOSE', key: this.key }, 'NODE_SOCKET_ALL_CLOSED', callback); }; SocketListSend.prototype.getConnections = function getConnections(callback) { this._request({ cmd: 'NODE_SOCKET_GET_COUNT', key: this.key }, 'NODE_SOCKET_COUNT', function(err, msg) { if (err) return callback(err); callback(null, msg.count); }); }; // This object keep track of the socket there are received function SocketListReceive(slave, key) { EventEmitter.call(this); var self = this; this.connections = 0; this.key = key; this.slave = slave; function onempty() { if (!self.slave.connected) return; self.slave.send({ cmd: 'NODE_SOCKET_ALL_CLOSED', key: self.key }); } this.slave.on('internalMessage', function(msg) { if (msg.key !== self.key) return; if (msg.cmd === 'NODE_SOCKET_NOTIFY_CLOSE') { // Already empty if (self.connections === 0) return onempty(); // Wait for sockets to get closed self.once('empty', onempty); } else if (msg.cmd === 'NODE_SOCKET_GET_COUNT') { if (!self.slave.connected) return; self.slave.send({ cmd: 'NODE_SOCKET_COUNT', key: self.key, count: self.connections }); } }); } util.inherits(SocketListReceive, EventEmitter); SocketListReceive.prototype.add = function(obj) { var self = this; this.connections++; // Notify previous owner of socket about its state change obj.socket.once('close', function() { self.connections--; if (self.connections === 0) self.emit('empty'); }); }; function getSocketList(type, slave, key) { var sockets = slave._channel.sockets[type]; var socketList = sockets[key]; if (!socketList) { var Construct = type === 'send' ? SocketListSend : SocketListReceive; socketList = sockets[key] = new Construct(slave, key); } return socketList; } var INTERNAL_PREFIX = 'NODE_'; function handleMessage(target, message, handle) { var eventName = 'message'; if (message !== null && typeof message === 'object' && typeof message.cmd === 'string' && message.cmd.length > INTERNAL_PREFIX.length && message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX) { eventName = 'internalMessage'; } target.emit(eventName, message, handle); } function setupChannel(target, channel) { target._channel = channel; target._handleQueue = null; var decoder = new StringDecoder('utf8'); var jsonBuffer = ''; channel.buffering = false; channel.onread = function(pool, offset, length, recvHandle) { if (pool) { jsonBuffer += decoder.write(pool.slice(offset, offset + length)); var i, start = 0; //Linebreak is used as a message end sign while ((i = jsonBuffer.indexOf('\n', start)) >= 0) { var json = jsonBuffer.slice(start, i); var message = JSON.parse(json); // There will be at most one NODE_HANDLE message in every chunk we // read because SCM_RIGHTS messages don't get coalesced. Make sure // that we deliver the handle with the right message however. if (message && message.cmd === 'NODE_HANDLE') handleMessage(target, message, recvHandle); else handleMessage(target, message, undefined); start = i + 1; } jsonBuffer = jsonBuffer.slice(start); this.buffering = jsonBuffer.length !== 0; } else { this.buffering = false; target.disconnect(); channel.onread = nop; channel.close(); maybeClose(target); } }; // object where socket lists will live channel.sockets = { got: {}, send: {} }; // handlers will go through this target.on('internalMessage', function(message, handle) { // Once acknowledged - continue sending handles. if (message.cmd === 'NODE_HANDLE_ACK') { assert(Array.isArray(target._handleQueue)); var queue = target._handleQueue; target._handleQueue = null; queue.forEach(function(args) { target.send(args.message, args.handle); }); return; } if (message.cmd !== 'NODE_HANDLE') return; // Acknowledge handle receival. target.send({ cmd: 'NODE_HANDLE_ACK' }); var obj = handleConversion[message.type]; // Update simultaneous accepts on Windows if (process.platform === 'win32') { handle._simultaneousAccepts = false; net._setSimultaneousAccepts(handle); } // Convert handle object obj.got.call(this, message, handle, function(handle) { handleMessage(target, message.msg, handle); }); }); target.send = function(message, handle) { if (typeof message === 'undefined') { throw new TypeError('message cannot be undefined'); } if (!this.connected) { this.emit('error', new Error('channel closed')); return; } // package messages with a handle object if (handle) { // this message will be handled by an internalMessage event handler message = { cmd: 'NODE_HANDLE', type: null, msg: message }; if (handle instanceof net.Socket) { message.type = 'net.Socket'; } else if (handle instanceof net.Server) { message.type = 'net.Server'; } else if (handle instanceof process.binding('tcp_wrap').TCP || handle instanceof process.binding('pipe_wrap').Pipe) { message.type = 'net.Native'; } else if (handle instanceof dgram.Socket) { message.type = 'dgram.Socket'; } else if (handle instanceof process.binding('udp_wrap').UDP) { message.type = 'dgram.Native'; } else { throw new TypeError("This handle type can't be sent"); } // Queue-up message and handle if we haven't received ACK yet. if (this._handleQueue) { this._handleQueue.push({ message: message.msg, handle: handle }); return; } var obj = handleConversion[message.type]; // convert TCP object to native handle object handle = handleConversion[message.type].send.apply(target, arguments); // Update simultaneous accepts on Windows if (obj.simultaneousAccepts) { net._setSimultaneousAccepts(handle); } } else if (this._handleQueue) { // Queue request anyway to avoid out-of-order messages. this._handleQueue.push({ message: message, handle: null }); return; } var string = JSON.stringify(message) + '\n'; var writeReq = channel.writeUtf8String(string, handle); if (!writeReq) { var er = errnoException(process._errno, 'write', 'cannot write to IPC channel.'); this.emit('error', er); } else if (handle && !this._handleQueue) { this._handleQueue = []; } if (obj && obj.postSend) { writeReq.oncomplete = obj.postSend.bind(null, handle); } else { writeReq.oncomplete = nop; } /* If the master is > 2 read() calls behind, please stop sending. */ return channel.writeQueueSize < (65536 * 2); }; target.connected = true; target.disconnect = function() { if (!this.connected) { this.emit('error', new Error('IPC channel is already disconnected')); return; } // do not allow messages to be written this.connected = false; this._channel = null; var fired = false; function finish() { if (fired) return; fired = true; channel.close(); target.emit('disconnect'); } // If a message is being read, then wait for it to complete. if (channel.buffering) { this.once('message', finish); this.once('internalMessage', finish); return; } finish(); }; channel.readStart(); } function nop() { } exports.fork = function(modulePath /*, args, options*/) { // Get options and args arguments. var options, args, execArgv; if (Array.isArray(arguments[1])) { args = arguments[1]; options = util._extend({}, arguments[2]); } else { args = []; options = util._extend({}, arguments[1]); } // Prepare arguments for fork: execArgv = options.execArgv || process.execArgv; args = execArgv.concat([modulePath], args); // Leave stdin open for the IPC channel. stdout and stderr should be the // same as the parent's if silent isn't set. options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] : [0, 1, 2, 'ipc']; options.execPath = options.execPath || process.execPath; return spawn(options.execPath, args, options); }; exports._forkChild = function(fd) { // set process.send() var p = createPipe(true); p.open(fd); p.unref(); setupChannel(process, p); var refs = 0; process.on('newListener', function(name) { if (name !== 'message' && name !== 'disconnect') return; if (++refs === 1) p.ref(); }); process.on('removeListener', function(name) { if (name !== 'message' && name !== 'disconnect') return; if (--refs === 0) p.unref(); }); }; exports.exec = function(command /*, options, callback */) { var file, args, options, callback; if (typeof arguments[1] === 'function') { options = undefined; callback = arguments[1]; } else { options = arguments[1]; callback = arguments[2]; } if (process.platform === 'win32') { file = 'cmd.exe'; args = ['/s', '/c', '"' + command + '"']; // Make a shallow copy before patching so we don't clobber the user's // options object. options = util._extend({}, options); options.windowsVerbatimArguments = true; } else { file = '/bin/sh'; args = ['-c', command]; } return exports.execFile(file, args, options, callback); }; exports.execFile = function(file /* args, options, callback */) { var args, optionArg, callback; var options = { encoding: 'utf8', timeout: 0, maxBuffer: 200 * 1024, killSignal: 'SIGTERM', cwd: null, env: null }; // Parse the parameters. if (typeof arguments[arguments.length - 1] === 'function') { callback = arguments[arguments.length - 1]; } if (Array.isArray(arguments[1])) { args = arguments[1]; options = util._extend(options, arguments[2]); } else { args = []; options = util._extend(options, arguments[1]); } var child = spawn(file, args, { cwd: options.cwd, env: options.env, windowsVerbatimArguments: !!options.windowsVerbatimArguments }); var stdout = ''; var stderr = ''; var killed = false; var exited = false; var timeoutId; var err; function exithandler(code, signal) { if (exited) return; exited = true; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } if (!callback) return; if (err) { callback(err, stdout, stderr); } else if (code === 0 && signal === null) { callback(null, stdout, stderr); } else { var e = new Error('Command failed: ' + stderr); e.killed = child.killed || killed; e.code = code; e.signal = signal; callback(e, stdout, stderr); } } function errorhandler(e) { err = e; child.stdout.destroy(); child.stderr.destroy(); exithandler(); } function kill() { child.stdout.destroy(); child.stderr.destroy(); killed = true; try { child.kill(options.killSignal); } catch (e) { err = e; exithandler(); } } if (options.timeout > 0) { timeoutId = setTimeout(function() { kill(); timeoutId = null; }, options.timeout); } child.stdout.setEncoding(options.encoding); child.stderr.setEncoding(options.encoding); child.stdout.addListener('data', function(chunk) { stdout += chunk; if (stdout.length > options.maxBuffer) { err = new Error('stdout maxBuffer exceeded.'); kill(); } }); child.stderr.addListener('data', function(chunk) { stderr += chunk; if (stderr.length > options.maxBuffer) { err = new Error('stderr maxBuffer exceeded.'); kill(); } }); child.addListener('close', exithandler); child.addListener('error', errorhandler); return child; }; var spawn = exports.spawn = function(file, args, options) { args = args ? args.slice(0) : []; args.unshift(file); var env = (options ? options.env : null) || process.env; var envPairs = []; for (var key in env) { envPairs.push(key + '=' + env[key]); } var child = new ChildProcess(); if (options && options.customFds && !options.stdio) { options.stdio = options.customFds.map(function(fd) { return fd === -1 ? 'pipe' : fd; }); } child.spawn({ file: file, args: args, cwd: options ? options.cwd : null, windowsVerbatimArguments: !!(options && options.windowsVerbatimArguments), detached: !!(options && options.detached), envPairs: envPairs, stdio: options ? options.stdio : null, uid: options ? options.uid : null, gid: options ? options.gid : null }); return child; }; function maybeClose(subprocess) { subprocess._closesGot++; if (subprocess._closesGot == subprocess._closesNeeded) { subprocess.emit('close', subprocess.exitCode, subprocess.signalCode); } } function ChildProcess() { EventEmitter.call(this); // Initialize TCPWrap and PipeWrap process.binding('tcp_wrap'); process.binding('pipe_wrap'); var self = this; this._closesNeeded = 1; this._closesGot = 0; this.connected = false; this.signalCode = null; this.exitCode = null; this.killed = false; this._handle = new Process(); this._handle.owner = this; this._handle.onexit = function(exitCode, signalCode) { // // follow 0.4.x behaviour: // // - normally terminated processes don't touch this.signalCode // - signaled processes don't touch this.exitCode // // new in 0.9.x: // // - spawn failures are reported with exitCode == -1 // var err = (exitCode == -1) ? errnoException(process._errno, 'spawn') : null; if (signalCode) { self.signalCode = signalCode; } else { self.exitCode = exitCode; } if (self.stdin) { self.stdin.destroy(); } self._handle.close(); self._handle = null; if (exitCode == -1) { self.emit('error', err); } else { self.emit('exit', self.exitCode, self.signalCode); } // if any of the stdio streams have not been touched, // then pull all the data through so that it can get the // eof and emit a 'close' event. // Do it on nextTick so that the user has one last chance // to consume the output, if for example they only want to // start reading the data once the process exits. process.nextTick(function() { flushStdio(self); }); maybeClose(self); }; } util.inherits(ChildProcess, EventEmitter); function flushStdio(subprocess) { subprocess.stdio.forEach(function(stream, fd, stdio) { if (!stream || !stream.readable || stream._consuming || stream._readableState.flowing) return; stream.resume(); }); } function getHandleWrapType(stream) { if (stream instanceof handleWraps.Pipe) return 'pipe'; if (stream instanceof handleWraps.TTY) return 'tty'; if (stream instanceof handleWraps.TCP) return 'tcp'; if (stream instanceof handleWraps.UDP) return 'udp'; return false; } ChildProcess.prototype.spawn = function(options) { var self = this, ipc, ipcFd, // If no `stdio` option was given - use default stdio = options.stdio || 'pipe'; // Replace shortcut with an array if (typeof stdio === 'string') { switch (stdio) { case 'ignore': stdio = ['ignore', 'ignore', 'ignore']; break; case 'pipe': stdio = ['pipe', 'pipe', 'pipe']; break; case 'inherit': stdio = [0, 1, 2]; break; default: throw new TypeError('Incorrect value of stdio option: ' + stdio); } } else if (!Array.isArray(stdio)) { throw new TypeError('Incorrect value of stdio option: ' + stdio); } // At least 3 stdio will be created // Don't concat() a new Array() because it would be sparse, and // stdio.reduce() would skip the sparse elements of stdio. // See http://stackoverflow.com/a/5501711/3561 while (stdio.length < 3) stdio.push(undefined); // Translate stdio into C++-readable form // (i.e. PipeWraps or fds) stdio = stdio.reduce(function(acc, stdio, i) { function cleanup() { acc.filter(function(stdio) { return stdio.type === 'pipe' || stdio.type === 'ipc'; }).forEach(function(stdio) { stdio.handle.close(); }); } // Defaults if (stdio === undefined || stdio === null) { stdio = i < 3 ? 'pipe' : 'ignore'; } if (stdio === 'ignore') { acc.push({type: 'ignore'}); } else if (stdio === 'pipe' || typeof stdio === 'number' && stdio < 0) { acc.push({type: 'pipe', handle: createPipe()}); } else if (stdio === 'ipc') { if (ipc !== undefined) { // Cleanup previously created pipes cleanup(); throw Error('Child process can have only one IPC pipe'); } ipc = createPipe(true); ipcFd = i; acc.push({ type: 'pipe', handle: ipc, ipc: true }); } else if (typeof stdio === 'number' || typeof stdio.fd === 'number') { acc.push({ type: 'fd', fd: stdio.fd || stdio }); } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) || getHandleWrapType(stdio._handle)) { var handle = getHandleWrapType(stdio) ? stdio : getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle; acc.push({ type: 'wrap', wrapType: getHandleWrapType(handle), handle: handle }); } else { // Cleanup cleanup(); throw new TypeError('Incorrect value for stdio stream: ' + stdio); } return acc; }, []); options.stdio = stdio; if (ipc !== undefined) { // Let child process know about opened IPC channel options.envPairs = options.envPairs || []; options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd); } var r = this._handle.spawn(options); if (r) { // Close all opened fds on error stdio.forEach(function(stdio) { if (stdio.type === 'pipe') { stdio.handle.close(); } }); this._handle.close(); this._handle = null; throw errnoException(process._errno, 'spawn'); } this.pid = this._handle.pid; stdio.forEach(function(stdio, i) { if (stdio.type === 'ignore') return; if (stdio.ipc) { self._closesNeeded++; return; } if (stdio.handle) { // when i === 0 - we're dealing with stdin // (which is the only one writable pipe) stdio.socket = createSocket(self.pid !== 0 ? stdio.handle : null, i > 0); if (i > 0 && self.pid !== 0) { self._closesNeeded++; stdio.socket.on('close', function() { maybeClose(self); }); } } }); this.stdin = stdio.length >= 1 && stdio[0].socket !== undefined ? stdio[0].socket : null; this.stdout = stdio.length >= 2 && stdio[1].socket !== undefined ? stdio[1].socket : null; this.stderr = stdio.length >= 3 && stdio[2].socket !== undefined ? stdio[2].socket : null; this.stdio = stdio.map(function(stdio) { return stdio.socket === undefined ? null : stdio.socket; }); // Add .send() method and start listening for IPC data if (ipc !== undefined) setupChannel(this, ipc); return r; }; function errnoException(errorno, syscall, errmsg) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var message = syscall + ' ' + errorno; if (errmsg) { message += ' - ' + errmsg; } var e = new Error(message); e.errno = e.code = errorno; e.syscall = syscall; return e; } ChildProcess.prototype.kill = function(sig) { var signal; if (!constants) { constants = process.binding('constants'); } if (sig === 0) { signal = 0; } else if (!sig) { signal = constants['SIGTERM']; } else { signal = constants[sig]; } if (signal === undefined) { throw new Error('Unknown signal: ' + sig); } if (this._handle) { var r = this._handle.kill(signal); if (r == 0) { /* Success. */ this.killed = true; return true; } else if (process._errno == 'ESRCH') { /* Already dead. */ } else if (process._errno == 'EINVAL' || process._errno == 'ENOSYS') { /* The underlying platform doesn't support this signal. */ throw errnoException(process._errno, 'kill'); } else { /* Other error, almost certainly EPERM. */ this.emit('error', errnoException(process._errno, 'kill')); } } /* Kill didn't succeed. */ return false; }; ChildProcess.prototype.ref = function() { if (this._handle) this._handle.ref(); }; ChildProcess.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var SlowBuffer = process.binding('buffer').SlowBuffer; var assert = require('assert'); exports.INSPECT_MAX_BYTES = 50; // Make SlowBuffer inherit from Buffer. // This is an exception to the rule that __proto__ is not allowed in core. SlowBuffer.prototype.__proto__ = Buffer.prototype; function clamp(index, len, defaultValue) { if (typeof index !== 'number') return defaultValue; index = ~~index; // Coerce to integer. if (index >= len) return len; if (index >= 0) return index; index += len; if (index >= 0) return index; return 0; } function toHex(n) { if (n < 16) return '0' + n.toString(16); return n.toString(16); } SlowBuffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); start = +start || 0; if (typeof end !== 'number') end = this.length; // Fastpath empty strings if (+end == start) { return ''; } switch (encoding) { case 'hex': return this.hexSlice(start, end); case 'utf8': case 'utf-8': return this.utf8Slice(start, end); case 'ascii': return this.asciiSlice(start, end); case 'binary': return this.binarySlice(start, end); case 'base64': return this.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.ucs2Slice(start, end); default: throw new TypeError('Unknown encoding: ' + encoding); } }; SlowBuffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); switch (encoding) { case 'hex': return this.hexWrite(string, offset, length); case 'utf8': case 'utf-8': return this.utf8Write(string, offset, length); case 'ascii': return this.asciiWrite(string, offset, length); case 'binary': return this.binaryWrite(string, offset, length); case 'base64': return this.base64Write(string, offset, length); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.ucs2Write(string, offset, length); default: throw new TypeError('Unknown encoding: ' + encoding); } }; // slice(start, end) SlowBuffer.prototype.slice = function(start, end) { var len = this.length; start = clamp(start, len, 0); end = clamp(end, len, len); return new Buffer(this, end - start, start); }; var zeroBuffer = new SlowBuffer(0); // Buffer function Buffer(subject, encoding, offset) { if (!(this instanceof Buffer)) { return new Buffer(subject, encoding, offset); } var buffer = this; // chakra-specific code if (SlowBuffer.makeFastBufferObject !== undefined) { buffer = SlowBuffer.makeFastBufferObject(); buffer.__proto__ = this.__proto__; } var type; // Are we slicing? if (typeof offset === 'number') { if (!Buffer.isBuffer(subject)) { throw new TypeError('First argument must be a Buffer when slicing'); } buffer.length = +encoding > 0 ? Math.ceil(encoding) : 0; buffer.parent = subject.parent ? subject.parent : subject; buffer.offset = offset; } else { // Find the length switch (type = typeof subject) { case 'number': buffer.length = +subject > 0 ? Math.ceil(subject) : 0; break; case 'string': buffer.length = Buffer.byteLength(subject, encoding); break; case 'object': // Assume object is array-ish buffer.length = +subject.length > 0 ? Math.ceil(subject.length) : 0; break; default: throw new TypeError('First argument needs to be a number, ' + 'array or string.'); } if (buffer.length > Buffer.poolSize) { // Big buffer, just alloc one. buffer.parent = new SlowBuffer(buffer.length); buffer.offset = 0; } else if (buffer.length > 0) { // Small buffer. if (!pool || pool.length - pool.used < buffer.length) allocPool(); buffer.parent = pool; buffer.offset = pool.used; pool.used += buffer.length; if (pool.used & 7) pool.used = (pool.used + 8) & ~7; } else { // Zero-length buffer buffer.parent = zeroBuffer; buffer.offset = 0; } // optimize by branching logic for new allocations if (typeof subject !== 'number') { if (type === 'string') { // We are a string buffer.length = buffer.write(subject, 0, encoding); // if subject is buffer then use built-in copy method } else if (Buffer.isBuffer(subject)) { if (subject.parent) subject.parent.copy(buffer.parent, buffer.offset, subject.offset, buffer.length + subject.offset); else subject.copy(buffer.parent, buffer.offset, 0, buffer.length); } else if (isArrayIsh(subject)) { for (var i = 0; i < buffer.length; i++) buffer.parent[i + buffer.offset] = subject[i]; } } } SlowBuffer.makeFastBuffer( buffer.parent, buffer, buffer.offset, buffer.length); return buffer; } function isArrayIsh(subject) { return Array.isArray(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number'; } exports.SlowBuffer = SlowBuffer; exports.Buffer = Buffer; Buffer.isEncoding = function(encoding) { switch (encoding && encoding.toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; default: return false; } }; Buffer.poolSize = 8 * 1024; var pool; function allocPool() { pool = new SlowBuffer(Buffer.poolSize); pool.used = 0; } // Static methods Buffer.isBuffer = function isBuffer(b) { return b instanceof Buffer; }; // Inspect Buffer.prototype.inspect = function inspect() { var out = [], len = this.length, name = this.constructor.name; for (var i = 0; i < len; i++) { out[i] = toHex(this[i]); if (i == exports.INSPECT_MAX_BYTES) { out[i + 1] = '...'; break; } } return '<' + name + ' ' + out.join(' ') + '>'; }; Buffer.prototype.get = function get(offset) { if (offset < 0 || offset >= this.length) throw new RangeError('offset is out of bounds'); return this.parent[this.offset + offset]; }; Buffer.prototype.set = function set(offset, v) { if (offset < 0 || offset >= this.length) throw new RangeError('offset is out of bounds'); return this.parent[this.offset + offset] = v; }; // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8') Buffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); if (string.length > 0 && (length < 0 || offset < 0)) throw new RangeError('attempt to write beyond buffer bounds'); var ret; switch (encoding) { case 'hex': ret = this.parent.hexWrite(string, this.offset + offset, length); break; case 'utf8': case 'utf-8': ret = this.parent.utf8Write(string, this.offset + offset, length); break; case 'ascii': ret = this.parent.asciiWrite(string, this.offset + offset, length); break; case 'binary': ret = this.parent.binaryWrite(string, this.offset + offset, length); break; case 'base64': // Warning: maxLength not taken into account in base64Write ret = this.parent.base64Write(string, this.offset + offset, length); break; case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': ret = this.parent.ucs2Write(string, this.offset + offset, length); break; default: throw new TypeError('Unknown encoding: ' + encoding); } Buffer._charsWritten = SlowBuffer._charsWritten; return ret; }; Buffer.prototype.toJSON = function () { // CHAKRA: since buffer is a Proxy object we are seeing Array.prototype.slice.call retunring an arrays of nulls // not sure if it's a bug or not, but this is a workaround for this issue if (process.ischakra) { var arr = new Array(this.length); for (var i = 0; i < this.length; i++) { // this will make sure that we are retreiving the value through the proxy arr[i] = this[i]; } return arr; } else { return Array.prototype.slice.call(this, 0); } }; // toString(encoding, start=0, end=buffer.length) Buffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); if (typeof start !== 'number' || start < 0) { start = 0; } else if (start > this.length) { start = this.length; } if (typeof end !== 'number' || end > this.length) { end = this.length; } else if (end < 0) { end = 0; } start = start + this.offset; end = end + this.offset; switch (encoding) { case 'hex': return this.parent.hexSlice(start, end); case 'utf8': case 'utf-8': return this.parent.utf8Slice(start, end); case 'ascii': return this.parent.asciiSlice(start, end); case 'binary': return this.parent.binarySlice(start, end); case 'base64': return this.parent.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.parent.ucs2Slice(start, end); default: throw new TypeError('Unknown encoding: ' + encoding); } }; // byteLength Buffer.byteLength = SlowBuffer.byteLength; // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function fill(value, start, end) { value || (value = 0); start || (start = 0); end || (end = this.length); if (typeof value === 'string') { value = value.charCodeAt(0); } if (typeof value !== 'number' || isNaN(value)) { throw new TypeError('value is not a number'); } if (end < start) throw new RangeError('end < start'); // Fill 0 bytes; we're done if (end === start) return 0; if (this.length == 0) return 0; if (start < 0 || start >= this.length) { throw new RangeError('start out of bounds'); } if (end < 0 || end > this.length) { throw new RangeError('end out of bounds'); } return this.parent.fill(value, start + this.offset, end + this.offset); }; Buffer.concat = function(list, length) { if (!Array.isArray(list)) { throw new TypeError('Usage: Buffer.concat(list, [length])'); } if (list.length === 0) { return new Buffer(0); } else if (list.length === 1) { return list[0]; } if (typeof length !== 'number') { length = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; length += buf.length; } } var buffer = new Buffer(length); var pos = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; buf.copy(buffer, pos); pos += buf.length; } return buffer; }; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function(target, target_start, start, end) { // set undefined/NaN or out of bounds values equal to their default if (!(target_start >= 0)) target_start = 0; if (!(start >= 0)) start = 0; if (!(end < this.length)) end = this.length; // Copy 0 bytes; we're done if (end === start || target.length === 0 || this.length === 0 || start > this.length) return 0; if (end < start) throw new RangeError('sourceEnd < sourceStart'); if (target_start >= target.length) throw new RangeError('targetStart out of bounds'); if (target.length - target_start < end - start) end = target.length - target_start + start; return this.parent.copy(target.parent || target, target_start + (target.offset || 0), start + this.offset, end + this.offset); }; // slice(start, end) Buffer.prototype.slice = function(start, end) { var len = this.length; start = clamp(start, len, 0); end = clamp(end, len, len); return new Buffer(this.parent, end - start, start + this.offset); }; // Legacy methods for backwards compatibility. Buffer.prototype.utf8Slice = function(start, end) { return this.toString('utf8', start, end); }; Buffer.prototype.binarySlice = function(start, end) { return this.toString('binary', start, end); }; Buffer.prototype.asciiSlice = function(start, end) { return this.toString('ascii', start, end); }; Buffer.prototype.utf8Write = function(string, offset) { return this.write(string, offset, 'utf8'); }; Buffer.prototype.binaryWrite = function(string, offset) { return this.write(string, offset, 'binary'); }; Buffer.prototype.asciiWrite = function(string, offset) { return this.write(string, offset, 'ascii'); }; /* * Need to make sure that buffer isn't trying to write out of bounds. * This check is far too slow internally for fast buffers. */ function checkOffset(offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint'); if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length'); } Buffer.prototype.readUInt8 = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length); return this[offset]; }; function readUInt16(buffer, offset, isBigEndian) { var val = 0; if (isBigEndian) { val = buffer[offset] << 8; val |= buffer[offset + 1]; } else { val = buffer[offset]; val |= buffer[offset + 1] << 8; } return val; } Buffer.prototype.readUInt16LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readUInt16(this, offset, false, noAssert); }; Buffer.prototype.readUInt16BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readUInt16(this, offset, true, noAssert); }; function readUInt32(buffer, offset, isBigEndian, noAssert) { var val = 0; if (isBigEndian) { val = buffer[offset + 1] << 16; val |= buffer[offset + 2] << 8; val |= buffer[offset + 3]; val = val + (buffer[offset] << 24 >>> 0); } else { val = buffer[offset + 2] << 16; val |= buffer[offset + 1] << 8; val |= buffer[offset]; val = val + (buffer[offset + 3] << 24 >>> 0); } return val; } Buffer.prototype.readUInt32LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readUInt32(this, offset, false, noAssert); }; Buffer.prototype.readUInt32BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readUInt32(this, offset, true, noAssert); }; /* * Signed integer types, yay team! A reminder on how two's complement actually * works. The first bit is the signed bit, i.e. tells us whether or not the * number should be positive or negative. If the two's complement value is * positive, then we're done, as it's equivalent to the unsigned representation. * * Now if the number is positive, you're pretty much done, you can just leverage * the unsigned translations and return those. Unfortunately, negative numbers * aren't quite that straightforward. * * At first glance, one might be inclined to use the traditional formula to * translate binary numbers between the positive and negative values in two's * complement. (Though it doesn't quite work for the most negative value) * Mainly: * - invert all the bits * - add one to the result * * Of course, this doesn't quite work in Javascript. Take for example the value * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of * course, Javascript will do the following: * * > ~0xff80 * -65409 * * Whoh there, Javascript, that's not quite right. But wait, according to * Javascript that's perfectly correct. When Javascript ends up seeing the * constant 0xff80, it has no notion that it is actually a signed number. It * assumes that we've input the unsigned value 0xff80. Thus, when it does the * binary negation, it casts it into a signed value, (positive 0xff80). Then * when you perform binary negation on that, it turns it into a negative number. * * Instead, we're going to have to use the following general formula, that works * in a rather Javascript friendly way. I'm glad we don't support this kind of * weird numbering scheme in the kernel. * * (BIT-MAX - (unsigned)val + 1) * -1 * * The astute observer, may think that this doesn't make sense for 8-bit numbers * (really it isn't necessary for them). However, when you get 16-bit numbers, * you do. Let's go back to our prior example and see how this will look: * * (0xffff - 0xff80 + 1) * -1 * (0x007f + 1) * -1 * (0x0080) * -1 */ Buffer.prototype.readInt8 = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length); if (!(this[offset] & 0x80)) return (this[offset]); return ((0xff - this[offset] + 1) * -1); }; function readInt16(buffer, offset, isBigEndian) { var val = readUInt16(buffer, offset, isBigEndian); if (!(val & 0x8000)) return val; return (0xffff - val + 1) * -1; } Buffer.prototype.readInt16LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readInt16(this, offset, false); }; Buffer.prototype.readInt16BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readInt16(this, offset, true); }; function readInt32(buffer, offset, isBigEndian) { var val = readUInt32(buffer, offset, isBigEndian); if (!(val & 0x80000000)) return (val); return (0xffffffff - val + 1) * -1; } Buffer.prototype.readInt32LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readInt32(this, offset, false); }; Buffer.prototype.readInt32BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readInt32(this, offset, true); }; Buffer.prototype.readFloatLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatLE(this.offset + offset, !!noAssert); }; Buffer.prototype.readFloatBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatBE(this.offset + offset, !!noAssert); }; Buffer.prototype.readDoubleLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleLE(this.offset + offset, !!noAssert); }; Buffer.prototype.readDoubleBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleBE(this.offset + offset, !!noAssert); }; function checkInt(buffer, value, offset, ext, max, min) { if ((value % 1) !== 0 || value > max || value < min) throw TypeError('value is out of bounds'); if ((offset % 1) !== 0 || offset < 0) throw TypeError('offset is not uint'); if (offset + ext > buffer.length || buffer.length + offset < 0) throw RangeError('Trying to write outside buffer length'); } Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); this[offset] = value; }; function writeUInt16(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value & 0xff00) >>> 8; buffer[offset + 1] = value & 0x00ff; } else { buffer[offset + 1] = (value & 0xff00) >>> 8; buffer[offset] = value & 0x00ff; } } Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); writeUInt16(this, value, offset, false); }; Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); writeUInt16(this, value, offset, true); }; function writeUInt32(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value >>> 24) & 0xff; buffer[offset + 1] = (value >>> 16) & 0xff; buffer[offset + 2] = (value >>> 8) & 0xff; buffer[offset + 3] = value & 0xff; } else { buffer[offset + 3] = (value >>> 24) & 0xff; buffer[offset + 2] = (value >>> 16) & 0xff; buffer[offset + 1] = (value >>> 8) & 0xff; buffer[offset] = value & 0xff; } } Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); writeUInt32(this, value, offset, false); }; Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); writeUInt32(this, value, offset, true); }; /* * We now move onto our friends in the signed number category. Unlike unsigned * numbers, we're going to have to worry a bit more about how we put values into * arrays. Since we are only worrying about signed 32-bit values, we're in * slightly better shape. Unfortunately, we really can't do our favorite binary * & in this system. It really seems to do the wrong thing. For example: * * > -32 & 0xff * 224 * * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of * this aren't treated as a signed number. Ultimately a bad thing. * * What we're going to want to do is basically create the unsigned equivalent of * our representation and pass that off to the wuint* functions. To do that * we're going to do the following: * * - if the value is positive * we can pass it directly off to the equivalent wuint * - if the value is negative * we do the following computation: * mb + val + 1, where * mb is the maximum unsigned value in that byte size * val is the Javascript negative integer * * * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If * you do out the computations: * * 0xffff - 128 + 1 * 0xffff - 127 * 0xff80 * * You can then encode this value as the signed version. This is really rather * hacky, but it should work and get the job done which is our goal here. */ Buffer.prototype.writeInt8 = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); if (value < 0) value = 0xff + value + 1; this[offset] = value; }; Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (value < 0) value = 0xffff + value + 1; writeUInt16(this, value, offset, false); }; Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (value < 0) value = 0xffff + value + 1; writeUInt16(this, value, offset, true); }; Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; writeUInt32(this, value, offset, false); }; Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; writeUInt32(this, value, offset, true); }; Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatLE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatBE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleLE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleBE(value, this.offset + offset, !!noAssert); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! // // UTILITY var util = require('util'); var pSlice = Array.prototype.slice; // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) assert.AssertionError = function AssertionError(options) { this.name = 'AssertionError'; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; this.message = options.message || getMessage(this); var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) Error.captureStackTrace(this, stackStartFunction); }; // assert.AssertionError instanceof Error util.inherits(assert.AssertionError, Error); function replacer(key, value) { if (value === undefined) { return '' + value; } if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) { return value.toString(); } if (typeof value === 'function' || value instanceof RegExp) { return value.toString(); } return value; } function truncate(s, n) { if (typeof s == 'string') { return s.length < n ? s : s.slice(0, n); } else { return s; } } function getMessage(self) { return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + self.operator + ' ' + truncate(JSON.stringify(self.expected, replacer), 128); } // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new assert.AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!!!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected)) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; function _deepEqual(actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { if (actual[i] !== expected[i]) return false; } return true; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (actual instanceof Date && expected instanceof Date) { return actual.getTime() === expected.getTime(); // 7.3 If the expected value is a RegExp object, the actual value is // equivalent if it is also a RegExp object with the same source and // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). } else if (actual instanceof RegExp && expected instanceof RegExp) { return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; // 7.4. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if (typeof actual != 'object' && typeof expected != 'object') { return actual == expected; // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else { return objEquiv(actual, expected); } } function isUndefinedOrNull(value) { return value === null || value === undefined; } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b) { if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false; // an identical 'prototype' property. if (a.prototype !== b.prototype) return false; //~~~I've managed to break Object.keys through screwy arguments passing. // Converting to array solves the problem. if (isArguments(a)) { if (!isArguments(b)) { return false; } a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b); } try { var ka = Object.keys(a), kb = Object.keys(b), key, i; } catch (e) {//happens when one is a string literal and the other isn't return false; } // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] != kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key])) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected)) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } else if (actual instanceof expected) { return true; } else if (expected.call({}, actual) === true) { return true; } return false; } function _throws(shouldThrow, block, expected, message) { var actual; if (typeof expected === 'string') { message = expected; expected = null; } try { block(); } catch (e) { actual = e; } message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } if (!shouldThrow && expectedException(actual, expected)) { fail(actual, expected, 'Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [true].concat(pSlice.call(arguments))); }; // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = function(block, /*optional*/message) { _throws.apply(this, [false].concat(pSlice.call(arguments))); }; assert.ifError = function(err) { if (err) {throw err;}}; shellcommon\shell\cortana\opensource\node\deps\logger\src\logger_wrap.cppnode_logger_wrapshellcommon\shell\cortana\opensource\node\deps\nativerequire\src\nativerequire_wrap.cppnode_nativerequire_wrapshellcommon\shell\cortana\opensource\node\lib\node_script.cppnode_evalsshellcommon\shell\cortana\opensource\node\lib\node_http_parser.cppnode_http_parsershellcommon\shell\cortana\opensource\node\lib\node_buffer.cppnode_buffershellcommon\shell\cortana\opensource\node\lib\pipe_wrap.cppnode_pipe_wrapshellcommon\shell\cortana\opensource\node\lib\cares_wrap.cppnode_cares_wrapshellcommon\shell\cortana\opensource\node\lib\fs_event_wrap.cppnode_fs_event_wrapshellcommon\shell\cortana\opensource\node\lib\node_file.cppnode_fsshellcommon\shell\cortana\opensource\node\lib\node_os.cppnode_osshellcommon\shell\cortana\opensource\node\lib\process_wrap.cppnode_process_wrapshellcommon\shell\cortana\opensource\node\lib\signal_wrap.cppnode_signal_wrapshellcommon\shell\cortana\opensource\node\lib\tcp_wrap.cppnode_tcp_wrapshellcommon\shell\cortana\opensource\node\lib\timer_wrap.cppnode_timer_wrapshellcommon\shell\cortana\opensource\node\lib\tty_wrap.cppnode_tty_wrapshellcommon\shell\cortana\opensource\node\lib\udp_wrap.cppnode_udp_wrapshellcommon\shell\cortana\opensource\node\lib\node_zlib.cppnode_zlib.ARegExp__isexternal__stackCollectGarbagegcgenericunknown erroriostreamiostream stream errorsystemjsrtUtils::InstanceOf(function() { var isInstanceOf = function(a,b) { return (a instanceof b); }; Object.defineProperty(this, '__isInstanceOf__', { enumerable: false, configurable: false, writable: false, value: isInstanceOf }); return this.__isInstanceOf__; }).call(this);hasOwnPropertyObjectjsrtUtils::isUint(function() { var isUintRegex = /^(0|[1-9]\d*)$/; var isUint = function(value) { var result = isUintRegex.test(value); isUintRegex.lastIndex = 0; return result; }; Object.defineProperty(this, '__isUint__', { enumerable: false, configurable: false, writable: false, value: isUint }); return this.__isUint__; }).call(this)jsrtUtils::getEnumerableNamedProperties(function() { var getEnumerableNamedProperties = function(obj, isUint) { var props = []; for (var key in obj) { if (!isUint(key)) props.push(key); } return props; }; Object.defineProperty(this, '__getEnumerableNamedProperties__', { enumerable: false, configurable: false, writable: false, value: getEnumerableNamedProperties }); return this.__getEnumerableNamedProperties__; }).call(this)jsrtUtils::getEnumerableIndexedProperties(function() { var getEnumerableIndexedProperties = function(obj, isUint) { var props = []; for (var key in obj) { if (isUint(key)) props.push(key); } return props; }; Object.defineProperty(this, '__getEnumerableIndexedProperties__', { enumerable: false, configurable: false, writable: false, value: getEnumerableIndexedProperties }); return this.__getEnumerableIndexedProperties__; }).call(this)jsrtUtils::getIndexedOwnKeys(function() { var getIndexedOwnKeys = function(obj, isUint) { var props = []; Object.keys(obj).forEach(function(item) { if (isUint(item)) props.push(item); }); return props; }; Object.defineProperty(this, '__getIndexedOwnKeys__', { enumerable: false, configurable: false, writable: false, value: getIndexedOwnKeys }); return this.__getIndexedOwnKeys__; }).call(this)jsrtUtils::getNamedOwnKeys(function() { var getNamedOwnKeys = function(obj, isUint) { var props = []; Object.keys(obj).forEach(function(item) { { if (!isUint(item)) props.push(item); } return props; }; Object.defineProperty(this, '__getNamedOwnKeys__', { enumerable: false, configurable: false, writable: false, value: getNamedOwnKeys }); return this.__getNamedOwnKeys__; }).call(this)jsrtUtils::createEnumerationIterator(function() { var createEnumerationIterator = function(props) { var i = 0; return { next: function() { if (i === props.length) return { done: true } return { value : props[i++] }; } }; }; Object.defineProperty(this, '__createEnumerationIterator__', { enumerable: false, configurable: false, writable: false, value: createEnumerationIterator }); return this.__createEnumerationIterator__; }).call(this)jsrtUtils::GetPropertyNames(function() { var getPropertyNames = function(a) { var names = []; for(var propertyName in a) { names.push(propertyName); } return names; }; Object.defineProperty(this, '__getPropertyNames__', { enumerable: false, configurable: false, writable: false, value: getPropertyNames }); return this.__getPropertyNames__; }).call(this);definePropertygetPropertyNamesgetOwnPropertyNamesgetPropertyDescriptorgetPrototypeOffreezesealpreventExtensionsisFrozenisSealedisExtensibleapplyconstructNo logger is currently setInvalid arguments, expected: [log level : number], [message : string], [guid : string, optional]Failed to convert given string to GUID structure. HRESULT:Invalid arguments, expected: [log level : number]LoadSourceCode Failed on CreateScriptString, for script name: %S, error code: %dLoadSourceCode Failed on GenerateScriptFromFile, for script name: %S, error code: %dRequireFromByteCodeCache: Source file loaded for script: %SRequireFromByteCodeCache: could not load source file: %dFailed to load script retrieved from bytecode cache: %sNativeRequireUtils::RequireFromString Failed on Script::Run, for script name: %S, returne value is emptyNativeRequireUtils::RequireFromString Failed on CreateScriptString, for script name: %S, error code: %dNativeRequireUtils::RequireFromString Failed on Script::New, for script name: %S, returned script is emptyRequire error: Failed to compile script codeRequire error: Failed to convert script code to wide char stringRequire error : Unknown error occured // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { var objects = []; for (var i = 0; i < arguments.length; i++) { objects.push(inspect(arguments[i])); } return objects.join(' '); } var i = 1; var args = arguments; var len = args.length; var str = String(f).replace(formatRegExp, function(x) { if (x === '%%') return '%'; if (i >= len) return x; switch (x) { case '%s': return String(args[i++]); case '%d': return Number(args[i++]); case '%j': return JSON.stringify(args[i++]); default: return x; } }); for (var x = args[i]; i < len; x = args[++i]) { if (x === null || typeof x !== 'object') { str += ' ' + x; } else { str += ' ' + inspect(x); } } return str; }; // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. exports.deprecate = function(fn, msg) { if (process.noDeprecation === true) { return fn; } var warned = false; function deprecated() { if (!warned) { if (process.throwDeprecation) { throw new Error(msg); } else if (process.traceDeprecation) { console.trace(msg); } else { console.error(msg); } warned = true; } return fn.apply(this, arguments); } return deprecated; }; exports.print = function() { for (var i = 0, len = arguments.length; i < len; ++i) { process.stdout.write(String(arguments[i])); } }; exports.puts = function() { for (var i = 0, len = arguments.length; i < len; ++i) { process.stdout.write(arguments[i] + '\n'); } }; exports.debug = function(x) { process.stderr.write('DEBUG: ' + x + '\n'); }; var error = exports.error = function(x) { for (var i = 0, len = arguments.length; i < len; ++i) { process.stderr.write(arguments[i] + '\n'); } }; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (typeof opts === 'boolean') { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object exports._extend(ctx, opts); } // set default options if (typeof ctx.showHidden === 'undefined') ctx.showHidden = false; if (typeof ctx.depth === 'undefined') ctx.depth = 2; if (typeof ctx.colors === 'undefined') ctx.colors = false; if (typeof ctx.customInspect === 'undefined') ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } exports.inspect = inspect; // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect.styles[styleType]; if (style) { return '\u001b[' + inspect.colors[style][0] + 'm' + str + '\u001b[' + inspect.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && typeof value.inspect === 'function' && // Filter out the util module, it's inspect function is special value.inspect !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { return String(value.inspect(recurseTimes)); } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (typeof value === 'function') { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (typeof value === 'function') { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { switch (typeof value) { case 'undefined': return ctx.stylize('undefined', 'undefined'); case 'string': var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); case 'number': return ctx.stylize('' + value, 'number'); case 'boolean': return ctx.stylize('' + value, 'boolean'); } // For some reason typeof null is "object", so special case here. if (value === null) { return ctx.stylize('null', 'null'); } } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (recurseTimes === null) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (typeof name === 'undefined') { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var numLinesEst = 0; var length = output.reduce(function(prev, cur) { numLinesEst++; if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar) || (typeof ar === 'object' && objectToString(ar) === '[object Array]'); } exports.isArray = isArray; function isRegExp(re) { return typeof re === 'object' && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; function isDate(d) { return typeof d === 'object' && objectToString(d) === '[object Date]'; } exports.isDate = isDate; function isError(e) { return typeof e === 'object' && objectToString(e) === '[object Error]'; } exports.isError = isError; function objectToString(o) { return Object.prototype.toString.call(o); } exports.p = exports.deprecate(function() { for (var i = 0, len = arguments.length; i < len; ++i) { error(exports.inspect(arguments[i])); } }, 'util.p: Use console.error() instead.'); function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); } var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // 26 Feb 16:19:34 function timestamp() { var d = new Date(); var time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join(':'); return [d.getDate(), months[d.getMonth()], time].join(' '); } exports.log = function(msg) { exports.puts(timestamp() + ' - ' + msg.toString()); }; exports.exec = exports.deprecate(function() { return require('child_process').exec.apply(this, arguments); }, 'util.exec is now called `child_process.exec`.'); function pump(readStream, writeStream, callback) { var callbackCalled = false; function call(a, b, c) { if (callback && !callbackCalled) { callback(a, b, c); callbackCalled = true; } } readStream.addListener('data', function(chunk) { if (writeStream.write(chunk) === false) readStream.pause(); }); writeStream.addListener('drain', function() { readStream.resume(); }); readStream.addListener('end', function() { writeStream.end(); }); readStream.addListener('close', function() { call(); }); readStream.addListener('error', function(err) { writeStream.end(); call(err); }); writeStream.addListener('error', function(err) { readStream.destroy(); call(err); }); } exports.pump = exports.deprecate(pump, 'util.pump() is deprecated. Use readableStream.pipe() instead.'); /** * Inherit the prototype methods from one constructor into another. * * The Function.prototype.inherits from lang.js rewritten as a standalone * function (not on Function.prototype). NOTE: If this file is to be loaded * during bootstrapping this function needs to be rewritten using some native * functions as prototype setup using normal JavaScript does not work as * expected during bootstrapping (see mirror.js in r114903). * * @param {function} ctor Constructor function which needs to inherit the * prototype. * @param {function} superCtor Constructor function to inherit prototype from. */ exports.inherits = function(ctor, superCtor) { ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; exports._extend = function(origin, add) { // Don't do anything if add isn't an object if (!add || typeof add !== 'object') return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; }; function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var StringDecoder = require('string_decoder').StringDecoder; var EventEmitter = require('events').EventEmitter; var net = require('net'); var dgram = require('dgram'); var Process = process.binding('process_wrap').Process; var assert = require('assert'); var util = require('util'); var constants; // if (!constants) constants = process.binding('constants'); var handleWraps = {}; function handleWrapGetter(name, callback) { var cons; Object.defineProperty(handleWraps, name, { get: function() { if (cons !== undefined) return cons; return cons = callback(); } }); } handleWrapGetter('Pipe', function() { return process.binding('pipe_wrap').Pipe; }); handleWrapGetter('TTY', function() { return process.binding('tty_wrap').TTY; }); handleWrapGetter('TCP', function() { return process.binding('tcp_wrap').TCP; }); handleWrapGetter('UDP', function() { return process.binding('udp_wrap').UDP; }); // constructors for lazy loading function createPipe(ipc) { return new handleWraps.Pipe(ipc); } function createSocket(pipe, readable) { var s = new net.Socket({ handle: pipe }); if (readable) { s.writable = false; s.readable = true; } else { s.writable = true; s.readable = false; } return s; } // this object contain function to convert TCP objects to native handle objects // and back again. var handleConversion = { 'net.Native': { simultaneousAccepts: true, send: function(message, handle) { return handle; }, got: function(message, handle, emit) { emit(handle); } }, 'net.Server': { simultaneousAccepts: true, send: function(message, server) { return server._handle; }, got: function(message, handle, emit) { var self = this; var server = new net.Server(); server.listen(handle, function() { emit(server); }); } }, 'net.Socket': { send: function(message, socket) { // if the socket was created by net.Server if (socket.server) { // the slave should keep track of the socket message.key = socket.server._connectionKey; var firstTime = !this._channel.sockets.send[message.key]; var socketList = getSocketList('send', this, message.key); // the server should no longer expose a .connection property // and when asked to close it should query the socket status from // the slaves if (firstTime) socket.server._setupSlave(socketList); // Act like socket is detached socket.server._connections--; } // remove handle from socket object, it will be closed when the socket // will be sent var handle = socket._handle; handle.onread = function() {}; socket._handle = null; return handle; }, postSend: function(handle) { // Close the Socket handle after sending it handle.close(); }, got: function(message, handle, emit) { var socket = new net.Socket({handle: handle}); socket.readable = socket.writable = true; // if the socket was created by net.Server we will track the socket if (message.key) { // add socket to connections list var socketList = getSocketList('got', this, message.key); socketList.add({ socket: socket }); } emit(socket); } }, 'dgram.Native': { simultaneousAccepts: false, send: function(message, handle) { return handle; }, got: function(message, handle, emit) { emit(handle); } }, 'dgram.Socket': { simultaneousAccepts: false, send: function(message, socket) { message.dgramType = socket.type; return socket._handle; }, got: function(message, handle, emit) { var socket = new dgram.Socket(message.dgramType); socket.bind(handle, function() { emit(socket); }); } } }; // This object keep track of the socket there are sended function SocketListSend(slave, key) { EventEmitter.call(this); var self = this; this.key = key; this.slave = slave; } util.inherits(SocketListSend, EventEmitter); SocketListSend.prototype._request = function(msg, cmd, callback) { var self = this; if (!this.slave.connected) return onclose(); this.slave.send(msg); function onclose() { self.slave.removeListener('internalMessage', onreply); callback(new Error('Slave closed before reply')); }; function onreply(msg) { if (!(msg.cmd === cmd && msg.key === self.key)) return; self.slave.removeListener('disconnect', onclose); self.slave.removeListener('internalMessage', onreply); callback(null, msg); }; this.slave.once('disconnect', onclose); this.slave.on('internalMessage', onreply); }; SocketListSend.prototype.close = function close(callback) { this._request({ cmd: 'NODE_SOCKET_NOTIFY_CLOSE', key: this.key }, 'NODE_SOCKET_ALL_CLOSED', callback); }; SocketListSend.prototype.getConnections = function getConnections(callback) { this._request({ cmd: 'NODE_SOCKET_GET_COUNT', key: this.key }, 'NODE_SOCKET_COUNT', function(err, msg) { if (err) return callback(err); callback(null, msg.count); }); }; // This object keep track of the socket there are received function SocketListReceive(slave, key) { EventEmitter.call(this); var self = this; this.connections = 0; this.key = key; this.slave = slave; function onempty() { if (!self.slave.connected) return; self.slave.send({ cmd: 'NODE_SOCKET_ALL_CLOSED', key: self.key }); } this.slave.on('internalMessage', function(msg) { if (msg.key !== self.key) return; if (msg.cmd === 'NODE_SOCKET_NOTIFY_CLOSE') { // Already empty if (self.connections === 0) return onempty(); // Wait for sockets to get closed self.once('empty', onempty); } else if (msg.cmd === 'NODE_SOCKET_GET_COUNT') { if (!self.slave.connected) return; self.slave.send({ cmd: 'NODE_SOCKET_COUNT', key: self.key, count: self.connections }); } }); } util.inherits(SocketListReceive, EventEmitter); SocketListReceive.prototype.add = function(obj) { var self = this; this.connections++; // Notify previous owner of socket about its state change obj.socket.once('close', function() { self.connections--; if (self.connections === 0) self.emit('empty'); }); }; function getSocketList(type, slave, key) { var sockets = slave._channel.sockets[type]; var socketList = sockets[key]; if (!socketList) { var Construct = type === 'send' ? SocketListSend : SocketListReceive; socketList = sockets[key] = new Construct(slave, key); } return socketList; } var INTERNAL_PREFIX = 'NODE_'; function handleMessage(target, message, handle) { var eventName = 'message'; if (message !== null && typeof message === 'object' && typeof message.cmd === 'string' && message.cmd.length > INTERNAL_PREFIX.length && message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX) { eventName = 'internalMessage'; } target.emit(eventName, message, handle); } function setupChannel(target, channel) { target._channel = channel; target._handleQueue = null; var decoder = new StringDecoder('utf8'); var jsonBuffer = ''; channel.buffering = false; channel.onread = function(pool, offset, length, recvHandle) { if (pool) { jsonBuffer += decoder.write(pool.slice(offset, offset + length)); var i, start = 0; //Linebreak is used as a message end sign while ((i = jsonBuffer.indexOf('\n', start)) >= 0) { var json = jsonBuffer.slice(start, i); var message = JSON.parse(json); // There will be at most one NODE_HANDLE message in every chunk we // read because SCM_RIGHTS messages don't get coalesced. Make sure // that we deliver the handle with the right message however. if (message && message.cmd === 'NODE_HANDLE') handleMessage(target, message, recvHandle); else handleMessage(target, message, undefined); start = i + 1; } jsonBuffer = jsonBuffer.slice(start); this.buffering = jsonBuffer.length !== 0; } else { this.buffering = false; target.disconnect(); channel.onread = nop; channel.close(); maybeClose(target); } }; // object where socket lists will live channel.sockets = { got: {}, send: {} }; // handlers will go through this target.on('internalMessage', function(message, handle) { // Once acknowledged - continue sending handles. if (message.cmd === 'NODE_HANDLE_ACK') { assert(Array.isArray(target._handleQueue)); var queue = target._handleQueue; target._handleQueue = null; queue.forEach(function(args) { target.send(args.message, args.handle); }); return; } if (message.cmd !== 'NODE_HANDLE') return; // Acknowledge handle receival. target.send({ cmd: 'NODE_HANDLE_ACK' }); var obj = handleConversion[message.type]; // Update simultaneous accepts on Windows if (process.platform === 'win32') { handle._simultaneousAccepts = false; net._setSimultaneousAccepts(handle); } // Convert handle object obj.got.call(this, message, handle, function(handle) { handleMessage(target, message.msg, handle); }); }); target.send = function(message, handle) { if (typeof message === 'undefined') { throw new TypeError('message cannot be undefined'); } if (!this.connected) { this.emit('error', new Error('channel closed')); return; } // package messages with a handle object if (handle) { // this message will be handled by an internalMessage event handler message = { cmd: 'NODE_HANDLE', type: null, msg: message }; if (handle instanceof net.Socket) { message.type = 'net.Socket'; } else if (handle instanceof net.Server) { message.type = 'net.Server'; } else if (handle instanceof process.binding('tcp_wrap').TCP || handle instanceof process.binding('pipe_wrap').Pipe) { message.type = 'net.Native'; } else if (handle instanceof dgram.Socket) { message.type = 'dgram.Socket'; } else if (handle instanceof process.binding('udp_wrap').UDP) { message.type = 'dgram.Native'; } else { throw new TypeError("This handle type can't be sent"); } // Queue-up message and handle if we haven't received ACK yet. if (this._handleQueue) { this._handleQueue.push({ message: message.msg, handle: handle }); return; } var obj = handleConversion[message.type]; // convert TCP object to native handle object handle = handleConversion[message.type].send.apply(target, arguments); // Update simultaneous accepts on Windows if (obj.simultaneousAccepts) { net._setSimultaneousAccepts(handle); } } else if (this._handleQueue) { // Queue request anyway to avoid out-of-order messages. this._handleQueue.push({ message: message, handle: null }); return; } var string = JSON.stringify(message) + '\n'; var writeReq = channel.writeUtf8String(string, handle); if (!writeReq) { var er = errnoException(process._errno, 'write', 'cannot write to IPC channel.'); this.emit('error', er); } else if (handle && !this._handleQueue) { this._handleQueue = []; } if (obj && obj.postSend) { writeReq.oncomplete = obj.postSend.bind(null, handle); } else { writeReq.oncomplete = nop; } /* If the master is > 2 read() calls behind, please stop sending. */ return channel.writeQueueSize < (65536 * 2); }; target.connected = true; target.disconnect = function() { if (!this.connected) { this.emit('error', new Error('IPC channel is already disconnected')); return; } // do not allow messages to be written this.connected = false; this._channel = null; var fired = false; function finish() { if (fired) return; fired = true; channel.close(); target.emit('disconnect'); } // If a message is being read, then wait for it to complete. if (channel.buffering) { this.once('message', finish); this.once('internalMessage', finish); return; } finish(); }; channel.readStart(); } function nop() { } exports.fork = function(modulePath /*, args, options*/) { // Get options and args arguments. var options, args, execArgv; if (Array.isArray(arguments[1])) { args = arguments[1]; options = util._extend({}, arguments[2]); } else { args = []; options = util._extend({}, arguments[1]); } // Prepare arguments for fork: execArgv = options.execArgv || process.execArgv; args = execArgv.concat([modulePath], args); // Leave stdin open for the IPC channel. stdout and stderr should be the // same as the parent's if silent isn't set. options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] : [0, 1, 2, 'ipc']; options.execPath = options.execPath || process.execPath; return spawn(options.execPath, args, options); }; exports._forkChild = function(fd) { // set process.send() var p = createPipe(true); p.open(fd); p.unref(); setupChannel(process, p); var refs = 0; process.on('newListener', function(name) { if (name !== 'message' && name !== 'disconnect') return; if (++refs === 1) p.ref(); }); process.on('removeListener', function(name) { if (name !== 'message' && name !== 'disconnect') return; if (--refs === 0) p.unref(); }); }; exports.exec = function(command /*, options, callback */) { var file, args, options, callback; if (typeof arguments[1] === 'function') { options = undefined; callback = arguments[1]; } else { options = arguments[1]; callback = arguments[2]; } if (process.platform === 'win32') { file = 'cmd.exe'; args = ['/s', '/c', '"' + command + '"']; // Make a shallow copy before patching so we don't clobber the user's // options object. options = util._extend({}, options); options.windowsVerbatimArguments = true; } else { file = '/bin/sh'; args = ['-c', command]; } return exports.execFile(file, args, options, callback); }; exports.execFile = function(file /* args, options, callback */) { var args, optionArg, callback; var options = { encoding: 'utf8', timeout: 0, maxBuffer: 200 * 1024, killSignal: 'SIGTERM', cwd: null, env: null }; // Parse the parameters. if (typeof arguments[arguments.length - 1] === 'function') { callback = arguments[arguments.length - 1]; } if (Array.isArray(arguments[1])) { args = arguments[1]; options = util._extend(options, arguments[2]); } else { args = []; options = util._extend(options, arguments[1]); } var child = spawn(file, args, { cwd: options.cwd, env: options.env, windowsVerbatimArguments: !!options.windowsVerbatimArguments }); var stdout = ''; var stderr = ''; var killed = false; var exited = false; var timeoutId; var err; function exithandler(code, signal) { if (exited) return; exited = true; if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } if (!callback) return; if (err) { callback(err, stdout, stderr); } else if (code === 0 && signal === null) { callback(null, stdout, stderr); } else { var e = new Error('Command failed: ' + stderr); e.killed = child.killed || killed; e.code = code; e.signal = signal; callback(e, stdout, stderr); } } function errorhandler(e) { err = e; child.stdout.destroy(); child.stderr.destroy(); exithandler(); } function kill() { child.stdout.destroy(); child.stderr.destroy(); killed = true; try { child.kill(options.killSignal); } catch (e) { err = e; exithandler(); } } if (options.timeout > 0) { timeoutId = setTimeout(function() { kill(); timeoutId = null; }, options.timeout); } child.stdout.setEncoding(options.encoding); child.stderr.setEncoding(options.encoding); child.stdout.addListener('data', function(chunk) { stdout += chunk; if (stdout.length > options.maxBuffer) { err = new Error('stdout maxBuffer exceeded.'); kill(); } }); child.stderr.addListener('data', function(chunk) { stderr += chunk; if (stderr.length > options.maxBuffer) { err = new Error('stderr maxBuffer exceeded.'); kill(); } }); child.addListener('close', exithandler); child.addListener('error', errorhandler); return child; }; var spawn = exports.spawn = function(file, args, options) { args = args ? args.slice(0) : []; args.unshift(file); var env = (options ? options.env : null) || process.env; var envPairs = []; for (var key in env) { envPairs.push(key + '=' + env[key]); } var child = new ChildProcess(); if (options && options.customFds && !options.stdio) { options.stdio = options.customFds.map(function(fd) { return fd === -1 ? 'pipe' : fd; }); } child.spawn({ file: file, args: args, cwd: options ? options.cwd : null, windowsVerbatimArguments: !!(options && options.windowsVerbatimArguments), detached: !!(options && options.detached), envPairs: envPairs, stdio: options ? options.stdio : null, uid: options ? options.uid : null, gid: options ? options.gid : null }); return child; }; function maybeClose(subprocess) { subprocess._closesGot++; if (subprocess._closesGot == subprocess._closesNeeded) { subprocess.emit('close', subprocess.exitCode, subprocess.signalCode); } } function ChildProcess() { EventEmitter.call(this); // Initialize TCPWrap and PipeWrap process.binding('tcp_wrap'); process.binding('pipe_wrap'); var self = this; this._closesNeeded = 1; this._closesGot = 0; this.connected = false; this.signalCode = null; this.exitCode = null; this.killed = false; this._handle = new Process(); this._handle.owner = this; this._handle.onexit = function(exitCode, signalCode) { // // follow 0.4.x behaviour: // // - normally terminated processes don't touch this.signalCode // - signaled processes don't touch this.exitCode // // new in 0.9.x: // // - spawn failures are reported with exitCode == -1 // var err = (exitCode == -1) ? errnoException(process._errno, 'spawn') : null; if (signalCode) { self.signalCode = signalCode; } else { self.exitCode = exitCode; } if (self.stdin) { self.stdin.destroy(); } self._handle.close(); self._handle = null; if (exitCode == -1) { self.emit('error', err); } else { self.emit('exit', self.exitCode, self.signalCode); } // if any of the stdio streams have not been touched, // then pull all the data through so that it can get the // eof and emit a 'close' event. // Do it on nextTick so that the user has one last chance // to consume the output, if for example they only want to // start reading the data once the process exits. process.nextTick(function() { flushStdio(self); }); maybeClose(self); }; } util.inherits(ChildProcess, EventEmitter); function flushStdio(subprocess) { subprocess.stdio.forEach(function(stream, fd, stdio) { if (!stream || !stream.readable || stream._consuming || stream._readableState.flowing) return; stream.resume(); }); } function getHandleWrapType(stream) { if (stream instanceof handleWraps.Pipe) return 'pipe'; if (stream instanceof handleWraps.TTY) return 'tty'; if (stream instanceof handleWraps.TCP) return 'tcp'; if (stream instanceof handleWraps.UDP) return 'udp'; return false; } ChildProcess.prototype.spawn = function(options) { var self = this, ipc, ipcFd, // If no `stdio` option was given - use default stdio = options.stdio || 'pipe'; // Replace shortcut with an array if (typeof stdio === 'string') { switch (stdio) { case 'ignore': stdio = ['ignore', 'ignore', 'ignore']; break; case 'pipe': stdio = ['pipe', 'pipe', 'pipe']; break; case 'inherit': stdio = [0, 1, 2]; break; default: throw new TypeError('Incorrect value of stdio option: ' + stdio); } } else if (!Array.isArray(stdio)) { throw new TypeError('Incorrect value of stdio option: ' + stdio); } // At least 3 stdio will be created // Don't concat() a new Array() because it would be sparse, and // stdio.reduce() would skip the sparse elements of stdio. // See http://stackoverflow.com/a/5501711/3561 while (stdio.length < 3) stdio.push(undefined); // Translate stdio into C++-readable form // (i.e. PipeWraps or fds) stdio = stdio.reduce(function(acc, stdio, i) { function cleanup() { acc.filter(function(stdio) { return stdio.type === 'pipe' || stdio.type === 'ipc'; }).forEach(function(stdio) { stdio.handle.close(); }); } // Defaults if (stdio === undefined || stdio === null) { stdio = i < 3 ? 'pipe' : 'ignore'; } if (stdio === 'ignore') { acc.push({type: 'ignore'}); } else if (stdio === 'pipe' || typeof stdio === 'number' && stdio < 0) { acc.push({type: 'pipe', handle: createPipe()}); } else if (stdio === 'ipc') { if (ipc !== undefined) { // Cleanup previously created pipes cleanup(); throw Error('Child process can have only one IPC pipe'); } ipc = createPipe(true); ipcFd = i; acc.push({ type: 'pipe', handle: ipc, ipc: true }); } else if (typeof stdio === 'number' || typeof stdio.fd === 'number') { acc.push({ type: 'fd', fd: stdio.fd || stdio }); } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) || getHandleWrapType(stdio._handle)) { var handle = getHandleWrapType(stdio) ? stdio : getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle; acc.push({ type: 'wrap', wrapType: getHandleWrapType(handle), handle: handle }); } else { // Cleanup cleanup(); throw new TypeError('Incorrect value for stdio stream: ' + stdio); } return acc; }, []); options.stdio = stdio; if (ipc !== undefined) { // Let child process know about opened IPC channel options.envPairs = options.envPairs || []; options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd); } var r = this._handle.spawn(options); if (r) { // Close all opened fds on error stdio.forEach(function(stdio) { if (stdio.type === 'pipe') { stdio.handle.close(); } }); this._handle.close(); this._handle = null; throw errnoException(process._errno, 'spawn'); } this.pid = this._handle.pid; stdio.forEach(function(stdio, i) { if (stdio.type === 'ignore') return; if (stdio.ipc) { self._closesNeeded++; return; } if (stdio.handle) { // when i === 0 - we're dealing with stdin // (which is the only one writable pipe) stdio.socket = createSocket(self.pid !== 0 ? stdio.handle : null, i > 0); if (i > 0 && self.pid !== 0) { self._closesNeeded++; stdio.socket.on('close', function() { maybeClose(self); }); } } }); this.stdin = stdio.length >= 1 && stdio[0].socket !== undefined ? stdio[0].socket : null; this.stdout = stdio.length >= 2 && stdio[1].socket !== undefined ? stdio[1].socket : null; this.stderr = stdio.length >= 3 && stdio[2].socket !== undefined ? stdio[2].socket : null; this.stdio = stdio.map(function(stdio) { return stdio.socket === undefined ? null : stdio.socket; }); // Add .send() method and start listening for IPC data if (ipc !== undefined) setupChannel(this, ipc); return r; }; function errnoException(errorno, syscall, errmsg) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var message = syscall + ' ' + errorno; if (errmsg) { message += ' - ' + errmsg; } var e = new Error(message); e.errno = e.code = errorno; e.syscall = syscall; return e; } ChildProcess.prototype.kill = function(sig) { var signal; if (!constants) { constants = process.binding('constants'); } if (sig === 0) { signal = 0; } else if (!sig) { signal = constants['SIGTERM']; } else { signal = constants[sig]; } if (signal === undefined) { throw new Error('Unknown signal: ' + sig); } if (this._handle) { var r = this._handle.kill(signal); if (r == 0) { /* Success. */ this.killed = true; return true; } else if (process._errno == 'ESRCH') { /* Already dead. */ } else if (process._errno == 'EINVAL' || process._errno == 'ENOSYS') { /* The underlying platform doesn't support this signal. */ throw errnoException(process._errno, 'kill'); } else { /* Other error, almost certainly EPERM. */ this.emit('error', errnoException(process._errno, 'kill')); } } /* Kill didn't succeed. */ return false; }; ChildProcess.prototype.ref = function() { if (this._handle) this._handle.ref(); }; ChildProcess.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var events = require('events'); var stream = require('stream'); var timers = require('timers'); var util = require('util'); var assert = require('assert'); var cares; var cluster; function noop() {} // constructor for lazy loading function createPipe() { var Pipe = process.binding('pipe_wrap').Pipe; return new Pipe(); } // constructor for lazy loading function createTCP() { var TCP = process.binding('tcp_wrap').TCP; return new TCP(); } function createHandle(fd) { var tty = process.binding('tty_wrap'); var type = tty.guessHandleType(fd); if (type === 'PIPE') return createPipe(); if (type === 'TCP') return createTCP(); throw new TypeError('Unsupported fd type: ' + type); } var debug; if (process.env.NODE_DEBUG && /net/.test(process.env.NODE_DEBUG)) { var pid = process.pid; debug = function(x) { // if console is not set up yet, then skip this. if (!console.error) return; console.error('NET: %d', pid, util.format.apply(util, arguments).slice(0, 500)); }; } else { debug = function() { }; } function isPipeName(s) { return typeof s === 'string' && toNumber(s) === false; } exports.createServer = function() { return new Server(arguments[0], arguments[1]); }; // Target API: // // var s = net.connect({port: 80, host: 'google.com'}, function() { // ... // }); // // There are various forms: // // connect(options, [cb]) // connect(port, [host], [cb]) // connect(path, [cb]); // exports.connect = exports.createConnection = function() { var args = normalizeConnectArgs(arguments); var s = new Socket(args[0]); return Socket.prototype.connect.apply(s, args); }; // Returns an array [options] or [options, cb] // It is the same as the argument of Socket.prototype.connect(). function normalizeConnectArgs(args) { var options = {}; if (typeof args[0] === 'object') { // connect(options, [cb]) options = args[0]; } else if (isPipeName(args[0])) { // connect(path, [cb]); options.path = args[0]; } else { // connect(port, [host], [cb]) options.port = args[0]; if (typeof args[1] === 'string') { options.host = args[1]; } } var cb = args[args.length - 1]; return (typeof cb === 'function') ? [options, cb] : [options]; } exports._normalizeConnectArgs = normalizeConnectArgs; // called when creating new Socket, or when re-using a closed Socket function initSocketHandle(self) { self.destroyed = false; self.errorEmitted = false; self.bytesRead = 0; self._bytesDispatched = 0; // Handle creation may be deferred to bind() or connect() time. if (self._handle) { self._handle.owner = self; self._handle.onread = onread; } } function Socket(options) { if (!(this instanceof Socket)) return new Socket(options); this._connecting = false; this._handle = null; switch (typeof options) { case 'number': options = { fd: options }; // Legacy interface. break; case 'undefined': options = {}; break; } stream.Duplex.call(this, options); if (options.handle) { this._handle = options.handle; // private } else if (typeof options.fd !== 'undefined') { this._handle = createHandle(options.fd); this._handle.open(options.fd); this.readable = options.readable !== false; this.writable = options.writable !== false; } else { // these will be set once there is a connection this.readable = this.writable = false; } this.onend = null; // shut down the socket when we're finished with it. this.on('finish', onSocketFinish); this.on('_socketEnd', onSocketEnd); initSocketHandle(this); this._pendingData = null; this._pendingEncoding = ''; // handle strings directly this._writableState.decodeStrings = false; // default to *not* allowing half open sockets this.allowHalfOpen = options && options.allowHalfOpen || false; // if we have a handle, then start the flow of data into the // buffer. if not, then this will happen when we connect if (this._handle && options.readable !== false) this.read(0); } util.inherits(Socket, stream.Duplex); // the user has called .end(), and all the bytes have been // sent out to the other side. // If allowHalfOpen is false, or if the readable side has // ended already, then destroy. // If allowHalfOpen is true, then we need to do a shutdown, // so that only the writable side will be cleaned up. function onSocketFinish() { // If still connecting - defer handling 'finish' until 'connect' will happen if (this._connecting) { debug('osF: not yet connected'); return this.once('connect', onSocketFinish); } debug('onSocketFinish'); if (!this.readable || this._readableState.ended) { debug('oSF: ended, destroy', this._readableState); return this.destroy(); } debug('oSF: not ended, call shutdown()'); // otherwise, just shutdown, or destroy() if not possible if (!this._handle || !this._handle.shutdown) return this.destroy(); var shutdownReq = this._handle.shutdown(); if (!shutdownReq) return this._destroy(errnoException(process._errno, 'shutdown')); shutdownReq.oncomplete = afterShutdown; } function afterShutdown(status, handle, req) { var self = handle.owner; debug('afterShutdown destroyed=%j', self.destroyed, self._readableState); // callback may come after call to destroy. if (self.destroyed) return; if (self._readableState.ended) { debug('readableState ended, destroying'); self.destroy(); } else { self.once('_socketEnd', self.destroy); } } // the EOF has been received, and no more bytes are coming. // if the writable side has ended already, then clean everything // up. function onSocketEnd() { // XXX Should not have to do as much crap in this function. // ended should already be true, since this is called *after* // the EOF errno and onread has eof'ed debug('onSocketEnd', this._readableState); this._readableState.ended = true; if (this._readableState.endEmitted) { this.readable = false; } else { this.once('end', function() { this.readable = false; }); this.read(0); } if (!this.allowHalfOpen) { this.write = writeAfterFIN; this.destroySoon(); } } // Provide a better error message when we call end() as a result // of the other side sending a FIN. The standard 'write after end' // is overly vague, and makes it seem like the user's code is to blame. function writeAfterFIN(chunk, encoding, cb) { if (typeof encoding === 'function') { cb = encoding; encoding = null; } var er = new Error('This socket has been ended by the other party'); er.code = 'EPIPE'; var self = this; // TODO: defer error events consistently everywhere, not just the cb self.emit('error', er); if (typeof cb === 'function') { process.nextTick(function() { cb(er); }); } } exports.Socket = Socket; exports.Stream = Socket; // Legacy naming. Socket.prototype.read = function(n) { if (n === 0) return stream.Readable.prototype.read.call(this, n); this.read = stream.Readable.prototype.read; this._consuming = true; return this.read(n); }; Socket.prototype.listen = function() { debug('socket.listen'); var self = this; self.on('connection', arguments[0]); listen(self, null, null, null); }; Socket.prototype.setTimeout = function(msecs, callback) { if (msecs > 0 && !isNaN(msecs) && isFinite(msecs)) { timers.enroll(this, msecs); timers._unrefActive(this); if (callback) { this.once('timeout', callback); } } else if (msecs === 0) { timers.unenroll(this); if (callback) { this.removeListener('timeout', callback); } } }; Socket.prototype._onTimeout = function() { debug('_onTimeout'); this.emit('timeout'); }; Socket.prototype.setNoDelay = function(enable) { // backwards compatibility: assume true when `enable` is omitted if (this._handle && this._handle.setNoDelay) this._handle.setNoDelay(typeof enable === 'undefined' ? true : !!enable); }; Socket.prototype.setKeepAlive = function(setting, msecs) { if (this._handle && this._handle.setKeepAlive) this._handle.setKeepAlive(setting, ~~(msecs / 1000)); }; Socket.prototype.address = function() { if (this._handle && this._handle.getsockname) { return this._handle.getsockname(); } return null; }; Object.defineProperty(Socket.prototype, 'readyState', { get: function() { if (this._connecting) { return 'opening'; } else if (this.readable && this.writable) { return 'open'; } else if (this.readable && !this.writable) { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; } else { return 'closed'; } } }); Object.defineProperty(Socket.prototype, 'bufferSize', { get: function() { if (this._handle) { return this._handle.writeQueueSize + this._writableState.length; } } }); // Just call handle.readStart until we have enough in the buffer Socket.prototype._read = function(n) { debug('_read'); if (this._connecting || !this._handle) { debug('_read wait for connection'); this.once('connect', this._read.bind(this, n)); } else if (!this._handle.reading) { // not already reading, start the flow debug('Socket._read readStart'); this._handle.reading = true; var r = this._handle.readStart(); if (r) this._destroy(errnoException(process._errno, 'read')); } }; Socket.prototype.end = function(data, encoding) { stream.Duplex.prototype.end.call(this, data, encoding); this.writable = false; DTRACE_NET_STREAM_END(this); // just in case we're waiting for an EOF. if (this.readable && !this._readableState.endEmitted) this.read(0); return; }; Socket.prototype.destroySoon = function() { if (this.writable) this.end(); if (this._writableState.finished) this.destroy(); else this.once('finish', this.destroy); }; Socket.prototype._destroy = function(exception, cb) { debug('destroy'); var self = this; function fireErrorCallbacks() { if (cb) cb(exception); if (exception && !self.errorEmitted) { process.nextTick(function() { self.emit('error', exception); }); self.errorEmitted = true; } }; if (this.destroyed) { debug('already destroyed, fire error callbacks'); fireErrorCallbacks(); return; } self._connecting = false; this.readable = this.writable = false; timers.unenroll(this); debug('close'); if (this._handle) { if (this !== process.stderr) debug('close handle'); var isException = exception ? true : false; this._handle.close(function() { debug('emit close'); self.emit('close', isException); }); this._handle.onread = noop; this._handle = null; } fireErrorCallbacks(); this.destroyed = true; if (this.server) { COUNTER_NET_SERVER_CONNECTION_CLOSE(this); debug('has server'); this.server._connections--; if (this.server._emitCloseIfDrained) { this.server._emitCloseIfDrained(); } } }; Socket.prototype.destroy = function(exception) { debug('destroy', exception); this._destroy(exception); }; // This function is called whenever the handle gets a // buffer, or when there's an error reading. function onread(buffer, offset, length) { var handle = this; var self = handle.owner; assert(handle === self._handle, 'handle != self._handle'); timers._unrefActive(self); var end = offset + length; debug('onread', process._errno, offset, length, end); if (buffer) { debug('got data'); // read success. // In theory (and in practice) calling readStop right now // will prevent this from being called again until _read() gets // called again. // if we didn't get any bytes, that doesn't necessarily mean EOF. // wait for the next one. if (offset === end) { debug('not any data, keep waiting'); return; } // if it's not enough data, we'll just call handle.readStart() // again right away. self.bytesRead += length; // Optimization: emit the original buffer with end points var ret = true; // nadavbar: back ported the DoS fix issue: https://github.com/joyent/node/commit/653d4db71f569ddc87a0bc21f5ecc5ceaf37f932 if (self.ondata && !self._drain_paused) self.ondata(buffer, offset, end); else ret = self.push(buffer.slice(offset, end)); if (handle.reading && !ret) { handle.reading = false; debug('readStop'); var r = handle.readStop(); if (r) self._destroy(errnoException(process._errno, 'read')); } } else if (process._errno == 'EOF') { debug('EOF'); if (self._readableState.length === 0) self.readable = false; if (self.onend) self.once('end', self.onend); // push a null to signal the end of data. self.push(null); // internal end event so that we know that the actual socket // is no longer readable, and we can start the shutdown // procedure. No need to wait for all the data to be consumed. self.emit('_socketEnd'); } else { debug('error', process._errno); // Error self._destroy(errnoException(process._errno, 'read')); } } Socket.prototype._getpeername = function() { if (!this._handle || !this._handle.getpeername) { return {}; } if (!this._peername) { this._peername = this._handle.getpeername(); // getpeername() returns null on error if (this._peername === null) { return {}; } } return this._peername; }; Socket.prototype.__defineGetter__('remoteAddress', function() { return this._getpeername().address; }); Socket.prototype.__defineGetter__('remotePort', function() { return this._getpeername().port; }); Socket.prototype._getsockname = function() { if (!this._handle || !this._handle.getsockname) { return {}; } if (!this._sockname) { this._sockname = this._handle.getsockname(); if (this._sockname === null) { return {}; } } return this._sockname; }; Socket.prototype.__defineGetter__('localAddress', function() { return this._getsockname().address; }); Socket.prototype.__defineGetter__('localPort', function() { return this._getsockname().port; }); Socket.prototype.write = function(chunk, encoding, cb) { if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) throw new TypeError('invalid data'); return stream.Duplex.prototype.write.apply(this, arguments); }; Socket.prototype._write = function(data, encoding, cb) { // If we are still connecting, then buffer this for later. // The Writable logic will buffer up any more writes while // waiting for this one to be done. if (this._connecting) { this._pendingData = data; this._pendingEncoding = encoding; this.once('connect', function() { this._write(data, encoding, cb); }); return; } this._pendingData = null; this._pendingEncoding = ''; timers._unrefActive(this); if (!this._handle) { this._destroy(new Error('This socket is closed.'), cb); return false; } var enc = Buffer.isBuffer(data) ? 'buffer' : encoding; var writeReq = createWriteReq(this._handle, data, enc); if (!writeReq || typeof writeReq !== 'object') return this._destroy(errnoException(process._errno, 'write'), cb); writeReq.oncomplete = afterWrite; this._bytesDispatched += writeReq.bytes; // If it was entirely flushed, we can write some more right now. // However, if more is left in the queue, then wait until that clears. if (this._handle.writeQueueSize === 0) cb(); else writeReq.cb = cb; }; function createWriteReq(handle, data, encoding) { switch (encoding) { case 'buffer': return handle.writeBuffer(data); case 'utf8': case 'utf-8': return handle.writeUtf8String(data); case 'ascii': return handle.writeAsciiString(data); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return handle.writeUcs2String(data); default: return handle.writeBuffer(new Buffer(data, encoding)); } } Socket.prototype.__defineGetter__('bytesWritten', function() { var bytes = this._bytesDispatched, state = this._writableState, data = this._pendingData, encoding = this._pendingEncoding; state.buffer.forEach(function(el) { if (Buffer.isBuffer(el.chunk)) bytes += el.chunk.length; else bytes += Buffer.byteLength(el.chunk, el.encoding); }); if (data) { if (Buffer.isBuffer(data)) bytes += data.length; else bytes += Buffer.byteLength(data, encoding); } return bytes; }); function afterWrite(status, handle, req) { var self = handle.owner; var state = self._writableState; if (self !== process.stderr && self !== process.stdout) debug('afterWrite', status, req); // callback may come after call to destroy. if (self.destroyed) { debug('afterWrite destroyed'); return; } if (status) { debug('write failure', errnoException(process._errno, 'write')); self._destroy(errnoException(process._errno, 'write'), req.cb); return; } timers._unrefActive(self); if (self !== process.stderr && self !== process.stdout) debug('afterWrite call cb'); if (req.cb) req.cb.call(self); } function connect(self, address, port, addressType, localAddress) { // TODO return promise from Socket.prototype.connect which // wraps _connectReq. assert.ok(self._connecting); if (localAddress) { var r; if (addressType == 6) { r = self._handle.bind6(localAddress); } else { r = self._handle.bind(localAddress); } if (r) { self._destroy(errnoException(process._errno, 'bind')); return; } } var connectReq; if (addressType == 6) { connectReq = self._handle.connect6(address, port); } else if (addressType == 4) { connectReq = self._handle.connect(address, port); } else { connectReq = self._handle.connect(address, afterConnect); } if (connectReq !== null) { connectReq.oncomplete = afterConnect; } else { self._destroy(errnoException(process._errno, 'connect')); } } Socket.prototype.connect = function(options, cb) { if (this.write !== Socket.prototype.write) this.write = Socket.prototype.write; if (typeof options !== 'object') { // Old API: // connect(port, [host], [cb]) // connect(path, [cb]); var args = normalizeConnectArgs(arguments); return Socket.prototype.connect.apply(this, args); } if (this.destroyed) { this._readableState.reading = false; this._readableState.ended = false; this._writableState.ended = false; this._writableState.ending = false; this._writableState.finished = false; this.destroyed = false; this._handle = null; } var self = this; var pipe = !!options.path; if (!this._handle) { this._handle = pipe ? createPipe() : createTCP(); initSocketHandle(this); } if (typeof cb === 'function') { self.once('connect', cb); } timers._unrefActive(this); self._connecting = true; self.writable = true; if (pipe) { connect(self, options.path); } else if (!options.host) { debug('connect: missing host'); connect(self, '127.0.0.1', options.port, 4); } else { var host = options.host; debug('connect: find host ' + host); require('dns').lookup(host, function(err, ip, addressType) { // It's possible we were destroyed while looking this up. // XXX it would be great if we could cancel the promise returned by // the look up. if (!self._connecting) return; if (err) { // net.createConnection() creates a net.Socket object and // immediately calls net.Socket.connect() on it (that's us). // There are no event listeners registered yet so defer the // error event to the next tick. process.nextTick(function() { self.emit('error', err); self._destroy(); }); } else { timers._unrefActive(self); addressType = addressType || 4; // node_net.cc handles null host names graciously but user land // expects remoteAddress to have a meaningful value ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1'); connect(self, ip, options.port, addressType, options.localAddress); } }); } return self; }; Socket.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Socket.prototype.unref = function() { if (this._handle) this._handle.unref(); }; function afterConnect(status, handle, req, readable, writable) { var self = handle.owner; // callback may come after call to destroy if (self.destroyed) { return; } assert(handle === self._handle, 'handle != self._handle'); debug('afterConnect'); assert.ok(self._connecting); self._connecting = false; if (status == 0) { self.readable = readable; self.writable = writable; timers._unrefActive(self); self.emit('connect'); // start the first read, or get an immediate EOF. // this doesn't actually consume any bytes, because len=0. if (readable) self.read(0); } else { self._connecting = false; self._destroy(errnoException(process._errno, 'connect')); } } function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function Server(/* [ options, ] listener */) { if (!(this instanceof Server)) return new Server(arguments[0], arguments[1]); events.EventEmitter.call(this); var self = this; var options; if (typeof arguments[0] == 'function') { options = {}; self.on('connection', arguments[0]); } else { options = arguments[0] || {}; if (typeof arguments[1] == 'function') { self.on('connection', arguments[1]); } } this._connections = 0; Object.defineProperty(this, 'connections', { get: util.deprecate(function() { if (self._usingSlaves) { return null; } return self._connections; }, 'connections property is deprecated. Use getConnections() method'), set: util.deprecate(function(val) { return (self._connections = val); }, 'connections property is deprecated. Use getConnections() method'), configurable: true, enumerable: true }); this._handle = null; this._usingSlaves = false; this._slaves = []; this.allowHalfOpen = options.allowHalfOpen || false; } util.inherits(Server, events.EventEmitter); exports.Server = Server; function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; } var createServerHandle = exports._createServerHandle = function(address, port, addressType, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { var r = 0; // assign handle in listen, and clean up if bind or listen fails var handle; if (typeof fd === 'number' && fd >= 0) { try { handle = createHandle(fd); } catch (e) { // Not a fd we can listen on. This will trigger an error. debug('listen invalid fd=' + fd + ': ' + e.message); process._errno = 'EINVAL'; // hack, callers expect that errno is set return null; } handle.open(fd); handle.readable = true; handle.writable = true; return handle; } else if (port == -1 && addressType == -1) { handle = createPipe(); if (process.platform === 'win32') { var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); if (!isNaN(instances)) { handle.setPendingInstances(instances); } } } else { handle = createTCP(); } if (address || port) { debug('bind to ' + address); if (addressType == 6) { r = handle.bind6(address, port); } else { if (defineSecurityProps) { // Chakra/WP addition if (pipeNameForSecurityDescriptor) { r = handle.bind(address, port, defineSecurityProps, pipeNameForSecurityDescriptor); } else { r = handle.bind(address, port, defineSecurityProps); } } else { r = handle.bind(address, port); } } } if (r) { handle.close(); handle = null; } return handle; }; Server.prototype._listen2 = function (address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { debug('listen2', address, port, addressType, backlog); var self = this; var r = 0; // If there is not yet a handle, we need to create one and bind. // In the case of a server sent via IPC, we don't need to do this. if (!self._handle) { debug('_listen2: create a handle'); self._handle = createServerHandle(address, port, addressType, fd, defineSecurityProps, pipeNameForSecurityDescriptor, pipeNameForSecurityDescriptor); if (!self._handle) { var error = errnoException(process._errno, 'listen'); process.nextTick(function() { self.emit('error', error); }); return; } } else { debug('_listen2: have a handle already'); } self._handle.onconnection = onconnection; self._handle.owner = self; // Use a backlog of 512 entries. We pass 511 to the listen() call because // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); // which will thus give us a backlog of 512 entries. r = self._handle.listen(backlog || 511); if (r) { var ex = errnoException(process._errno, 'listen'); self._handle.close(); self._handle = null; process.nextTick(function() { self.emit('error', ex); }); return; } // generate connection key, this should be unique to the connection this._connectionKey = addressType + ':' + address + ':' + port; process.nextTick(function() { self.emit('listening'); }); }; function listen(self, address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor) { if (!cluster) cluster = require('cluster'); if (cluster.isMaster) { self._listen2(address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor); return; } cluster._getServer(self, address, port, addressType, fd, function(handle) { // Some operating systems (notably OS X and Solaris) don't report EADDRINUSE // errors right away. libuv mimics that behavior for the sake of platform // consistency but that means we have have a socket on our hands that is // not actually bound. That's why we check if the actual port matches what // we requested and if not, raise an error. The exception is when port == 0 // because that means "any random port". if (port && handle.getsockname && port != handle.getsockname().port) { self.emit('error', errnoException('EADDRINUSE', 'bind')); return; } self._handle = handle; self._listen2(address, port, addressType, backlog, fd, defineSecurityProps, pipeNameForSecurityDescriptor); }); } Server.prototype.listen = function() { var self = this; var lastArg = arguments[arguments.length - 1]; if (typeof lastArg == 'function') { self.once('listening', lastArg); } var port = toNumber(arguments[0]); // The third optional argument is the backlog size. // When the ip is omitted it can be the second argument. var backlog = toNumber(arguments[1]) || toNumber(arguments[2]); var TCP = process.binding('tcp_wrap').TCP; if (arguments.length == 0 || typeof arguments[0] == 'function') { // Bind to a random port. listen(self, '0.0.0.0', 0, null, backlog); } else if (arguments[0] && typeof arguments[0] === 'object') { var h = arguments[0]; if (h._handle) { h = h._handle; } else if (h.handle) { h = h.handle; } if (h instanceof TCP) { self._handle = h; listen(self, null, -1, -1, backlog); } else if (typeof h.fd === 'number' && h.fd >= 0) { listen(self, null, null, null, backlog, h.fd); } else { throw new Error('Invalid listen argument: ' + h); } } else if (isPipeName(arguments[0])) { // UNIX socket or Windows pipe. var pipeName = self._pipeName = arguments[0]; // Chakra/WP addition var defineSecurityProps = false; var pipeNameForSecurityProps = null; var defineSecurityPropsIndex = 1; if (backlog && typeof arguments[defineSecurityPropsIndex] != 'boolean') { defineSecurityPropsIndex = 2; } if (typeof arguments[defineSecurityPropsIndex] == 'boolean') { defineSecurityProps = arguments[defineSecurityPropsIndex]; if (typeof arguments[defineSecurityPropsIndex + 1] == 'string') { pipeNameForSecurityProps = arguments[defineSecurityPropsIndex + 1]; } } // end of Chakra/ WP addition listen(self, pipeName, -1, -1, backlog, null, defineSecurityProps, pipeNameForSecurityProps); } else if (typeof arguments[1] == 'undefined' || typeof arguments[1] == 'function' || typeof arguments[1] == 'number') { // The first argument is the port, no IP given. listen(self, '0.0.0.0', port, 4, backlog); } else { // The first argument is the port, the second an IP. // Chakra/Threshold addition. if (arguments[1] === '127.0.0.1') { listen(self, '127.0.0.1', port, 4, backlog); } else if (arguments[1] === '[::1]' || arguments[1] === '::1') { listen(self, '::1', port, 6, backlog); } else { // End of Chakra/Threshold addition. require('dns').lookup(arguments[1], function(err, ip, addressType) { if (err) { self.emit('error', err); } else { listen(self, ip || '0.0.0.0', port, ip ? addressType : 4, backlog); } }); } } return self; }; Server.prototype.address = function() { if (this._handle && this._handle.getsockname) { return this._handle.getsockname(); } else if (this._pipeName) { return this._pipeName; } else { return null; } }; function onconnection(clientHandle) { var handle = this; var self = handle.owner; debug('onconnection'); if (!clientHandle) { self.emit('error', errnoException(process._errno, 'accept')); return; } if (self.maxConnections && self._connections >= self.maxConnections) { clientHandle.close(); return; } var socket = new Socket({ handle: clientHandle, allowHalfOpen: self.allowHalfOpen }); socket.readable = socket.writable = true; self._connections++; socket.server = self; DTRACE_NET_SERVER_CONNECTION(socket); COUNTER_NET_SERVER_CONNECTION(socket); self.emit('connection', socket); } Server.prototype.getConnections = function(cb) { function end(err, connections) { process.nextTick(function() { cb(err, connections); }); } if (!this._usingSlaves) { return end(null, this._connections); } // Poll slaves var left = this._slaves.length, total = this._connections; function oncount(err, count) { if (err) { left = -1; return end(err); } total += count; if (--left === 0) return end(null, total); } this._slaves.forEach(function(slave) { slave.getConnections(oncount); }); }; Server.prototype.close = function(cb) { function onSlaveClose() { if (--left !== 0) return; self._connections = 0; self._emitCloseIfDrained(); } if (!this._handle) { // Throw error. Follows net_legacy behaviour. throw new Error('Not running'); } if (cb) { this.once('close', cb); } this._handle.close(); this._handle = null; if (this._usingSlaves) { var self = this, left = this._slaves.length; // Increment connections to be sure that, even if all sockets will be closed // during polling of slaves, `close` event will be emitted only once. this._connections++; // Poll slaves this._slaves.forEach(function(slave) { slave.close(onSlaveClose); }); } else { this._emitCloseIfDrained(); } return this; }; Server.prototype._emitCloseIfDrained = function() { debug('SERVER _emitCloseIfDrained'); var self = this; if (self._handle || self._connections) { debug('SERVER handle? %j connections? %d', !!self._handle, self._connections); return; } process.nextTick(function() { debug('SERVER: emit close'); self.emit('close'); }); }; Server.prototype.listenFD = util.deprecate(function(fd, type) { return this.listen({ fd: fd }); }, 'listenFD is deprecated. Use listen({fd: }).'); Server.prototype._setupSlave = function(socketList) { this._usingSlaves = true; this._slaves.push(socketList); }; Server.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Server.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // TODO: isIP should be moved to the DNS code. Putting it here now because // this is what the legacy system did. exports.isIP = function() { cares = cares || process.binding('cares_wrap'); return cares.isIP.apply(this, arguments); } exports.isIPv4 = function(input) { return exports.isIP(input) === 4; }; exports.isIPv6 = function(input) { return exports.isIP(input) === 6; }; if (process.platform === 'win32') { var simultaneousAccepts; exports._setSimultaneousAccepts = function(handle) { if (typeof handle === 'undefined') { return; } if (typeof simultaneousAccepts === 'undefined') { simultaneousAccepts = (process.env.NODE_MANY_ACCEPTS && process.env.NODE_MANY_ACCEPTS !== '0'); } if (handle._simultaneousAccepts !== simultaneousAccepts) { handle.setSimultaneousAccepts(simultaneousAccepts); handle._simultaneousAccepts = simultaneousAccepts; } }; } else { exports._setSimultaneousAccepts = function(handle) {}; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Inspiration for this code comes from Salvatore Sanfilippo's linenoise. // https://github.com/antirez/linenoise // Reference: // * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html // * http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html var kHistorySize = 30; var kBufSize = 10 * 1024; var util = require('util'); var inherits = require('util').inherits; var EventEmitter = require('events').EventEmitter; exports.createInterface = function(input, output, completer, terminal) { var rl; if (arguments.length === 1) { rl = new Interface(input); } else { rl = new Interface(input, output, completer, terminal); } return rl; }; function Interface(input, output, completer, terminal) { if (!(this instanceof Interface)) { return new Interface(input, output, completer, terminal); } this._sawReturn = false; EventEmitter.call(this); if (arguments.length === 1) { // an options object was given output = input.output; completer = input.completer; terminal = input.terminal; input = input.input; } completer = completer || function() { return []; }; if (typeof completer !== 'function') { throw new TypeError('Argument \'completer\' must be a function'); } // backwards compat; check the isTTY prop of the output stream // when `terminal` was not specified if (typeof terminal == 'undefined') { terminal = !!output.isTTY; } var self = this; this.output = output; this.input = input; // Check arity, 2 - for async, 1 for sync this.completer = completer.length === 2 ? completer : function(v, callback) { callback(null, completer(v)); }; this.setPrompt('> '); this.terminal = !!terminal; function ondata(data) { self._normalWrite(data); } function onend() { self.close(); } function onkeypress(s, key) { self._ttyWrite(s, key); } function onresize() { self._refreshLine(); } if (!this.terminal) { input.on('data', ondata); input.on('end', onend); self.once('close', function() { input.removeListener('data', ondata); input.removeListener('end', onend); }); var StringDecoder = require('string_decoder').StringDecoder; // lazy load this._decoder = new StringDecoder('utf8'); } else { exports.emitKeypressEvents(input); // input usually refers to stdin input.on('keypress', onkeypress); // Current line this.line = ''; this._setRawMode(true); this.terminal = true; // Cursor position on the line. this.cursor = 0; this.history = []; this.historyIndex = -1; output.on('resize', onresize); self.once('close', function() { input.removeListener('keypress', onkeypress); output.removeListener('resize', onresize); }); } input.resume(); } inherits(Interface, EventEmitter); Interface.prototype.__defineGetter__('columns', function() { return this.output.columns || Infinity; }); Interface.prototype.setPrompt = function(prompt, length) { this._prompt = prompt; if (length) { this._promptLength = length; } else { var lines = prompt.split(/[\r\n]/); var lastLine = lines[lines.length - 1]; this._promptLength = lastLine.length; } }; Interface.prototype._setRawMode = function(mode) { if (typeof this.input.setRawMode === 'function') { return this.input.setRawMode(mode); } }; Interface.prototype.prompt = function(preserveCursor) { if (this.paused) this.resume(); if (this.terminal) { if (!preserveCursor) this.cursor = 0; this._refreshLine(); } else { this.output.write(this._prompt); } }; Interface.prototype.question = function(query, cb) { if (typeof cb === 'function') { if (this._questionCallback) { this.prompt(); } else { this._oldPrompt = this._prompt; this.setPrompt(query); this._questionCallback = cb; this.prompt(); } } }; Interface.prototype._onLine = function(line) { if (this._questionCallback) { var cb = this._questionCallback; this._questionCallback = null; this.setPrompt(this._oldPrompt); cb(line); } else { this.emit('line', line); } }; Interface.prototype._addHistory = function() { if (this.line.length === 0) return ''; if (this.history.length === 0 || this.history[0] !== this.line) { this.history.unshift(this.line); // Only store so many if (this.history.length > kHistorySize) this.history.pop(); } this.historyIndex = -1; return this.history[0]; }; Interface.prototype._refreshLine = function() { var columns = this.columns; // line length var line = this._prompt + this.line; var lineLength = line.length; var lineCols = lineLength % columns; var lineRows = (lineLength - lineCols) / columns; // cursor position var cursorPos = this._getCursorPos(); // first move to the bottom of the current line, based on cursor pos var prevRows = this.prevRows || 0; if (prevRows > 0) { exports.moveCursor(this.output, 0, -prevRows); } // Cursor to left edge. exports.cursorTo(this.output, 0); // erase data exports.clearScreenDown(this.output); // Write the prompt and the current buffer content. this.output.write(line); // Force terminal to allocate a new line if (lineCols === 0) { this.output.write(' '); } // Move cursor to original position. exports.cursorTo(this.output, cursorPos.cols); var diff = lineRows - cursorPos.rows; if (diff > 0) { exports.moveCursor(this.output, 0, -diff); } this.prevRows = cursorPos.rows; }; Interface.prototype.close = function() { if (this.closed) return; if (this.terminal) { this._setRawMode(false); } this.pause(); this.closed = true; this.emit('close'); }; Interface.prototype.pause = function() { if (this.paused) return; this.input.pause(); this.paused = true; this.emit('pause'); }; Interface.prototype.resume = function() { if (!this.paused) return; this.input.resume(); this.paused = false; this.emit('resume'); }; Interface.prototype.write = function(d, key) { if (this.paused) this.resume(); this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d); }; // \r\n, \n, or \r followed by something other than \n var lineEnding = /\r?\n|\r(?!\n)/; Interface.prototype._normalWrite = function(b) { if (b === undefined) { return; } var string = this._decoder.write(b); if (this._sawReturn) { string = string.replace(/^\n/, ''); this._sawReturn = false; } if (this._line_buffer) { string = this._line_buffer + string; this._line_buffer = null; } if (lineEnding.test(string)) { this._sawReturn = /\r$/.test(string); // got one or more newlines; process into "line" events var lines = string.split(lineEnding); // either '' or (concievably) the unfinished portion of the next line string = lines.pop(); this._line_buffer = string; lines.forEach(function(line) { this._onLine(line); }, this); } else if (string) { // no newlines this time, save what we have for next time this._line_buffer = string; } }; Interface.prototype._insertString = function(c) { //BUG: Problem when adding tabs with following content. // Perhaps the bug is in _refreshLine(). Not sure. // A hack would be to insert spaces instead of literal '\t'. if (this.cursor < this.line.length) { var beg = this.line.slice(0, this.cursor); var end = this.line.slice(this.cursor, this.line.length); this.line = beg + c + end; this.cursor += c.length; this._refreshLine(); } else { this.line += c; this.cursor += c.length; if (this._getCursorPos().cols === 0) { this._refreshLine(); } else { this.output.write(c); } // a hack to get the line refreshed if it's needed this._moveCursor(0); } }; Interface.prototype._tabComplete = function() { var self = this; self.pause(); self.completer(self.line.slice(0, self.cursor), function(err, rv) { self.resume(); if (err) { // XXX Log it somewhere? return; } var completions = rv[0], completeOn = rv[1]; // the text that was completed if (completions && completions.length) { // Apply/show completions. if (completions.length === 1) { self._insertString(completions[0].slice(completeOn.length)); } else { self.output.write('\r\n'); var width = completions.reduce(function(a, b) { return a.length > b.length ? a : b; }).length + 2; // 2 space padding var maxColumns = Math.floor(self.columns / width) || 1; var group = [], c; for (var i = 0, compLen = completions.length; i < compLen; i++) { c = completions[i]; if (c === '') { handleGroup(self, group, width, maxColumns); group = []; } else { group.push(c); } } handleGroup(self, group, width, maxColumns); // If there is a common prefix to all matches, then apply that // portion. var f = completions.filter(function(e) { if (e) return e; }); var prefix = commonPrefix(f); if (prefix.length > completeOn.length) { self._insertString(prefix.slice(completeOn.length)); } } self._refreshLine(); } }); }; // this = Interface instance function handleGroup(self, group, width, maxColumns) { if (group.length == 0) { return; } var minRows = Math.ceil(group.length / maxColumns); for (var row = 0; row < minRows; row++) { for (var col = 0; col < maxColumns; col++) { var idx = row * maxColumns + col; if (idx >= group.length) { break; } var item = group[idx]; self.output.write(item); if (col < maxColumns - 1) { for (var s = 0, itemLen = item.length; s < width - itemLen; s++) { self.output.write(' '); } } } self.output.write('\r\n'); } self.output.write('\r\n'); } function commonPrefix(strings) { if (!strings || strings.length == 0) { return ''; } var sorted = strings.slice().sort(); var min = sorted[0]; var max = sorted[sorted.length - 1]; for (var i = 0, len = min.length; i < len; i++) { if (min[i] != max[i]) { return min.slice(0, i); } } return min; } Interface.prototype._wordLeft = function() { if (this.cursor > 0) { var leading = this.line.slice(0, this.cursor); var match = leading.match(/([^\w\s]+|\w+|)\s*$/); this._moveCursor(-match[0].length); } }; Interface.prototype._wordRight = function() { if (this.cursor < this.line.length) { var trailing = this.line.slice(this.cursor); var match = trailing.match(/^(\s+|\W+|\w+)\s*/); this._moveCursor(match[0].length); } }; Interface.prototype._deleteLeft = function() { if (this.cursor > 0 && this.line.length > 0) { this.line = this.line.slice(0, this.cursor - 1) + this.line.slice(this.cursor, this.line.length); this.cursor--; this._refreshLine(); } }; Interface.prototype._deleteRight = function() { this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1, this.line.length); this._refreshLine(); }; Interface.prototype._deleteWordLeft = function() { if (this.cursor > 0) { var leading = this.line.slice(0, this.cursor); var match = leading.match(/([^\w\s]+|\w+|)\s*$/); leading = leading.slice(0, leading.length - match[0].length); this.line = leading + this.line.slice(this.cursor, this.line.length); this.cursor = leading.length; this._refreshLine(); } }; Interface.prototype._deleteWordRight = function() { if (this.cursor < this.line.length) { var trailing = this.line.slice(this.cursor); var match = trailing.match(/^(\s+|\W+|\w+)\s*/); this.line = this.line.slice(0, this.cursor) + trailing.slice(match[0].length); this._refreshLine(); } }; Interface.prototype._deleteLineLeft = function() { this.line = this.line.slice(this.cursor); this.cursor = 0; this._refreshLine(); }; Interface.prototype._deleteLineRight = function() { this.line = this.line.slice(0, this.cursor); this._refreshLine(); }; Interface.prototype.clearLine = function() { this._moveCursor(+Infinity); this.output.write('\r\n'); this.line = ''; this.cursor = 0; this.prevRows = 0; }; Interface.prototype._line = function() { var line = this._addHistory(); this.clearLine(); this._onLine(line); }; Interface.prototype._historyNext = function() { if (this.historyIndex > 0) { this.historyIndex--; this.line = this.history[this.historyIndex]; this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } else if (this.historyIndex === 0) { this.historyIndex = -1; this.cursor = 0; this.line = ''; this._refreshLine(); } }; Interface.prototype._historyPrev = function() { if (this.historyIndex + 1 < this.history.length) { this.historyIndex++; this.line = this.history[this.historyIndex]; this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } }; // Returns current cursor's position and line Interface.prototype._getCursorPos = function() { var columns = this.columns; var cursorPos = this.cursor + this._promptLength; var cols = cursorPos % columns; var rows = (cursorPos - cols) / columns; return {cols: cols, rows: rows}; }; // This function moves cursor dx places to the right // (-dx for left) and refreshes the line if it is needed Interface.prototype._moveCursor = function(dx) { var oldcursor = this.cursor; var oldPos = this._getCursorPos(); this.cursor += dx; // bounds check if (this.cursor < 0) this.cursor = 0; if (this.cursor > this.line.length) this.cursor = this.line.length; var newPos = this._getCursorPos(); // check if cursors are in the same line if (oldPos.rows === newPos.rows) { exports.moveCursor(this.output, this.cursor - oldcursor, 0); this.prevRows = newPos.rows; } else { this._refreshLine(); } }; // handle a write from the tty Interface.prototype._ttyWrite = function(s, key) { key = key || {}; // Ignore escape key - Fixes #2876 if (key.name == 'escape') return; if (key.ctrl && key.shift) { /* Control and shift pressed */ switch (key.name) { case 'backspace': this._deleteLineLeft(); break; case 'delete': this._deleteLineRight(); break; } } else if (key.ctrl) { /* Control key pressed */ switch (key.name) { case 'c': if (EventEmitter.listenerCount(this, 'SIGINT') > 0) { this.emit('SIGINT'); } else { // This readline instance is finished this.close(); } break; case 'h': // delete left this._deleteLeft(); break; case 'd': // delete right or EOF if (this.cursor === 0 && this.line.length === 0) { // This readline instance is finished this.close(); } else if (this.cursor < this.line.length) { this._deleteRight(); } break; case 'u': // delete the whole line this.cursor = 0; this.line = ''; this._refreshLine(); break; case 'k': // delete from current to end of line this._deleteLineRight(); break; case 'a': // go to the start of the line this._moveCursor(-Infinity); break; case 'e': // go to the end of the line this._moveCursor(+Infinity); break; case 'b': // back one character this._moveCursor(-1); break; case 'f': // forward one character this._moveCursor(+1); break; case 'n': // next history item this._historyNext(); break; case 'p': // previous history item this._historyPrev(); break; case 'z': if (process.platform == 'win32') break; if (EventEmitter.listenerCount(this, 'SIGTSTP') > 0) { this.emit('SIGTSTP'); } else { process.once('SIGCONT', (function(self) { return function() { // Don't raise events if stream has already been abandoned. if (!self.paused) { // Stream must be paused and resumed after SIGCONT to catch // SIGINT, SIGTSTP, and EOF. self.pause(); self.emit('SIGCONT'); } // explictly re-enable "raw mode" and move the cursor to // the correct position. // See https://github.com/joyent/node/issues/3295. self._setRawMode(true); self._refreshLine(); }; })(this)); this._setRawMode(false); process.kill(process.pid, 'SIGTSTP'); } break; case 'w': // delete backwards to a word boundary case 'backspace': this._deleteWordLeft(); break; case 'delete': // delete forward to a word boundary this._deleteWordRight(); break; case 'backspace': this._deleteWordLeft(); break; case 'left': this._wordLeft(); break; case 'right': this._wordRight(); break; } } else if (key.meta) { /* Meta key pressed */ switch (key.name) { case 'b': // backward word this._wordLeft(); break; case 'f': // forward word this._wordRight(); break; case 'd': // delete forward word case 'delete': this._deleteWordRight(); break; case 'backspace': // delete backwards to a word boundary this._deleteWordLeft(); break; } } else { /* No modifier keys used */ // \r bookkeeping is only relevant if a \n comes right after. if (this._sawReturn && key.name !== 'enter') this._sawReturn = false; switch (key.name) { case 'return': // carriage return, i.e. \r this._sawReturn = true; this._line(); break; case 'enter': if (this._sawReturn) this._sawReturn = false; else this._line(); break; case 'backspace': this._deleteLeft(); break; case 'delete': this._deleteRight(); break; case 'tab': // tab completion this._tabComplete(); break; case 'left': this._moveCursor(-1); break; case 'right': this._moveCursor(+1); break; case 'home': this._moveCursor(-Infinity); break; case 'end': this._moveCursor(+Infinity); break; case 'up': this._historyPrev(); break; case 'down': this._historyNext(); break; default: if (Buffer.isBuffer(s)) s = s.toString('utf-8'); if (s) { var lines = s.split(/\r\n|\n|\r/); for (var i = 0, len = lines.length; i < len; i++) { if (i > 0) { this._line(); } this._insertString(lines[i]); } } } } }; exports.Interface = Interface; /** * accepts a readable Stream instance and makes it emit "keypress" events */ function emitKeypressEvents(stream) { if (stream._keypressDecoder) return; var StringDecoder = require('string_decoder').StringDecoder; // lazy load stream._keypressDecoder = new StringDecoder('utf8'); function onData(b) { if (EventEmitter.listenerCount(stream, 'keypress') > 0) { var r = stream._keypressDecoder.write(b); if (r) emitKey(stream, r); } else { // Nobody's watching anyway stream.removeListener('data', onData); stream.on('newListener', onNewListener); } } function onNewListener(event) { if (event == 'keypress') { stream.on('data', onData); stream.removeListener('newListener', onNewListener); } } if (EventEmitter.listenerCount(stream, 'keypress') > 0) { stream.on('data', onData); } else { stream.on('newListener', onNewListener); } } exports.emitKeypressEvents = emitKeypressEvents; /* Some patterns seen in terminal key escape codes, derived from combos seen at http://www.midnight-commander.org/browser/lib/tty/key.c ESC letter ESC [ letter ESC [ modifier letter ESC [ 1 ; modifier letter ESC [ num char ESC [ num ; modifier char ESC O letter ESC O modifier letter ESC O 1 ; modifier letter ESC N letter ESC [ [ num ; modifier char ESC [ [ 1 ; modifier letter ESC ESC [ num char ESC ESC O letter - char is usually ~ but $ and ^ also happen with rxvt - modifier is 1 + (shift * 1) + (left_alt * 2) + (ctrl * 4) + (right_alt * 8) - two leading ESCs apparently mean the same as one leading ESC */ // Regexes used for ansi escape code splitting var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; var functionKeyCodeRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; function emitKey(stream, s) { var ch, key = { name: undefined, ctrl: false, meta: false, shift: false }, parts; if (Buffer.isBuffer(s)) { if (s[0] > 127 && s[1] === undefined) { s[0] -= 128; s = '\x1b' + s.toString(stream.encoding || 'utf-8'); } else { s = s.toString(stream.encoding || 'utf-8'); } } key.sequence = s; if (s === '\r') { // carriage return key.name = 'return'; } else if (s === '\n') { // enter, should have been called linefeed key.name = 'enter'; } else if (s === '\t') { // tab key.name = 'tab'; } else if (s === '\b' || s === '\x7f' || s === '\x1b\x7f' || s === '\x1b\b') { // backspace or ctrl+h key.name = 'backspace'; key.meta = (s.charAt(0) === '\x1b'); } else if (s === '\x1b' || s === '\x1b\x1b') { // escape key key.name = 'escape'; key.meta = (s.length === 2); } else if (s === ' ' || s === '\x1b ') { key.name = 'space'; key.meta = (s.length === 2); } else if (s <= '\x1a') { // ctrl+letter key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); key.ctrl = true; } else if (s.length === 1 && s >= 'a' && s <= 'z') { // lowercase letter key.name = s; } else if (s.length === 1 && s >= 'A' && s <= 'Z') { // shift+letter key.name = s.toLowerCase(); key.shift = true; } else if (parts = metaKeyCodeRe.exec(s)) { // meta+character key key.name = parts[1].toLowerCase(); key.meta = true; key.shift = /^[A-Z]$/.test(parts[1]); } else if (parts = functionKeyCodeRe.exec(s)) { // ansi escape sequence // reassemble the key code leaving out leading \x1b's, // the modifier key bitflag and any meaningless "1;" sequence var code = (parts[1] || '') + (parts[2] || '') + (parts[4] || '') + (parts[6] || ''), modifier = (parts[3] || parts[5] || 1) - 1; // Parse the key modifier key.ctrl = !!(modifier & 4); key.meta = !!(modifier & 10); key.shift = !!(modifier & 1); key.code = code; // Parse the key itself switch (code) { /* xterm/gnome ESC O letter */ case 'OP': key.name = 'f1'; break; case 'OQ': key.name = 'f2'; break; case 'OR': key.name = 'f3'; break; case 'OS': key.name = 'f4'; break; /* xterm/rxvt ESC [ number ~ */ case '[11~': key.name = 'f1'; break; case '[12~': key.name = 'f2'; break; case '[13~': key.name = 'f3'; break; case '[14~': key.name = 'f4'; break; /* from Cygwin and used in libuv */ case '[[A': key.name = 'f1'; break; case '[[B': key.name = 'f2'; break; case '[[C': key.name = 'f3'; break; case '[[D': key.name = 'f4'; break; case '[[E': key.name = 'f5'; break; /* common */ case '[15~': key.name = 'f5'; break; case '[17~': key.name = 'f6'; break; case '[18~': key.name = 'f7'; break; case '[19~': key.name = 'f8'; break; case '[20~': key.name = 'f9'; break; case '[21~': key.name = 'f10'; break; case '[23~': key.name = 'f11'; break; case '[24~': key.name = 'f12'; break; /* xterm ESC [ letter */ case '[A': key.name = 'up'; break; case '[B': key.name = 'down'; break; case '[C': key.name = 'right'; break; case '[D': key.name = 'left'; break; case '[E': key.name = 'clear'; break; case '[F': key.name = 'end'; break; case '[H': key.name = 'home'; break; /* xterm/gnome ESC O letter */ case 'OA': key.name = 'up'; break; case 'OB': key.name = 'down'; break; case 'OC': key.name = 'right'; break; case 'OD': key.name = 'left'; break; case 'OE': key.name = 'clear'; break; case 'OF': key.name = 'end'; break; case 'OH': key.name = 'home'; break; /* xterm/rxvt ESC [ number ~ */ case '[1~': key.name = 'home'; break; case '[2~': key.name = 'insert'; break; case '[3~': key.name = 'delete'; break; case '[4~': key.name = 'end'; break; case '[5~': key.name = 'pageup'; break; case '[6~': key.name = 'pagedown'; break; /* putty */ case '[[5~': key.name = 'pageup'; break; case '[[6~': key.name = 'pagedown'; break; /* rxvt */ case '[7~': key.name = 'home'; break; case '[8~': key.name = 'end'; break; /* rxvt keys with modifiers */ case '[a': key.name = 'up'; key.shift = true; break; case '[b': key.name = 'down'; key.shift = true; break; case '[c': key.name = 'right'; key.shift = true; break; case '[d': key.name = 'left'; key.shift = true; break; case '[e': key.name = 'clear'; key.shift = true; break; case '[2$': key.name = 'insert'; key.shift = true; break; case '[3$': key.name = 'delete'; key.shift = true; break; case '[5$': key.name = 'pageup'; key.shift = true; break; case '[6$': key.name = 'pagedown'; key.shift = true; break; case '[7$': key.name = 'home'; key.shift = true; break; case '[8$': key.name = 'end'; key.shift = true; break; case 'Oa': key.name = 'up'; key.ctrl = true; break; case 'Ob': key.name = 'down'; key.ctrl = true; break; case 'Oc': key.name = 'right'; key.ctrl = true; break; case 'Od': key.name = 'left'; key.ctrl = true; break; case 'Oe': key.name = 'clear'; key.ctrl = true; break; case '[2^': key.name = 'insert'; key.ctrl = true; break; case '[3^': key.name = 'delete'; key.ctrl = true; break; case '[5^': key.name = 'pageup'; key.ctrl = true; break; case '[6^': key.name = 'pagedown'; key.ctrl = true; break; case '[7^': key.name = 'home'; key.ctrl = true; break; case '[8^': key.name = 'end'; key.ctrl = true; break; /* misc. */ case '[Z': key.name = 'tab'; key.shift = true; break; default: key.name = 'undefined'; break; } } else if (s.length > 1 && s[0] !== '\x1b') { // Got a longer-than-one string of characters. // Probably a paste, since it wasn't a control sequence. Array.prototype.forEach.call(s, function(c) { emitKey(stream, c); }); return; } // Don't emit a key if no name was found if (key.name === undefined) { key = undefined; } if (s.length === 1) { ch = s; } if (key || ch) { stream.emit('keypress', ch, key); } } /** * moves the cursor to the x and y coordinate on the given stream */ function cursorTo(stream, x, y) { if (typeof x !== 'number' && typeof y !== 'number') return; if (typeof x !== 'number') throw new Error("Can't set cursor row without also setting it's column"); if (typeof y !== 'number') { stream.write('\x1b[' + (x + 1) + 'G'); } else { stream.write('\x1b[' + (y + 1) + ';' + (x + 1) + 'H'); } } exports.cursorTo = cursorTo; /** * moves the cursor relative to its current location */ function moveCursor(stream, dx, dy) { if (dx < 0) { stream.write('\x1b[' + (-dx) + 'D'); } else if (dx > 0) { stream.write('\x1b[' + dx + 'C'); } if (dy < 0) { stream.write('\x1b[' + (-dy) + 'A'); } else if (dy > 0) { stream.write('\x1b[' + dy + 'B'); } } exports.moveCursor = moveCursor; /** * clears the current line the cursor is on: * -1 for left of the cursor * +1 for right of the cursor * 0 for the entire line */ function clearLine(stream, dir) { if (dir < 0) { // to the beginning stream.write('\x1b[1K'); } else if (dir > 0) { // to the end stream.write('\x1b[0K'); } else { // entire line stream.write('\x1b[2K'); } } exports.clearLine = clearLine; /** * clears the screen from the current position of the cursor down */ function clearScreenDown(stream) { stream.write('\x1b[0J'); } exports.clearScreenDown = clearScreenDown; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var events = require('events'); var EventEmitter = events.EventEmitter; var inherits = util.inherits; // methods that are called when trying to shut down expliclitly bound EEs var endMethods = ['end', 'abort', 'destroy', 'destroySoon']; // communicate with events module, but don't require that // module to have to load this one, since this module has // a few side effects. events.usingDomains = true; // let the process know we're using domains process._usingDomains(); exports.Domain = Domain; exports.create = exports.createDomain = function(cb) { return new Domain(cb); }; // it's possible to enter one domain while already inside // another one. the stack is each entered domain. var stack = []; exports._stack = stack; // the active domain is always the one that we're currently in. exports.active = null; inherits(Domain, EventEmitter); function Domain() { EventEmitter.call(this); this.members = []; } Domain.prototype.enter = function() { if (this._disposed) return; // note that this might be a no-op, but we still need // to push it onto the stack so that we can pop it later. exports.active = process.domain = this; stack.push(this); }; Domain.prototype.exit = function() { if (this._disposed) return; // exit all domains until this one. var d; do { d = stack.pop(); } while (d && d !== this); exports.active = stack[stack.length - 1]; process.domain = exports.active; }; // note: this works for timers as well. Domain.prototype.add = function(ee) { // disposed domains can't be used for new things. if (this._disposed) return; // already added to this domain. if (ee.domain === this) return; // has a domain already - remove it first. if (ee.domain) { ee.domain.remove(ee); } // check for circular Domain->Domain links. // This causes bad insanity! // // For example: // var d = domain.create(); // var e = domain.create(); // d.add(e); // e.add(d); // e.emit('error', er); // RangeError, stack overflow! if (this.domain && (ee instanceof Domain)) { for (var d = this.domain; d; d = d.domain) { if (ee === d) return; } } ee.domain = this; this.members.push(ee); }; Domain.prototype.remove = function(ee) { ee.domain = null; var index = this.members.indexOf(ee); if (index !== -1) { this.members.splice(index, 1); } }; Domain.prototype.run = function(fn) { return this.bind(fn)(); }; Domain.prototype.intercept = function(cb) { return this.bind(cb, true); }; Domain.prototype.bind = function(cb, interceptError) { // if cb throws, catch it here. var self = this; var b = function() { // disposing turns functions into no-ops if (self._disposed) return; if (this instanceof Domain) { return cb.apply(this, arguments); } // only intercept first-arg errors if explicitly requested. if (interceptError && arguments[0] && (arguments[0] instanceof Error)) { var er = arguments[0]; util._extend(er, { domainBound: cb, domainThrown: false, domain: self }); self.emit('error', er); return; } // remove first-arg if intercept as assumed to be the error-arg if (interceptError) { var len = arguments.length; var args; switch (len) { case 0: case 1: // no args that we care about. args = []; break; case 2: // optimization for most common case: cb(er, data) args = [arguments[1]]; break; default: // slower for less common case: cb(er, foo, bar, baz, ...) args = new Array(len - 1); for (var i = 1; i < len; i++) { args[i - 1] = arguments[i]; } break; } self.enter(); var ret = cb.apply(this, args); self.exit(); return ret; } self.enter(); var ret = cb.apply(this, arguments); self.exit(); return ret; }; b.domain = this; return b; }; Domain.prototype.dispose = function() { if (this._disposed) return; // if we're the active domain, then get out now. this.exit(); this.emit('dispose'); // remove error handlers. this.removeAllListeners(); this.on('error', function() {}); // try to kill all the members. // XXX There should be more consistent ways // to shut down things! this.members.forEach(function(m) { // if it's a timeout or interval, cancel it. clearTimeout(m); // drop all event listeners. if (m instanceof EventEmitter) { m.removeAllListeners(); // swallow errors m.on('error', function() {}); } // Be careful! // By definition, we're likely in error-ridden territory here, // so it's quite possible that calling some of these methods // might cause additional exceptions to be thrown. endMethods.forEach(function(method) { if (typeof m[method] === 'function') { try { m[method](); } catch (er) {} } }); }); // remove from parent domain, if there is one. if (this.domain) this.domain.remove(this); // kill the references so that they can be properly gc'ed. this.members.length = 0; // finally, mark this domain as 'no longer relevant' // so that it can't be entered or activated. this._disposed = true; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var inherits = require('util').inherits; var net = require('net'); var TTY = process.binding('tty_wrap').TTY; var isTTY = process.binding('tty_wrap').isTTY; var util = require('util'); exports.isatty = function(fd) { return isTTY(fd); }; // backwards-compat exports.setRawMode = util.deprecate(function(flag) { if (!process.stdin.isTTY) { throw new Error('can\'t set raw mode on non-tty'); } process.stdin.setRawMode(flag); }, 'tty.setRawMode: Use `process.stdin.setRawMode()` instead.'); function ReadStream(fd, options) { if (!(this instanceof ReadStream)) return new ReadStream(fd, options); options = util._extend({ highWaterMark: 0, readable: true, writable: false, handle: new TTY(fd, true) }, options); net.Socket.call(this, options); this.isRaw = false; this.isTTY = true; } inherits(ReadStream, net.Socket); exports.ReadStream = ReadStream; ReadStream.prototype.setRawMode = function(flag) { flag = !!flag; this._handle.setRawMode(flag); this.isRaw = flag; }; function WriteStream(fd) { if (!(this instanceof WriteStream)) return new WriteStream(fd); net.Socket.call(this, { handle: new TTY(fd, false), readable: false, writable: true }); var winSize = this._handle.getWindowSize(); if (winSize) { this.columns = winSize[0]; this.rows = winSize[1]; } } inherits(WriteStream, net.Socket); exports.WriteStream = WriteStream; WriteStream.prototype.isTTY = true; WriteStream.prototype._refreshSize = function() { var oldCols = this.columns; var oldRows = this.rows; var winSize = this._handle.getWindowSize(); if (!winSize) { this.emit('error', errnoException(process._errno, 'getWindowSize')); return; } var newCols = winSize[0]; var newRows = winSize[1]; if (oldCols !== newCols || oldRows !== newRows) { this.columns = newCols; this.rows = newRows; this.emit('resize'); } }; // backwards-compat WriteStream.prototype.cursorTo = function(x, y) { require('readline').cursorTo(this, x, y); }; WriteStream.prototype.moveCursor = function(dx, dy) { require('readline').moveCursor(this, dx, dy); }; WriteStream.prototype.clearLine = function(dir) { require('readline').clearLine(this, dir); }; WriteStream.prototype.clearScreenDown = function() { require('readline').clearScreenDown(this); }; WriteStream.prototype.getWindowSize = function() { return [this.columns, this.rows]; }; // TODO share with net_uv and others function errnoException(errorno, syscall) { var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); var net = require('net'); var Stream = require('stream'); var url = require('url'); var EventEmitter = require('events').EventEmitter; var FreeList = require('freelist').FreeList; var HTTPParser = process.binding('http_parser').HTTPParser; var assert = require('assert').ok; // an empty buffer for UPGRADE/CONNECT bodyHead compatibility var emptyBuffer = new Buffer(0); var debug; if (process.env.NODE_DEBUG && /http/.test(process.env.NODE_DEBUG)) { debug = function(x) { console.error('HTTP: %s', x); }; } else { debug = function() { }; } function readStart(socket) { if (!socket || !socket._handle || !socket._handle.readStart) return; if (!socket._drain_paused) { socket._handle.readStart(); } } function readStop(socket) { if (!socket || !socket._handle || !socket._handle.readStop) return; socket._handle.readStop(); } // Only called in the slow case where slow means // that the request headers were either fragmented // across multiple TCP packets or too large to be // processed in a single run. This method is also // called to process trailing HTTP headers. function parserOnHeaders(headers, url) { // Once we exceeded headers limit - stop collecting them if (this.maxHeaderPairs <= 0 || this._headers.length < this.maxHeaderPairs) { this._headers = this._headers.concat(headers); } this._url += url; } // info.headers and info.url are set only if .onHeaders() // has not been called for this request. // // info.url is not set for response parsers but that's not // applicable here since all our parsers are request parsers. function parserOnHeadersComplete(info) { var parser = this; var headers = info.headers; var url = info.url; if (!headers) { headers = parser._headers; parser._headers = []; } if (!url) { url = parser._url; parser._url = ''; } parser.incoming = new IncomingMessage(parser.socket); parser.incoming.httpVersionMajor = info.versionMajor; parser.incoming.httpVersionMinor = info.versionMinor; parser.incoming.httpVersion = info.versionMajor + '.' + info.versionMinor; parser.incoming.url = url; var n = headers.length; // If parser.maxHeaderPairs <= 0 - assume that there're no limit if (parser.maxHeaderPairs > 0) { n = Math.min(n, parser.maxHeaderPairs); } for (var i = 0; i < n; i += 2) { var k = headers[i]; var v = headers[i + 1]; parser.incoming._addHeaderLine(k, v); } if (info.method) { // server only parser.incoming.method = info.method; } else { // client only parser.incoming.statusCode = info.statusCode; // CHECKME dead code? we're always a request parser } parser.incoming.upgrade = info.upgrade; var skipBody = false; // response to HEAD or CONNECT if (!info.upgrade) { // For upgraded connections and CONNECT method request, // we'll emit this after parser.execute // so that we can capture the first part of the new protocol skipBody = parser.onIncoming(parser.incoming, info.shouldKeepAlive); } return skipBody; } // XXX This is a mess. // TODO: http.Parser should be a Writable emits request/response events. function parserOnBody(b, start, len) { var parser = this; var stream = parser.incoming; // if the stream has already been removed, then drop it. if (!stream) return; var socket = stream.socket; // pretend this was the result of a stream._read call. if (len > 0 && !stream._dumped) { var slice = b.slice(start, start + len); var ret = stream.push(slice); if (!ret) readStop(socket); } } function parserOnMessageComplete() { var parser = this; var stream = parser.incoming; if (stream) { stream.complete = true; // Emit any trailing headers. var headers = parser._headers; if (headers) { for (var i = 0, n = headers.length; i < n; i += 2) { var k = headers[i]; var v = headers[i + 1]; parser.incoming._addHeaderLine(k, v); } parser._headers = []; parser._url = ''; } if (!stream.upgrade) // For upgraded connections, also emit this after parser.execute stream.push(null); } if (stream && !parser.incoming._pendings.length) { // For emit end event stream.push(null); } if (parser.socket.readable) { // force to read the next incoming message readStart(parser.socket); } } var parsers = new FreeList('parsers', 1000, function() { var parser = new HTTPParser(HTTPParser.REQUEST); parser._headers = []; parser._url = ''; // Only called in the slow case where slow means // that the request headers were either fragmented // across multiple TCP packets or too large to be // processed in a single run. This method is also // called to process trailing HTTP headers. parser.onHeaders = parserOnHeaders; parser.onHeadersComplete = parserOnHeadersComplete; parser.onBody = parserOnBody; parser.onMessageComplete = parserOnMessageComplete; return parser; }); exports.parsers = parsers; var CRLF = '\r\n'; var STATUS_CODES = exports.STATUS_CODES = { 100 : 'Continue', 101 : 'Switching Protocols', 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918 200 : 'OK', 201 : 'Created', 202 : 'Accepted', 203 : 'Non-Authoritative Information', 204 : 'No Content', 205 : 'Reset Content', 206 : 'Partial Content', 207 : 'Multi-Status', // RFC 4918 300 : 'Multiple Choices', 301 : 'Moved Permanently', 302 : 'Moved Temporarily', 303 : 'See Other', 304 : 'Not Modified', 305 : 'Use Proxy', 307 : 'Temporary Redirect', 400 : 'Bad Request', 401 : 'Unauthorized', 402 : 'Payment Required', 403 : 'Forbidden', 404 : 'Not Found', 405 : 'Method Not Allowed', 406 : 'Not Acceptable', 407 : 'Proxy Authentication Required', 408 : 'Request Time-out', 409 : 'Conflict', 410 : 'Gone', 411 : 'Length Required', 412 : 'Precondition Failed', 413 : 'Request Entity Too Large', 414 : 'Request-URI Too Large', 415 : 'Unsupported Media Type', 416 : 'Requested Range Not Satisfiable', 417 : 'Expectation Failed', 418 : 'I\'m a teapot', // RFC 2324 422 : 'Unprocessable Entity', // RFC 4918 423 : 'Locked', // RFC 4918 424 : 'Failed Dependency', // RFC 4918 425 : 'Unordered Collection', // RFC 4918 426 : 'Upgrade Required', // RFC 2817 428 : 'Precondition Required', // RFC 6585 429 : 'Too Many Requests', // RFC 6585 431 : 'Request Header Fields Too Large',// RFC 6585 500 : 'Internal Server Error', 501 : 'Not Implemented', 502 : 'Bad Gateway', 503 : 'Service Unavailable', 504 : 'Gateway Time-out', 505 : 'HTTP Version Not Supported', 506 : 'Variant Also Negotiates', // RFC 2295 507 : 'Insufficient Storage', // RFC 4918 509 : 'Bandwidth Limit Exceeded', 510 : 'Not Extended', // RFC 2774 511 : 'Network Authentication Required' // RFC 6585 }; var connectionExpression = /Connection/i; var transferEncodingExpression = /Transfer-Encoding/i; var closeExpression = /close/i; var chunkExpression = /chunk/i; var contentLengthExpression = /Content-Length/i; var dateExpression = /Date/i; var expectExpression = /Expect/i; var continueExpression = /100-continue/i; var dateCache; function utcDate() { if (!dateCache) { var d = new Date(); dateCache = d.toUTCString(); setTimeout(function() { dateCache = undefined; }, 1000 - d.getMilliseconds()); } return dateCache; } /* Abstract base class for ServerRequest and ClientResponse. */ function IncomingMessage(socket) { Stream.Readable.call(this); // XXX This implementation is kind of all over the place // When the parser emits body chunks, they go in this list. // _read() pulls them out, and when it finds EOF, it ends. this.socket = socket; this.connection = socket; this.httpVersion = null; this.complete = false; this.headers = {}; this.trailers = {}; this.readable = true; this._pendings = []; this._pendingIndex = 0; // request (server) only this.url = ''; this.method = null; // response (client) only this.statusCode = null; this.client = this.socket; // flag for backwards compatibility grossness. this._consuming = false; // flag for when we decide that this message cannot possibly be // read by the user, so there's no point continuing to handle it. this._dumped = false; } util.inherits(IncomingMessage, Stream.Readable); exports.IncomingMessage = IncomingMessage; IncomingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); this.socket.setTimeout(msecs); }; IncomingMessage.prototype.read = function(n) { this._consuming = true; this.read = Stream.Readable.prototype.read; return this.read(n); }; IncomingMessage.prototype._read = function(n) { // We actually do almost nothing here, because the parserOnBody // function fills up our internal buffer directly. However, we // do need to unpause the underlying socket so that it flows. if (!this.socket.readable) this.push(null); else readStart(this.socket); }; // It's possible that the socket will be destroyed, and removed from // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. IncomingMessage.prototype.destroy = function(error) { if (this.socket) this.socket.destroy(error); }; // Add the given (field, value) pair to the message // // Per RFC2616, section 4.2 it is acceptable to join multiple instances of the // same header with a ', ' if the header in question supports specification of // multiple values this way. If not, we declare the first instance the winner // and drop the second. Extended header fields (those beginning with 'x-') are // always joined. IncomingMessage.prototype._addHeaderLine = function(field, value) { var dest = this.complete ? this.trailers : this.headers; field = field.toLowerCase(); switch (field) { // Array headers: case 'set-cookie': if (dest[field] !== undefined) { dest[field].push(value); } else { dest[field] = [value]; } break; // Comma separate. Maybe make these arrays? case 'accept': case 'accept-charset': case 'accept-encoding': case 'accept-language': case 'connection': case 'cookie': case 'pragma': case 'link': case 'www-authenticate': case 'proxy-authenticate': case 'sec-websocket-extensions': case 'sec-websocket-protocol': if (dest[field] !== undefined) { dest[field] += ', ' + value; } else { dest[field] = value; } break; default: if (field.slice(0, 2) == 'x-') { // except for x- if (dest[field] !== undefined) { dest[field] += ', ' + value; } else { dest[field] = value; } } else { // drop duplicates if (dest[field] === undefined) dest[field] = value; } break; } }; // Call this instead of resume() if we want to just // dump all the data to /dev/null IncomingMessage.prototype._dump = function() { if (!this._dumped) { this._dumped = true; if (this.socket.parser) this.socket.parser.incoming = null; this.push(null); readStart(this.socket); this.read(); } }; function OutgoingMessage() { Stream.call(this); this.output = []; this.outputEncodings = []; this.writable = true; this._last = false; this.chunkedEncoding = false; this.shouldKeepAlive = true; this.useChunkedEncodingByDefault = true; this.sendDate = false; this._hasBody = true; this._trailer = ''; this.finished = false; this._hangupClose = false; this.socket = null; this.connection = null; } util.inherits(OutgoingMessage, Stream); exports.OutgoingMessage = OutgoingMessage; OutgoingMessage.prototype.setTimeout = function(msecs, callback) { if (callback) this.on('timeout', callback); if (!this.socket) { this.once('socket', function(socket) { socket.setTimeout(msecs); }); } else this.socket.setTimeout(msecs); }; // It's possible that the socket will be destroyed, and removed from // any messages, before ever calling this. In that case, just skip // it, since something else is destroying this connection anyway. OutgoingMessage.prototype.destroy = function(error) { if (this.socket) this.socket.destroy(error); else this.once('socket', function(socket) { socket.destroy(error); }); }; // This abstract either writing directly to the socket or buffering it. OutgoingMessage.prototype._send = function(data, encoding) { // This is a shameful hack to get the headers and first body chunk onto // the same packet. Future versions of Node are going to take care of // this at a lower level and in a more general way. if (!this._headerSent) { if (typeof data === 'string') { data = this._header + data; } else { this.output.unshift(this._header); this.outputEncodings.unshift('ascii'); } this._headerSent = true; } return this._writeRaw(data, encoding); }; OutgoingMessage.prototype._writeRaw = function(data, encoding) { if (data.length === 0) { return true; } if (this.connection && this.connection._httpMessage === this && this.connection.writable && !this.connection.destroyed) { // There might be pending data in the this.output buffer. while (this.output.length) { if (!this.connection.writable) { this._buffer(data, encoding); return false; } var c = this.output.shift(); var e = this.outputEncodings.shift(); this.connection.write(c, e); } // Directly write to socket. return this.connection.write(data, encoding); } else if (this.connection && this.connection.destroyed) { // The socket was destroyed. If we're still trying to write to it, // then we haven't gotten the 'close' event yet. return false; } else { // buffer, as long as we're not destroyed. this._buffer(data, encoding); return false; } }; OutgoingMessage.prototype._buffer = function(data, encoding) { if (data.length === 0) return; var length = this.output.length; if (length === 0 || typeof data != 'string') { this.output.push(data); this.outputEncodings.push(encoding); return false; } var lastEncoding = this.outputEncodings[length - 1]; var lastData = this.output[length - 1]; if ((encoding && lastEncoding === encoding) || (!encoding && data.constructor === lastData.constructor)) { this.output[length - 1] = lastData + data; return false; } this.output.push(data); this.outputEncodings.push(encoding); return false; }; OutgoingMessage.prototype._storeHeader = function(firstLine, headers) { // firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n' // in the case of response it is: 'HTTP/1.1 200 OK\r\n' var state = { sentConnectionHeader: false, sentContentLengthHeader: false, sentTransferEncodingHeader: false, sentDateHeader: false, sentExpect: false, messageHeader: firstLine }; var field, value; var self = this; if (headers) { var keys = Object.keys(headers); var isArray = (Array.isArray(headers)); var field, value; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; } else { field = key; value = headers[key]; } if (Array.isArray(value)) { for (var j = 0; j < value.length; j++) { storeHeader(this, state, field, value[j]); } } else { storeHeader(this, state, field, value); } } } // Date header if (this.sendDate == true && state.sentDateHeader == false) { state.messageHeader += 'Date: ' + utcDate() + CRLF; } // Force the connection to close when the response is a 204 No Content or // a 304 Not Modified and the user has set a "Transfer-Encoding: chunked" // header. // // RFC 2616 mandates that 204 and 304 responses MUST NOT have a body but // node.js used to send out a zero chunk anyway to accommodate clients // that don't have special handling for those responses. // // It was pointed out that this might confuse reverse proxies to the point // of creating security liabilities, so suppress the zero chunk and force // the connection to close. var statusCode = this.statusCode; if ((statusCode == 204 || statusCode === 304) && this.chunkedEncoding === true) { debug(statusCode + ' response should not use chunked encoding,' + ' closing connection.'); this.chunkedEncoding = false; this.shouldKeepAlive = false; } // keep-alive logic if (state.sentConnectionHeader === false) { var shouldSendKeepAlive = this.shouldKeepAlive && (state.sentContentLengthHeader || this.useChunkedEncodingByDefault || this.agent); if (shouldSendKeepAlive) { state.messageHeader += 'Connection: keep-alive\r\n'; } else { this._last = true; state.messageHeader += 'Connection: close\r\n'; } } if (state.sentContentLengthHeader == false && state.sentTransferEncodingHeader == false) { if (this._hasBody) { if (this.useChunkedEncodingByDefault) { state.messageHeader += 'Transfer-Encoding: chunked\r\n'; this.chunkedEncoding = true; } else { this._last = true; } } else { // Make sure we don't end the 0\r\n\r\n at the end of the message. this.chunkedEncoding = false; } } this._header = state.messageHeader + CRLF; this._headerSent = false; // wait until the first body chunk, or close(), is sent to flush, // UNLESS we're sending Expect: 100-continue. if (state.sentExpect) this._send(''); }; function storeHeader(self, state, field, value) { // Protect against response splitting. The if statement is there to // minimize the performance impact in the common case. if (/[\r\n]/.test(value)) value = value.replace(/[\r\n]+[ \t]*/g, ''); state.messageHeader += field + ': ' + value + CRLF; if (connectionExpression.test(field)) { state.sentConnectionHeader = true; if (closeExpression.test(value)) { self._last = true; } else { self.shouldKeepAlive = true; } } else if (transferEncodingExpression.test(field)) { state.sentTransferEncodingHeader = true; if (chunkExpression.test(value)) self.chunkedEncoding = true; } else if (contentLengthExpression.test(field)) { state.sentContentLengthHeader = true; } else if (dateExpression.test(field)) { state.sentDateHeader = true; } else if (expectExpression.test(field)) { state.sentExpect = true; } } OutgoingMessage.prototype.setHeader = function(name, value) { if (arguments.length < 2) { throw new Error('`name` and `value` are required for setHeader().'); } if (this._header) { throw new Error('Can\'t set headers after they are sent.'); } var key = name.toLowerCase(); this._headers = this._headers || {}; this._headerNames = this._headerNames || {}; this._headers[key] = value; this._headerNames[key] = name; }; OutgoingMessage.prototype.getHeader = function(name) { if (arguments.length < 1) { throw new Error('`name` is required for getHeader().'); } if (!this._headers) return; var key = name.toLowerCase(); return this._headers[key]; }; OutgoingMessage.prototype.removeHeader = function(name) { if (arguments.length < 1) { throw new Error('`name` is required for removeHeader().'); } if (this._header) { throw new Error('Can\'t remove headers after they are sent.'); } if (!this._headers) return; var key = name.toLowerCase(); delete this._headers[key]; delete this._headerNames[key]; }; OutgoingMessage.prototype._renderHeaders = function() { if (this._header) { throw new Error('Can\'t render headers after they are sent to the client.'); } if (!this._headers) return {}; var headers = {}; var keys = Object.keys(this._headers); for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; headers[this._headerNames[key]] = this._headers[key]; } return headers; }; Object.defineProperty(OutgoingMessage.prototype, 'headersSent', { configurable: true, enumerable: true, get: function() { return !!this._header; } }); OutgoingMessage.prototype.write = function(chunk, encoding) { if (!this._header) { this._implicitHeader(); } if (!this._hasBody) { debug('This type of response MUST NOT have a body. ' + 'Ignoring write() calls.'); return true; } if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) { throw new TypeError('first argument must be a string or Buffer'); } // If we get an empty string or buffer, then just do nothing, and // signal the user to keep writing. if (chunk.length === 0) return true; // TODO(bnoordhuis) Temporary optimization hack, remove in v0.11. We only // want to convert the buffer when we're sending: // // a) Transfer-Encoding chunks, because it lets us pack the chunk header // and the chunk into a single write(), or // // b) the first chunk of a fixed-length request, because it lets us pack // the request headers and the chunk into a single write(). // // Converting to strings is expensive, CPU-wise, but reducing the number // of write() calls more than makes up for that because we're dramatically // reducing the number of TCP roundtrips. if (chunk instanceof Buffer && (this.chunkedEncoding || !this._headerSent)) { chunk = chunk.toString('binary'); encoding = 'binary'; } var len, ret; if (this.chunkedEncoding) { if (typeof(chunk) === 'string' && encoding !== 'hex' && encoding !== 'base64') { len = Buffer.byteLength(chunk, encoding); chunk = len.toString(16) + CRLF + chunk + CRLF; ret = this._send(chunk, encoding); } else { // buffer, or a non-toString-friendly encoding len = chunk.length; this._send(len.toString(16) + CRLF); this._send(chunk, encoding); ret = this._send(CRLF); } } else { ret = this._send(chunk, encoding); } debug('write ret = ' + ret); return ret; }; OutgoingMessage.prototype.addTrailers = function(headers) { this._trailer = ''; var keys = Object.keys(headers); var isArray = (Array.isArray(headers)); var field, value; for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; if (isArray) { field = headers[key][0]; value = headers[key][1]; } else { field = key; value = headers[key]; } this._trailer += field + ': ' + value + CRLF; } }; var zero_chunk_buf = new Buffer('\r\n0\r\n'); var crlf_buf = new Buffer('\r\n'); OutgoingMessage.prototype.end = function(data, encoding) { if (this.finished) { return false; } if (!this._header) { this._implicitHeader(); } if (data && !this._hasBody) { debug('This type of response MUST NOT have a body. ' + 'Ignoring data passed to end().'); data = false; } var ret; var hot = this._headerSent === false && (data && data.length > 0) && this.output.length === 0 && this.connection && this.connection.writable && this.connection._httpMessage === this; // The benefits of the hot-path optimization below start to fall // off when the buffer size gets up near 128KB, because the cost // of the copy is more than the cost of the extra write() call. // Switch to the write/end method at that point. Heuristics and // magic numbers are awful, but slow http responses are worse. if (hot && Buffer.isBuffer(data) && data.length > 120 * 1024) hot = false; if (hot) { // Hot path. They're doing // res.writeHead(); // res.end(blah); // HACKY. if (typeof data === 'string') { if (this.chunkedEncoding) { var l = Buffer.byteLength(data, encoding).toString(16); ret = this.connection.write(this._header + l + CRLF + data + '\r\n0\r\n' + this._trailer + '\r\n', encoding); } else { ret = this.connection.write(this._header + data, encoding); } } else if (Buffer.isBuffer(data)) { if (this.chunkedEncoding) { var chunk_size = data.length.toString(16); // Skip expensive Buffer.byteLength() calls; only ISO-8859-1 characters // are allowed in HTTP headers. Therefore: // // this._header.length == Buffer.byteLength(this._header.length) // this._trailer.length == Buffer.byteLength(this._trailer.length) // var header_len = this._header.length; var chunk_size_len = chunk_size.length; var data_len = data.length; var trailer_len = this._trailer.length; var len = header_len + chunk_size_len + 2 + // '\r\n'.length data_len + 5 + // '\r\n0\r\n'.length trailer_len + 2; // '\r\n'.length var buf = new Buffer(len); var off = 0; buf.write(this._header, off, header_len, 'ascii'); off += header_len; buf.write(chunk_size, off, chunk_size_len, 'ascii'); off += chunk_size_len; crlf_buf.copy(buf, off); off += 2; data.copy(buf, off); off += data_len; zero_chunk_buf.copy(buf, off); off += 5; if (trailer_len > 0) { buf.write(this._trailer, off, trailer_len, 'ascii'); off += trailer_len; } crlf_buf.copy(buf, off); ret = this.connection.write(buf); } else { var header_len = this._header.length; var buf = new Buffer(header_len + data.length); buf.write(this._header, 0, header_len, 'ascii'); data.copy(buf, header_len); ret = this.connection.write(buf); } } else { throw new TypeError('first argument must be a string or Buffer'); } this._headerSent = true; } else if (data) { // Normal body write. ret = this.write(data, encoding); } if (!hot) { if (this.chunkedEncoding) { ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk. } else { // Force a flush, HACK. ret = this._send(''); } } this.finished = true; // There is the first message on the outgoing queue, and we've sent // everything to the socket. debug('outgoing message end.'); if (this.output.length === 0 && this.connection._httpMessage === this) { this._finish(); } return ret; }; OutgoingMessage.prototype._finish = function() { assert(this.connection); if (this instanceof ServerResponse) { DTRACE_HTTP_SERVER_RESPONSE(this.connection); COUNTER_HTTP_SERVER_RESPONSE(); } else { assert(this instanceof ClientRequest); DTRACE_HTTP_CLIENT_REQUEST(this, this.connection); COUNTER_HTTP_CLIENT_REQUEST(); } this.emit('finish'); }; OutgoingMessage.prototype._flush = function() { // This logic is probably a bit confusing. Let me explain a bit: // // In both HTTP servers and clients it is possible to queue up several // outgoing messages. This is easiest to imagine in the case of a client. // Take the following situation: // // req1 = client.request('GET', '/'); // req2 = client.request('POST', '/'); // // When the user does // // req2.write('hello world\n'); // // it's possible that the first request has not been completely flushed to // the socket yet. Thus the outgoing messages need to be prepared to queue // up data internally before sending it on further to the socket's queue. // // This function, outgoingFlush(), is called by both the Server and Client // to attempt to flush any pending messages out to the socket. if (!this.socket) return; var ret; while (this.output.length) { if (!this.socket.writable) return; // XXX Necessary? var data = this.output.shift(); var encoding = this.outputEncodings.shift(); ret = this.socket.write(data, encoding); } if (this.finished) { // This is a queue to the server or client to bring in the next this. this._finish(); } else if (ret) { // This is necessary to prevent https from breaking this.emit('drain'); } }; function ServerResponse(req) { OutgoingMessage.call(this); if (req.method === 'HEAD') this._hasBody = false; this.sendDate = true; if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) { this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te); this.shouldKeepAlive = false; } } util.inherits(ServerResponse, OutgoingMessage); exports.ServerResponse = ServerResponse; ServerResponse.prototype.statusCode = 200; function onServerResponseClose() { // EventEmitter.emit makes a copy of the 'close' listeners array before // calling the listeners. detachSocket() unregisters onServerResponseClose // but if detachSocket() is called, directly or indirectly, by a 'close' // listener, onServerResponseClose is still in that copy of the listeners // array. That is, in the example below, b still gets called even though // it's been removed by a: // // var obj = new events.EventEmitter; // obj.on('event', a); // obj.on('event', b); // function a() { obj.removeListener('event', b) } // function b() { throw "BAM!" } // obj.emit('event'); // throws // // Ergo, we need to deal with stale 'close' events and handle the case // where the ServerResponse object has already been deconstructed. // Fortunately, that requires only a single if check. :-) if (this._httpMessage) this._httpMessage.emit('close'); } ServerResponse.prototype.assignSocket = function(socket) { assert(!socket._httpMessage); socket._httpMessage = this; socket.on('close', onServerResponseClose); this.socket = socket; this.connection = socket; this.emit('socket', socket); this._flush(); }; ServerResponse.prototype.detachSocket = function(socket) { assert(socket._httpMessage == this); socket.removeListener('close', onServerResponseClose); socket._httpMessage = null; this.socket = this.connection = null; }; ServerResponse.prototype.writeContinue = function() { this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii'); this._sent100 = true; }; ServerResponse.prototype._implicitHeader = function() { this.writeHead(this.statusCode); }; ServerResponse.prototype.writeHead = function(statusCode) { var reasonPhrase, headers, headerIndex; if (typeof arguments[1] == 'string') { reasonPhrase = arguments[1]; headerIndex = 2; } else { reasonPhrase = STATUS_CODES[statusCode] || 'unknown'; headerIndex = 1; } this.statusCode = statusCode; var obj = arguments[headerIndex]; if (obj && this._headers) { // Slow-case: when progressive API and header fields are passed. headers = this._renderHeaders(); if (Array.isArray(obj)) { // handle array case // TODO: remove when array is no longer accepted var field; for (var i = 0, len = obj.length; i < len; ++i) { field = obj[i][0]; if (headers[field] !== undefined) { obj.push([field, headers[field]]); } } headers = obj; } else { // handle object case var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { var k = keys[i]; if (k) headers[k] = obj[k]; } } } else if (this._headers) { // only progressive api is used headers = this._renderHeaders(); } else { // only writeHead() called headers = obj; } var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' + reasonPhrase + CRLF; if (statusCode === 204 || statusCode === 304 || (100 <= statusCode && statusCode <= 199)) { // RFC 2616, 10.2.5: // The 204 response MUST NOT include a message-body, and thus is always // terminated by the first empty line after the header fields. // RFC 2616, 10.3.5: // The 304 response MUST NOT contain a message-body, and thus is always // terminated by the first empty line after the header fields. // RFC 2616, 10.1 Informational 1xx: // This class of status code indicates a provisional response, // consisting only of the Status-Line and optional headers, and is // terminated by an empty line. this._hasBody = false; } // don't keep alive connections where the client expects 100 Continue // but we sent a final status; they may put extra bytes on the wire. if (this._expect_continue && !this._sent100) { this.shouldKeepAlive = false; } this._storeHeader(statusLine, headers); }; ServerResponse.prototype.writeHeader = function() { this.writeHead.apply(this, arguments); }; // New Agent code. // The largest departure from the previous implementation is that // an Agent instance holds connections for a variable number of host:ports. // Surprisingly, this is still API compatible as far as third parties are // concerned. The only code that really notices the difference is the // request object. // Another departure is that all code related to HTTP parsing is in // ClientRequest.onSocket(). The Agent is now *strictly* // concerned with managing a connection pool. function Agent(options) { EventEmitter.call(this); var self = this; self.options = options || {}; self.requests = {}; self.sockets = {}; self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets; self.on('free', function(socket, host, port, localAddress) { var name = host + ':' + port; if (localAddress) { name += ':' + localAddress; } if (!socket.destroyed && self.requests[name] && self.requests[name].length) { self.requests[name].shift().onSocket(socket); if (self.requests[name].length === 0) { // don't leak delete self.requests[name]; } } else { // If there are no pending requests just destroy the // socket and it will get removed from the pool. This // gets us out of timeout issues and allows us to // default to Connection:keep-alive. socket.destroy(); } }); self.createConnection = net.createConnection; } util.inherits(Agent, EventEmitter); exports.Agent = Agent; Agent.defaultMaxSockets = 5; Agent.prototype.defaultPort = 80; Agent.prototype.addRequest = function(req, host, port, localAddress) { var name = host + ':' + port; if (localAddress) { name += ':' + localAddress; } if (!this.sockets[name]) { this.sockets[name] = []; } if (this.sockets[name].length < this.maxSockets) { // If we are under maxSockets create a new one. req.onSocket(this.createSocket(name, host, port, localAddress, req)); } else { // We are over limit so we'll add it to the queue. if (!this.requests[name]) { this.requests[name] = []; } this.requests[name].push(req); } }; Agent.prototype.createSocket = function(name, host, port, localAddress, req) { var self = this; var options = util._extend({}, self.options); options.port = port; options.host = host; options.localAddress = localAddress; options.servername = host; if (req) { var hostHeader = req.getHeader('host'); if (hostHeader) { options.servername = hostHeader.replace(/:.*$/, ''); } } var s = self.createConnection(options); if (!self.sockets[name]) { self.sockets[name] = []; } this.sockets[name].push(s); var onFree = function() { self.emit('free', s, host, port, localAddress); } s.on('free', onFree); var onClose = function(err) { // This is the only place where sockets get removed from the Agent. // If you want to remove a socket from the pool, just close it. // All socket errors end in a close event anyway. self.removeSocket(s, name, host, port, localAddress); } s.on('close', onClose); var onRemove = function() { // We need this function for cases like HTTP 'upgrade' // (defined by WebSockets) where we need to remove a socket from the pool // because it'll be locked up indefinitely self.removeSocket(s, name, host, port, localAddress); s.removeListener('close', onClose); s.removeListener('free', onFree); s.removeListener('agentRemove', onRemove); } s.on('agentRemove', onRemove); return s; }; Agent.prototype.removeSocket = function(s, name, host, port, localAddress) { if (this.sockets[name]) { var index = this.sockets[name].indexOf(s); if (index !== -1) { this.sockets[name].splice(index, 1); if (this.sockets[name].length === 0) { // don't leak delete this.sockets[name]; } } } if (this.requests[name] && this.requests[name].length) { var req = this.requests[name][0]; // If we have pending requests and a socket gets closed a new one this.createSocket(name, host, port, localAddress, req).emit('free'); } }; var globalAgent = new Agent(); exports.globalAgent = globalAgent; function ClientRequest(options, cb) { var self = this; OutgoingMessage.call(self); self.agent = options.agent === undefined ? globalAgent : options.agent; var defaultPort = options.defaultPort || 80; var port = options.port || defaultPort; var host = options.hostname || options.host || 'localhost'; if (options.setHost === undefined) { var setHost = true; } self.socketPath = options.socketPath; var method = self.method = (options.method || 'GET').toUpperCase(); self.path = options.path || '/'; if (cb) { self.once('response', cb); } if (!Array.isArray(options.headers)) { if (options.headers) { var keys = Object.keys(options.headers); for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; self.setHeader(key, options.headers[key]); } } if (host && !this.getHeader('host') && setHost) { var hostHeader = host; if (port && +port !== defaultPort) { hostHeader += ':' + port; } this.setHeader('Host', hostHeader); } } if (options.auth && !this.getHeader('Authorization')) { //basic auth this.setHeader('Authorization', 'Basic ' + new Buffer(options.auth).toString('base64')); } if (method === 'GET' || method === 'HEAD' || method === 'CONNECT') { self.useChunkedEncodingByDefault = false; } else { self.useChunkedEncodingByDefault = true; } if (Array.isArray(options.headers)) { self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', options.headers); } else if (self.getHeader('expect')) { self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n', self._renderHeaders()); } if (self.socketPath) { self._last = true; self.shouldKeepAlive = false; if (options.createConnection) { self.onSocket(options.createConnection(self.socketPath)); } else { self.onSocket(net.createConnection(self.socketPath)); } } else if (self.agent) { // If there is an agent we should default to Connection:keep-alive. self._last = false; self.shouldKeepAlive = true; self.agent.addRequest(self, host, port, options.localAddress); } else { // No agent, default to Connection:close. self._last = true; self.shouldKeepAlive = false; if (options.createConnection) { options.port = port; options.host = host; var conn = options.createConnection(options); } else { var conn = net.createConnection({ port: port, host: host, localAddress: options.localAddress }); } self.onSocket(conn); } self._deferToConnect(null, null, function() { self._flush(); self = null; }); } util.inherits(ClientRequest, OutgoingMessage); exports.ClientRequest = ClientRequest; ClientRequest.prototype._implicitHeader = function() { this._storeHeader(this.method + ' ' + this.path + ' HTTP/1.1\r\n', this._renderHeaders()); }; ClientRequest.prototype.abort = function() { if (this.socket) { // in-progress this.socket.destroy(); } else { // haven't been assigned a socket yet. // this could be more efficient, it could // remove itself from the pending requests this._deferToConnect('destroy', []); } }; function createHangUpError() { var error = new Error('socket hang up'); error.code = 'ECONNRESET'; return error; } // Free the parser and also break any links that it // might have to any other things. // TODO: All parser data should be attached to a // single object, so that it can be easily cleaned // up by doing `parser.data = {}`, which should // be done in FreeList.free. `parsers.free(parser)` // should be all that is needed. function freeParser(parser, req) { if (parser) { parser._headers = []; parser.onIncoming = null; if (parser.socket) { parser.socket.onend = null; parser.socket.ondata = null; parser.socket.parser = null; } parser.socket = null; parser.incoming = null; parsers.free(parser); parser = null; } if (req) { req.parser = null; } } function socketCloseListener() { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP socket close'); req.emit('close'); if (req.res && req.res.readable) { // Socket closed before we emitted 'end' below. req.res.emit('aborted'); var res = req.res; res.on('end', function() { res.emit('close'); }); res.push(null); } else if (!req.res && !req._hadError) { // This socket error fired before we started to // receive a response. The error needs to // fire on the request. req.emit('error', createHangUpError()); req._hadError = true; } // Too bad. That output wasn't getting written. // This is pretty terrible that it doesn't raise an error. // Fixed better in v0.10 if (req.output) req.output.length = 0; if (req.outputEncodings) req.outputEncodings.length = 0; if (parser) { parser.finish(); freeParser(parser, req); } } function socketErrorListener(err) { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP SOCKET ERROR: ' + err.message + '\n' + err.stack); if (req) { req.emit('error', err); // For Safety. Some additional errors might fire later on // and we need to make sure we don't double-fire the error event. req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } function socketOnEnd() { var socket = this; var req = this._httpMessage; var parser = this.parser; if (!req.res) { // If we don't have a response then we know that the socket // ended prematurely and we need to emit an error on the request. req.emit('error', createHangUpError()); req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } function socketOnData(d, start, end) { var socket = this; var req = this._httpMessage; var parser = this.parser; var ret = parser.execute(d, start, end - start); if (ret instanceof Error) { debug('parse error'); freeParser(parser, req); socket.destroy(); req.emit('error', ret); req._hadError = true; } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT var bytesParsed = ret; var res = parser.incoming; req.res = res; socket.ondata = null; socket.onend = null; parser.finish(); // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (EventEmitter.listenerCount(req, eventName) > 0) { req.upgradeOrConnect = true; // detach the socket socket.emit('agentRemove'); socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); socket.unshift(bodyHead); req.emit(eventName, res, socket, emptyBuffer); req.emit('close'); } else { // Got Upgrade header or CONNECT method, but have no handler. socket.destroy(); } freeParser(parser, req); } else if (parser.incoming && parser.incoming.complete && // When the status code is 100 (Continue), the server will // send a final response after this client sends a request // body. So, we must not free the parser. parser.incoming.statusCode !== 100) { freeParser(parser, req); } } // client function parserOnIncomingClient(res, shouldKeepAlive) { var parser = this; var socket = this.socket; var req = socket._httpMessage; // propogate "domain" setting... if (req.domain && !res.domain) { debug('setting "res.domain"'); res.domain = req.domain; } debug('AGENT incoming response!'); if (req.res) { // We already have a response object, this means the server // sent a double response. socket.destroy(); return; } req.res = res; // Responses to CONNECT request is handled as Upgrade. if (req.method === 'CONNECT') { res.upgrade = true; return true; // skip body } // Responses to HEAD requests are crazy. // HEAD responses aren't allowed to have an entity-body // but *can* have a content-length which actually corresponds // to the content-length of the entity-body had the request // been a GET. var isHeadResponse = req.method == 'HEAD'; debug('AGENT isHeadResponse ' + isHeadResponse); if (res.statusCode == 100) { // restart the parser, as this is a continue message. delete req.res; // Clear res so that we don't hit double-responses. req.emit('continue'); return true; } if (req.shouldKeepAlive && !shouldKeepAlive && !req.upgradeOrConnect) { // Server MUST respond with Connection:keep-alive for us to enable it. // If we've been upgraded (via WebSockets) we also shouldn't try to // keep the connection open. req.shouldKeepAlive = false; } DTRACE_HTTP_CLIENT_RESPONSE(socket, req); COUNTER_HTTP_CLIENT_RESPONSE(); req.res = res; res.req = req; // add our listener first, so that we guarantee socket cleanup res.on('end', responseOnEnd); var handled = req.emit('response', res); // If the user did not listen for the 'response' event, then they // can't possibly read the data, so we ._dump() it into the void // so that the socket doesn't hang there in a paused state. if (!handled) res._dump(); return isHeadResponse; } // client function responseOnEnd() { var res = this; var req = res.req; var socket = req.socket; if (!req.shouldKeepAlive) { if (socket.writable) { debug('AGENT socket.destroySoon()'); socket.destroySoon(); } assert(!socket.writable); } else { debug('AGENT socket keep-alive'); if (req.timeoutCb) { socket.setTimeout(0, req.timeoutCb); req.timeoutCb = null; } socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); // Mark this socket as available, AFTER user-added end // handlers have a chance to run. process.nextTick(function() { socket.emit('free'); }); } } ClientRequest.prototype.onSocket = function(socket) { var req = this; process.nextTick(function() { var parser = parsers.alloc(); req.socket = socket; req.connection = socket; parser.reinitialize(HTTPParser.RESPONSE); parser.socket = socket; parser.incoming = null; req.parser = parser; socket.parser = parser; socket._httpMessage = req; // Setup "drain" propogation. httpSocketSetup(socket); // Propagate headers limit from request object to parser if (typeof req.maxHeadersCount === 'number') { parser.maxHeaderPairs = req.maxHeadersCount << 1; } else { // Set default value because parser may be reused from FreeList parser.maxHeaderPairs = 2000; } socket.on('error', socketErrorListener); socket.ondata = socketOnData; socket.onend = socketOnEnd; socket.on('close', socketCloseListener); parser.onIncoming = parserOnIncomingClient; req.emit('socket', socket); }); }; ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) { // This function is for calls that need to happen once the socket is // connected and writable. It's an important promisy thing for all the socket // calls that happen either now (when a socket is assigned) or // in the future (when a socket gets assigned out of the pool and is // eventually writable). var self = this; var onSocket = function() { if (self.socket.writable) { if (method) { self.socket[method].apply(self.socket, arguments_); } if (cb) { cb(); } } else { self.socket.once('connect', function() { if (method) { self.socket[method].apply(self.socket, arguments_); } if (cb) { cb(); } }); } } if (!self.socket) { self.once('socket', onSocket); } else { onSocket(); } }; ClientRequest.prototype.setTimeout = function(msecs, callback) { if (callback) this.once('timeout', callback); var self = this; function emitTimeout() { self.emit('timeout'); } if (this.socket && this.socket.writable) { if (this.timeoutCb) this.socket.setTimeout(0, this.timeoutCb); this.timeoutCb = emitTimeout; this.socket.setTimeout(msecs, emitTimeout); return; } // Set timeoutCb so that it'll get cleaned up on request end this.timeoutCb = emitTimeout; if (this.socket) { var sock = this.socket; this.socket.once('connect', function() { sock.setTimeout(msecs, emitTimeout); }); return; } this.once('socket', function(sock) { sock.setTimeout(msecs, emitTimeout); }); }; ClientRequest.prototype.setNoDelay = function() { this._deferToConnect('setNoDelay', arguments); }; ClientRequest.prototype.setSocketKeepAlive = function() { this._deferToConnect('setKeepAlive', arguments); }; ClientRequest.prototype.clearTimeout = function(cb) { this.setTimeout(0, cb); }; exports.request = function(options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'http:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } return new ClientRequest(options, cb); }; exports.get = function(options, cb) { var req = exports.request(options, cb); req.end(); return req; }; function ondrain() { if (this._httpMessage) this._httpMessage.emit('drain'); } function httpSocketSetup(socket) { socket.removeListener('drain', ondrain); socket.on('drain', ondrain); } function Server(requestListener) { if (!(this instanceof Server)) return new Server(requestListener); net.Server.call(this, { allowHalfOpen: true }); if (requestListener) { this.addListener('request', requestListener); } // Similar option to this. Too lazy to write my own docs. // http://www.squid-cache.org/Doc/config/half_closed_clients/ // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F this.httpAllowHalfOpen = false; this.addListener('connection', connectionListener); this.addListener('clientError', function(err, conn) { conn.destroy(err); }); this.timeout = 2 * 60 * 1000; } util.inherits(Server, net.Server); Server.prototype.setTimeout = function(msecs, callback) { this.timeout = msecs; if (callback) this.on('timeout', callback); }; exports.Server = Server; exports.createServer = function(requestListener) { return new Server(requestListener); }; function connectionListener(socket) { var self = this; var outgoing = []; var incoming = []; function abortIncoming() { while (incoming.length) { var req = incoming.shift(); req.emit('aborted'); req.emit('close'); } // abort socket._httpMessage ? } function serverSocketCloseListener() { debug('server socket close'); // mark this parser as reusable if (this.parser) freeParser(this.parser); abortIncoming(); } debug('SERVER new http connection'); httpSocketSetup(socket); // If the user has added a listener to the server, // request, or response, then it's their responsibility. // otherwise, destroy on timeout by default if (self.timeout) socket.setTimeout(self.timeout); socket.on('timeout', function() { var req = socket.parser && socket.parser.incoming; var reqTimeout = req && !req.complete && req.emit('timeout', socket); var res = socket._httpMessage; var resTimeout = res && res.emit('timeout', socket); var serverTimeout = self.emit('timeout', socket); if (!reqTimeout && !resTimeout && !serverTimeout) socket.destroy(); }); var parser = parsers.alloc(); parser.reinitialize(HTTPParser.REQUEST); parser.socket = socket; socket.parser = parser; parser.incoming = null; // Propagate headers limit from server instance to parser if (typeof this.maxHeadersCount === 'number') { parser.maxHeaderPairs = this.maxHeadersCount << 1; } else { // Set default value because parser may be reused from FreeList parser.maxHeaderPairs = 2000; } socket.addListener('error', function(e) { self.emit('clientError', e, this); }); socket.ondata = function (d, start, end) { assert(!socket._drain_paused); var ret = parser.execute(d, start, end - start); if (ret instanceof Error) { debug('parse error'); socket.destroy(ret); } else if (parser.incoming && parser.incoming.upgrade) { // Upgrade or CONNECT var bytesParsed = ret; var req = parser.incoming; socket.ondata = null; socket.onend = null; socket.removeListener('close', serverSocketCloseListener); parser.finish(); freeParser(parser, req); // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade'; if (EventEmitter.listenerCount(self, eventName) > 0) { socket.unshift(bodyHead); self.emit(eventName, req, req.socket, emptyBuffer); } else { // Got upgrade header or CONNECT method, but have no handler. socket.destroy(); } if (socket._drain_paused) { // onIncoming paused the socket, we should pause the parser as well debug('pause parser'); socket.parser.pause(); } } }; socket.onend = function() { var ret = parser.finish(); if (ret instanceof Error) { debug('parse error'); socket.destroy(ret); return; } if (!self.httpAllowHalfOpen) { abortIncoming(); if (socket.writable) socket.end(); } else if (outgoing.length) { outgoing[outgoing.length - 1]._last = true; } else if (socket._httpMessage) { socket._httpMessage._last = true; } else { if (socket.writable) socket.end(); } }; socket.addListener('close', serverSocketCloseListener); socket._drain_paused = false; function socketOnDrain() { // If we previously paused, then start reading again. if (socket._drain_paused) { socket._drain_paused = false; socket.parser.resume(); socket.resume(); } } socket.on('drain', socketOnDrain); // The following callback is issued after the headers have been read on a // new message. In this callback we setup the response object and pass it // to the user. parser.onIncoming = function(req, shouldKeepAlive) { incoming.push(req); // If the writable end isn't consuming, then stop reading // so that we don't become overwhelmed by a flood of // pipelined requests that may never be resolved. if (!socket._drain_paused && socket._handle) { var needPause = socket._handle.writeQueueSize > 0; if (needPause) { socket._drain_paused = true; // We also need to pause the parser, but don't do that until after // the call to execute, because we may still be processing the last // chunk. socket.pause(); } } var res = new ServerResponse(req); res.shouldKeepAlive = shouldKeepAlive; DTRACE_HTTP_SERVER_REQUEST(req, socket); COUNTER_HTTP_SERVER_REQUEST(); if (socket._httpMessage) { // There are already pending outgoing res, append. outgoing.push(res); } else { res.assignSocket(socket); } // When we're finished writing the response, check if this is the last // respose, if so destroy the socket. res.on('finish', function() { // Usually the first incoming element should be our request. it may // be that in the case abortIncoming() was called that the incoming // array will be empty. assert(incoming.length == 0 || incoming[0] === req); incoming.shift(); // if the user never called req.read(), and didn't pipe() or // .resume() or .on('data'), then we call req._dump() so that the // bytes will be pulled off the wire. if (!req._consuming) req._dump(); res.detachSocket(socket); if (res._last) { socket.destroySoon(); } else { // start sending the next message var m = outgoing.shift(); if (m) { m.assignSocket(socket); } } }); if (req.headers.expect !== undefined && (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) && continueExpression.test(req.headers['expect'])) { res._expect_continue = true; if (EventEmitter.listenerCount(self, 'checkContinue') > 0) { self.emit('checkContinue', req, res); } else { res.writeContinue(); self.emit('request', req, res); } } else { self.emit('request', req, res); } return false; // Not a HEAD response. (Not even a response!) }; } exports._connectionListener = connectionListener; // Legacy Interface function Client(port, host) { if (!(this instanceof Client)) return new Client(port, host); EventEmitter.call(this); host = host || 'localhost'; port = port || 80; this.host = host; this.port = port; this.agent = new Agent({ host: host, port: port, maxSockets: 1 }); } util.inherits(Client, EventEmitter); Client.prototype.request = function(method, path, headers) { var self = this; var options = {}; options.host = self.host; options.port = self.port; if (method[0] === '/') { headers = path; path = method; method = 'GET'; } options.method = method; options.path = path; options.headers = headers; options.agent = self.agent; var c = new ClientRequest(options); c.on('error', function(e) { self.emit('error', e); }); // The old Client interface emitted 'end' on socket end. // This doesn't map to how we want things to operate in the future // but it will get removed when we remove this legacy interface. c.on('socket', function(s) { s.on('end', function() { if (self._decoder) { var ret = self._decoder.end(); if (ret) self.emit('data', ret); } self.emit('end'); }); }); return c; }; exports.Client = util.deprecate(Client, 'http.Client will be removed soon. Do not use it.'); exports.createClient = util.deprecate(function(port, host) { return new Client(port, host); }, 'http.createClient is deprecated. Use `http.request` instead.'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a transform stream is a readable/writable stream where you do // something with the data. Sometimes it's called a "filter", // but that's not a great name for it, since that implies a thing where // some bits pass through, and others are simply ignored. (That would // be a valid example of a transform, of course.) // // While the output is causally related to the input, it's not a // necessarily symmetric or synchronous transformation. For example, // a zlib stream might take multiple plain-text writes(), and then // emit a single compressed chunk some time in the future. // // Here's how this works: // // The Transform stream has all the aspects of the readable and writable // stream classes. When you write(chunk), that calls _write(chunk,cb) // internally, and returns false if there's a lot of pending writes // buffered up. When you call read(), that calls _read(n) until // there's enough pending readable data buffered up. // // In a transform stream, the written data is placed in a buffer. When // _read(n) is called, it transforms the queued up data, calling the // buffered _write cb's as it consumes chunks. If consuming a single // written chunk would result in multiple output chunks, then the first // outputted bit calls the readcb, and subsequent chunks just go into // the read buffer, and will cause it to emit 'readable' if necessary. // // This way, back-pressure is actually determined by the reading side, // since _read has to be called to start processing a new chunk. However, // a pathological inflate type of transform can cause excessive buffering // here. For example, imagine a stream where every byte of input is // interpreted as an integer from 0-255, and then results in that many // bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in // 1kb of data being output. In this case, you could write a very small // amount of input, and end up with a very large amount of output. In // such a pathological inflating mechanism, there'd be no way to tell // the system to stop doing the transform. A single 4MB write could // cause the system to run out of memory. // // However, even in such a pathological case, only a single written chunk // would be consumed, and then the rest would wait (un-transformed) until // the results of the previous transformed chunk were consumed. module.exports = Transform; var Duplex = require('_stream_duplex'); var util = require('util'); util.inherits(Transform, Duplex); function TransformState(options, stream) { this.afterTransform = function(er, data) { return afterTransform(stream, er, data); }; this.needTransform = false; this.transforming = false; this.writecb = null; this.writechunk = null; } function afterTransform(stream, er, data) { var ts = stream._transformState; ts.transforming = false; var cb = ts.writecb; if (!cb) return stream.emit('error', new Error('no writecb in Transform class')); ts.writechunk = null; ts.writecb = null; if (data !== null && data !== undefined) stream.push(data); if (cb) cb(er); var rs = stream._readableState; rs.reading = false; if (rs.needReadable || rs.length < rs.highWaterMark) { stream._read(rs.highWaterMark); } } function Transform(options) { if (!(this instanceof Transform)) return new Transform(options); Duplex.call(this, options); var ts = this._transformState = new TransformState(options, this); // when the writable side finishes, then flush out anything remaining. var stream = this; // start out asking for a readable event once data is transformed. this._readableState.needReadable = true; // we have implemented the _read method, and done the other things // that Readable wants before the first _read call, so unset the // sync guard flag. this._readableState.sync = false; this.once('finish', function() { if ('function' === typeof this._flush) this._flush(function(er) { done(stream, er); }); else done(stream); }); } Transform.prototype.push = function(chunk, encoding) { this._transformState.needTransform = false; return Duplex.prototype.push.call(this, chunk, encoding); }; // This is the part where you do stuff! // override this function in implementation classes. // 'chunk' is an input chunk. // // Call `push(newChunk)` to pass along transformed output // to the readable side. You may call 'push' zero or more times. // // Call `cb(err)` when you are done with this chunk. If you pass // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. Transform.prototype._transform = function(chunk, encoding, cb) { throw new Error('not implemented'); }; Transform.prototype._write = function(chunk, encoding, cb) { var ts = this._transformState; ts.writecb = cb; ts.writechunk = chunk; ts.writeencoding = encoding; if (!ts.transforming) { var rs = this._readableState; if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); } }; // Doesn't matter what the args are here. // _transform does all the work. // That we got here means that the readable side wants more data. Transform.prototype._read = function(n) { var ts = this._transformState; if (ts.writechunk && ts.writecb && !ts.transforming) { ts.transforming = true; this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); } else { // mark that we need a transform, so that any data that comes in // will get processed, now that we've asked for it. ts.needTransform = true; } }; function done(stream, er) { if (er) return stream.emit('error', er); // if there's nothing in the write buffer, then that means // that nothing more will ever be provided var ws = stream._writableState; var rs = stream._readableState; var ts = stream._transformState; if (ws.length) throw new Error('calling transform done when ws.length != 0'); if (ts.transforming) throw new Error('calling transform done when still transforming'); return stream.push(null); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // Microsoft grants you the right to use these script files for the sole purpose of either: (i) interacting through your browser with the Microsoft website, subject to the website's terms of use; or (ii) using the files as included with a Microsoft product subject to that product's license terms. Microsoft reserves all other rights to the files not expressly granted by Microsoft, whether by implication, estoppel or otherwise. The notices and licenses below are for informational purposes only. // Punycode.js // Copyright 2011 Mathias Bynens // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /*! http://mths.be/punycode v1.2.0 by @mathias */ ;(function(root) { /** * The `punycode` object. * @name punycode * @type Object */ var punycode, /** Detect free variables `define`, `exports`, `module` and `require` */ freeDefine = typeof define == 'function' && typeof define.amd == 'object' && define.amd && define, freeExports = typeof exports == 'object' && exports, freeModule = typeof module == 'object' && module, freeRequire = typeof require == 'function' && require, /** Highest positive signed 32-bit float value */ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 /** Bootstring parameters */ base = 36, tMin = 1, tMax = 26, skew = 38, damp = 700, initialBias = 72, initialN = 128, // 0x80 delimiter = '-', // '\x2D' /** Regular expressions */ regexPunycode = /^xn--/, regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators /** Error messages */ errors = { 'overflow': 'Overflow: input needs wider integers to process', 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 'invalid-input': 'Invalid input' }, /** Convenience shortcuts */ baseMinusTMin = base - tMin, floor = Math.floor, stringFromCharCode = String.fromCharCode, /** Temporary variable */ key; /*--------------------------------------------------------------------------*/ /** * A generic error utility function. * @private * @param {String} type The error type. * @returns {Error} Throws a `RangeError` with the applicable error message. */ function error(type) { throw RangeError(errors[type]); } /** * A generic `Array#map` utility function. * @private * @param {Array} array The array to iterate over. * @param {Function} callback The function that gets called for every array * item. * @returns {Array} A new array of values returned by the callback function. */ function map(array, fn) { var length = array.length; while (length--) { array[length] = fn(array[length]); } return array; } /** * A simple `Array#map`-like wrapper to work with domain name strings. * @private * @param {String} domain The domain name. * @param {Function} callback The function that gets called for every * character. * @returns {Array} A new string of characters returned by the callback * function. */ function mapDomain(string, fn) { return map(string.split(regexSeparators), fn).join('.'); } /** * Creates an array containing the decimal code points of each Unicode * character in the string. While JavaScript uses UCS-2 internally, * this function will convert a pair of surrogate halves (each of which * UCS-2 exposes as separate characters) into a single code point, * matching UTF-16. * @see `punycode.ucs2.encode` * @see * @memberOf punycode.ucs2 * @name decode * @param {String} string The Unicode input string (UCS-2). * @returns {Array} The new array of code points. */ function ucs2decode(string) { var output = [], counter = 0, length = string.length, value, extra; while (counter < length) { value = string.charCodeAt(counter++); if ((value & 0xF800) == 0xD800 && counter < length) { // high surrogate, and there is a next character extra = string.charCodeAt(counter++); if ((extra & 0xFC00) == 0xDC00) { // low surrogate output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); } else { output.push(value, extra); } } else { output.push(value); } } return output; } /** * Creates a string based on an array of decimal code points. * @see `punycode.ucs2.decode` * @memberOf punycode.ucs2 * @name encode * @param {Array} codePoints The array of decimal code points. * @returns {String} The new Unicode string (UCS-2). */ function ucs2encode(array) { return map(array, function(value) { var output = ''; if (value > 0xFFFF) { value -= 0x10000; output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); value = 0xDC00 | value & 0x3FF; } output += stringFromCharCode(value); return output; }).join(''); } /** * Converts a basic code point into a digit/integer. * @see `digitToBasic()` * @private * @param {Number} codePoint The basic (decimal) code point. * @returns {Number} The numeric value of a basic code point (for use in * representing integers) in the range `0` to `base - 1`, or `base` if * the code point does not represent a value. */ function basicToDigit(codePoint) { return codePoint - 48 < 10 ? codePoint - 22 : codePoint - 65 < 26 ? codePoint - 65 : codePoint - 97 < 26 ? codePoint - 97 : base; } /** * Converts a digit/integer into a basic code point. * @see `basicToDigit()` * @private * @param {Number} digit The numeric value of a basic code point. * @returns {Number} The basic code point whose value (when used for * representing integers) is `digit`, which needs to be in the range * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is * used; else, the lowercase form is used. The behavior is undefined * if flag is non-zero and `digit` has no uppercase form. */ function digitToBasic(digit, flag) { // 0..25 map to ASCII a..z or A..Z // 26..35 map to ASCII 0..9 return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); } /** * Bias adaptation function as per section 3.4 of RFC 3492. * http://tools.ietf.org/html/rfc3492#section-3.4 * @private */ function adapt(delta, numPoints, firstTime) { var k = 0; delta = firstTime ? floor(delta / damp) : delta >> 1; delta += floor(delta / numPoints); for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { delta = floor(delta / baseMinusTMin); } return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); } /** * Converts a basic code point to lowercase if `flag` is falsy, or to * uppercase if `flag` is truthy. The code point is unchanged if it's * caseless. The behavior is undefined if `codePoint` is not a basic code * point. * @private * @param {Number} codePoint The numeric value of a basic code point. * @returns {Number} The resulting basic code point. */ function encodeBasic(codePoint, flag) { codePoint -= (codePoint - 97 < 26) << 5; return codePoint + (!flag && codePoint - 65 < 26) << 5; } /** * Converts a Punycode string of ASCII code points to a string of Unicode * code points. * @memberOf punycode * @param {String} input The Punycode string of ASCII code points. * @returns {String} The resulting string of Unicode code points. */ function decode(input) { // Don't use UCS-2 var output = [], inputLength = input.length, out, i = 0, n = initialN, bias = initialBias, basic, j, index, oldi, w, k, digit, t, length, /** Cached calculation results */ baseMinusT; // Handle the basic code points: let `basic` be the number of input code // points before the last delimiter, or `0` if there is none, then copy // the first basic code points to the output. basic = input.lastIndexOf(delimiter); if (basic < 0) { basic = 0; } for (j = 0; j < basic; ++j) { // if it's not a basic code point if (input.charCodeAt(j) >= 0x80) { error('not-basic'); } output.push(input.charCodeAt(j)); } // Main decoding loop: start just after the last delimiter if any basic code // points were copied; start at the beginning otherwise. for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { // `index` is the index of the next character to be consumed. // Decode a generalized variable-length integer into `delta`, // which gets added to `i`. The overflow checking is easier // if we increase `i` as we go, then subtract off its starting // value at the end to obtain `delta`. for (oldi = i, w = 1, k = base; /* no condition */; k += base) { if (index >= inputLength) { error('invalid-input'); } digit = basicToDigit(input.charCodeAt(index++)); if (digit >= base || digit > floor((maxInt - i) / w)) { error('overflow'); } i += digit * w; t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (digit < t) { break; } baseMinusT = base - t; if (w > floor(maxInt / baseMinusT)) { error('overflow'); } w *= baseMinusT; } out = output.length + 1; bias = adapt(i - oldi, out, oldi == 0); // `i` was supposed to wrap around from `out` to `0`, // incrementing `n` each time, so we'll fix that now: if (floor(i / out) > maxInt - n) { error('overflow'); } n += floor(i / out); i %= out; // Insert `n` at position `i` of the output output.splice(i++, 0, n); } return ucs2encode(output); } /** * Converts a string of Unicode code points to a Punycode string of ASCII * code points. * @memberOf punycode * @param {String} input The string of Unicode code points. * @returns {String} The resulting Punycode string of ASCII code points. */ function encode(input) { var n, delta, handledCPCount, basicLength, bias, j, m, q, k, t, currentValue, output = [], /** `inputLength` will hold the number of code points in `input`. */ inputLength, /** Cached calculation results */ handledCPCountPlusOne, baseMinusT, qMinusT; // Convert the input in UCS-2 to Unicode input = ucs2decode(input); // Cache the length inputLength = input.length; // Initialize the state n = initialN; delta = 0; bias = initialBias; // Handle the basic code points for (j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue < 0x80) { output.push(stringFromCharCode(currentValue)); } } handledCPCount = basicLength = output.length; // `handledCPCount` is the number of code points that have been handled; // `basicLength` is the number of basic code points. // Finish the basic string - if it is not empty - with a delimiter if (basicLength) { output.push(delimiter); } // Main encoding loop: while (handledCPCount < inputLength) { // All non-basic code points < n have been handled already. Find the next // larger one: for (m = maxInt, j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue >= n && currentValue < m) { m = currentValue; } } // Increase `delta` enough to advance the decoder's state to , // but guard against overflow handledCPCountPlusOne = handledCPCount + 1; if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { error('overflow'); } delta += (m - n) * handledCPCountPlusOne; n = m; for (j = 0; j < inputLength; ++j) { currentValue = input[j]; if (currentValue < n && ++delta > maxInt) { error('overflow'); } if (currentValue == n) { // Represent delta as a generalized variable-length integer for (q = delta, k = base; /* no condition */; k += base) { t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); if (q < t) { break; } qMinusT = q - t; baseMinusT = base - t; output.push( stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) ); q = floor(qMinusT / baseMinusT); } output.push(stringFromCharCode(digitToBasic(q, 0))); bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); delta = 0; ++handledCPCount; } } ++delta; ++n; } return output.join(''); } /** * Converts a Punycode string representing a domain name to Unicode. Only the * Punycoded parts of the domain name will be converted, i.e. it doesn't * matter if you call it on a string that has already been converted to * Unicode. * @memberOf punycode * @param {String} domain The Punycode domain name to convert to Unicode. * @returns {String} The Unicode representation of the given Punycode * string. */ function toUnicode(domain) { return mapDomain(domain, function(string) { return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string; }); } /** * Converts a Unicode string representing a domain name to Punycode. Only the * non-ASCII parts of the domain name will be converted, i.e. it doesn't * matter if you call it with a domain that's already in ASCII. * @memberOf punycode * @param {String} domain The domain name to convert, as a Unicode string. * @returns {String} The Punycode representation of the given domain name. */ function toASCII(domain) { return mapDomain(domain, function(string) { return regexNonASCII.test(string) ? 'xn--' + encode(string) : string; }); } /*--------------------------------------------------------------------------*/ /** Define the public API */ punycode = { /** * A string representing the current Punycode.js version number. * @memberOf punycode * @type String */ 'version': '1.2.0', /** * An object of methods to convert from JavaScript's internal character * representation (UCS-2) to decimal Unicode code points, and back. * @see * @memberOf punycode * @type Object */ 'ucs2': { 'decode': ucs2decode, 'encode': ucs2encode }, 'decode': decode, 'encode': encode, 'toASCII': toASCII, 'toUnicode': toUnicode }; /** Expose `punycode` */ if (freeExports) { if (freeModule && freeModule.exports == freeExports) { // in Node.js or Ringo 0.8+ freeModule.exports = punycode; } else { // in Narwhal or Ringo 0.7- for (key in punycode) { punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); } } } else if (freeDefine) { // via curl.js or RequireJS define('punycode', punycode); } else { // in a browser or Rhino root.punycode = punycode; } }(this)); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // the sys module was renamed to 'util'. // this shim remains to keep old programs working. module.exports = require('util'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var binding = process.binding('evals'); module.exports = Script; Script.Script = Script; function Script(code, ctx, filename) { if (!(this instanceof Script)) { return new Script(code, ctx, filename); } var ns = new binding.NodeScript(code, ctx, filename); // bind all methods to this Script object Object.keys(binding.NodeScript.prototype).forEach(function(f) { if (typeof binding.NodeScript.prototype[f] === 'function') { this[f] = function() { if (!(this instanceof Script)) { throw new TypeError('invalid call to ' + f); } return ns[f].apply(ns, arguments); }; } }, this); } Script.createScript = function(code, ctx, name) { return new Script(code, ctx, name); }; Script.createContext = binding.NodeScript.createContext; Script.runInContext = binding.NodeScript.runInContext; Script.runInThisContext = binding.NodeScript.runInThisContext; Script.runInNewContext = binding.NodeScript.runInNewContext; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var cares, net = require('net'); function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. // For backwards compatibility. libuv returns ENOENT on NXDOMAIN. if (errorno == 'ENOENT') { errorno = 'ENOTFOUND'; } var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // c-ares invokes a callback either synchronously or asynchronously, // but the dns API should always invoke a callback asynchronously. // // This function makes sure that the callback is invoked asynchronously. // It returns a function that invokes the callback within nextTick(). // // To avoid invoking unnecessary nextTick(), `immediately` property of // returned function should be set to true after c-ares returned. // // Usage: // // function someAPI(callback) { // callback = makeAsync(callback); // channel.someAPI(..., callback); // callback.immediately = true; // } function makeAsync(callback) { if (typeof callback !== 'function') { return callback; } return function asyncCallback() { if (asyncCallback.immediately) { // The API already returned, we can invoke the callback immediately. callback.apply(null, arguments); } else { var args = arguments; process.nextTick(function() { callback.apply(null, args); }); } }; } // Easy DNS A/AAAA look up // lookup(domain, [family,] callback) exports.lookup = function(domain, family, callback) { // parse arguments if (arguments.length === 2) { callback = family; family = 0; } else if (!family) { family = 0; } else { family = +family; if (family !== 4 && family !== 6) { throw new Error('invalid argument: `family` must be 4 or 6'); } } callback = makeAsync(callback); if (!domain) { callback(null, null, family === 6 ? 6 : 4); return {}; } // Hack required for Windows because Win7 removed the // localhost entry from c:\WINDOWS\system32\drivers\etc\hosts // See http://daniel.haxx.se/blog/2011/02/21/localhost-hack-on-windows/ // TODO Remove this once c-ares handles this problem. if (process.platform == 'win32' && domain == 'localhost') { callback(null, '127.0.0.1', 4); return {}; } var matchedFamily = net.isIP(domain); if (matchedFamily) { callback(null, domain, matchedFamily); return {}; } function onanswer(addresses) { if (addresses) { if (family) { callback(null, addresses[0], family); } else { callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4); } } else { callback(errnoException(process._errno, 'getaddrinfo')); } } cares = cares || process.binding('cares_wrap'); var wrap = cares.getaddrinfo(domain, family); if (!wrap) { throw errnoException(process._errno, 'getaddrinfo'); } wrap.oncomplete = onanswer; callback.immediately = true; return wrap; }; function resolver(bindingName) { cares = cares || process.binding('cares_wrap'); var binding = cares[bindingName]; return function query(name, callback) { function onanswer(status, result) { if (!status) { callback(null, result); } else { callback(errnoException(process._errno, bindingName)); } } callback = makeAsync(callback); var wrap = binding(name, onanswer); if (!wrap) { throw errnoException(process._errno, bindingName); } callback.immediately = true; return wrap; } } var resolveMap = {}; exports.resolve4 = resolveMap.A = resolver('queryA'); exports.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); exports.resolveCname = resolveMap.CNAME = resolver('queryCname'); exports.resolveMx = resolveMap.MX = resolver('queryMx'); exports.resolveNs = resolveMap.NS = resolver('queryNs'); exports.resolveTxt = resolveMap.TXT = resolver('queryTxt'); exports.resolveSrv = resolveMap.SRV = resolver('querySrv'); exports.resolveNaptr = resolveMap.NAPTR = resolver('queryNaptr'); exports.reverse = resolveMap.PTR = resolver('getHostByAddr'); exports.resolve = function(domain, type_, callback_) { var resolver, callback; if (typeof type_ == 'string') { resolver = resolveMap[type_]; callback = callback_; } else { resolver = exports.resolve4; callback = type_; } if (typeof resolver === 'function') { return resolver(domain, callback); } else { throw new Error('Unknown type "' + type_ + '"'); } }; // ERROR CODES exports.NODATA = 'ENODATA'; exports.FORMERR = 'EFORMERR'; exports.SERVFAIL = 'ESERVFAIL'; exports.NOTFOUND = 'ENOTFOUND'; exports.NOTIMP = 'ENOTIMP'; exports.REFUSED = 'EREFUSED'; exports.BADQUERY = 'EBADQUERY'; exports.ADNAME = 'EADNAME'; exports.BADFAMILY = 'EBADFAMILY'; exports.BADRESP = 'EBADRESP'; exports.CONNREFUSED = 'ECONNREFUSED'; exports.TIMEOUT = 'ETIMEOUT'; exports.EOF = 'EOF'; exports.FILE = 'EFILE'; exports.NOMEM = 'ENOMEM'; exports.DESTRUCTION = 'EDESTRUCTION'; exports.BADSTR = 'EBADSTR'; exports.BADFLAGS = 'EBADFLAGS'; exports.NONAME = 'ENONAME'; exports.BADHINTS = 'EBADHINTS'; exports.NOTINITIALIZED = 'ENOTINITIALIZED'; exports.LOADIPHLPAPI = 'ELOADIPHLPAPI'; exports.ADDRGETNETWORKPARAMS = 'EADDRGETNETWORKPARAMS'; exports.CANCELLED = 'ECANCELLED'; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Query String Utilities var QueryString = exports; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function charCode(c) { return c.charCodeAt(0); } // a safe fast alternative to decodeURIComponent QueryString.unescapeBuffer = function(s, decodeSpaces) { var out = new Buffer(s.length); var state = 'CHAR'; // states: CHAR, HEX0, HEX1 var n, m, hexchar; for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) { var c = s.charCodeAt(inIndex); switch (state) { case 'CHAR': switch (c) { case charCode('%'): n = 0; m = 0; state = 'HEX0'; break; case charCode('+'): if (decodeSpaces) c = charCode(' '); // pass thru default: out[outIndex++] = c; break; } break; case 'HEX0': state = 'HEX1'; hexchar = c; if (charCode('0') <= c && c <= charCode('9')) { n = c - charCode('0'); } else if (charCode('a') <= c && c <= charCode('f')) { n = c - charCode('a') + 10; } else if (charCode('A') <= c && c <= charCode('F')) { n = c - charCode('A') + 10; } else { out[outIndex++] = charCode('%'); out[outIndex++] = c; state = 'CHAR'; break; } break; case 'HEX1': state = 'CHAR'; if (charCode('0') <= c && c <= charCode('9')) { m = c - charCode('0'); } else if (charCode('a') <= c && c <= charCode('f')) { m = c - charCode('a') + 10; } else if (charCode('A') <= c && c <= charCode('F')) { m = c - charCode('A') + 10; } else { out[outIndex++] = charCode('%'); out[outIndex++] = hexchar; out[outIndex++] = c; break; } out[outIndex++] = 16 * n + m; break; } } // TODO support returning arbitrary buffers. return out.slice(0, outIndex - 1); }; QueryString.unescape = function(s, decodeSpaces) { return QueryString.unescapeBuffer(s, decodeSpaces).toString(); }; QueryString.escape = function(str) { return encodeURIComponent(str); }; var stringifyPrimitive = function(v) { switch (typeof v) { case 'string': return v; case 'boolean': return v ? 'true' : 'false'; case 'number': return isFinite(v) ? v : ''; default: return ''; } }; QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) { sep = sep || '&'; eq = eq || '='; if (obj === null) { obj = undefined; } if (typeof obj === 'object') { return Object.keys(obj).map(function(k) { var ks = QueryString.escape(stringifyPrimitive(k)) + eq; if (Array.isArray(obj[k])) { return obj[k].map(function(v) { return ks + QueryString.escape(stringifyPrimitive(v)); }).join(sep); } else { return ks + QueryString.escape(stringifyPrimitive(obj[k])); } }).join(sep); } if (!name) return ''; return QueryString.escape(stringifyPrimitive(name)) + eq + QueryString.escape(stringifyPrimitive(obj)); }; // Parse a key=val string. QueryString.parse = QueryString.decode = function(qs, sep, eq, options) { sep = sep || '&'; eq = eq || '='; var obj = {}; if (typeof qs !== 'string' || qs.length === 0) { return obj; } var regexp = /\+/g; qs = qs.split(sep); var maxKeys = 1000; if (options && typeof options.maxKeys === 'number') { maxKeys = options.maxKeys; } var len = qs.length; // maxKeys <= 0 means that we should not limit keys count if (maxKeys > 0 && len > maxKeys) { len = maxKeys; } for (var i = 0; i < len; ++i) { var x = qs[i].replace(regexp, '%20'), idx = x.indexOf(eq), kstr, vstr, k, v; if (idx >= 0) { kstr = x.substr(0, idx); vstr = x.substr(idx + 1); } else { kstr = x; vstr = ''; } try { k = decodeURIComponent(kstr); v = decodeURIComponent(vstr); } catch (e) { k = QueryString.unescape(kstr, true); v = QueryString.unescape(vstr, true); } if (!hasOwnProperty(obj, k)) { obj[k] = v; } else if (Array.isArray(obj[k])) { obj[k].push(v); } else { obj[k] = [obj[k], v]; } } return obj; }; // Copyright (c) Microsoft Corporation. All rights reserved. // Patch classes for chakra var extend = function (dest, from) { var props = Object.getOwnPropertyNames(from); props.forEach(function (name) { var destination = Object.getOwnPropertyDescriptor(from, name); try { Object.defineProperty(dest, name, destination); } catch (e) { // ignore errors } }); }; if (!global.__chakra_wp_patched) { // patch fs.js to ignore handling of symbolic links var pathModule = require('path'); var fs = require('fs'); var isWindows = process.platform === 'win32'; // Regex to find the device root, including trailing slash. E.g. 'c:\\'. if (isWindows) { var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; } else { var splitRootRe = /^[\/]*/; } if (isWindows) { var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; } else { var nextPartRe = /(.*?)(?:[\/]+|$)/g; } fs.realpathSync = function realpathSync(p, cache) { // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return cache[p]; } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { knownHard[base] = true; } } // walk down the path, swapping out linked pathparts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { continue; } var resolvedLink; if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // some known symbolic link. no need to stat again. resolvedLink = cache[base]; } else { var permError = false; var stat; try { stat = fs.lstatSync(base); } catch (e) { if (e.errno == 50) { permError = true; stat = null; } else { throw e; } } if (permError || !stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; continue; } // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); } resolvedLink = pathModule.resolve(previous, linkTarget); // track this, if given a cache. if (cache) cache[base] = resolvedLink; if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } if (cache) cache[original] = p; return p; }; function maybeCallback(cb) { return typeof cb === 'function' ? cb : rethrow(); } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { if (typeof cb !== 'function') { return rethrow(); } return function () { return cb.apply(null, arguments); }; } // path fs.realpath: fs.realpath = function realpath(p, cache, cb) { if (typeof cb !== 'function') { cb = maybeCallback(cache); cache = null; } // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return process.nextTick(cb.bind(null, null, cache[p])); } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function (err) { // PATCH: we ignore permissions error, path exists in this case if (err && err.errno != 50) return cb(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } // walk down the path, swapping out linked pathparts for their real // values function LOOP() { // stop if scanned past end of path if (pos >= p.length) { if (cache) cache[original] = p; return cb(null, p); } // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { return process.nextTick(LOOP); } if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // known symbolic link. no need to stat again. return gotResolvedLink(cache[base]); } return fs.lstat(base, gotStat); } function gotStat(err, stat) { // PATCH: we ignore permissions error, path exists in this case if (err && err.errno != 50) return cb(err); // PATCH: we ignore permissions error, path exists in this case // if not a symlink, skip to the next path part if ((err && err.errno == 50) || !stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; return process.nextTick(LOOP); } // stat & read the link if not read before // call gotTarget as soon as the link target is known // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } fs.stat(base, function (err) { if (err) return cb(err); fs.readlink(base, function (err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target, base) { if (err) return cb(err); var resolvedLink = pathModule.resolve(previous, target); if (cache) cache[base] = resolvedLink; gotResolvedLink(resolvedLink); } function gotResolvedLink(resolvedLink) { // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } }; Object.defineProperty(global, '__chakra_wp_patched', { enumerable: false, value: true }); }// This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var util = require('util'); var events = require('events'); var UDP = process.binding('udp_wrap').UDP; var BIND_STATE_UNBOUND = 0; var BIND_STATE_BINDING = 1; var BIND_STATE_BOUND = 2; // lazily loaded var cluster = null; var dns = null; var net = null; // no-op callback function noop() { } function isIP(address) { if (!net) net = require('net'); return net.isIP(address); } function lookup(address, family, callback) { if (!dns) dns = require('dns'); return dns.lookup(address, family, callback); } function lookup4(address, callback) { return lookup(address || '0.0.0.0', 4, callback); } function lookup6(address, callback) { return lookup(address || '::0', 6, callback); } function newHandle(type) { if (type == 'udp4') { var handle = new UDP; handle.lookup = lookup4; return handle; } if (type == 'udp6') { var handle = new UDP; handle.lookup = lookup6; handle.bind = handle.bind6; handle.send = handle.send6; return handle; } if (type == 'unix_dgram') throw new Error('unix_dgram sockets are not supported any more.'); throw new Error('Bad socket type specified. Valid types are: udp4, udp6'); } exports._createSocketHandle = function(address, port, addressType, fd) { // Opening an existing fd is not supported for UDP handles. assert(typeof fd !== 'number' || fd < 0); var handle = newHandle(addressType); if (port || address) { var r = handle.bind(address, port || 0, 0); if (r == -1) { handle.close(); handle = null; } } return handle; }; function Socket(type, listener) { events.EventEmitter.call(this); var handle = newHandle(type); handle.owner = this; this._handle = handle; this._receiving = false; this._bindState = BIND_STATE_UNBOUND; this.type = type; this.fd = null; // compatibility hack if (typeof listener === 'function') this.on('message', listener); } util.inherits(Socket, events.EventEmitter); exports.Socket = Socket; exports.createSocket = function(type, listener) { return new Socket(type, listener); }; function startListening(socket) { socket._handle.onmessage = onMessage; // Todo: handle errors socket._handle.recvStart(); socket._receiving = true; socket._bindState = BIND_STATE_BOUND; socket.fd = -42; // compatibility hack socket.emit('listening'); } function replaceHandle(self, newHandle) { // Set up the handle that we got from master. newHandle.lookup = self._handle.lookup; newHandle.bind = self._handle.bind; newHandle.send = self._handle.send; newHandle.owner = self; // Replace the existing handle by the handle we got from master. self._handle.close(); self._handle = newHandle; } Socket.prototype.bind = function(/*port, address, callback*/) { var self = this; self._healthCheck(); if (this._bindState != BIND_STATE_UNBOUND) throw new Error('Socket is already bound'); this._bindState = BIND_STATE_BINDING; if (typeof arguments[arguments.length - 1] === 'function') self.once('listening', arguments[arguments.length - 1]); var UDP = process.binding('udp_wrap').UDP; if (arguments[0] instanceof UDP) { replaceHandle(self, arguments[0]); startListening(self); return; } var port = arguments[0]; var address = arguments[1]; if (typeof address === 'function') address = ''; // a.k.a. "any address" // resolve address first self._handle.lookup(address, function(err, ip) { if (err) { self._bindState = BIND_STATE_UNBOUND; self.emit('error', err); return; } if (!cluster) cluster = require('cluster'); if (cluster.isWorker) { cluster._getServer(self, ip, port, self.type, -1, function(handle) { if (!self._handle) // handle has been closed in the mean time. return handle.close(); replaceHandle(self, handle); startListening(self); }); } else { if (!self._handle) return; // handle has been closed in the mean time if (self._handle.bind(ip, port || 0, /*flags=*/ 0)) { self.emit('error', errnoException(process._errno, 'bind')); self._bindState = BIND_STATE_UNBOUND; // Todo: close? return; } startListening(self); } }); }; // thin wrapper around `send`, here for compatibility with dgram_legacy.js Socket.prototype.sendto = function(buffer, offset, length, port, address, callback) { if (typeof offset !== 'number' || typeof length !== 'number') throw new Error('send takes offset and length as args 2 and 3'); if (typeof address !== 'string') throw new Error(this.type + ' sockets must send to port, address'); this.send(buffer, offset, length, port, address, callback); }; Socket.prototype.send = function(buffer, offset, length, port, address, callback) { var self = this; if (!Buffer.isBuffer(buffer)) throw new TypeError('First argument must be a buffer object.'); if (offset >= buffer.length) throw new Error('Offset into buffer too large'); if (offset + length > buffer.length) throw new Error('Offset + length beyond buffer length'); callback = callback || noop; self._healthCheck(); if (self._bindState == BIND_STATE_UNBOUND) self.bind(0, null); // If the socket hasn't been bound yet, push the outbound packet onto the // send queue and send after binding is complete. if (self._bindState != BIND_STATE_BOUND) { // If the send queue hasn't been initialized yet, do it, and install an // event handler that flushes the send queue after binding is done. if (!self._sendQueue) { self._sendQueue = []; self.once('listening', function() { // Flush the send queue. for (var i = 0; i < self._sendQueue.length; i++) self.send.apply(self, self._sendQueue[i]); self._sendQueue = undefined; }); } self._sendQueue.push([buffer, offset, length, port, address, callback]); return; } self._handle.lookup(address, function(err, ip) { if (err) { if (callback) callback(err); self.emit('error', err); } else if (self._handle) { var req = self._handle.send(buffer, offset, length, port, ip); if (req) { req.oncomplete = afterSend; req.cb = callback; } else { // don't emit as error, dgram_legacy.js compatibility var err = errnoException(process._errno, 'send'); process.nextTick(function() { callback(err); }); } } }); }; function afterSend(status, handle, req, buffer) { var self = handle.owner; if (req.cb) req.cb(null, buffer.length); // compatibility with dgram_legacy.js } Socket.prototype.close = function() { this._healthCheck(); this._stopReceiving(); this._handle.close(); this._handle = null; this.emit('close'); }; Socket.prototype.address = function() { this._healthCheck(); var address = this._handle.getsockname(); if (!address) throw errnoException(process._errno, 'getsockname'); return address; }; Socket.prototype.setBroadcast = function(arg) { if (this._handle.setBroadcast((arg) ? 1 : 0)) { throw errnoException(process._errno, 'setBroadcast'); } }; Socket.prototype.setTTL = function(arg) { if (typeof arg !== 'number') { throw new TypeError('Argument must be a number'); } if (this._handle.setTTL(arg)) { throw errnoException(process._errno, 'setTTL'); } return arg; }; Socket.prototype.setMulticastTTL = function(arg) { if (typeof arg !== 'number') { throw new TypeError('Argument must be a number'); } if (this._handle.setMulticastTTL(arg)) { throw errnoException(process._errno, 'setMulticastTTL'); } return arg; }; Socket.prototype.setMulticastLoopback = function(arg) { arg = arg ? 1 : 0; if (this._handle.setMulticastLoopback(arg)) { throw errnoException(process._errno, 'setMulticastLoopback'); } return arg; // 0.4 compatibility }; Socket.prototype.addMembership = function(multicastAddress, interfaceAddress) { this._healthCheck(); if (!multicastAddress) { throw new Error('multicast address must be specified'); } if (this._handle.addMembership(multicastAddress, interfaceAddress)) { throw new errnoException(process._errno, 'addMembership'); } }; Socket.prototype.dropMembership = function(multicastAddress, interfaceAddress) { this._healthCheck(); if (!multicastAddress) { throw new Error('multicast address must be specified'); } if (this._handle.dropMembership(multicastAddress, interfaceAddress)) { throw new errnoException(process._errno, 'dropMembership'); } }; Socket.prototype._healthCheck = function() { if (!this._handle) throw new Error('Not running'); // error message from dgram_legacy.js }; Socket.prototype._stopReceiving = function() { if (!this._receiving) return; this._handle.recvStop(); this._receiving = false; this.fd = null; // compatibility hack }; function onMessage(handle, slab, start, len, rinfo) { var self = handle.owner; if (!slab) { return self.emit('error', errnoException(process._errno, 'recvmsg')); } rinfo.size = len; // compatibility self.emit('message', slab.slice(start, start + len), rinfo); } Socket.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Socket.prototype.unref = function() { if (this._handle) this._handle.unref(); }; // TODO share with net_uv and others function errnoException(errorno, syscall) { var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Timer = process.binding('timer_wrap').Timer; var L = require('_linklist'); var assert = require('assert').ok; // Timeout values > TIMEOUT_MAX are set to 1. var TIMEOUT_MAX = 2147483647; // 2^31-1 var debug; if (process.env.NODE_DEBUG && /timer/.test(process.env.NODE_DEBUG)) { debug = function() { require('util').error.apply(this, arguments); }; } else { debug = function() { }; } // IDLE TIMEOUTS // // Because often many sockets will have the same idle timeout we will not // use one timeout watcher per item. It is too much overhead. Instead // we'll use a single watcher for all sockets with the same timeout value // and a linked list. This technique is described in the libev manual: // http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts // Object containing all lists, timers // key = time in milliseconds // value = list var lists = {}; // the main function - creates lists on demand and the watchers associated // with them. function insert(item, msecs) { item._idleStart = Date.now(); item._idleTimeout = msecs; if (msecs < 0) return; var list; if (lists[msecs]) { list = lists[msecs]; } else { list = new Timer(); list.start(msecs, 0); L.init(list); lists[msecs] = list; list.msecs = msecs; list.ontimeout = listOnTimeout; } L.append(list, item); assert(!L.isEmpty(list)); // list is not empty } function listOnTimeout() { var msecs = this.msecs; var list = this; debug('timeout callback ' + msecs); var now = Date.now(); debug('now: ' + now); var first; while (first = L.peek(list)) { var diff = now - first._idleStart; if (diff < msecs) { list.start(msecs - diff, 0); debug(msecs + ' list wait because diff is ' + diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the // domain or uncaughtException handler ignore the exception, // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 var domain = first.domain; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; first._onTimeout(); if (domain) domain.exit(); threw = false; } finally { if (threw) { process.nextTick(function() { list.ontimeout(); }); } } } } debug(msecs + ' list empty'); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; } var unenroll = exports.unenroll = function(item) { L.remove(item); var list = lists[item._idleTimeout]; // if empty then stop the watcher debug('unenroll'); if (list && L.isEmpty(list)) { debug('unenroll: list empty'); list.close(); delete lists[item._idleTimeout]; } // if active is called later, then we want to make sure not to insert again item._idleTimeout = -1; }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { // if this item was already in a list somewhere // then we should unenroll it from that if (item._idleNext) unenroll(item); // Ensure that msecs fits into signed int32 if (msecs > 0x7fffffff) { msecs = 0x7fffffff; } item._idleTimeout = msecs; L.init(item); }; // call this whenever the item is active (not idle) // it will reset its timeout. exports.active = function(item) { var msecs = item._idleTimeout; if (msecs >= 0) { var list = lists[msecs]; if (!list || L.isEmpty(list)) { insert(item, msecs); } else { item._idleStart = Date.now(); L.append(list, item); } } }; /* * DOM-style timers */ exports.setTimeout = function(callback, after) { var timer; after *= 1; // coalesce to number or NaN if (!(after >= 1 && after <= TIMEOUT_MAX)) { after = 1; // schedule on next tick, follows browser behaviour } timer = new Timeout(after); if (arguments.length <= 2) { timer._onTimeout = callback; } else { /* * Sometimes setTimeout is called with arguments, EG * * setTimeout(callback, 2000, "hello", "world") * * If that's the case we need to call the callback with * those args. The overhead of an extra closure is not * desired in the normal case. */ var args = Array.prototype.slice.call(arguments, 2); timer._onTimeout = function() { callback.apply(timer, args); } } if (process.domain) timer.domain = process.domain; exports.active(timer); return timer; }; exports.clearTimeout = function(timer) { if (timer && (timer.ontimeout || timer._onTimeout)) { timer.ontimeout = timer._onTimeout = null; if (timer instanceof Timeout) { timer.close(); // for after === 0 } else { exports.unenroll(timer); } } }; exports.setInterval = function(callback, repeat) { repeat *= 1; // coalesce to number or NaN if (!(repeat >= 1 && repeat <= TIMEOUT_MAX)) { repeat = 1; // schedule on next tick, follows browser behaviour } var timer = new Timeout(repeat); var args = Array.prototype.slice.call(arguments, 2); timer._onTimeout = wrapper; timer._repeat = true; if (process.domain) timer.domain = process.domain; exports.active(timer); return timer; function wrapper() { callback.apply(this, args); // If callback called clearInterval(). if (timer._repeat === false) return; // If timer is unref'd (or was - it's permanently removed from the list.) if (this._handle) { this._handle.start(repeat, 0); } else { timer._idleTimeout = repeat; exports.active(timer); } } }; exports.clearInterval = function(timer) { if (timer && timer._repeat) { timer._repeat = false; clearTimeout(timer); } }; var Timeout = function(after) { this._idleTimeout = after; this._idlePrev = this; this._idleNext = this; this._idleStart = null; this._onTimeout = null; this._repeat = false; }; Timeout.prototype.unref = function() { if (!this._handle) { var now = Date.now(); if (!this._idleStart) this._idleStart = now; var delay = this._idleStart + this._idleTimeout - now; if (delay < 0) delay = 0; exports.unenroll(this); this._handle = new Timer(); this._handle.ontimeout = this._onTimeout; this._handle.start(delay, 0); this._handle.domain = this.domain; this._handle.unref(); } else { this._handle.unref(); } }; Timeout.prototype.ref = function() { if (this._handle) this._handle.ref(); }; Timeout.prototype.close = function() { this._onTimeout = null; if (this._handle) { this._handle.ontimeout = null; this._handle.close(); } else { exports.unenroll(this); } }; var immediateQueue = {}; L.init(immediateQueue); function processImmediate() { var immediate = L.shift(immediateQueue); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } if (immediate._onImmediate) { if (immediate.domain) immediate.domain.enter(); immediate._onImmediate(); if (immediate.domain) immediate.domain.exit(); } } exports.setImmediate = function(callback) { var immediate = {}, args; L.init(immediate); immediate._onImmediate = callback; if (arguments.length > 1) { args = Array.prototype.slice.call(arguments, 1); immediate._onImmediate = function() { callback.apply(immediate, args); }; } if (!process._needImmediateCallback) { process._needImmediateCallback = true; process._immediateCallback = processImmediate; } if (process.domain) immediate.domain = process.domain; L.append(immediateQueue, immediate); return immediate; }; exports.clearImmediate = function(immediate) { if (!immediate) return; immediate._onImmediate = undefined; L.remove(immediate); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } }; // Internal APIs that need timeouts should use timers._unrefActive isntead of // timers.active as internal timeouts shouldn't hold the loop open var unrefList, unrefTimer; function unrefTimeout() { var now = Date.now(); debug('unrefTimer fired'); var first; while (first = L.peek(unrefList)) { var diff = now - first._idleStart; if (diff < first._idleTimeout) { diff = first._idleTimeout - diff; unrefTimer.start(diff, 0); unrefTimer.when = now + diff; debug('unrefTimer rescheudling for later'); return; } L.remove(first); var domain = first.domain; if (!first._onTimeout) continue; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; debug('unreftimer firing timeout'); first._onTimeout(); threw = false; if (domain) domain.exit(); } finally { if (threw) process.nextTick(unrefTimeout); } } debug('unrefList is empty'); unrefTimer.when = -1; } exports._unrefActive = function(item) { var msecs = item._idleTimeout; if (!msecs || msecs < 0) return; assert(msecs >= 0); L.remove(item); if (!unrefList) { debug('unrefList initialized'); unrefList = {}; L.init(unrefList); debug('unrefTimer initialized'); unrefTimer = new Timer(); unrefTimer.unref(); unrefTimer.when = -1; unrefTimer.ontimeout = unrefTimeout; } var now = Date.now(); item._idleStart = now; if (L.isEmpty(unrefList)) { debug('unrefList empty'); L.append(unrefList, item); unrefTimer.start(msecs, 0); unrefTimer.when = now + msecs; debug('unrefTimer scheduled'); return; } var when = now + msecs; debug('unrefList find where we can insert'); var cur, them; for (cur = unrefList._idlePrev; cur != unrefList; cur = cur._idlePrev) { them = cur._idleStart + cur._idleTimeout; if (when < them) { debug('unrefList inserting into middle of list'); L.append(cur, item); if (unrefTimer.when > when) { debug('unrefTimer is scheduled to fire too late, reschedule'); unrefTimer.start(msecs, 0); unrefTimer.when = when; } return; } } debug('unrefList append to end'); L.append(unrefList, item); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // A bit simpler than readable streams. // Implement an async ._write(chunk, cb), and it'll handle all // the drain event emission and buffering. module.exports = Writable; Writable.WritableState = WritableState; var util = require('util'); var assert = require('assert'); var Stream = require('stream'); util.inherits(Writable, Stream); function WriteReq(chunk, encoding, cb) { this.chunk = chunk; this.encoding = encoding; this.callback = cb; } function WritableState(options, stream) { options = options || {}; // the point at which write() starts returning false // Note: 0 is a valid value, means that we always return false if // the entire buffer is not flushed immediately on write() var hwm = options.highWaterMark; this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; // object stream flag to indicate whether or not this stream // contains buffers or objects. this.objectMode = !!options.objectMode; // cast to ints. this.highWaterMark = ~~this.highWaterMark; this.needDrain = false; // at the start of calling end() this.ending = false; // when end() has been called, and returned this.ended = false; // when 'finish' is emitted this.finished = false; // should we decode strings into buffers before passing to _write? // this is here so that some node-core streams can optimize string // handling at a lower level. var noDecode = options.decodeStrings === false; this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. // Everything else in the universe uses 'utf8', though. this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement // of how much we're waiting to get pushed to some underlying // socket or file. this.length = 0; // a flag to see when we're in the middle of a write. this.writing = false; // a flag to be able to tell if the onwrite cb is called immediately, // or on a later tick. We set this to true at first, becuase any // actions that shouldn't happen until "later" should generally also // not happen before the first write call. this.sync = true; // a flag to know if we're processing previously buffered items, which // may call the _write() callback in the same tick, so that we don't // end up in an overlapped onwrite situation. this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) this.onwrite = function(er) { onwrite(stream, er); }; // the callback that the user supplies to write(chunk,encoding,cb) this.writecb = null; // the amount that is being written when _write is called. this.writelen = 0; this.buffer = []; } function Writable(options) { // Writable ctor is applied to Duplexes, though they're not // instanceof Writable, they're instanceof Readable. if (!(this instanceof Writable) && !(this instanceof Stream.Duplex)) return new Writable(options); this._writableState = new WritableState(options, this); // legacy. this.writable = true; Stream.call(this); } // Otherwise people can pipe Writable streams, which is just wrong. Writable.prototype.pipe = function() { this.emit('error', new Error('Cannot pipe. Not readable.')); }; function writeAfterEnd(stream, state, cb) { var er = new Error('write after end'); // TODO: defer error events consistently everywhere, not just the cb stream.emit('error', er); process.nextTick(function() { cb(er); }); } // If we get something that is not a buffer, string, null, or undefined, // and we're not in objectMode, then that's an error. // Otherwise stream chunks are all considered to be of length=1, and the // watermarks determine how many objects to keep in the buffer, rather than // how many bytes or characters. function validChunk(stream, state, chunk, cb) { var valid = true; if (!Buffer.isBuffer(chunk) && 'string' !== typeof chunk && chunk !== null && chunk !== undefined && !state.objectMode) { var er = new TypeError('Invalid non-string/buffer chunk'); stream.emit('error', er); process.nextTick(function() { cb(er); }); valid = false; } return valid; } Writable.prototype.write = function(chunk, encoding, cb) { var state = this._writableState; var ret = false; if (typeof encoding === 'function') { cb = encoding; encoding = null; } if (Buffer.isBuffer(chunk)) encoding = 'buffer'; else if (!encoding) encoding = state.defaultEncoding; if (typeof cb !== 'function') cb = function() {}; if (state.ended) writeAfterEnd(this, state, cb); else if (validChunk(this, state, chunk, cb)) ret = writeOrBuffer(this, state, chunk, encoding, cb); return ret; }; function decodeChunk(state, chunk, encoding) { if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { chunk = new Buffer(chunk, encoding); } return chunk; } // if we're already writing something, then just put this // in the queue, and wait our turn. Otherwise, call _write // If we return false, then we need a drain event, so set that flag. function writeOrBuffer(stream, state, chunk, encoding, cb) { chunk = decodeChunk(state, chunk, encoding); var len = state.objectMode ? 1 : chunk.length; state.length += len; var ret = state.length < state.highWaterMark; state.needDrain = !ret; if (state.writing) state.buffer.push(new WriteReq(chunk, encoding, cb)); else doWrite(stream, state, len, chunk, encoding, cb); return ret; } function doWrite(stream, state, len, chunk, encoding, cb) { state.writelen = len; state.writecb = cb; state.writing = true; state.sync = true; stream._write(chunk, encoding, state.onwrite); state.sync = false; } function onwriteError(stream, state, sync, er, cb) { if (sync) process.nextTick(function() { cb(er); }); else cb(er); stream.emit('error', er); } function onwriteStateUpdate(state) { state.writing = false; state.writecb = null; state.length -= state.writelen; state.writelen = 0; } function onwrite(stream, er) { var state = stream._writableState; var sync = state.sync; var cb = state.writecb; onwriteStateUpdate(state); if (er) onwriteError(stream, state, sync, er, cb); else { // Check if we're actually ready to finish, but don't emit yet var finished = needFinish(stream, state); if (!finished && !state.bufferProcessing && state.buffer.length) clearBuffer(stream, state); if (sync) { process.nextTick(function() { afterWrite(stream, state, finished, cb); }); } else { afterWrite(stream, state, finished, cb); } } } function afterWrite(stream, state, finished, cb) { if (!finished) onwriteDrain(stream, state); cb(); if (finished) finishMaybe(stream, state); } // Must force callback to be called on nextTick, so that we don't // emit 'drain' before the write() consumer gets the 'false' return // value, and has a chance to attach a 'drain' listener. function onwriteDrain(stream, state) { if (state.length === 0 && state.needDrain) { state.needDrain = false; stream.emit('drain'); } } // if there's something in the buffer waiting, then process it function clearBuffer(stream, state) { state.bufferProcessing = true; for (var c = 0; c < state.buffer.length; c++) { var entry = state.buffer[c]; var chunk = entry.chunk; var encoding = entry.encoding; var cb = entry.callback; var len = state.objectMode ? 1 : chunk.length; doWrite(stream, state, len, chunk, encoding, cb); // if we didn't call the onwrite immediately, then // it means that we need to wait until it does. // also, that means that the chunk and cb are currently // being processed, so move the buffer counter past them. if (state.writing) { c++; break; } } state.bufferProcessing = false; if (c < state.buffer.length) state.buffer = state.buffer.slice(c); else state.buffer.length = 0; } Writable.prototype._write = function(chunk, encoding, cb) { cb(new Error('not implemented')); }; Writable.prototype.end = function(chunk, encoding, cb) { var state = this._writableState; if (typeof chunk === 'function') { cb = chunk; chunk = null; encoding = null; } else if (typeof encoding === 'function') { cb = encoding; encoding = null; } if (typeof chunk !== 'undefined' && chunk !== null) this.write(chunk, encoding); // ignore unnecessary end() calls. if (!state.ending && !state.finished) endWritable(this, state, cb); }; function needFinish(stream, state) { return (state.ending && state.length === 0 && !state.finished && !state.writing); } function finishMaybe(stream, state) { var need = needFinish(stream, state); if (need) { state.finished = true; stream.emit('finish'); } return need; } function endWritable(stream, state, cb) { state.ending = true; finishMaybe(stream, state); if (cb) { if (state.finished) process.nextTick(cb); else stream.once('finish', cb); } state.ended = true; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = Stream; var EE = require('events').EventEmitter; var util = require('util'); util.inherits(Stream, EE); Stream.Readable = require('_stream_readable'); Stream.Writable = require('_stream_writable'); Stream.Duplex = require('_stream_duplex'); Stream.Transform = require('_stream_transform'); Stream.PassThrough = require('_stream_passthrough'); // Backwards-compat with node 0.4.x Stream.Stream = Stream; // old-style streams. Note that the pipe method (the only relevant // part of this class) is overridden in the Readable class. function Stream() { EE.call(this); } Stream.prototype.pipe = function(dest, options) { var source = this; function ondata(chunk) { if (dest.writable) { if (false === dest.write(chunk) && source.pause) { source.pause(); } } } source.on('data', ondata); function ondrain() { if (source.readable && source.resume) { source.resume(); } } dest.on('drain', ondrain); // If the 'end' option is not supplied, dest.end() will be called when // source gets the 'end' or 'close' events. Only dest.end() once. if (!dest._isStdio && (!options || options.end !== false)) { source.on('end', onend); source.on('close', onclose); } var didOnEnd = false; function onend() { if (didOnEnd) return; didOnEnd = true; dest.end(); } function onclose() { if (didOnEnd) return; didOnEnd = true; if (typeof dest.destroy === 'function') dest.destroy(); } // don't leave dangling pipes when there are errors. function onerror(er) { cleanup(); if (EE.listenerCount(this, 'error') === 0) { throw er; // Unhandled stream error in pipe. } } source.on('error', onerror); dest.on('error', onerror); // remove all the event listeners that were added. function cleanup() { source.removeListener('data', ondata); dest.removeListener('drain', ondrain); source.removeListener('end', onend); source.removeListener('close', onclose); source.removeListener('error', onerror); dest.removeListener('error', onerror); source.removeListener('end', cleanup); source.removeListener('close', cleanup); dest.removeListener('close', cleanup); } source.on('end', cleanup); source.on('close', cleanup); dest.on('close', cleanup); dest.emit('pipe', source); // Allow for unix-like usage: A.pipe(B).pipe(C) return dest; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // code was taken from node's module.js and then changed to use the native require var nativerequire = process.binding('nativerequire_wrap'); var NativeModule = require('native_module'); var assert = require('assert').ok; var path = require('path'); var fs; // we have to do this in order to solve the crazy dependancy issues that happend when _stream_readable is required before stream - this happend in several of node tests // the original module.js does not suffer from this since it always loads fs which loads stream var stream = require('stream'); // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all // modules in thier own context. // we don't support context load for now Module._cache = {}; Module._extensions = {}; var modulePaths = []; Module.globalPaths = []; if (process.ischakra) { Module._useScriptsSerialization = false; } // Cache which can be loaded to disk of the relative location of one module to another. function PathCache() { if (!(this instanceof PathCache)) { return new PathCache(); } // true if changed since set. this._dirty = false; // the file the cache read/writes from/to, if this cache originated from a file. this._cacheFile = undefined; // the key --> filename mappings for this cache. this._mappings = {}; // insert a key --> filename mapping. this.insert = function(key, filename) { this._mappings[key] = filename; this._dirty = true; } // remove a key --> filename mapping. this.remove = function(key) { delete this._mappings[key]; this._dirty = true; } // lookup a key --> filename mapping. this.find = function(key) { var filename = this._mappings[key]; if (!filename) { return undefined; } return filename; } // loads the cache from a file. If the file doesn't exist or is corrupt, starts from a clean state. this.load = function(filename) { this._cacheFile = filename; this._dirty = false; this._mappings = {}; if (!nativerequire.fileExistsNotDir(filename)) { return; } fs = fs || require('fs'); try { this._mappings = JSON.parse(fs.readFileSync(filename)); } catch (ex) { console.error('Failed to read json paths cache from file:', filename, ex); } } // Can be used for optimization for saving the native require paths cache // And then used in load. Note that this method is async where load is sync this.save = function(filename, cb) { cb = cb || Function(); var self = this; if (!this._dirty) { return cb(null); } this._dirty = false; if (this._cacheFile !== filename) { return cb(new Error('path cache file changed.')); } fs = fs || require('fs'); return fs.writeFile(this._cacheFile, JSON.stringify(this._mappings), function(err) { if (err) { self._dirty = true; } return cb(err); }); } // removes entries of files which does not exist from the path cache // this may be used by modules which saves/loads the path cache in order to trim the cache if it's get large this.validate = function(flush) { var keys = Object.keys(this._mappings); for (var key in keys) { if (!nativerequire.fileExistsNotDir(this._mappings[key])) { this.remove(key); } } if (this._cacheFile && this._dirty && flush) { fs = fs || require('fs'); fs.writeFileSync(this._cacheFile, JSON.stringify(this._mappings)); this._dirty = false; } } this.size = function() { try { return Object.keys(this._mappings).length; } catch (e) { console.error('failed to get path cache size:', e); return 0; } } }; Module._pathCache = new PathCache(); // Write the cache file back to disk according to the count and interval. function periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval) { if (pathCacheSaves-- == 0) { return; } setTimeout(function() { Module._pathCache.save(filename, function(err) { return periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval); }); }, pathCacheSaveInterval); }; // Loads the path cache from predefined location if the caller of node has enabled // a cache filepath + version in Node::Start. // Starting with writes back to disk at 5, 10, and 15s into the process startup to capture startup paths. function loadGlobalPathCache() { var filename = nativerequire.loadCacheFilePath('npc'); if (!filename) { return; } var pathCacheSaves = 3; var pathCacheSaveInterval = 5000; Module._pathCache.load(filename); periodicPathCacheSave(filename, pathCacheSaves, pathCacheSaveInterval); } loadGlobalPathCache(); // bootstrap main module. Module.runMain = function () { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback(); }; Module._debug = function () { }; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { Module._debug = function (x) { console.error(x); }; } // We use this alias for the preprocessor that filters it out var debug = Module._debug; // given a module name, and a list of paths to test, returns the first // matching file in the following precedence. // // require("a.") // -> a. // // require("a") // -> a // -> a. // -> a/index. // check if the directory is a package.json dir var packageCache = {}; function readPackage(requestPath) { if (hasOwnProperty(packageCache, requestPath)) { return packageCache[requestPath]; } try { var jsonPath = path.resolve(requestPath, 'package.json'); if (!nativerequire.fileExistsNotDir(jsonPath)) return undefined; var pkg = nativerequire.readJsonPackage(jsonPath); if (!pkg) { throw new Error("Unable to read package, or properties are missing"); } packageCache[requestPath] = pkg; } catch (e) { e.path = jsonPath; e.message = 'Error parsing ' + jsonPath + ': ' + e.message; throw e; } return pkg; } function tryPackage(requestPath, exts) { var pkg = readPackage(requestPath); if (!pkg || !pkg.main) return false; var filename = path.resolve(requestPath, pkg.main); return tryFile(filename) || tryExtensions(filename, exts) || tryExtensions(path.resolve(filename, 'index'), exts); } // In order to minimize unnecessary lstat() calls, // this cache is a list of known-real paths. // Set to an empty object to reset. Module._realpathCache = {}; // check if the file exists and is not a directory function tryFile(requestPath) { if (nativerequire.fileExistsNotDir(requestPath)) { return requestPath; //not using fs.realpathSync(requestPath, Module._realpathCache); like in original code here. We assume that there are no links // as it turn out, this method can blow up the memory } return false; } // given a path check a the file exists with any of the set extensions function tryExtensions(p, exts) { for (var i = 0, EL = exts.length; i < EL; i++) { var filename = tryFile(p + exts[i]); if (filename) { return filename; } } return false; } Module._tryPath = function (request, basePath, trailingSlash, cacheKey, exts) { var filename; if (!trailingSlash) { // try to join the request to the path filename = tryFile(basePath); if (!filename && !trailingSlash) { // try it with each of the extensions filename = tryExtensions(basePath, exts); } } if (!filename) { filename = tryPackage(basePath, exts); } if (!filename) { // try it with each of the extensions at "index" filename = tryExtensions(path.resolve(basePath, 'index'), exts); } if (filename) { Module._pathCache.insert(cacheKey, filename); } return filename; } Module._findInPaths = function (request, paths, trailingSlash, cacheKey, exts) { var filename; for (var i = 0, PL = paths.length; i < PL; i++) { var basePath = path.resolve(paths[i], request); filename = Module._tryPath(request, basePath, trailingSlash, cacheKey, exts); if (filename) { return filename; } } return filename; }; // this function was re-written in order to allow more efficient search of modules // instead of building the paths table with every possibility of '[sub dir]\node_modules' we // built it incremently and insert the folders which we build to the cache until we find the module // the main difference here is that the original code created many strings that weren't needed since // the modules are often found in the higher levels Module._findPath = function (request, paths, parent) { var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { paths = ['']; } var trailingSlash = (request.slice(-1) === '/'); var cacheKey; // cacheKey is only paths or paths & parent paths if such exist if (!parent || !parent.paths) { cacheKey = JSON.stringify({ request: request, paths: paths }); } else { cacheKey = JSON.stringify({ request: request, parent: parent.paths, paths: paths }); } var filename = Module._pathCache.find(cacheKey); if (filename) { return filename; } filename = Module._findInPaths(request, paths, trailingSlash, cacheKey, exts); if (filename) { return filename; } if (parent) { if (!parent.paths) { parent.paths = []; } else { var filename = Module._findInPaths(request, parent.paths, trailingSlash, cacheKey, exts); if (filename) { return filename; } } var pathToStartFrom = parent.paths.length > 0 ? parent.paths[parent.paths.length - 1] : path.resolve(path.dirname(parent.filename)); var index = pathToStartFrom.length; if (process.platform == 'win32') { pathToStartFrom = pathToStartFrom.replace(/\//g, '\\') } while (index > 0) { var basePath; // TODO: do not check node_modules within node_modules? if (index == pathToStartFrom.length) { basePath = pathToStartFrom + path.sep + 'node_modules'; } else { basePath = pathToStartFrom.substring(0, index) + path.sep + 'node_modules'; } parent.paths.push(basePath); filename = Module._tryPath(request, path.resolve(basePath, request), trailingSlash, cacheKey, exts); if (filename) { return filename; } index = pathToStartFrom.lastIndexOf(path.sep, index - 1); } } filename = Module._findInPaths(request, modulePaths, trailingSlash, cacheKey, exts); if (filename) { return filename; } return filename; }; Module._resolveLookupPaths = function (request, parent) { // if parent is null, this is probably the main module if (!parent) { return [request,[]]; } if (NativeModule.exists(request)) { return [request, []]; } var start = request.substring(0, 2); if (start !== './' && start !== '..') { return [request, []]; } // Is the parent an index module? // We can assume the parent has a valid extension, // as it already has been accepted as a module. var isIndex = /^index\.\w+?$/.test(path.basename(parent.filename)); var parentIdPath = isIndex ? parent.id : path.dirname(parent.id); var id = path.resolve(parentIdPath, request); // make sure require('./path') and require('path') get distinct ids, even // when called from the toplevel js file if (parentIdPath === '.' && id.indexOf('/') === -1) { id = './' + id; } return [id, [path.dirname(parent.filename)]]; }; Module._load = function (request, parent, isMain) { if (parent) { debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id); } var filename; var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } if (NativeModule.exists(filename)) { // REPL is a special case, because it needs the real require. return require(filename); } var module = new Module(filename, parent); if (isMain) { process.mainModule = module; module.id = '.'; } Module._cache[filename] = module; var hadException = true; try { module.load(filename); hadException = false; } finally { if (hadException) { delete Module._cache[filename]; Module._pathCache.validate(true); } } return module.exports; }; Module.require = function require(path, parent) { return Module._load(path, parent); } Module._resolveFilename = function (request, parent) { if (NativeModule.exists(request)) { return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; var filename = Module._findPath(request, paths, parent); if (!filename) { var err = new Error("Cannot find module '" + request + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; } return filename; }; Module.prototype.load = function (filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.paths = Module._nodeModulePaths(path.dirname(filename)); this.filename = filename; var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; }; Module.prototype.require = function (path) { assert(typeof path === 'string', 'path must be a string'); assert(path, 'missing path'); return Module._load(path, this); }; // Resolved path to process.argv[1] will be lazily placed here // (needed for setting breakpoint when called with --debug-brk) var resolvedArgv; // Returns exception if any // this code was mainly taken from compile, we load and compile the js file here using native require Module.prototype._loadJs = function (filename) { var self = this; function require(path) { return self.require(path); } require.resolve = function (request) { return Module._resolveFilename(request, self); }; require.main = process.mainModule; // we throw the same errors that module.js throw, in order to be complaint with module.js Object.defineProperty(require, 'paths', { get: function () { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.'); } }); require.registerExtension = function () { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.'); }; // Enable support to add extra extension types require.extensions = Module._extensions; require.cache = Module._cache; var dirname = path.dirname(filename); var compiledCode; if (process.ischakra && Module._useScriptsSerialization) { compiledCode = nativerequire.require(filename, filename + '.jsbc'); } else { compiledCode = nativerequire.require(filename); } var args = [self.exports, require, self, filename, dirname]; return compiledCode.apply(self.exports, args); }; // Native extension for .js Module._extensions['.js'] = function (module, filename) { module._loadJs(filename); }; function stripBOM(content) { // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) // because the buffer-to-string conversion in `fs.readFileSync()` // translates it to FEFF, the UTF-16 BOM. if (content.charCodeAt(0) === 0xFEFF) { content = content.slice(1); } return content; } // Native extension for .json Module._extensions['.json'] = function (module, filename) { var content = require('fs').readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } }; //Native extension for .node Module._extensions['.node'] = process.dlopen; Module._initPaths = function () { var isWindows = process.platform === 'win32'; if (isWindows) { var homeDir = process.env.USERPROFILE; } else { var homeDir = process.env.HOME; } var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; if (homeDir) { paths.unshift(path.resolve(homeDir, '.node_libraries')); paths.unshift(path.resolve(homeDir, '.node_modules')); } // node.ch specific for now - disable the use of NODE_PATH for security reasons if (!process.disable_node_env_vars) { if (process.env['NODE_PATH']) { var splitter = isWindows ? ';' : ':'; paths = process.env['NODE_PATH'].split(splitter).concat(paths); } } modulePaths = paths; // clone as a read-only copy, for introspection Module.globalPaths = modulePaths.slice(0); }; // 'from' is the __dirname of the module. Module._nodeModulePaths = function (from) { // guarantee that 'from' is absolute. from = path.resolve(from); // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; // yes, '/' works on both, but let's be a little canonical. var joiner = process.platform === 'win32' ? '\\' : '/'; var paths = []; var parts = from.split(splitRe); for (var tip = parts.length - 1; tip >= 0; tip--) { // don't search in .../node_modules/node_modules if (parts[tip] === 'node_modules') continue; var dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner); paths.push(dir); } return paths; }; Module._initPaths(); // backwards compatibility Module.Module = Module; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! // // UTILITY var util = require('util'); var pSlice = Array.prototype.slice; // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) assert.AssertionError = function AssertionError(options) { this.name = 'AssertionError'; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; this.message = options.message || getMessage(this); var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) Error.captureStackTrace(this, stackStartFunction); }; // assert.AssertionError instanceof Error util.inherits(assert.AssertionError, Error); function replacer(key, value) { if (value === undefined) { return '' + value; } if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) { return value.toString(); } if (typeof value === 'function' || value instanceof RegExp) { return value.toString(); } return value; } function truncate(s, n) { if (typeof s == 'string') { return s.length < n ? s : s.slice(0, n); } else { return s; } } function getMessage(self) { return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + self.operator + ' ' + truncate(JSON.stringify(self.expected, replacer), 128); } // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new assert.AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!!!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected)) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; function _deepEqual(actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; for (var i = 0; i < actual.length; i++) { if (actual[i] !== expected[i]) return false; } return true; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (actual instanceof Date && expected instanceof Date) { return actual.getTime() === expected.getTime(); // 7.3 If the expected value is a RegExp object, the actual value is // equivalent if it is also a RegExp object with the same source and // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). } else if (actual instanceof RegExp && expected instanceof RegExp) { return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; // 7.4. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if (typeof actual != 'object' && typeof expected != 'object') { return actual == expected; // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else { return objEquiv(actual, expected); } } function isUndefinedOrNull(value) { return value === null || value === undefined; } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b) { if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false; // an identical 'prototype' property. if (a.prototype !== b.prototype) return false; //~~~I've managed to break Object.keys through screwy arguments passing. // Converting to array solves the problem. if (isArguments(a)) { if (!isArguments(b)) { return false; } a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b); } try { var ka = Object.keys(a), kb = Object.keys(b), key, i; } catch (e) {//happens when one is a string literal and the other isn't return false; } // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length != kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] != kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key])) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected)) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } else if (actual instanceof expected) { return true; } else if (expected.call({}, actual) === true) { return true; } return false; } function _throws(shouldThrow, block, expected, message) { var actual; if (typeof expected === 'string') { message = expected; expected = null; } try { block(); } catch (e) { actual = e; } message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } if (!shouldThrow && expectedException(actual, expected)) { fail(actual, expected, 'Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [true].concat(pSlice.call(arguments))); }; // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = function(block, /*optional*/message) { _throws.apply(this, [false].concat(pSlice.call(arguments))); }; assert.ifError = function(err) { if (err) {throw err;}}; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var isWindows = process.platform === 'win32'; var util = require('util'); // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } function getDirNameForUNC(path) { if (path.length <= 2) { return path[0]; //return only one slash in that case } //skip slashes at the begining: var i; for (i = 0; i < path.length; ++i) { if(!isCharAtIndexSlash(path, i)) { break; } } var prefix = path.substr(0, i); path = path.substr(i); if (path.indexOf('\\') === -1 && path.indexOf('/') === -1) { //path of type "\\\\server"" return prefix[0]; } //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i > -1; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } if (i === -1) { //path contains only slashes: return prefix[0]; //return one slash. } //loop over the string backwards, until the previoud slash: for (; i >=0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } if (i == -1) { //path of type "\\server\\" return path.substr(0, i); //return slashes at the begining without the first 2. ""///server" -->"/" } var dir = path.substr(0, i); if (dir.indexOf('\\') == -1 && dir.indexOf('/') == -1) { //the path of type "//server/share/" --> retrun with the share return prefix + path; } //in case the path is of type \\\\server\\share\\folder1\\ we need to return \\\server\\share\\ with the slashes at the end //unlike in the case of \\\\server\\share\\folder1\\folder2 we need to return \\\\server\\share\\folder1 without slashes at the end var dir = path.substr(0, i + 1); var foldersCount = 0; for (i = 0; i < dir.length ; i++) { if (!isCharAtIndexSlash(dir, i)) { foldersCount++; while (!isCharAtIndexSlash(dir, i)) { i++; } } } if (foldersCount > 2) { //need to remove slashes at the end for (i = dir.length - 1; isCharAtIndexSlash(dir, i); --i); dir = dir.substr(0, i + 1); } return prefix + dir; } function getDirNameForPartialPath(path) { var prefix; //path of type "../foo/bar" if ((path.length > 2) && (path[0] === '.') && (path[1] === '.') && isCharAtIndexSlash(path, 2)) { prefix = path.substr(0, 3); path = path.substr(3); } //path of type "./foo/bar" or "..foo/bar" else if (((path[0] === '.') && isCharAtIndexSlash(path, 1)) || (path[0] === '.') && (path[1] === '.')) { prefix = path.substr(0, 2); path = path.substr(2); } //path of type ".foo/bar" or "/foo/bar" else if ((path[0] === '.') || (isCharAtIndexSlash(path, 0) && !isCharAtIndexSlash(path, 1))) { prefix = path.substr(0, 1); path = path.substr(1); } else { return '.'; } //if we got here, path is of type "foo/bar/baz..." var i; //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i >= 0; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } //loop over the string backwards, to remove the current folder from the path: for (; i >= 0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } //remove one slash at the end if there's any. //make sure not to remove the first slash in case prefix is empty if (isCharAtIndexSlash(path, i + 1)) { --i; } //actually remove the tail and return the dir: path = path.substr(0, i); //in case path is empty if prefix was "../" needs to return "./", if prefix was "./" needs to return "." if ((path.length == 0) && (prefix.length > 1)) { prefix = prefix.substr(0, prefix.length - 1); } if (prefix) { return prefix + path; } return path; } function getDirNameForDrive(path) { if ((path.length === 2) && (path.charAt(1) === ':')) { return path; } var prefix; if (path.length > 2 && (path.charAt(1) === ':')) { //there's a suffix to the drive name: var endOfDriveInd = isCharAtIndexSlash(path, 2) ? 3 : 2; prefix = path.substr(0, endOfDriveInd); //only the drive name path = path.substr(endOfDriveInd); } else { return '.'; } if (path.indexOf('\\') === -1 && path.indexOf('/') === -1) { //path of type "c:\\file" // return only the drive return prefix; } var i; //loop backwards until passing the slashes at the end (if there's any) for (i = path.length -1; i >=0; --i) { if(!isCharAtIndexSlash(path, i)) { break; } } if (i == -1) { //path contains only slashes: return prefix; //return only the drive } //loop over the string backwards, to remove the current folder from the path: for (; i >=0; --i) { if (isCharAtIndexSlash(path, i)) { break; } } //remove one slash at the end if there's any: if(isCharAtIndexSlash(path, i)) { --i; } //actually remove the tail and return the dir: path = path.substr(0, i + 1); return prefix + path; } function isCharAtIndexSlash(path, index) { return (path.charAt(index) === '/' || path.charAt(index) === '\\'); } // receives path and returns the file name without slashes: function getFileNameFromPath(path) { path = getTailStrFromPathHelper('/', path); path = getTailStrFromPathHelper('\\', path); return path; } //returns the last string in path after the last given delimiter: function getTailStrFromPathHelper(delimiter, path) { if (path.lastIndexOf(delimiter) != -1) { path = path.split(delimiter); var i; for (i = path.length -1; i >=0; --i) { if(path[i] != '' && path[i] != '\\' && path[i] != '/') { break; } } path = path.slice(0, i + 1); return path[i]; } return path; } if (isWindows) { // Regex to split a windows path into three parts: [*, device, slash, // tail] windows-only var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; // Regex to split the tail part of the above into [*, dir, basename, ext] var splitTailRe = /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; // Function to split a filename into [root, dir, basename, ext] // windows version var splitPath = function(filename) { // Separate device+slash from tail var result = splitDeviceRe.exec(filename), device = (result[1] || '') + (result[2] || ''), tail = result[3] || ''; // Split the tail into dir, basename and extension var result2 = splitTailRe.exec(tail), dir = result2[1], basename = result2[2], ext = result2[3]; return [device, dir, basename, ext]; }; var normalizeUNCRoot = function(device) { return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\'); }; // path.resolve([from ...], to) // windows version exports.resolve = function() { var resolvedDevice = '', resolvedTail = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1; i--) { var path; if (i >= 0) { path = arguments[i]; } else if (!resolvedDevice) { path = process.cwd(); } else { // Windows has the concept of drive-specific current working // directories. If we've resolved a drive letter but not yet an // absolute path, get cwd for that drive. We're sure the device is not // an unc path at this points, because unc paths are always absolute. path = process.env['=' + resolvedDevice]; // Verify that a drive-local cwd was found and that it actually points // to our drive. If not, default to the drive's root. if (!path || path.substr(0, 3).toLowerCase() !== resolvedDevice.toLowerCase() + '\\') { path = resolvedDevice + '\\'; } } // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } var result = splitDeviceRe.exec(path), device = result[1] || '', isUnc = device && device.charAt(1) !== ':', isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute tail = result[3]; if (device && resolvedDevice && device.toLowerCase() !== resolvedDevice.toLowerCase()) { // This path points to another device so it is not applicable continue; } if (!resolvedDevice) { resolvedDevice = device; } if (!resolvedAbsolute) { resolvedTail = tail + '\\' + resolvedTail; resolvedAbsolute = isAbsolute; } if (resolvedDevice && resolvedAbsolute) { break; } } // Convert slashes to backslashes when `resolvedDevice` points to an UNC // root. Also squash multiple slashes into a single one where appropriate. if (isUnc) { resolvedDevice = normalizeUNCRoot(resolvedDevice); } // At this point the path should be resolved to a full absolute path, // but handle relative paths to be safe (might happen when process.cwd() // fails) // Normalize the tail path function f(p) { return !!p; } resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/).filter(f), !resolvedAbsolute).join('\\'); return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || '.'; }; // windows version exports.normalize = function(path) { var result = splitDeviceRe.exec(path), device = result[1] || '', isUnc = device && device.charAt(1) !== ':', isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute tail = result[3], trailingSlash = /[\\\/]$/.test(tail); // Normalize the tail path tail = normalizeArray(tail.split(/[\\\/]+/).filter(function(p) { return !!p; }), !isAbsolute).join('\\'); if (!tail && !isAbsolute) { tail = '.'; } if (tail && trailingSlash) { tail += '\\'; } // Convert slashes to backslashes when `device` points to an UNC root. // Also squash multiple slashes into a single one where appropriate. if (isUnc) { device = normalizeUNCRoot(device); } return device + (isAbsolute ? '\\' : '') + tail; }; // windows version exports.join = function() { function f(p) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; } var paths = Array.prototype.filter.call(arguments, f); var joined = paths.join('\\'); // Make sure that the joined path doesn't start with two slashes, because // normalize() will mistake it for an UNC path then. // // This step is skipped when it is very clear that the user actually // intended to point at an UNC path. This is assumed when the first // non-empty string arguments starts with exactly two slashes followed by // at least one more non-slash character. // // Note that for normalize() to treat a path as an UNC path it needs to // have at least 2 components, so we don't filter for that here. // This means that the user can use join to construct UNC paths from // a server name and a share name; for example: // path.join('//server', 'share') -> '\\\\server\\share\') if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) { joined = joined.replace(/^[\\\/]{2,}/, '\\'); } return exports.normalize(joined); }; // path.relative(from, to) // it will solve the relative path from 'from' to 'to', for instance: // from = 'C:\\orandea\\test\\aaa' // to = 'C:\\orandea\\impl\\bbb' // The output of the function should be: '..\\..\\impl\\bbb' // windows version exports.relative = function(from, to) { from = exports.resolve(from); to = exports.resolve(to); // windows is not case sensitive var lowerFrom = from.toLowerCase(); var lowerTo = to.toLowerCase(); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var toParts = trim(to.split('\\')); var lowerFromParts = trim(lowerFrom.split('\\')); var lowerToParts = trim(lowerTo.split('\\')); var length = Math.min(lowerFromParts.length, lowerToParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (lowerFromParts[i] !== lowerToParts[i]) { samePartsLength = i; break; } } if (samePartsLength == 0) { return to; } var outputParts = []; for (var i = samePartsLength; i < lowerFromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('\\'); }; exports.sep = '\\'; exports.delimiter = ';'; } else /* posix */ { // Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = path.charAt(0) === '/', trailingSlash = path.substr(-1) === '/'; // Normalize the path path = normalizeArray(path.split('/').filter(function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(paths.filter(function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; // path.relative(from, to) // posix version exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.sep = '/'; exports.delimiter = ':'; } exports.dirname = function(path) { if (!isWindows) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { // No dirname whatsoever return '.'; } if (dir) { // It has a dirname, strip trailing slash dir = dir.substr(0, dir.length - 1); } return root + dir; } //code below changed from original Node // 1. handle the case of path.length = 1. if (path.length === 1) { if (isCharAtIndexSlash(path, 0)) { return path; } else { return '.'; } } // 2. handle the case of local drive: d:\\aa\\bb var firstChar = path.charAt(0); if ((firstChar <= 'Z' && firstChar >= 'A') || (firstChar <= 'z' && firstChar >= 'a')){ return getDirNameForDrive(path); } if (path.length > 1) { // 3. handle the case of UNC: \\\\server\\share\\folder if (isCharAtIndexSlash(path, 0) && isCharAtIndexSlash(path, 1)) { return getDirNameForUNC(path); } // 3. handle the case of partial path: /aa/bb/cc return getDirNameForPartialPath(path); } // 5. no dir return '.'; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { //code changed from original Node if (!isWindows) { return splitPath(path)[3]; } path = getFileNameFromPath(path); var indDot = path.lastIndexOf('.'); path = (0 >= indDot) || (path === '..') ? '' : path.substr(indDot); return path; }; exports.exists = util.deprecate(function(path, callback) { require('fs').exists(path, callback); }, 'path.exists is now called `fs.exists`.'); exports.existsSync = util.deprecate(function(path) { return require('fs').existsSync(path); }, 'path.existsSync is now called `fs.existsSync`.'); if (isWindows) { exports._makeLong = function(path) { // Note: this will *probably* throw somewhere. if (typeof path !== 'string') return path; if (!path) { return ''; } var resolvedPath = exports.resolve(path); if (/^[a-zA-Z]\:\\/.test(resolvedPath)) { // path is local filesystem path, which needs to be converted // to long UNC path. return '\\\\?\\' + resolvedPath; } else if (/^\\\\[^?.]/.test(resolvedPath)) { // path is network UNC path, which needs to be converted // to long UNC path. return '\\\\?\\UNC\\' + resolvedPath.substring(2); } return path; }; } else { exports._makeLong = function(path) { return path; }; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var domain; exports.usingDomains = false; function EventEmitter() { this.domain = null; if (exports.usingDomains) { // if there is an active domain, then attach to it. domain = domain || require('domain'); if (domain.active && !(this instanceof domain.Domain)) { this.domain = domain.active; } } this._events = this._events || {}; this._maxListeners = this._maxListeners || defaultMaxListeners; } exports.EventEmitter = EventEmitter; // By default EventEmitters will print a warning if more than // 10 listeners are added to it. This is a useful default which // helps finding memory leaks. // // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. var defaultMaxListeners = 10; EventEmitter.prototype.setMaxListeners = function(n) { if (typeof n !== 'number' || n < 0) throw TypeError('n must be a positive number'); this._maxListeners = n; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (typeof this._events.error === 'object' && !this._events.error.length)) { er = arguments[1]; if (this.domain) { if (!er) er = new TypeError('Uncaught, unspecified "error" event.'); er.domainEmitter = this; er.domain = this.domain; er.domainThrown = false; this.domain.emit('error', er); } else if (er instanceof Error) { throw er; // Unhandled 'error' event } else { throw TypeError('Uncaught, unspecified "error" event.'); } return false; } } handler = this._events[type]; if (typeof handler === 'undefined') return false; if (this.domain && this !== process) this.domain.enter(); if (typeof handler === 'function') { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } } else if (typeof handler === 'object') { len = arguments.length; args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } if (this.domain && this !== process) this.domain.exit(); return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (typeof listener !== 'function') throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, typeof listener.listener === 'function' ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (typeof this._events[type] === 'object') // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (typeof this._events[type] === 'object' && !this._events[type].warned) { m = this._maxListeners; if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); console.trace(); } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (typeof listener !== 'function') throw TypeError('listener must be a function'); function g() { this.removeListener(type, g); listener.apply(this, arguments); } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (typeof listener !== 'function') throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (typeof list.listener === 'function' && list.listener === listener)) { this._events[type] = undefined; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (typeof list === 'object') { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; this._events[type] = undefined; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) this._events[type] = undefined; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } this._events[type] = undefined; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (typeof this._events[type] === 'function') ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.listenerCount = function(emitter, type) { var ret; if (!emitter._events || !emitter._events[type]) ret = 0; else if (typeof emitter._events[type] === 'function') ret = 1; else ret = emitter._events[type].length; return ret; }; // Copyright (c) Microsoft Corporation. All rights reserved. // Patch classes for chakra var extend = function(dest, from) { var props = Object.getOwnPropertyNames(from); props.forEach(function(name) { var destination = Object.getOwnPropertyDescriptor(from, name); try { Object.defineProperty(dest, name, destination); } catch (e) { // ignore errors } }); }; function patchErrorStack() { var util = require('util'); // the 2nd argument is ignored for now Error.__proto__.captureStackTrace = function(err, func) { var currentStack; try { throw new Error; } catch (e) { currentStack = e.stack; } // remove the first line so this function won't be seen var splittedStack = currentStack.split('\n'); var firstLine = splittedStack[0]; splittedStack.splice(0, 3); if (err.name) { firstLine = err.name + ': ' + err.message; } err.stack = firstLine + '\n' + splittedStack.join('\n'); } } function patchTypedArrays() { ArrayBuffer.prototype.slice = function(begin, end) { if (!begin) { throw new Error('Wrong number of arguments.'); } // boundary/arguments check - we do exactly the same ones as in node's // ArrayBuffer if (!end) { end = this.byteLength; } if (begin < 0) { begin = this.byteLength + begin; } if (begin < 0) { begin = 0; } if (begin > this.byteLength) { begin = this.byteLength; } if (end < 0) { end = this.byteLength + end; } if (end < 0) { end = 0; } if (end > this.byteLength) { end = this.byteLength; } if (begin > end) { begin = end; } var slice_length = end - begin; var slicedBuffer = new ArrayBuffer(slice_length); var sourceDataView = new DataView(this); var destDataView = new DataView(slicedBuffer); for (var i = 0; i < slice_length; i++) { destDataView.setInt8(i, sourceDataView.getInt8(begin + i)); } return slicedBuffer; }; // patch slice method for each type: [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array].forEach(function(item) { item.prototype.slice = item.prototype.subarray; item.prototype.get = function(i) { return this[i]; }; item.prototype.set = function(first, second) { if (first instanceof Array) { // in this case - first is an array of values, second is the offset for (var j = 0; j < first.length; j++) { this[j + second] = first[j]; } } else { this[first] = second; } } }); } // this patch fix some failing tests which rely on the stack trace // this little patch adds "JsonParse" to the stack trace function patchJsonParse() { var JsonParseOriginal = JSON.parse; var JsonParse = function() { return JsonParseOriginal.apply(this, arguments); } JSON.parse = JsonParse; } if (!global.__chakra_patched) { // patch console patchErrorStack(); patchTypedArrays(); patchJsonParse(); Object.defineProperty( global, '__chakra_patched', { enumerable: false, value: true }); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Transform = require('_stream_transform'); var binding = process.binding('zlib'); var util = require('util'); var assert = require('assert').ok; // zlib doesn't provide these, so kludge them in following the same // const naming scheme zlib uses. binding.Z_MIN_WINDOWBITS = 8; binding.Z_MAX_WINDOWBITS = 15; binding.Z_DEFAULT_WINDOWBITS = 15; // fewer than 64 bytes per chunk is stupid. // technically it could work with as few as 8, but even 64 bytes // is absurdly low. Usually a MB or more is best. binding.Z_MIN_CHUNK = 64; binding.Z_MAX_CHUNK = Infinity; binding.Z_DEFAULT_CHUNK = (16 * 1024); binding.Z_MIN_MEMLEVEL = 1; binding.Z_MAX_MEMLEVEL = 9; binding.Z_DEFAULT_MEMLEVEL = 8; binding.Z_MIN_LEVEL = -1; binding.Z_MAX_LEVEL = 9; binding.Z_DEFAULT_LEVEL = binding.Z_DEFAULT_COMPRESSION; // expose all the zlib constants Object.keys(binding).forEach(function(k) { if (k.match(/^Z/)) exports[k] = binding[k]; }); // translation table for return codes. exports.codes = { Z_OK: binding.Z_OK, Z_STREAM_END: binding.Z_STREAM_END, Z_NEED_DICT: binding.Z_NEED_DICT, Z_ERRNO: binding.Z_ERRNO, Z_STREAM_ERROR: binding.Z_STREAM_ERROR, Z_DATA_ERROR: binding.Z_DATA_ERROR, Z_MEM_ERROR: binding.Z_MEM_ERROR, Z_BUF_ERROR: binding.Z_BUF_ERROR, Z_VERSION_ERROR: binding.Z_VERSION_ERROR }; Object.keys(exports.codes).forEach(function(k) { exports.codes[exports.codes[k]] = k; }); exports.Deflate = Deflate; exports.Inflate = Inflate; exports.Gzip = Gzip; exports.Gunzip = Gunzip; exports.DeflateRaw = DeflateRaw; exports.InflateRaw = InflateRaw; exports.Unzip = Unzip; exports.createDeflate = function(o) { return new Deflate(o); }; exports.createInflate = function(o) { return new Inflate(o); }; exports.createDeflateRaw = function(o) { return new DeflateRaw(o); }; exports.createInflateRaw = function(o) { return new InflateRaw(o); }; exports.createGzip = function(o) { return new Gzip(o); }; exports.createGunzip = function(o) { return new Gunzip(o); }; exports.createUnzip = function(o) { return new Unzip(o); }; // Convenience methods. // compress/decompress a string or buffer in one step. exports.deflate = function(buffer, callback) { zlibBuffer(new Deflate(), buffer, callback); }; exports.gzip = function(buffer, callback) { zlibBuffer(new Gzip(), buffer, callback); }; exports.deflateRaw = function(buffer, callback) { zlibBuffer(new DeflateRaw(), buffer, callback); }; exports.unzip = function(buffer, callback) { zlibBuffer(new Unzip(), buffer, callback); }; exports.inflate = function(buffer, callback) { zlibBuffer(new Inflate(), buffer, callback); }; exports.gunzip = function(buffer, callback) { zlibBuffer(new Gunzip(), buffer, callback); }; exports.inflateRaw = function(buffer, callback) { zlibBuffer(new InflateRaw(), buffer, callback); }; function zlibBuffer(engine, buffer, callback) { var buffers = []; var nread = 0; engine.on('error', onError); engine.on('end', onEnd); engine.end(buffer); flow(); function flow() { var chunk; while (null !== (chunk = engine.read())) { buffers.push(chunk); nread += chunk.length; } engine.once('readable', flow); } function onError(err) { engine.removeListener('end', onEnd); engine.removeListener('readable', flow); callback(err); } function onEnd() { var buf = Buffer.concat(buffers, nread); buffers = []; callback(null, buf); engine.close(); } } // generic zlib // minimal 2-byte header function Deflate(opts) { if (!(this instanceof Deflate)) return new Deflate(opts); Zlib.call(this, opts, binding.DEFLATE); } function Inflate(opts) { if (!(this instanceof Inflate)) return new Inflate(opts); Zlib.call(this, opts, binding.INFLATE); } // gzip - bigger header, same deflate compression function Gzip(opts) { if (!(this instanceof Gzip)) return new Gzip(opts); Zlib.call(this, opts, binding.GZIP); } function Gunzip(opts) { if (!(this instanceof Gunzip)) return new Gunzip(opts); Zlib.call(this, opts, binding.GUNZIP); } // raw - no header function DeflateRaw(opts) { if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); Zlib.call(this, opts, binding.DEFLATERAW); } function InflateRaw(opts) { if (!(this instanceof InflateRaw)) return new InflateRaw(opts); Zlib.call(this, opts, binding.INFLATERAW); } // auto-detect header. function Unzip(opts) { if (!(this instanceof Unzip)) return new Unzip(opts); Zlib.call(this, opts, binding.UNZIP); } // the Zlib class they all inherit from // This thing manages the queue of requests, and returns // true or false if there is anything in the queue when // you call the .write() method. function Zlib(opts, mode) { this._opts = opts = opts || {}; this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK; Transform.call(this, opts); if (opts.flush) { if (opts.flush !== binding.Z_NO_FLUSH && opts.flush !== binding.Z_PARTIAL_FLUSH && opts.flush !== binding.Z_SYNC_FLUSH && opts.flush !== binding.Z_FULL_FLUSH && opts.flush !== binding.Z_FINISH && opts.flush !== binding.Z_BLOCK) { throw new Error('Invalid flush flag: ' + opts.flush); } } this._flushFlag = opts.flush || binding.Z_NO_FLUSH; if (opts.chunkSize) { if (opts.chunkSize < exports.Z_MIN_CHUNK || opts.chunkSize > exports.Z_MAX_CHUNK) { throw new Error('Invalid chunk size: ' + opts.chunkSize); } } if (opts.windowBits) { if (opts.windowBits < exports.Z_MIN_WINDOWBITS || opts.windowBits > exports.Z_MAX_WINDOWBITS) { throw new Error('Invalid windowBits: ' + opts.windowBits); } } if (opts.level) { if (opts.level < exports.Z_MIN_LEVEL || opts.level > exports.Z_MAX_LEVEL) { throw new Error('Invalid compression level: ' + opts.level); } } if (opts.memLevel) { if (opts.memLevel < exports.Z_MIN_MEMLEVEL || opts.memLevel > exports.Z_MAX_MEMLEVEL) { throw new Error('Invalid memLevel: ' + opts.memLevel); } } if (opts.strategy) { if (opts.strategy != exports.Z_FILTERED && opts.strategy != exports.Z_HUFFMAN_ONLY && opts.strategy != exports.Z_RLE && opts.strategy != exports.Z_FIXED && opts.strategy != exports.Z_DEFAULT_STRATEGY) { throw new Error('Invalid strategy: ' + opts.strategy); } } if (opts.dictionary) { if (!Buffer.isBuffer(opts.dictionary)) { throw new Error('Invalid dictionary: it should be a Buffer instance'); } } this._binding = new binding.Zlib(mode); var self = this; this._hadError = false; this._binding.onerror = function(message, errno) { // there is no way to cleanly recover. // continuing only obscures problems. self._binding = null; self._hadError = true; var error = new Error(message); error.errno = errno; error.code = exports.codes[errno]; self.emit('error', error); }; this._binding.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, opts.level || exports.Z_DEFAULT_COMPRESSION, opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, opts.strategy || exports.Z_DEFAULT_STRATEGY, opts.dictionary); this._buffer = new Buffer(this._chunkSize); this._offset = 0; this._closed = false; this.once('end', this.close); } util.inherits(Zlib, Transform); Zlib.prototype.reset = function reset() { return this._binding.reset(); }; // This is the _flush function called by the transform class, // internally, when the last chunk has been written. Zlib.prototype._flush = function(callback) { this._transform(new Buffer(0), '', callback); }; Zlib.prototype.flush = function(callback) { var ws = this._writableState; if (ws.ended) { if (callback) process.nextTick(callback); } else if (ws.ending) { if (callback) this.once('end', callback); } else if (ws.needDrain) { var self = this; this.once('drain', function() { self.flush(callback); }); } else { this._flushFlag = binding.Z_FULL_FLUSH; this.write(new Buffer(0), '', callback); } }; Zlib.prototype.close = function(callback) { if (callback) process.nextTick(callback); if (this._closed) return; this._closed = true; this._binding.close(); var self = this; process.nextTick(function() { self.emit('close'); }); }; Zlib.prototype._transform = function(chunk, encoding, cb) { var flushFlag; var ws = this._writableState; var ending = ws.ending || ws.ended; var last = ending && (!chunk || ws.length === chunk.length); if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input')); // If it's the last chunk, or a final flush, we use the Z_FINISH flush flag. // If it's explicitly flushing at some other time, then we use // Z_FULL_FLUSH. Otherwise, use Z_NO_FLUSH for maximum compression // goodness. if (last) flushFlag = binding.Z_FINISH; else { flushFlag = this._flushFlag; // once we've flushed the last of the queue, stop flushing and // go back to the normal behavior. if (chunk.length >= ws.length) { this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH; } } var availInBefore = chunk && chunk.length; var availOutBefore = this._chunkSize - this._offset; var inOff = 0; var req = this._binding.write(flushFlag, chunk, // in inOff, // in_off availInBefore, // in_len this._buffer, // out this._offset, //out_off availOutBefore); // out_len req.buffer = chunk; req.callback = callback; var self = this; function callback(availInAfter, availOutAfter, buffer) { if (self._hadError) return; var have = availOutBefore - availOutAfter; assert(have >= 0, 'have should not go down'); if (have > 0) { var out = self._buffer.slice(self._offset, self._offset + have); self._offset += have; // serve some output to the consumer. self.push(out); } // exhausted the output buffer, or used all the input create a new one. if (availOutAfter === 0 || self._offset >= self._chunkSize) { availOutBefore = self._chunkSize; self._offset = 0; self._buffer = new Buffer(self._chunkSize); } if (availOutAfter === 0) { // Not actually done. Need to reprocess. // Also, update the availInBefore to the availInAfter value, // so that if we have to hit it a third (fourth, etc.) time, // it'll have the correct byte counts. inOff += (availInBefore - availInAfter); availInBefore = availInAfter; var newReq = self._binding.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize); newReq.callback = callback; // this same function newReq.buffer = chunk; return; } // finished with the chunk. cb(); } }; util.inherits(Deflate, Zlib); util.inherits(Inflate, Zlib); util.inherits(Gzip, Zlib); util.inherits(Gunzip, Zlib); util.inherits(DeflateRaw, Zlib); util.inherits(InflateRaw, Zlib); util.inherits(Unzip, Zlib); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var binding = process.binding('os'); var util = require('util'); exports.endianness = binding.getEndianness; exports.hostname = binding.getHostname; exports.loadavg = binding.getLoadAvg; exports.uptime = binding.getUptime; exports.freemem = binding.getFreeMem; exports.totalmem = binding.getTotalMem; exports.cpus = binding.getCPUs; exports.type = binding.getOSType; exports.release = binding.getOSRelease; exports.networkInterfaces = binding.getInterfaceAddresses; exports.arch = function() { return process.arch; }; exports.platform = function() { return process.platform; }; exports.tmpdir = function() { return process.env.TMPDIR || process.env.TMP || process.env.TEMP || (process.platform === 'win32' ? 'c:\\windows\\temp' : '/tmp'); }; exports.tmpDir = exports.tmpdir; exports.getNetworkInterfaces = util.deprecate(function() { return exports.networkInterfaces(); }, 'getNetworkInterfaces is now called `os.networkInterfaces`.'); exports.EOL = process.platform === 'win32' ? '\r\n' : '\n'; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* A repl library that you can include in your own code to get a runtime * interface to your program. * * var repl = require("repl"); * // start repl on stdin * repl.start("prompt> "); * * // listen for unix socket connections and start repl on them * net.createServer(function(socket) { * repl.start("node via Unix socket> ", socket); * }).listen("/tmp/node-repl-sock"); * * // listen for TCP socket connections and start repl on them * net.createServer(function(socket) { * repl.start("node via TCP socket> ", socket); * }).listen(5001); * * // expose foo to repl context * repl.start("node > ").context.foo = "stdin is fun"; */ var util = require('util'); var inherits = require('util').inherits; var Stream = require('stream'); var vm = require('vm'); var path = require('path'); var fs = require('fs'); var rl = require('readline'); var Console = require('console').Console; var EventEmitter = require('events').EventEmitter; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } // hack for require.resolve("./relative") to work properly. module.filename = path.resolve('repl'); // hack for repl require to work properly with node_modules folders module.paths = require('module')._nodeModulePaths(module.filename); // Can overridden with custom print functions, such as `probe` or `eyes.js`. // This is the default "writer" value if none is passed in the REPL options. exports.writer = util.inspect; exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net', 'os', 'path', 'punycode', 'querystring', 'readline', 'stream', 'string_decoder', 'tls', 'tty', 'url', 'util', 'vm', 'zlib']; function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) { if (!(this instanceof REPLServer)) { return new REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined); } EventEmitter.call(this); var options, input, output; if (typeof prompt == 'object') { // an options object was given options = prompt; stream = options.stream || options.socket; input = options.input; output = options.output; eval_ = options.eval; useGlobal = options.useGlobal; ignoreUndefined = options.ignoreUndefined; prompt = options.prompt; } else if (typeof prompt != 'string') { throw new Error('An options Object, or a prompt String are required'); } else { options = {}; } var self = this; self.useGlobal = !!useGlobal; self.ignoreUndefined = !!ignoreUndefined; self.eval = eval_ || function(code, context, file, cb) { var err, result; try { if (self.useGlobal) { result = vm.runInThisContext(code, file); } else { result = vm.runInContext(code, context, file); } } catch (e) { err = e; } if (err && process.domain) { process.domain.emit('error', err); process.domain.exit(); } else { cb(err, result); } }; if (!input && !output) { // legacy API, passing a 'stream'/'socket' option if (!stream) { // use stdin and stdout as the default streams if none were given stream = process; } if (stream.stdin && stream.stdout) { // We're given custom object with 2 streams, or the `process` object input = stream.stdin; output = stream.stdout; } else { // We're given a duplex readable/writable Stream, like a `net.Socket` input = stream; output = stream; } } self.inputStream = input; self.outputStream = output; self.resetContext(); self.bufferedCommand = ''; self.prompt = (prompt != undefined ? prompt : '> '); function complete(text, callback) { self.complete(text, callback); } var rli = rl.createInterface({ input: self.inputStream, output: self.outputStream, completer: complete, terminal: options.terminal }); self.rli = rli; this.commands = {}; defineDefaultCommands(this); // figure out which "writer" function to use self.writer = options.writer || exports.writer; if (typeof options.useColors === 'undefined') { options.useColors = rli.terminal; } self.useColors = !!options.useColors; if (self.useColors && self.writer === util.inspect) { // Turn on ANSI coloring. self.writer = function(obj, showHidden, depth) { return util.inspect(obj, showHidden, depth, true); }; } rli.setPrompt(self.prompt); rli.on('close', function() { self.emit('exit'); }); var sawSIGINT = false; rli.on('SIGINT', function() { var empty = rli.line.length === 0; rli.clearLine(); if (!(self.bufferedCommand && self.bufferedCommand.length > 0) && empty) { if (sawSIGINT) { rli.close(); sawSIGINT = false; return; } rli.output.write('(^C again to quit)\n'); sawSIGINT = true; } else { sawSIGINT = false; } self.bufferedCommand = ''; self.displayPrompt(); }); rli.on('line', function(cmd) { sawSIGINT = false; var skipCatchall = false; cmd = trimWhitespace(cmd); // Check to see if a REPL keyword was used. If it returns true, // display next prompt and return. if (cmd && cmd.charAt(0) === '.' && isNaN(parseFloat(cmd))) { var matches = cmd.match(/^(\.[^\s]+)\s*(.*)$/); var keyword = matches && matches[1]; var rest = matches && matches[2]; if (self.parseREPLKeyword(keyword, rest) === true) { return; } else { self.outputStream.write('Invalid REPL keyword\n'); skipCatchall = true; } } if (!skipCatchall) { var evalCmd = self.bufferedCommand + cmd + '\n'; // This try is for determining if the command is complete, or should // continue onto the next line. // We try to evaluate both expressions e.g. // '{ a : 1 }' // and statements e.g. // 'for (var i = 0; i < 10; i++) console.log(i);' // First we attempt to eval as expression with parens. // This catches '{a : 1}' properly. self.eval('(' + evalCmd + ')', self.context, 'repl', function(e, ret) { if (e && !isSyntaxError(e)) return finish(e); if (typeof ret === 'function' && /^[\r\n\s]*function/.test(evalCmd) || e) { // Now as statement without parens. self.eval(evalCmd, self.context, 'repl', finish); } else { finish(null, ret); } }); } else { finish(null); } function finish(e, ret) { self.memory(cmd); // If error was SyntaxError and not JSON.parse error if (isSyntaxError(e)) { if (!self.bufferedCommand && cmd.trim().match(/^npm /)) { self.outputStream.write('npm should be run outside of the ' + 'node repl, in your normal shell.\n' + '(Press Control-D to exit.)\n'); self.bufferedCommand = ''; self.displayPrompt(); return; } // Start buffering data like that: // { // ... x: 1 // ... } self.bufferedCommand += cmd + '\n'; self.displayPrompt(); return; } else if (e) { self.outputStream.write((e.stack || e) + '\n'); } // Clear buffer if no SyntaxErrors self.bufferedCommand = ''; // If we got any output - print it (if no error) if (!e && (!self.ignoreUndefined || ret !== undefined)) { self.context._ = ret; self.outputStream.write(self.writer(ret) + '\n'); } // Display prompt again self.displayPrompt(); }; }); rli.on('SIGCONT', function() { self.displayPrompt(true); }); self.displayPrompt(); } inherits(REPLServer, EventEmitter); exports.REPLServer = REPLServer; // prompt is a string to print on each line for the prompt, // source is a stream to use for I/O, defaulting to stdin/stdout. exports.start = function(prompt, source, eval_, useGlobal, ignoreUndefined) { var repl = new REPLServer(prompt, source, eval_, useGlobal, ignoreUndefined); if (!exports.repl) exports.repl = repl; return repl; }; REPLServer.prototype.createContext = function() { var context; if (this.useGlobal) { context = global; } else { context = vm.createContext(); for (var i in global) context[i] = global[i]; context.console = new Console(this.outputStream); context.global = context; context.global.global = context; } context.module = module; context.require = require; this.lines = []; this.lines.level = []; // make built-in modules available directly // (loaded lazily) exports._builtinLibs.forEach(function(name) { Object.defineProperty(context, name, { get: function() { var lib = require(name); context._ = context[name] = lib; return lib; }, // allow the creation of other globals with this name set: function(val) { delete context[name]; context[name] = val; }, configurable: true }); }); return context; }; REPLServer.prototype.resetContext = function() { this.context = this.createContext(); }; REPLServer.prototype.displayPrompt = function(preserveCursor) { var prompt = this.prompt; if (this.bufferedCommand.length) { prompt = '...'; var levelInd = new Array(this.lines.level.length).join('..'); prompt += levelInd + ' '; } this.rli.setPrompt(prompt); this.rli.prompt(preserveCursor); }; // A stream to push an array into a REPL // used in REPLServer.complete function ArrayStream() { Stream.call(this); this.run = function(data) { var self = this; data.forEach(function(line) { self.emit('data', line + '\n'); }); } } util.inherits(ArrayStream, Stream); ArrayStream.prototype.readable = true; ArrayStream.prototype.writable = true; ArrayStream.prototype.resume = function() {}; ArrayStream.prototype.write = function() {}; var requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/; var simpleExpressionRE = /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/; // Provide a list of completions for the given leading text. This is // given to the readline interface for handling tab completion. // // Example: // complete('var foo = util.') // -> [['util.print', 'util.debug', 'util.log', 'util.inspect', 'util.pump'], // 'util.' ] // // Warning: This eval's code like "foo.bar.baz", so it will run property // getter code. REPLServer.prototype.complete = function(line, callback) { // There may be local variables to evaluate, try a nested REPL if (this.bufferedCommand != undefined && this.bufferedCommand.length) { // Get a new array of inputed lines var tmp = this.lines.slice(); // Kill off all function declarations to push all local variables into // global scope this.lines.level.forEach(function(kill) { if (kill.isFunction) { tmp[kill.line] = ''; } }); var flat = new ArrayStream(); // make a new "input" stream var magic = new REPLServer('', flat); // make a nested REPL magic.context = magic.createContext(); flat.run(tmp); // eval the flattened code // all this is only profitable if the nested REPL // does not have a bufferedCommand if (!magic.bufferedCommand) { return magic.complete(line, callback); } } var completions; // list of completion lists, one for each inheritance "level" var completionGroups = []; var completeOn, match, filter, i, j, group, c; // REPL commands (e.g. ".break"). var match = null; match = line.match(/^\s*(\.\w*)$/); if (match) { completionGroups.push(Object.keys(this.commands)); completeOn = match[1]; if (match[1].length > 1) { filter = match[1]; } completionGroupsLoaded(); } else if (match = line.match(requireRE)) { // require('...') var exts = Object.keys(require.extensions); var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') + ')$'); completeOn = match[1]; var subdir = match[2] || ''; var filter = match[1]; var dir, files, f, name, base, ext, abs, subfiles, s; group = []; var paths = module.paths.concat(require('module').globalPaths); for (i = 0; i < paths.length; i++) { dir = path.resolve(paths[i], subdir); try { files = fs.readdirSync(dir); } catch (e) { continue; } for (f = 0; f < files.length; f++) { name = files[f]; ext = path.extname(name); base = name.slice(0, -ext.length); if (base.match(/-\d+\.\d+(\.\d+)?/) || name === '.npm') { // Exclude versioned names that 'npm' installs. continue; } if (exts.indexOf(ext) !== -1) { if (!subdir || base !== 'index') { group.push(subdir + base); } } else { abs = path.resolve(dir, name); try { if (fs.statSync(abs).isDirectory()) { group.push(subdir + name + '/'); subfiles = fs.readdirSync(abs); for (s = 0; s < subfiles.length; s++) { if (indexRe.test(subfiles[s])) { group.push(subdir + name); } } } } catch (e) {} } } } if (group.length) { completionGroups.push(group); } if (!subdir) { completionGroups.push(exports._builtinLibs); } completionGroupsLoaded(); // Handle variable member lookup. // We support simple chained expressions like the following (no function // calls, etc.). That is for simplicity and also because we *eval* that // leading expression so for safety (see WARNING above) don't want to // eval function calls. // // foo.bar<|> # completions for 'foo' with filter 'bar' // spam.eggs.<|> # completions for 'spam.eggs' with filter '' // foo<|> # all scope vars with filter 'foo' // foo.<|> # completions for 'foo' with filter '' } else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) { match = simpleExpressionRE.exec(line); if (line.length === 0 || match) { var expr; completeOn = (match ? match[0] : ''); if (line.length === 0) { filter = ''; expr = ''; } else if (line[line.length - 1] === '.') { filter = ''; expr = match[0].slice(0, match[0].length - 1); } else { var bits = match[0].split('.'); filter = bits.pop(); expr = bits.join('.'); } // Resolve expr and get its completions. var obj, memberGroups = []; if (!expr) { // If context is instance of vm.ScriptContext // Get global vars synchronously if (this.useGlobal || this.context.constructor && this.context.constructor.name === 'Context') { var contextProto = this.context; while (contextProto = Object.getPrototypeOf(contextProto)) { completionGroups.push(Object.getOwnPropertyNames(contextProto)); } completionGroups.push(Object.getOwnPropertyNames(this.context)); addStandardGlobals(completionGroups, filter); completionGroupsLoaded(); } else { this.eval('.scope', this.context, 'repl', function(err, globals) { if (err || !globals) { addStandardGlobals(completionGroups, filter); } else if (Array.isArray(globals[0])) { // Add grouped globals globals.forEach(function(group) { completionGroups.push(group); }); } else { completionGroups.push(globals); addStandardGlobals(completionGroups, filter); } completionGroupsLoaded(); }); } } else { this.eval(expr, this.context, 'repl', function(e, obj) { // if (e) console.log(e); if (obj != null) { if (typeof obj === 'object' || typeof obj === 'function') { memberGroups.push(Object.getOwnPropertyNames(obj)); } // works for non-objects try { var sentinel = 5; var p; if (typeof obj === 'object' || typeof obj === 'function') { p = Object.getPrototypeOf(obj); } else { p = obj.constructor ? obj.constructor.prototype : null; } while (p !== null) { memberGroups.push(Object.getOwnPropertyNames(p)); p = Object.getPrototypeOf(p); // Circular refs possible? Let's guard against that. sentinel--; if (sentinel <= 0) { break; } } } catch (e) { //console.log("completion error walking prototype chain:" + e); } } if (memberGroups.length) { for (i = 0; i < memberGroups.length; i++) { completionGroups.push(memberGroups[i].map(function(member) { return expr + '.' + member; })); } if (filter) { filter = expr + '.' + filter; } } completionGroupsLoaded(); }); } } else { completionGroupsLoaded(); } } else { completionGroupsLoaded(); } // Will be called when all completionGroups are in place // Useful for async autocompletion function completionGroupsLoaded(err) { if (err) throw err; // Filter, sort (within each group), uniq and merge the completion groups. if (completionGroups.length && filter) { var newCompletionGroups = []; for (i = 0; i < completionGroups.length; i++) { group = completionGroups[i].filter(function(elem) { return elem.indexOf(filter) == 0; }); if (group.length) { newCompletionGroups.push(group); } } completionGroups = newCompletionGroups; } if (completionGroups.length) { var uniq = {}; // unique completions across all groups completions = []; // Completion group 0 is the "closest" // (least far up the inheritance chain) // so we put its completions last: to be closest in the REPL. for (i = completionGroups.length - 1; i >= 0; i--) { group = completionGroups[i]; group.sort(); for (var j = 0; j < group.length; j++) { c = group[j]; if (!hasOwnProperty(c)) { completions.push(c); uniq[c] = true; } } completions.push(''); // separator btwn groups } while (completions.length && completions[completions.length - 1] === '') { completions.pop(); } } callback(null, [completions || [], completeOn]); } }; /** * Used to parse and execute the Node REPL commands. * * @param {keyword} keyword The command entered to check. * @return {Boolean} If true it means don't continue parsing the command. */ REPLServer.prototype.parseREPLKeyword = function(keyword, rest) { var cmd = this.commands[keyword]; if (cmd) { cmd.action.call(this, rest); return true; } return false; }; REPLServer.prototype.defineCommand = function(keyword, cmd) { if (typeof cmd === 'function') { cmd = {action: cmd}; } else if (typeof cmd.action !== 'function') { throw new Error('bad argument, action must be a function'); } this.commands['.' + keyword] = cmd; }; REPLServer.prototype.memory = function memory(cmd) { var self = this; self.lines = self.lines || []; self.lines.level = self.lines.level || []; // save the line so I can do magic later if (cmd) { // TODO should I tab the level? self.lines.push(new Array(self.lines.level.length).join(' ') + cmd); } else { // I don't want to not change the format too much... self.lines.push(''); } // I need to know "depth." // Because I can not tell the difference between a } that // closes an object literal and a } that closes a function if (cmd) { // going down is { and ( e.g. function() { // going up is } and ) var dw = cmd.match(/{|\(/g); var up = cmd.match(/}|\)/g); up = up ? up.length : 0; dw = dw ? dw.length : 0; var depth = dw - up; if (depth) { (function workIt() { if (depth > 0) { // going... down. // push the line#, depth count, and if the line is a function. // Since JS only has functional scope I only need to remove // "function() {" lines, clearly this will not work for // "function() // {" but nothing should break, only tab completion for local // scope will not work for this function. self.lines.level.push({ line: self.lines.length - 1, depth: depth, isFunction: /\s*function\s*/.test(cmd) }); } else if (depth < 0) { // going... up. var curr = self.lines.level.pop(); if (curr) { var tmp = curr.depth + depth; if (tmp < 0) { //more to go, recurse depth += curr.depth; workIt(); } else if (tmp > 0) { //remove and push back curr.depth += depth; self.lines.level.push(curr); } } } }()); } // it is possible to determine a syntax error at this point. // if the REPL still has a bufferedCommand and // self.lines.level.length === 0 // TODO? keep a log of level so that any syntax breaking lines can // be cleared on .break and in the case of a syntax error? // TODO? if a log was kept, then I could clear the bufferedComand and // eval these lines and throw the syntax error } else { self.lines.level = []; } }; function addStandardGlobals(completionGroups, filter) { // Global object properties // (http://www.ecma-international.org/publications/standards/Ecma-262.htm) completionGroups.push(['NaN', 'Infinity', 'undefined', 'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'Object', 'Function', 'Array', 'String', 'Boolean', 'Number', 'Date', 'RegExp', 'Error', 'EvalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'Math', 'JSON']); // Common keywords. Exclude for completion on the empty string, b/c // they just get in the way. if (filter) { completionGroups.push(['break', 'case', 'catch', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', 'false', 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void', 'while', 'with', 'yield']); } } function defineDefaultCommands(repl) { // TODO remove me after 0.3.x repl.defineCommand('break', { help: 'Sometimes you get stuck, this gets you out', action: function() { this.bufferedCommand = ''; this.displayPrompt(); } }); var clearMessage; if (repl.useGlobal) { clearMessage = 'Alias for .break'; } else { clearMessage = 'Break, and also clear the local context'; } repl.defineCommand('clear', { help: clearMessage, action: function() { this.bufferedCommand = ''; if (!this.useGlobal) { this.outputStream.write('Clearing context...\n'); this.resetContext(); } this.displayPrompt(); } }); repl.defineCommand('exit', { help: 'Exit the repl', action: function() { this.rli.close(); } }); repl.defineCommand('help', { help: 'Show repl options', action: function() { var self = this; Object.keys(this.commands).sort().forEach(function(name) { var cmd = self.commands[name]; self.outputStream.write(name + '\t' + (cmd.help || '') + '\n'); }); this.displayPrompt(); } }); repl.defineCommand('save', { help: 'Save all evaluated commands in this REPL session to a file', action: function(file) { try { fs.writeFileSync(file, this.lines.join('\n') + '\n'); this.outputStream.write('Session saved to:' + file + '\n'); } catch (e) { this.outputStream.write('Failed to save:' + file + '\n'); } this.displayPrompt(); } }); repl.defineCommand('load', { help: 'Load JS from a file into the REPL session', action: function(file) { try { var stats = fs.statSync(file); if (stats && stats.isFile()) { var self = this; var data = fs.readFileSync(file, 'utf8'); var lines = data.split('\n'); this.displayPrompt(); lines.forEach(function(line) { if (line) { self.rli.write(line + '\n'); } }); } } catch (e) { this.outputStream.write('Failed to load:' + file + '\n'); } this.displayPrompt(); } }); } function trimWhitespace(cmd) { var trimmer = /^\s*(.+)\s*$/m, matches = trimmer.exec(cmd); if (matches && matches.length === 2) { return matches[1]; } return ''; } function regexpEscape(s) { return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); } /** * Converts commands that use var and function () to use the * local exports.context when evaled. This provides a local context * on the REPL. * * @param {String} cmd The cmd to convert. * @return {String} The converted command. */ REPLServer.prototype.convertToContext = function(cmd) { var self = this, matches, scopeVar = /^\s*var\s*([_\w\$]+)(.*)$/m, scopeFunc = /^\s*function\s*([_\w\$]+)/; // Replaces: var foo = "bar"; with: self.context.foo = bar; matches = scopeVar.exec(cmd); if (matches && matches.length === 3) { return 'self.context.' + matches[1] + matches[2]; } // Replaces: function foo() {}; with: foo = function foo() {}; matches = scopeFunc.exec(self.bufferedCommand); if (matches && matches.length === 2) { return matches[1] + ' = ' + self.bufferedCommand; } return cmd; }; /** * Returns `true` if "e" is a SyntaxError, `false` otherwise. * This function filters out false positives likes JSON.parse() errors and * RegExp syntax errors. */ function isSyntaxError(e) { // Convert error to string e = e && (e.stack || e.toString()); return e && ((e.match(/^SyntaxError/) && // RegExp syntax error !e.match(/^SyntaxError: Invalid regular expression/) && !e.match(/^SyntaxError: Invalid flags supplied to RegExp constructor/) && // "strict mode" syntax errors !e.match(/^SyntaxError: .*strict mode.*/i) && // JSON.parse() error !e.match(/\n {4}at Object.parse \(native\)\n/) && // Regexp errors in chakra: !e.match(/^Error: Expected .* in regular expression/) && !e.match(/^SyntaxError: Syntax error in regular expression/) && // Chakra Json parse error: !e.match(/\n {3}at JsonParse \(_chakra_patch.js/)) || ( (e.match(/^Error: Syntax error/) || e.match(/^Error: Expected/) ) && // RegExp syntax error !e.match(/^Error: Syntax error: Invalid regular expression/) && !e.match( /^Error: Syntax error: Invalid flags supplied to RegExp constructor/ ) && // "strict mode" syntax errors !e.match(/^Error: Syntax error: .*strict mode.*/i) && // JSON.parse() error !e.match(/\n {4}at Object.parse \(native\)\n/) && // Regexp errors in chakra: !e.match(/^Error: Expected .* in regular expression/) && !e.match(/^SyntaxError: Syntax error in regular expression/) && // Chakra Json parse error: !e.match(/\n {3}at JsonParse \(_chakra_patch.js/) )); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Maintainers, keep in mind that octal literals are not allowed // in strict mode. Use the decimal value and add a comment with // the octal value. Example: // // var mode = 438; /* mode=0666 */ var util = require('util'); var pathModule = require('path'); var binding = process.binding('fs'); var constants = process.binding('constants'); var fs = exports; var Stream = require('stream').Stream; var EventEmitter = require('events').EventEmitter; var Readable = Stream.Readable; var Writable = Stream.Writable; var kMinPoolSpace = 128; var O_APPEND = constants.O_APPEND || 0; var O_CREAT = constants.O_CREAT || 0; var O_DIRECTORY = constants.O_DIRECTORY || 0; var O_EXCL = constants.O_EXCL || 0; var O_NOCTTY = constants.O_NOCTTY || 0; var O_NOFOLLOW = constants.O_NOFOLLOW || 0; var O_RDONLY = constants.O_RDONLY || 0; var O_RDWR = constants.O_RDWR || 0; var O_SYMLINK = constants.O_SYMLINK || 0; var O_SYNC = constants.O_SYNC || 0; var O_TRUNC = constants.O_TRUNC || 0; var O_WRONLY = constants.O_WRONLY || 0; var isWindows = process.platform === 'win32'; var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); function rethrow() { // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and // is fairly slow to generate. var callback; if (DEBUG) { var backtrace = new Error; callback = debugCallback; } else callback = missingCallback; return callback; function debugCallback(err) { if (err) { backtrace.message = err.message; err = backtrace; missingCallback(err); } } function missingCallback(err) { if (err) { if (process.throwDeprecation) throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs else if (!process.noDeprecation) { var msg = 'fs: missing callback ' + (err.stack || err.message); if (process.traceDeprecation) console.trace(msg); else console.error(msg); } } } } function maybeCallback(cb) { return typeof cb === 'function' ? cb : rethrow(); } // Ensure that callbacks run in the global context. Only use this function // for callbacks that are passed to the binding layer, callbacks that are // invoked from JS already run in the proper scope. function makeCallback(cb) { if (typeof cb !== 'function') { return rethrow(); } return function() { return cb.apply(null, arguments); }; } function assertEncoding(encoding) { if (encoding && !Buffer.isEncoding(encoding)) { throw new Error('Unknown encoding: ' + encoding); } } function nullCheck(path, callback) { if (('' + path).indexOf('\u0000') !== -1) { var er = new Error('Path must be a string without null bytes.'); if (!callback) throw er; process.nextTick(function() { callback(er); }); return false; } return true; } fs.Stats = binding.Stats; fs.Stats.prototype._checkModeProperty = function(property) { return ((this.mode & constants.S_IFMT) === property); }; fs.Stats.prototype.isDirectory = function() { return this._checkModeProperty(constants.S_IFDIR); }; fs.Stats.prototype.isFile = function() { return this._checkModeProperty(constants.S_IFREG); }; fs.Stats.prototype.isBlockDevice = function() { return this._checkModeProperty(constants.S_IFBLK); }; fs.Stats.prototype.isCharacterDevice = function() { return this._checkModeProperty(constants.S_IFCHR); }; fs.Stats.prototype.isSymbolicLink = function() { return this._checkModeProperty(constants.S_IFLNK); }; fs.Stats.prototype.isFIFO = function() { return this._checkModeProperty(constants.S_IFIFO); }; fs.Stats.prototype.isSocket = function() { return this._checkModeProperty(constants.S_IFSOCK); }; fs.exists = function(path, callback) { if (!nullCheck(path, cb)) return; binding.stat(pathModule._makeLong(path), cb); function cb(err, stats) { if (callback) callback(err ? false : true); } }; fs.existsSync = function(path) { try { nullCheck(path); binding.stat(pathModule._makeLong(path)); return true; } catch (e) { return false; } }; fs.readFile = function(path, options, callback_) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: null, flag: 'r' }; } else if (typeof options === 'string') { options = { encoding: options, flag: 'r' }; } else if (!options) { options = { encoding: null, flag: 'r' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } var encoding = options.encoding; assertEncoding(encoding); // first, stat the file, so we know the size. var size; var buffer; // single buffer with file data var buffers; // list for when size is unknown var pos = 0; var fd; var flag = options.flag || 'r'; fs.open(path, flag, 438 /*=0666*/, function(er, fd_) { if (er) return callback(er); fd = fd_; fs.fstat(fd, function(er, st) { if (er) return callback(er); size = st.size; if (size === 0) { // the kernel lies about many files. // Go ahead and try to read some bytes. buffers = []; return read(); } buffer = new Buffer(size); read(); }); }); function read() { if (size === 0) { buffer = new Buffer(8192); fs.read(fd, buffer, 0, 8192, -1, afterRead); } else { fs.read(fd, buffer, pos, size - pos, -1, afterRead); } } function afterRead(er, bytesRead) { if (er) { return fs.close(fd, function(er2) { return callback(er); }); } if (bytesRead === 0) { return close(); } pos += bytesRead; if (size !== 0) { if (pos === size) close(); else read(); } else { // unknown size, just read until we don't get bytes. buffers.push(buffer.slice(0, bytesRead)); read(); } } function close() { fs.close(fd, function(er) { if (size === 0) { // collected the data into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (encoding) buffer = buffer.toString(encoding); return callback(er, buffer); }); } }; fs.readFileSync = function(path, options) { if (!options) { options = { encoding: null, flag: 'r' }; } else if (typeof options === 'string') { options = { encoding: options, flag: 'r' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } var encoding = options.encoding; assertEncoding(encoding); var flag = options.flag || 'r'; var fd = fs.openSync(path, flag, 438 /*=0666*/); var size; var threw = true; try { size = fs.fstatSync(fd).size; threw = false; } finally { if (threw) fs.closeSync(fd); } var pos = 0; var buffer; // single buffer with file data var buffers; // list for when size is unknown if (size === 0) { buffers = []; } else { buffer = new Buffer(size); } var done = false; while (!done) { var threw = true; try { if (size !== 0) { var bytesRead = fs.readSync(fd, buffer, pos, size - pos); } else { // the kernel lies about many files. // Go ahead and try to read some bytes. buffer = new Buffer(8192); var bytesRead = fs.readSync(fd, buffer, 0, 8192); if (bytesRead) { buffers.push(buffer.slice(0, bytesRead)); } } threw = false; } finally { if (threw) fs.closeSync(fd); } pos += bytesRead; done = (bytesRead === 0) || (size !== 0 && pos >= size); } fs.closeSync(fd); if (size === 0) { // data was collected into the buffers list. buffer = Buffer.concat(buffers, pos); } else if (pos < size) { buffer = buffer.slice(0, pos); } if (encoding) buffer = buffer.toString(encoding); return buffer; }; // Used by binding.open and friends function stringToFlags(flag) { // Only mess with strings if (typeof flag !== 'string') { return flag; } // O_EXCL is mandated by POSIX, Windows supports it too. // Let's add a check anyway, just in case. if (!O_EXCL && ~flag.indexOf('x')) { throw errnoException('ENOSYS', 'fs.open(O_EXCL)'); } switch (flag) { case 'r' : return O_RDONLY; case 'rs' : return O_RDONLY | O_SYNC; case 'r+' : return O_RDWR; case 'rs+' : return O_RDWR | O_SYNC; case 'w' : return O_TRUNC | O_CREAT | O_WRONLY; case 'wx' : // fall through case 'xw' : return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL; case 'w+' : return O_TRUNC | O_CREAT | O_RDWR; case 'wx+': // fall through case 'xw+': return O_TRUNC | O_CREAT | O_RDWR | O_EXCL; case 'a' : return O_APPEND | O_CREAT | O_WRONLY; case 'ax' : // fall through case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; case 'a+' : return O_APPEND | O_CREAT | O_RDWR; case 'ax+': // fall through case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL; } throw new Error('Unknown file open flag: ' + flag); } // exported but hidden, only used by test/simple/test-fs-open-flags.js Object.defineProperty(exports, '_stringToFlags', { enumerable: false, value: stringToFlags }); // Yes, the follow could be easily DRYed up but I provide the explicit // list to make the arguments clear. fs.close = function(fd, callback) { binding.close(fd, makeCallback(callback)); }; fs.closeSync = function(fd) { return binding.close(fd); }; function modeNum(m, def) { switch (typeof m) { case 'number': return m; case 'string': return parseInt(m, 8); default: if (def) { return modeNum(def); } else { return undefined; } } } fs.open = function(path, flags, mode, callback) { callback = makeCallback(arguments[arguments.length - 1]); mode = modeNum(mode, 438 /*=0666*/); if (!nullCheck(path, callback)) return; binding.open(pathModule._makeLong(path), stringToFlags(flags), mode, callback); }; fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 438 /*=0666*/); nullCheck(path); return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode); }; fs.read = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, length, position, encoding, callback) var cb = arguments[4], encoding = arguments[3]; assertEncoding(encoding); position = arguments[2]; length = arguments[1]; buffer = new Buffer(length); offset = 0; callback = function(err, bytesRead) { if (!cb) return; var str = (bytesRead > 0) ? buffer.toString(encoding, 0, bytesRead) : ''; (cb)(err, str, bytesRead); }; } function wrapper(err, bytesRead) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback && callback(err, bytesRead || 0, buffer); } binding.read(fd, buffer, offset, length, position, wrapper); }; fs.readSync = function(fd, buffer, offset, length, position) { var legacy = false; if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, length, position, encoding, callback) legacy = true; var encoding = arguments[3]; assertEncoding(encoding); position = arguments[2]; length = arguments[1]; buffer = new Buffer(length); offset = 0; } var r = binding.read(fd, buffer, offset, length, position); if (!legacy) { return r; } var str = (r > 0) ? buffer.toString(encoding, 0, r) : ''; return [str, r]; }; fs.write = function(fd, buffer, offset, length, position, callback) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, data, position, encoding, callback) callback = arguments[4]; position = arguments[2]; assertEncoding(arguments[3]); buffer = new Buffer('' + arguments[1], arguments[3]); offset = 0; length = buffer.length; } if (!length) { if (typeof callback == 'function') { process.nextTick(function() { callback(undefined, 0); }); } return; } callback = maybeCallback(callback); function wrapper(err, written) { // Retain a reference to buffer so that it can't be GC'ed too soon. callback(err, written || 0, buffer); } binding.write(fd, buffer, offset, length, position, wrapper); }; fs.writeSync = function(fd, buffer, offset, length, position) { if (!Buffer.isBuffer(buffer)) { // legacy string interface (fd, data, position, encoding) position = arguments[2]; assertEncoding(arguments[3]); buffer = new Buffer('' + arguments[1], arguments[3]); offset = 0; length = buffer.length; } if (!length) return 0; return binding.write(fd, buffer, offset, length, position); }; fs.rename = function(oldPath, newPath, callback) { callback = makeCallback(callback); if (!nullCheck(oldPath, callback)) return; if (!nullCheck(newPath, callback)) return; binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath), callback); }; fs.renameSync = function(oldPath, newPath) { nullCheck(oldPath); nullCheck(newPath); return binding.rename(pathModule._makeLong(oldPath), pathModule._makeLong(newPath)); }; fs.truncate = function(path, len, callback) { if (typeof path === 'number') { // legacy return fs.ftruncate(path, len, callback); } if (typeof len === 'function') { callback = len; len = 0; } else if (typeof len === 'undefined') { len = 0; } callback = maybeCallback(callback); fs.open(path, 'w', function(er, fd) { if (er) return callback(er); binding.ftruncate(fd, len, function(er) { fs.close(fd, function(er2) { callback(er || er2); }); }); }); }; fs.truncateSync = function(path, len) { if (typeof path === 'number') { // legacy return fs.ftruncateSync(path, len); } if (typeof len === 'undefined') { len = 0; } // allow error to be thrown, but still close fd. var fd = fs.openSync(path, 'w'); try { var ret = fs.ftruncateSync(fd, len); } finally { fs.closeSync(fd); } return ret; }; fs.ftruncate = function(fd, len, callback) { if (typeof len === 'function') { callback = len; len = 0; } else if (typeof len === 'undefined') { len = 0; } binding.ftruncate(fd, len, makeCallback(callback)); }; fs.ftruncateSync = function(fd, len) { if (typeof len === 'undefined') { len = 0; } return binding.ftruncate(fd, len); }; fs.rmdir = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.rmdir(pathModule._makeLong(path), callback); }; fs.rmdirSync = function(path) { nullCheck(path); return binding.rmdir(pathModule._makeLong(path)); }; fs.fdatasync = function(fd, callback) { binding.fdatasync(fd, makeCallback(callback)); }; fs.fdatasyncSync = function(fd) { return binding.fdatasync(fd); }; fs.fsync = function(fd, callback) { binding.fsync(fd, makeCallback(callback)); }; fs.fsyncSync = function(fd) { return binding.fsync(fd); }; fs.mkdir = function(path, mode, callback) { if (typeof mode === 'function') callback = mode; callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/), callback); }; fs.mkdirSync = function(path, mode) { nullCheck(path); return binding.mkdir(pathModule._makeLong(path), modeNum(mode, 511 /*=0777*/)); }; fs.readdir = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.readdir(pathModule._makeLong(path), callback); }; fs.readdirSync = function(path) { nullCheck(path); return binding.readdir(pathModule._makeLong(path)); }; fs.fstat = function(fd, callback) { binding.fstat(fd, makeCallback(callback)); }; fs.lstat = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.lstat(pathModule._makeLong(path), callback); }; fs.stat = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.stat(pathModule._makeLong(path), callback); }; fs.fstatSync = function(fd) { return binding.fstat(fd); }; fs.lstatSync = function(path) { nullCheck(path); return binding.lstat(pathModule._makeLong(path)); }; fs.statSync = function(path) { nullCheck(path); return binding.stat(pathModule._makeLong(path)); }; fs.readlink = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.readlink(pathModule._makeLong(path), callback); }; fs.readlinkSync = function(path) { nullCheck(path); return binding.readlink(pathModule._makeLong(path)); }; function preprocessSymlinkDestination(path, type) { if (!isWindows) { // No preprocessing is needed on Unix. return path; } else if (type === 'junction') { // Junctions paths need to be absolute and \\?\-prefixed. return pathModule._makeLong(path); } else { // Windows symlinks don't tolerate forward slashes. return ('' + path).replace(/\//g, '\\'); } } fs.symlink = function(destination, path, type_, callback) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); if (!nullCheck(destination, callback)) return; if (!nullCheck(path, callback)) return; binding.symlink(preprocessSymlinkDestination(destination, type), pathModule._makeLong(path), type, callback); }; fs.symlinkSync = function(destination, path, type) { type = (typeof type === 'string' ? type : null); nullCheck(destination); nullCheck(path); return binding.symlink(preprocessSymlinkDestination(destination, type), pathModule._makeLong(path), type); }; fs.link = function(srcpath, dstpath, callback) { callback = makeCallback(callback); if (!nullCheck(srcpath, callback)) return; if (!nullCheck(dstpath, callback)) return; binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath), callback); }; fs.linkSync = function(srcpath, dstpath) { nullCheck(srcpath); nullCheck(dstpath); return binding.link(pathModule._makeLong(srcpath), pathModule._makeLong(dstpath)); }; fs.unlink = function(path, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.unlink(pathModule._makeLong(path), callback); }; fs.unlinkSync = function(path) { nullCheck(path); return binding.unlink(pathModule._makeLong(path)); }; fs.fchmod = function(fd, mode, callback) { binding.fchmod(fd, modeNum(mode), makeCallback(callback)); }; fs.fchmodSync = function(fd, mode) { return binding.fchmod(fd, modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchmod = function(path, mode, callback) { callback = maybeCallback(callback); fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) { if (err) { callback(err); return; } // prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. fs.fchmod(fd, mode, function(err) { fs.close(fd, function(err2) { callback(err || err2); }); }); }); }; fs.lchmodSync = function(path, mode) { var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK); // prefer to return the chmod error, if one occurs, // but still try to close, and report closing errors if they occur. var err, err2; try { var ret = fs.fchmodSync(fd, mode); } catch (er) { err = er; } try { fs.closeSync(fd); } catch (er) { err2 = er; } if (err || err2) throw (err || err2); return ret; }; } fs.chmod = function(path, mode, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.chmod(pathModule._makeLong(path), modeNum(mode), callback); }; fs.chmodSync = function(path, mode) { nullCheck(path); return binding.chmod(pathModule._makeLong(path), modeNum(mode)); }; if (constants.hasOwnProperty('O_SYMLINK')) { fs.lchown = function(path, uid, gid, callback) { callback = maybeCallback(callback); fs.open(path, constants.O_WRONLY | constants.O_SYMLINK, function(err, fd) { if (err) { callback(err); return; } fs.fchown(fd, uid, gid, callback); }); }; fs.lchownSync = function(path, uid, gid) { var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK); return fs.fchownSync(fd, uid, gid); }; } fs.fchown = function(fd, uid, gid, callback) { binding.fchown(fd, uid, gid, makeCallback(callback)); }; fs.fchownSync = function(fd, uid, gid) { return binding.fchown(fd, uid, gid); }; fs.chown = function(path, uid, gid, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.chown(pathModule._makeLong(path), uid, gid, callback); }; fs.chownSync = function(path, uid, gid) { nullCheck(path); return binding.chown(pathModule._makeLong(path), uid, gid); }; // converts Date or number to a fractional UNIX timestamp function toUnixTimestamp(time) { if (typeof time == 'number') { return time; } if (time instanceof Date) { // convert to 123.456 UNIX timestamp return time.getTime() / 1000; } throw new Error('Cannot parse time: ' + time); } // exported for unit tests, not for public consumption fs._toUnixTimestamp = toUnixTimestamp; fs.utimes = function(path, atime, mtime, callback) { callback = makeCallback(callback); if (!nullCheck(path, callback)) return; binding.utimes(pathModule._makeLong(path), toUnixTimestamp(atime), toUnixTimestamp(mtime), callback); }; fs.utimesSync = function(path, atime, mtime) { nullCheck(path); atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.utimes(pathModule._makeLong(path), atime, mtime); }; fs.futimes = function(fd, atime, mtime, callback) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime, makeCallback(callback)); }; fs.futimesSync = function(fd, atime, mtime) { atime = toUnixTimestamp(atime); mtime = toUnixTimestamp(mtime); binding.futimes(fd, atime, mtime); }; function writeAll(fd, buffer, offset, length, position, callback) { callback = maybeCallback(arguments[arguments.length - 1]); // write(fd, buffer, offset, length, position, callback) fs.write(fd, buffer, offset, length, position, function(writeErr, written) { if (writeErr) { fs.close(fd, function() { if (callback) callback(writeErr); }); } else { if (written === length) { fs.close(fd, callback); } else { offset += written; length -= written; position += written; writeAll(fd, buffer, offset, length, position, callback); } } }); } fs.writeFile = function(path, data, options, callback) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'w' }; } else if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } assertEncoding(options.encoding); var flag = options.flag || 'w'; fs.open(path, options.flag || 'w', options.mode, function(openErr, fd) { if (openErr) { if (callback) callback(openErr); } else { var buffer = Buffer.isBuffer(data) ? data : new Buffer('' + data, options.encoding || 'utf8'); var position = /a/.test(flag) ? null : 0; writeAll(fd, buffer, 0, buffer.length, position, callback); } }); }; fs.writeFileSync = function(path, data, options) { if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'w' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'w' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } assertEncoding(options.encoding); var flag = options.flag || 'w'; var fd = fs.openSync(path, flag, options.mode); if (!Buffer.isBuffer(data)) { data = new Buffer('' + data, options.encoding || 'utf8'); } var written = 0; var length = data.length; var position = /a/.test(flag) ? null : 0; try { while (written < length) { written += fs.writeSync(fd, data, written, length - written, position); position += written; } } finally { fs.closeSync(fd); } }; fs.appendFile = function(path, data, options, callback_) { var callback = maybeCallback(arguments[arguments.length - 1]); if (typeof options === 'function' || !options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'a' }; } else if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } if (!options.flag) options = util._extend({ flag: 'a' }, options); fs.writeFile(path, data, options, callback); }; fs.appendFileSync = function(path, data, options) { if (!options) { options = { encoding: 'utf8', mode: 438 /*=0666*/, flag: 'a' }; } else if (typeof options === 'string') { options = { encoding: options, mode: 438, flag: 'a' }; } else if (typeof options !== 'object') { throw new TypeError('Bad arguments'); } if (!options.flag) options = util._extend({ flag: 'a' }, options); fs.writeFileSync(path, data, options); }; function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function FSWatcher() { EventEmitter.call(this); var self = this; var FSEvent = process.binding('fs_event_wrap').FSEvent; this._handle = new FSEvent(); this._handle.owner = this; this._handle.onchange = function(status, event, filename) { if (status) { self._handle.close(); self.emit('error', errnoException(process._errno, 'watch')); } else { self.emit('change', event, filename); } }; } util.inherits(FSWatcher, EventEmitter); FSWatcher.prototype.start = function(filename, persistent) { nullCheck(filename); var r = this._handle.start(pathModule._makeLong(filename), persistent); if (r) { this._handle.close(); throw errnoException(process._errno, 'watch'); } }; FSWatcher.prototype.close = function() { this._handle.close(); }; fs.watch = function(filename) { nullCheck(filename); var watcher; var options; var listener; if ('object' == typeof arguments[1]) { options = arguments[1]; listener = arguments[2]; } else { options = {}; listener = arguments[1]; } if (options.persistent === undefined) options.persistent = true; watcher = new FSWatcher(); watcher.start(filename, options.persistent); if (listener) { watcher.addListener('change', listener); } return watcher; }; // Stat Change Watchers function StatWatcher() { EventEmitter.call(this); var self = this; this._handle = new binding.StatWatcher(); // uv_fs_poll is a little more powerful than ev_stat but we curb it for // the sake of backwards compatibility var oldStatus = -1; this._handle.onchange = function(current, previous, newStatus) { if (oldStatus === -1 && newStatus === -1 && current.nlink === previous.nlink) return; oldStatus = newStatus; self.emit('change', current, previous); }; this._handle.onstop = function() { self.emit('stop'); }; } util.inherits(StatWatcher, EventEmitter); StatWatcher.prototype.start = function(filename, persistent, interval) { nullCheck(filename); this._handle.start(pathModule._makeLong(filename), persistent, interval); }; StatWatcher.prototype.stop = function() { this._handle.stop(); }; var statWatchers = {}; function inStatWatchers(filename) { return Object.prototype.hasOwnProperty.call(statWatchers, filename) && statWatchers[filename]; } fs.watchFile = function(filename) { nullCheck(filename); var stat; var listener; var options = { // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. interval: 5007, persistent: true }; if ('object' == typeof arguments[1]) { options = util._extend(options, arguments[1]); listener = arguments[2]; } else { listener = arguments[1]; } if (!listener) { throw new Error('watchFile requires a listener function'); } if (inStatWatchers(filename)) { stat = statWatchers[filename]; } else { stat = statWatchers[filename] = new StatWatcher(); stat.start(filename, options.persistent, options.interval); } stat.addListener('change', listener); return stat; }; fs.unwatchFile = function(filename, listener) { nullCheck(filename); if (!inStatWatchers(filename)) return; var stat = statWatchers[filename]; if (typeof listener === 'function') { stat.removeListener('change', listener); } else { stat.removeAllListeners('change'); } if (EventEmitter.listenerCount(stat, 'change') === 0) { stat.stop(); statWatchers[filename] = undefined; } }; // Realpath // Not using realpath(2) because it's bad. // See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html var normalize = pathModule.normalize; // Regexp that finds the next partion of a (partial) path // result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] if (isWindows) { var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; } else { var nextPartRe = /(.*?)(?:[\/]+|$)/g; } // Regex to find the device root, including trailing slash. E.g. 'c:\\'. if (isWindows) { var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; } else { var splitRootRe = /^[\/]*/; } fs.realpathSync = function realpathSync(p, cache) { // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return cache[p]; } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstatSync(base); knownHard[base] = true; } knownHard[base] = true; } // walk down the path, swapping out linked pathparts for their real // values // NB: p.length changes. while (pos < p.length) { // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { continue; } var resolvedLink; if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // some known symbolic link. no need to stat again. resolvedLink = cache[base]; } else { var stat = fs.lstatSync(base); if (!stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; continue; } // read the link if it wasn't read before // dev/ino always return 0 on windows, so skip the check. var linkTarget = null; if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { linkTarget = seenLinks[id]; } } if (linkTarget === null) { fs.statSync(base); linkTarget = fs.readlinkSync(base); } resolvedLink = pathModule.resolve(previous, linkTarget); // track this, if given a cache. if (cache) cache[base] = resolvedLink; if (!isWindows) seenLinks[id] = linkTarget; } // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } if (cache) cache[original] = p; return p; }; fs.realpath = function realpath(p, cache, cb) { if (typeof cb !== 'function') { cb = maybeCallback(cache); cache = null; } // make p is absolute p = pathModule.resolve(p); if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { return process.nextTick(cb.bind(null, null, cache[p])); } var original = p, seenLinks = {}, knownHard = {}; // current character position in p var pos; // the partial path so far, including a trailing slash if any var current; // the partial path without a trailing slash (except when pointing at a root) var base; // the partial path scanned in the previous round, with slash var previous; start(); function start() { // Skip over roots var m = splitRootRe.exec(p); pos = m[0].length; current = m[0]; base = m[0]; previous = ''; // On windows, check that the root exists. On unix there is no need. if (isWindows && !knownHard[base]) { fs.lstat(base, function(err) { if (err) return cb(err); knownHard[base] = true; LOOP(); }); } else { process.nextTick(LOOP); } } // walk down the path, swapping out linked pathparts for their real // values function LOOP() { // stop if scanned past end of path if (pos >= p.length) { if (cache) cache[original] = p; return cb(null, p); } // find the next part nextPartRe.lastIndex = pos; var result = nextPartRe.exec(p); previous = current; current += result[0]; base = previous + result[1]; pos = nextPartRe.lastIndex; // continue if not a symlink if (knownHard[base] || (cache && cache[base] === base)) { return process.nextTick(LOOP); } if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { // known symbolic link. no need to stat again. return gotResolvedLink(cache[base]); } return fs.lstat(base, gotStat); } function gotStat(err, stat) { if (err) return cb(err); // if not a symlink, skip to the next path part if (!stat.isSymbolicLink()) { knownHard[base] = true; if (cache) cache[base] = base; return process.nextTick(LOOP); } // stat & read the link if not read before // call gotTarget as soon as the link target is known // dev/ino always return 0 on windows, so skip the check. if (!isWindows) { var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); if (seenLinks.hasOwnProperty(id)) { return gotTarget(null, seenLinks[id], base); } } fs.stat(base, function(err) { if (err) return cb(err); fs.readlink(base, function(err, target) { if (!isWindows) seenLinks[id] = target; gotTarget(err, target); }); }); } function gotTarget(err, target, base) { if (err) return cb(err); var resolvedLink = pathModule.resolve(previous, target); if (cache) cache[base] = resolvedLink; gotResolvedLink(resolvedLink); } function gotResolvedLink(resolvedLink) { // resolve the link, then start over p = pathModule.resolve(resolvedLink, p.slice(pos)); start(); } }; var pool; function allocNewPool(poolSize) { pool = new Buffer(poolSize); pool.used = 0; } fs.createReadStream = function(path, options) { return new ReadStream(path, options); }; util.inherits(ReadStream, Readable); fs.ReadStream = ReadStream; function ReadStream(path, options) { if (!(this instanceof ReadStream)) return new ReadStream(path, options); // a little bit bigger buffer and water marks by default options = util._extend({ highWaterMark: 64 * 1024 }, options || {}); Readable.call(this, options); this.path = path; this.fd = options.hasOwnProperty('fd') ? options.fd : null; this.flags = options.hasOwnProperty('flags') ? options.flags : 'r'; this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ this.start = options.hasOwnProperty('start') ? options.start : undefined; this.end = options.hasOwnProperty('end') ? options.end : undefined; this.autoClose = options.hasOwnProperty('autoClose') ? options.autoClose : true; this.pos = undefined; if (this.start !== undefined) { if ('number' !== typeof this.start) { throw TypeError('start must be a Number'); } if (this.end === undefined) { this.end = Infinity; } else if ('number' !== typeof this.end) { throw TypeError('end must be a Number'); } if (this.start > this.end) { throw new Error('start must be <= end'); } this.pos = this.start; } if (typeof this.fd !== 'number') this.open(); this.on('end', function() { if (this.autoClose) { this.destroy(); } }); } fs.FileReadStream = fs.ReadStream; // support the legacy name ReadStream.prototype.open = function() { var self = this; fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { if (this.autoClose) { self.destroy(); } self.emit('error', er); return; } self.fd = fd; self.emit('open', fd); // start the flow of data. self.read(); }); }; ReadStream.prototype._read = function(n) { if (typeof this.fd !== 'number') return this.once('open', function() { this._read(n); }); if (this.destroyed) return; if (!pool || pool.length - pool.used < kMinPoolSpace) { // discard the old pool. pool = null; allocNewPool(this._readableState.highWaterMark); } // Grab another reference to the pool in the case that while we're // in the thread pool another read() finishes up the pool, and // allocates a new one. var thisPool = pool; var toRead = Math.min(pool.length - pool.used, n); var start = pool.used; if (this.pos !== undefined) toRead = Math.min(this.end - this.pos + 1, toRead); // already read everything we were supposed to read! // treat as EOF. if (toRead <= 0) return this.push(null); // the actual read. var self = this; fs.read(this.fd, pool, pool.used, toRead, this.pos, onread); // move the pool positions, and internal position for reading. if (this.pos !== undefined) this.pos += toRead; pool.used += toRead; function onread(er, bytesRead) { if (er) { if (self.autoClose) { self.destroy(); } self.emit('error', er); } else { var b = null; if (bytesRead > 0) b = thisPool.slice(start, start + bytesRead); self.push(b); } } }; ReadStream.prototype.destroy = function() { if (this.destroyed) return; this.destroyed = true; if ('number' === typeof this.fd) this.close(); }; ReadStream.prototype.close = function(cb) { var self = this; if (cb) this.once('close', cb); if (this.closed || 'number' !== typeof this.fd) { if ('number' !== typeof this.fd) { this.once('open', close); return; } return process.nextTick(this.emit.bind(this, 'close')); } this.closed = true; close(); function close(fd) { fs.close(fd || self.fd, function(er) { if (er) self.emit('error', er); else self.emit('close'); }); self.fd = null; } }; fs.createWriteStream = function(path, options) { return new WriteStream(path, options); }; util.inherits(WriteStream, Writable); fs.WriteStream = WriteStream; function WriteStream(path, options) { if (!(this instanceof WriteStream)) return new WriteStream(path, options); options = options || {}; Writable.call(this, options); this.path = path; this.fd = null; this.fd = options.hasOwnProperty('fd') ? options.fd : null; this.flags = options.hasOwnProperty('flags') ? options.flags : 'w'; this.mode = options.hasOwnProperty('mode') ? options.mode : 438; /*=0666*/ this.start = options.hasOwnProperty('start') ? options.start : undefined; this.pos = undefined; this.bytesWritten = 0; if (this.start !== undefined) { if ('number' !== typeof this.start) { throw TypeError('start must be a Number'); } if (this.start < 0) { throw new Error('start must be >= zero'); } this.pos = this.start; } if ('number' !== typeof this.fd) this.open(); // dispose on finish. this.once('finish', this.close); } fs.FileWriteStream = fs.WriteStream; // support the legacy name WriteStream.prototype.open = function() { fs.open(this.path, this.flags, this.mode, function(er, fd) { if (er) { this.destroy(); this.emit('error', er); return; } this.fd = fd; this.emit('open', fd); }.bind(this)); }; WriteStream.prototype._write = function(data, encoding, cb) { if (!Buffer.isBuffer(data)) return this.emit('error', new Error('Invalid data')); if (typeof this.fd !== 'number') return this.once('open', function() { this._write(data, encoding, cb); }); var self = this; fs.write(this.fd, data, 0, data.length, this.pos, function(er, bytes) { if (er) { self.destroy(); return cb(er); } self.bytesWritten += bytes; cb(); }); if (this.pos !== undefined) this.pos += data.length; }; WriteStream.prototype.destroy = ReadStream.prototype.destroy; WriteStream.prototype.close = ReadStream.prototype.close; // There is no shutdown() for files. WriteStream.prototype.destroySoon = WriteStream.prototype.end; // SyncWriteStream is internal. DO NOT USE. // Temporary hack for process.stdout and process.stderr when piped to files. function SyncWriteStream(fd) { Stream.call(this); this.fd = fd; this.writable = true; this.readable = false; } util.inherits(SyncWriteStream, Stream); // Export fs.SyncWriteStream = SyncWriteStream; SyncWriteStream.prototype.write = function(data, arg1, arg2) { var encoding, cb; // parse arguments if (arg1) { if (typeof arg1 === 'string') { encoding = arg1; cb = arg2; } else if (typeof arg1 === 'function') { cb = arg1; } else { throw new Error('bad arg'); } } assertEncoding(encoding); // Change strings to buffers. SLOW if (typeof data == 'string') { data = new Buffer(data, encoding); } fs.writeSync(this.fd, data, 0, data.length); if (cb) { process.nextTick(cb); } return true; }; SyncWriteStream.prototype.end = function(data, arg1, arg2) { if (data) { this.write(data, arg1, arg2); } this.destroy(); }; SyncWriteStream.prototype.destroy = function() { fs.closeSync(this.fd); this.fd = null; this.emit('close'); return true; }; SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var NativeModule = require('native_module'); var Script = process.binding('evals').NodeScript; var runInThisContext = Script.runInThisContext; var runInNewContext = Script.runInNewContext; var assert = require('assert').ok; // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function Module(id, parent) { this.id = id; this.exports = {}; this.parent = parent; if (parent && parent.children) { parent.children.push(this); } this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all // modules in thier own context. if (!process.disable_node_env_vars) { Module._contextLoad = (+process.env['NODE_MODULE_CONTEXTS'] > 0); } Module._cache = {}; Module._pathCache = {}; Module._extensions = {}; var modulePaths = []; Module.globalPaths = []; Module.wrapper = NativeModule.wrapper; Module.wrap = NativeModule.wrap; var path = NativeModule.require('path'); Module._debug = function() {}; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { Module._debug = function(x) { console.error(x); }; } // We use this alias for the preprocessor that filters it out var debug = Module._debug; // given a module name, and a list of paths to test, returns the first // matching file in the following precedence. // // require("a.") // -> a. // // require("a") // -> a // -> a. // -> a/index. function statPath(path) { var fs = NativeModule.require('fs'); try { return fs.statSync(path); } catch (ex) {} return false; } // check if the directory is a package.json dir var packageCache = {}; function readPackage(requestPath) { if (hasOwnProperty(packageCache, requestPath)) { return packageCache[requestPath]; } var fs = NativeModule.require('fs'); try { var jsonPath = path.resolve(requestPath, 'package.json'); var json = fs.readFileSync(jsonPath, 'utf8'); } catch (e) { return false; } try { // nabar: the following line is commented in order to be more memory efficient and disable the package cache // var pkg = packageCache[requestPath] = JSON.parse(json); var pkg = JSON.parse(json); } catch (e) { e.path = jsonPath; e.message = 'Error parsing ' + jsonPath + ': ' + e.message; throw e; } return pkg; } function tryPackage(requestPath, exts) { var pkg = readPackage(requestPath); if (!pkg || !pkg.main) return false; var filename = path.resolve(requestPath, pkg.main); return tryFile(filename) || tryExtensions(filename, exts) || tryExtensions(path.resolve(filename, 'index'), exts); } // In order to minimize unnecessary lstat() calls, // this cache is a list of known-real paths. // Set to an empty object to reset. Module._realpathCache = {}; // check if the file exists and is not a directory function tryFile(requestPath) { var fs = NativeModule.require('fs'); var stats = statPath(requestPath); if (stats && !stats.isDirectory()) { return fs.realpathSync(requestPath, Module._realpathCache); } return false; } // given a path check a the file exists with any of the set extensions function tryExtensions(p, exts) { for (var i = 0, EL = exts.length; i < EL; i++) { var filename = tryFile(p + exts[i]); if (filename) { return filename; } } return false; } Module._findPath = function(request, paths) { var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { paths = ['']; } var trailingSlash = (request.slice(-1) === '/'); var cacheKey = JSON.stringify({request: request, paths: paths}); if (Module._pathCache[cacheKey]) { return Module._pathCache[cacheKey]; } // For each path for (var i = 0, PL = paths.length; i < PL; i++) { var basePath = path.resolve(paths[i], request); var filename; if (!trailingSlash) { // try to join the request to the path filename = tryFile(basePath); if (!filename && !trailingSlash) { // try it with each of the extensions filename = tryExtensions(basePath, exts); } } if (!filename) { filename = tryPackage(basePath, exts); } if (!filename) { // try it with each of the extensions at "index" filename = tryExtensions(path.resolve(basePath, 'index'), exts); } if (filename) { Module._pathCache[cacheKey] = filename; return filename; } } return false; }; // 'from' is the __dirname of the module. Module._nodeModulePaths = function(from) { // guarantee that 'from' is absolute. from = path.resolve(from); // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//; // yes, '/' works on both, but let's be a little canonical. var joiner = process.platform === 'win32' ? '\\' : '/'; var paths = []; var parts = from.split(splitRe); for (var tip = parts.length - 1; tip >= 0; tip--) { // don't search in .../node_modules/node_modules if (parts[tip] === 'node_modules') continue; var dir = parts.slice(0, tip + 1).concat('node_modules').join(joiner); paths.push(dir); } return paths; }; Module._resolveLookupPaths = function(request, parent) { if (NativeModule.exists(request)) { return [request, []]; } var start = request.substring(0, 2); if (start !== './' && start !== '..') { var paths = modulePaths; if (parent) { if (!parent.paths) parent.paths = []; paths = parent.paths.concat(paths); } return [request, paths]; } // with --eval, parent.id is not set and parent.filename is null if (!parent || !parent.id || !parent.filename) { // make require('./path/to/foo') work - normally the path is taken // from realpath(__filename) but with eval there is no filename var mainPaths = ['.'].concat(modulePaths); mainPaths = Module._nodeModulePaths('.').concat(mainPaths); return [request, mainPaths]; } // Is the parent an index module? // We can assume the parent has a valid extension, // as it already has been accepted as a module. var isIndex = /^index\.\w+?$/.test(path.basename(parent.filename)); var parentIdPath = isIndex ? parent.id : path.dirname(parent.id); var id = path.resolve(parentIdPath, request); // make sure require('./path') and require('path') get distinct ids, even // when called from the toplevel js file if (parentIdPath === '.' && id.indexOf('/') === -1) { id = './' + id; } debug('RELATIVE: requested:' + request + ' set ID to: ' + id + ' from ' + parent.id); return [id, [path.dirname(parent.filename)]]; }; Module._load = function(request, parent, isMain) { if (parent) { debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id); } var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; if (cachedModule) { return cachedModule.exports; } if (NativeModule.exists(filename)) { // REPL is a special case, because it needs the real require. if (filename == 'repl') { var replModule = new Module('repl'); replModule._compile(NativeModule.getSource('repl'), 'repl.js'); NativeModule._cache.repl = replModule; return replModule.exports; } debug('load native module ' + request); return NativeModule.require(filename); } var module = new Module(filename, parent); if (isMain) { process.mainModule = module; module.id = '.'; } Module._cache[filename] = module; var hadException = true; try { module.load(filename); hadException = false; } finally { if (hadException) { delete Module._cache[filename]; } } return module.exports; }; Module._resolveFilename = function(request, parent) { if (NativeModule.exists(request)) { return request; } var resolvedModule = Module._resolveLookupPaths(request, parent); var id = resolvedModule[0]; var paths = resolvedModule[1]; // look up the filename first, since that's the cache key. debug('looking for ' + JSON.stringify(id) + ' in ' + JSON.stringify(paths)); var filename = Module._findPath(request, paths); if (!filename) { var err = new Error("Cannot find module '" + request + "'"); err.code = 'MODULE_NOT_FOUND'; throw err; } return filename; }; Module.prototype.load = function(filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.filename = filename; this.paths = Module._nodeModulePaths(path.dirname(filename)); var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true; }; Module.prototype.require = function(path) { assert(typeof path === 'string', 'path must be a string'); assert(path, 'missing path'); return Module._load(path, this); }; // Resolved path to process.argv[1] will be lazily placed here // (needed for setting breakpoint when called with --debug-brk) var resolvedArgv; // Returns exception if any Module.prototype._compile = function(content, filename) { var self = this; // remove shebang content = content.replace(/^\#\!.*/, ''); function require(path) { return self.require(path); } require.resolve = function(request) { return Module._resolveFilename(request, self); }; Object.defineProperty(require, 'paths', { get: function() { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.'); }}); require.main = process.mainModule; // Enable support to add extra extension types require.extensions = Module._extensions; require.registerExtension = function() { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.'); }; require.cache = Module._cache; var dirname = path.dirname(filename); if (Module._contextLoad) { if (self.id !== '.') { debug('load submodule'); // not root module var sandbox = {}; for (var k in global) { sandbox[k] = global[k]; } sandbox.require = require; sandbox.exports = self.exports; sandbox.__filename = filename; sandbox.__dirname = dirname; sandbox.module = self; sandbox.global = sandbox; sandbox.root = root; return runInNewContext(content, sandbox, filename, true); } debug('load root module'); // root module global.require = require; global.exports = self.exports; global.__filename = filename; global.__dirname = dirname; global.module = self; return runInThisContext(content, filename, true); } // create wrapper function var wrapper = Module.wrap(content); var compiledWrapper = runInThisContext(wrapper, filename, true); if (global.v8debug) { if (!resolvedArgv) { // we enter the repl if we're not given a filename argument. if (process.argv[1]) { resolvedArgv = Module._resolveFilename(process.argv[1], null); } else { resolvedArgv = 'repl'; } } // Set breakpoint on module start if (filename === resolvedArgv) { global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0); } } var args = [self.exports, require, self, filename, dirname]; return compiledWrapper.apply(self.exports, args); }; function stripBOM(content) { // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) // because the buffer-to-string conversion in `fs.readFileSync()` // translates it to FEFF, the UTF-16 BOM. if (content.charCodeAt(0) === 0xFEFF) { content = content.slice(1); } return content; } // Native extension for .js Module._extensions['.js'] = function(module, filename) { var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); module._compile(stripBOM(content), filename); }; // Native extension for .json Module._extensions['.json'] = function(module, filename) { var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); try { module.exports = JSON.parse(stripBOM(content)); } catch (err) { err.message = filename + ': ' + err.message; throw err; } }; //Native extension for .node Module._extensions['.node'] = process.dlopen; // bootstrap main module. Module.runMain = function() { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback(); }; Module._initPaths = function() { var isWindows = process.platform === 'win32'; if (isWindows) { var homeDir = process.env.USERPROFILE; } else { var homeDir = process.env.HOME; } var paths = [path.resolve(process.execPath, '..', '..', 'lib', 'node')]; if (homeDir) { paths.unshift(path.resolve(homeDir, '.node_libraries')); paths.unshift(path.resolve(homeDir, '.node_modules')); } if (!process.disable_node_env_vars) { if (process.env['NODE_PATH']) { var splitter = isWindows ? ';' : ':'; paths = process.env['NODE_PATH'].split(splitter).concat(paths); } } modulePaths = paths; // clone as a read-only copy, for introspection. Module.globalPaths = modulePaths.slice(0); }; // bootstrap repl Module.requireRepl = function() { return Module._load('repl', '.'); }; Module._initPaths(); // backwards compatibility Module.Module = Module; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = process.binding('constants'); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var assert = require('assert'); var fork = require('child_process').fork; var net = require('net'); var EventEmitter = require('events').EventEmitter; var util = require('util'); function isObject(o) { return (typeof o === 'object' && o !== null); } var debug; if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) { debug = function(x) { var prefix = process.pid + ',' + (process.env.NODE_UNIQUE_ID ? 'Worker' : 'Master'); console.error(prefix, x); }; } else { debug = function() { }; } // cluster object: function Cluster() { EventEmitter.call(this); } util.inherits(Cluster, EventEmitter); var cluster = module.exports = new Cluster(); // Used in the master: var masterStarted = false; var ids = 0; var serverHandlers = {}; // Used in the worker: var serverListeners = {}; var queryIds = 0; var queryCallbacks = {}; // Define isWorker and isMaster cluster.isWorker = 'NODE_UNIQUE_ID' in process.env; cluster.isMaster = ! cluster.isWorker; // The worker object is only used in a worker cluster.worker = cluster.isWorker ? {} : null; // The workers array is only used in the master cluster.workers = cluster.isMaster ? {} : null; // Settings object var settings = cluster.settings = {}; // Simple function to call a function on each worker function eachWorker(cb) { // Go through all workers for (var id in cluster.workers) { if (cluster.workers.hasOwnProperty(id)) { cb(cluster.workers[id]); } } } // Extremely simple progress tracker function ProgressTracker(missing, callback) { this.missing = missing; this.callback = callback; } ProgressTracker.prototype.done = function() { this.missing -= 1; this.check(); }; ProgressTracker.prototype.check = function() { if (this.missing === 0) this.callback(); }; cluster.setupMaster = function(options) { // This can only be called from the master. assert(cluster.isMaster); // Don't allow this function to run more than once if (masterStarted) return; masterStarted = true; // Get filename and arguments options = options || {}; // By default, V8 writes the profile data of all processes to a single // v8.log. // // Running that log file through a tick processor produces bogus numbers // because many events won't match up with the recorded memory mappings // and you end up with graphs where 80+% of ticks is unaccounted for. // // Fixing the tick processor to deal with multi-process output is not very // useful because the processes may be running wildly disparate workloads. // // That's why we fix up the command line arguments to include // a "--logfile=v8-%p.log" argument (where %p is expanded to the PID) // unless it already contains a --logfile argument. var execArgv = options.execArgv || process.execArgv; if (execArgv.some(function(s) { return /^--prof/.test(s); }) && !execArgv.some(function(s) { return /^--logfile=/.test(s); })) { execArgv = execArgv.slice(); execArgv.push('--logfile=v8-%p.log'); } // Set settings object settings = cluster.settings = { exec: options.exec || process.argv[1], execArgv: execArgv, args: options.args || process.argv.slice(2), silent: options.silent || false }; // emit setup event cluster.emit('setup'); }; // Check if a message is internal only var INTERNAL_PREFIX = 'NODE_CLUSTER_'; function isInternalMessage(message) { return isObject(message) && typeof message.cmd === 'string' && message.cmd.length > INTERNAL_PREFIX.length && message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX; } // Modify message object to be internal function internalMessage(inMessage) { var outMessage = util._extend({}, inMessage); // Add internal prefix to cmd outMessage.cmd = INTERNAL_PREFIX + (outMessage.cmd || ''); return outMessage; } // Handle callback messages function handleResponse(outMessage, outHandle, inMessage, inHandle, worker) { // The message there will be sent var message = internalMessage(outMessage); // callback id - will be undefined if not set message._queryEcho = inMessage._requestEcho; // Call callback if a query echo is received if (inMessage._queryEcho) { queryCallbacks[inMessage._queryEcho](inMessage.content, inHandle); delete queryCallbacks[inMessage._queryEcho]; } // Send if outWrap contains something useful if (!(outMessage === undefined && message._queryEcho === undefined)) { sendInternalMessage(worker, message, outHandle); } } // Handle messages from both master and workers var messageHandler = {}; function handleMessage(worker, inMessage, inHandle) { // Remove internal prefix var message = util._extend({}, inMessage); message.cmd = inMessage.cmd.substr(INTERNAL_PREFIX.length); var respondUsed = false; function respond(outMessage, outHandler) { respondUsed = true; handleResponse(outMessage, outHandler, inMessage, inHandle, worker); } // Run handler if it exists if (messageHandler[message.cmd]) { messageHandler[message.cmd](message, worker, respond); } // Send respond if it hasn't been called yet if (respondUsed === false) { respond(); } } // Messages to the master will be handled using these methods if (cluster.isMaster) { // Handle online messages from workers messageHandler.online = function(message, worker) { worker.state = 'online'; debug('Worker ' + worker.process.pid + ' online'); worker.emit('online'); cluster.emit('online', worker); }; // Handle queryServer messages from workers messageHandler.queryServer = function(message, worker, send) { // This sequence of information is unique to the connection // but not to the worker var args = [message.address, message.port, message.addressType, message.fd]; var key = args.join(':'); var handler; if (serverHandlers.hasOwnProperty(key)) { handler = serverHandlers[key]; } else if (message.addressType === 'udp4' || message.addressType === 'udp6') { var dgram = require('dgram'); handler = dgram._createSocketHandle.apply(net, args); serverHandlers[key] = handler; } else { handler = net._createServerHandle.apply(net, args); serverHandlers[key] = handler; } // echo callback with the fd handler associated with it send({}, handler); }; // Handle listening messages from workers messageHandler.listening = function(message, worker) { worker.state = 'listening'; // Emit listening, now that we know the worker is listening worker.emit('listening', { address: message.address, port: message.port, addressType: message.addressType, fd: message.fd }); cluster.emit('listening', worker, { address: message.address, port: message.port, addressType: message.addressType, fd: message.fd }); }; // Handle suicide messages from workers messageHandler.suicide = function(message, worker) { worker.suicide = true; }; } // Messages to a worker will be handled using these methods else if (cluster.isWorker) { // Handle worker.disconnect from master messageHandler.disconnect = function(message, worker) { worker.disconnect(); }; } function toDecInt(value) { value = parseInt(value, 10); return isNaN(value) ? null : value; } // Create a worker object, that works both for master and worker function Worker(customEnv) { if (!(this instanceof Worker)) return new Worker(); EventEmitter.call(this); var self = this; var env = process.env; // Assign a unique id, default null this.id = cluster.isMaster ? ++ids : toDecInt(env.NODE_UNIQUE_ID); // XXX: Legacy. Remove in 0.9 this.workerID = this.uniqueID = this.id; // Assign state this.state = 'none'; // Create or get process if (cluster.isMaster) { // Create env object // first: copy and add id property var envCopy = util._extend({}, env); envCopy['NODE_UNIQUE_ID'] = this.id; // second: extend envCopy with the env argument if (isObject(customEnv)) { envCopy = util._extend(envCopy, customEnv); } // fork worker this.process = fork(settings.exec, settings.args, { 'env': envCopy, 'silent': settings.silent, 'execArgv': settings.execArgv }); } else { this.process = process; } if (cluster.isMaster) { // Save worker in the cluster.workers array cluster.workers[this.id] = this; // Emit a fork event, on next tick // There is no worker.fork event since this has no real purpose process.nextTick(function() { cluster.emit('fork', self); }); } // handle internalMessage, exit and disconnect event this.process.on('internalMessage', handleMessage.bind(null, this)); this.process.once('exit', function(exitCode, signalCode) { prepareExit(self, 'dead'); self.emit('exit', exitCode, signalCode); cluster.emit('exit', self, exitCode, signalCode); }); this.process.once('disconnect', function() { prepareExit(self, 'disconnected'); self.emit('disconnect'); cluster.emit('disconnect', self); }); // relay message and error this.process.on('message', this.emit.bind(this, 'message')); this.process.on('error', this.emit.bind(this, 'error')); } util.inherits(Worker, EventEmitter); cluster.Worker = Worker; function prepareExit(worker, state) { // set state to disconnect worker.state = state; // Make suicide a boolean worker.suicide = !!worker.suicide; // Remove from workers in the master if (cluster.isMaster) { delete cluster.workers[worker.id]; } } // Send internal message function sendInternalMessage(worker, message/*, handler, callback*/) { // Exist callback var callback = arguments[arguments.length - 1]; if (typeof callback !== 'function') { callback = undefined; } // exist handler var handler = arguments[2] !== callback ? arguments[2] : undefined; if (!isInternalMessage(message)) { message = internalMessage(message); } // Store callback for later if (callback) { message._requestEcho = worker.id + ':' + (++queryIds); queryCallbacks[message._requestEcho] = callback; } worker.send(message, handler); } // Send message to worker or master Worker.prototype.send = function() { // You could also just use process.send in a worker this.process.send.apply(this.process, arguments); }; // Kill the worker without restarting Worker.prototype.kill = Worker.prototype.destroy = function(signal) { if (!signal) signal = 'SIGTERM'; var self = this; this.suicide = true; if (cluster.isMaster) { // Disconnect IPC channel // this way the worker won't need to propagate suicide state to master if (self.process.connected) { self.process.once('disconnect', function() { self.process.kill(signal); }); self.process.disconnect(); } else { self.process.kill(signal); } } else { // Channel is open if (this.process.connected) { // Inform master to suicide and then kill sendInternalMessage(this, {cmd: 'suicide'}, function() { process.exit(0); }); // When channel is closed, terminate the process this.process.once('disconnect', function() { process.exit(0); }); } else { process.exit(0); } } }; // The .disconnect function will close all servers // and then disconnect the IPC channel. if (cluster.isMaster) { // Used in master Worker.prototype.disconnect = function() { this.suicide = true; sendInternalMessage(this, {cmd: 'disconnect'}); }; } else { // Used in workers Worker.prototype.disconnect = function() { var self = this; this.suicide = true; // keep track of open servers var servers = Object.keys(serverListeners).length; var progress = new ProgressTracker(servers, function() { // There are no more servers open so we will close the IPC channel. // Closing the IPC channel will emit a disconnect event // in both master and worker on the process object. // This event will be handled by prepareExit. self.process.disconnect(); }); // depending on where this function was called from (master or worker) // The suicide state has already been set, // but it doesn't really matter if we set it again. sendInternalMessage(this, {cmd: 'suicide'}, function() { // in case there are no servers progress.check(); // closing all servers gracefully var server; for (var key in serverListeners) { server = serverListeners[key]; // in case the server is closed we won't close it again if (server._handle === null) { progress.done(); continue; } server.on('close', progress.done.bind(progress)); server.close(); } }); }; } // Fork a new worker cluster.fork = function(env) { // This can only be called from the master. assert(cluster.isMaster); // Make sure that the master has been initialized cluster.setupMaster(); return (new cluster.Worker(env)); }; // execute .disconnect on all workers and close handlers when done cluster.disconnect = function(callback) { // This can only be called from the master. assert(cluster.isMaster); // Close all TCP handlers when all workers are disconnected var workers = Object.keys(cluster.workers).length; var progress = new ProgressTracker(workers, function() { for (var key in serverHandlers) { serverHandlers[key].close(); delete serverHandlers[key]; } // call callback when done if (callback) callback(); }); // begin disconnecting all workers eachWorker(function(worker) { worker.once('disconnect', progress.done.bind(progress)); worker.disconnect(); }); // in case there weren't any workers progress.check(); }; // Internal function. Called from src/node.js when worker process starts. cluster._setupWorker = function() { // Get worker class var worker = cluster.worker = new Worker(); // we will terminate the worker // when the worker is disconnected from the parent accidentally process.once('disconnect', function() { if (worker.suicide !== true) { process.exit(0); } }); // Tell master that the worker is online worker.state = 'online'; sendInternalMessage(worker, { cmd: 'online' }); }; // Internal function. Called by net.js and dgram.js when attempting to bind a // TCP server or UDP socket. cluster._getServer = function(tcpSelf, address, port, addressType, fd, cb) { // This can only be called from a worker. assert(cluster.isWorker); // Store tcp instance for later use var key = [address, port, addressType, fd].join(':'); serverListeners[key] = tcpSelf; // Send a listening message to the master tcpSelf.once('listening', function() { cluster.worker.state = 'listening'; sendInternalMessage(cluster.worker, { cmd: 'listening', address: address, port: tcpSelf.address().port || port, addressType: addressType, fd: fd }); }); // Request the fd handler from the master process var message = { cmd: 'queryServer', address: address, port: port, addressType: addressType, fd: fd }; // The callback will be stored until the master has responded sendInternalMessage(cluster.worker, message, function(msg, handle) { cb(handle); }); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. function assertEncoding(encoding) { if (encoding && !Buffer.isEncoding(encoding)) { throw new Error('Unknown encoding: ' + encoding); } } var StringDecoder = exports.StringDecoder = function(encoding) { this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); assertEncoding(encoding); switch (this.encoding) { case 'utf8': // CESU-8 represents each of Surrogate Pair by 3-bytes this.surrogateSize = 3; break; case 'ucs2': case 'utf16le': // UTF-16 represents each of Surrogate Pair by 2-bytes this.surrogateSize = 2; this.detectIncompleteChar = utf16DetectIncompleteChar; break; case 'base64': // Base-64 stores 3 bytes in 4 chars, and pads the remainder. this.surrogateSize = 3; this.detectIncompleteChar = base64DetectIncompleteChar; break; default: this.write = passThroughWrite; return; } this.charBuffer = new Buffer(6); this.charReceived = 0; this.charLength = 0; }; StringDecoder.prototype.write = function(buffer) { var charStr = ''; var offset = 0; // if our last write ended with an incomplete multibyte character while (this.charLength) { // determine how many remaining bytes this buffer has to offer for this char var i = (buffer.length >= this.charLength - this.charReceived) ? this.charLength - this.charReceived : buffer.length; // add the new bytes to the char buffer buffer.copy(this.charBuffer, this.charReceived, offset, i); this.charReceived += (i - offset); offset = i; if (this.charReceived < this.charLength) { // still not enough chars in this buffer? wait for more ... return ''; } // get the character that was split charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); // lead surrogate (D800-DBFF) is also the incomplete character var charCode = charStr.charCodeAt(charStr.length - 1); if (charCode >= 0xD800 && charCode <= 0xDBFF) { this.charLength += this.surrogateSize; charStr = ''; continue; } this.charReceived = this.charLength = 0; // if there are no more bytes in this buffer, just emit our char if (i == buffer.length) return charStr; // otherwise cut off the characters end from the beginning of this buffer buffer = buffer.slice(i, buffer.length); break; } var lenIncomplete = this.detectIncompleteChar(buffer); var end = buffer.length; if (this.charLength) { // buffer the incomplete character bytes we got buffer.copy(this.charBuffer, 0, buffer.length - lenIncomplete, end); this.charReceived = lenIncomplete; end -= lenIncomplete; } charStr += buffer.toString(this.encoding, 0, end); var end = charStr.length - 1; var charCode = charStr.charCodeAt(end); // lead surrogate (D800-DBFF) is also the incomplete character if (charCode >= 0xD800 && charCode <= 0xDBFF) { var size = this.surrogateSize; this.charLength += size; this.charReceived += size; this.charBuffer.copy(this.charBuffer, size, 0, size); this.charBuffer.write(charStr.charAt(charStr.length - 1), this.encoding); return charStr.substring(0, end); } // or just emit the charStr return charStr; }; StringDecoder.prototype.detectIncompleteChar = function(buffer) { // determine how many bytes we have to check at the end of this buffer var i = (buffer.length >= 3) ? 3 : buffer.length; // Figure out if one of the last i bytes of our buffer announces an // incomplete char. for (; i > 0; i--) { var c = buffer[buffer.length - i]; // See http://en.wikipedia.org/wiki/UTF-8#Description // 110XXXXX if (i == 1 && c >> 5 == 0x06) { this.charLength = 2; break; } // 1110XXXX if (i <= 2 && c >> 4 == 0x0E) { this.charLength = 3; break; } // 11110XXX if (i <= 3 && c >> 3 == 0x1E) { this.charLength = 4; break; } } return i; }; StringDecoder.prototype.end = function(buffer) { var res = ''; if (buffer && buffer.length) res = this.write(buffer); if (this.charReceived) { var cr = this.charReceived; var buf = this.charBuffer; var enc = this.encoding; res += buf.slice(0, cr).toString(enc); } return res; }; function passThroughWrite(buffer) { return buffer.toString(this.encoding); } function utf16DetectIncompleteChar(buffer) { var incomplete = this.charReceived = buffer.length % 2; this.charLength = incomplete ? 2 : 0; return incomplete; } function base64DetectIncompleteChar(buffer) { var incomplete = this.charReceived = buffer.length % 3; this.charLength = incomplete ? 3 : 0; return incomplete; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a passthrough stream. // basically just the most minimal sort of Transform stream. // Every written chunk gets output as-is. module.exports = PassThrough; var Transform = require('_stream_transform'); var util = require('util'); util.inherits(PassThrough, Transform); function PassThrough(options) { if (!(this instanceof PassThrough)) return new PassThrough(options); Transform.call(this, options); } PassThrough.prototype._transform = function(chunk, encoding, cb) { cb(null, chunk); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This is a free list to avoid creating so many of the same object. exports.FreeList = function(name, max, constructor) { this.name = name; this.constructor = constructor; this.max = max; this.list = []; }; exports.FreeList.prototype.alloc = function() { //debug("alloc " + this.name + " " + this.list.length); return this.list.length ? this.list.shift() : this.constructor.apply(this, arguments); }; exports.FreeList.prototype.free = function(obj) { //debug("free " + this.name + " " + this.list.length); if (this.list.length < this.max) { this.list.push(obj); } }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var punycode = require('punycode'); exports.parse = urlParse; exports.resolve = urlResolve; exports.resolveObject = urlResolveObject; exports.format = urlFormat; exports.Url = Url; function Url() { this.protocol = null; this.slashes = null; this.auth = null; this.host = null; this.port = null; this.hostname = null; this.hash = null; this.search = null; this.query = null; this.pathname = null; this.path = null; this.href = null; } // Reference: RFC 3986, RFC 1808, RFC 2396 // define these here so at least they only have to be // compiled once on the first module load. var protocolPattern = /^([a-z0-9.+-]+:)/i, portPattern = /:[0-9]*$/, // RFC 2396: characters reserved for delimiting URLs. // We actually just auto-escape these. delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], // RFC 2396: characters not allowed for various reasons. unwise = ['{', '}', '|', '\\', '^', '~', '`'].concat(delims), // Allowed by RFCs, but cause of XSS attacks. Always escape these. autoEscape = ['\''].concat(delims), // Characters that are never ever allowed in a hostname. // Note that any invalid chars are also handled, but these // are the ones that are *expected* to be seen, so we fast-path // them. nonHostChars = ['%', '/', '?', ';', '#'] .concat(unwise).concat(autoEscape), hostEndingChars = ['/', '?', '#'], hostnameMaxLen = 255, hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, // protocols that can allow "unsafe" and "unwise" chars. unsafeProtocol = { 'javascript': true, 'javascript:': true }, // protocols that never have a hostname. hostlessProtocol = { 'javascript': true, 'javascript:': true }, // protocols that always contain a // bit. slashedProtocol = { 'http': true, 'https': true, 'ftp': true, 'gopher': true, 'file': true, 'http:': true, 'https:': true, 'ftp:': true, 'gopher:': true, 'file:': true }, querystring = require('querystring'); function urlParse(url, parseQueryString, slashesDenoteHost) { if (url && typeof(url) === 'object' && url instanceof Url) return url; var u = new Url; u.parse(url, parseQueryString, slashesDenoteHost); return u; } Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { if (typeof url !== 'string') { throw new TypeError("Parameter 'url' must be a string, not " + typeof url); } var rest = url; // trim before proceeding. // This is to support parse stuff like " http://foo.com \n" rest = rest.trim(); var proto = protocolPattern.exec(rest); if (proto) { proto = proto[0]; var lowerProto = proto.toLowerCase(); this.protocol = lowerProto; rest = rest.substr(proto.length); } // figure out if it's got a host // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { var slashes = rest.substr(0, 2) === '//'; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.substr(2); this.slashes = true; } } if (!hostlessProtocol[proto] && (slashes || (proto && !slashedProtocol[proto]))) { // there's a hostname. // the first instance of /, ?, ;, or # ends the host. // // If there is an @ in the hostname, then non-host chars *are* allowed // to the left of the last @ sign, unless some host-ending character // comes *before* the @-sign. // URLs are obnoxious. // // ex: // http://a@b@c/ => user:a@b host:c // http://a@b?@c => user:a host:c path:/?@c // v0.12 TODO(isaacs): This is not quite how Chrome does things. // Review our test case against browsers more comprehensively. // find the first instance of any hostEndingChars var hostEnd = -1; for (var i = 0; i < hostEndingChars.length; i++) { var hec = rest.indexOf(hostEndingChars[i]); if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec; } // at this point, either we have an explicit point where the // auth portion cannot go past, or the last @ char is the decider. var auth, atSign; if (hostEnd === -1) { // atSign can be anywhere. atSign = rest.lastIndexOf('@'); } else { // atSign must be in auth portion. // http://a@b/c@d => host:b auth:a path:/c@d atSign = rest.lastIndexOf('@', hostEnd); } // Now we have a portion which is definitely the auth. // Pull that off. if (atSign !== -1) { auth = rest.slice(0, atSign); rest = rest.slice(atSign + 1); this.auth = decodeURIComponent(auth); } // the host is the remaining to the left of the first non-host char hostEnd = -1; for (var i = 0; i < nonHostChars.length; i++) { var hec = rest.indexOf(nonHostChars[i]); if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) hostEnd = hec; } // if we still have not hit it, then the entire thing is a host. if (hostEnd === -1) hostEnd = rest.length; this.host = rest.slice(0, hostEnd); rest = rest.slice(hostEnd); // pull out port. this.parseHost(); // we've indicated that there is a hostname, // so even if it's empty, it has to be present. this.hostname = this.hostname || ''; // if hostname begins with [ and ends with ] // assume that it's an IPv6 address. var ipv6Hostname = this.hostname[0] === '[' && this.hostname[this.hostname.length - 1] === ']'; // validate a little. if (!ipv6Hostname) { var hostparts = this.hostname.split(/\./); for (var i = 0, l = hostparts.length; i < l; i++) { var part = hostparts[i]; if (!part) continue; if (!part.match(hostnamePartPattern)) { var newpart = ''; for (var j = 0, k = part.length; j < k; j++) { if (part.charCodeAt(j) > 127) { // we replace non-ASCII char with a temporary placeholder // we need this to make sure size of hostname is not // broken by replacing non-ASCII by nothing newpart += 'x'; } else { newpart += part[j]; } } // we test again with ASCII char only if (!newpart.match(hostnamePartPattern)) { var validParts = hostparts.slice(0, i); var notHost = hostparts.slice(i + 1); var bit = part.match(hostnamePartStart); if (bit) { validParts.push(bit[1]); notHost.unshift(bit[2]); } if (notHost.length) { rest = '/' + notHost.join('.') + rest; } this.hostname = validParts.join('.'); break; } } } } if (this.hostname.length > hostnameMaxLen) { this.hostname = ''; } else { // hostnames are always lower case. this.hostname = this.hostname.toLowerCase(); } if (!ipv6Hostname) { // IDNA Support: Returns a puny coded representation of "domain". // It only converts the part of the domain name that // has non ASCII characters. I.e. it dosent matter if // you call it with a domain that already is in ASCII. var domainArray = this.hostname.split('.'); var newOut = []; for (var i = 0; i < domainArray.length; ++i) { var s = domainArray[i]; newOut.push(s.match(/[^A-Za-z0-9_-]/) ? 'xn--' + punycode.encode(s) : s); } this.hostname = newOut.join('.'); } var p = this.port ? ':' + this.port : ''; var h = this.hostname || ''; this.host = h + p; this.href += this.host; // strip [ and ] from the hostname // the host field still retains them, though if (ipv6Hostname) { this.hostname = this.hostname.substr(1, this.hostname.length - 2); if (rest[0] !== '/') { rest = '/' + rest; } } } // now rest is set to the post-host stuff. // chop off any delim chars. if (!unsafeProtocol[lowerProto]) { // First, make 100% sure that any "autoEscape" chars get // escaped, even if encodeURIComponent doesn't think they // need to be. for (var i = 0, l = autoEscape.length; i < l; i++) { var ae = autoEscape[i]; var esc = encodeURIComponent(ae); if (esc === ae) { esc = escape(ae); } rest = rest.split(ae).join(esc); } } // chop off from the tail first. var hash = rest.indexOf('#'); if (hash !== -1) { // got a fragment string. this.hash = rest.substr(hash); rest = rest.slice(0, hash); } var qm = rest.indexOf('?'); if (qm !== -1) { this.search = rest.substr(qm); this.query = rest.substr(qm + 1); if (parseQueryString) { this.query = querystring.parse(this.query); } rest = rest.slice(0, qm); } else if (parseQueryString) { // no query string, but parseQueryString still requested this.search = ''; this.query = {}; } if (rest) this.pathname = rest; if (slashedProtocol[proto] && this.hostname && !this.pathname) { this.pathname = '/'; } //to support http.request if (this.pathname || this.search) { var p = this.pathname || ''; var s = this.search || ''; this.path = p + s; } // finally, reconstruct the href based on what has been validated. this.href = this.format(); return this; }; // format a parsed object into a url string function urlFormat(obj) { // ensure it's an object, and not a string url. // If it's an obj, this is a no-op. // this way, you can call url_format() on strings // to clean up potentially wonky urls. if (typeof(obj) === 'string') obj = urlParse(obj); if (!(obj instanceof Url)) return Url.prototype.format.call(obj); return obj.format(); } Url.prototype.format = function() { var auth = this.auth || ''; if (auth) { auth = encodeURIComponent(auth); auth = auth.replace(/%3A/i, ':'); auth += '@'; } var protocol = this.protocol || '', pathname = this.pathname || '', hash = this.hash || '', host = false, query = ''; if (this.host) { host = auth + this.host; } else if (this.hostname) { host = auth + (this.hostname.indexOf(':') === -1 ? this.hostname : '[' + this.hostname + ']'); if (this.port) { host += ':' + this.port; } } if (this.query && typeof this.query === 'object' && Object.keys(this.query).length) { query = querystring.stringify(this.query); } var search = this.search || (query && ('?' + query)) || ''; if (protocol && protocol.substr(-1) !== ':') protocol += ':'; // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. // unless they had them to begin with. if (this.slashes || (!protocol || slashedProtocol[protocol]) && host !== false) { host = '//' + (host || ''); if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; } else if (!host) { host = ''; } if (hash && hash.charAt(0) !== '#') hash = '#' + hash; if (search && search.charAt(0) !== '?') search = '?' + search; pathname = pathname.replace(/[?#]/g, function(match) { return encodeURIComponent(match); }); search = search.replace('#', '%23'); return protocol + host + pathname + search + hash; }; function urlResolve(source, relative) { return urlParse(source, false, true).resolve(relative); } Url.prototype.resolve = function(relative) { return this.resolveObject(urlParse(relative, false, true)).format(); }; function urlResolveObject(source, relative) { if (!source) return relative; return urlParse(source, false, true).resolveObject(relative); } Url.prototype.resolveObject = function(relative) { if (typeof relative === 'string') { var rel = new Url(); rel.parse(relative, false, true); relative = rel; } var result = new Url(); Object.keys(this).forEach(function(k) { result[k] = this[k]; }, this); // hash is always overridden, no matter what. // even href="" will remove it. result.hash = relative.hash; // if the relative url is empty, then there's nothing left to do here. if (relative.href === '') { result.href = result.format(); return result; } // hrefs like //foo/bar always cut to the protocol. if (relative.slashes && !relative.protocol) { // take everything except the protocol from relative Object.keys(relative).forEach(function(k) { if (k !== 'protocol') result[k] = relative[k]; }); //urlParse appends trailing / to urls like http://www.example.com if (slashedProtocol[result.protocol] && result.hostname && !result.pathname) { result.path = result.pathname = '/'; } result.href = result.format(); return result; } if (relative.protocol && relative.protocol !== result.protocol) { // if it's a known url protocol, then changing // the protocol does weird things // first, if it's not file:, then we MUST have a host, // and if there was a path // to begin with, then we MUST have a path. // if it is file:, then the host is dropped, // because that's known to be hostless. // anything else is assumed to be absolute. if (!slashedProtocol[relative.protocol]) { Object.keys(relative).forEach(function(k) { result[k] = relative[k]; }); result.href = result.format(); return result; } result.protocol = relative.protocol; if (!relative.host && !hostlessProtocol[relative.protocol]) { var relPath = (relative.pathname || '').split('/'); while (relPath.length && !(relative.host = relPath.shift())); if (!relative.host) relative.host = ''; if (!relative.hostname) relative.hostname = ''; if (relPath[0] !== '') relPath.unshift(''); if (relPath.length < 2) relPath.unshift(''); result.pathname = relPath.join('/'); } else { result.pathname = relative.pathname; } result.search = relative.search; result.query = relative.query; result.host = relative.host || ''; result.auth = relative.auth; result.hostname = relative.hostname || relative.host; result.port = relative.port; // to support http.request if (result.pathname || result.search) { var p = result.pathname || ''; var s = result.search || ''; result.path = p + s; } result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; } var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), isRelAbs = ( relative.host || relative.pathname && relative.pathname.charAt(0) === '/' ), mustEndAbs = (isRelAbs || isSourceAbs || (result.host && relative.pathname)), removeAllDots = mustEndAbs, srcPath = result.pathname && result.pathname.split('/') || [], relPath = relative.pathname && relative.pathname.split('/') || [], psychotic = result.protocol && !slashedProtocol[result.protocol]; // if the url is a non-slashed url, then relative // links like ../.. should be able // to crawl up to the hostname, as well. This is strange. // result.protocol has already been set by now. // Later on, put the first path part into the host field. if (psychotic) { result.hostname = ''; result.port = null; if (result.host) { if (srcPath[0] === '') srcPath[0] = result.host; else srcPath.unshift(result.host); } result.host = ''; if (relative.protocol) { relative.hostname = null; relative.port = null; if (relative.host) { if (relPath[0] === '') relPath[0] = relative.host; else relPath.unshift(relative.host); } relative.host = null; } mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); } if (isRelAbs) { // it's absolute. result.host = (relative.host || relative.host === '') ? relative.host : result.host; result.hostname = (relative.hostname || relative.hostname === '') ? relative.hostname : result.hostname; result.search = relative.search; result.query = relative.query; srcPath = relPath; // fall through to the dot-handling below. } else if (relPath.length) { // it's relative // throw away the existing file, and take the new path instead. if (!srcPath) srcPath = []; srcPath.pop(); srcPath = srcPath.concat(relPath); result.search = relative.search; result.query = relative.query; } else if (relative.search !== null && relative.search !== undefined) { // just pull out the search. // like href='?foo'. // Put this after the other two cases because it simplifies the booleans if (psychotic) { result.hostname = result.host = srcPath.shift(); //occationaly the auth can get stuck only in host //this especialy happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } result.search = relative.search; result.query = relative.query; //to support http.request if (result.pathname !== null || result.search !== null) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.href = result.format(); return result; } if (!srcPath.length) { // no path at all. easy. // we've already handled the other stuff above. result.pathname = null; //to support http.request if (result.search) { result.path = '/' + result.search; } else { result.path = null; } result.href = result.format(); return result; } // if a url ENDs in . or .., then it must get a trailing slash. // however, if it ends in anything else non-slashy, // then it must NOT get a trailing slash. var last = srcPath.slice(-1)[0]; var hasTrailingSlash = ( (result.host || relative.host) && (last === '.' || last === '..') || last === ''); // strip single dots, resolve double dots to parent dir // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = srcPath.length; i >= 0; i--) { last = srcPath[i]; if (last == '.') { srcPath.splice(i, 1); } else if (last === '..') { srcPath.splice(i, 1); up++; } else if (up) { srcPath.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (!mustEndAbs && !removeAllDots) { for (; up--; up) { srcPath.unshift('..'); } } if (mustEndAbs && srcPath[0] !== '' && (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { srcPath.unshift(''); } if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { srcPath.push(''); } var isAbsolute = srcPath[0] === '' || (srcPath[0] && srcPath[0].charAt(0) === '/'); // put the host back if (psychotic) { result.hostname = result.host = isAbsolute ? '' : srcPath.length ? srcPath.shift() : ''; //occationaly the auth can get stuck only in host //this especialy happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? result.host.split('@') : false; if (authInHost) { result.auth = authInHost.shift(); result.host = result.hostname = authInHost.shift(); } } mustEndAbs = mustEndAbs || (result.host && srcPath.length); if (mustEndAbs && !isAbsolute) { srcPath.unshift(''); } if (!srcPath.length) { result.pathname = null; result.path = null; } else { result.pathname = srcPath.join('/'); } //to support request.http if (result.pathname !== null || result.search !== null) { result.path = (result.pathname ? result.pathname : '') + (result.search ? result.search : ''); } result.auth = relative.auth || result.auth; result.slashes = result.slashes || relative.slashes; result.href = result.format(); return result; }; Url.prototype.parseHost = function() { var host = this.host; var port = portPattern.exec(host); if (port) { port = port[0]; if (port !== ':') { this.port = port.substr(1); } host = host.substr(0, host.length - port.length); } if (host) this.hostname = host; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. function init(list) { list._idleNext = list; list._idlePrev = list; } exports.init = init; // show the most idle item function peek(list) { if (list._idlePrev == list) return null; return list._idlePrev; } exports.peek = peek; // remove the most idle item from the list function shift(list) { var first = list._idlePrev; remove(first); return first; } exports.shift = shift; // remove a item from its list function remove(item) { if (item._idleNext) { item._idleNext._idlePrev = item._idlePrev; } if (item._idlePrev) { item._idlePrev._idleNext = item._idleNext; } item._idleNext = null; item._idlePrev = null; } exports.remove = remove; // remove a item from its list and place at the end. function append(list, item) { remove(item); item._idleNext = list._idleNext; list._idleNext._idlePrev = item; item._idlePrev = list; list._idleNext = item; } exports.append = append; function isEmpty(list) { return list._idleNext === list; } exports.isEmpty = isEmpty; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'), path = require('path'), net = require('net'), vm = require('vm'), repl = require('repl'), inherits = util.inherits, spawn = require('child_process').spawn; exports.start = function(argv, stdin, stdout) { argv || (argv = process.argv.slice(2)); if (argv.length < 1) { console.error('Usage: node debug script.js'); process.exit(1); } // Setup input/output streams stdin = stdin || process.stdin; stdout = stdout || process.stdout; var args = ['--debug-brk'].concat(argv), interface_ = new Interface(stdin, stdout, args); stdin.resume(); process.on('uncaughtException', function(e) { console.error("There was an internal error in Node's debugger. " + 'Please report this bug.'); console.error(e.message); console.error(e.stack); if (interface_.child) interface_.child.kill(); process.exit(1); }); }; exports.port = 5858; // // Parser/Serializer for V8 debugger protocol // http://code.google.com/p/v8/wiki/DebuggerProtocol // // Usage: // p = new Protocol(); // // p.onResponse = function(res) { // // do stuff with response from V8 // }; // // socket.setEncoding('utf8'); // socket.on('data', function(s) { // // Pass strings into the protocol // p.execute(s); // }); // // function Protocol() { this._newRes(); } exports.Protocol = Protocol; Protocol.prototype._newRes = function(raw) { this.res = { raw: raw || '', headers: {} }; this.state = 'headers'; this.reqSeq = 1; this.execute(''); }; Protocol.prototype.execute = function(d) { var res = this.res; res.raw += d; switch (this.state) { case 'headers': var endHeaderIndex = res.raw.indexOf('\r\n\r\n'); if (endHeaderIndex < 0) break; var rawHeader = res.raw.slice(0, endHeaderIndex); var endHeaderByteIndex = Buffer.byteLength(rawHeader, 'utf8'); var lines = rawHeader.split('\r\n'); for (var i = 0; i < lines.length; i++) { var kv = lines[i].split(/: +/); res.headers[kv[0]] = kv[1]; } this.contentLength = +res.headers['Content-Length']; this.bodyStartByteIndex = endHeaderByteIndex + 4; this.state = 'body'; var len = Buffer.byteLength(res.raw, 'utf8'); if (len - this.bodyStartByteIndex < this.contentLength) { break; } // pass thru case 'body': var resRawByteLength = Buffer.byteLength(res.raw, 'utf8'); if (resRawByteLength - this.bodyStartByteIndex >= this.contentLength) { var buf = new Buffer(resRawByteLength); buf.write(res.raw, 0, resRawByteLength, 'utf8'); res.body = buf.slice(this.bodyStartByteIndex, this.bodyStartByteIndex + this.contentLength).toString('utf8'); // JSON parse body? res.body = res.body.length ? JSON.parse(res.body) : {}; // Done! this.onResponse(res); this._newRes(buf.slice(this.bodyStartByteIndex + this.contentLength).toString('utf8')); } break; default: throw new Error('Unknown state'); break; } }; Protocol.prototype.serialize = function(req) { req.type = 'request'; req.seq = this.reqSeq++; var json = JSON.stringify(req); return 'Content-Length: ' + Buffer.byteLength(json, 'utf8') + '\r\n\r\n' + json; }; var NO_FRAME = -1; function Client() { net.Stream.call(this); var protocol = this.protocol = new Protocol(this); this._reqCallbacks = []; var socket = this; this.currentFrame = NO_FRAME; this.currentSourceLine = -1; this.currentSource = null; this.handles = {}; this.scripts = {}; this.breakpoints = []; // Note that 'Protocol' requires strings instead of Buffers. socket.setEncoding('utf8'); socket.on('data', function(d) { protocol.execute(d); }); protocol.onResponse = this._onResponse.bind(this); } inherits(Client, net.Stream); exports.Client = Client; Client.prototype._addHandle = function(desc) { if (typeof desc != 'object' || typeof desc.handle != 'number') { return; } this.handles[desc.handle] = desc; if (desc.type == 'script') { this._addScript(desc); } }; var natives = process.binding('natives'); Client.prototype._addScript = function(desc) { this.scripts[desc.id] = desc; if (desc.name) { desc.isNative = (desc.name.replace('.js', '') in natives) || desc.name == 'node.js'; } }; Client.prototype._removeScript = function(desc) { this.scripts[desc.id] = undefined; }; Client.prototype._onResponse = function(res) { var cb, index = -1; this._reqCallbacks.some(function(fn, i) { if (fn.request_seq == res.body.request_seq) { cb = fn; index = i; return true; } }); var self = this; var handled = false; if (res.headers.Type == 'connect') { // Request a list of scripts for our own storage. self.reqScripts(); self.emit('ready'); handled = true; } else if (res.body && res.body.event == 'break') { this.emit('break', res.body); handled = true; } else if (res.body && res.body.event == 'exception') { this.emit('exception', res.body); handled = true; } else if (res.body && res.body.event == 'afterCompile') { this._addHandle(res.body.body.script); handled = true; } else if (res.body && res.body.event == 'scriptCollected') { // ??? this._removeScript(res.body.body.script); handled = true; } if (cb) { this._reqCallbacks.splice(index, 1); handled = true; var err = res.success === false && (res.message || true) || res.body.success === false && (res.body.message || true); cb(err, res.body && res.body.body || res.body, res); } if (!handled) this.emit('unhandledResponse', res.body); }; Client.prototype.req = function(req, cb) { this.write(this.protocol.serialize(req)); cb.request_seq = req.seq; this._reqCallbacks.push(cb); }; Client.prototype.reqVersion = function(cb) { cb = cb || function() {}; this.req({ command: 'version' } , function(err, body, res) { if (err) return cb(err); cb(null, res.body.body.V8Version, res.body.running); }); }; Client.prototype.reqLookup = function(refs, cb) { var self = this; // TODO: We have a cache of handle's we've already seen in this.handles // This can be used if we're careful. var req = { command: 'lookup', arguments: { handles: refs } }; cb = cb || function() {}; this.req(req, function(err, res) { if (err) return cb(err); for (var ref in res) { if (typeof res[ref] == 'object') { self._addHandle(res[ref]); } } cb(null, res); }); }; Client.prototype.reqScopes = function(cb) { var self = this, req = { command: 'scopes', arguments: {} }; cb = cb || function() {}; this.req(req, function(err, res) { if (err) return cb(err); var refs = res.scopes.map(function(scope) { return scope.object.ref; }); self.reqLookup(refs, function(err, res) { if (err) return cb(err); var globals = Object.keys(res).map(function(key) { return res[key].properties.map(function(prop) { return prop.name; }); }); cb(null, globals.reverse()); }); }); }; // This is like reqEval, except it will look up the expression in each of the // scopes associated with the current frame. Client.prototype.reqEval = function(expression, cb) { var self = this; if (this.currentFrame == NO_FRAME) { // Only need to eval in global scope. this.reqFrameEval(expression, NO_FRAME, cb); return; } cb = cb || function() {}; // Otherwise we need to get the current frame to see which scopes it has. this.reqBacktrace(function(err, bt) { if (err || !bt.frames) { // ?? return cb(null, {}); } var frame = bt.frames[self.currentFrame]; var evalFrames = frame.scopes.map(function(s) { if (!s) return; var x = bt.frames[s.index]; if (!x) return; return x.index; }); self._reqFramesEval(expression, evalFrames, cb); }); }; // Finds the first scope in the array in which the epxression evals. Client.prototype._reqFramesEval = function(expression, evalFrames, cb) { if (evalFrames.length == 0) { // Just eval in global scope. this.reqFrameEval(expression, NO_FRAME, cb); return; } var self = this; var i = evalFrames.shift(); cb = cb || function() {}; this.reqFrameEval(expression, i, function(err, res) { if (!err) return cb(null, res); self._reqFramesEval(expression, evalFrames, cb); }); }; Client.prototype.reqFrameEval = function(expression, frame, cb) { var self = this; var req = { command: 'evaluate', arguments: { expression: expression } }; if (frame == NO_FRAME) { req.arguments.global = true; } else { req.arguments.frame = frame; } cb = cb || function() {}; this.req(req, function(err, res) { if (!err) self._addHandle(res); cb(err, res); }); }; // reqBacktrace(cb) // TODO: from, to, bottom Client.prototype.reqBacktrace = function(cb) { this.req({ command: 'backtrace', arguments: { inlineRefs: true } } , cb); }; // reqSetExceptionBreak(type, cb) // TODO: from, to, bottom Client.prototype.reqSetExceptionBreak = function(type, cb) { this.req({ command: 'setexceptionbreak', arguments: { type: type, enabled: true } }, cb); }; // Returns an array of objects like this: // // { handle: 11, // type: 'script', // name: 'node.js', // id: 14, // lineOffset: 0, // columnOffset: 0, // lineCount: 562, // sourceStart: '(function(process) {\n\n ', // sourceLength: 15939, // scriptType: 2, // compilationType: 0, // context: { ref: 10 }, // text: 'node.js (lines: 562)' } // Client.prototype.reqScripts = function(cb) { var self = this; cb = cb || function() {}; this.req({ command: 'scripts' } , function(err, res) { if (err) return cb(err); for (var i = 0; i < res.length; i++) { self._addHandle(res[i]); } cb(null); }); }; Client.prototype.reqContinue = function(cb) { this.currentFrame = NO_FRAME; this.req({ command: 'continue' }, cb); }; Client.prototype.listbreakpoints = function(cb) { this.req({ command: 'listbreakpoints' }, cb); }; Client.prototype.setBreakpoint = function(req, cb) { req = { command: 'setbreakpoint', arguments: req }; this.req(req, cb); }; Client.prototype.clearBreakpoint = function(req, cb) { var req = { command: 'clearbreakpoint', arguments: req }; this.req(req, cb); }; Client.prototype.reqSource = function(from, to, cb) { var req = { command: 'source', fromLine: from, toLine: to }; this.req(req, cb); }; // client.next(1, cb); Client.prototype.step = function(action, count, cb) { var req = { command: 'continue', arguments: { stepaction: action, stepcount: count } }; this.currentFrame = NO_FRAME; this.req(req, cb); }; Client.prototype.mirrorObject = function(handle, depth, cb) { var self = this; var val; if (handle.type === 'object') { // The handle looks something like this: // { handle: 8, // type: 'object', // className: 'Object', // constructorFunction: { ref: 9 }, // protoObject: { ref: 4 }, // prototypeObject: { ref: 2 }, // properties: [ { name: 'hello', propertyType: 1, ref: 10 } ], // text: '#' } // For now ignore the className and constructor and prototype. // TJ's method of object inspection would probably be good for this: // https://groups.google.com/forum/?pli=1#!topic/nodejs-dev/4gkWBOimiOg var propertyRefs = handle.properties.map(function(p) { return p.ref; }); cb = cb || function() {}; this.reqLookup(propertyRefs, function(err, res) { if (err) { console.error('problem with reqLookup'); cb(null, handle); return; } var mirror, waiting = 1; if (handle.className == 'Array') { mirror = []; } else if (handle.className == 'Date') { mirror = new Date(handle.value); } else { mirror = {}; } var keyValues = []; handle.properties.forEach(function(prop, i) { var value = res[prop.ref]; var mirrorValue; if (value) { mirrorValue = value.value ? value.value : value.text; } else { mirrorValue = '[?]'; } if (Array.isArray(mirror) && typeof prop.name != 'number') { // Skip the 'length' property. return; } keyValues[i] = { name: prop.name, value: mirrorValue }; if (value && value.handle && depth > 0) { waiting++; self.mirrorObject(value, depth - 1, function(err, result) { if (!err) keyValues[i].value = result; waitForOthers(); }); } }); waitForOthers(); function waitForOthers() { if (--waiting === 0 && cb) { keyValues.forEach(function(kv) { mirror[kv.name] = kv.value; }); cb(null, mirror); } }; }); return; } else if (handle.type === 'function') { val = function() {}; } else if (handle.type === 'null') { val = null; } else if (handle.value !== undefined) { val = handle.value; } else if (handle.type === 'undefined') { val = undefined; } else { val = handle; } process.nextTick(function() { cb(null, val); }); }; Client.prototype.fullTrace = function(cb) { var self = this; cb = cb || function() {}; this.reqBacktrace(function(err, trace) { if (err) return cb(err); if (trace.totalFrames <= 0) return cb(Error('No frames')); var refs = []; for (var i = 0; i < trace.frames.length; i++) { var frame = trace.frames[i]; // looks like this: // { type: 'frame', // index: 0, // receiver: { ref: 1 }, // func: { ref: 0 }, // script: { ref: 7 }, // constructCall: false, // atReturn: false, // debuggerFrame: false, // arguments: [], // locals: [], // position: 160, // line: 7, // column: 2, // sourceLineText: ' debugger;', // scopes: [ { type: 1, index: 0 }, { type: 0, index: 1 } ], // text: '#00 blah() /home/ryan/projects/node/test-debug.js l...' } refs.push(frame.script.ref); refs.push(frame.func.ref); refs.push(frame.receiver.ref); } self.reqLookup(refs, function(err, res) { if (err) return cb(err); for (var i = 0; i < trace.frames.length; i++) { var frame = trace.frames[i]; frame.script = res[frame.script.ref]; frame.func = res[frame.func.ref]; frame.receiver = res[frame.receiver.ref]; } cb(null, trace); }); }); }; var commands = [ [ 'run (r)', 'cont (c)', 'next (n)', 'step (s)', 'out (o)', 'backtrace (bt)', 'setBreakpoint (sb)', 'clearBreakpoint (cb)' ], [ 'watch', 'unwatch', 'watchers', 'repl', 'restart', 'kill', 'list', 'scripts', 'breakOnException', 'breakpoints', 'version' ] ]; var helpMessage = 'Commands: ' + commands.map(function(group) { return group.join(', '); }).join(',\n'); function SourceUnderline(sourceText, position, repl) { if (!sourceText) return ''; var head = sourceText.slice(0, position), tail = sourceText.slice(position); // Colourize char if stdout supports colours if (repl.useColors) { tail = tail.replace(/(.+?)([^\w]|$)/, '\u001b[32m$1\u001b[39m$2'); } // Return source line with coloured char at `position` return [ head, tail ].join(''); } function SourceInfo(body) { var result = body.exception ? 'exception in ' : 'break in '; if (body.script) { if (body.script.name) { var name = body.script.name, dir = path.resolve() + '/'; // Change path to relative, if possible if (name.indexOf(dir) === 0) { name = name.slice(dir.length); } result += name; } else { result += '[unnamed]'; } } result += ':'; result += body.sourceLine + 1; if (body.exception) result += '\n' + body.exception.text; return result; } // This class is the repl-enabled debugger interface which is invoked on // "node debug" function Interface(stdin, stdout, args) { var self = this, child; this.stdin = stdin; this.stdout = stdout; this.args = args; // Two eval modes are available: controlEval and debugEval // But controlEval is used by default var opts = { prompt: 'debug> ', input: this.stdin, output: this.stdout, eval: this.controlEval.bind(this), useGlobal: false, ignoreUndefined: true }; if (parseInt(process.env['NODE_NO_READLINE'], 10)) { opts.terminal = false; } else if (parseInt(process.env['NODE_FORCE_READLINE'], 10)) { opts.terminal = true; // Emulate Ctrl+C if we're emulating terminal if (!this.stdout.isTTY) { process.on('SIGINT', function() { self.repl.rli.emit('SIGINT'); }); } } if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { opts.useColors = false; } this.repl = repl.start(opts); // Do not print useless warning repl._builtinLibs.splice(repl._builtinLibs.indexOf('repl'), 1); // Kill child process when main process dies this.repl.on('exit', function() { process.exit(0); }); // Handle all possible exits process.on('exit', this.killChild.bind(this)); process.once('SIGTERM', process.exit.bind(process, 0)); process.once('SIGHUP', process.exit.bind(process, 0)); var proto = Interface.prototype, ignored = ['pause', 'resume', 'exitRepl', 'handleBreak', 'requireConnection', 'killChild', 'trySpawn', 'controlEval', 'debugEval', 'print', 'childPrint', 'clearline'], shortcut = { 'run': 'r', 'cont': 'c', 'next': 'n', 'step': 's', 'out': 'o', 'backtrace': 'bt', 'setBreakpoint': 'sb', 'clearBreakpoint': 'cb', 'pause_': 'pause' }; function defineProperty(key, protoKey) { // Check arity var fn = proto[protoKey].bind(self); if (proto[protoKey].length === 0) { Object.defineProperty(self.repl.context, key, { get: fn, enumerable: true, configurable: false }); } else { self.repl.context[key] = fn; } }; // Copy all prototype methods in repl context // Setup them as getters if possible for (var i in proto) { if (Object.prototype.hasOwnProperty.call(proto, i) && ignored.indexOf(i) === -1) { defineProperty(i, i); if (shortcut[i]) defineProperty(shortcut[i], i); } } this.killed = false; this.waiting = null; this.paused = 0; this.context = this.repl.context; this.history = { debug: [], control: [] }; this.breakpoints = []; this._watchers = []; // Run script automatically this.pause(); // XXX Need to figure out why we need this delay setTimeout(function() { self.run(function() { self.resume(); }); }, 10); } // Stream control Interface.prototype.pause = function() { if (this.killed || this.paused++ > 0) return false; this.repl.rli.pause(); this.stdin.pause(); }; Interface.prototype.resume = function(silent) { if (this.killed || this.paused === 0 || --this.paused !== 0) return false; this.repl.rli.resume(); if (silent !== true) { this.repl.displayPrompt(); } this.stdin.resume(); if (this.waiting) { this.waiting(); this.waiting = null; } }; // Clear current line Interface.prototype.clearline = function() { if (this.stdout.isTTY) { this.stdout.cursorTo(0); this.stdout.clearLine(1); } else { this.stdout.write('\b'); } }; // Print text to output stream Interface.prototype.print = function(text, oneline) { if (this.killed) return; this.clearline(); this.stdout.write(typeof text === 'string' ? text : util.inspect(text)); if (oneline !== true) { this.stdout.write('\n'); } }; // Format and print text from child process Interface.prototype.childPrint = function(text) { this.print(text.toString().split(/\r\n|\r|\n/g).filter(function(chunk) { return chunk; }).map(function(chunk) { return '< ' + chunk; }).join('\n')); this.repl.displayPrompt(true); }; // Errors formatting Interface.prototype.error = function(text) { this.print(text); this.resume(); }; // Debugger's `break` event handler Interface.prototype.handleBreak = function(r) { var self = this; this.pause(); // Save execution context's data this.client.currentSourceLine = r.sourceLine; this.client.currentSourceLineText = r.sourceLineText; this.client.currentSourceColumn = r.sourceColumn; this.client.currentFrame = 0; this.client.currentScript = r.script && r.script.name; // Print break data this.print(SourceInfo(r)); // Show watchers' values this.watchers(true, function(err) { if (err) return self.error(err); // And list source self.list(2); self.resume(true); }); }; // Internal method for checking connection state Interface.prototype.requireConnection = function() { if (!this.client) { this.error('App isn\'t running... Try `run` instead'); return false; } return true; }; // Evals // Used for debugger's commands evaluation and execution Interface.prototype.controlEval = function(code, context, filename, callback) { try { // Repeat last command if empty line are going to be evaluated if (this.repl.rli.history && this.repl.rli.history.length > 0) { if (code === '(\n)') { code = '(' + this.repl.rli.history[0] + '\n)'; } } var result = vm.runInContext(code, context, filename); // Repl should not ask for next command // if current one was asynchronous. if (this.paused === 0) return callback(null, result); // Add a callback for asynchronous command // (it will be automatically invoked by .resume() method this.waiting = function() { callback(null, result); }; } catch (e) { callback(e); } }; // Used for debugger's remote evaluation (`repl`) commands Interface.prototype.debugEval = function(code, context, filename, callback) { if (!this.requireConnection()) return; var self = this, client = this.client; // Repl asked for scope variables if (code === '.scope') { client.reqScopes(callback); return; } var frame = client.currentFrame === NO_FRAME ? frame : undefined; self.pause(); // Request remote evaluation globally or in current frame client.reqFrameEval(code, frame, function(err, res) { if (err) { callback(err); self.resume(true); return; } // Request object by handles (and it's sub-properties) client.mirrorObject(res, 3, function(err, mirror) { callback(null, mirror); self.resume(true); }); }); }; // Utils // Returns number of digits (+1) function intChars(n) { // TODO dumb: if (n < 50) { return 3; } else if (n < 950) { return 4; } else if (n < 9950) { return 5; } else { return 6; } } // Adds spaces and prefix to number function leftPad(n, prefix) { var s = n.toString(), nchars = intChars(n), nspaces = nchars - s.length - 1; prefix || (prefix = ' '); for (var i = 0; i < nspaces; i++) { prefix += ' '; } return prefix + s; } // Commands // Print help message Interface.prototype.help = function() { this.print(helpMessage); }; // Run script Interface.prototype.run = function() { var callback = arguments[0]; if (this.child) { this.error('App is already running... Try `restart` instead'); callback && callback(true); } else { this.trySpawn(callback); } }; // Restart script Interface.prototype.restart = function() { if (!this.requireConnection()) return; var self = this; self.pause(); self.killChild(); // XXX need to wait a little bit for the restart to work? setTimeout(function() { self.trySpawn(); self.resume(); }, 1000); }; // Print version Interface.prototype.version = function() { if (!this.requireConnection()) return; var self = this; this.pause(); this.client.reqVersion(function(err, v) { if (err) { self.error(err); } else { self.print(v); } self.resume(); }); }; // List source code Interface.prototype.list = function(delta) { if (!this.requireConnection()) return; delta || (delta = 5); var self = this, client = this.client, from = client.currentSourceLine - delta + 1, to = client.currentSourceLine + delta + 1; self.pause(); client.reqSource(from, to, function(err, res) { if (err || !res) { self.error('You can\'t list source code right now'); self.resume(); return; } var lines = res.source.split('\n'); for (var i = 0; i < lines.length; i++) { var lineno = res.fromLine + i + 1; if (lineno < from || lineno > to) continue; var current = lineno == 1 + client.currentSourceLine, breakpoint = client.breakpoints.some(function(bp) { return bp.script === client.currentScript && bp.line == lineno; }); if (lineno == 1) { // The first line needs to have the module wrapper filtered out of // it. var wrapper = require('module').wrapper[0]; lines[i] = lines[i].slice(wrapper.length); client.currentSourceColumn -= wrapper.length; } // Highlight executing statement var line; if (current) { line = SourceUnderline(lines[i], client.currentSourceColumn, self.repl); } else { line = lines[i]; } self.print(leftPad(lineno, breakpoint && '*') + ' ' + line); } self.resume(); }); }; // Print backtrace Interface.prototype.backtrace = function() { if (!this.requireConnection()) return; var self = this, client = this.client; self.pause(); client.fullTrace(function(err, bt) { if (err) { self.error('Can\'t request backtrace now'); self.resume(); return; } if (bt.totalFrames == 0) { self.print('(empty stack)'); } else { var trace = [], firstFrameNative = bt.frames[0].script.isNative; for (var i = 0; i < bt.frames.length; i++) { var frame = bt.frames[i]; if (!firstFrameNative && frame.script.isNative) break; var text = '#' + i + ' '; if (frame.func.inferredName && frame.func.inferredName.length > 0) { text += frame.func.inferredName + ' '; } text += path.basename(frame.script.name) + ':'; text += (frame.line + 1) + ':' + (frame.column + 1); trace.push(text); } self.print(trace.join('\n')); } self.resume(); }); }; // First argument tells if it should display internal node scripts or not // (available only for internal debugger's functions) Interface.prototype.scripts = function() { if (!this.requireConnection()) return; var client = this.client, displayNatives = arguments[0] || false, scripts = []; this.pause(); for (var id in client.scripts) { var script = client.scripts[id]; if (typeof script == 'object' && script.name) { if (displayNatives || script.name == client.currentScript || !script.isNative) { scripts.push( (script.name == client.currentScript ? '* ' : ' ') + id + ': ' + path.basename(script.name) ); } } } this.print(scripts.join('\n')); this.resume(); }; // Continue execution of script Interface.prototype.cont = function() { if (!this.requireConnection()) return; this.pause(); var self = this; this.client.reqContinue(function(err) { if (err) self.error(err); self.resume(); }); }; // Step commands generator Interface.stepGenerator = function(type, count) { return function() { if (!this.requireConnection()) return; var self = this; self.pause(); self.client.step(type, count, function(err, res) { if (err) self.error(err); self.resume(); }); }; }; // Jump to next command Interface.prototype.next = Interface.stepGenerator('next', 1); // Step in Interface.prototype.step = Interface.stepGenerator('in', 1); // Step out Interface.prototype.out = Interface.stepGenerator('out', 1); // Watch Interface.prototype.watch = function(expr) { this._watchers.push(expr); }; // Unwatch Interface.prototype.unwatch = function(expr) { var index = this._watchers.indexOf(expr); // Unwatch by expression // or // Unwatch by watcher number this._watchers.splice(index !== -1 ? index : +expr, 1); }; // List watchers Interface.prototype.watchers = function() { var self = this, verbose = arguments[0] || false, callback = arguments[1] || function() {}, waiting = this._watchers.length, values = []; this.pause(); if (!waiting) { this.resume(); return callback(); } this._watchers.forEach(function(watcher, i) { self.debugEval(watcher, null, null, function(err, value) { values[i] = err ? '' : value; wait(); }); }); function wait() { if (--waiting === 0) { if (verbose) self.print('Watchers:'); self._watchers.forEach(function(watcher, i) { self.print(leftPad(i, ' ') + ': ' + watcher + ' = ' + JSON.stringify(values[i])); }); if (verbose) self.print(''); self.resume(); callback(null); } } }; // Break on exception Interface.prototype.breakOnException = function breakOnException() { if (!this.requireConnection()) return; var self = this; // Break on exceptions this.pause(); this.client.reqSetExceptionBreak('all', function(err, res) { self.resume(); }); }; // Add breakpoint Interface.prototype.setBreakpoint = function(script, line, condition, silent) { if (!this.requireConnection()) return; var self = this, scriptId, ambiguous; // setBreakpoint() should insert breakpoint on current line if (script === undefined) { script = this.client.currentScript; line = this.client.currentSourceLine + 1; } // setBreakpoint(line-number) should insert breakpoint in current script if (line === undefined && typeof script === 'number') { line = script; script = this.client.currentScript; } if (/\(\)$/.test(script)) { // setBreakpoint('functionname()'); var req = { type: 'function', target: script.replace(/\(\)$/, ''), condition: condition }; } else { // setBreakpoint('scriptname') if (script != +script && !this.client.scripts[script]) { var scripts = this.client.scripts; Object.keys(scripts).forEach(function(id) { if (scripts[id] && scripts[id].name.indexOf(script) !== -1) { if (scriptId) { ambiguous = true; } scriptId = id; } }); } else { scriptId = script; } if (ambiguous) return this.error('Script name is ambiguous'); if (line <= 0) return this.error('Line should be a positive value'); var req; if (scriptId) { req = { type: 'scriptId', target: scriptId, line: line - 1, condition: condition }; } else { this.print('Warning: script \'' + script + '\' was not loaded yet.'); var escapedPath = script.replace(/([/\\.?*()^${}|[\]])/g, '\\$1'); var scriptPathRegex = '^(.*[\\/\\\\])?' + escapedPath + '$'; req = { type: 'scriptRegExp', target: scriptPathRegex, line: line - 1, condition: condition }; } } self.pause(); self.client.setBreakpoint(req, function(err, res) { if (err) { if (!silent) { self.error(err); } } else { if (!silent) { self.list(5); } // Try load scriptId and line from response if (!scriptId) { scriptId = res.script_id; line = res.line + 1; } // Remember this breakpoint even if scriptId is not resolved yet self.client.breakpoints.push({ id: res.breakpoint, scriptId: scriptId, script: (self.client.scripts[scriptId] || {}).name, line: line, condition: condition, scriptReq: script }); } self.resume(); }); }; // Clear breakpoint Interface.prototype.clearBreakpoint = function(script, line) { if (!this.requireConnection()) return; var ambiguous, breakpoint, index; this.client.breakpoints.some(function(bp, i) { if (bp.scriptId === script || bp.scriptReq === script || (bp.script && bp.script.indexOf(script) !== -1)) { if (index !== undefined) { ambiguous = true; } if (bp.line === line) { index = i; breakpoint = bp.id; return true; } } }); if (ambiguous) return this.error('Script name is ambiguous'); if (breakpoint === undefined) { return this.error('Script : ' + script + ' not found'); } var self = this, req = { breakpoint: breakpoint }; self.pause(); self.client.clearBreakpoint(req, function(err, res) { if (err) { self.error(err); } else { self.client.breakpoints.splice(index, 1); self.list(5); } self.resume(); }); }; // Show breakpoints Interface.prototype.breakpoints = function() { if (!this.requireConnection()) return; this.pause(); var self = this; this.client.listbreakpoints(function(err, res) { if (err) { self.error(err); } else { self.print(res); self.resume(); } }); }; // Pause child process Interface.prototype.pause_ = function() { if (!this.requireConnection()) return; var self = this, cmd = 'process._debugPause();'; this.pause(); this.client.reqFrameEval(cmd, NO_FRAME, function(err, res) { if (err) { self.error(err); } else { self.resume(); } }); }; // Kill child process Interface.prototype.kill = function() { if (!this.child) return; this.killChild(); }; // Activate debug repl Interface.prototype.repl = function() { if (!this.requireConnection()) return; var self = this; self.print('Press Ctrl + C to leave debug repl'); // Don't display any default messages var listeners = this.repl.rli.listeners('SIGINT').slice(0); this.repl.rli.removeAllListeners('SIGINT'); // Exit debug repl on Ctrl + C this.repl.rli.once('SIGINT', function() { // Restore all listeners process.nextTick(function() { listeners.forEach(function(listener) { self.repl.rli.on('SIGINT', listener); }); }); // Exit debug repl self.exitRepl(); }); // Set new this.repl.eval = this.debugEval.bind(this); this.repl.context = {}; // Swap history this.history.control = this.repl.rli.history; this.repl.rli.history = this.history.debug; this.repl.prompt = '> '; this.repl.rli.setPrompt('> '); this.repl.displayPrompt(); }; // Exit debug repl Interface.prototype.exitRepl = function() { // Restore eval this.repl.eval = this.controlEval.bind(this); // Swap history this.history.debug = this.repl.rli.history; this.repl.rli.history = this.history.control; this.repl.context = this.context; this.repl.prompt = 'debug> '; this.repl.rli.setPrompt('debug> '); this.repl.displayPrompt(); }; // Quit Interface.prototype.quit = function() { this.killChild(); process.exit(0); }; // Kills child process Interface.prototype.killChild = function() { if (this.child) { this.child.kill(); this.child = null; } if (this.client) { // Save breakpoints this.breakpoints = this.client.breakpoints; this.client.destroy(); this.client = null; } }; // Spawns child process (and restores breakpoints) Interface.prototype.trySpawn = function(cb) { var self = this, breakpoints = this.breakpoints || [], port = exports.port, host = 'localhost', childArgs = this.args; this.killChild(); if (this.args.length === 2) { var match = this.args[1].match(/^([^:]+):(\d+)$/); if (match) { // Connecting to remote debugger // `node debug localhost:5858` host = match[1]; port = parseInt(match[2], 10); this.child = { kill: function() { // TODO Do we really need to handle it? } }; } } else if (this.args.length === 3) { // `node debug -p pid` if (this.args[1] === '-p' && /^\d+$/.test(this.args[2])) { this.child = { kill: function() { // TODO Do we really need to handle it? } }; process._debugProcess(parseInt(this.args[2], 10)); } else { var match = this.args[1].match(/^--port=(\d+)$/); if (match) { // Start debugger on custom port // `node debug --port=5858 app.js` port = parseInt(match[1], 10); childArgs = ['--debug-brk=' + port].concat(this.args.slice(2)); } } } if (!this.child) { this.child = spawn(process.execPath, childArgs); this.child.stdout.on('data', this.childPrint.bind(this)); this.child.stderr.on('data', this.childPrint.bind(this)); } this.pause(); var client = self.client = new Client(), connectionAttempts = 0; client.once('ready', function() { self.stdout.write(' ok\n'); // Restore breakpoints breakpoints.forEach(function(bp) { self.print('Restoring breakpoint ' + bp.scriptReq + ':' + bp.line); self.setBreakpoint(bp.scriptReq, bp.line, bp.condition, true); }); client.on('close', function() { self.pause(); self.print('program terminated'); self.resume(); self.client = null; self.killChild(); }); if (cb) cb(); self.resume(); }); client.on('unhandledResponse', function(res) { self.pause(); self.print('\nunhandled res:' + JSON.stringify(res)); self.resume(); }); client.on('break', function(res) { self.handleBreak(res.body); }); client.on('exception', function(res) { self.handleBreak(res.body); }); client.on('error', connectError); function connectError() { // If it's failed to connect 4 times then don't catch the next error if (connectionAttempts >= 10) { client.removeListener('error', connectError); } setTimeout(attemptConnect, 500); } function attemptConnect() { ++connectionAttempts; self.stdout.write('.'); client.connect(port, host); } setTimeout(function() { self.print('connecting..', true); attemptConnect(); }, 50); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var crypto = require('crypto'); var util = require('util'); var net = require('net'); var url = require('url'); var events = require('events'); var stream = require('stream'); var assert = require('assert').ok; var constants = require('constants'); var DEFAULT_CIPHERS = 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' + // TLS 1.2 'RC4:HIGH:!MD5:!aNULL:!EDH'; // TLS 1.0 // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more // renegotations are seen. The settings are applied to all remote client // connections. exports.CLIENT_RENEG_LIMIT = 3; exports.CLIENT_RENEG_WINDOW = 600; exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024; exports.getCiphers = function() { var names = process.binding('crypto').getSSLCiphers(); // Drop all-caps names in favor of their lowercase aliases, var ctx = {}; names.forEach(function(name) { if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); ctx[name] = true; }); return Object.getOwnPropertyNames(ctx).sort(); }; var debug; if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) { debug = function(a) { console.error('TLS:', a); }; } else { debug = function() { }; } var Connection = null; try { Connection = process.binding('crypto').Connection; } catch (e) { throw new Error('node.js not compiled with openssl crypto support.'); } // Convert protocols array into valid OpenSSL protocols list // ("\x06spdy/2\x08http/1.1\x08http/1.0") function convertNPNProtocols(NPNProtocols, out) { // If NPNProtocols is Array - translate it into buffer if (Array.isArray(NPNProtocols)) { var buff = new Buffer(NPNProtocols.reduce(function(p, c) { return p + 1 + Buffer.byteLength(c); }, 0)); NPNProtocols.reduce(function(offset, c) { var clen = Buffer.byteLength(c); buff[offset] = clen; buff.write(c, offset + 1); return offset + 1 + clen; }, 0); NPNProtocols = buff; } // If it's already a Buffer - store it if (Buffer.isBuffer(NPNProtocols)) { out.NPNProtocols = NPNProtocols; } } function checkServerIdentity(host, cert) { // Create regexp to much hostnames function regexpify(host, wildcards) { // Add trailing dot (make hostnames uniform) if (!/\.$/.test(host)) host += '.'; // The same applies to hostname with more than one wildcard, // if hostname has wildcard when wildcards are not allowed, // or if there are less than two dots after wildcard (i.e. *.com or *d.com) // // also // // "The client SHOULD NOT attempt to match a presented identifier in // which the wildcard character comprises a label other than the // left-most label (e.g., do not match bar.*.example.net)." // RFC6125 if (!wildcards && /\*/.test(host) || /[\.\*].*\*/.test(host) || /\*/.test(host) && !/\*.*\..+\..+/.test(host)) { return /$./; } // Replace wildcard chars with regexp's wildcard and // escape all characters that have special meaning in regexps // (i.e. '.', '[', '{', '*', and others) var re = host.replace( /\*([a-z0-9\\-_\.])|[\.,\-\\\^\$+?*\[\]\(\):!\|{}]/g, function(all, sub) { if (sub) return '[a-z0-9\\-_]*' + (sub === '-' ? '\\-' : sub); return '\\' + all; }); return new RegExp('^' + re + '$', 'i'); } var dnsNames = [], uriNames = [], ips = [], matchCN = true, valid = false; // There're several names to perform check against: // CN and altnames in certificate extension // (DNS names, IP addresses, and URIs) // // Walk through altnames and generate lists of those names if (cert.subjectaltname) { cert.subjectaltname.split(/, /g).forEach(function(altname) { if (/^DNS:/.test(altname)) { dnsNames.push(altname.slice(4)); } else if (/^IP Address:/.test(altname)) { ips.push(altname.slice(11)); } else if (/^URI:/.test(altname)) { var uri = url.parse(altname.slice(4)); if (uri) uriNames.push(uri.hostname); } }); } // If hostname is an IP address, it should be present in the list of IP // addresses. if (net.isIP(host)) { valid = ips.some(function(ip) { return ip === host; }); } else { // Transform hostname to canonical form if (!/\.$/.test(host)) host += '.'; // Otherwise check all DNS/URI records from certificate // (with allowed wildcards) dnsNames = dnsNames.map(function(name) { return regexpify(name, true); }); // Wildcards ain't allowed in URI names uriNames = uriNames.map(function(name) { return regexpify(name, false); }); dnsNames = dnsNames.concat(uriNames); if (dnsNames.length > 0) matchCN = false; // Match against Common Name (CN) only if no supported identifiers are // present. // // "As noted, a client MUST NOT seek a match for a reference identifier // of CN-ID if the presented identifiers include a DNS-ID, SRV-ID, // URI-ID, or any application-specific identifier types supported by the // client." // RFC6125 if (matchCN) { var commonNames = cert.subject.CN; if (Array.isArray(commonNames)) { for (var i = 0, k = commonNames.length; i < k; ++i) { dnsNames.push(regexpify(commonNames[i], true)); } } else { dnsNames.push(regexpify(commonNames, true)); } } valid = dnsNames.some(function(re) { return re.test(host); }); } return valid; } exports.checkServerIdentity = checkServerIdentity; function SlabBuffer() { this.create(); } SlabBuffer.prototype.create = function create() { this.isFull = false; this.pool = new Buffer(exports.SLAB_BUFFER_SIZE); this.offset = 0; this.remaining = this.pool.length; }; SlabBuffer.prototype.use = function use(context, fn, size) { if (this.remaining === 0) { this.isFull = true; return 0; } var actualSize = this.remaining; if (size !== null) actualSize = Math.min(size, actualSize); var bytes = fn.call(context, this.pool, this.offset, actualSize); if (bytes > 0) { this.offset += bytes; this.remaining -= bytes; } assert(this.remaining >= 0); return bytes; }; var slabBuffer = null; // Base class of both CleartextStream and EncryptedStream function CryptoStream(pair, options) { stream.Duplex.call(this, options); this.pair = pair; this._pending = null; this._pendingEncoding = ''; this._pendingCallback = null; this._doneFlag = false; this._retryAfterPartial = false; this._halfRead = false; this._sslOutCb = null; this._resumingSession = false; this._reading = true; this._destroyed = false; this._ended = false; this._finished = false; this._opposite = null; if (slabBuffer === null) slabBuffer = new SlabBuffer(); this._buffer = slabBuffer; this.once('finish', onCryptoStreamFinish); // net.Socket calls .onend too this.once('end', onCryptoStreamEnd); } util.inherits(CryptoStream, stream.Duplex); function onCryptoStreamFinish() { this._finished = true; if (this === this.pair.cleartext) { debug('cleartext.onfinish'); if (this.pair.ssl) { // Generate close notify // NOTE: first call checks if client has sent us shutdown, // second call enqueues shutdown into the BIO. if (this.pair.ssl.shutdown() !== 1) { if (this.pair.ssl && this.pair.ssl.error) return this.pair.error(); this.pair.ssl.shutdown(); } if (this.pair.ssl && this.pair.ssl.error) return this.pair.error(); } } else { debug('encrypted.onfinish'); } // Try to read just to get sure that we won't miss EOF if (this._opposite.readable) this._opposite.read(0); if (this._opposite._ended) { this._done(); // No half-close, sorry if (this === this.pair.cleartext) this._opposite._done(); } } function onCryptoStreamEnd() { this._ended = true; if (this === this.pair.cleartext) { debug('cleartext.onend'); } else { debug('encrypted.onend'); } if (this.onend) this.onend(); } // NOTE: Called once `this._opposite` is set. CryptoStream.prototype.init = function init() { var self = this; this._opposite.on('sslOutEnd', function() { if (self._sslOutCb) { var cb = self._sslOutCb; self._sslOutCb = null; cb(null); } }); }; CryptoStream.prototype._write = function write(data, encoding, cb) { assert(this._pending === null); // Black-hole data if (!this.pair.ssl) return cb(null); // When resuming session don't accept any new data. // And do not put too much data into openssl, before writing it from encrypted // side. // // TODO(indutny): Remove magic number, use watermark based limits if (!this._resumingSession && this._opposite._internallyPendingBytes() < 128 * 1024) { // Write current buffer now var written; if (this === this.pair.cleartext) { debug('cleartext.write called with ' + data.length + ' bytes'); written = this.pair.ssl.clearIn(data, 0, data.length); } else { debug('encrypted.write called with ' + data.length + ' bytes'); written = this.pair.ssl.encIn(data, 0, data.length); } // Handle and report errors if (this.pair.ssl && this.pair.ssl.error) { return cb(this.pair.error(true)); } // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); // Cycle encrypted data if (this.pair.encrypted._internallyPendingBytes()) this.pair.encrypted.read(0); // Get NPN and Server name when ready this.pair.maybeInitFinished(); // Whole buffer was written if (written === data.length) { if (this === this.pair.cleartext) { debug('cleartext.write succeed with ' + written + ' bytes'); } else { debug('encrypted.write succeed with ' + written + ' bytes'); } // Invoke callback only when all data read from opposite stream if (this._opposite._halfRead) { assert(this._sslOutCb === null); this._sslOutCb = cb; } else { cb(null); } return; } else if (written !== 0 && written !== -1) { assert(!this._retryAfterPartial); this._retryAfterPartial = true; this._write(data.slice(written), encoding, cb); this._retryAfterPartial = false; return; } } else { debug('cleartext.write queue is full'); // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); } // No write has happened this._pending = data; this._pendingEncoding = encoding; this._pendingCallback = cb; if (this === this.pair.cleartext) { debug('cleartext.write queued with ' + data.length + ' bytes'); } else { debug('encrypted.write queued with ' + data.length + ' bytes'); } }; CryptoStream.prototype._writePending = function writePending() { var data = this._pending, encoding = this._pendingEncoding, cb = this._pendingCallback; this._pending = null; this._pendingEncoding = ''; this._pendingCallback = null; this._write(data, encoding, cb); }; CryptoStream.prototype._read = function read(size) { // XXX: EOF?! if (!this.pair.ssl) return this.push(null); // Wait for session to be resumed // Mark that we're done reading, but don't provide data or EOF if (this._resumingSession || !this._reading) return this.push(''); var out; if (this === this.pair.cleartext) { debug('cleartext.read called with ' + size + ' bytes'); out = this.pair.ssl.clearOut; } else { debug('encrypted.read called with ' + size + ' bytes'); out = this.pair.ssl.encOut; } var bytesRead = 0, start = this._buffer.offset; do { var read = this._buffer.use(this.pair.ssl, out, size); if (read > 0) { bytesRead += read; size -= read; } // Handle and report errors if (this.pair.ssl && this.pair.ssl.error) { this.pair.error(); break; } // Get NPN and Server name when ready this.pair.maybeInitFinished(); } while (read > 0 && !this._buffer.isFull && bytesRead < size); // Create new buffer if previous was filled up var pool = this._buffer.pool; if (this._buffer.isFull) this._buffer.create(); assert(bytesRead >= 0); if (this === this.pair.cleartext) { debug('cleartext.read succeed with ' + bytesRead + ' bytes'); } else { debug('encrypted.read succeed with ' + bytesRead + ' bytes'); } // Try writing pending data if (this._pending !== null) this._writePending(); if (this._opposite._pending !== null) this._opposite._writePending(); if (bytesRead === 0) { // EOF when cleartext has finished and we have nothing to read if (this._opposite._finished && this._internallyPendingBytes() === 0) { // Perform graceful shutdown this._done(); // No half-open, sorry! if (this === this.pair.cleartext) this._opposite._done(); // EOF this.push(null); } else { // Bail out this.push(''); } } else { // Give them requested data if (this.ondata) { var self = this; this.ondata(pool, start, start + bytesRead); // Consume data automatically // simple/test-https-drain fails without it process.nextTick(function() { self.read(bytesRead); }); } this.push(pool.slice(start, start + bytesRead)); } // Let users know that we've some internal data to read var halfRead = this._internallyPendingBytes() !== 0; // Smart check to avoid invoking 'sslOutEnd' in the most of the cases if (this._halfRead !== halfRead) { this._halfRead = halfRead; // Notify listeners about internal data end if (!halfRead) { if (this === this.pair.cleartext) { debug('cleartext.sslOutEnd'); } else { debug('encrypted.sslOutEnd'); } this.emit('sslOutEnd'); } } }; CryptoStream.prototype.setTimeout = function(timeout, callback) { if (this.socket) this.socket.setTimeout(timeout, callback); }; CryptoStream.prototype.setNoDelay = function(noDelay) { if (this.socket) this.socket.setNoDelay(noDelay); }; CryptoStream.prototype.setKeepAlive = function(enable, initialDelay) { if (this.socket) this.socket.setKeepAlive(enable, initialDelay); }; CryptoStream.prototype.__defineGetter__('bytesWritten', function() { return this.socket ? this.socket.bytesWritten : 0; }); // Example: // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org function parseCertString(s) { var out = {}; var parts = s.split('\n'); for (var i = 0, len = parts.length; i < len; i++) { var sepIndex = parts[i].indexOf('='); if (sepIndex > 0) { var key = parts[i].slice(0, sepIndex); var value = parts[i].slice(sepIndex + 1); if (key in out) { if (!Array.isArray(out[key])) { out[key] = [out[key]]; } out[key].push(value); } else { out[key] = value; } } } return out; } CryptoStream.prototype.getPeerCertificate = function() { if (this.pair.ssl) { var c = this.pair.ssl.getPeerCertificate(); if (c) { if (c.issuer) c.issuer = parseCertString(c.issuer); if (c.subject) c.subject = parseCertString(c.subject); return c; } } return null; }; CryptoStream.prototype.getSession = function() { if (this.pair.ssl) { return this.pair.ssl.getSession(); } return null; }; CryptoStream.prototype.isSessionReused = function() { if (this.pair.ssl) { return this.pair.ssl.isSessionReused(); } return null; }; CryptoStream.prototype.getCipher = function(err) { if (this.pair.ssl) { return this.pair.ssl.getCurrentCipher(); } else { return null; } }; CryptoStream.prototype.end = function(chunk, encoding) { if (this === this.pair.cleartext) { debug('cleartext.end'); } else { debug('encrypted.end'); } // Write pending data first if (this._pending !== null) this._writePending(); this.writable = false; stream.Duplex.prototype.end.call(this, chunk, encoding); }; CryptoStream.prototype.destroySoon = function(err) { if (this === this.pair.cleartext) { debug('cleartext.destroySoon'); } else { debug('encrypted.destroySoon'); } if (this.writable) this.end(); if (this._writableState.finished && this._opposite._ended) { this.destroy(); } else { // Wait for both `finish` and `end` events to ensure that all data that // was written on this side was read from the other side. var self = this; var waiting = 2; function finish() { if (--waiting === 0) self.destroy(); } this._opposite.once('end', finish); this.once('finish', finish); } }; CryptoStream.prototype.destroy = function(err) { if (this._destroyed) return; this._destroyed = true; this.readable = this.writable = false; // Destroy both ends if (this === this.pair.cleartext) { debug('cleartext.destroy'); } else { debug('encrypted.destroy'); } this._opposite.destroy(); var self = this; process.nextTick(function() { // Force EOF self.push(null); // Emit 'close' event self.emit('close', err ? true : false); }); }; CryptoStream.prototype._done = function() { this._doneFlag = true; if (this === this.pair.encrypted && !this.pair._secureEstablished) return this.pair.error(); if (this.pair.cleartext._doneFlag && this.pair.encrypted._doneFlag && !this.pair._doneFlag) { // If both streams are done: this.pair.destroy(); } }; // readyState is deprecated. Don't use it. Object.defineProperty(CryptoStream.prototype, 'readyState', { get: function() { if (this._connecting) { return 'opening'; } else if (this.readable && this.writable) { return 'open'; } else if (this.readable && !this.writable) { return 'readOnly'; } else if (!this.readable && this.writable) { return 'writeOnly'; } else { return 'closed'; } } }); function CleartextStream(pair, options) { CryptoStream.call(this, pair, options); // This is a fake kludge to support how the http impl sits // on top of net Sockets var self = this; this._handle = { readStop: function() { self._reading = false; }, readStart: function() { if (self._reading && self._readableState.length > 0) return; self._reading = true; self.read(0); if (self._opposite.readable) self._opposite.read(0); } }; } util.inherits(CleartextStream, CryptoStream); CleartextStream.prototype._internallyPendingBytes = function() { if (this.pair.ssl) { return this.pair.ssl.clearPending(); } else { return 0; } }; CleartextStream.prototype.address = function() { return this.socket && this.socket.address(); }; CleartextStream.prototype.__defineGetter__('remoteAddress', function() { return this.socket && this.socket.remoteAddress; }); CleartextStream.prototype.__defineGetter__('remotePort', function() { return this.socket && this.socket.remotePort; }); function EncryptedStream(pair, options) { CryptoStream.call(this, pair, options); } util.inherits(EncryptedStream, CryptoStream); EncryptedStream.prototype._internallyPendingBytes = function() { if (this.pair.ssl) { return this.pair.ssl.encPending(); } else { return 0; } }; function onhandshakestart() { debug('onhandshakestart'); var self = this; var ssl = self.ssl; var now = Date.now(); assert(now >= ssl.lastHandshakeTime); if ((now - ssl.lastHandshakeTime) >= exports.CLIENT_RENEG_WINDOW * 1000) { ssl.handshakes = 0; } var first = (ssl.lastHandshakeTime === 0); ssl.lastHandshakeTime = now; if (first) return; if (++ssl.handshakes > exports.CLIENT_RENEG_LIMIT) { // Defer the error event to the next tick. We're being called from OpenSSL's // state machine and OpenSSL is not re-entrant. We cannot allow the user's // callback to destroy the connection right now, it would crash and burn. setImmediate(function() { var err = new Error('TLS session renegotiation attack detected.'); if (self.cleartext) self.cleartext.emit('error', err); }); } } function onhandshakedone() { // for future use debug('onhandshakedone'); } function onclienthello(hello) { var self = this, once = false; this._resumingSession = true; function callback(err, session) { if (once) return; once = true; if (err) return self.socket.destroy(err); self.ssl.loadSession(session); // Cycle data self._resumingSession = false; self.cleartext.read(0); self.encrypted.read(0); } if (hello.sessionId.length <= 0 || !this.server || !this.server.emit('resumeSession', hello.sessionId, callback)) { callback(null, null); } } function onnewsession(key, session) { if (!this.server) return; this.server.emit('newSession', key, session); } /** * Provides a pair of streams to do encrypted communication. */ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized, options) { if (!(this instanceof SecurePair)) { return new SecurePair(credentials, isServer, requestCert, rejectUnauthorized, options); } var self = this; options || (options = {}); events.EventEmitter.call(this); this.server = options.server; this._secureEstablished = false; this._isServer = isServer ? true : false; this._encWriteState = true; this._clearWriteState = true; this._doneFlag = false; this._destroying = false; if (!credentials) { this.credentials = crypto.createCredentials(); } else { this.credentials = credentials; } if (!this._isServer) { // For clients, we will always have either a given ca list or be using // default one requestCert = true; } this._rejectUnauthorized = rejectUnauthorized ? true : false; this._requestCert = requestCert ? true : false; this.ssl = new Connection(this.credentials.context, this._isServer ? true : false, this._isServer ? this._requestCert : options.servername, this._rejectUnauthorized); if (this._isServer) { this.ssl.onhandshakestart = onhandshakestart.bind(this); this.ssl.onhandshakedone = onhandshakedone.bind(this); this.ssl.onclienthello = onclienthello.bind(this); this.ssl.onnewsession = onnewsession.bind(this); this.ssl.lastHandshakeTime = 0; this.ssl.handshakes = 0; } if (process.features.tls_sni) { if (this._isServer && options.SNICallback) { this.ssl.setSNICallback(options.SNICallback); } this.servername = null; } if (process.features.tls_npn && options.NPNProtocols) { this.ssl.setNPNProtocols(options.NPNProtocols); this.npnProtocol = null; } /* Acts as a r/w stream to the cleartext side of the stream. */ this.cleartext = new CleartextStream(this, options.cleartext); /* Acts as a r/w stream to the encrypted side of the stream. */ this.encrypted = new EncryptedStream(this, options.encrypted); /* Let streams know about each other */ this.cleartext._opposite = this.encrypted; this.encrypted._opposite = this.cleartext; this.cleartext.init(); this.encrypted.init(); process.nextTick(function() { /* The Connection may be destroyed by an abort call */ if (self.ssl) { self.ssl.start(); } }); } util.inherits(SecurePair, events.EventEmitter); exports.createSecurePair = function(credentials, isServer, requestCert, rejectUnauthorized) { var pair = new SecurePair(credentials, isServer, requestCert, rejectUnauthorized); return pair; }; SecurePair.prototype.maybeInitFinished = function() { if (this.ssl && !this._secureEstablished && this.ssl.isInitFinished()) { if (process.features.tls_npn) { this.npnProtocol = this.ssl.getNegotiatedProtocol(); } if (process.features.tls_sni) { this.servername = this.ssl.getServername(); } this._secureEstablished = true; debug('secure established'); this.emit('secure'); } }; SecurePair.prototype.destroy = function() { if (this._destroying) return; if (!this._doneFlag) { debug('SecurePair.destroy'); this._destroying = true; // SecurePair should be destroyed only after it's streams this.cleartext.destroy(); this.encrypted.destroy(); this._doneFlag = true; this.ssl.error = null; this.ssl.close(); this.ssl = null; } }; SecurePair.prototype.error = function(returnOnly) { var err = this.ssl.error; this.ssl.error = null; if (!this._secureEstablished) { // Emit ECONNRESET instead of zero return if (!err || err.message === 'ZERO_RETURN') { var connReset = new Error('socket hang up'); connReset.code = 'ECONNRESET'; connReset.sslError = err && err.message; err = connReset; } this.destroy(); if (!returnOnly) this.emit('error', err); } else if (this._isServer && this._rejectUnauthorized && /peer did not return a certificate/.test(err.message)) { // Not really an error. this.destroy(); } else { if (!returnOnly) this.cleartext.emit('error', err); } return err; }; // TODO: support anonymous (nocert) and PSK // AUTHENTICATION MODES // // There are several levels of authentication that TLS/SSL supports. // Read more about this in "man SSL_set_verify". // // 1. The server sends a certificate to the client but does not request a // cert from the client. This is common for most HTTPS servers. The browser // can verify the identity of the server, but the server does not know who // the client is. Authenticating the client is usually done over HTTP using // login boxes and cookies and stuff. // // 2. The server sends a cert to the client and requests that the client // also send it a cert. The client knows who the server is and the server is // requesting the client also identify themselves. There are several // outcomes: // // A) verifyError returns null meaning the client's certificate is signed // by one of the server's CAs. The server know's the client idenity now // and the client is authorized. // // B) For some reason the client's certificate is not acceptable - // verifyError returns a string indicating the problem. The server can // either (i) reject the client or (ii) allow the client to connect as an // unauthorized connection. // // The mode is controlled by two boolean variables. // // requestCert // If true the server requests a certificate from client connections. For // the common HTTPS case, users will want this to be false, which is what // it defaults to. // // rejectUnauthorized // If true clients whose certificates are invalid for any reason will not // be allowed to make connections. If false, they will simply be marked as // unauthorized but secure communication will continue. By default this is // true. // // // // Options: // - requestCert. Send verify request. Default to false. // - rejectUnauthorized. Boolean, default to true. // - key. string. // - cert: string. // - ca: string or array of strings. // // emit 'secureConnection' // function (cleartextStream, encryptedStream) { } // // 'cleartextStream' has the boolean property 'authorized' to determine if // it was verified by the CA. If 'authorized' is false, a property // 'authorizationError' is set on cleartextStream and has the possible // values: // // "UNABLE_TO_GET_ISSUER_CERT", "UNABLE_TO_GET_CRL", // "UNABLE_TO_DECRYPT_CERT_SIGNATURE", "UNABLE_TO_DECRYPT_CRL_SIGNATURE", // "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", "CERT_SIGNATURE_FAILURE", // "CRL_SIGNATURE_FAILURE", "CERT_NOT_YET_VALID" "CERT_HAS_EXPIRED", // "CRL_NOT_YET_VALID", "CRL_HAS_EXPIRED" "ERROR_IN_CERT_NOT_BEFORE_FIELD", // "ERROR_IN_CERT_NOT_AFTER_FIELD", "ERROR_IN_CRL_LAST_UPDATE_FIELD", // "ERROR_IN_CRL_NEXT_UPDATE_FIELD", "OUT_OF_MEM", // "DEPTH_ZERO_SELF_SIGNED_CERT", "SELF_SIGNED_CERT_IN_CHAIN", // "UNABLE_TO_GET_ISSUER_CERT_LOCALLY", "UNABLE_TO_VERIFY_LEAF_SIGNATURE", // "CERT_CHAIN_TOO_LONG", "CERT_REVOKED" "INVALID_CA", // "PATH_LENGTH_EXCEEDED", "INVALID_PURPOSE" "CERT_UNTRUSTED", // "CERT_REJECTED" // // // TODO: // cleartext.credentials (by mirroring from pair object) // cleartext.getCertificate() (by mirroring from pair.credentials.context) function Server(/* [options], listener */) { var options, listener; if (typeof arguments[0] == 'object') { options = arguments[0]; listener = arguments[1]; } else if (typeof arguments[0] == 'function') { options = {}; listener = arguments[0]; } if (!(this instanceof Server)) return new Server(options, listener); this._contexts = []; var self = this; // Handle option defaults: this.setOptions(options); if (!self.pfx && (!self.cert || !self.key)) { throw new Error('Missing PFX or certificate + private key.'); } var sharedCreds = crypto.createCredentials({ pfx: self.pfx, key: self.key, passphrase: self.passphrase, cert: self.cert, ca: self.ca, ciphers: self.ciphers || DEFAULT_CIPHERS, secureProtocol: self.secureProtocol, secureOptions: self.secureOptions, crl: self.crl, sessionIdContext: self.sessionIdContext }); var timeout = options.handshakeTimeout || (120 * 1000); if (typeof timeout !== 'number') { throw new TypeError('handshakeTimeout must be a number'); } // constructor call net.Server.call(this, function(socket) { var creds = crypto.createCredentials(null, sharedCreds.context); var pair = new SecurePair(creds, true, self.requestCert, self.rejectUnauthorized, { server: self, NPNProtocols: self.NPNProtocols, SNICallback: self.SNICallback, // Stream options cleartext: self._cleartext, encrypted: self._encrypted }); var cleartext = pipe(pair, socket); cleartext._controlReleased = false; function listener() { pair.emit('error', new Error('TLS handshake timeout')); } if (timeout > 0) { socket.setTimeout(timeout, listener); } pair.once('secure', function() { socket.setTimeout(0, listener); pair.cleartext.authorized = false; pair.cleartext.npnProtocol = pair.npnProtocol; pair.cleartext.servername = pair.servername; if (!self.requestCert) { cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } else { var verifyError = pair.ssl.verifyError(); if (verifyError) { pair.cleartext.authorizationError = verifyError.message; if (self.rejectUnauthorized) { socket.destroy(); pair.destroy(); } else { cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } } else { pair.cleartext.authorized = true; cleartext._controlReleased = true; self.emit('secureConnection', pair.cleartext, pair.encrypted); } } }); pair.on('error', function(err) { self.emit('clientError', err, this); }); }); if (listener) { this.on('secureConnection', listener); } } util.inherits(Server, net.Server); exports.Server = Server; exports.createServer = function(options, listener) { return new Server(options, listener); }; Server.prototype.setOptions = function(options) { if (typeof options.requestCert == 'boolean') { this.requestCert = options.requestCert; } else { this.requestCert = false; } if (typeof options.rejectUnauthorized == 'boolean') { this.rejectUnauthorized = options.rejectUnauthorized; } else { this.rejectUnauthorized = false; } if (options.pfx) this.pfx = options.pfx; if (options.key) this.key = options.key; if (options.passphrase) this.passphrase = options.passphrase; if (options.cert) this.cert = options.cert; if (options.ca) this.ca = options.ca; if (options.secureProtocol) this.secureProtocol = options.secureProtocol; if (options.crl) this.crl = options.crl; if (options.ciphers) this.ciphers = options.ciphers; var secureOptions = options.secureOptions || 0; if (options.honorCipherOrder) { secureOptions |= constants.SSL_OP_CIPHER_SERVER_PREFERENCE; } if (secureOptions) this.secureOptions = secureOptions; if (options.NPNProtocols) convertNPNProtocols(options.NPNProtocols, this); if (options.SNICallback) { this.SNICallback = options.SNICallback; } else { this.SNICallback = this.SNICallback.bind(this); } if (options.sessionIdContext) { this.sessionIdContext = options.sessionIdContext; } else if (this.requestCert) { this.sessionIdContext = crypto.createHash('md5') .update(process.argv.join(' ')) .digest('hex'); } if (options.cleartext) this.cleartext = options.cleartext; if (options.encrypted) this.encrypted = options.encrypted; }; // SNI Contexts High-Level API Server.prototype.addContext = function(servername, credentials) { if (!servername) { throw 'Servername is required parameter for Server.addContext'; } var re = new RegExp('^' + servername.replace(/([\.^$+?\-\\[\]{}])/g, '\\$1') .replace(/\*/g, '.*') + '$'); this._contexts.push([re, crypto.createCredentials(credentials).context]); }; Server.prototype.SNICallback = function(servername) { var ctx; this._contexts.some(function(elem) { if (servername.match(elem[0]) !== null) { ctx = elem[1]; return true; } }); return ctx; }; // Target API: // // var s = tls.connect({port: 8000, host: "google.com"}, function() { // if (!s.authorized) { // s.destroy(); // return; // } // // // s.socket; // // s.end("hello world\n"); // }); // // function normalizeConnectArgs(listArgs) { var args = net._normalizeConnectArgs(listArgs); var options = args[0]; var cb = args[1]; if (typeof listArgs[1] === 'object') { options = util._extend(options, listArgs[1]); } else if (typeof listArgs[2] === 'object') { options = util._extend(options, listArgs[2]); } return (cb) ? [options, cb] : [options]; } exports.connect = function(/* [port, host], options, cb */) { var args = normalizeConnectArgs(arguments); var options = args[0]; var cb = args[1]; var defaults = { rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED }; options = util._extend(defaults, options || {}); var socket = options.socket ? options.socket : new net.Stream(); var sslcontext = crypto.createCredentials(options); convertNPNProtocols(options.NPNProtocols, this); var hostname = options.servername || options.host || 'localhost', pair = new SecurePair(sslcontext, false, true, options.rejectUnauthorized === true ? true : false, { NPNProtocols: this.NPNProtocols, servername: hostname, cleartext: options.cleartext, encrypted: options.encrypted }); if (options.session) { var session = options.session; if (typeof session === 'string') session = new Buffer(session, 'binary'); pair.ssl.setSession(session); } var cleartext = pipe(pair, socket); if (cb) { cleartext.once('secureConnect', cb); } if (!options.socket) { var connect_opt = (options.path && !options.port) ? {path: options.path} : { port: options.port, host: options.host, localAddress: options.localAddress }; socket.connect(connect_opt); } pair.on('secure', function() { var verifyError = pair.ssl.verifyError(); cleartext.npnProtocol = pair.npnProtocol; // Verify that server's identity matches it's certificate's names if (!verifyError) { var validCert = checkServerIdentity(hostname, pair.cleartext.getPeerCertificate()); if (!validCert) { verifyError = new Error('Hostname/IP doesn\'t match certificate\'s ' + 'altnames'); } } if (verifyError) { cleartext.authorized = false; cleartext.authorizationError = verifyError.message; if (pair._rejectUnauthorized) { cleartext.emit('error', verifyError); pair.destroy(); } else { cleartext.emit('secureConnect'); } } else { cleartext.authorized = true; cleartext.emit('secureConnect'); } }); pair.on('error', function(err) { cleartext.emit('error', err); }); cleartext._controlReleased = true; return cleartext; }; function pipe(pair, socket) { pair.encrypted.pipe(socket); socket.pipe(pair.encrypted); pair.encrypted.on('close', function() { process.nextTick(function() { // Encrypted should be unpiped from socket to prevent possible // write after destroy. pair.encrypted.unpipe(socket); socket.destroy(); }); }); pair.fd = socket.fd; var cleartext = pair.cleartext; cleartext.socket = socket; cleartext.encrypted = pair.encrypted; cleartext.authorized = false; // cycle the data whenever the socket drains, so that // we can pull some more into it. normally this would // be handled by the fact that pipe() triggers read() calls // on writable.drain, but CryptoStreams are a bit more // complicated. Since the encrypted side actually gets // its data from the cleartext side, we have to give it a // light kick to get in motion again. socket.on('drain', function() { if (pair.encrypted._pending) pair.encrypted._writePending(); if (pair.cleartext._pending) pair.cleartext._writePending(); pair.encrypted.read(0); pair.cleartext.read(0); }); function onerror(e) { if (cleartext._controlReleased) { cleartext.emit('error', e); } } function onclose() { socket.removeListener('error', onerror); socket.removeListener('timeout', ontimeout); } function ontimeout() { cleartext.emit('timeout'); } socket.on('error', onerror); socket.on('close', onclose); socket.on('timeout', ontimeout); return cleartext; } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Hello, and welcome to hacking node.js! // // This file is invoked by node::Load in src/node.cc, and responsible for // bootstrapping the node.js core. Special caution is given to the performance // of the startup process, so many dependencies are invoked lazily. (function(process) { this.global = this; function startup() { var EventEmitter = NativeModule.require('events').EventEmitter; process.__proto__ = Object.create(EventEmitter.prototype, { constructor: { value: process.constructor } }); EventEmitter.call(process); process.EventEmitter = EventEmitter; // process.EventEmitter is deprecated // do this good and early, since it handles errors. startup.processFatal(); startup.globalVariables(); startup.globalTimeouts(); startup.globalConsole(); startup.processAssert(); startup.processConfig(); startup.processNextTick(); startup.processStdio(); startup.processKillAndExit(); startup.processSignalHandlers(); startup.processChannel(); startup.resolveArgv0(); if (NativeModule.exists('_third_party_patch')) { // allow third parties to patch node before any script loading is done NativeModule.require('_third_party_patch'); } // if node is using chakra // load the chakra patch module in order to fix some known issues // caused by incompatbility of chakra and v8 if (process.ischakra) { if (NativeModule.exists('_chakra_patch')) { NativeModule.require('_chakra_patch'); } } // There are various modes that Node can run in. The most common two // are running from a script and running the REPL - but there are a few // others like the debugger or running --eval arguments. Here we decide // which mode we run in. if (NativeModule.exists('_third_party_main')) { // To allow people to extend Node in different ways, this hook allows // one to drop a file lib/_third_party_main.js into the build // directory which will be executed instead of Node's normal loading. process.nextTick(function() { NativeModule.require('_third_party_main'); }); } else if (process.argv[1] == 'debug') { // Start the debugger agent var d = NativeModule.require('_debugger'); d.start(); } else if (process._eval != null) { // User passed '-e' or '--eval' arguments to Node. evalScript('[eval]'); } else if (process.argv[1]) { // make process.argv[1] into a full path var path = NativeModule.require('path'); process.argv[1] = path.resolve(process.argv[1]); // If this is a worker in cluster mode, start up the communiction // channel. if (process.env.NODE_UNIQUE_ID) { var cluster = NativeModule.require('cluster'); cluster._setupWorker(); // Make sure it's not accidentally inherited by child processes. delete process.env.NODE_UNIQUE_ID; } var Module; if (!process.ischakra) { Module = NativeModule.require('module'); } if (global.v8debug && process.execArgv.some(function(arg) { return arg.match(/^--debug-brk(=[0-9]*)?$/); })) { Module = Module || NativeModule.require('module'); // XXX Fix this terrible hack! // // Give the client program a few ticks to connect. // Otherwise, there's a race condition where `node debug foo.js` // will not be able to connect in time to catch the first // breakpoint message on line 1. // // A better fix would be to somehow get a message from the // global.v8debug object about a connection, and runMain when // that occurs. --isaacs var debugTimeout = +process.env.NODE_DEBUG_TIMEOUT || 50; setTimeout(Module.runMain, debugTimeout); } else { // Main entry point into most programs: if (process.ischakra) { Module = NativeModule.require('nativerequire'); } else { Module = NativeModule.require('module'); } Module.runMain(); } } else { // use regular Module for REPL var Module = Module || NativeModule.require('module'); // If -i or --interactive were passed, or stdin is a TTY. if (process._forceRepl || NativeModule.require('tty').isatty(0)) { // REPL var opts = { useGlobal: true, ignoreUndefined: false }; if (parseInt(process.env['NODE_NO_READLINE'], 10)) { opts.terminal = false; } if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { opts.useColors = false; } var repl = Module.requireRepl().start(opts); repl.on('exit', function() { process.exit(); }); } else { // Read all of stdin - execute it. process.stdin.setEncoding('utf8'); var code = ''; process.stdin.on('data', function(d) { code += d; }); process.stdin.on('end', function() { process._eval = code; evalScript('[stdin]'); }); } } } startup.globalVariables = function() { global.process = process; global.global = global; global.GLOBAL = global; global.root = global; global.Buffer = NativeModule.require('buffer').Buffer; process.binding('buffer').setFastBufferConstructor(global.Buffer); process.domain = null; process._exiting = false; // exposing the external events emitter: // the event emitter will be used to fire events from external sources var events = NativeModule.require('events'); global.externalEvents = new events.EventEmitter(); }; startup.globalTimeouts = function() { global.setTimeout = function() { var t = NativeModule.require('timers'); return t.setTimeout.apply(this, arguments); }; global.setInterval = function() { var t = NativeModule.require('timers'); return t.setInterval.apply(this, arguments); }; global.clearTimeout = function() { var t = NativeModule.require('timers'); return t.clearTimeout.apply(this, arguments); }; global.clearInterval = function() { var t = NativeModule.require('timers'); return t.clearInterval.apply(this, arguments); }; global.setImmediate = function() { var t = NativeModule.require('timers'); return t.setImmediate.apply(this, arguments); }; global.clearImmediate = function() { var t = NativeModule.require('timers'); return t.clearImmediate.apply(this, arguments); }; }; startup.globalConsole = function() { var emptyConsole = { log: function() { }, debug: function() { }, info: function() { }, warn: function() { }, warning: function() { }, error: function() { }, }; global.__defineGetter__('console', function() { if (process.ischakra && process.noconsole) { return emptyConsole; } else { return NativeModule.require('console'); } }); }; startup._lazyConstants = null; startup.lazyConstants = function() { if (!startup._lazyConstants) { startup._lazyConstants = process.binding('constants'); } return startup._lazyConstants; }; startup.processFatal = function() { // call into the active domain, or emit uncaughtException, // and exit if there are no listeners. process._fatalException = function(er) { var caught = false; if (process.domain) { var domain = process.domain; var domainModule = NativeModule.require('domain'); var domainStack = domainModule._stack; // ignore errors on disposed domains. // // XXX This is a bit stupid. We should probably get rid of // domain.dispose() altogether. It's almost always a terrible // idea. --isaacs if (domain._disposed) return true; er.domain = domain; er.domainThrown = true; // wrap this in a try/catch so we don't get infinite throwing try { // One of three things will happen here. // // 1. There is a handler, caught = true // 2. There is no handler, caught = false // 3. It throws, caught = false // // If caught is false after this, then there's no need to exit() // the domain, because we're going to crash the process anyway. caught = domain.emit('error', er); // Exit all domains on the stack. Uncaught exceptions end the // current tick and no domains should be left on the stack // between ticks. var domainModule = NativeModule.require('domain'); domainStack.length = 0; domainModule.active = process.domain = null; } catch (er2) { // The domain error handler threw! oh no! // See if another domain can catch THIS error, // or else crash on the original one. // If the user already exited it, then don't double-exit. if (domain === domainModule.active) domainStack.pop(); if (domainStack.length) { var parentDomain = domainStack[domainStack.length - 1]; process.domain = domainModule.active = parentDomain; caught = process._fatalException(er2); } else caught = false; } } else { caught = process.emit('uncaughtException', er); } // if someone handled it, then great. otherwise, die in C++ land // since that means that we'll exit the process, emit the 'exit' event if (!caught) { try { if (!process._exiting) { process._exiting = true; process.emit('exit', 1); } } catch (er) { // nothing to be done about it at this point. } } // if we handled an error, then make sure any ticks get processed if (caught) process._needTickCallback(); return caught; }; }; var assert; startup.processAssert = function() { // Note that calls to assert() are pre-processed out by JS2C for the // normal build of node. They persist only in the node_g build. // Similarly for debug(). assert = process.assert = function(x, msg) { if (!x) throw new Error(msg || 'assertion error'); }; }; startup.processConfig = function () { // used for `process.config`, but not a real module if (process.ischakra) { Object.defineProperty(process, 'config', { get: function () { throw new Error('process.config is removed due to optimizations, please do not use.'); } }); return; } var config = NativeModule._source.config; delete NativeModule._source.config; // strip the gyp comment line at the beginning config = config.split('\n').slice(1).join('\n').replace(/'/g, '"'); process.config = JSON.parse(config, function(key, value) { if (value === 'true') return true; if (value === 'false') return false; return value; }); }; startup.processNextTick = function() { var _needTickCallback = process._needTickCallback; var nextTickQueue = []; var needSpinner = true; var inTick = false; // this infobox thing is used so that the C++ code in src/node.cc // can have easy accesss to our nextTick state, and avoid unnecessary // calls into process._tickCallback. // order is [length, index, depth] // Never write code like this without very good reason! var infoBox = process._tickInfoBox; var length = 0; var index = 1; var depth = 2; process.nextTick = nextTick; // needs to be accessible from cc land process._nextDomainTick = _nextDomainTick; process._tickCallback = _tickCallback; process._tickDomainCallback = _tickDomainCallback; process._tickFromSpinner = _tickFromSpinner; // the maximum number of times it'll process something like // nextTick(function f(){nextTick(f)}) // It's unlikely, but not illegal, to hit this limit. When // that happens, it yields to libuv's tick spinner. // This is a loop counter, not a stack depth, so we aren't using // up lots of memory here. I/O can sneak in before nextTick if this // limit is hit, which is not ideal, but not terrible. process.maxTickDepth = 1000; function tickDone(tickDepth_) { if (infoBox[length] !== 0) { if (infoBox[length] <= infoBox[index]) { nextTickQueue = []; infoBox[length] = 0; } else { nextTickQueue.splice(0, infoBox[index]); infoBox[length] = nextTickQueue.length; if (needSpinner) { _needTickCallback(); needSpinner = false; } } } inTick = false; infoBox[index] = 0; infoBox[depth] = tickDepth_; } function maxTickWarn() { // XXX Remove all this maxTickDepth stuff in 0.11 var msg = '(node) warning: Recursive process.nextTick detected. ' + 'This will break in the next version of node. ' + 'Please use setImmediate for recursive deferral.'; if (process.throwDeprecation) throw new Error(msg); else if (process.traceDeprecation) console.trace(msg); else console.error(msg); } function _tickFromSpinner() { needSpinner = true; // coming from spinner, reset! if (infoBox[depth] !== 0) infoBox[depth] = 0; // no callbacks to run if (infoBox[length] === 0) return infoBox[index] = infoBox[depth] = 0; process._tickCallback(); } // run callbacks that have no domain // using domains will cause this to be overridden function _tickCallback() { var callback, nextTickLength, threw; if (inTick) return; if (infoBox[length] === 0) { infoBox[index] = 0; infoBox[depth] = 0; return; } inTick = true; while (infoBox[depth]++ < process.maxTickDepth) { nextTickLength = infoBox[length]; if (infoBox[index] === nextTickLength) return tickDone(0); while (infoBox[index] < nextTickLength) { callback = nextTickQueue[infoBox[index]++].callback; threw = true; try { callback(); threw = false; } finally { if (threw) tickDone(infoBox[depth]); } } } tickDone(0); } function _tickDomainCallback() { var nextTickLength, tock, callback, threw; // if you add a nextTick in a domain's error handler, then // it's possible to cycle indefinitely. Normally, the tickDone // in the finally{} block below will prevent this, however if // that error handler ALSO triggers multiple MakeCallbacks, then // it'll try to keep clearing the queue, since the finally block // fires *before* the error hits the top level and is handled. if (infoBox[depth] >= process.maxTickDepth) return _needTickCallback(); if (inTick) return; inTick = true; // always do this at least once. otherwise if process.maxTickDepth // is set to some negative value, or if there were repeated errors // preventing depth from being cleared, we'd never process any // of them. while (infoBox[depth]++ < process.maxTickDepth) { nextTickLength = infoBox[length]; if (infoBox[index] === nextTickLength) return tickDone(0); while (infoBox[index] < nextTickLength) { tock = nextTickQueue[infoBox[index]++]; callback = tock.callback; if (tock.domain) { if (tock.domain._disposed) continue; tock.domain.enter(); } threw = true; try { callback(); threw = false; } finally { // finally blocks fire before the error hits the top level, // so we can't clear the depth at this point. if (threw) tickDone(infoBox[depth]); } if (tock.domain) { tock.domain.exit(); } } } tickDone(0); } function nextTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) return; if (infoBox[depth] >= process.maxTickDepth) maxTickWarn(); var obj = { callback: callback, domain: null }; nextTickQueue.push(obj); infoBox[length]++; if (needSpinner) { _needTickCallback(); needSpinner = false; } } function _nextDomainTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) return; if (infoBox[depth] >= process.maxTickDepth) maxTickWarn(); var obj = { callback: callback, domain: process.domain }; nextTickQueue.push(obj); infoBox[length]++; if (needSpinner) { _needTickCallback(); needSpinner = false; } } }; function evalScript(name) { var Module = NativeModule.require('module'); var path = NativeModule.require('path'); var cwd = process.cwd(); var module = new Module(name); module.filename = path.join(cwd, name); module.paths = Module._nodeModulePaths(cwd); var script = process._eval; if (!Module._contextLoad) { var body = script; script = 'global.__filename = ' + JSON.stringify(name) + ';\n' + 'global.exports = exports;\n' + 'global.module = module;\n' + 'global.__dirname = __dirname;\n' + 'global.require = require;\n' + 'return require("vm").runInThisContext(' + JSON.stringify(body) + ', ' + JSON.stringify(name) + ', true);\n'; } var result = module._compile(script, name + '-wrapper'); if (process._print_eval) console.log(result); } function errnoException(errorno, syscall) { // TODO make this more compatible with ErrnoException from src/node.cc // Once all of Node is using this function the ErrnoException from // src/node.cc should be removed. var e = new Error(syscall + ' ' + errorno); e.errno = e.code = errorno; e.syscall = syscall; return e; } function createWritableStdioStream(fd) { var stream; var tty_wrap = process.binding('tty_wrap'); // Note stream._type is used for test-module-load-list.js switch (tty_wrap.guessHandleType(fd)) { case 'TTY': var tty = NativeModule.require('tty'); stream = new tty.WriteStream(fd); stream._type = 'tty'; // Hack to have stream not keep the event loop alive. // See https://github.com/joyent/node/issues/1726 if (stream._handle && stream._handle.unref) { stream._handle.unref(); } break; case 'FILE': var fs = NativeModule.require('fs'); stream = new fs.SyncWriteStream(fd); stream._type = 'fs'; break; case 'PIPE': case 'TCP': var net = NativeModule.require('net'); stream = new net.Socket({ fd: fd, readable: false, writable: true }); // FIXME Should probably have an option in net.Socket to create a // stream from an existing fd which is writable only. But for now // we'll just add this hack and set the `readable` member to false. // Test: ./node test/fixtures/echo.js < /etc/passwd stream.readable = false; stream.read = null; stream._type = 'pipe'; // FIXME Hack to have stream not keep the event loop alive. // See https://github.com/joyent/node/issues/1726 if (stream._handle && stream._handle.unref) { stream._handle.unref(); } break; default: // Probably an error on in uv_guess_handle() throw new Error('Implement me. Unknown stream file type!'); } // For supporting legacy API we put the FD here. stream.fd = fd; stream._isStdio = true; return stream; } startup.processStdio = function() { var stdin, stdout, stderr; // TODO: we might want also to add a specific switch for this? if (process.ischakra && process.noconsole) { stdin = { id : '__mock_stdin', write: function() { }, read: function() { }, pipe: function() { } } stdout = { id: '__mock_stdout', write: function() { }, read: function() { }, pipe: function() { } } stderr = { id: '__mock_stderr', write: function() { }, read: function() { }, pipe: function() { } } } process.__defineGetter__('stdout', function() { if (stdout) return stdout; stdout = createWritableStdioStream(1); stdout.destroy = stdout.destroySoon = function(er) { er = er || new Error('process.stdout cannot be closed.'); stdout.emit('error', er); }; if (stdout.isTTY) { process.on('SIGWINCH', function() { stdout._refreshSize(); }); } return stdout; }); process.__defineGetter__('stderr', function() { if (stderr) return stderr; stderr = createWritableStdioStream(2); stderr.destroy = stderr.destroySoon = function(er) { er = er || new Error('process.stderr cannot be closed.'); stderr.emit('error', er); }; return stderr; }); process.__defineGetter__('stdin', function() { if (stdin) return stdin; var tty_wrap = process.binding('tty_wrap'); var fd = 0; switch (tty_wrap.guessHandleType(fd)) { case 'TTY': var tty = NativeModule.require('tty'); stdin = new tty.ReadStream(fd, { highWaterMark: 0, readable: true, writable: false }); break; case 'FILE': var fs = NativeModule.require('fs'); stdin = new fs.ReadStream(null, { fd: fd }); break; case 'PIPE': case 'TCP': var net = NativeModule.require('net'); stdin = new net.Socket({ fd: fd, readable: true, writable: false }); break; default: // Probably an error on in uv_guess_handle() throw new Error('Implement me. Unknown stdin file type!'); } // For supporting legacy API we put the FD here. stdin.fd = fd; // stdin starts out life in a paused state, but node doesn't // know yet. Explicitly to readStop() it to put it in the // not-reading state. if (stdin._handle && stdin._handle.readStop) { stdin._handle.reading = false; stdin._readableState.reading = false; stdin._handle.readStop(); } // if the user calls stdin.pause(), then we need to stop reading // immediately, so that the process can close down. stdin.on('pause', function() { if (!stdin._handle) return; stdin._readableState.reading = false; stdin._handle.reading = false; stdin._handle.readStop(); }); return stdin; }); process.openStdin = function() { process.stdin.resume(); return process.stdin; }; }; startup.processKillAndExit = function() { process.exit = function(code) { if (!process._exiting) { process._exiting = true; process.emit('exit', code || 0); } process.reallyExit(code || 0); }; process.kill = function(pid, sig) { var r; // preserve null signal if (0 === sig) { r = process._kill(pid, 0); } else { sig = sig || 'SIGTERM'; if (startup.lazyConstants()[sig]) { r = process._kill(pid, startup.lazyConstants()[sig]); } else { throw new Error('Unknown signal: ' + sig); } } if (r) { throw errnoException(process._errno, 'kill'); } return true; }; }; startup.processSignalHandlers = function() { // Load events module in order to access prototype elements on process like // process.addListener. var signalWraps = {}; var addListener = process.addListener; var removeListener = process.removeListener; function isSignal(event) { return event.slice(0, 3) === 'SIG' && startup.lazyConstants().hasOwnProperty(event); } // Wrap addListener for the special signal types process.on = process.addListener = function(type, listener) { if (isSignal(type) && !signalWraps.hasOwnProperty(type)) { var Signal = process.binding('signal_wrap').Signal; var wrap = new Signal(); wrap.unref(); wrap.onsignal = function() { process.emit(type); }; var signum = startup.lazyConstants()[type]; var r = wrap.start(signum); if (r) { wrap.close(); throw errnoException(process._errno, 'uv_signal_start'); } signalWraps[type] = wrap; } return addListener.apply(this, arguments); }; process.removeListener = function(type, listener) { var ret = removeListener.apply(this, arguments); if (isSignal(type)) { assert(signalWraps.hasOwnProperty(type)); if (this.listeners(type).length === 0) { signalWraps[type].close(); delete signalWraps[type]; } } return ret; }; }; startup.processChannel = function() { // If we were spawned with env NODE_CHANNEL_FD then load that up and // start parsing data from that stream. if (process.env.NODE_CHANNEL_FD) { var fd = parseInt(process.env.NODE_CHANNEL_FD, 10); assert(fd >= 0); // Make sure it's not accidentally inherited by child processes. delete process.env.NODE_CHANNEL_FD; var cp = NativeModule.require('child_process'); // Load tcp_wrap to avoid situation where we might immediately receive // a message. // FIXME is this really necessary? process.binding('tcp_wrap'); cp._forkChild(fd); assert(process.send); } } startup.resolveArgv0 = function() { var cwd = process.cwd(); var isWindows = process.platform === 'win32'; // Make process.argv[0] into a full path, but only touch argv[0] if it's // not a system $PATH lookup. // TODO: Make this work on Windows as well. Note that "node" might // execute cwd\node.exe, or some %PATH%\node.exe on Windows, // and that every directory has its own cwd, so d:node.exe is valid. var argv0 = process.argv[0]; if (!isWindows && argv0.indexOf('/') !== -1 && argv0.charAt(0) !== '/') { var path = NativeModule.require('path'); process.argv[0] = path.join(cwd, process.argv[0]); } }; // Below you find a minimal module system, which is used to load the node // core modules found in lib/*.js. All core modules are compiled into the // node binary, so they can be loaded faster. var Script = process.binding('evals').NodeScript; var runInThisContext = Script.runInThisContext; function NativeModule(id) { this.filename = id + '.js'; this.id = id; this.exports = {}; this.loaded = false; } NativeModule._source = process.binding('natives'); NativeModule._cache = {}; NativeModule.require = function(id) { if (id == 'native_module') { return NativeModule; } var cached = NativeModule.getCached(id); if (cached) { return cached.exports; } if (!NativeModule.exists(id)) { throw new Error('No such native module ' + id); } process.moduleLoadList.push('NativeModule ' + id); var nativeModule = new NativeModule(id); nativeModule.cache(); nativeModule.compile(); return nativeModule.exports; }; if (process.ischakra) { NativeModule.requireBuiltinModule = process.binding('nativerequire_wrap').requireBuiltinModule; } NativeModule.getCached = function(id) { return NativeModule._cache[id]; } NativeModule.exists = function(id) { return NativeModule._source.hasOwnProperty(id); } NativeModule.getSource = function (id) { if (process.ischakra) { // this will happen only when repl is used return process.lazyBindBuiltinModule(id); } else { return NativeModule._source[id]; } } NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = [ '(function(exports, require, module, __filename, __dirname) { ', '\n});' ]; NativeModule.prototype.compile = function() { if (process.ischakra) { // prevent us from fetching large strings into javascript var fn = NativeModule.requireBuiltinModule(this.id); fn(this.exports, NativeModule.require, this, this.filename); } else { // original node.js code var source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); var fn = runInThisContext(source, this.filename, true); fn(this.exports, NativeModule.require, this, this.filename); } this.loaded = true; }; NativeModule.prototype.cache = function() { NativeModule._cache[this.id] = this; }; startup(); }); // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // Note: In 0.8 and before, crypto functions all defaulted to using // binary-encoded strings rather than buffers. exports.DEFAULT_ENCODING = 'buffer'; try { var binding = process.binding('crypto'); var SecureContext = binding.SecureContext; var randomBytes = binding.randomBytes; var pseudoRandomBytes = binding.pseudoRandomBytes; var getCiphers = binding.getCiphers; var getHashes = binding.getHashes; var crypto = true; } catch (e) { var crypto = false; } var stream = require('stream'); var util = require('util'); // This is here because many functions accepted binary strings without // any explicit encoding in older versions of node, and we don't want // to break them unnecessarily. function toBuf(str, encoding) { encoding = encoding || 'binary'; if (typeof str === 'string') { if (encoding === 'buffer') encoding = 'binary'; str = new Buffer(str, encoding); } return str; } var assert = require('assert'); var StringDecoder = require('string_decoder').StringDecoder; function Credentials(secureProtocol, flags, context) { if (!(this instanceof Credentials)) { return new Credentials(secureProtocol, flags, context); } if (!crypto) { throw new Error('node.js not compiled with openssl crypto support.'); } if (context) { this.context = context; } else { this.context = new SecureContext(); if (secureProtocol) { this.context.init(secureProtocol); } else { this.context.init(); } } if (flags) this.context.setOptions(flags); } exports.Credentials = Credentials; exports.createCredentials = function(options, context) { if (!options) options = {}; var c = new Credentials(options.secureProtocol, options.secureOptions, context); if (context) return c; if (options.key) { if (options.passphrase) { c.context.setKey(options.key, options.passphrase); } else { c.context.setKey(options.key); } } if (options.cert) c.context.setCert(options.cert); if (options.ciphers) c.context.setCiphers(options.ciphers); if (options.ca) { if (Array.isArray(options.ca)) { for (var i = 0, len = options.ca.length; i < len; i++) { c.context.addCACert(options.ca[i]); } } else { c.context.addCACert(options.ca); } } else { c.context.addRootCerts(); } if (options.crl) { if (Array.isArray(options.crl)) { for (var i = 0, len = options.crl.length; i < len; i++) { c.context.addCRL(options.crl[i]); } } else { c.context.addCRL(options.crl); } } if (options.sessionIdContext) { c.context.setSessionIdContext(options.sessionIdContext); } if (options.pfx) { var pfx = options.pfx; var passphrase = options.passphrase; pfx = toBuf(pfx); if (passphrase) passphrase = toBuf(passphrase); if (passphrase) { c.context.loadPKCS12(pfx, passphrase); } else { c.context.loadPKCS12(pfx); } } return c; }; function LazyTransform(options) { this._options = options; } util.inherits(LazyTransform, stream.Transform); [ '_readableState', '_writableState', '_transformState' ].forEach(function(prop, i, props) { Object.defineProperty(LazyTransform.prototype, prop, { get: function() { stream.Transform.call(this, this._options); this._writableState.decodeStrings = false; this._writableState.defaultEncoding = 'binary'; return this[prop]; }, set: function(val) { Object.defineProperty(this, prop, { value: val, enumerable: true, configurable: true, writable: true }); }, configurable: true, enumerable: true }); }); exports.createHash = exports.Hash = Hash; function Hash(algorithm, options) { if (!(this instanceof Hash)) return new Hash(algorithm, options); this._binding = new binding.Hash(algorithm); LazyTransform.call(this, options); } util.inherits(Hash, LazyTransform); Hash.prototype._transform = function(chunk, encoding, callback) { this._binding.update(chunk, encoding); callback(); }; Hash.prototype._flush = function(callback) { var encoding = this._readableState.encoding || 'buffer'; this.push(this._binding.digest(encoding), encoding); callback(); }; Hash.prototype.update = function(data, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; if (encoding === 'buffer' && typeof data === 'string') encoding = 'binary'; this._binding.update(data, encoding); return this; }; Hash.prototype.digest = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; return this._binding.digest(outputEncoding); }; exports.createHmac = exports.Hmac = Hmac; function Hmac(hmac, key, options) { if (!(this instanceof Hmac)) return new Hmac(hmac, key, options); this._binding = new binding.Hmac(); this._binding.init(hmac, toBuf(key)); LazyTransform.call(this, options); } util.inherits(Hmac, LazyTransform); Hmac.prototype.update = Hash.prototype.update; Hmac.prototype.digest = Hash.prototype.digest; Hmac.prototype._flush = Hash.prototype._flush; Hmac.prototype._transform = Hash.prototype._transform; function getDecoder(decoder, encoding) { decoder = decoder || new StringDecoder(encoding); assert(decoder.encoding === encoding, 'Cannot change encoding'); return decoder; } exports.createCipher = exports.Cipher = Cipher; function Cipher(cipher, password, options) { if (!(this instanceof Cipher)) return new Cipher(cipher, password, options); this._binding = new binding.Cipher; this._binding.init(cipher, toBuf(password)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Cipher, LazyTransform); Cipher.prototype._transform = function(chunk, encoding, callback) { this.push(this._binding.update(chunk, encoding)); callback(); }; Cipher.prototype._flush = function(callback) { this.push(this._binding.final()); callback(); }; Cipher.prototype.update = function(data, inputEncoding, outputEncoding) { inputEncoding = inputEncoding || exports.DEFAULT_ENCODING; outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; var ret = this._binding.update(data, inputEncoding); if (outputEncoding && outputEncoding !== 'buffer') { this._decoder = getDecoder(this._decoder, outputEncoding); ret = this._decoder.write(ret); } return ret; }; Cipher.prototype.final = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; var ret = this._binding.final(); if (outputEncoding && outputEncoding !== 'buffer') { this._decoder = getDecoder(this._decoder, outputEncoding); ret = this._decoder.end(ret); } return ret; }; Cipher.prototype.setAutoPadding = function(ap) { this._binding.setAutoPadding(ap); return this; }; exports.createCipheriv = exports.Cipheriv = Cipheriv; function Cipheriv(cipher, key, iv, options) { if (!(this instanceof Cipheriv)) return new Cipheriv(cipher, key, iv, options); this._binding = new binding.Cipher(); this._binding.initiv(cipher, toBuf(key), toBuf(iv)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Cipheriv, LazyTransform); Cipheriv.prototype._transform = Cipher.prototype._transform; Cipheriv.prototype._flush = Cipher.prototype._flush; Cipheriv.prototype.update = Cipher.prototype.update; Cipheriv.prototype.final = Cipher.prototype.final; Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createDecipher = exports.Decipher = Decipher; function Decipher(cipher, password, options) { if (!(this instanceof Decipher)) return new Decipher(cipher, password, options); this._binding = new binding.Decipher; this._binding.init(cipher, toBuf(password)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Decipher, LazyTransform); Decipher.prototype._transform = Cipher.prototype._transform; Decipher.prototype._flush = Cipher.prototype._flush; Decipher.prototype.update = Cipher.prototype.update; Decipher.prototype.final = Cipher.prototype.final; Decipher.prototype.finaltol = Cipher.prototype.final; Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createDecipheriv = exports.Decipheriv = Decipheriv; function Decipheriv(cipher, key, iv, options) { if (!(this instanceof Decipheriv)) return new Decipheriv(cipher, key, iv, options); this._binding = new binding.Decipher; this._binding.initiv(cipher, toBuf(key), toBuf(iv)); this._decoder = null; LazyTransform.call(this, options); } util.inherits(Decipheriv, LazyTransform); Decipheriv.prototype._transform = Cipher.prototype._transform; Decipheriv.prototype._flush = Cipher.prototype._flush; Decipheriv.prototype.update = Cipher.prototype.update; Decipheriv.prototype.final = Cipher.prototype.final; Decipheriv.prototype.finaltol = Cipher.prototype.final; Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; exports.createSign = exports.Sign = Sign; function Sign(algorithm, options) { if (!(this instanceof Sign)) return new Sign(algorithm, options); this._binding = new binding.Sign(); this._binding.init(algorithm); stream.Writable.call(this, options); } util.inherits(Sign, stream.Writable); Sign.prototype._write = function(chunk, encoding, callback) { this._binding.update(chunk, encoding); callback(); }; Sign.prototype.update = Hash.prototype.update; Sign.prototype.sign = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; var ret = this._binding.sign(toBuf(key)); if (encoding && encoding !== 'buffer') ret = ret.toString(encoding); return ret; }; exports.createVerify = exports.Verify = Verify; function Verify(algorithm, options) { if (!(this instanceof Verify)) return new Verify(algorithm, options); this._binding = new binding.Verify; this._binding.init(algorithm); stream.Writable.call(this, options); } util.inherits(Verify, stream.Writable); Verify.prototype._write = Sign.prototype._write; Verify.prototype.update = Sign.prototype.update; Verify.prototype.verify = function(object, signature, sigEncoding) { sigEncoding = sigEncoding || exports.DEFAULT_ENCODING; return this._binding.verify(toBuf(object), toBuf(signature, sigEncoding)); }; exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman; function DiffieHellman(sizeOrKey, encoding) { if (!(this instanceof DiffieHellman)) return new DiffieHellman(sizeOrKey, encoding); if (!sizeOrKey) this._binding = new binding.DiffieHellman(); else { encoding = encoding || exports.DEFAULT_ENCODING; sizeOrKey = toBuf(sizeOrKey, encoding); this._binding = new binding.DiffieHellman(sizeOrKey); } } exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = DiffieHellmanGroup; function DiffieHellmanGroup(name) { if (!(this instanceof DiffieHellmanGroup)) return new DiffieHellmanGroup(name); this._binding = new binding.DiffieHellmanGroup(name); } DiffieHellmanGroup.prototype.generateKeys = DiffieHellman.prototype.generateKeys = dhGenerateKeys; function dhGenerateKeys(encoding) { var keys = this._binding.generateKeys(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') keys = keys.toString(encoding); return keys; } DiffieHellmanGroup.prototype.computeSecret = DiffieHellman.prototype.computeSecret = dhComputeSecret; function dhComputeSecret(key, inEnc, outEnc) { inEnc = inEnc || exports.DEFAULT_ENCODING; outEnc = outEnc || exports.DEFAULT_ENCODING; var ret = this._binding.computeSecret(toBuf(key, inEnc)); if (outEnc && outEnc !== 'buffer') ret = ret.toString(outEnc); return ret; } DiffieHellmanGroup.prototype.getPrime = DiffieHellman.prototype.getPrime = dhGetPrime; function dhGetPrime(encoding) { var prime = this._binding.getPrime(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') prime = prime.toString(encoding); return prime; } DiffieHellmanGroup.prototype.getGenerator = DiffieHellman.prototype.getGenerator = dhGetGenerator; function dhGetGenerator(encoding) { var generator = this._binding.getGenerator(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') generator = generator.toString(encoding); return generator; } DiffieHellmanGroup.prototype.getPublicKey = DiffieHellman.prototype.getPublicKey = dhGetPublicKey; function dhGetPublicKey(encoding) { var key = this._binding.getPublicKey(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') key = key.toString(encoding); return key; } DiffieHellmanGroup.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey = dhGetPrivateKey; function dhGetPrivateKey(encoding) { var key = this._binding.getPrivateKey(); encoding = encoding || exports.DEFAULT_ENCODING; if (encoding && encoding !== 'buffer') key = key.toString(encoding); return key; } DiffieHellman.prototype.setPublicKey = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; this._binding.setPublicKey(toBuf(key, encoding)); return this; }; DiffieHellman.prototype.setPrivateKey = function(key, encoding) { encoding = encoding || exports.DEFAULT_ENCODING; this._binding.setPrivateKey(toBuf(key, encoding)); return this; }; exports.pbkdf2 = function(password, salt, iterations, keylen, callback) { if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2'); return pbkdf2(password, salt, iterations, keylen, callback); }; exports.pbkdf2Sync = function(password, salt, iterations, keylen) { return pbkdf2(password, salt, iterations, keylen); }; function pbkdf2(password, salt, iterations, keylen, callback) { password = toBuf(password); salt = toBuf(salt); if (exports.DEFAULT_ENCODING === 'buffer') return binding.PBKDF2(password, salt, iterations, keylen, callback); // at this point, we need to handle encodings. var encoding = exports.DEFAULT_ENCODING; if (callback) { binding.PBKDF2(password, salt, iterations, keylen, function(er, ret) { if (ret) ret = ret.toString(encoding); callback(er, ret); }); } else { var ret = binding.PBKDF2(password, salt, iterations, keylen); return ret.toString(encoding); } } exports.randomBytes = randomBytes; exports.pseudoRandomBytes = pseudoRandomBytes; exports.rng = randomBytes; exports.prng = pseudoRandomBytes; exports.getCiphers = function() { return filterDuplicates(getCiphers.call(null, arguments)); }; exports.getHashes = function() { return filterDuplicates(getHashes.call(null, arguments)); }; function filterDuplicates(names) { // Drop all-caps names in favor of their lowercase aliases, // for example, 'sha1' instead of 'SHA1'. var ctx = {}; names.forEach(function(name) { if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); ctx[name] = true; }); return Object.getOwnPropertyNames(ctx).sort(); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var tls = require('tls'); var http = require('http'); var util = require('util'); var url = require('url'); var inherits = require('util').inherits; function Server(opts, requestListener) { if (!(this instanceof Server)) return new Server(opts, requestListener); if (process.features.tls_npn && !opts.NPNProtocols) { opts.NPNProtocols = ['http/1.1', 'http/1.0']; } tls.Server.call(this, opts, http._connectionListener); this.httpAllowHalfOpen = false; if (requestListener) { this.addListener('request', requestListener); } this.addListener('clientError', function(err, conn) { conn.destroy(err); }); } inherits(Server, tls.Server); exports.Server = Server; exports.createServer = function(opts, requestListener) { return new Server(opts, requestListener); }; // HTTPS agents. function createConnection(port, host, options) { if (typeof port === 'object') { options = port; } else if (typeof host === 'object') { options = host; } else if (typeof options === 'object') { options = options; } else { options = {}; } if (typeof port === 'number') { options.port = port; } if (typeof host === 'string') { options.host = host; } return tls.connect(options); } function Agent(options) { http.Agent.call(this, options); this.createConnection = createConnection; } inherits(Agent, http.Agent); Agent.prototype.defaultPort = 443; var globalAgent = new Agent(); exports.globalAgent = globalAgent; exports.Agent = Agent; exports.request = function(options, cb) { if (typeof options === 'string') { options = url.parse(options); } if (options.protocol && options.protocol !== 'https:') { throw new Error('Protocol:' + options.protocol + ' not supported.'); } options = util._extend({ createConnection: createConnection, defaultPort: 443 }, options); if (typeof options.agent === 'undefined') { if (typeof options.ca === 'undefined' && typeof options.cert === 'undefined' && typeof options.ciphers === 'undefined' && typeof options.key === 'undefined' && typeof options.passphrase === 'undefined' && typeof options.pfx === 'undefined' && typeof options.rejectUnauthorized === 'undefined') { options.agent = globalAgent; } else { options.agent = new Agent(options); } } return new http.ClientRequest(options, cb); }; exports.get = function(options, cb) { var req = exports.request(options, cb); req.end(); return req; }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // a duplex stream is just a stream that is both readable and writable. // Since JS doesn't have multiple prototypal inheritance, this class // prototypally inherits from Readable, and then parasitically from // Writable. module.exports = Duplex; var util = require('util'); var Readable = require('_stream_readable'); var Writable = require('_stream_writable'); util.inherits(Duplex, Readable); Object.keys(Writable.prototype).forEach(function(method) { if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; }); function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); Readable.call(this, options); Writable.call(this, options); if (options && options.readable === false) this.readable = false; if (options && options.writable === false) this.writable = false; this.allowHalfOpen = true; if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; this.once('end', onend); } // the no-half-open enforcer function onend() { // if we allow half-open state, or if the writable side ended, // then we're ok. if (this.allowHalfOpen || this._writableState.ended) return; // no more data can be written. // But allow more writes to happen in this tick. process.nextTick(this.end.bind(this)); } // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var util = require('util'); function Console(stdout, stderr) { if (!(this instanceof Console)) { return new Console(stdout, stderr); } if (!stdout || typeof stdout.write !== 'function') { throw new TypeError('Console expects a writable stream instance'); } if (!stderr) { stderr = stdout; } var prop = { writable: true, enumerable: false, configurable: true }; prop.value = stdout; Object.defineProperty(this, '_stdout', prop); prop.value = stderr; Object.defineProperty(this, '_stderr', prop); prop.value = {}; Object.defineProperty(this, '_times', prop); // bind the prototype functions to this Console instance Object.keys(Console.prototype).forEach(function(k) { this[k] = this[k].bind(this); }, this); } Console.prototype.log = function() { this._stdout.write(util.format.apply(this, arguments) + '\n'); }; Console.prototype.info = Console.prototype.log; Console.prototype.warn = function() { this._stderr.write(util.format.apply(this, arguments) + '\n'); }; Console.prototype.error = Console.prototype.warn; Console.prototype.dir = function(object) { this._stdout.write(util.inspect(object) + '\n'); }; Console.prototype.time = function(label) { this._times[label] = Date.now(); }; Console.prototype.timeEnd = function(label) { var time = this._times[label]; if (!time) { throw new Error('No such label: ' + label); } var duration = Date.now() - time; this.log('%s: %dms', label, duration); }; Console.prototype.trace = function() { // TODO probably can to do this better with V8's debug object once that is // exposed. var err = new Error; err.name = 'Trace'; err.message = util.format.apply(this, arguments); Error.captureStackTrace(err, arguments.callee); this.error(err.stack); }; Console.prototype.assert = function(expression) { if (!expression) { var arr = Array.prototype.slice.call(arguments, 1); require('assert').ok(false, util.format.apply(this, arr)); } }; module.exports = new Console(process.stdout, process.stderr); module.exports.Console = Console; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var SlowBuffer = process.binding('buffer').SlowBuffer; var assert = require('assert'); exports.INSPECT_MAX_BYTES = 50; // Make SlowBuffer inherit from Buffer. // This is an exception to the rule that __proto__ is not allowed in core. SlowBuffer.prototype.__proto__ = Buffer.prototype; function clamp(index, len, defaultValue) { if (typeof index !== 'number') return defaultValue; index = ~~index; // Coerce to integer. if (index >= len) return len; if (index >= 0) return index; index += len; if (index >= 0) return index; return 0; } function toHex(n) { if (n < 16) return '0' + n.toString(16); return n.toString(16); } SlowBuffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); start = +start || 0; if (typeof end !== 'number') end = this.length; // Fastpath empty strings if (+end == start) { return ''; } switch (encoding) { case 'hex': return this.hexSlice(start, end); case 'utf8': case 'utf-8': return this.utf8Slice(start, end); case 'ascii': return this.asciiSlice(start, end); case 'binary': return this.binarySlice(start, end); case 'base64': return this.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.ucs2Slice(start, end); default: throw new TypeError('Unknown encoding: ' + encoding); } }; SlowBuffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); switch (encoding) { case 'hex': return this.hexWrite(string, offset, length); case 'utf8': case 'utf-8': return this.utf8Write(string, offset, length); case 'ascii': return this.asciiWrite(string, offset, length); case 'binary': return this.binaryWrite(string, offset, length); case 'base64': return this.base64Write(string, offset, length); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.ucs2Write(string, offset, length); default: throw new TypeError('Unknown encoding: ' + encoding); } }; // slice(start, end) SlowBuffer.prototype.slice = function(start, end) { var len = this.length; start = clamp(start, len, 0); end = clamp(end, len, len); return new Buffer(this, end - start, start); }; var zeroBuffer = new SlowBuffer(0); // Buffer function Buffer(subject, encoding, offset) { if (!(this instanceof Buffer)) { return new Buffer(subject, encoding, offset); } var buffer = this; // chakra-specific code if (SlowBuffer.makeFastBufferObject !== undefined) { buffer = SlowBuffer.makeFastBufferObject(); buffer.__proto__ = this.__proto__; } var type; // Are we slicing? if (typeof offset === 'number') { if (!Buffer.isBuffer(subject)) { throw new TypeError('First argument must be a Buffer when slicing'); } buffer.length = +encoding > 0 ? Math.ceil(encoding) : 0; buffer.parent = subject.parent ? subject.parent : subject; buffer.offset = offset; } else { // Find the length switch (type = typeof subject) { case 'number': buffer.length = +subject > 0 ? Math.ceil(subject) : 0; break; case 'string': buffer.length = Buffer.byteLength(subject, encoding); break; case 'object': // Assume object is array-ish buffer.length = +subject.length > 0 ? Math.ceil(subject.length) : 0; break; default: throw new TypeError('First argument needs to be a number, ' + 'array or string.'); } if (buffer.length > Buffer.poolSize) { // Big buffer, just alloc one. buffer.parent = new SlowBuffer(buffer.length); buffer.offset = 0; } else if (buffer.length > 0) { // Small buffer. if (!pool || pool.length - pool.used < buffer.length) allocPool(); buffer.parent = pool; buffer.offset = pool.used; pool.used += buffer.length; if (pool.used & 7) pool.used = (pool.used + 8) & ~7; } else { // Zero-length buffer buffer.parent = zeroBuffer; buffer.offset = 0; } // optimize by branching logic for new allocations if (typeof subject !== 'number') { if (type === 'string') { // We are a string buffer.length = buffer.write(subject, 0, encoding); // if subject is buffer then use built-in copy method } else if (Buffer.isBuffer(subject)) { if (subject.parent) subject.parent.copy(buffer.parent, buffer.offset, subject.offset, buffer.length + subject.offset); else subject.copy(buffer.parent, buffer.offset, 0, buffer.length); } else if (isArrayIsh(subject)) { for (var i = 0; i < buffer.length; i++) buffer.parent[i + buffer.offset] = subject[i]; } } } SlowBuffer.makeFastBuffer( buffer.parent, buffer, buffer.offset, buffer.length); return buffer; } function isArrayIsh(subject) { return Array.isArray(subject) || subject && typeof subject === 'object' && typeof subject.length === 'number'; } exports.SlowBuffer = SlowBuffer; exports.Buffer = Buffer; Buffer.isEncoding = function(encoding) { switch (encoding && encoding.toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; default: return false; } }; Buffer.poolSize = 8 * 1024; var pool; function allocPool() { pool = new SlowBuffer(Buffer.poolSize); pool.used = 0; } // Static methods Buffer.isBuffer = function isBuffer(b) { return b instanceof Buffer; }; // Inspect Buffer.prototype.inspect = function inspect() { var out = [], len = this.length, name = this.constructor.name; for (var i = 0; i < len; i++) { out[i] = toHex(this[i]); if (i == exports.INSPECT_MAX_BYTES) { out[i + 1] = '...'; break; } } return '<' + name + ' ' + out.join(' ') + '>'; }; Buffer.prototype.get = function get(offset) { if (offset < 0 || offset >= this.length) throw new RangeError('offset is out of bounds'); return this.parent[this.offset + offset]; }; Buffer.prototype.set = function set(offset, v) { if (offset < 0 || offset >= this.length) throw new RangeError('offset is out of bounds'); return this.parent[this.offset + offset] = v; }; // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8') Buffer.prototype.write = function(string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { if (!isFinite(length)) { encoding = length; length = undefined; } } else { // legacy var swap = encoding; encoding = offset; offset = length; length = swap; } offset = +offset || 0; var remaining = this.length - offset; if (!length) { length = remaining; } else { length = +length; if (length > remaining) { length = remaining; } } encoding = String(encoding || 'utf8').toLowerCase(); if (string.length > 0 && (length < 0 || offset < 0)) throw new RangeError('attempt to write beyond buffer bounds'); var ret; switch (encoding) { case 'hex': ret = this.parent.hexWrite(string, this.offset + offset, length); break; case 'utf8': case 'utf-8': ret = this.parent.utf8Write(string, this.offset + offset, length); break; case 'ascii': ret = this.parent.asciiWrite(string, this.offset + offset, length); break; case 'binary': ret = this.parent.binaryWrite(string, this.offset + offset, length); break; case 'base64': // Warning: maxLength not taken into account in base64Write ret = this.parent.base64Write(string, this.offset + offset, length); break; case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': ret = this.parent.ucs2Write(string, this.offset + offset, length); break; default: throw new TypeError('Unknown encoding: ' + encoding); } Buffer._charsWritten = SlowBuffer._charsWritten; return ret; }; Buffer.prototype.toJSON = function () { // CHAKRA: since buffer is a Proxy object we are seeing Array.prototype.slice.call retunring an arrays of nulls // not sure if it's a bug or not, but this is a workaround for this issue if (process.ischakra) { var arr = new Array(this.length); for (var i = 0; i < this.length; i++) { // this will make sure that we are retreiving the value through the proxy arr[i] = this[i]; } return arr; } else { return Array.prototype.slice.call(this, 0); } }; // toString(encoding, start=0, end=buffer.length) Buffer.prototype.toString = function(encoding, start, end) { encoding = String(encoding || 'utf8').toLowerCase(); if (typeof start !== 'number' || start < 0) { start = 0; } else if (start > this.length) { start = this.length; } if (typeof end !== 'number' || end > this.length) { end = this.length; } else if (end < 0) { end = 0; } start = start + this.offset; end = end + this.offset; switch (encoding) { case 'hex': return this.parent.hexSlice(start, end); case 'utf8': case 'utf-8': return this.parent.utf8Slice(start, end); case 'ascii': return this.parent.asciiSlice(start, end); case 'binary': return this.parent.binarySlice(start, end); case 'base64': return this.parent.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return this.parent.ucs2Slice(start, end); default: throw new TypeError('Unknown encoding: ' + encoding); } }; // byteLength Buffer.byteLength = SlowBuffer.byteLength; // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function fill(value, start, end) { value || (value = 0); start || (start = 0); end || (end = this.length); if (typeof value === 'string') { value = value.charCodeAt(0); } if (typeof value !== 'number' || isNaN(value)) { throw new TypeError('value is not a number'); } if (end < start) throw new RangeError('end < start'); // Fill 0 bytes; we're done if (end === start) return 0; if (this.length == 0) return 0; if (start < 0 || start >= this.length) { throw new RangeError('start out of bounds'); } if (end < 0 || end > this.length) { throw new RangeError('end out of bounds'); } return this.parent.fill(value, start + this.offset, end + this.offset); }; Buffer.concat = function(list, length) { if (!Array.isArray(list)) { throw new TypeError('Usage: Buffer.concat(list, [length])'); } if (list.length === 0) { return new Buffer(0); } else if (list.length === 1) { return list[0]; } if (typeof length !== 'number') { length = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; length += buf.length; } } var buffer = new Buffer(length); var pos = 0; for (var i = 0; i < list.length; i++) { var buf = list[i]; buf.copy(buffer, pos); pos += buf.length; } return buffer; }; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function(target, target_start, start, end) { // set undefined/NaN or out of bounds values equal to their default if (!(target_start >= 0)) target_start = 0; if (!(start >= 0)) start = 0; if (!(end < this.length)) end = this.length; // Copy 0 bytes; we're done if (end === start || target.length === 0 || this.length === 0 || start > this.length) return 0; if (end < start) throw new RangeError('sourceEnd < sourceStart'); if (target_start >= target.length) throw new RangeError('targetStart out of bounds'); if (target.length - target_start < end - start) end = target.length - target_start + start; return this.parent.copy(target.parent || target, target_start + (target.offset || 0), start + this.offset, end + this.offset); }; // slice(start, end) Buffer.prototype.slice = function(start, end) { var len = this.length; start = clamp(start, len, 0); end = clamp(end, len, len); return new Buffer(this.parent, end - start, start + this.offset); }; // Legacy methods for backwards compatibility. Buffer.prototype.utf8Slice = function(start, end) { return this.toString('utf8', start, end); }; Buffer.prototype.binarySlice = function(start, end) { return this.toString('binary', start, end); }; Buffer.prototype.asciiSlice = function(start, end) { return this.toString('ascii', start, end); }; Buffer.prototype.utf8Write = function(string, offset) { return this.write(string, offset, 'utf8'); }; Buffer.prototype.binaryWrite = function(string, offset) { return this.write(string, offset, 'binary'); }; Buffer.prototype.asciiWrite = function(string, offset) { return this.write(string, offset, 'ascii'); }; /* * Need to make sure that buffer isn't trying to write out of bounds. * This check is far too slow internally for fast buffers. */ function checkOffset(offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint'); if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length'); } Buffer.prototype.readUInt8 = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length); return this[offset]; }; function readUInt16(buffer, offset, isBigEndian) { var val = 0; if (isBigEndian) { val = buffer[offset] << 8; val |= buffer[offset + 1]; } else { val = buffer[offset]; val |= buffer[offset + 1] << 8; } return val; } Buffer.prototype.readUInt16LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readUInt16(this, offset, false, noAssert); }; Buffer.prototype.readUInt16BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readUInt16(this, offset, true, noAssert); }; function readUInt32(buffer, offset, isBigEndian, noAssert) { var val = 0; if (isBigEndian) { val = buffer[offset + 1] << 16; val |= buffer[offset + 2] << 8; val |= buffer[offset + 3]; val = val + (buffer[offset] << 24 >>> 0); } else { val = buffer[offset + 2] << 16; val |= buffer[offset + 1] << 8; val |= buffer[offset]; val = val + (buffer[offset + 3] << 24 >>> 0); } return val; } Buffer.prototype.readUInt32LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readUInt32(this, offset, false, noAssert); }; Buffer.prototype.readUInt32BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readUInt32(this, offset, true, noAssert); }; /* * Signed integer types, yay team! A reminder on how two's complement actually * works. The first bit is the signed bit, i.e. tells us whether or not the * number should be positive or negative. If the two's complement value is * positive, then we're done, as it's equivalent to the unsigned representation. * * Now if the number is positive, you're pretty much done, you can just leverage * the unsigned translations and return those. Unfortunately, negative numbers * aren't quite that straightforward. * * At first glance, one might be inclined to use the traditional formula to * translate binary numbers between the positive and negative values in two's * complement. (Though it doesn't quite work for the most negative value) * Mainly: * - invert all the bits * - add one to the result * * Of course, this doesn't quite work in Javascript. Take for example the value * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of * course, Javascript will do the following: * * > ~0xff80 * -65409 * * Whoh there, Javascript, that's not quite right. But wait, according to * Javascript that's perfectly correct. When Javascript ends up seeing the * constant 0xff80, it has no notion that it is actually a signed number. It * assumes that we've input the unsigned value 0xff80. Thus, when it does the * binary negation, it casts it into a signed value, (positive 0xff80). Then * when you perform binary negation on that, it turns it into a negative number. * * Instead, we're going to have to use the following general formula, that works * in a rather Javascript friendly way. I'm glad we don't support this kind of * weird numbering scheme in the kernel. * * (BIT-MAX - (unsigned)val + 1) * -1 * * The astute observer, may think that this doesn't make sense for 8-bit numbers * (really it isn't necessary for them). However, when you get 16-bit numbers, * you do. Let's go back to our prior example and see how this will look: * * (0xffff - 0xff80 + 1) * -1 * (0x007f + 1) * -1 * (0x0080) * -1 */ Buffer.prototype.readInt8 = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length); if (!(this[offset] & 0x80)) return (this[offset]); return ((0xff - this[offset] + 1) * -1); }; function readInt16(buffer, offset, isBigEndian) { var val = readUInt16(buffer, offset, isBigEndian); if (!(val & 0x8000)) return val; return (0xffff - val + 1) * -1; } Buffer.prototype.readInt16LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readInt16(this, offset, false); }; Buffer.prototype.readInt16BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length); return readInt16(this, offset, true); }; function readInt32(buffer, offset, isBigEndian) { var val = readUInt32(buffer, offset, isBigEndian); if (!(val & 0x80000000)) return (val); return (0xffffffff - val + 1) * -1; } Buffer.prototype.readInt32LE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readInt32(this, offset, false); }; Buffer.prototype.readInt32BE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return readInt32(this, offset, true); }; Buffer.prototype.readFloatLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatLE(this.offset + offset, !!noAssert); }; Buffer.prototype.readFloatBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); return this.parent.readFloatBE(this.offset + offset, !!noAssert); }; Buffer.prototype.readDoubleLE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleLE(this.offset + offset, !!noAssert); }; Buffer.prototype.readDoubleBE = function(offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); return this.parent.readDoubleBE(this.offset + offset, !!noAssert); }; function checkInt(buffer, value, offset, ext, max, min) { if ((value % 1) !== 0 || value > max || value < min) throw TypeError('value is out of bounds'); if ((offset % 1) !== 0 || offset < 0) throw TypeError('offset is not uint'); if (offset + ext > buffer.length || buffer.length + offset < 0) throw RangeError('Trying to write outside buffer length'); } Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); this[offset] = value; }; function writeUInt16(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value & 0xff00) >>> 8; buffer[offset + 1] = value & 0x00ff; } else { buffer[offset + 1] = (value & 0xff00) >>> 8; buffer[offset] = value & 0x00ff; } } Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); writeUInt16(this, value, offset, false); }; Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); writeUInt16(this, value, offset, true); }; function writeUInt32(buffer, value, offset, isBigEndian) { if (isBigEndian) { buffer[offset] = (value >>> 24) & 0xff; buffer[offset + 1] = (value >>> 16) & 0xff; buffer[offset + 2] = (value >>> 8) & 0xff; buffer[offset + 3] = value & 0xff; } else { buffer[offset + 3] = (value >>> 24) & 0xff; buffer[offset + 2] = (value >>> 16) & 0xff; buffer[offset + 1] = (value >>> 8) & 0xff; buffer[offset] = value & 0xff; } } Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); writeUInt32(this, value, offset, false); }; Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); writeUInt32(this, value, offset, true); }; /* * We now move onto our friends in the signed number category. Unlike unsigned * numbers, we're going to have to worry a bit more about how we put values into * arrays. Since we are only worrying about signed 32-bit values, we're in * slightly better shape. Unfortunately, we really can't do our favorite binary * & in this system. It really seems to do the wrong thing. For example: * * > -32 & 0xff * 224 * * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of * this aren't treated as a signed number. Ultimately a bad thing. * * What we're going to want to do is basically create the unsigned equivalent of * our representation and pass that off to the wuint* functions. To do that * we're going to do the following: * * - if the value is positive * we can pass it directly off to the equivalent wuint * - if the value is negative * we do the following computation: * mb + val + 1, where * mb is the maximum unsigned value in that byte size * val is the Javascript negative integer * * * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If * you do out the computations: * * 0xffff - 128 + 1 * 0xffff - 127 * 0xff80 * * You can then encode this value as the signed version. This is really rather * hacky, but it should work and get the job done which is our goal here. */ Buffer.prototype.writeInt8 = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); if (value < 0) value = 0xff + value + 1; this[offset] = value; }; Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (value < 0) value = 0xffff + value + 1; writeUInt16(this, value, offset, false); }; Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (value < 0) value = 0xffff + value + 1; writeUInt16(this, value, offset, true); }; Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; writeUInt32(this, value, offset, false); }; Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (value < 0) value = 0xffffffff + value + 1; writeUInt32(this, value, offset, true); }; Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatLE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length); this.parent.writeFloatBE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleLE(value, this.offset + offset, !!noAssert); }; Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length); this.parent.writeDoubleBE(value, this.offset + offset, !!noAssert); }; // This file is based on or incorporates material from the projects listed // below (collectively "Third Party Code"). Microsoft is not the original // author of the Third Party Code. The original copyright notice and the // license, under which Microsoft received such Third Party Code, are set // forth below. Such licenses and notices are provided for informational // purposes only. Microsoft, not the third party, licenses the Third Party // Code to you under the terms set forth in the EULA for the Microsoft // Product. Microsoft reserves all other rights not expressly granted under // this agreement, whether by implication, estoppel or otherwise. // // node.js v.0.10.10 // Copyright Joyent, Inc. and other Node contributors. // // Provided for Informational Purposes Only // // MIT License // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the ""Software""), // to deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom // the Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module.exports = Readable; Readable.ReadableState = ReadableState; var EE = require('events').EventEmitter; var Stream = require('stream'); var util = require('util'); var StringDecoder; util.inherits(Readable, Stream); function ReadableState(options, stream) { options = options || {}; // the point at which it stops calling _read() to fill the buffer // Note: 0 is a valid value, means "don't call _read preemptively ever" var hwm = options.highWaterMark; this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; // cast to ints. this.highWaterMark = ~~this.highWaterMark; this.buffer = []; this.length = 0; this.pipes = null; this.pipesCount = 0; this.flowing = false; this.ended = false; this.endEmitted = false; this.reading = false; // In streams that never have any data, and do push(null) right away, // the consumer can miss the 'end' event if they do some I/O before // consuming the stream. So, we don't emit('end') until some reading // happens. this.calledRead = false; // a flag to be able to tell if the onwrite cb is called immediately, // or on a later tick. We set this to true at first, becuase any // actions that shouldn't happen until "later" should generally also // not happen before the first write call. this.sync = true; // whenever we return null, then we set a flag to say // that we're awaiting a 'readable' event emission. this.needReadable = false; this.emittedReadable = false; this.readableListening = false; // object stream flag. Used to make read(n) ignore n and to // make all the buffer merging and length checks go away this.objectMode = !!options.objectMode; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. // Everything else in the universe uses 'utf8', though. this.defaultEncoding = options.defaultEncoding || 'utf8'; // when piping, we only care about 'readable' events that happen // after read()ing all the bytes and not getting any pushback. this.ranOut = false; // the number of writers that are awaiting a drain event in .pipe()s this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled this.readingMore = false; this.decoder = null; this.encoding = null; if (options.encoding) { if (!StringDecoder) StringDecoder = require('string_decoder').StringDecoder; this.decoder = new StringDecoder(options.encoding); this.encoding = options.encoding; } } function Readable(options) { if (!(this instanceof Readable)) return new Readable(options); this._readableState = new ReadableState(options, this); // legacy this.readable = true; Stream.call(this); } // Manually shove something into the read() buffer. // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should // write() some more. Readable.prototype.push = function(chunk, encoding) { var state = this._readableState; if (typeof chunk === 'string' && !state.objectMode) { encoding = encoding || state.defaultEncoding; if (encoding !== state.encoding) { chunk = new Buffer(chunk, encoding); encoding = ''; } } return readableAddChunk(this, state, chunk, encoding, false); }; // Unshift should *always* be something directly out of read() Readable.prototype.unshift = function(chunk) { var state = this._readableState; return readableAddChunk(this, state, chunk, '', true); }; function readableAddChunk(stream, state, chunk, encoding, addToFront) { var er = chunkInvalid(state, chunk); if (er) { stream.emit('error', er); } else if (chunk === null || chunk === undefined) { state.reading = false; if (!state.ended) onEofChunk(stream, state); } else if (state.objectMode || chunk && chunk.length > 0) { if (state.ended && !addToFront) { var e = new Error('stream.push() after EOF'); stream.emit('error', e); } else if (state.endEmitted && addToFront) { var e = new Error('stream.unshift() after end event'); stream.emit('error', e); } else { if (state.decoder && !addToFront && !encoding) chunk = state.decoder.write(chunk); // update the buffer info. state.length += state.objectMode ? 1 : chunk.length; if (addToFront) { state.buffer.unshift(chunk); } else { state.reading = false; state.buffer.push(chunk); } if (state.needReadable) emitReadable(stream); maybeReadMore(stream, state); } } else if (!addToFront) { state.reading = false; } return needMoreData(state); } // if it's past the high water mark, we can push in some more. // Also, if we have no data yet, we can stand some // more bytes. This is to work around cases where hwm=0, // such as the repl. Also, if the push() triggered a // readable event, and the user called read(largeNumber) such that // needReadable was set, then we ought to push more, so that another // 'readable' event will be triggered. function needMoreData(state) { return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); } // backwards compatibility. Readable.prototype.setEncoding = function(enc) { if (!StringDecoder) StringDecoder = require('string_decoder').StringDecoder; this._readableState.decoder = new StringDecoder(enc); this._readableState.encoding = enc; }; // Don't raise the hwm > 128MB var MAX_HWM = 0x800000; function roundUpToNextPowerOf2(n) { if (n >= MAX_HWM) { n = MAX_HWM; } else { // Get the next highest power of 2 n--; for (var p = 1; p < 32; p <<= 1) n |= n >> p; n++; } return n; } function howMuchToRead(n, state) { if (state.length === 0 && state.ended) return 0; if (state.objectMode) return n === 0 ? 0 : 1; if (isNaN(n) || n === null) { // only flow one buffer at a time if (state.flowing && state.buffer.length) return state.buffer[0].length; else return state.length; } if (n <= 0) return 0; // If we're asking for more than the target buffer level, // then raise the water mark. Bump up to the next highest // power of 2, to prevent increasing it excessively in tiny // amounts. if (n > state.highWaterMark) state.highWaterMark = roundUpToNextPowerOf2(n); // don't have that much. return null, unless we've ended. if (n > state.length) { if (!state.ended) { state.needReadable = true; return 0; } else return state.length; } return n; } // you can override either this method, or the async _read(n) below. Readable.prototype.read = function(n) { var state = this._readableState; state.calledRead = true; var nOrig = n; if (typeof n !== 'number' || n > 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we // already have a bunch of data in the buffer, then just trigger // the 'readable' event and move on. if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { emitReadable(this); return null; } n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up. if (n === 0 && state.ended) { if (state.length === 0) endReadable(this); return null; } // All the actual chunk generation logic needs to be // *below* the call to _read. The reason is that in certain // synthetic stream cases, such as passthrough streams, _read // may be a completely synchronous operation which may change // the state of the read buffer, providing enough data when // before there was *not* enough. // // So, the steps are: // 1. Figure out what the state of things will be after we do // a read from the buffer. // // 2. If that resulting state will trigger a _read, then call _read. // Note that this may be asynchronous, or synchronous. Yes, it is // deeply ugly to write APIs this way, but that still doesn't mean // that the Readable class should behave improperly, as streams are // designed to be sync/async agnostic. // Take note if the _read call is sync or async (ie, if the read call // has returned yet), so that we know whether or not it's safe to emit // 'readable' etc. // // 3. Actually pull the requested chunks out of the buffer and return. // if we need a readable event, then we need to do some reading. var doRead = state.needReadable; // if we currently have less than the highWaterMark, then also read some if (state.length - n <= state.highWaterMark) doRead = true; // however, if we've ended, then there's no point, and if we're already // reading, then it's unnecessary. if (state.ended || state.reading) doRead = false; if (doRead) { state.reading = true; state.sync = true; // if the length is currently zero, then we *need* a readable event. if (state.length === 0) state.needReadable = true; // call internal read method this._read(state.highWaterMark); state.sync = false; } // If _read called its callback synchronously, then `reading` // will be false, and we need to re-evaluate how much data we // can return to the user. if (doRead && !state.reading) n = howMuchToRead(nOrig, state); var ret; if (n > 0) ret = fromList(n, state); else ret = null; if (ret === null) { state.needReadable = true; n = 0; } state.length -= n; // If we have nothing in the buffer, then we want to know // as soon as we *do* get something into the buffer. if (state.length === 0 && !state.ended) state.needReadable = true; // If we happened to read() exactly the remaining amount in the // buffer, and the EOF has been seen at this point, then make sure // that we emit 'end' on the very next tick. if (state.ended && !state.endEmitted && state.length === 0) endReadable(this); return ret; }; function chunkInvalid(state, chunk) { var er = null; if (!Buffer.isBuffer(chunk) && 'string' !== typeof chunk && chunk !== null && chunk !== undefined && !state.objectMode && !er) { er = new TypeError('Invalid non-string/buffer chunk'); } return er; } function onEofChunk(stream, state) { if (state.decoder && !state.ended) { var chunk = state.decoder.end(); if (chunk && chunk.length) { state.buffer.push(chunk); state.length += state.objectMode ? 1 : chunk.length; } } state.ended = true; // if we've ended and we have some data left, then emit // 'readable' now to make sure it gets picked up. if (state.length > 0) emitReadable(stream); else endReadable(stream); } // Don't emit readable right away in sync mode, because this can trigger // another read() call => stack overflow. This way, it might trigger // a nextTick recursion warning, but that's not so bad. function emitReadable(stream) { var state = stream._readableState; state.needReadable = false; if (state.emittedReadable) return; state.emittedReadable = true; if (state.sync) process.nextTick(function() { emitReadable_(stream); }); else emitReadable_(stream); } function emitReadable_(stream) { stream.emit('readable'); } // at this point, the user has presumably seen the 'readable' event, // and called read() to consume some data. that may have triggered // in turn another _read(n) call, in which case reading = true if // it's in progress. // However, if we're not ended, or reading, and the length < hwm, // then go ahead and try to read some more preemptively. function maybeReadMore(stream, state) { if (!state.readingMore) { state.readingMore = true; process.nextTick(function() { maybeReadMore_(stream, state); }); } } function maybeReadMore_(stream, state) { var len = state.length; while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { stream.read(0); if (len === state.length) // didn't get any data, stop spinning. break; else len = state.length; } state.readingMore = false; } // abstract method. to be overridden in specific implementation classes. // call cb(er, data) where data is <= n in length. // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. Readable.prototype._read = function(n) { this.emit('error', new Error('not implemented')); }; Readable.prototype.pipe = function(dest, pipeOpts) { var src = this; var state = this._readableState; switch (state.pipesCount) { case 0: state.pipes = dest; break; case 1: state.pipes = [state.pipes, dest]; break; default: state.pipes.push(dest); break; } state.pipesCount += 1; var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; var endFn = doEnd ? onend : cleanup; if (state.endEmitted) process.nextTick(endFn); else src.once('end', endFn); dest.on('unpipe', onunpipe); function onunpipe(readable) { if (readable !== src) return; cleanup(); } function onend() { dest.end(); } // when the dest drains, it reduces the awaitDrain counter // on the source. This would be more elegant with a .once() // handler in flow(), but adding and removing repeatedly is // too slow. var ondrain = pipeOnDrain(src); dest.on('drain', ondrain); function cleanup() { // cleanup event handlers once the pipe is broken dest.removeListener('close', onclose); dest.removeListener('finish', onfinish); dest.removeListener('drain', ondrain); dest.removeListener('error', onerror); dest.removeListener('unpipe', onunpipe); src.removeListener('end', onend); src.removeListener('end', cleanup); // if the reader is waiting for a drain event from this // specific writer, then it would cause it to never start // flowing again. // So, if this is awaiting a drain, then we just call it now. // If we don't know, then assume that we are waiting for one. if (!dest._writableState || dest._writableState.needDrain) ondrain(); } // if the dest has an error, then stop piping into it. // however, don't suppress the throwing behavior for this. function onerror(er) { unpipe(); if (EE.listenerCount(dest, 'error') === 0) dest.emit('error', er); } dest.once('error', onerror); // Both close and finish should trigger unpipe, but only once. function onclose() { dest.removeListener('finish', onfinish); unpipe(); } dest.once('close', onclose); function onfinish() { dest.removeListener('close', onclose); unpipe(); } dest.once('finish', onfinish); function unpipe() { src.unpipe(dest); } // tell the dest that it's being piped to dest.emit('pipe', src); // start the flow if it hasn't been started already. if (!state.flowing) { // the handler that waits for readable events after all // the data gets sucked out in flow. // This would be easier to follow with a .once() handler // in flow(), but that is too slow. this.on('readable', pipeOnReadable); state.flowing = true; process.nextTick(function() { flow(src); }); } return dest; }; function pipeOnDrain(src) { return function() { var dest = this; var state = src._readableState; state.awaitDrain--; if (state.awaitDrain === 0) flow(src); }; } function flow(src) { var state = src._readableState; var chunk; state.awaitDrain = 0; function write(dest, i, list) { var written = dest.write(chunk); if (false === written) { state.awaitDrain++; } } while (state.pipesCount && null !== (chunk = src.read())) { if (state.pipesCount === 1) write(state.pipes, 0, null); else state.pipes.forEach(write); src.emit('data', chunk); // if anyone needs a drain, then we have to wait for that. if (state.awaitDrain > 0) return; } // if every destination was unpiped, either before entering this // function, or in the while loop, then stop flowing. // // NB: This is a pretty rare edge case. if (state.pipesCount === 0) { state.flowing = false; // if there were data event listeners added, then switch to old mode. if (EE.listenerCount(src, 'data') > 0) emitDataEvents(src); return; } // at this point, no one needed a drain, so we just ran out of data // on the next readable event, start it over again. state.ranOut = true; } function pipeOnReadable() { if (this._readableState.ranOut) { this._readableState.ranOut = false; flow(this); } } Readable.prototype.unpipe = function(dest) { var state = this._readableState; // if we're not piping anywhere, then do nothing. if (state.pipesCount === 0) return this; // just one destination. most common case. if (state.pipesCount === 1) { // passed in one, but it's not the right one. if (dest && dest !== state.pipes) return this; if (!dest) dest = state.pipes; // got a match. state.pipes = null; state.pipesCount = 0; this.removeListener('readable', pipeOnReadable); state.flowing = false; if (dest) dest.emit('unpipe', this); return this; } // slow case. multiple pipe destinations. if (!dest) { // remove all. var dests = state.pipes; var len = state.pipesCount; state.pipes = null; state.pipesCount = 0; this.removeListener('readable', pipeOnReadable); state.flowing = false; for (var i = 0; i < len; i++) dests[i].emit('unpipe', this); return this; } // try to find the right one. var i = state.pipes.indexOf(dest); if (i === -1) return this; state.pipes.splice(i, 1); state.pipesCount -= 1; if (state.pipesCount === 1) state.pipes = state.pipes[0]; dest.emit('unpipe', this); return this; }; // set up data events if they are asked for // Ensure readable listeners eventually get something Readable.prototype.on = function(ev, fn) { var res = Stream.prototype.on.call(this, ev, fn); if (ev === 'data' && !this._readableState.flowing) emitDataEvents(this); if (ev === 'readable' && this.readable) { var state = this._readableState; if (!state.readableListening) { state.readableListening = true; state.emittedReadable = false; state.needReadable = true; if (!state.reading) { this.read(0); } else if (state.length) { emitReadable(this, state); } } } return res; }; Readable.prototype.addListener = Readable.prototype.on; // pause() and resume() are remnants of the legacy readable stream API // If the user uses them, then switch into old mode. Readable.prototype.resume = function() { emitDataEvents(this); this.read(0); this.emit('resume'); }; Readable.prototype.pause = function() { emitDataEvents(this, true); this.emit('pause'); }; function emitDataEvents(stream, startPaused) { var state = stream._readableState; if (state.flowing) { // https://github.com/isaacs/readable-stream/issues/16 throw new Error('Cannot switch to old mode now.'); } var paused = startPaused || false; var readable = false; // convert to an old-style stream. stream.readable = true; stream.pipe = Stream.prototype.pipe; stream.on = stream.addListener = Stream.prototype.on; stream.on('readable', function() { readable = true; var c; while (!paused && (null !== (c = stream.read()))) stream.emit('data', c); if (c === null) { readable = false; stream._readableState.needReadable = true; } }); stream.pause = function() { paused = true; this.emit('pause'); }; stream.resume = function() { paused = false; if (readable) process.nextTick(function() { stream.emit('readable'); }); else this.read(0); this.emit('resume'); }; // now make it start, just in case it hadn't already. stream.emit('readable'); } // wrap an old-style stream as the async data source. // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. Readable.prototype.wrap = function(stream) { var state = this._readableState; var paused = false; var self = this; stream.on('end', function() { if (state.decoder && !state.ended) { var chunk = state.decoder.end(); if (chunk && chunk.length) self.push(chunk); } self.push(null); }); stream.on('data', function(chunk) { if (state.decoder) chunk = state.decoder.write(chunk); if (!chunk || !state.objectMode && !chunk.length) return; var ret = self.push(chunk); if (!ret) { paused = true; stream.pause(); } }); // proxy all the other methods. // important when wrapping filters and duplexes. for (var i in stream) { if (typeof stream[i] === 'function' && typeof this[i] === 'undefined') { this[i] = function(method) { return function() { return stream[method].apply(stream, arguments); }}(i); } } // proxy certain important events. var events = ['error', 'close', 'destroy', 'pause', 'resume']; events.forEach(function(ev) { stream.on(ev, self.emit.bind(self, ev)); }); // when we try to consume some more bytes, simply unpause the // underlying stream. self._read = function(n) { if (paused) { paused = false; stream.resume(); } }; return self; }; // exposed for testing purposes only. Readable._fromList = fromList; // Pluck off n bytes from an array of buffers. // Length is the combined lengths of all the buffers in the list. function fromList(n, state) { var list = state.buffer; var length = state.length; var stringMode = !!state.decoder; var objectMode = !!state.objectMode; var ret; // nothing in the list, definitely empty. if (list.length === 0) return null; if (length === 0) ret = null; else if (objectMode) ret = list.shift(); else if (!n || n >= length) { // read it all, truncate the array. if (stringMode) ret = list.join(''); else ret = Buffer.concat(list, length); list.length = 0; } else { // read just some of it. if (n < list[0].length) { // just take a part of the first list item. // slice is the same for buffers and strings. var buf = list[0]; ret = buf.slice(0, n); list[0] = buf.slice(n); } else if (n === list[0].length) { // first list is a perfect match ret = list.shift(); } else { // complex case. // we have enough to cover it, but it spans past the first buffer. if (stringMode) ret = ''; else ret = new Buffer(n); var c = 0; for (var i = 0, l = list.length; i < l && c < n; i++) { var buf = list[0]; var cpy = Math.min(n - c, buf.length); if (stringMode) ret += buf.slice(0, cpy); else buf.copy(ret, c, 0, cpy); if (cpy < buf.length) list[0] = buf.slice(cpy); else list.shift(); c += cpy; } } } return ret; } function endReadable(stream) { var state = stream._readableState; // If we get here before consuming all the bytes, then that is a // bug in node. Should never happen. if (state.length > 0) throw new Error('endReadable called on non-empty stream'); if (!state.endEmitted && state.calledRead) { state.ended = true; process.nextTick(function() { // Check that we didn't get one last unshift. if (!state.endEmitted && state.length === 0) { state.endEmitted = true; stream.readable = false; stream.emit('end'); } }); } } GetLastModifiedDateFromHModule: could not find module file path: %dGetLastModifiedDateFromHModule: could not convert to utf8: %d - %sGetLastModifiedDateFromHModule: could not stat module: %dchakra.dllCreateCacheFileName: could not load chakra.dll: %dCreateCacheFileName: could not get module handle of current module: %d%s_cbsj_%d_%I64u_%I64u.jsbc\ProcessFileList: could not stat directory: %d - %S.jsProcessDirectory: could not stat directory: %d - %SProcessDirectory: arg not directory: %d - %SProcessDirectory: could not readdir directory: %d - %SGenerateFileList: could not process directory: %d - %SPreprocessByteCacheFiles: could not generate file list: %dPreprocessByteCacheFiles: could not create cache file name: %dPreprocessByteCacheFiles: could not convert cachefile to unicode: %d - %SPreprocessByteCacheFiles: could not open file: %d - %SComputeKey: could not convert key to unicode: %d - %S.jsAddFilesToByteCache: could not generate script for file: %d - %SAddFilesToByteCache: could not serialize script for file: %d - %SAddFilesToByteCache: could not compute key for file: %d - %SAddFilesToByteCache: could not add file to bytecode cache: %d - %SCreateBuiltInScriptStringHelper: could not generate script for builtin: %d - %SAddBuiltInsToByteCache: could not generate script for builtin: %d - %SAddBuiltInsToByteCache: could not serialize script for builtin: %d - %SAddBuiltInsToByteCache: could not compute key for builtin: %d - %SAddBuiltInsToByteCache: could not add builtin to bytecode cache: %d - %SCreateByteCodeCache: could not coinitialize: %dCreateByteCodeCache: could not CreateByteCodeCacheWriter: %dCreateByteCodeCache: could not InitializeByteCodeCache: %dCreateByteCodeCache: could not AddFilesToByteCache: %dCreateByteCodeCache: could not AddBuiltInsToByteCache: %dBuildByteCacheImpl: could not PreprocessByteCacheFiles: %d - %S - %SBuildByteCacheImpl: could not CreateByteCodeCache: %d - %S - %Scbsj%s_%sDeleteByteCodeForBasePath: could not copy directory: %d - %SDeleteByteCodeForBasePath: could not find directory slash: %d - %SDeleteByteCodeForBasePath: could not readdir directory: %d - %S%s\%sDeleteByteCodeForBasePath: could not create full filename: %d - %S - %SProcessDirectory: could not delete file: %d - %SValidateByteCacheImpl: Invalid Argument(s) %pValidateByteCacheImpl: could not CreateCacheFileName: %d - %SValidateByteCacheImpl: expected valid file does not exist, cache is invalid: %d - %SOpenByteCache: Invalid Argument(s) %pOpenByteCache: Attempting to open a second bytecache on thread that already has one.OpenByteCache: CoInitializing the thread failed: %dOpenByteCache: Could not create bytecode file name from file path: %d - %SOpenByteCache: could not convert cachefile to unicode: %d - %sOpenByteCache: Could not open bytecode file from file path: %d - %SOpenByteCache: Opening bytecode cache...: %SOpenByteCache: Byte code cache needs regeneration: %d - %SOpenByteCache: Could could not deserialize bytecode from file name: %d - %SOpenByteCache: Opening bytecode cache complete: %SCloseByteCache: Trying to close a byte code cache on an unitialized thread.CloseByteCache: could not delete file: %d - %SLoadCacheFilePath: Could not create cache file name from file path: %d - %SLoadCacheFilePath: Could not find extension on file path: %d - %SLoadCacheFilePath: Could not fit extension on file path: %d - %S - %Svector too longWrong arguments, expected a stringnativerequire_wrap::Require - a javascript error occured while requiring: %S, returning to javascriptnativerequire_wrap::Require - a non libuv error occured while requiring %S, Error: %S for: nativerequire_wrap::Require - Failed, libuv error occured while requiring %S, error code: %dnativerequire_wrap::ReadJsonPackage failed on JsonParse::Init for: %S, error code: %dFailed on JsonParser::Init, error code is:nativerequire_wrap::ReadJsonPackage failed for: %S, error code: %dFailed on JsonParser::Read, error code is:nativerequire_wrap::FileExistsNotDir - Failed For %S, result: %dInvalid arguments, expected: [module id : string]nativerequire_wrap::RequireBuiltinModule failed on require from string for: %S, throwing exception in javascriptFailed to require: NativeRequireUtils::SaveSerializedScript First call to JsSerializeScript failed, error code: %dNativeRequireUtils::SaveSerializedScript second call to JsSerializeScript failed, error code: %dPostQueuedCompletionStatusCreateIoCompletionPortmallocGetQueuedCompletionStatusCreateEventUNKNOWNOKEOFEADDRINFOENONETECHARSETEAIFAMNOSUPPORTEAISERVICEEAISOCKTYPEESHUTDOWNsuccessend of filegetaddrinfo errorpermission deniedresource temporarily unavailableaddress already in useaddress not availableaddress family not supportedconnection already in progressbad file descriptorresource busy or lockedsoftware caused connection abortconnection refusedconnection reset by peerdestination address requiredbad address in system call argumenthost is unreachableinterrupted system callinvalid argumentsocket is already connectedtoo many open filesmessage too longnetwork is downnetwork is unreachablefile table overflowno buffer space availablenot enough memorynot a directoryillegal operation on a directorymachine is not on the networksocket is not connectedsocket operation on non-socketoperation not supported on socketfunction not implementedbroken pipeprotocol errorprotocol not supportedprotocol wrong type for socketconnection timed outinvalid Unicode characteraddress family for hostname not supportedservname not supported for ai_socktypeai_socktype not supportedcannot send after transport endpoint shutdownfile already existsno such processname too longoperation not permittedtoo many symbolic links encounteredcross-device link not permitteddirectory not emptyno space left on devicei/o errorread-only file systemno such deviceinvalid seekoperation canceledUnknown system errorHARDWARE\DESCRIPTION\System\CentralProcessor\%d~MHzProcessorNameStringNULno error./*%s*%s\*realloc\??\\\?\%s\%s%x6%u.%u.%u.%u0123456789CreateJobObjectWSetInformationJobObject\/:comexe ""\SYSTEMROOT=SYSTEMROOTSYSTEMDRIVE=SYSTEMDRIVETEMP=TEMPGetEnvironmentVariableWUnregisterWaitExPATHAssignProcessToJobObjectRegisterWaitForSingleObject\\.\pipe\uv\%p-%dQueueUserWorkItem狫_H&l4dğrC y*RB_INSERT[2;6~[2;2~[2;5~[2~[4;6~[4;2~[4;5~[4~[6;6~[6;2~[6;5~[6~[1;6~[1;2~[1;5~[1~[5;6~[5;2~[5;5~[5~[3;6~[3;2~[3;5~[3~[23^[23~[11^[[A[24^[24~[12^[[B[25^[25~[13^[[C[26^[26~[14^[[D[28^[28~[15^[[E[29^[29~[17^[17~[31^[31~[18^[18~[32^[32~[19^[19~[33^[33~[20^[20~[34^[34~[21^[21~[23@[23$[24@[24$Unknown error%s: (%d) %s(%d) %sWSAStartupclosesocketsocketGetModuleHandleAGetProcAddresserror!!!! in node_buffer.h, JsGetValueType failed, error code is: %d error!!! in node_buffer.h, JsGetValueType returned type of: %d bad locale nameios_base::badbit setios_base::failbit setios_base::eofbit setprocess._tickFromSpinner assigned to non-function \\_tickDomainCallback_nextDomainTickprocess._tickDomainCallback assigned to non-function process._nextDomainTick assigned to non-function nextTickenterexit_disposedprocess._tickCallback assigned to non-function _errnoUnknown system errno %dutf8utf-8asciibase64ucs2ucs-2utf16leutf-16lebinaryhexraw'raw' (array of integers) has been removed. Use 'binary'. raws'raws' encoding has been renamed to 'binary'. Please update your code. 'raw' encoding (array of integers) has been removed. Use 'binary'. 'raw' encoding (array of integers) has been removed. %s messagename%s: ownerBad argument.uv_chdiruv_cwdargument must be an integer or octal string.invalid octal stringuv_resident_set_memoryrssheapTotalheapUsedprocess.hrtime() only accepts an Array tuple.process.dlopen takes exactly 2 arguments.Out of memory.Symbol %s not found.Module version mismatch. Expected %d, got %d._fatalExceptionNo such module_eval_print_eval_forceReplnoDeprecationthrowDeprecationtraceDeprecation--debug-brk--debug-brk=--debug=Bad debug option. Debug port must be in range 1025 to 65535. Usage: node [options] [ -e script | script.js ] [arguments] node debug script.js [arguments] Options: -v, --version print node's version -e, --eval script evaluate script -p, --print evaluate script and print result -i, --interactive always enter the REPL even if stdin does not appear to be a terminal --no-deprecation silence deprecation warnings --trace-deprecation show stack traces on deprecations --v8-options print v8 command line options --max-stack-size=val set max v8 stack size (bytes) --cache-builtin cache the source of the builtin modules (this speeds up startup, but increases memory consumption) --no-console don't load console the module (reduces memory consumption) --disable-node-env-vars Disable the use of the enviornment variables listed below Environment variables: NODE_PATH ';'-separated list of directories prefixed to the module search path. NODE_MODULE_CONTEXTS Set to 1 to load modules in their own global contexts. NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL Documentation can be found at http://nodejs.org/ requires an argument Error: Error: %s requires an argument \-debugger listening on port %d Starting debugger agent. Invalid number of arguments.OpenProcesssprintfOpenFileMappingWMapViewOfFileCreateRemoteThreadWaitForSingleObject--expose_debug_asv8debug_exiting%pLuLdluldeEpP.bad cast?binding:script(function(source, target) { Object.getOwnPropertyNames(source).forEach(function(key) { try { var desc = Object.getOwnPropertyDescriptor(source, key); if (desc.value === source) desc.value = target; Object.defineProperty(target, key, desc); } catch (e) { // Catch sealed properties errors } }); })createContext() accept only object as first argument.needs at least 'code' argument.needs a 'context' argument.evalmachine.Must be called as a method of Script.'this' must be a result of previous new Script(code) call.Argument must be HTTPParser.REQUEST or HTTPParser.RESPONSEAlready parsing a bufferArgument should be a bufferOffset is out of boundsoff + len > buffer.lengthParse ErrorbytesParsedHTTPParserREQUESTRESPONSEexecutefinishreinitializeonHeadersonHeadersCompleteonBodyonMessageCompleteDELETEGETHEADPOSTPUTCONNECTOPTIONSTRACECOPYLOCKMKCOLMOVEPROPFINDPROPPATCHSEARCHUNLOCKREPORTMKACTIVITYCHECKOUTMERGEM-SEARCHNOTIFYSUBSCRIBEUNSUBSCRIBEPATCHPURGEUNKNOWN_METHODmethodstatusCodehttpVersionversionMajorversionMinorshouldKeepAliveupgradeheadersBufferBad argumentlength > kMaxLengthvalue is not a numberMust have start <= endend cannot be longer than parent.lengthFirst arg should be a BuffersourceEnd < sourceStarttargetStart out of boundssourceStart out of boundssourceEnd out of boundsArgument must be a stringFirst argument must be a Bufferoffset out of rangelength out of rangeoffset or length out of rangeInvalid hex stringoffset is not uintTrying to read beyond buffer lengthvalue not a numberTrying to write beyond buffer lengthPipefdreadStartreadStopshutdownwriteBufferwriteAsciiStringwriteUtf8StringwriteUcs2StringbindlistenconnectsetPendingInstancesPipeWrap: Aborting due to unwrap failure at %s:%d onconnectionbyteswriteQueueSizeonreadshellcommon\shell\cortana\opensource\node\lib\stream_wrap.cppStreamWrap: Aborting due to unwrap failure at %s:%d Not enough argumentshandleslab_%pSUCCESSEFORMERRESERVFAILENOTFOUNDENOTIMPEREFUSEDEBADQUERYEBADNAMEEBADFAMILYEBADRESPETIMEOUTEFILEEDESTRUCTIONEBADSTREBADFLAGSENONAMEEBADHINTSENOTINITIALIZEDELOADIPHLPAPIEADDRGETNETWORKPARAMSECANCELLED(UNKNOWN)exchangepriorityportweightflagsserviceregexpreplacementorderpreferencequeryAqueryAaaaqueryCnamequeryMxqueryNsqueryTxtquerySrvqueryNaptrgetHostByAddrgetHostByNamegetaddrinfoisIPAF_INETAF_INET6AF_UNSPECFSEventFSEventWrap: Aborting due to unwrap failure at %s:%d Bad argumentschangeonchangepath requiredpath must be a stringdest path requiredsrc path requireddest path must be a stringsrc path must be a stringdirjunctionfileUnknown symlink typeold path requirednew path requiredold path must be a stringnew path must be a stringNot an integerflags requiredmode requiredflags must be an intmode must be an intSecond argument needs to be a bufferLength extends beyond bufferuid requiredgid requireduid must be an intgid must be an intfd requiredfd must be an intatime requiredmtime requiredatime must be a numbermtime must be a numberutimefutimeLEgethostnameWindows_NT%d.%d.%duserniceidleirqmodelspeedtimesuv_interface_addressesIPv4IPv6addressfamilyinternalgetEndiannessgetHostnamegetLoadAvggetUptimegetTotalMemgetFreeMemgetCPUsgetOSTypegetOSReleasegetInterfaceAddressesProcessspawnkillstdiotypeignorepipewrapwrapTypetcpudpProcessWrap: Aborting due to unwrap failure at %s:%d options.uid is out of rangeoptions.uid should be a numberoptions.gid is out of rangeoptions.gid should be a numberargsenvPairswindowsVerbatimArgumentsdetachedonexitSignalonsignalSignalWrap: Aborting due to unwrap failure at %s:%d TCPbind6connect6getsocknamegetpeernamesetNoDelaysetKeepAlivesetSimultaneousAcceptsTCPWrap: Aborting due to unwrap failure at %s:%d TimerWrap: Aborting due to unwrap failure at %s:%d TTYgetWindowSizesetRawModeisTTYguessHandleTypeUDPPIPEFILETTYWrap: Aborting due to unwrap failure at %s:%d onmessagesendsend6recvStartrecvStopaddMembershipdropMembershipsetMulticastTTLsetMulticastLoopbacksetBroadcastsetTTLUDPWrap: Aborting due to unwrap failure at %s:%d Missing dictionaryBad dictionaryZlib errorInit errorFailed to set dictionaryFailed to reset streaminitresetZlibcallbackonerrorZ_NO_FLUSHZ_PARTIAL_FLUSHZ_SYNC_FLUSHZ_FULL_FLUSHZ_FINISHZ_BLOCKZ_OKZ_STREAM_ENDZ_NEED_DICTZ_ERRNOZ_STREAM_ERRORZ_DATA_ERRORZ_MEM_ERRORZ_BUF_ERRORZ_VERSION_ERRORZ_NO_COMPRESSIONZ_BEST_SPEEDZ_BEST_COMPRESSIONZ_DEFAULT_COMPRESSIONZ_FILTEREDZ_HUFFMAN_ONLYZ_RLEZ_FIXEDZ_DEFAULT_STRATEGYZLIB_VERNUMDEFLATEINFLATEGZIPGUNZIPDEFLATERAWINFLATERAWUNZIPZLIB_VERSION0123456789abcdefABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/>>?456789:;<= ? !"#$%&'()*+,-./0123expected argument args[0] to be a connection object_handleexpected object for _handle.As() to contain integer member fdexpected object for _conn to contain string member remoteAddressremoteAddressexpected object for _conn to contain integer member remotePortremotePortexpected object for _conn to contain integer member bufferSizebufferSizeexpected argument 1 to be number of bytesexpected object for arg0 to contain string member urlexpected object for arg0 to contain string member methodexpected object for arg0 to contain object member headersexpected object for request to contain string member headersx-forwarded-forexpected argument args[1] to be a connection objectexpected object for arg0 to contain string member _header_headerexpected object for _conn to contain integer member fdexpected object for _conn to contain string member hosthostexpected object for _conn to contain integer member portonstoponecoreuap\inetcore\Wwa\AppModelCommon\Common.hpponecoreuap\inetcore\Wwa\AppModelCommon\AutoHandle.hppntdll.dllRtlDllShutdownInProgresswil_p0hLocal\SM0:%d:%d:%hsonecoreuap\inetcore\wwa\bytecode\lib\automapviewoffilehandle.cppzO?l4vzc onecoreuap\inetcore\wwa\bytecode\lib\bsearch_s.cppSystem\CurrentControlSet\Services\Tcpip\ParametersDatabasePath\hostsriphlpapi.dllGetNetworkParamsGetAdaptersAddressescryptbase.dllSystemFunction036%lu.%lu.%lu.%lu.in-addr.arpa%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpaLOCALDOMAINRES_OPTIONSSystem\CurrentControlSet\Services\VxD\MSTCPNameServerDhcpNameServerInterfaces%s,%sfec0:0:0:ffff:fbndots:retrans:retry:rotate012345678901234567890123456789ABCDEF0123456789abcdef0123456789abcdef0123456789HOSTALIASES%u.%u.%u.%uHPE_OKHPE_CB_message_beginthe on_message_begin callback failedHPE_CB_urlthe on_url callback failedHPE_CB_header_fieldthe on_header_field callback failedHPE_CB_header_valuethe on_header_value callback failedHPE_CB_headers_completethe on_headers_complete callback failedHPE_CB_bodythe on_body callback failedHPE_CB_message_completethe on_message_complete callback failedHPE_INVALID_EOF_STATEstream ended at an unexpected timeHPE_HEADER_OVERFLOWtoo many header bytes seen; overflow detectedHPE_CLOSED_CONNECTIONdata received after completed connection: close messageHPE_INVALID_VERSIONinvalid HTTP versionHPE_INVALID_STATUSinvalid HTTP status codeHPE_INVALID_METHODinvalid HTTP methodHPE_INVALID_URLinvalid URLHPE_INVALID_HOSTinvalid hostHPE_INVALID_PORTinvalid portHPE_INVALID_PATHinvalid pathHPE_INVALID_QUERY_STRINGinvalid query stringHPE_INVALID_FRAGMENTinvalid fragmentHPE_LF_EXPECTEDLF character expectedHPE_INVALID_HEADER_TOKENinvalid character in headerHPE_INVALID_CONTENT_LENGTHinvalid character in content-length headerHPE_INVALID_CHUNK_SIZEinvalid character in chunk size headerHPE_INVALID_CONSTANTinvalid constant stringHPE_INVALID_INTERNAL_STATEencountered unexpected internal stateHPE_STRICTstrict mode assertion failedHPE_PAUSEDparser is pausedHPE_UNKNOWNan unknown error occurredconnectionproxy-connectioncontent-lengthtransfer-encodingchunkedkeep-alive  !#$%&'*+-.0123456789abcdefghijklmnopqrstuvwxyz^_`abcdefghijklmnopqrstuvwxyz|~usao2)GUyv2147483647-2147483648 F HDSincorrect header checkunknown compression methodinvalid window sizeunknown header flags setheader crc mismatchinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backincorrect data checkincorrect length check`Psp0  ` @ X ;x8 h( H T+t4  d$ D \ S|< l,  L R#r2  b" B Z Cz: j*  J V@3v6 f& F  ^ c~> n. N `Qq1  a! A Y ;y9 i)  I U+u5  e% E ] S}= m-  M S#s3  c# C [ C{; k+  K W@3w7 g' G  _ c? o/ O `Psp0  ` @ X ;x8 h( H T+t4  d$ D \ S|< l,  L R#r2  b" B Z Cz: j*  J V@3v6 f& F  ^ c~> n. N `Qq1  a! A Y ;y9 i)  I U+u5  e% E ] S}= m-  M S#s3  c# C [ C{; k+  K W@3w7 g' G  _ c? o/ O A@!  @a`10  @     need dictionarystream endfile errorstream errordata errorinsufficient memorybuffer errorincompatible version@@ #+3;CScs !1Aa  0@`0w,aQ mjp5c飕d2yҗ+L |~-d jHqA}mQDžӃVlkdzbeO\lcc=  n;^iLA`rqgjm Zjz  ' }Dңhi]Wbgeq6lknv+ӉZzJgo߹ホCՎ`~ѡ8ROggW?K6H+ L J6`zA`Ugn1yiFafo%6hRw G "/&U;( Z+j\1е,[d&c윣ju m ?6grWJz+{8 Ғ |! ӆBhn[&wowGZpj;f\ eibkaElx TN³9a&g`MGiIwn>JjѮZf @;7SŞϲG0򽽊º0S$6к)WTg#.zfJah]+o*7 Z-A1b62S-+ldEw}ZVǖAOIъ OM~-QJ#SpxAaU׮.7׵Y-6]]wll?AԞZ͢$ Faw$eڪ]]FD(koipvk19Z* ,  m86F߲]qTp0ek*1u4yީ%8S1bSWĔՖk1**ykʬHpo].*F6fcTT"eM©g0&):{ϼkZ> 8$,52F*sw1pHkQ6Fzw]cN̵J #pAF]#l8?1(BOgT~yUbL8^#ܖTZ1ObbSyOIV~P-{b-R4٠~^eGnHl/Su6: #jT$+e?yHf'*b#ٽЧ ?&~?$pi;FBzw[keZ~7 Sv8H 3?r$7jnԄYFܨ |OQ;օ U d S - =G\ p&Gw)` /a߫i5&LsZ<#0zMzFM8,9; :R:(q-v,.7/pXqYs3r%w+OQvrtEux܉~OK }!b|tyBxʠz{.lD~m8onlk[wjR1h58ib?mcf+aQ`צedd"fig HINSKyuJcO NZLݘMFGN@E$DD2AsX@*IBCPhTg3U>uW ַVS:R|P~Q9ZS [fYX4])\ZEo^m/_5qϱ٥s\ۼqދ!K7 kfֶԁ-b3Πjp]$^'~*I@VW<âM˟ŏ{ tDCm-@wm.B+(铜>Td"ŀǼϭ~8y$owJ1}05_K^ iϏ은BI#ƈdX܁T̓cQ: rՆ⩗ fn|xK)o%ƭ/3vUuA?)C:|sĵ@͂ Ͳ;bIUeh"׻_HS1޼^Z4eg Wb27_k%8ם(ŊO}do׸Jj3wVcXWP0qB{߭gCru&op-?'Bs ưGz>2[Ȏg; i8P/ _Y=чe:ZO?(3wwXR @hQ+ğH*0"ZOWoI}@mNП5+#*'G| AH=XX?#1jvʬ`p^Y<L~i/{kHwâ hs)aLoD~Pf7VM'(@ﰤ ہg9x+n&;f?/X)T`D1 ߨMߒ.FgTp'Hq/L0UEc?kǃh6ry7]P\@TN%s7@'>$!AxUʰ\3;Y^U~PGl!;b F2ȂpԞ(Q_V:1X: n3 m:@/)IJNv"2x+ٗ Kx.HҥfAj^y9*O]#kM`~b_R 7zFh!1߈Vc0a"j6nS Nr)Υ{t*F8#vufz`rs"WG9^EMvc΍&DAdQy/4Aڱ&S֚E biLQ<6'5P..T&q]w4.6IE? v\[YI>U!lDa>Ԫ΋ϩ7~8A]&nv|oY yKiw\¹9~$ 66nQfq>,o,IӔ 渱{I .H>C-Yn馑gQz tafw0a, Qmpjc5dۈ2yܸو L+~|-dj qHA}mԵQӅlVdkbze\Ocl=c ;n Li^`Agqr<KG k5Blۻ֬@2lE\u ϫ=Y&0Q:Qa!V#Ϻ(_ ٲ $/o|XhLaf-=vAq *q3xɢ4 j m=-dlc\kkQlabe0bNl{WeP|b-I|LeMaX:QΣtԻ0JߥA=ؕפmCij4ngF`D-s3 L_ |Pq<'A  Wh% of a^)ɘИ"רY=. \;l  tҚG9w&sc d; mj>zjZ '}DhibW]egl6qnkv+zZgJoC`֣ѓ~8ORѻgWg?H6K +گ L6JAz``ègU1nFiyaf%oҠRh6 w G"U&/ź; (+Z\j1,ٞ[ޮd°c&ujm 6?rgWJz{+ 8Ҏվ | !Bhݳڃn&[owGwZjpf; \ebiaklE x NT9§g&a`IiGM>nwۮjJZ@ f7;𩼮S޻G0齽ʺŠS0$6TW)#gfz.aJ]h*o+ 7 Z-1A26b+-Sdl}wEVZOAي»IˬO ~M-JQS#xpaA.U7Y-۩6˚w]]llA?Z$㧲F waރ$Ųe]]DFok(vpi91k *Z  ,8mF6]pTqke0*1¶u4%y<8syjHA}X*ݹ1SbSW§ٖծ1k**kypH]oF*.f6TTcMe"¤0g)&Ůޟ:{kZ >8,$5*F21wsHpQkzF6c]wN̵ׄJ# pȄA#]F8l1?(gOB~TUyLbˁ8#^TO1ZbbySIOP~V{-b-4R^~Ge­lHnuS/:6# $Tj?e+y䏼Hf*'˼Ѝb# &??~p$iBF;[wzek~ZS 7H8v ?3$rj7nFY |OQ; U dؓS - \G=&pGw`)/ ai5&sL <:R=Pe6^X7}o5641W0ճ2k3$k%'1&-[#bML"'{ "!$*x(+)`F(> q-q,v.Ț/7pqXsYr3w%vQO+tru՛E~xKO} |b!ytxBz{l.m~Do8nkljw[h1Ri85bcm?a+f`Qeddf"giH IKSNJuyOcN LZMݥFĚGE@ND$A2D@XsBI*CThPU3gWu>V SR:P|Q~Z9[ SYfX]4\)^oEZ_/m5qs<\kg2z &J8 좞V`a/6i\lU,zB\uHƒ=&FW A+Ox]`غ7W>9q߳!7Kk ֩fض-bѠ3pj$]^Ĝ'*~@IWVÕ<ӂMʏş{ Dt͆mC-@mw+B.(>dT"ş~Ϝ8yo$w1J}50K_ ^ϋiBۉI#dXфTQc:r Р fΫnx|)Ko%3/uUv?A)ġ:C|sд@͉ ;IbeU"hH_S1ފZ^ھ4ge ȋbW72%k_ܝ8Ŵ(}OodJֿjw3XcVPW0Bq{gǧurCo&p-?О'sB zGɠ2>[ ;g/P8i_ Y=嗇e:ϏOZw3(?RXw@ Qh+HZ"0*WOIo@}m5N#+'*GA |􏒨HX=#?X1vjʨ`^pYL'!$UxAׯ3\Y;U^GP~b;!lڇF 2p(ԐQV_:X1: 3n :m@I)/NJ2"v+x xKH.jAf^O*9y]#Mk~`bю_޶ Rz7hFм!10cV"ajحn6 SrN){t*8Fv#fu`zrϮsɛW"G9E^vMcD&dA/yQA4S&ֿ EbLil!>aDƋΪ~7A8n&]|vYoᡱ Kyi׫w¡\~9$66 Qnf>q,o,ӹI 散 I{.C>HnY-Qg̰t zfa         0@`  0@`  (08@P`p L,l\<|B"bR2r J*jZ:zF&fV6vN.n^>~A!aQ1q I)iY9yE%eU5u M-m]=}   S S  3 3  s s    K K  + +  k k     [ [  ; ;  { {     G G  ' '  g g     W W  7 7  w w     O O  / /  o o     _ _  ? ?     @ `P0pH(hX8xD$dT4tC#c     z8?0@ _BMraB3GRSDSg+ Ap*]N1_-2Node.pdbUGP .text$di .text$lp00node.dll!20_pri7.text$mn.text$mn$00.text$np.text$x .text$ydd.text$zy4H.text$zz.rdata$brc .rdata$00$brc0.rdata$T$brc .rdata$zz$brcP .idata$5P.00cfg`.CRT$XCAh.CRT$XCC.CRT$XCL .CRT$XCU.CRT$XCZ.CRT$XIA.CRT$XIAA.CRT$XIZ.CRT$XLA.CRT$XLZ.cfguard.rdata .rdata$00  .rdata$zz).rdata$zzzdbgP).xdata@*.xdata$x *P.edatapP+ .idata$2|S+.idata$3S+ .idata$4`+.idata$6+(.data$00$brc(+.data$dk00$brc8+.data$pr00$brc+.data$r$brc+P.data$zz$brcЇ+0.data+.data$00+.data$dk00+0.data$zz+0 .bss+.bss$00p+ .bss$dk00+0.bss$pr00@+.bss$zz+^.pdata,.tls,x.stls,`!.tls$1/.tls$ZZZ@/`.rsrc$01`@/.rsrc$02dT42p!^P) t d T 42B20  20!>)20!Pl)4 p`P0!y) ALV@4 pP(B  r0!S )d42 p 0p!!!): (d5$T4 42, pR!"1%)""(k' T342, p `P!8%%@)t 4 rP@L((*4  p4 pP++,4 rp@, --2p0P4 pP.2//b  4 2p% 4 p`PH!496x)R`!t 4@66)!@66)!t 4@66)!@66)  4 2p!H7 8)20!8P:) 4 p!X:;4)4`8`<<f=t d42!>t?)dT42p!?Y@)d4pP@!@A)r~@@ADANAnA p`PAAC  4 rp6 (d7$46. pPb!C)E)CQDDDD   ; *d;&4:2 pPX!0EF )0EEEFfFpF{FN|s~6 (d7$46. pPb!FH)F1GGGGr20!HHp)&&h 4 p p`0PIJKd42p!K=L)" "d4 pPDLLQQ2p!d4R6R<)!R6R<)!d4R6R<)!R6R<)d42 p! SS)4 PS'T;T]TgT  BdT42pR p`0P! UX)R p ` 0: )4<2 p`P(!0YE[L)0YYHZZZZ [ (  P! tP[d[ )!dd[[)!  4[[,)![[,)!d[[)!P[d[ )! td4P[d[ )!P[d[ )! t"-)! td4"-)! td"-)! td4"-)!!4 p `P8!P]^8) P]]]]?^W^r^^^^`P!t 4 _U_)! _U_)!t 4 _U_)! _U_)!t 4 _U_)r p`0P!`GbH)@`Oa-b9 (4>4 p`P!Pbd)2>Pbb dudd N\% %t!dT4 Pd%ee r0pe  d T 4 rp!0ff)0fVfffff!!t d 4 r !fg)f)g\gtg}gg8 dT4 p0!gi)gOh{i? .t*d&4 P!jJn)jjj`lklxllmLmmm0d4pPPnnnn4 p`P!`oip)`ooNpB< +4  p`P(!ppDsD) ,8Dppp0qqrrrrs.sZ `P!t4ss)!ss)!t4ss)!t4ss)# #4r p`Ph!uhw)@uuEwT* *t&d"4 Pp!pwx)`pwwxx%d42 p!yy@)d42 p  4 2p!{&|p)h 4 Rp  4 Rp!`}~)20!`)%%4p ` P!ف)V0 IW ##t d 4 rP!$L)pO8QXf' 't"dT 4 rx!0)p0@t2p!d 40R<)!0R<)!d 40R<)!0R<)  4 RpB p 0d 4 r p!8r)d 4R p! )  4 2p!K)  4 2p!;)20!P4) bH)@8)  2PH bX)@8@i  2PX4 Rp )@8݋  2P B! )4 p!q)0)@HL!   RPr p`0Pp@`4r p`P!)@d" ' 't#d4 PP ! ) f  P !Wx)H2"  4 Rp!')4 Rp/p t d T 42!)! 0P!ڗ<)  4 2`!`)d42 p!l|)d4P`!;)AMO''  20dT 4 p20! ()R0d T 4 rp_kС%4F_4 pPp ڢգd 4 rph}`  p`0PX ҤΦ4 pP0F  p`0P p`0P@ܫ4 p4 R p t dT42!\)td42!d۳8) 0!F\)4pP!L )LV*T4 r p`X!)z* t d T 4R4 pP!t)<Z*((4p ` P!N) +4+R+c++++++,dT42p!`кx)20!غ )tT42! )T4 p `!t)d T 4Rp!)d T 4 rp!@ѽ ) dT 4 Rp!1D)dT42p!@p)d42 p!)d4 pX!$<)t d 4R!<)$ R p`P0!D)( (40( p`P!00)0<0qd|1.22 Rp`0!I)P)@\8&6>@H\i22  2Pd 4 Rp !P))@8Pp23  2P  dT4p!1`)!1`)!,383)td42!ld)R0!)20!)20!P)d 4 R p!\)R p`0P!<)!p`0!`)))@8@8+s888  2P  2P  4 2p!)d42 p!f)= ,4cX p`P!pB)0<HXhpo#99^:;;;;;;;3! d T 4 rp!)d 4 Rp!)L)@8Cn~n==  2PB 1to-dn)4mf Ph"!) 0<^jv 2(Em  : 0 \ 8y  +E^==e>> >?@ @@&@@QAA BB!B1B{BBC2P  4 2p!) 4R p`P!8)  4 2p!T@`)!d@el)!@el)!@`)!T@`)!@`)!TFG)!dTFG)!TFG)  4 2p!d@)!@)!d@)!@)!@)!dGTHl)  4 2p! )  4 2p!()T 4 2 p `!0U)!0U)!0U)!0U)!0U)!JK$)!JK$)d 4 Rp!X)@RK4R p`P!)^K2P  T 4 R p`!D)04RjL2P#rp`0!))$)@`8@86`muNPXly]]  2P bp!))@8]  2PpT4 `!t`P)!`P)!t`P)20!@{)  4 2p!)td  P!4 )!)!4 )R0!*X*@8"^  2PR0*@8(   2P 0!,*p*@0H0=<^a  RPdpP!4 *! *!4 *! *2p!40F$*!0F$*!40F$*!0F$*`0P!tt*!D*!D*!D*!t*!tt*!t*!tt*- -4"!p ` P!(*`l|3DLT\3S[abb ccCcncvc! !4 p`P! T*`ccc  rp`0  r0!t!'!*!T'!!*!'!!*!!'!*!t!'!*!tT!'!*4Rpd 4 r p!"#P*d 4R p!#$p*p`0P! $)%*!$)%*! $)%*!$)%*! dd*!dd*0 0t,d(4 P!'*$*'|'()de: )dT%4SL pPZ! *0*0<H **;,-O.g...T/e'f)gggghd T 4 rp/ /t+d'4 P!24p*`lx222223534B4S4`4{444.m6m p!d445X*!45X*!d445X*C 24WL p`PZ!5`D* 586667:0;I;H??@BRChC~CCmm n"n*n.o7o?omouo t d T 4R!DF * p P!d4FF *!FF *!d4FF *!d4FF *d T 4RpRp`042 p`0!tT JJ *!JJ *!tT JJ *2p`04 p!dLM *!LM *!dLM *!dLM *t 4 r P  4 rp!d OvPh *!OvPh *!d OvPh *!OvPh *!d OvPh */ /t-+d,'4*$ P!PV *0<HT`lPQQQR[RRUV*V7VRV^VoopKpppp 0P!tdV1W *!V1W *!tdV1W *!V1W *!tdV1W *< +4F< p`P0!`YD]d *`YY[\\]pHqVqss20!P]u] *UU%M&E'=(8)3*.+&x,h-] 0P T4 p`(!ӌD*xssss2p!d4*!*!d4*!*!d4ss*20!,*pP0!Ѝ6D*11x-h!5 p ` 0P!g`*Rtے '.^tthuuu  P!t d 4 pP*! X*!X*!pP*! t d 4 pP*!t d 4 pP*!pP*!t d 4 pP*! t d 4 pP*! !4 p`PH!ܤ0*&2>JVbnz ;Ku p`P0 D. dT4 r!t P*!P*!t P*!P*- -h  p`0P!P_*P-Pwx!xDyZyyyyyyyyzp0P!p/*P!t*!d*!4*!*!*!*! td4*!*!tzzx*! td4zzx*!tdzzx*  20!t*!*!t*T 42 p `  20!@i@*B!4IX* 0h!Pp**@HPu)x~   RPh b@!H*T*@E8HER6  2P@ R0*@k8ȶkx  2Pd4 p Fӷ42 P!Pȸ`*# #td4P!и|*и,  4 2p!*4!\*d 4R p  4 rpB!E$*20!h<*8 '#t4P@!p_T*p+$dS4RN p`!pi* t d T 4 r!p_*  4 2pd4 p t d T 4R  R0d2p t dT424 rpX~;p r0֕ɕ R0pΙ  4 Rp4 t T 4241*p`& )SSsZ%%IYVYz  4 2p&  4 2P20&i  4 Rpt4 Rp TT4 p ` 4 rp`&Cd;d2Pbp`0&  d 4 Rp&Lu bXt*@8  2PX0d 4 p *@DH .Q  RP4 rp0*@HȜ  RP0d42p+ +t'd#4 P8ƦҦӤ' 't#d4P`rAM$ $4 p`PȨ٪_rtd 4 P4 p Pd 4  pd4 rpP% %4 p `PC0au 4 p`P@  4 p 4 rp`P8r0 4 rp`P8d 4 rp8 *@XH Ee  RP42 p2p0XZF'2  d 4 p$4t d 4 r  iR p ` 0Hx!*@\H(Q\j  BP0H4 Rpp"*@8\z  2Ppt d 4 r"*@HQa  RP4 Rp   [ i   2P2P; *d[&4ZR pPK`4MX*4N JpB47 &d"4pP8bO[(! !tdT 4 `'3?+TYk# #td4Po{ ?I3"t\4[XP,s5E6 %d]!4\VpP`]m% 4un p`P`-d4 PbpXl& Jp`0(BN5 '46, p`PPRFRe dT4 px *4 prv2 p ` 03 !t,T+4* (2cT*d 4 Rp) (*@5 8     5 B   2P!!t d 4 R 00)*@y 8 G c y    2P0+4 p`PXRB: )4yn p`Pb6BNZ$7*4, (p2^# #td4PT4 r p `  4 2p 4rp ` P0 4v p`P 0  4 r`d T 4Rp$d/4., pP`&4OLPP ` 0 P0d 4 r p& 4 p`P  t d 4 R d4r p""hT 4R `""hd 4 r ptdT2t d 4RtT42 dT4pB 4 ph t d T 421 d_T^4]Vp$d4 pT4 p ` T4r p `$ N p`P0`d 4 r p 4 p`P T 4 2 p `* 4 p`P 4 pP  4 2p 4(  p`P* 4  p`P 4R p ` P d T 4 rp dT 4 rp d 4 2pt d 4Rd42 p4 r p- ] p`0P d T 4 Rpt T 4 r dT4 rp4 pPp, h0b p`0P ^p`0%t4Phd T42p 4 p@T 42 p `d42 p d"T!4 p$d_4^Z p  4 p`Pd42 p p`P0 p`P0! !ht4 P d T 42p d4 R P  t T 4R  p`P0d4  pHd 4 r p8% 4r p`P8# 4 p`PXdT pP p`P0H!!h 4 rp* h  p`0Prp`08T 4 2 p ` p`P0@ 4 p@ 4^ Zpd4 r p P dT4p  4 p` Zp`P0 p`P0` p`P0!"p`0Pd 4 r p 0p td4td4  RP dT4p  d4 p3*@8^  2P R08MMMM dT4 p`y̘H4 p`P5AAΙ 2Pd 4 rpIHIId 4 rpJIJJ  d4r p('G5*@3G8E*F;FFG3G@G\G  2P(d 4 rpPHH7HHR0xp6*@ɠ8l~ɠ  2Px3 %4" p`Pԗ۔ 33 %4  p`P6BNZƝߝ24 RpDƴѴR 0qKJKhK%4 P@Zj^L¼22P-  p`0PhP\ht4GT\i! p`0* h p`P0 p`0d 4 RpQu2vvvv&w1w;wFw""t4PXňш݈HRq4 rpd4dddT4 p`!d`ccdd 4 rpAcbb(c  dT4 ppÂcn1 #!t 4P @""d4 pPHa|{{A|))d%4 p P>t|}4 pPaΎH5 '49. p`PbrrPqqqKrYrRp0P4 R pP  P'h4pR~PO PBP dT4 p W0r04 rp:OFOVOfOvOOONNNNNNNN,Od 4 rp( Z! !4 p`PPiu+a,6A! !4 p`Px".:ij$ $4 p`Plx%2_,6A! !4 p`Pkw#/s.8C p`0Pco{4>I$ $4 p`Piu;H*o)3>! !4 p`P@(5rp`0PS@=td4  T4 rp`X`!!4 pP!!4 p `P%~4 RpNZ+2P2P4 p`P fT 4 2 p `T 4 rp`H%4 p`Pp! !4 p`Pk,C4r p`Pk}T4 p`l+ p`0Pzrp`0Pt 4 r 8>J*2P4 2 p`Ph 4 Rp`P! !4 p`P`|! !4 p`PhJE! !4 p`Pg ^ D! !4 p`P| vY ! !4 p`P|! !4 p`P(    r p`0PPl+Rr p`0Pxd#Jr p`0Pr p`0P xr p`0P({d 4 rpPc`E! !4r p`PeBT4 p`! !! rp`0f"!"R" p`0P    d 4 rpH##N#t#d 4 rpp4$##$d T 4 rp4 p`PY.e. -t--..9.T4 rp`j6p55K63 %4 p`P8+0**+4 p`P`R54c465T4 rp`31E22T4 rp`l766M74 p`P,-+6,,,,d 4 Rp;'&&('4r p`P(33 3t3333 `0PP=1..)1d 4 rpx1P111$ $4 p`PAAB,>>>>a??l@|@A2P( (4 p `P==>:x:::l;;t<<=2P$ $4 p`PEEF,BBBB^CCfDvDE2PT 4 rp`:H999T 4 rp`@d877E8T 4 rp`h49x889-T4p`rIH@GGH-T4p`rI`HHI3 %4 p`P OLRMNd 4 rpZSRS>S! !4 p`P0XVdV TyTTU0V2P4r p`PXRpQQR4 rp`P5QPPPQ4 rp`:P OqO P  td4 PL0JJK4 rp`PY(YuYY.T241 .p bY$XXXr p`0P% %4 p `PHXV-WW4 p`Pprj~jhFiiIjSj4 p`PC\O\Z6[[\$\4 p`Pddbcccc4 p`P3g?ge&ff gg4 p`Phh`gg5hhh4 p`P8ee@ddezee4 p`P`bb avaaZbdb4 p`P``__e```4 p`Pc_o_^V^^:_D_4 p`P]]p\\E]]] p`0P""4 pPyvwy! !4 p`P(Utatr s&s)t3t4 p`PPzzyz-zzzz4 &d#"4! pPxnl[mn4 rp`P{P{{{d 4 rp<{z{#{  4 rp' 't#4 P0b' 't#4 Prքd T r p& &"dP@~dT4ph~}}l~d4p}|%}u}d4p||U||d4 px̅$_2$4p ` Pr?qlppq4 p `P0qTqqqdT4 pT 4 rpXÉd4r p`Pvuvvv4 &d!"4  pPuttteu d@T?4>:pt d 4 rW-  p`0Pu" "d4 pP К+2<Kwd4 rpH0ۘ4 pPpЖ"@2x.h*d;&4:2 pPbp,*:@2x.h*d=&4<4 pPr %p%3,7J5 '48. p`P8b)7jx?5 '4:0 p`P`rgsb$/5 '48. p`PbYeuڨ&6 (d9$480 pPrǢӢRšء0;GY: )4<2 p`P0m{; *d;&4:2 pPP?KWg6 (d9$480 pPxrb@KWi6 (d9$480 pPrry6 (d9$480 pPr@_8CV6 (d7$46. pPb.A۸6 (d7$46. pPb K5 '48. p`P@bCOTb_rįЯ; *d;&4:2 pPh.<oy; *d;&4:2 pPS_kp(mx; *d;&4:2 pP¿οڿp,˽̾׾_it: )d?%4>6 pP&2>JVvb77BM`; *d;&4:2 pP0?KW`׹ ]h{! !4 p`PßF"2t 4 rPk pS: ,t3(d2$41* P B7Ead r pP4 rp`PH pd 4 rppU9d 4 rp5" "4" pPL8 'tW#dV4URP7Bd 4 rp=i3 %5!t4430P8rmP <d 4 rp`gK# #td4P[09T4 rp`@0!% %4(  p`P*6BNp 3 " `0PT4 rp``4r pP(d4 pP`4 rp`Px%@ T4 rp`&e dT4 rp,8DP4 pP9 4 &d!"4  pP=y..x*h&d"4 pP@ g  ) )h%d!4 pPhRjt/ !4 p`P .  4 p`P%T4 rp`%! !4 p`Pf r  Z  : D 4 p`P0    A   T4 rp`XDT4 rp`=@ dT4 rpJT4 rp`)0 +4$p`P$+4$p`P Ct4 RpH8]d T 4 rppUdv""4 `P`d 4 rp$qd4 p!P!!!4 rp`P2!P  !T4 rp`8 #"d""4 rp`P`5 P 4 rp`P$ #o##!!t d 4 R P$$M$o$ T4r p`xu++p***/+P+T4 rp`,++,d rpP&$2%%d 4 rpY*)*=*4 rp`P7'0&&' `0P@)P'')/  p`0Ph;P::;. 4 p`Pz<;B<<+4$p`Ps4@334%4I4d 4 rp> >q>>d 4 rp >=a==9 +t"'d!#4  P02 300122! !4 p`PX,B8BDB@@LAkAAA BT4 rp`pC`BBQCT4 rp`DCCDT4 rp`@p??a@T4 rp`EDEE% %4 p`P /0(...//d T 4 rpH99099999%%4 pPpg8s84+578G84 Rp-,,-d 4 rp9888& &!4 p `PULLU4 Rp @FEFFt d 4 r8 YXgXX  p`0P` ZKIJ9K" "d4r pP IWU-V%WT4p IH II4pP xG`FF_G  p`0P [YYi[d 4 rp( HHQHH t4d4 rpP& &d"4 pPx ``` ^m^!_E__`m`""d4 pP \[[\r p `0 gf9gg4 p`P hig-h7hhh4 &d'"4& pP@ YqeqmJnpq&q3 %4.$ p`Ph mmm iijjIjkAmKmVm0 "4& pP {{wuxxxzv{{4 &48. p`P bwwwwwq rgrtrr)stuDwOwYwcwnw# #t4 P G0 "4& pP ĆІσ܃%0 "4& pP0 {e|||~fptd4  ׏Ў'" "d4 pP q}@ōCMT4 rp` pČь-  p`0P N[( R0  Tt4 RpH @߉2T4 rp` tH"p0 d T 4 rp Jp`P0@Rp ` 00- td4Ph T4 R p ` td4Pt d42 d T 4 2pd 4 R p. dU4TN p P`dT42p42 p t d T 4 r. dO4NJ p P@  d 2p!4OJp`P@ tdT 4  +p`P0@Bp ` P 04r p`P t d T 4 R 4 p ` P.xhT4 p `0 4 2 p`P2 !dW!4U!N p P`# p`0Ppd T 4 Rpd 4 R p2 0d 42 p tdT4d4  p p ` P 0. dT4RN p P` 4 p! !p`0P d T 42p 4 r p`8  2p0P' dT4ph!T4 p `@  4 Rp% 45, p`PP4R pd 4R pT 42p` 4 p ` P( (4(p`P d T 4 Rp$ $4$p`P' d4 p PP' d4 p PX4p`PX& &d&T&4&r" p5 #TX#4W#Pp`p" "d "T "4 "Rpd T 4Rp& &d &T &4 &2" p( 4 p`Pp% 4 p`Ph d T 4 2p T 4 2 p ` d T 4 R T 4 Rp`' '4'p`P 4 pP 42p`P d T 42p T 4 2 p ` d 4 2 p Ptd42T 4 r p ` tdT4  p`0P t d T 42 tdT4t* 4  p`P B p`P0 tdT4td T4d 4 R p  d T4pt d44`*x*@*++L***@*0+LLP*p**@*X++*@*8+(QT**`++PT*h*@*+(Oȓ*ؒ*h*@*i[R*H*L*P*RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR```````` 0MppxPN@&P'P'0F((s _000p`00szP(PP(Ps^0М``000    U                 U        `0          `(`(          ))        PsXP@@@ 0*@G`H@\ @+{`0 `0 P`@@иpм X -P`^p@b`c@N@pppppppP f@p{k3@IЏ`o@O@N0@P  J$ wL@H Jо  .P0pOp 0@.0J@P#P1{{KLpP~Џ !!!!!!!!!!!!`@{`}``0 ~~0~~|Ќ{`10`P0{pwuPnPP@@`RR S`pHpH0Hd !HйR0 3pR@6i05pD@ `0L4LLLp5@"`0"""" OPP`%g20"V4P2!@@@@` &PQF I01@06J` 1p1@@pQ@I00!@з0|Ѝ U7P$p${` &`@7pS`@${{{0fЍ@`T T$$$%V`Vؚ+b)b)b)```-+p@؀+(++P+x++8+`+++ȁ+++@+h+++1.  '.0 `2p3P  `!!p2p?FFG%p@6Gab`vcpd e@efghpiPjp Pk0lmnnor`spt667GP?'7=3P4p8 4P(p4(??`0 p; #@@#P(`#P@@ >`>>.@((0<## $$$P%%%% &`&&&<>`@P) '`)))P**+0P+' 0@P@,p,0445, -P--6`78 9`;`1 7= <0<@. [**** *=*c*****G*n****G*m**ź***A*****B*g**Ǽ***P***ǽ***3*Y***Ҿ***?*k***ݿ**C*k****:*t***0*u***$*i*** *R*{**#*\*****7******;*\**** *Q*v*****E*o****'*P*|*****+*G*c*}***** *=*n*** *>*p****8*l****P*****Q*****P****2*f****8*j****4*f****0*b******_*** *<*l****8*k****;*t****B*x****B*r****V***6*t*** *4*\******7*]***** *-*O*w******Q*v****#*N*w*****;*_*****"*E*k******L*w*****>*p****,*Q*t*****;*^***** */*Q*****M****-*^****8*g****)*V****8*i****C*z****"*E*h*******3*R*k****0*j***2*Q***2*}****`***)*P*{****"*K*s*****E*m***"*w***_***#*F*|***.*****@*p*** *@*o****>*o****#+`++++V++++$+l+++ +2+V+++ +R++++3++++Y+|+++&+j++++.+J++++ +P + + + +Q + + + +# +K + + + + +> + + + + + +0 +F +q + + ++/+\+++++C+n++++++N+++++++,+I+i++++ +,+b+}++++)+I+k+++++++ +Y+++e++++(+`+++(+f+++H++++b+++)+t+++m+++)+]++++A+a++++'+++ +J + + +!+S!+!+ "+?"+s"+"+ #+b#+#+#+8$+r$+$+$+$+7%+h%+%+%+(&+}&+&+&+:'+'+'+(+Z(+(+(+=)+)+)+)+ *+P*+*+*+2++++g,+=-+-+-+-+.+n.+.+.+/+9/+/+/+0+1+e1+q2+2+2+3+Q3+3+3+3+-4+4+4+4+,5+c5+5+5+6+N6+6+6+6+*7+a7+7+7+7+8+98+n8+8+8+9+F9+{9+9+9+:+E:+:+:+:+G;+;+;+;+*<+J<+<+<+<+ =+T=+=+=+=+ >+#>+?>+Y>+s>+>+>+2?+l?+?+?+@+V@+@+@+?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Node.dll??0?$Handle@VArray@v8@@@v8@@QEAA@PEAVArray@1@@Z??0?$Handle@VArray@v8@@@v8@@QEAA@XZ??0?$Handle@VBoolean@v8@@@v8@@QEAA@PEAVBoolean@1@@Z??0?$Handle@VBoolean@v8@@@v8@@QEAA@XZ??0?$Handle@VContext@v8@@@v8@@QEAA@PEAVContext@1@@Z??0?$Handle@VContext@v8@@@v8@@QEAA@XZ??0?$Handle@VDate@v8@@@v8@@QEAA@PEAVDate@1@@Z??0?$Handle@VDate@v8@@@v8@@QEAA@XZ??0?$Handle@VExternal@v8@@@v8@@QEAA@PEAVExternal@1@@Z??0?$Handle@VExternal@v8@@@v8@@QEAA@XZ??0?$Handle@VFunction@v8@@@v8@@QEAA@PEAVFunction@1@@Z??0?$Handle@VFunction@v8@@@v8@@QEAA@XZ??0?$Handle@VFunctionTemplate@v8@@@v8@@QEAA@PEAVFunctionTemplate@1@@Z??0?$Handle@VFunctionTemplate@v8@@@v8@@QEAA@XZ??0?$Handle@VInt32@v8@@@v8@@QEAA@PEAVInt32@1@@Z??0?$Handle@VInteger@v8@@@v8@@QEAA@PEAVInteger@1@@Z??0?$Handle@VInteger@v8@@@v8@@QEAA@XZ??0?$Handle@VMessage@v8@@@v8@@QEAA@XZ??0?$Handle@VNumber@v8@@@v8@@QEAA@PEAVNumber@1@@Z??0?$Handle@VNumber@v8@@@v8@@QEAA@XZ??0?$Handle@VObject@v8@@@v8@@QEAA@PEAVObject@1@@Z??0?$Handle@VObject@v8@@@v8@@QEAA@XZ??0?$Handle@VObjectTemplate@v8@@@v8@@QEAA@PEAVObjectTemplate@1@@Z??0?$Handle@VObjectTemplate@v8@@@v8@@QEAA@XZ??0?$Handle@VPrimitive@v8@@@v8@@QEAA@PEAVPrimitive@1@@Z??0?$Handle@VPrimitive@v8@@@v8@@QEAA@XZ??0?$Handle@VScript@v8@@@v8@@QEAA@PEAVScript@1@@Z??0?$Handle@VScript@v8@@@v8@@QEAA@XZ??0?$Handle@VSignature@v8@@@v8@@QEAA@PEAVSignature@1@@Z??0?$Handle@VSignature@v8@@@v8@@QEAA@XZ??0?$Handle@VString@v8@@@v8@@QEAA@PEAVString@1@@Z??0?$Handle@VString@v8@@@v8@@QEAA@XZ??0?$Handle@VUint32@v8@@@v8@@QEAA@PEAVUint32@1@@Z??0?$Handle@VValue@v8@@@v8@@QEAA@PEAVValue@1@@Z??0?$Handle@VValue@v8@@@v8@@QEAA@XZ??0?$Local@VArray@v8@@@v8@@QEAA@XZ??0?$Local@VBoolean@v8@@@v8@@QEAA@XZ??0?$Local@VContext@v8@@@v8@@QEAA@XZ??0?$Local@VDate@v8@@@v8@@QEAA@XZ??0?$Local@VExternal@v8@@@v8@@QEAA@XZ??0?$Local@VFunction@v8@@@v8@@QEAA@XZ??0?$Local@VFunctionTemplate@v8@@@v8@@QEAA@XZ??0?$Local@VInteger@v8@@@v8@@QEAA@XZ??0?$Local@VMessage@v8@@@v8@@QEAA@XZ??0?$Local@VNumber@v8@@@v8@@QEAA@XZ??0?$Local@VObject@v8@@@v8@@QEAA@XZ??0?$Local@VObjectTemplate@v8@@@v8@@QEAA@XZ??0?$Local@VPrimitive@v8@@@v8@@QEAA@XZ??0?$Local@VScript@v8@@@v8@@QEAA@XZ??0?$Local@VSignature@v8@@@v8@@QEAA@XZ??0?$Local@VValue@v8@@@v8@@QEAA@XZ??0?$Persistent@VArray@v8@@@v8@@QEAA@AEBV?$Handle@VArray@v8@@@1@@Z??0?$Persistent@VArray@v8@@@v8@@QEAA@XZ??0?$Persistent@VContext@v8@@@v8@@QEAA@AEBV01@@Z??0?$Persistent@VContext@v8@@@v8@@QEAA@XZ??0?$Persistent@VFunction@v8@@@v8@@QEAA@AEBV?$Handle@VFunction@v8@@@1@@Z??0?$Persistent@VFunction@v8@@@v8@@QEAA@XZ??0?$Persistent@VFunctionTemplate@v8@@@v8@@QEAA@AEBV01@@Z??0?$Persistent@VFunctionTemplate@v8@@@v8@@QEAA@AEBV?$Handle@VFunctionTemplate@v8@@@1@@Z??0?$Persistent@VFunctionTemplate@v8@@@v8@@QEAA@XZ??0?$Persistent@VObject@v8@@@v8@@QEAA@AEBV01@@Z??0?$Persistent@VObject@v8@@@v8@@QEAA@AEBV?$Handle@VObject@v8@@@1@@Z??0?$Persistent@VObject@v8@@@v8@@QEAA@XZ??0?$Persistent@VObjectTemplate@v8@@@v8@@QEAA@AEBV?$Handle@VObjectTemplate@v8@@@1@@Z??0?$Persistent@VObjectTemplate@v8@@@v8@@QEAA@XZ??0?$Persistent@VScript@v8@@@v8@@QEAA@AEBV?$Handle@VScript@v8@@@1@@Z??0?$Persistent@VScript@v8@@@v8@@QEAA@XZ??0?$Persistent@VSignature@v8@@@v8@@QEAA@AEBV?$Handle@VSignature@v8@@@1@@Z??0?$Persistent@VString@v8@@@v8@@QEAA@AEBV01@@Z??0?$Persistent@VString@v8@@@v8@@QEAA@AEBV?$Handle@VString@v8@@@1@@Z??0?$Persistent@VString@v8@@@v8@@QEAA@XZ??0AccessorInfo@v8@@QEAA@V?$Local@VValue@v8@@@1@V?$Local@VObject@v8@@@1@@Z??0Arguments@v8@@QEAA@PEAPEAVValue@1@HV?$Local@VObject@v8@@@1@_NV?$Local@VFunction@v8@@@1@@Z??0AsciiValue@String@v8@@QEAA@V?$Handle@VValue@v8@@@2@@Z??0Buffer@node@@AEAA@V?$Handle@VObject@v8@@@v8@@_K@Z??0Buffer@node@@QEAA@AEBV01@@Z??0ExternalAsciiStringResource@String@v8@@QEAA@AEBV012@@Z??0ExternalAsciiStringResource@String@v8@@QEAA@XZ??0HandleScope@v8@@QEAA@XZ??0HandleWrap@node@@IEAA@V?$Handle@VObject@v8@@@v8@@PEAUuv_handle_s@@@Z??0HandleWrap@node@@QEAA@AEBV01@@Z??0ObjectWrap@node@@QEAA@AEBV01@@Z??0ObjectWrap@node@@QEAA@XZ??0PipeWrap@node@@AEAA@V?$Handle@VObject@v8@@@v8@@_N@Z??0PipeWrap@node@@QEAA@$$QEAV01@@Z??0PipeWrap@node@@QEAA@AEBV01@@Z??0RetainedObjectInfo@v8@@QEAA@$$QEAV01@@Z??0RetainedObjectInfo@v8@@QEAA@AEBV01@@Z??0RetainedObjectInfo@v8@@QEAA@XZ??0Scope@Context@v8@@QEAA@V?$Handle@VContext@v8@@@2@@Z??0StreamWrap@node@@IEAA@V?$Handle@VObject@v8@@@v8@@PEAUuv_stream_s@@@Z??0StreamWrap@node@@QEAA@$$QEAV01@@Z??0StreamWrap@node@@QEAA@AEBV01@@Z??0TryCatch@v8@@QEAA@XZ??0Utf8Value@String@v8@@QEAA@V?$Handle@VValue@v8@@@2@@Z??0Value@String@v8@@QEAA@V?$Handle@VValue@v8@@@2@@Z??1?$Persistent@VArray@v8@@@v8@@QEAA@XZ??1?$Persistent@VContext@v8@@@v8@@QEAA@XZ??1?$Persistent@VFunction@v8@@@v8@@QEAA@XZ??1?$Persistent@VFunctionTemplate@v8@@@v8@@QEAA@XZ??1?$Persistent@VObject@v8@@@v8@@QEAA@XZ??1?$Persistent@VObjectTemplate@v8@@@v8@@QEAA@XZ??1?$Persistent@VScript@v8@@@v8@@QEAA@XZ??1?$Persistent@VSignature@v8@@@v8@@QEAA@XZ??1?$Persistent@VString@v8@@@v8@@QEAA@XZ??1AsciiValue@String@v8@@QEAA@XZ??1Buffer@node@@UEAA@XZ??1ExternalAsciiStringResource@String@v8@@UEAA@XZ??1HandleScope@v8@@QEAA@XZ??1HandleWrap@node@@MEAA@XZ??1ObjectWrap@node@@UEAA@XZ??1PipeWrap@node@@UEAA@XZ??1Scope@Context@v8@@QEAA@XZ??1StreamWrap@node@@UEAA@XZ??1TryCatch@v8@@QEAA@XZ??1Utf8Value@String@v8@@QEAA@XZ??1Value@String@v8@@QEAA@XZ??4?$Handle@VArray@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VArray@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VBoolean@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VBoolean@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VContext@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VContext@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VData@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VData@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VDate@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VDate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VExternal@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VExternal@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VFunction@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VFunction@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VFunctionTemplate@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VFunctionTemplate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VInt32@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VInt32@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VInteger@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VInteger@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VMessage@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VMessage@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VNumber@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VNumber@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VObject@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VObject@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VObjectTemplate@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VObjectTemplate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VPrimitive@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VPrimitive@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VScript@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VScript@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VSignature@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VSignature@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VString@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VString@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VUint32@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VUint32@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Handle@VValue@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Handle@VValue@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VArray@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VArray@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VBoolean@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VBoolean@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VContext@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VContext@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VDate@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VDate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VExternal@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VExternal@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VFunction@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VFunction@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VFunctionTemplate@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VFunctionTemplate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VInt32@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VInt32@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VInteger@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VInteger@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VMessage@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VMessage@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VNumber@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VNumber@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VObject@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VObject@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VObjectTemplate@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VObjectTemplate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VPrimitive@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VPrimitive@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VScript@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VScript@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VSignature@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VSignature@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VUint32@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VUint32@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Local@VValue@v8@@@v8@@QEAAAEAV01@$$QEAV01@@Z??4?$Local@VValue@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VArray@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VContext@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VFunction@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAAEAV01@AEBV?$Handle@VFunctionTemplate@v8@@@1@@Z??4?$Persistent@VObject@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VObject@v8@@@v8@@QEAAAEAV01@AEBV?$Handle@VObject@v8@@@1@@Z??4?$Persistent@VObjectTemplate@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VScript@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4?$Persistent@VString@v8@@@v8@@QEAAAEAV01@AEBV01@@Z??4AccessorInfo@v8@@QEAAAEAV01@$$QEAV01@@Z??4AccessorInfo@v8@@QEAAAEAV01@AEBV01@@Z??4Arguments@v8@@QEAAAEAV01@$$QEAV01@@Z??4Arguments@v8@@QEAAAEAV01@AEBV01@@Z??4Array@v8@@QEAAAEAV01@$$QEAV01@@Z??4Array@v8@@QEAAAEAV01@AEBV01@@Z??4Boolean@v8@@QEAAAEAV01@$$QEAV01@@Z??4Boolean@v8@@QEAAAEAV01@AEBV01@@Z??4Buffer@node@@QEAAAEAV01@AEBV01@@Z??4Context@v8@@QEAAAEAV01@$$QEAV01@@Z??4Context@v8@@QEAAAEAV01@AEBV01@@Z??4Data@v8@@QEAAAEAV01@$$QEAV01@@Z??4Data@v8@@QEAAAEAV01@AEBV01@@Z??4Date@v8@@QEAAAEAV01@$$QEAV01@@Z??4Date@v8@@QEAAAEAV01@AEBV01@@Z??4Debug@v8@@QEAAAEAV01@$$QEAV01@@Z??4Debug@v8@@QEAAAEAV01@AEBV01@@Z??4Exception@v8@@QEAAAEAV01@$$QEAV01@@Z??4Exception@v8@@QEAAAEAV01@AEBV01@@Z??4External@v8@@QEAAAEAV01@$$QEAV01@@Z??4External@v8@@QEAAAEAV01@AEBV01@@Z??4ExternalAsciiStringResource@String@v8@@QEAAAEAV012@AEBV012@@Z??4Function@v8@@QEAAAEAV01@$$QEAV01@@Z??4Function@v8@@QEAAAEAV01@AEBV01@@Z??4FunctionTemplate@v8@@QEAAAEAV01@$$QEAV01@@Z??4FunctionTemplate@v8@@QEAAAEAV01@AEBV01@@Z??4HandleScope@v8@@QEAAAEAV01@AEBV01@@Z??4HandleWrap@node@@QEAAAEAV01@AEBV01@@Z??4HeapProfiler@v8@@QEAAAEAV01@$$QEAV01@@Z??4HeapProfiler@v8@@QEAAAEAV01@AEBV01@@Z??4HeapStatistics@v8@@QEAAAEAV01@$$QEAV01@@Z??4HeapStatistics@v8@@QEAAAEAV01@AEBV01@@Z??4Int32@v8@@QEAAAEAV01@$$QEAV01@@Z??4Int32@v8@@QEAAAEAV01@AEBV01@@Z??4Integer@v8@@QEAAAEAV01@$$QEAV01@@Z??4Integer@v8@@QEAAAEAV01@AEBV01@@Z??4Isolate@v8@@QEAAAEAV01@$$QEAV01@@Z??4Isolate@v8@@QEAAAEAV01@AEBV01@@Z??4JitCodeEvent@v8@@QEAAAEAV01@$$QEAV01@@Z??4JitCodeEvent@v8@@QEAAAEAV01@AEBV01@@Z??4Locker@v8@@QEAAAEAV01@$$QEAV01@@Z??4Locker@v8@@QEAAAEAV01@AEBV01@@Z??4Message@v8@@QEAAAEAV01@$$QEAV01@@Z??4Message@v8@@QEAAAEAV01@AEBV01@@Z??4Number@v8@@QEAAAEAV01@$$QEAV01@@Z??4Number@v8@@QEAAAEAV01@AEBV01@@Z??4Object@v8@@QEAAAEAV01@$$QEAV01@@Z??4Object@v8@@QEAAAEAV01@AEBV01@@Z??4ObjectTemplate@v8@@QEAAAEAV01@$$QEAV01@@Z??4ObjectTemplate@v8@@QEAAAEAV01@AEBV01@@Z??4ObjectWrap@node@@QEAAAEAV01@AEBV01@@Z??4PipeWrap@node@@QEAAAEAV01@$$QEAV01@@Z??4PipeWrap@node@@QEAAAEAV01@AEBV01@@Z??4Primitive@v8@@QEAAAEAV01@$$QEAV01@@Z??4Primitive@v8@@QEAAAEAV01@AEBV01@@Z??4ResourceConstraints@v8@@QEAAAEAV01@$$QEAV01@@Z??4ResourceConstraints@v8@@QEAAAEAV01@AEBV01@@Z??4RetainedObjectInfo@v8@@QEAAAEAV01@$$QEAV01@@Z??4RetainedObjectInfo@v8@@QEAAAEAV01@AEBV01@@Z??4Scope@Context@v8@@QEAAAEAV012@AEBV012@@Z??4Script@v8@@QEAAAEAV01@$$QEAV01@@Z??4Script@v8@@QEAAAEAV01@AEBV01@@Z??4Signature@v8@@QEAAAEAV01@$$QEAV01@@Z??4Signature@v8@@QEAAAEAV01@AEBV01@@Z??4StreamWrap@node@@QEAAAEAV01@$$QEAV01@@Z??4StreamWrap@node@@QEAAAEAV01@AEBV01@@Z??4String@v8@@QEAAAEAV01@$$QEAV01@@Z??4String@v8@@QEAAAEAV01@AEBV01@@Z??4TryCatch@v8@@QEAAAEAV01@AEBV01@@Z??4Uint32@v8@@QEAAAEAV01@$$QEAV01@@Z??4Uint32@v8@@QEAAAEAV01@AEBV01@@Z??4V8@v8@@QEAAAEAV01@$$QEAV01@@Z??4V8@v8@@QEAAAEAV01@AEBV01@@Z??4Value@v8@@QEAAAEAV01@$$QEAV01@@Z??4Value@v8@@QEAAAEAV01@AEBV01@@Z??AArguments@v8@@QEBA?AV?$Local@VValue@v8@@@1@H@Z??C?$Handle@VArray@v8@@@v8@@QEBAPEAVArray@1@XZ??C?$Handle@VBoolean@v8@@@v8@@QEBAPEAVBoolean@1@XZ??C?$Handle@VContext@v8@@@v8@@QEBAPEAVContext@1@XZ??C?$Handle@VExternal@v8@@@v8@@QEBAPEAVExternal@1@XZ??C?$Handle@VFunction@v8@@@v8@@QEBAPEAVFunction@1@XZ??C?$Handle@VFunctionTemplate@v8@@@v8@@QEBAPEAVFunctionTemplate@1@XZ??C?$Handle@VInteger@v8@@@v8@@QEBAPEAVInteger@1@XZ??C?$Handle@VMessage@v8@@@v8@@QEBAPEAVMessage@1@XZ??C?$Handle@VObject@v8@@@v8@@QEBAPEAVObject@1@XZ??C?$Handle@VObjectTemplate@v8@@@v8@@QEBAPEAVObjectTemplate@1@XZ??C?$Handle@VPrimitive@v8@@@v8@@QEBAPEAVPrimitive@1@XZ??C?$Handle@VScript@v8@@@v8@@QEBAPEAVScript@1@XZ??C?$Handle@VString@v8@@@v8@@QEBAPEAVString@1@XZ??C?$Handle@VValue@v8@@@v8@@QEBAPEAVValue@1@XZ??D?$Handle@VArray@v8@@@v8@@QEBAPEAVArray@1@XZ??D?$Handle@VBoolean@v8@@@v8@@QEBAPEAVBoolean@1@XZ??D?$Handle@VContext@v8@@@v8@@QEBAPEAVContext@1@XZ??D?$Handle@VData@v8@@@v8@@QEBAPEAVData@1@XZ??D?$Handle@VDate@v8@@@v8@@QEBAPEAVDate@1@XZ??D?$Handle@VExternal@v8@@@v8@@QEBAPEAVExternal@1@XZ??D?$Handle@VFunction@v8@@@v8@@QEBAPEAVFunction@1@XZ??D?$Handle@VFunctionTemplate@v8@@@v8@@QEBAPEAVFunctionTemplate@1@XZ??D?$Handle@VInteger@v8@@@v8@@QEBAPEAVInteger@1@XZ??D?$Handle@VNumber@v8@@@v8@@QEBAPEAVNumber@1@XZ??D?$Handle@VObject@v8@@@v8@@QEBAPEAVObject@1@XZ??D?$Handle@VObjectTemplate@v8@@@v8@@QEBAPEAVObjectTemplate@1@XZ??D?$Handle@VPrimitive@v8@@@v8@@QEBAPEAVPrimitive@1@XZ??D?$Handle@VScript@v8@@@v8@@QEBAPEAVScript@1@XZ??D?$Handle@VSignature@v8@@@v8@@QEBAPEAVSignature@1@XZ??D?$Handle@VString@v8@@@v8@@QEBAPEAVString@1@XZ??D?$Handle@VValue@v8@@@v8@@QEBAPEAVValue@1@XZ??DAsciiValue@String@v8@@QEAAPEADXZ??DAsciiValue@String@v8@@QEBAPEBDXZ??DUtf8Value@String@v8@@QEAAPEADXZ??DUtf8Value@String@v8@@QEBAPEBDXZ??DValue@String@v8@@QEAAPEAGXZ??DValue@String@v8@@QEBAPEBGXZ??_7Buffer@node@@6B@??_7ExternalAsciiStringResource@String@v8@@6B@??_7HandleWrap@node@@6B@??_7ObjectWrap@node@@6B@??_7PipeWrap@node@@6B@??_7RetainedObjectInfo@v8@@6B@??_7StreamWrap@node@@6B@?AddGCEpilogueCallback@V8@v8@@SAXP6AXHH@Z@Z?AddGCPrologueCallback@V8@v8@@SAXP6AXHH@Z@Z?AdjustAmountOfExternalAllocatedMemory@V8@v8@@SA_J_J@Z?AfterConnect@PipeWrap@node@@CAXPEAUuv_connect_s@@H@Z?AfterShutdown@StreamWrap@node@@CAXPEAUuv_shutdown_s@@H@Z?AfterWrite@StreamWrap@node@@CAXPEAUuv_write_s@@H@Z?AsciiSlice@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?AsciiWrite@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?AtExit@node@@YAXP6AXPEAX@Z0@Z?Base64Slice@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Base64Write@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?BinarySlice@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?BinaryWrite@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Bind@PipeWrap@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?BooleanValue@Value@v8@@QEBA_NXZ?BuildByteCache@nativerequire@node@@YAHPEBD0I_N@Z?ByteLength@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Call@Function@v8@@QEAA?AV?$Local@VValue@v8@@@2@V?$Handle@VObject@v8@@@2@HQEAV?$Handle@VValue@v8@@@2@@Z?Callee@Arguments@v8@@QEBA?AV?$Local@VFunction@v8@@@2@XZ?Cast@Array@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@Date@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@External@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@Function@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@Integer@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@Number@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@Object@v8@@SAPEAV12@PEAVValue@2@@Z?Cast@String@v8@@SAPEAV12@PEAVValue@2@@Z?Clear@?$Handle@VArray@v8@@@v8@@QEAAXXZ?Clear@?$Handle@VBoolean@v8@@@v8@@QEAAXXZ?Clear@?$Handle@VInteger@v8@@@v8@@QEAAXXZ?Clear@?$Handle@VObject@v8@@@v8@@QEAAXXZ?Clear@?$Handle@VPrimitive@v8@@@v8@@QEAAXXZ?Clear@?$Handle@VString@v8@@@v8@@QEAAXXZ?Clear@?$Handle@VValue@v8@@@v8@@QEAAXXZ?ClearWeak@?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAXXZ?ClearWeak@?$Persistent@VObject@v8@@@v8@@QEAAXXZ?Close@HandleWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Compile@Script@v8@@SA?AV?$Local@VScript@v8@@@2@P6A_NPEAXPEAPEBG@ZP6AX0@Z0PEBGPEBE@Z?Compile@Script@v8@@SA?AV?$Local@VScript@v8@@@2@PEBG0@Z?Compile@Script@v8@@SA?AV?$Local@VScript@v8@@@2@V?$Handle@VString@v8@@@2@V?$Handle@VValue@v8@@@2@@Z?Concat@String@v8@@SA?AV?$Local@VString@v8@@@2@V?$Handle@VString@v8@@@2@0@Z?Connect@PipeWrap@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Copy@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Data@AccessorInfo@v8@@QEBA?AV?$Local@VValue@v8@@@2@XZ?Data@Buffer@node@@SAPEADPEAV12@@Z?Data@Buffer@node@@SAPEADV?$Handle@VValue@v8@@@v8@@@Z?DebugBreak@Debug@v8@@SAXPEAVIsolate@2@@Z?DecodeBytes@node@@YA_JV?$Handle@VValue@v8@@@v8@@W4encoding@1@@Z?DecodeWrite@node@@YA_JPEAD_KV?$Handle@VValue@v8@@@v8@@W4encoding@1@@Z?DefineWrapperClass@HeapProfiler@v8@@SAXGP6APEAVRetainedObjectInfo@2@GV?$Handle@VValue@v8@@@2@@Z@Z?Delete@Object@v8@@QEAA_NV?$Handle@VString@v8@@@2@@Z?DisableAgent@Debug@v8@@SAXXZ?DisableExternalObjectFinalizer@v8@@YAXPEAX@Z?Dispose@?$Persistent@VArray@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VContext@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VFunction@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VObject@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VObjectTemplate@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VScript@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VSignature@v8@@@v8@@QEAAXXZ?Dispose@?$Persistent@VString@v8@@@v8@@QEAAXXZ?Dispose@V8@v8@@SA_NXZ?EmitExternalEvent@node@@YA_NV?$Handle@VString@v8@@@v8@@HQEAV?$Handle@VValue@v8@@@3@@Z?Empty@String@v8@@SA?AV?$Local@VString@v8@@@2@XZ?EnableAgent@Debug@v8@@SA_NPEBDH_N@Z?Encode@node@@YA?AV?$Local@VValue@v8@@@v8@@PEBX_KW4encoding@1@@Z?Enter@Isolate@v8@@QEAAXXZ?Equals@Value@v8@@QEBA_NV?$Handle@VValue@v8@@@2@@Z?ErrnoException@node@@YA?AV?$Local@VValue@v8@@@v8@@HPEBD00@Z?Error@Exception@v8@@SA?AV?$Local@VValue@v8@@@2@V?$Handle@VString@v8@@@2@@Z?Exception@TryCatch@v8@@QEAA?AV?$Local@VValue@v8@@@2@XZ?Exit@Isolate@v8@@QEAAXXZ?ExternalArrayDataHelper@Object@v8@@AEAA?AW4_JsErrorCode@@PEAPEAUExternalArrayData@2@@Z?False@v8@@YA?AV?$Handle@VBoolean@v8@@@1@XZ?FatalException@node@@YAXAEAVTryCatch@v8@@@Z?Fill@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Get@Object@v8@@QEAA?AV?$Local@VValue@v8@@@2@I@Z?Get@Object@v8@@QEAA?AV?$Local@VValue@v8@@@2@V?$Handle@VValue@v8@@@2@@Z?GetAndClearException@TryCatch@v8@@AEAAXXZ?GetConstructor@Object@v8@@QEAA?AV?$Local@VValue@v8@@@2@XZ?GetCurrent@Context@v8@@SA?AV?$Local@VContext@v8@@@2@XZ?GetCurrent@HandleScope@v8@@SAPEAV12@XZ?GetCurrent@Isolate@v8@@SAPEAV12@XZ?GetElementCount@RetainedObjectInfo@v8@@UEAA_JXZ?GetEndColumn@Message@v8@@QEBAHXZ?GetFD@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@V?$Local@VString@v8@@@4@AEBVAccessorInfo@4@@Z?GetFunction@FunctionTemplate@v8@@QEAA?AV?$Local@VFunction@v8@@@2@XZ?GetGroupLabel@RetainedObjectInfo@v8@@UEAAPEBDXZ?GetHandle@HandleWrap@node@@QEAAPEAUuv_handle_s@@XZ?GetHeapEnumerator@V8@v8@@SA_NPEAPEAUIActiveScriptProfilerHeapEnum@@@Z?GetHeapStatistics@V8@v8@@SAXPEAVHeapStatistics@2@@Z?GetHiddenValue@Object@v8@@QEAA?AV?$Local@VValue@v8@@@2@V?$Handle@VString@v8@@@2@@Z?GetIndexedPropertiesExternalArrayData@Object@v8@@QEAAPEAXXZ?GetIndexedPropertiesExternalArrayDataLength@Object@v8@@QEAAHXZ?GetIndexedPropertiesExternalArrayDataType@Object@v8@@QEAA?AW4ExternalArrayType@2@XZ?GetLineNumber@Message@v8@@QEBAHXZ?GetPointerFromInternalField@Object@v8@@QEAAPEAXH@Z?GetPropertyNames@Object@v8@@QEAA?AV?$Local@VArray@v8@@@2@XZ?GetPrototype@Object@v8@@QEAA?AV?$Local@VValue@v8@@@2@XZ?GetScriptResourceName@Message@v8@@QEBA?AV?$Handle@VValue@v8@@@2@XZ?GetSizeInBytes@RetainedObjectInfo@v8@@UEAA_JXZ?GetSourceLine@Message@v8@@QEBA?AV?$Local@VString@v8@@@2@XZ?GetStartColumn@Message@v8@@QEBAHXZ?GetStream@StreamWrap@node@@QEAAPEAUuv_stream_s@@XZ?GetVersion@V8@v8@@SAPEBDXZ?Global@Context@v8@@QEAA?AV?$Local@VObject@v8@@@2@XZ?Has@Object@v8@@QEAA_NV?$Handle@VString@v8@@@2@@Z?HasCaught@TryCatch@v8@@QEAA_NXZ?HasInstance@Buffer@node@@SA_NV?$Handle@VValue@v8@@@v8@@@Z?HasInstance@FunctionTemplate@v8@@QEAA_NV?$Handle@VValue@v8@@@2@@Z?HexSlice@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?HexWrite@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Holder@Arguments@v8@@QEBA?AV?$Local@VObject@v8@@@2@XZ?Initialize@Buffer@node@@SAXV?$Handle@VObject@v8@@@v8@@@Z?Initialize@HandleWrap@node@@SAXV?$Handle@VObject@v8@@@v8@@@Z?Initialize@PipeWrap@node@@SAXV?$Handle@VObject@v8@@@v8@@@Z?Initialize@StreamWrap@node@@SAXV?$Handle@VObject@v8@@@v8@@@Z?Initialize@V8@v8@@SA_NXZ?InitializeCurrentContext@V8@v8@@SA_NXZ?InstanceTemplate@FunctionTemplate@v8@@QEAA?AV?$Local@VObjectTemplate@v8@@@2@XZ?Instantiate@PipeWrap@node@@SA?AV?$Local@VObject@v8@@@v8@@XZ?Int32Value@Value@v8@@QEBAHXZ?IntegerValue@Value@v8@@QEBA_JXZ?InternalFieldCount@Object@v8@@QEAAHXZ?InternalFieldHelper@Object@v8@@AEAA?AW4_JsErrorCode@@PEAPEAPEAXPEAH@Z?InternalStringPtr@String@v8@@QEAAPEBGPEA_K@Z?IsArray@Value@v8@@QEBA_NXZ?IsBoolean@Value@v8@@QEBA_NXZ?IsConstructCall@Arguments@v8@@QEBA_NXZ?IsDate@Value@v8@@QEBA_NXZ?IsDead@V8@v8@@SA_NXZ?IsEmpty@?$Handle@VArray@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VBoolean@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VFunction@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VFunctionTemplate@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VInteger@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VMessage@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VObject@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VObjectTemplate@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VPrimitive@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VScript@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VString@v8@@@v8@@QEBA_NXZ?IsEmpty@?$Handle@VValue@v8@@@v8@@QEBA_NXZ?IsExternal@External@v8@@SA_NPEBVValue@2@@Z?IsExternal@Value@v8@@QEBA_NXZ?IsFalse@Value@v8@@QEBA_NXZ?IsFunction@Value@v8@@QEBA_NXZ?IsInt32@Value@v8@@QEBA_NXZ?IsNearDeath@?$Persistent@VFunctionTemplate@v8@@@v8@@QEBA_NXZ?IsNearDeath@?$Persistent@VObject@v8@@@v8@@QEBA_NXZ?IsNull@Value@v8@@QEBA_NXZ?IsNumber@Value@v8@@QEBA_NXZ?IsObject@Value@v8@@QEBA_NXZ?IsRegExp@Value@v8@@QEBA_NXZ?IsString@Value@v8@@QEBA_NXZ?IsTrue@Value@v8@@QEBA_NXZ?IsUint32@Value@v8@@QEBA_NXZ?IsUndefined@Value@v8@@QEBA_NXZ?IsWeak@?$Persistent@VFunctionTemplate@v8@@@v8@@QEBA_NXZ?IsWeak@?$Persistent@VObject@v8@@@v8@@QEBA_NXZ?Length@Arguments@v8@@QEBAHXZ?Length@Array@v8@@QEBAIXZ?Length@Buffer@node@@SA_KPEAV12@@Z?Length@Buffer@node@@SA_KV?$Handle@VValue@v8@@@v8@@@Z?Length@String@v8@@QEBAHXZ?Listen@PipeWrap@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?LogError@logger@node@@YAXPEBG@Z?LogInfo@logger@node@@YAXPEBG@Z?LogVerbose@logger@node@@YAXPEBG@Z?LogWarn@logger@node@@YAXPEBG@Z?LogfError@logger@node@@YAXPEBGZZ?LogfInfo@logger@node@@YAXPEBGZZ?LogfVerbose@logger@node@@YAXPEBGZZ?LogfWarn@logger@node@@YAXPEBGZZ?MakeCallback@node@@YA?AV?$Handle@VValue@v8@@@v8@@V?$Handle@VObject@v8@@@3@PEBDHQEAV23@@Z?MakeCallback@node@@YA?AV?$Handle@VValue@v8@@@v8@@V?$Handle@VObject@v8@@@3@V?$Handle@VFunction@v8@@@3@HQEAV23@@Z?MakeCallback@node@@YA?AV?$Handle@VValue@v8@@@v8@@V?$Handle@VObject@v8@@@3@V?$Handle@VString@v8@@@3@HQEAV23@@Z?MakeFastBuffer@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?MakeFastBufferObject@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?MakeWeak@?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAXPEAXP6AXV?$Persistent@VValue@v8@@@2@0@Z@Z?MakeWeak@?$Persistent@VObject@v8@@@v8@@QEAAXPEAXP6AXV?$Persistent@VValue@v8@@@2@0@Z@Z?MakeWeak@ObjectWrap@node@@IEAAXXZ?MarkIndependent@?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAXXZ?MarkIndependent@?$Persistent@VObject@v8@@@v8@@QEAAXXZ?MayContainNonAscii@String@v8@@QEBA_NXZ?Message@TryCatch@v8@@QEAA?AV?$Local@VMessage@v8@@@2@XZ?New@?$Local@VArray@v8@@@v8@@SA?AV12@V?$Handle@VArray@v8@@@2@@Z?New@?$Local@VBoolean@v8@@@v8@@SA?AV12@V?$Handle@VBoolean@v8@@@2@@Z?New@?$Local@VContext@v8@@@v8@@SA?AV12@V?$Handle@VContext@v8@@@2@@Z?New@?$Local@VDate@v8@@@v8@@SA?AV12@V?$Handle@VDate@v8@@@2@@Z?New@?$Local@VExternal@v8@@@v8@@SA?AV12@V?$Handle@VExternal@v8@@@2@@Z?New@?$Local@VFunction@v8@@@v8@@SA?AV12@V?$Handle@VFunction@v8@@@2@@Z?New@?$Local@VFunctionTemplate@v8@@@v8@@SA?AV12@V?$Handle@VFunctionTemplate@v8@@@2@@Z?New@?$Local@VInteger@v8@@@v8@@SA?AV12@V?$Handle@VInteger@v8@@@2@@Z?New@?$Local@VNumber@v8@@@v8@@SA?AV12@V?$Handle@VNumber@v8@@@2@@Z?New@?$Local@VObject@v8@@@v8@@SA?AV12@V?$Handle@VObject@v8@@@2@@Z?New@?$Local@VObjectTemplate@v8@@@v8@@SA?AV12@V?$Handle@VObjectTemplate@v8@@@2@@Z?New@?$Local@VScript@v8@@@v8@@SA?AV12@V?$Handle@VScript@v8@@@2@@Z?New@?$Local@VValue@v8@@@v8@@SA?AV12@V?$Handle@VValue@v8@@@2@@Z?New@?$Persistent@VArray@v8@@@v8@@SA?AV12@V?$Handle@VArray@v8@@@2@@Z?New@?$Persistent@VFunction@v8@@@v8@@SA?AV12@V?$Handle@VFunction@v8@@@2@@Z?New@?$Persistent@VFunctionTemplate@v8@@@v8@@SA?AV12@V?$Handle@VFunctionTemplate@v8@@@2@@Z?New@?$Persistent@VObject@v8@@@v8@@SA?AV12@V?$Handle@VObject@v8@@@2@@Z?New@?$Persistent@VObjectTemplate@v8@@@v8@@SA?AV12@V?$Handle@VObjectTemplate@v8@@@2@@Z?New@?$Persistent@VScript@v8@@@v8@@SA?AV12@V?$Handle@VScript@v8@@@2@@Z?New@?$Persistent@VString@v8@@@v8@@SA?AV12@V?$Handle@VString@v8@@@2@@Z?New@Array@v8@@SA?AV?$Local@VArray@v8@@@2@H@Z?New@Boolean@v8@@SA?AV?$Handle@VBoolean@v8@@@2@_N@Z?New@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?New@Buffer@node@@SA?AV?$Handle@VObject@v8@@@v8@@V?$Handle@VString@v8@@@4@@Z?New@Buffer@node@@SAPEAV12@PEAD_KP6AX0PEAX@Z2@Z?New@Buffer@node@@SAPEAV12@PEBD_K@Z?New@Buffer@node@@SAPEAV12@_K@Z?New@Context@v8@@SA?AV?$Persistent@VContext@v8@@@2@XZ?New@Date@v8@@SA?AV?$Local@VValue@v8@@@2@N@Z?New@Date@v8@@SA?AV?$Local@VValue@v8@@@2@XZ?New@External@v8@@SA?AV?$Local@VExternal@v8@@@2@PEAX@Z?New@FunctionTemplate@v8@@SA?AV?$Local@VFunctionTemplate@v8@@@2@P6A?AV?$Handle@VValue@v8@@@2@AEBVArguments@2@@ZV42@V?$Handle@VSignature@v8@@@2@@Z?New@Integer@v8@@SA?AV?$Local@VInteger@v8@@@2@H@Z?New@Number@v8@@SA?AV?$Local@VNumber@v8@@@2@N@Z?New@Object@v8@@SA?AV?$Local@VObject@v8@@@2@XZ?New@ObjectTemplate@v8@@SA?AV?$Local@VObjectTemplate@v8@@@2@XZ?New@PipeWrap@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?New@Script@v8@@SA?AV?$Local@VScript@v8@@@2@P6A_NPEAXPEAPEBG@ZP6AX0@Z0PEBGPEBE@Z?New@Script@v8@@SA?AV?$Local@VScript@v8@@@2@PEBG0@Z?New@Script@v8@@SA?AV?$Local@VScript@v8@@@2@V?$Handle@VString@v8@@@2@V?$Handle@VValue@v8@@@2@@Z?New@Signature@v8@@SA?AV?$Local@VSignature@v8@@@2@V?$Handle@VFunctionTemplate@v8@@@2@@Z?New@String@v8@@SA?AV?$Local@VString@v8@@@2@PEBDH@Z?New@String@v8@@SA?AV?$Local@VString@v8@@@2@PEBGH@Z?NewExternal@String@v8@@SA?AV?$Local@VString@v8@@@2@PEAVExternalAsciiStringResource@12@@Z?NewFromUnsigned@Integer@v8@@SA?AV?$Local@VInteger@v8@@@2@I@Z?NewInstance@Function@v8@@QEBA?AV?$Local@VObject@v8@@@2@HQEAV?$Handle@VValue@v8@@@2@@Z?NewInstance@Function@v8@@QEBA?AV?$Local@VObject@v8@@@2@XZ?NewInstance@ObjectTemplate@v8@@QEAA?AV?$Local@VObject@v8@@@2@V?$Handle@VObject@v8@@@2@@Z?NewInstance@ObjectTemplate@v8@@QEAA?AV?$Local@VObject@v8@@@2@XZ?NewSymbol@String@v8@@SA?AV?$Local@VString@v8@@@2@PEBDH@Z?NewSymbol@String@v8@@SA?AV?$Local@VString@v8@@@2@PEBGH@Z?Null@v8@@YA?AV?$Handle@VPrimitive@v8@@@1@XZ?NumberValue@Value@v8@@QEBANXZ?OnAlloc@StreamWrap@node@@CA?AUuv_buf_t@@PEAUuv_handle_s@@_K@Z?OnClose@HandleWrap@node@@CAXPEAUuv_handle_s@@@Z?OnConnection@PipeWrap@node@@CAXPEAUuv_stream_s@@H@Z?OnRead2@StreamWrap@node@@CAXPEAUuv_pipe_s@@_JUuv_buf_t@@W4uv_handle_type@@@Z?OnRead@StreamWrap@node@@CAXPEAUuv_stream_s@@_JUuv_buf_t@@@Z?OnReadCommon@StreamWrap@node@@CAXPEAUuv_stream_s@@_JUuv_buf_t@@W4uv_handle_type@@@Z?Open@PipeWrap@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ProcessDebugMessages@Debug@v8@@SAXXZ?PrototypeTemplate@FunctionTemplate@v8@@QEAA?AV?$Local@VObjectTemplate@v8@@@2@XZ?RangeError@Exception@v8@@SA?AV?$Local@VValue@v8@@@2@V?$Handle@VString@v8@@@2@@Z?ReThrow@TryCatch@v8@@QEAA?AV?$Handle@VValue@v8@@@2@XZ?ReadDoubleBE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ReadDoubleLE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ReadFloatBE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ReadFloatLE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ReadStart@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ReadStop@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Ref@HandleWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Ref@ObjectWrap@node@@MEAAXXZ?Replace@Buffer@node@@AEAAXPEAD_KP6AX0PEAX@Z2_N@Z?Run@Script@v8@@QEAA?AV?$Local@VValue@v8@@@2@XZ?Set@FunctionTemplate@v8@@QEAAXV?$Handle@VString@v8@@@2@V?$Handle@VData@v8@@@2@W4PropertyAttribute@2@@Z?Set@Object@v8@@QEAA_NIV?$Handle@VValue@v8@@@2@@Z?Set@Object@v8@@QEAA_NV?$Handle@VValue@v8@@@2@0W4PropertyAttribute@2@@Z?Set@ObjectTemplate@v8@@QEAAXV?$Handle@VString@v8@@@2@V?$Handle@VData@v8@@@2@W4PropertyAttribute@2@@Z?SetAccessor@Object@v8@@QEAA_NV?$Handle@VString@v8@@@2@P6A?AV?$Handle@VValue@v8@@@2@V?$Local@VString@v8@@@2@AEBVAccessorInfo@2@@ZP6AX1V?$Local@VValue@v8@@@2@2@ZV42@W4AccessControl@2@W4PropertyAttribute@2@@Z?SetAccessor@ObjectTemplate@v8@@QEAAXV?$Handle@VString@v8@@@2@P6A?AV?$Handle@VValue@v8@@@2@V?$Local@VString@v8@@@2@AEBVAccessorInfo@2@@ZP6AX1V?$Local@VValue@v8@@@2@2@ZV42@W4AccessControl@2@W4PropertyAttribute@2@@Z?SetClassName@FunctionTemplate@v8@@QEAAXV?$Handle@VString@v8@@@2@@Z?SetClassName@ObjectTemplate@v8@@QEAAXV?$Handle@VString@v8@@@2@@Z?SetDebugMessageDispatchHandler@Debug@v8@@SAXP6AXXZ_N@Z?SetErrno@node@@YAXUuv_err_s@@@Z?SetExternalObjectWithFinalizer@v8@@YAXPEAXP6AXV?$Persistent@VValue@v8@@@1@0@Z0@Z?SetFatalErrorHandler@V8@v8@@SAXP6AXPEBD0@Z@Z?SetFlagsFromCommandLine@V8@v8@@SAXPEAHPEAPEAD_N@Z?SetHandle@HandleWrap@node@@MEAAXPEAUuv_handle_s@@@Z?SetHandle@StreamWrap@node@@MEAAXPEAUuv_handle_s@@@Z?SetHiddenValue@Object@v8@@QEAA_NV?$Handle@VString@v8@@@2@V?$Handle@VValue@v8@@@2@@Z?SetIndexedPropertiesToExternalArrayData@Object@v8@@QEAAXPEAXW4ExternalArrayType@2@H@Z?SetIndexedPropertyHandler@ObjectTemplate@v8@@QEAAXP6A?AV?$Handle@VValue@v8@@@2@IAEBVAccessorInfo@2@@ZP6A?AV32@IV?$Local@VValue@v8@@@2@0@ZP6A?AV?$Handle@VInteger@v8@@@2@I0@ZP6A?AV?$Handle@VBoolean@v8@@@2@I0@ZP6A?AV?$Handle@VArray@v8@@@2@0@ZV32@@Z?SetInternalFieldCount@ObjectTemplate@v8@@QEAAXH@Z?SetJitCodeEventHandler@V8@v8@@SAXW4JitCodeEventOptions@2@P6AXPEBVJitCodeEvent@2@@Z@Z?SetNamedPropertyHandler@ObjectTemplate@v8@@QEAAXP6A?AV?$Handle@VValue@v8@@@2@V?$Local@VString@v8@@@2@AEBVAccessorInfo@2@@ZP6A?AV32@0V?$Local@VValue@v8@@@2@1@ZP6A?AV?$Handle@VInteger@v8@@@2@01@ZP6A?AV?$Handle@VBoolean@v8@@@2@01@ZP6A?AV?$Handle@VArray@v8@@@2@1@ZV32@@Z?SetNewRef@?$Persistent@VArray@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VContext@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VFunction@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VFunctionTemplate@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VObject@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VObjectTemplate@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VScript@v8@@@v8@@AEAAXPEAX@Z?SetNewRef@?$Persistent@VString@v8@@@v8@@AEAAXPEAX@Z?SetPendingInstances@PipeWrap@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?SetPointerInInternalField@Object@v8@@QEAAXHPEAX@Z?SetPrototype@Object@v8@@QEAA_NV?$Handle@VValue@v8@@@2@@Z?SetResourceConstraints@v8@@YA_NPEAVResourceConstraints@1@@Z?SetSupportsExternalArray@FunctionTemplate@v8@@QEAAXXZ?SetSupportsExternalArray@ObjectTemplate@v8@@QEAAXXZ?SetSupportsOverrideToString@ObjectTemplate@v8@@QEAAXXZ?SetWrapperClassId@?$Persistent@VFunctionTemplate@v8@@@v8@@QEAAXG@Z?SetWrapperClassId@?$Persistent@VObject@v8@@@v8@@QEAAXG@Z?Shutdown@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?StackTrace@TryCatch@v8@@QEAA?AV?$Local@VValue@v8@@@2@XZ?Start@node@@YAHHQEAPEAD@Z?Start@node@@YAHHQEAPEADPEBDIPEBVILogger@logger@1@PEAPEBD@Z?Start@node@@YAHHQEAPEADPEBVILogger@logger@1@PEAPEBD@Z?StateChange@StreamWrap@node@@IEAAXXZ?Stop@node@@YAXXZ?StrictEquals@Value@v8@@QEBA_NV?$Handle@VValue@v8@@@2@@Z?SupportsExternalArrayData@Object@v8@@AEAA_NXZ?This@AccessorInfo@v8@@QEBA?AV?$Local@VObject@v8@@@2@XZ?This@Arguments@v8@@QEBA?AV?$Local@VObject@v8@@@2@XZ?ThrowException@v8@@YA?AV?$Handle@VValue@v8@@@1@V21@@Z?ToBoolean@Value@v8@@QEBA?AV?$Local@VBoolean@v8@@@2@XZ?ToInt32@Value@v8@@QEBA?AV?$Local@VInt32@v8@@@2@XZ?ToInteger@Value@v8@@QEBA?AV?$Local@VInteger@v8@@@2@XZ?ToNumber@Value@v8@@QEBA?AV?$Local@VNumber@v8@@@2@XZ?ToObject@Value@v8@@QEBA?AV?$Local@VObject@v8@@@2@XZ?ToString@Value@v8@@QEBA?AV?$Local@VString@v8@@@2@XZ?ToUint32@Value@v8@@QEBA?AV?$Local@VUint32@v8@@@2@XZ?True@v8@@YA?AV?$Handle@VBoolean@v8@@@1@XZ?TypeError@Exception@v8@@SA?AV?$Local@VValue@v8@@@2@V?$Handle@VString@v8@@@2@@Z?UVException@node@@YA?AV?$Local@VValue@v8@@@v8@@HPEBD00@Z?UVHandle@PipeWrap@node@@QEAAPEAUuv_pipe_s@@XZ?Ucs2Slice@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Ucs2Write@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Uint32Value@Value@v8@@QEBAIXZ?Undefined@v8@@YA?AV?$Handle@VPrimitive@v8@@@1@XZ?Unref@HandleWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Unref@ObjectWrap@node@@MEAAXXZ?Unwrap@External@v8@@SAPEAXV?$Handle@VValue@v8@@@2@@Z?Unwrap@PipeWrap@node@@SAPEAV12@V?$Local@VObject@v8@@@v8@@@Z?UpdateWriteQueueSize@StreamWrap@node@@IEAAXXZ?Utf8Length@String@v8@@QEBAHXZ?Utf8Slice@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?Utf8Write@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?ValidateByteCache@nativerequire@node@@YAHPEBDI@Z?Value@Boolean@v8@@QEBA_NXZ?Value@External@v8@@QEBAPEAXXZ?Value@Int32@v8@@QEBAHXZ?Value@Integer@v8@@QEBA_JXZ?Value@Number@v8@@QEBANXZ?Value@Uint32@v8@@QEBAIXZ?WeakCallback@ObjectWrap@node@@CAXV?$Persistent@VValue@v8@@@v8@@PEAX@Z?WinapiErrnoException@node@@YA?AV?$Local@VValue@v8@@@v8@@HPEBD00@Z?Wrap@External@v8@@SA?AV?$Local@VValue@v8@@@2@PEAX@Z?Wrap@ObjectWrap@node@@IEAAXV?$Handle@VObject@v8@@@v8@@@Z?Write@String@v8@@QEBAHPEAGHHH@Z?WriteAscii@String@v8@@QEBAHPEADHHH@Z?WriteAsciiString@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteBuffer@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteDoubleBE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteDoubleLE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteFloatBE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteFloatLE@Buffer@node@@CA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteUcs2String@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?WriteUtf8@String@v8@@QEBAHPEADHPEAHH@Z?WriteUtf8String@StreamWrap@node@@SA?AV?$Handle@VValue@v8@@@v8@@AEBVArguments@4@@Z?constructor_template@Buffer@node@@2V?$Persistent@VFunctionTemplate@v8@@@v8@@A?kCloseCallback@HandleWrap@node@@0IB?kMaxLength@Buffer@node@@2IB?kUnref@HandleWrap@node@@0IB?length@AsciiValue@String@v8@@QEBAHXZ?length@Utf8Value@String@v8@@QEBAHXZ?length@Value@String@v8@@QEBAHXZ?no_deprecation@node@@3_NA?set_heap_size@HeapStatistics@v8@@QEAAX_K@Z?set_stack_limit@ResourceConstraints@v8@@QEAAXPEAI@Z?total_heap_size@HeapStatistics@v8@@QEAA_KXZ?used_heap_size@HeapStatistics@v8@@QEAA_KXZnode_buffer_modulenode_cares_wrap_modulenode_evals_modulenode_fs_event_wrap_modulenode_fs_modulenode_http_parser_modulenode_logger_wrap_modulenode_nativerequire_wrap_modulenode_os_modulenode_pipe_wrap_modulenode_process_wrap_modulenode_signal_wrap_modulenode_tcp_wrap_modulenode_timer_wrap_modulenode_tty_wrap_modulenode_udp_wrap_modulenode_zlib_moduleuv_acceptuv_async_inituv_async_senduv_backend_fduv_backend_timeoutuv_barrier_destroyuv_barrier_inituv_barrier_waituv_buf_inituv_canceluv_chdiruv_check_inituv_check_startuv_check_stopuv_closeuv_cond_broadcastuv_cond_destroyuv_cond_inituv_cond_signaluv_cond_timedwaituv_cond_waituv_cpu_infouv_cwduv_default_loopuv_disable_stdio_inheritanceuv_dlcloseuv_dlerroruv_dlopenuv_dlsymuv_err_nameuv_exepathuv_free_cpu_infouv_free_interface_addressesuv_freeaddrinfouv_fs_chmoduv_fs_chownuv_fs_closeuv_fs_event_inituv_fs_fchmoduv_fs_fchownuv_fs_fdatasyncuv_fs_fstatuv_fs_fsyncuv_fs_ftruncateuv_fs_futimeuv_fs_linkuv_fs_lstatuv_fs_mkdiruv_fs_openuv_fs_poll_inituv_fs_poll_startuv_fs_poll_stopuv_fs_readuv_fs_readdiruv_fs_readlinkuv_fs_renameuv_fs_req_cleanupuv_fs_rmdiruv_fs_sendfileuv_fs_statuv_fs_symlinkuv_fs_unlinkuv_fs_utimeuv_fs_writeuv_get_free_memoryuv_get_process_titleuv_get_total_memoryuv_getaddrinfouv_guess_handleuv_handle_sizeuv_hrtimeuv_idle_inituv_idle_startuv_idle_stopuv_inet_ntopuv_inet_ptonuv_interface_addressesuv_ip4_addruv_ip4_nameuv_ip6_addruv_ip6_nameuv_is_activeuv_is_closinguv_is_readableuv_is_writableuv_killuv_last_erroruv_listenuv_loadavguv_loop_deleteuv_loop_newuv_mutex_destroyuv_mutex_inituv_mutex_lockuv_mutex_trylockuv_mutex_unlockuv_nowuv_onceuv_pipe_binduv_pipe_connectuv_pipe_inituv_pipe_openuv_pipe_pending_instancesuv_poll_inituv_poll_init_socketuv_poll_startuv_poll_stopuv_prepare_inituv_prepare_startuv_prepare_stopuv_process_killuv_queue_workuv_read2_startuv_read_startuv_read_stopuv_refuv_req_sizeuv_resident_set_memoryuv_runuv_rwlock_destroyuv_rwlock_inituv_rwlock_rdlockuv_rwlock_rdunlockuv_rwlock_tryrdlockuv_rwlock_trywrlockuv_rwlock_wrlockuv_rwlock_wrunlockuv_sem_destroyuv_sem_inituv_sem_postuv_sem_trywaituv_sem_waituv_set_process_titleuv_setup_argsuv_shutdownuv_signal_inituv_signal_startuv_signal_stopuv_spawnuv_stopuv_strerroruv_strlcatuv_strlcpyuv_tcp_binduv_tcp_bind6uv_tcp_connectuv_tcp_connect6uv_tcp_getpeernameuv_tcp_getsocknameuv_tcp_inituv_tcp_keepaliveuv_tcp_nodelayuv_tcp_openuv_tcp_simultaneous_acceptsuv_thread_createuv_thread_joinuv_thread_selfuv_timer_againuv_timer_get_repeatuv_timer_inituv_timer_set_repeatuv_timer_startuv_timer_stopuv_tty_get_winsizeuv_tty_inituv_tty_reset_modeuv_tty_set_modeuv_udp_binduv_udp_bind6uv_udp_getsocknameuv_udp_inituv_udp_openuv_udp_recv_startuv_udp_recv_stopuv_udp_senduv_udp_send6uv_udp_set_broadcastuv_udp_set_membershipuv_udp_set_multicast_loopuv_udp_set_multicast_ttluv_udp_set_ttluv_unrefuv_update_timeuv_uptimeuv_versionuv_version_stringuv_walkuv_writeuv_write2x\+`+8PY+4b+X+Vb+X8X+zb+Y+b+X+b+hU+b+(Z+g+HS+h+PS+h+`H`+h+T+8y+pY+Xy+0W+zy+U+y+XXV+y+pW+y+0V+z+hY+.z+@Y+Pz+8Z+vz+W+z+X+z+W+z+U+"{+PZ+F{+X+j{+pT+{+W+{+V+{+XW+{+@8V+|+V+>|+V+^|+W+|+XXU+|+xV+|+8xZ+|+8`Z+}+ g+9psh+vh+lh+Vh+Lh+ @h+2h+o"h+h+  m+Hn+pn+bu+u+tu+u+u+q+u+u+p+u+*u+Hu+q+v+u+w+"n+a+a+r+n+0w+Bw+lr+r+r+x+r+r+n+r+r+s+s+2s+q+^s+rs+s+r+r+Ps+s+q+n+q+x+x+dx+f+,f+f+f+e+e+e+e+e+e+e+f+pe+f+Ze+De+0e+e+e+d+d+d+d+c+d+rd+f+g+g+.g+@g+Tg+dg+zg+g+g+g+g+^d+c+Nd+c+m+&m+m+m+l+l+`+l+l+l+l+hl+Zl+Jl+@l+4l+*l+"l+l+ l+k+k+k+k+k+k+vk+lk+^k+@k+$k+ k+k+j+j+j+j+j+j+j+j+j+j+j+}+}+}+tj+}+jj+Xj+Jj+@j+6j+,j+ j+j+j+j+i+i+i+i+i+i+i+i+i+i+xi+pi+`i+Ti+Ji+@i+6i+(i+i+i+i+h+h+h+h+h+h+~~+`+`+a+a+`+`+`+`+`+}+>}+L}+T}+^}+j}+t}+~}+}+}+}+}+~+h+x+w+w+w+pw+Rw+h+U_XcptFilter_amsg_exitLfreemalloc}_inittermW__C_specific_handlermsvcrt.dll_lockA_unlock{__dllonexit_onexit-SleepQueryPerformanceCounter GetCurrentProcessIdGetCurrentThreadIdGetSystemTimeAsFileTimeGetTickCountRtlCaptureContext RtlLookupFunctionEntryRtlVirtualUnwindUnhandledExceptionFilterSetUnhandledExceptionFilter GetCurrentProcessMTerminateProcessapi-ms-win-core-synch-l1-2-0.dllapi-ms-win-core-profile-l1-1-0.dllapi-ms-win-core-processthreads-l1-1-2.dllapi-ms-win-core-sysinfo-l1-2-1.dllapi-ms-win-core-rtlsupport-l1-2-0.dllapi-ms-win-core-errorhandling-l1-1-1.dllRJsIntToNumber7JsGetOwnPropertyDescriptor1JsGetExternalData;JsGetPropertyIdFromNameJsAddRefJsCreateFunctionJsCreateObject_JsReleaseUJsNumberToDoubleJsCreateExternalObject8JsGetOwnPropertyNamesiJsSetIndexedProperty5JsGetIndexedProperty%JsDoubleToNumbernJsSetPrototypeJsCreateArray JsDefinePropertyvJsStringToPointeruJsStrictEquals JsConvertValueToBoolean JsConvertValueToStringIJsGetValueType JsConvertValueToNumber(JsEqualsJsBooleanToBool JsConvertValueToObjectrJsStartDebuggingeJsSetCurrentContext.JsGetCurrentContext3JsGetGlobalObjectJsCreateContext JsConstructObjectNJsHasPropertyEJsGetTrueValue?JsGetPrototypefJsSetException:JsGetPropertyJJsHasException*JsGetAndClearException6JsGetNullValueHJsGetUndefinedValue2JsGetFalseValueZJsParseSerializedScriptXJsParseScriptJsCallFunctionmJsSetProperty"JsDeleteProperty\JsPointerToStringCJsGetStringLength$JsDisposeRuntimeBJsGetRuntimeMemoryUsage'JsEnumerateHeapJsCreateRuntimeJsCreateTypeErrorJsCreateErrorJsCreateRangeErrorMJsHasIndexedProperty`JsRunScript!JsDeleteIndexedPropertyJsBoolToBooleancJsSerializeScriptchakra.dll?GetAdaptersAddressesIPHLPAPI.DLLGetAddrInfoWFreeAddrInfoWWWSASocketW:WSAIoctlHWSARecv&WSADuplicateSocketWMWSASendJWSARecvFromPWSASendToWS2_32.dllRtlAllocateHeapRtlFreeHeapntdll.dll_purecallmodfmemcpy_smemmove_wcsnicmpwcstoul_errnovswprintf_s_wcsrevc_vsnprintfstrncmpstrrchrwcsstr wcsncpy_s2_free_localeabort_beginthreadex%callocstrncpy_s_snwprintf_s_strdupU_get_osfhandle_lseeki64|__doserrno_wmkdir_wrmdir'_fmode<_umaskrealloc_readwcscpy_s_close_write_wchmodswprintf_s_open_osfhandle wcsncmp_aligned_free_wcsdup_aligned_malloc_snprintf_sstrcpy_sstrchrsprintf_swcspbrk_strnicmpwcschrwcsrchrEfprintf2exit??1bad_cast@@UEAA@XZ??0bad_cast@@QEAA@PEBD@Z??0bad_cast@@QEAA@AEBV0@@Zn_vsprintf_pstrpbrk9fflushstrcspn1?what@exception@@UEBAPEBDXZ??1exception@@UEAA@XZ ??0exception@@QEAA@AEBQEBD@Z ??0exception@@QEAA@AEBV0@@Zlocaleconvprintf_stricmp atoistrstrstrerror_itow_sk_vsnwprintf_si_vsnwprintf ??0exception@@QEAA@AEBQEBDH@ZK_CxxThrowException[__CxxFrameHandler3memcpy??8type_info@@QEBAHAEBV0@@Zx__crtLCMapStringAN_get_current_localem___lc_handle_funcsetlocale__uncaught_exception__pctype_funcmisupperk___lc_codepage_funcn___mb_cur_max_func_ismbbleadmemsetiislowerlisspacetolowermemcmpfisdigit/?terminate@@YAXXZ??1type_info@@UEAA@XZ&CoInitializeExMultiByteToWideCharGetLastErrorWideCharToMultiByteCLSIDFromStringGetModuleHandleExWBCoUninitializeGetModuleFileNameWCreateFileWCloseHandleLoadLibraryW FreeLibrary PostQueuedCompletionStatus SetErrorModeGetQueuedCompletionStatusCreateIoCompletionPort3TryEnterCriticalSectionEnterCriticalSection&ReleaseSemaphore4WaitForMultipleObjectsLeaveCriticalSectionInitializeCriticalSection6WaitForSingleObject)SetEvent'ResetEventDeleteCriticalSectionCreateSemaphoreACreateEventAQueueUserWorkItemJProcess32First#RegQueryValueExWSetEnvironmentVariableWRegOpenKeyExW GetConsoleTitleWCreateToolhelp32SnapshotGetTickCount64K32GetProcessMemoryInfoQueryPerformanceFrequencyKProcess32NextGetSystemInfoGetCurrentDirectoryWSetCurrentDirectoryWGlobalMemoryStatusExRegCloseKeySetConsoleTitleWGetConsoleMode/GetFileType GetStartupInfoWSetHandleInformation GetStdHandleDuplicateHandleCreateFileAConnectNamedPipeGetProcAddressLocalFreeFormatMessageALoadLibraryExWCreateDirectoryWGReadFileFindFirstFileW SetLastErrorFindNextFileWYWriteFileDeviceIoControlKRemoveDirectoryWUSetFileTimeCreateHardLinkW FindClose*GetFileAttributesW+GetFileInformationByHandleMoveFileExWFlushFileBuffers7GetLongPathNameW8GetShortPathNameW ReadDirectoryChangesWSetInformationJobObjectNRegisterWaitForSingleObject[UnregisterWaitAssignProcessToJobObjectCreateJobObjectW GetEnvironmentVariableW0OpenProcessUnregisterWaitExCreateProcessWGetExitCodeProcess SetNamedPipeHandleState CreateNamedPipeACreateNamedPipeW PeekNamedPipeLSwitchToThread WaitNamedPipeW SetConsoleCtrlHandlerCancelIo GetConsoleScreenBufferInfoSetConsoleTextAttribute SetConsoleModeReadConsoleAFillConsoleOutputCharacterWReadConsoleInputW WriteConsoleInputWFillConsoleOutputAttribute WriteConsoleWGetNumberOfConsoleInputEventsSetConsoleCursorPositionGetModuleHandleAOpenFileMappingWFreeEnvironmentStringsWUnmapViewOfFileFormatMessageWCreateRemoteThreadCreateFileMappingWMapViewOfFile GetEnvironmentStringsWGetVersionExWOutputDebugStringWCompareStringOrdinalSSetFilePointerLSetEndOfFile~RtlEnumerateGenericTableAvlRtlEnumerateGenericTableWithoutSplayingAvl7RtlInsertElementGenericTableAvlRtlNumberGenericTableElementsAvl-RtlInitializeGenericTableAvlCompareStringExDRtlDeleteElementGenericTableAvlGetModuleFileNameA CreateSemaphoreExWHeapFree#ReleaseMutex7WaitForSingleObjectEx!OpenSemaphoreWHeapAlloc CreateMutexExWGetProcessHeap-GetFileSizeExTraceMessageInitializeCriticalSectionExEncodePointerDecodePointerapi-ms-win-core-com-l1-1-1.dllapi-ms-win-core-string-l1-1-0.dllapi-ms-win-core-libraryloader-l1-2-0.dllapi-ms-win-core-file-l1-2-1.dllapi-ms-win-core-handle-l1-1-0.dllapi-ms-win-core-libraryloader-l1-2-2.dllapi-ms-win-core-io-l1-1-1.dllapi-ms-win-core-synch-l1-2-1.dllapi-ms-win-core-synch-ansi-l1-1-0.dllapi-ms-win-core-threadpool-legacy-l1-1-0.dllapi-ms-win-core-kernel32-legacy-l1-1-5.dllapi-ms-win-core-registry-l1-1-0.dllapi-ms-win-core-processenvironment-l1-2-0.dllapi-ms-win-core-console-l2-1-0.dllapi-ms-win-core-toolhelp-l1-1-0.dllapi-ms-win-core-psapi-l1-1-0.dllapi-ms-win-core-console-l1-1-0.dllapi-ms-win-core-namedpipe-l1-2-0.dllapi-ms-win-core-heap-l2-1-0.dllapi-ms-win-core-localization-l1-2-1.dllapi-ms-win-core-file-l2-1-1.dllapi-ms-win-core-job-l2-1-0.dllapi-ms-win-core-kernel32-legacy-l1-1-1.dllapi-ms-win-core-memory-l1-1-2.dllapi-ms-win-core-debug-l1-1-1.dllapi-ms-win-core-heap-l1-2-0.dllapi-ms-win-eventing-classicprovider-l1-1-0.dllapi-ms-win-core-util-l1-1-0.dll__iob_funcCfopen6fclosestrcat_srand_sstrtol\getenvrand{isxdigit8ferror<fgets_create_localeO_HUGEwcstolsiswdigit_wcstod_lRegOpenKeyExAExpandEnvironmentStringsAGetWindowsDirectoryA"RegQueryValueExA RegEnumKeyExAGetVersionExA/IsProcessorFeaturePresentstrcmpwcscmp++p Ip @- ,H `  .P `v Ж .H P   0  H `    P'(  8 4x  L .?AVbad_alloc@std@@.?AVlogic_error@std@@.?AVlength_error@std@@.?AVout_of_range@std@@.?AV@@.?AV@@.?AV@@.?AV@@.?AV@@.?AVfailure@ios_base@std@@.?AVruntime_error@std@@.?AVbad_cast@@.?AVsystem_error@std@@.?AVexception@@+++)0I))))))()P)h)))Ї))))@)X)))Ȉ)))0)H)`)))))Љ)))) )8)H)h)))))؊)))8)h))))؋)) )0)P)`)x))))P)о) )2-+] f ":|)H3?.`7GRH AdAdAdAddAdAdd Ad Ad":|)H3? )Pp)p)))7)Pu)&)0I)Pi)p)))^P)d2t)@r))>)Pl)y)[T)d)S )` )!!)!!)"1%)8%%@)L(*p)*+)+,),/-)@-. ).0,)0?0)P00)0Q1d)2X2l)22)34) 4i4l)p44l)496x)@66)66)66)67) 7B7)H7 8)8P:)X:;4);[<)p<<)<z=\)==)>t?)??)?Y@)`@w@)@A)A)CL)0CC)C)E)0EF )FH)0HhH)pHH)HHp)HI)IK)K=L)DLQ)R6R<)6RRD)RR\)RRl)R S) SS)SS)ST)TU) UX) XX@)X!Yl)0YE[L)P[d[ )d[[)[[,)[P\@)P\U\X)U\b\h)b\h\x)h\=])P]^8)^_) _U_)U_`)``)``)`` )`GbH)Pbd)de<)e%f)0ff)fg)gi)ij)jJn)PnMo)`oip)ppDsD)Pss)ss)ss)sju()jutu@)tuuP)uhw)pwx)yy@)yy)yy)yz) zz`)z.{`)@{d{)p{{){{){{){&|p)0||)|V})`}~) ~D~)P~t~)~~)~~)~()0Z)`)ف)$L)0)݄)")0R<)RƅD)ƅυ\)υ؅l)A)P)0)8r) )4)p))K)`);)P4):L)@)L) )q)z))Џ)) )Wx)`)')0il)p))ڗ<)`)l|)tؙ);)P ))#l)0X)`) )Мl)ў)p`)ߟ) () H)Pl)ʠl)Рl) @)СH))w) )&L),)Ͱ)),)4)\)d۳8) )F\)L ))\)ĸ)t)N)`кx)غ ) )t))9)@ѽ )1D)@p))$<)<)D)00)I)P) S)`)1`)1(x)0f)ld)pl)))P)) V)\)<)`))f)pB)P)))))))8)@`)@el)e))()(0)@)$)8)H)\) )()0U)U)C)C))X))D))g)p)4l)<)) ) {  ) )  )0 j )p  ) Y)`))M)`P)`))t))0)@{)))T)Td)dk**.*4),* * **)0F$*Fr,*rx@*t*D*D*1*1=*=I*I**(* T*  *  )!'!*'!!*!"*""*""*0"w"D*"#P*#$p*$)%*)%&*&&*&'*'*$* *0*0[1\*p11)11)11)24p*45X*55`*55x*5`D*pDD)DF *FF *FH$ *HH< *HHL *HI) I}I| *II)IJ *JJ *JJ *JK *KK *KK *KL)LL *LM *MN *N0N *0N7N0 *@NNl)NhOX *pOO)OvPh *vPPt *PP *PP *PP *PV *V1W *1WY *YY *YCY *CYGY4 *GYKYD *`YD]d *P]u] *]*)ӌD**k*kt*t}*,*Ѝ6D*`)g`*pP*X*+t*+:*:@*@q*qu*uy*ܤ0*GP*P*)*)C*P_*p/*8U)`)**** *0*@*ٰP**X*XY*`:,*@i@*p),)4IX*Pp*H*ȶ*  (*Pȸ`*и|**)\*dл*) L)T*E$*Ll)*h<*p_T*pi*p_*()<))b)h)l)4)<u*),* >**D*4 *))04*,*) D)Lm)t )))+ )`l)l)$+*#$+*,O$+*)D)h))Cl)L))hl)p)lx*tD*ol)x)l)N)T))[)dl))*)*`)* r*l)*@*)$*T*,J)@* 8*8l))<))|)\x)P)`)&p))<^)&<)0V)`))N)l)@)* *0S*?*Ee*k**Z*Z**V*V****** 5*;}***V)`))d))?)@))')(s)tR`)N ( )( 4 )4 I  )J  $) k L)l  )  )  ) N)NH))x))$)$?)@0)"t)"-)-8)8E)EP)P)T)0)d)  )8)80))A )B)l)Th)T)1)2MP)Nk|)l))7)8h)))).).m)n$)<))" )" e )f 1"@)2"m")n"")"#,)#$P)$$l)$')'')''(0)((:(():(*L)*U*p)V**)**)*+)+,),j,)j,,),,),-)--)-K.4)L.m/`)n//)/0)0P0)b00)01 )12T)22)23),383)83v4)v44)4 5) 5+5),55 )57,)78P)8?9x)@9~9)~99)9<)<n=)n==)=.C).CC()CFP)FG)G(G)(GG)GG)GTHl)THI|)II)JJ)JK$)K+K4)+KRKH)RK^Kp)^KiL)jLM`))`|)!l)0L)`l)й:D*@m))Һ) l)0 * * O)p@)Ǽ)м)_D*p-*@~)þ)о)$)0*̿))WD*`)4/*@W)`$*Pl))) <)Pl))D@)`))")4O)X4* F)Pv)|*T*=*D)`*h *(i)p(*0ol)x0*8*>)D*) N*T)u*|l)')0CH*X)l) Z )`@)l);)Dt)|9<*@\)pl)=@)Dl))0e@)p@)@) X*Xxd *, *4) *t *)Kl)`~)l):)@q)F *`))W)`)))*)0W)`) *0 *M *`s)) !*4$ *8V)\!*T"*\@!*\!*))!)4z)))l%*%*'\$*Tc (*x0| *8.*o$*t'*(O$*p@&*v'*)L#* &*&*F'*p)d)K(*#*7l)@`)t *)d"*"*N )T / T*8  <*  "*  <#*  D#* y (*y  l)* ) P(*5 U (*`  ) +***t**|)* | *$6)*l),*) N)`);T*Df*p)l) $+*|$+*)V)`@) ) )B)P) )  l)  ) T!)`!!)!/")8"#(* #1#)@#W#)`#s#)##)# $) $n$)$$)$F%l)P%%)% &) &L&)`&&)&&)&&)'3')@'p'l)P(k()(())A*d)P**$+** +d)+l+$+*+,,*,f,$+*p,,+*P--$+*-2.+*@..<*.n/,+*//l)/0+*0b2+*p276P+*@66)66+*67l)77+*7e8)p8j;8+*;'<+*0<<t+*<>+*P??)?q@,*x@A,*A$Bl),BB,*BE+*E3F)l)P2*,2*j*p) 1*>)\f*l;(*D)D2*1*,1*D1*2*\1* ) c!l)l!E*1*L*k+.*t+-2*--| *D..2*./2*/22*2d3l)l33l)3 4)044)55X2*562*6U7D*`7p8p2*89D* 99D*9Y;2*`;<D*@<<3* =`=`3*h==$3*=)?h3*0BCL3*C,E43*@EE)EE)E'GX5*3GjG5*pGG)GG)G Hl)HH6*HI4*IJ 5*JqK8*KL) LGL)PLwL)L-M:*-MZMH;*|MM)MM 4*M=Nl)PNNl)N:OD*OO)O~PXD*PP)PP)PQ)Q3Q )*PqrC*rs@@*st@*tiw@*wyP>*yz>*zw{=*{a|C*t|>XC*PW>*lil)pB*=**<=*HHA*:l)@B*ފd)) xE*?*d?*aC*Œ,D*ԗ6* D*̘y<4*5|4*Am4*tD*֚D*ܚ,l)ܛ D*3*3*6D7*lɠ<6*ɠ6*b<*h<*ȡ)')0Y)`Ѣ)PD*@)@)0O)`d9* Υd9*|9*;|9*P9*d9*nd9*P8*<*P<*@) )8\@)d:*)<@)D7*$T* -*:* ':*0S)Fl)L^P8*j8*н@)ؽ@)L)ȾD*PT*T*k0G*i H*cG*iE*lF*H*"0F*L))9)@)I*)) 7)@S I*h))P`)`I* DI*0G)Pg)p)>L*JxL*)N0J*ZJ*J*xJ*kdK*(K*J*0<*I*K*J*)z)l))*)DL*))0]L*p)L*)L*L*L*L*lN*O*(|O*dN*x @O*| M*  LN* gM*| N*hLM*| M*JL*PL* L*lL*)))) 7)@W)`cO*eO*)) P* !4P*!f"pP*"")"")"")"")##P*#4$Q*P$g$)p$$)$$)$$)$$)$%)%'%)`%&LQ* &&LQ*&;'@S*P''l)(=(l)`((l))C)l)P))))**)0*+Q*+,R* -Y.`Q*.=1S*P11T*13tR* 33xS*4R58R*p5j6Q*6l7R*77)7d8V*x849LV*H9:U*:=T*=>DU*,>A,}* >>|*?-?)@?]?)p?@~*@,B}*`BpC8~*CDt~*DE~*E@F؀*`FxG*GG)HHx*HIȁ*IZKH*lKLD*LU*UIW*`WWl)XY *YtY)Y[8*[\D* ]^* ^`Ԃ*`!b*dbLdd*Tdd)eel)egfl)pff(*fg*gh* imh*mYq*qw\*w{*{؆**Ćl*Q@)`@)@) q@)ш@)1@)8rd)xd)@*Tp*ߊl)N,*p؇*@q*)Ў׏D*)Ԉ*i*p)P*4*-l*45 *<z+* )@))Fl)Lzl)l))) Ol)`Ȟ*О)< )P)ס*9x*P-*ĉ*R)X`)*ۦ)Z *`d),**$+*$+*!$+*(Y$+*`))1*8߬*yT*)=<*D*F)LM*T$+*)ıT*$)0l)tMԊ*T)P*<*hl)p*(*¹ *ȹ)}*Ժ$+*)$+*0v)|t)˽\*\Ӿ*ܾet*ll)&),~<*) )l)Bl)Pl){$+*)*R)`)X*`d)*,*T*)>*D$*,T*0*@vċ*|'؋*03D*<l**)X)`*-*4*n@)@)))@*`*T(*\x*fP*lW(*`*̌**9)@**@*^4*dK*T<*2*8Y*`)*S)\d*0d*8t *|*)d*0* (*`  * 6 *<  \* )f*lЍ*\(*d"T*(* h*2D*8|*"*(,*$T*d)&!*,!!(*!$&*,&&)&8'T*@'1(*8([+*d+.Ў*./$*/0*00@)01*13 *3x4<*45<*57L*7.9*49=d*>>)>b?|*h?G@*P@JA*PAQB*BY*[?\)P\\)\])`]])]!^)(^_* __)@``)`pc؏*xcc)cTd*\d