PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/usr/include/nodejs/src/
Upload File :
Current File : //usr/include/nodejs/src/env.h
// Copyright Joyent, Inc. and other Node contributors.
//
// 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.

#ifndef SRC_ENV_H_
#define SRC_ENV_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "aliased_buffer.h"
#if HAVE_INSPECTOR
#include "inspector_agent.h"
#include "inspector_profiler.h"
#endif
#include "callback_queue.h"
#include "debug_utils.h"
#include "handle_wrap.h"
#include "node.h"
#include "node_binding.h"
#include "node_http2_state.h"
#include "node_main_instance.h"
#include "node_options.h"
#include "req_wrap.h"
#include "util.h"
#include "uv.h"
#include "v8.h"

#include <array>
#include <atomic>
#include <cstdint>
#include <functional>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <vector>

struct nghttp2_rcbuf;

namespace node {

namespace contextify {
class ContextifyScript;
class CompiledFnEntry;
}

namespace fs {
class FileHandleReadWrap;
}

namespace performance {
class PerformanceState;
}

namespace tracing {
class AgentWriterHandle;
}

#if HAVE_INSPECTOR
namespace profiler {
class V8CoverageConnection;
class V8CpuProfilerConnection;
class V8HeapProfilerConnection;
}  // namespace profiler

namespace inspector {
class ParentInspectorHandle;
}
#endif  // HAVE_INSPECTOR

namespace worker {
class Worker;
}

namespace loader {
class ModuleWrap;

struct PackageConfig {
  enum class Exists { Yes, No };
  enum class IsValid { Yes, No };
  enum class HasMain { Yes, No };
  enum class HasName { Yes, No };
  enum PackageType : uint32_t { None = 0, CommonJS, Module };

  const Exists exists;
  const IsValid is_valid;
  const HasMain has_main;
  const std::string main;
  const HasName has_name;
  const std::string name;
  const PackageType type;

  v8::Global<v8::Value> exports;
};
}  // namespace loader

enum class FsStatsOffset {
  kDev = 0,
  kMode,
  kNlink,
  kUid,
  kGid,
  kRdev,
  kBlkSize,
  kIno,
  kSize,
  kBlocks,
  kATimeSec,
  kATimeNsec,
  kMTimeSec,
  kMTimeNsec,
  kCTimeSec,
  kCTimeNsec,
  kBirthTimeSec,
  kBirthTimeNsec,
  kFsStatsFieldsNumber
};

// Stat fields buffers contain twice the number of entries in an uv_stat_t
// because `fs.StatWatcher` needs room to store 2 `fs.Stats` instances.
constexpr size_t kFsStatsBufferLength =
    static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber) * 2;

// PER_ISOLATE_* macros: We have a lot of per-isolate properties
// and adding and maintaining their getters and setters by hand would be
// difficult so let's make the preprocessor generate them for us.
//
// In each macro, `V` is expected to be the name of a macro or function which
// accepts the number of arguments provided in each tuple in the macro body,
// typically two. The named function will be invoked against each tuple.
//
// Make sure that any macro V defined for use with the PER_ISOLATE_* macros is
// undefined again after use.

// Private symbols are per-isolate primitives but Environment proxies them
// for the sake of convenience.  Strings should be ASCII-only and have a
// "node:" prefix to avoid name clashes with third-party code.
#define PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)                              \
  V(alpn_buffer_private_symbol, "node:alpnBuffer")                            \
  V(arrow_message_private_symbol, "node:arrowMessage")                        \
  V(contextify_context_private_symbol, "node:contextify:context")             \
  V(contextify_global_private_symbol, "node:contextify:global")               \
  V(decorated_private_symbol, "node:decorated")                               \
  V(napi_type_tag, "node:napi:type_tag")                                      \
  V(napi_wrapper, "node:napi:wrapper")                                        \
  V(sab_lifetimepartner_symbol, "node:sharedArrayBufferLifetimePartner")      \
  V(untransferable_object_private_symbol, "node:untransferableObject")        \

// Symbols are per-isolate primitives but Environment proxies them
// for the sake of convenience.
#define PER_ISOLATE_SYMBOL_PROPERTIES(V)                                       \
  V(handle_onclose_symbol, "handle_onclose")                                   \
  V(no_message_symbol, "no_message_symbol")                                    \
  V(messaging_deserialize_symbol, "messaging_deserialize_symbol")              \
  V(messaging_transfer_symbol, "messaging_transfer_symbol")                    \
  V(messaging_clone_symbol, "messaging_clone_symbol")                          \
  V(messaging_transfer_list_symbol, "messaging_transfer_list_symbol")          \
  V(oninit_symbol, "oninit")                                                   \
  V(owner_symbol, "owner_symbol")                                              \
  V(onpskexchange_symbol, "onpskexchange")                                     \
  V(resource_symbol, "resource_symbol")                                        \
  V(trigger_async_id_symbol, "trigger_async_id_symbol")                        \

// Strings are per-isolate primitives but Environment proxies them
// for the sake of convenience.  Strings should be ASCII-only.
#define PER_ISOLATE_STRING_PROPERTIES(V)                                       \
  V(address_string, "address")                                                 \
  V(aliases_string, "aliases")                                                 \
  V(args_string, "args")                                                       \
  V(asn1curve_string, "asn1Curve")                                             \
  V(async_ids_stack_string, "async_ids_stack")                                 \
  V(bits_string, "bits")                                                       \
  V(buffer_string, "buffer")                                                   \
  V(bytes_parsed_string, "bytesParsed")                                        \
  V(bytes_read_string, "bytesRead")                                            \
  V(bytes_written_string, "bytesWritten")                                      \
  V(cached_data_produced_string, "cachedDataProduced")                         \
  V(cached_data_rejected_string, "cachedDataRejected")                         \
  V(cached_data_string, "cachedData")                                          \
  V(cache_key_string, "cacheKey")                                              \
  V(change_string, "change")                                                   \
  V(channel_string, "channel")                                                 \
  V(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite")           \
  V(clone_unsupported_type_str, "Cannot transfer object of unsupported type.") \
  V(code_string, "code")                                                       \
  V(commonjs_string, "commonjs")                                               \
  V(config_string, "config")                                                   \
  V(constants_string, "constants")                                             \
  V(crypto_dh_string, "dh")                                                    \
  V(crypto_dsa_string, "dsa")                                                  \
  V(crypto_ec_string, "ec")                                                    \
  V(crypto_ed25519_string, "ed25519")                                          \
  V(crypto_ed448_string, "ed448")                                              \
  V(crypto_x25519_string, "x25519")                                            \
  V(crypto_x448_string, "x448")                                                \
  V(crypto_rsa_string, "rsa")                                                  \
  V(crypto_rsa_pss_string, "rsa-pss")                                          \
  V(cwd_string, "cwd")                                                         \
  V(data_string, "data")                                                       \
  V(deserialize_info_string, "deserializeInfo")                                \
  V(dest_string, "dest")                                                       \
  V(destroyed_string, "destroyed")                                             \
  V(detached_string, "detached")                                               \
  V(dh_string, "DH")                                                           \
  V(dns_a_string, "A")                                                         \
  V(dns_aaaa_string, "AAAA")                                                   \
  V(dns_cname_string, "CNAME")                                                 \
  V(dns_mx_string, "MX")                                                       \
  V(dns_naptr_string, "NAPTR")                                                 \
  V(dns_ns_string, "NS")                                                       \
  V(dns_ptr_string, "PTR")                                                     \
  V(dns_soa_string, "SOA")                                                     \
  V(dns_srv_string, "SRV")                                                     \
  V(dns_txt_string, "TXT")                                                     \
  V(done_string, "done")                                                       \
  V(duration_string, "duration")                                               \
  V(ecdh_string, "ECDH")                                                       \
  V(emit_string, "emit")                                                       \
  V(emit_warning_string, "emitWarning")                                        \
  V(empty_object_string, "{}")                                                 \
  V(encoding_string, "encoding")                                               \
  V(entries_string, "entries")                                                 \
  V(entry_type_string, "entryType")                                            \
  V(env_pairs_string, "envPairs")                                              \
  V(env_var_settings_string, "envVarSettings")                                 \
  V(errno_string, "errno")                                                     \
  V(error_string, "error")                                                     \
  V(exchange_string, "exchange")                                               \
  V(exit_code_string, "exitCode")                                              \
  V(expire_string, "expire")                                                   \
  V(exponent_string, "exponent")                                               \
  V(exports_string, "exports")                                                 \
  V(ext_key_usage_string, "ext_key_usage")                                     \
  V(external_stream_string, "_externalStream")                                 \
  V(family_string, "family")                                                   \
  V(fatal_exception_string, "_fatalException")                                 \
  V(fd_string, "fd")                                                           \
  V(fields_string, "fields")                                                   \
  V(file_string, "file")                                                       \
  V(filename_string, "filename")                                               \
  V(fingerprint256_string, "fingerprint256")                                   \
  V(fingerprint_string, "fingerprint")                                         \
  V(flags_string, "flags")                                                     \
  V(fragment_string, "fragment")                                               \
  V(function_string, "function")                                               \
  V(get_data_clone_error_string, "_getDataCloneError")                         \
  V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId")              \
  V(gid_string, "gid")                                                         \
  V(h2_string, "h2")                                                           \
  V(handle_string, "handle")                                                   \
  V(help_text_string, "helpText")                                              \
  V(homedir_string, "homedir")                                                 \
  V(host_string, "host")                                                       \
  V(hostmaster_string, "hostmaster")                                           \
  V(http_1_1_string, "http/1.1")                                               \
  V(identity_string, "identity")                                               \
  V(ignore_string, "ignore")                                                   \
  V(infoaccess_string, "infoAccess")                                           \
  V(inherit_string, "inherit")                                                 \
  V(input_string, "input")                                                     \
  V(internal_binding_string, "internalBinding")                                \
  V(internal_string, "internal")                                               \
  V(ipv4_string, "IPv4")                                                       \
  V(ipv6_string, "IPv6")                                                       \
  V(isclosing_string, "isClosing")                                             \
  V(issuer_string, "issuer")                                                   \
  V(issuercert_string, "issuerCertificate")                                    \
  V(kill_signal_string, "killSignal")                                          \
  V(kind_string, "kind")                                                       \
  V(length_string, "length")                                                   \
  V(library_string, "library")                                                 \
  V(mac_string, "mac")                                                         \
  V(max_buffer_string, "maxBuffer")                                            \
  V(message_port_constructor_string, "MessagePort")                            \
  V(message_port_string, "messagePort")                                        \
  V(message_string, "message")                                                 \
  V(messageerror_string, "messageerror")                                       \
  V(minttl_string, "minttl")                                                   \
  V(module_string, "module")                                                   \
  V(modulus_string, "modulus")                                                 \
  V(name_string, "name")                                                       \
  V(netmask_string, "netmask")                                                 \
  V(next_string, "next")                                                       \
  V(nistcurve_string, "nistCurve")                                             \
  V(node_string, "node")                                                       \
  V(nsname_string, "nsname")                                                   \
  V(ocsp_request_string, "OCSPRequest")                                        \
  V(oncertcb_string, "oncertcb")                                               \
  V(onchange_string, "onchange")                                               \
  V(onclienthello_string, "onclienthello")                                     \
  V(oncomplete_string, "oncomplete")                                           \
  V(onconnection_string, "onconnection")                                       \
  V(ondone_string, "ondone")                                                   \
  V(onerror_string, "onerror")                                                 \
  V(onexit_string, "onexit")                                                   \
  V(onhandshakedone_string, "onhandshakedone")                                 \
  V(onhandshakestart_string, "onhandshakestart")                               \
  V(onkeylog_string, "onkeylog")                                               \
  V(onmessage_string, "onmessage")                                             \
  V(onnewsession_string, "onnewsession")                                       \
  V(onocspresponse_string, "onocspresponse")                                   \
  V(onreadstart_string, "onreadstart")                                         \
  V(onreadstop_string, "onreadstop")                                           \
  V(onshutdown_string, "onshutdown")                                           \
  V(onsignal_string, "onsignal")                                               \
  V(onunpipe_string, "onunpipe")                                               \
  V(onwrite_string, "onwrite")                                                 \
  V(openssl_error_stack, "opensslErrorStack")                                  \
  V(options_string, "options")                                                 \
  V(order_string, "order")                                                     \
  V(output_string, "output")                                                   \
  V(parse_error_string, "Parse Error")                                         \
  V(password_string, "password")                                               \
  V(path_string, "path")                                                       \
  V(pending_handle_string, "pendingHandle")                                    \
  V(pid_string, "pid")                                                         \
  V(pipe_source_string, "pipeSource")                                          \
  V(pipe_string, "pipe")                                                       \
  V(pipe_target_string, "pipeTarget")                                          \
  V(port1_string, "port1")                                                     \
  V(port2_string, "port2")                                                     \
  V(port_string, "port")                                                       \
  V(preference_string, "preference")                                           \
  V(primordials_string, "primordials")                                         \
  V(priority_string, "priority")                                               \
  V(process_string, "process")                                                 \
  V(promise_string, "promise")                                                 \
  V(psk_string, "psk")                                                         \
  V(pubkey_string, "pubkey")                                                   \
  V(query_string, "query")                                                     \
  V(raw_string, "raw")                                                         \
  V(read_host_object_string, "_readHostObject")                                \
  V(readable_string, "readable")                                               \
  V(reason_string, "reason")                                                   \
  V(refresh_string, "refresh")                                                 \
  V(regexp_string, "regexp")                                                   \
  V(rename_string, "rename")                                                   \
  V(replacement_string, "replacement")                                         \
  V(require_string, "require")                                                 \
  V(retry_string, "retry")                                                     \
  V(scheme_string, "scheme")                                                   \
  V(scopeid_string, "scopeid")                                                 \
  V(serial_number_string, "serialNumber")                                      \
  V(serial_string, "serial")                                                   \
  V(servername_string, "servername")                                           \
  V(service_string, "service")                                                 \
  V(session_id_string, "sessionId")                                            \
  V(shell_string, "shell")                                                     \
  V(signal_string, "signal")                                                   \
  V(sink_string, "sink")                                                       \
  V(size_string, "size")                                                       \
  V(sni_context_err_string, "Invalid SNI context")                             \
  V(sni_context_string, "sni_context")                                         \
  V(source_string, "source")                                                   \
  V(stack_string, "stack")                                                     \
  V(standard_name_string, "standardName")                                      \
  V(start_time_string, "startTime")                                            \
  V(status_string, "status")                                                   \
  V(stdio_string, "stdio")                                                     \
  V(subject_string, "subject")                                                 \
  V(subjectaltname_string, "subjectaltname")                                   \
  V(syscall_string, "syscall")                                                 \
  V(target_string, "target")                                                   \
  V(thread_id_string, "threadId")                                              \
  V(ticketkeycallback_string, "onticketkeycallback")                           \
  V(timeout_string, "timeout")                                                 \
  V(tls_ticket_string, "tlsTicket")                                            \
  V(transfer_string, "transfer")                                               \
  V(ttl_string, "ttl")                                                         \
  V(type_string, "type")                                                       \
  V(uid_string, "uid")                                                         \
  V(unknown_string, "<unknown>")                                               \
  V(url_special_ftp_string, "ftp:")                                            \
  V(url_special_file_string, "file:")                                          \
  V(url_special_gopher_string, "gopher:")                                      \
  V(url_special_http_string, "http:")                                          \
  V(url_special_https_string, "https:")                                        \
  V(url_special_ws_string, "ws:")                                              \
  V(url_special_wss_string, "wss:")                                            \
  V(url_string, "url")                                                         \
  V(username_string, "username")                                               \
  V(valid_from_string, "valid_from")                                           \
  V(valid_to_string, "valid_to")                                               \
  V(value_string, "value")                                                     \
  V(verify_error_string, "verifyError")                                        \
  V(version_string, "version")                                                 \
  V(weight_string, "weight")                                                   \
  V(windows_hide_string, "windowsHide")                                        \
  V(windows_verbatim_arguments_string, "windowsVerbatimArguments")             \
  V(wrap_string, "wrap")                                                       \
  V(writable_string, "writable")                                               \
  V(write_host_object_string, "_writeHostObject")                              \
  V(write_queue_size_string, "writeQueueSize")                                 \
  V(x_forwarded_string, "x-forwarded-for")                                     \
  V(zero_return_string, "ZERO_RETURN")

#define ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)                             \
  V(as_callback_data_template, v8::FunctionTemplate)                           \
  V(async_wrap_ctor_template, v8::FunctionTemplate)                            \
  V(async_wrap_object_ctor_template, v8::FunctionTemplate)                     \
  V(base_object_ctor_template, v8::FunctionTemplate)                           \
  V(compiled_fn_entry_template, v8::ObjectTemplate)                            \
  V(dir_instance_template, v8::ObjectTemplate)                                 \
  V(fd_constructor_template, v8::ObjectTemplate)                               \
  V(fdclose_constructor_template, v8::ObjectTemplate)                          \
  V(filehandlereadwrap_template, v8::ObjectTemplate)                           \
  V(fsreqpromise_constructor_template, v8::ObjectTemplate)                     \
  V(handle_wrap_ctor_template, v8::FunctionTemplate)                           \
  V(histogram_instance_template, v8::ObjectTemplate)                           \
  V(http2settings_constructor_template, v8::ObjectTemplate)                    \
  V(http2stream_constructor_template, v8::ObjectTemplate)                      \
  V(http2ping_constructor_template, v8::ObjectTemplate)                        \
  V(i18n_converter_template, v8::ObjectTemplate)                               \
  V(libuv_stream_wrap_ctor_template, v8::FunctionTemplate)                     \
  V(message_port_constructor_template, v8::FunctionTemplate)                   \
  V(pipe_constructor_template, v8::FunctionTemplate)                           \
  V(promise_wrap_template, v8::ObjectTemplate)                                 \
  V(sab_lifetimepartner_constructor_template, v8::FunctionTemplate)            \
  V(script_context_constructor_template, v8::FunctionTemplate)                 \
  V(secure_context_constructor_template, v8::FunctionTemplate)                 \
  V(shutdown_wrap_template, v8::ObjectTemplate)                                \
  V(streambaseoutputstream_constructor_template, v8::ObjectTemplate)           \
  V(tcp_constructor_template, v8::FunctionTemplate)                            \
  V(tty_constructor_template, v8::FunctionTemplate)                            \
  V(write_wrap_template, v8::ObjectTemplate)                                   \
  V(worker_heap_snapshot_taker_template, v8::ObjectTemplate)

#define ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)                                \
  V(as_callback_data, v8::Object)                                              \
  V(async_hooks_after_function, v8::Function)                                  \
  V(async_hooks_before_function, v8::Function)                                 \
  V(async_hooks_callback_trampoline, v8::Function)                             \
  V(async_hooks_binding, v8::Object)                                           \
  V(async_hooks_destroy_function, v8::Function)                                \
  V(async_hooks_init_function, v8::Function)                                   \
  V(async_hooks_promise_resolve_function, v8::Function)                        \
  V(buffer_prototype_object, v8::Object)                                       \
  V(crypto_key_object_constructor, v8::Function)                               \
  V(crypto_key_object_handle_constructor, v8::Function)                        \
  V(crypto_key_object_private_constructor, v8::Function)                       \
  V(crypto_key_object_public_constructor, v8::Function)                        \
  V(crypto_key_object_secret_constructor, v8::Function)                        \
  V(domexception_function, v8::Function)                                       \
  V(enhance_fatal_stack_after_inspector, v8::Function)                         \
  V(enhance_fatal_stack_before_inspector, v8::Function)                        \
  V(fs_use_promises_symbol, v8::Symbol)                                        \
  V(host_import_module_dynamically_callback, v8::Function)                     \
  V(host_initialize_import_meta_object_callback, v8::Function)                 \
  V(http2session_on_altsvc_function, v8::Function)                             \
  V(http2session_on_error_function, v8::Function)                              \
  V(http2session_on_frame_error_function, v8::Function)                        \
  V(http2session_on_goaway_data_function, v8::Function)                        \
  V(http2session_on_headers_function, v8::Function)                            \
  V(http2session_on_origin_function, v8::Function)                             \
  V(http2session_on_ping_function, v8::Function)                               \
  V(http2session_on_priority_function, v8::Function)                           \
  V(http2session_on_select_padding_function, v8::Function)                     \
  V(http2session_on_settings_function, v8::Function)                           \
  V(http2session_on_stream_close_function, v8::Function)                       \
  V(http2session_on_stream_trailers_function, v8::Function)                    \
  V(internal_binding_loader, v8::Function)                                     \
  V(immediate_callback_function, v8::Function)                                 \
  V(inspector_console_extension_installer, v8::Function)                       \
  V(messaging_deserialize_create_object, v8::Function)                         \
  V(message_port, v8::Object)                                                  \
  V(native_module_require, v8::Function)                                       \
  V(performance_entry_callback, v8::Function)                                  \
  V(performance_entry_template, v8::Function)                                  \
  V(prepare_stack_trace_callback, v8::Function)                                \
  V(process_object, v8::Object)                                                \
  V(primordials, v8::Object)                                                   \
  V(promise_reject_callback, v8::Function)                                     \
  V(script_data_constructor_function, v8::Function)                            \
  V(source_map_cache_getter, v8::Function)                                     \
  V(tick_callback_function, v8::Function)                                      \
  V(timers_callback_function, v8::Function)                                    \
  V(tls_wrap_constructor_function, v8::Function)                               \
  V(trace_category_state_function, v8::Function)                               \
  V(udp_constructor_function, v8::Function)                                    \
  V(url_constructor_function, v8::Function)

class Environment;

class IsolateData : public MemoryRetainer {
 public:
  IsolateData(v8::Isolate* isolate,
              uv_loop_t* event_loop,
              MultiIsolatePlatform* platform = nullptr,
              ArrayBufferAllocator* node_allocator = nullptr,
              const std::vector<size_t>* indexes = nullptr);
  SET_MEMORY_INFO_NAME(IsolateData)
  SET_SELF_SIZE(IsolateData)
  void MemoryInfo(MemoryTracker* tracker) const override;
  std::vector<size_t> Serialize(v8::SnapshotCreator* creator);

  inline uv_loop_t* event_loop() const;
  inline MultiIsolatePlatform* platform() const;
  inline std::shared_ptr<PerIsolateOptions> options();
  inline void set_options(std::shared_ptr<PerIsolateOptions> options);

  inline bool uses_node_allocator() const;
  inline v8::ArrayBuffer::Allocator* allocator() const;
  inline NodeArrayBufferAllocator* node_allocator() const;

  inline worker::Worker* worker_context() const;
  inline void set_worker_context(worker::Worker* context);

#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
#define V(TypeName, PropertyName)                                             \
  inline v8::Local<TypeName> PropertyName() const;
  PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
  PER_ISOLATE_SYMBOL_PROPERTIES(VY)
  PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VY
#undef VS
#undef VP
  inline v8::Local<v8::String> async_wrap_provider(int index) const;

  std::unordered_map<nghttp2_rcbuf*, v8::Eternal<v8::String>> http2_static_strs;
  inline v8::Isolate* isolate() const;
  IsolateData(const IsolateData&) = delete;
  IsolateData& operator=(const IsolateData&) = delete;
  IsolateData(IsolateData&&) = delete;
  IsolateData& operator=(IsolateData&&) = delete;

 private:
  void DeserializeProperties(const std::vector<size_t>* indexes);
  void CreateProperties();

#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
#define V(TypeName, PropertyName)                                             \
  v8::Eternal<TypeName> PropertyName ## _;
  PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
  PER_ISOLATE_SYMBOL_PROPERTIES(VY)
  PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VY
#undef VS
#undef VP
  // Keep a list of all Persistent strings used for AsyncWrap Provider types.
  std::array<v8::Eternal<v8::String>, AsyncWrap::PROVIDERS_LENGTH>
      async_wrap_providers_;

  v8::Isolate* const isolate_;
  uv_loop_t* const event_loop_;
  v8::ArrayBuffer::Allocator* const allocator_;
  NodeArrayBufferAllocator* const node_allocator_;
  const bool uses_node_allocator_;
  MultiIsolatePlatform* platform_;
  std::shared_ptr<PerIsolateOptions> options_;
  worker::Worker* worker_context_ = nullptr;
};

struct ContextInfo {
  explicit ContextInfo(const std::string& name) : name(name) {}
  const std::string name;
  std::string origin;
  bool is_default = false;
};

class EnabledDebugList;

// A unique-pointer-ish object that is compatible with the JS engine's
// ArrayBuffer::Allocator.
struct AllocatedBuffer {
 public:
  explicit inline AllocatedBuffer(Environment* env = nullptr);
  inline AllocatedBuffer(Environment* env, uv_buf_t buf);
  inline ~AllocatedBuffer();
  inline void Resize(size_t len);

  inline uv_buf_t release();
  inline char* data();
  inline const char* data() const;
  inline size_t size() const;
  inline void clear();

  inline v8::MaybeLocal<v8::Object> ToBuffer();
  inline v8::Local<v8::ArrayBuffer> ToArrayBuffer();

  inline AllocatedBuffer(AllocatedBuffer&& other);
  inline AllocatedBuffer& operator=(AllocatedBuffer&& other);
  AllocatedBuffer(const AllocatedBuffer& other) = delete;
  AllocatedBuffer& operator=(const AllocatedBuffer& other) = delete;

 private:
  Environment* env_;
  // We do not pass this to libuv directly, but uv_buf_t is a convenient way
  // to represent a chunk of memory, and plays nicely with other parts of core.
  uv_buf_t buffer_;

  friend class Environment;
};

class KVStore {
 public:
  KVStore() = default;
  virtual ~KVStore() = default;
  KVStore(const KVStore&) = delete;
  KVStore& operator=(const KVStore&) = delete;
  KVStore(KVStore&&) = delete;
  KVStore& operator=(KVStore&&) = delete;

  virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate,
                                         v8::Local<v8::String> key) const = 0;
  virtual v8::Maybe<std::string> Get(const char* key) const = 0;
  virtual void Set(v8::Isolate* isolate,
                   v8::Local<v8::String> key,
                   v8::Local<v8::String> value) = 0;
  virtual int32_t Query(v8::Isolate* isolate,
                        v8::Local<v8::String> key) const = 0;
  virtual int32_t Query(const char* key) const = 0;
  virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0;
  virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;

  virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const;
  virtual v8::Maybe<bool> AssignFromObject(v8::Local<v8::Context> context,
                                           v8::Local<v8::Object> entries);

  static std::shared_ptr<KVStore> CreateMapKVStore();
};

namespace per_process {
extern std::shared_ptr<KVStore> system_environment;
}

class AsyncHooks : public MemoryRetainer {
 public:
  SET_MEMORY_INFO_NAME(AsyncHooks)
  SET_SELF_SIZE(AsyncHooks)
  void MemoryInfo(MemoryTracker* tracker) const override;

  // Reason for both UidFields and Fields are that one is stored as a double*
  // and the other as a uint32_t*.
  enum Fields {
    kInit,
    kBefore,
    kAfter,
    kDestroy,
    kPromiseResolve,
    kTotals,
    kCheck,
    kStackLength,
    kUsesExecutionAsyncResource,
    kFieldsCount,
  };

  enum UidFields {
    kExecutionAsyncId,
    kTriggerAsyncId,
    kAsyncIdCounter,
    kDefaultTriggerAsyncId,
    kUidFieldsCount,
  };

  inline AliasedUint32Array& fields();
  inline AliasedFloat64Array& async_id_fields();
  inline AliasedFloat64Array& async_ids_stack();
  inline v8::Local<v8::Array> js_execution_async_resources();
  // Returns the native executionAsyncResource value at stack index `index`.
  // Resources provided on the JS side are not stored on the native stack,
  // in which case an empty `Local<>` is returned.
  // The `js_execution_async_resources` array contains the value in that case.
  inline v8::Local<v8::Object> native_execution_async_resource(size_t index);

  inline v8::Local<v8::String> provider_string(int idx);

  inline void no_force_checks();
  inline Environment* env();

  inline void push_async_context(double async_id, double trigger_async_id,
      v8::Local<v8::Object> execution_async_resource_);
  inline bool pop_async_context(double async_id);
  inline void clear_async_id_stack();  // Used in fatal exceptions.

  AsyncHooks(const AsyncHooks&) = delete;
  AsyncHooks& operator=(const AsyncHooks&) = delete;
  AsyncHooks(AsyncHooks&&) = delete;
  AsyncHooks& operator=(AsyncHooks&&) = delete;
  ~AsyncHooks() = default;

  // Used to set the kDefaultTriggerAsyncId in a scope. This is instead of
  // passing the trigger_async_id along with other constructor arguments.
  class DefaultTriggerAsyncIdScope {
   public:
    DefaultTriggerAsyncIdScope() = delete;
    explicit DefaultTriggerAsyncIdScope(Environment* env,
                                        double init_trigger_async_id);
    explicit DefaultTriggerAsyncIdScope(AsyncWrap* async_wrap);
    ~DefaultTriggerAsyncIdScope();

    DefaultTriggerAsyncIdScope(const DefaultTriggerAsyncIdScope&) = delete;
    DefaultTriggerAsyncIdScope& operator=(const DefaultTriggerAsyncIdScope&) =
        delete;
    DefaultTriggerAsyncIdScope(DefaultTriggerAsyncIdScope&&) = delete;
    DefaultTriggerAsyncIdScope& operator=(DefaultTriggerAsyncIdScope&&) =
        delete;

   private:
    AsyncHooks* async_hooks_;
    double old_default_trigger_async_id_;
  };

 private:
  friend class Environment;  // So we can call the constructor.
  inline AsyncHooks();
  // Stores the ids of the current execution context stack.
  AliasedFloat64Array async_ids_stack_;
  // Attached to a Uint32Array that tracks the number of active hooks for
  // each type.
  AliasedUint32Array fields_;
  // Attached to a Float64Array that tracks the state of async resources.
  AliasedFloat64Array async_id_fields_;

  void grow_async_ids_stack();

  v8::Global<v8::Array> js_execution_async_resources_;
  std::vector<v8::Global<v8::Object>> native_execution_async_resources_;
};

class ImmediateInfo : public MemoryRetainer {
 public:
  inline AliasedUint32Array& fields();
  inline uint32_t count() const;
  inline uint32_t ref_count() const;
  inline bool has_outstanding() const;
  inline void ref_count_inc(uint32_t increment);
  inline void ref_count_dec(uint32_t decrement);

  ImmediateInfo(const ImmediateInfo&) = delete;
  ImmediateInfo& operator=(const ImmediateInfo&) = delete;
  ImmediateInfo(ImmediateInfo&&) = delete;
  ImmediateInfo& operator=(ImmediateInfo&&) = delete;
  ~ImmediateInfo() = default;

  SET_MEMORY_INFO_NAME(ImmediateInfo)
  SET_SELF_SIZE(ImmediateInfo)
  void MemoryInfo(MemoryTracker* tracker) const override;

 private:
  friend class Environment;  // So we can call the constructor.
  inline explicit ImmediateInfo(v8::Isolate* isolate);

  enum Fields { kCount, kRefCount, kHasOutstanding, kFieldsCount };

  AliasedUint32Array fields_;
};

class TickInfo : public MemoryRetainer {
 public:
  inline AliasedUint8Array& fields();
  inline bool has_tick_scheduled() const;
  inline bool has_rejection_to_warn() const;

  SET_MEMORY_INFO_NAME(TickInfo)
  SET_SELF_SIZE(TickInfo)
  void MemoryInfo(MemoryTracker* tracker) const override;

  TickInfo(const TickInfo&) = delete;
  TickInfo& operator=(const TickInfo&) = delete;
  TickInfo(TickInfo&&) = delete;
  TickInfo& operator=(TickInfo&&) = delete;
  ~TickInfo() = default;

 private:
  friend class Environment;  // So we can call the constructor.
  inline explicit TickInfo(v8::Isolate* isolate);

  enum Fields { kHasTickScheduled = 0, kHasRejectionToWarn, kFieldsCount };

  AliasedUint8Array fields_;
};

class TrackingTraceStateObserver :
    public v8::TracingController::TraceStateObserver {
 public:
  explicit TrackingTraceStateObserver(Environment* env) : env_(env) {}

  void OnTraceEnabled() override {
    UpdateTraceCategoryState();
  }

  void OnTraceDisabled() override {
    UpdateTraceCategoryState();
  }

 private:
  void UpdateTraceCategoryState();

  Environment* env_;
};

class ShouldNotAbortOnUncaughtScope {
 public:
  explicit inline ShouldNotAbortOnUncaughtScope(Environment* env);
  inline void Close();
  inline ~ShouldNotAbortOnUncaughtScope();
  ShouldNotAbortOnUncaughtScope(const ShouldNotAbortOnUncaughtScope&) = delete;
  ShouldNotAbortOnUncaughtScope& operator=(
      const ShouldNotAbortOnUncaughtScope&) = delete;
  ShouldNotAbortOnUncaughtScope(ShouldNotAbortOnUncaughtScope&&) = delete;
  ShouldNotAbortOnUncaughtScope& operator=(ShouldNotAbortOnUncaughtScope&&) =
      delete;

 private:
  Environment* env_;
};

class CleanupHookCallback {
 public:
  CleanupHookCallback(void (*fn)(void*),
                      void* arg,
                      uint64_t insertion_order_counter)
      : fn_(fn), arg_(arg), insertion_order_counter_(insertion_order_counter) {}

  // Only hashes `arg_`, since that is usually enough to identify the hook.
  struct Hash {
    inline size_t operator()(const CleanupHookCallback& cb) const;
  };

  // Compares by `fn_` and `arg_` being equal.
  struct Equal {
    inline bool operator()(const CleanupHookCallback& a,
                           const CleanupHookCallback& b) const;
  };

  inline BaseObject* GetBaseObject() const;

 private:
  friend class Environment;
  void (*fn_)(void*);
  void* arg_;

  // We keep track of the insertion order for these objects, so that we can
  // call the callbacks in reverse order when we are cleaning up.
  uint64_t insertion_order_counter_;
};

class Environment : public MemoryRetainer {
 public:
  Environment(const Environment&) = delete;
  Environment& operator=(const Environment&) = delete;
  Environment(Environment&&) = delete;
  Environment& operator=(Environment&&) = delete;

  SET_MEMORY_INFO_NAME(Environment)

  inline size_t SelfSize() const override;
  bool IsRootNode() const override { return true; }
  void MemoryInfo(MemoryTracker* tracker) const override;

  void CreateProperties();
  // Should be called before InitializeInspector()
  void InitializeDiagnostics();
#if HAVE_INSPECTOR
  // If the environment is created for a worker, pass parent_handle and
  // the ownership if transferred into the Environment.
  int InitializeInspector(
      std::unique_ptr<inspector::ParentInspectorHandle> parent_handle);
#endif

  v8::MaybeLocal<v8::Value> BootstrapInternalLoaders();
  v8::MaybeLocal<v8::Value> BootstrapNode();
  v8::MaybeLocal<v8::Value> RunBootstrapping();

  inline size_t async_callback_scope_depth() const;
  inline void PushAsyncCallbackScope();
  inline void PopAsyncCallbackScope();

  static inline Environment* GetCurrent(v8::Isolate* isolate);
  static inline Environment* GetCurrent(v8::Local<v8::Context> context);
  static inline Environment* GetCurrent(
      const v8::FunctionCallbackInfo<v8::Value>& info);

  template <typename T>
  static inline Environment* GetCurrent(
      const v8::PropertyCallbackInfo<T>& info);

  static inline Environment* GetFromCallbackData(v8::Local<v8::Value> val);

  static uv_key_t thread_local_env;
  static inline Environment* GetThreadLocalEnv();

  Environment(IsolateData* isolate_data,
              v8::Local<v8::Context> context,
              const std::vector<std::string>& args,
              const std::vector<std::string>& exec_args,
              EnvironmentFlags::Flags flags,
              ThreadId thread_id);
  ~Environment() override;

  void InitializeLibuv(bool start_profiler_idle_notifier);
  inline const std::vector<std::string>& exec_argv();
  inline const std::vector<std::string>& argv();
  const std::string& exec_path() const;

  typedef void (*HandleCleanupCb)(Environment* env,
                                  uv_handle_t* handle,
                                  void* arg);
  struct HandleCleanup {
    uv_handle_t* handle_;
    HandleCleanupCb cb_;
    void* arg_;
  };

  void RegisterHandleCleanups();
  void CleanupHandles();
  void Exit(int code);
  void ExitEnv();

  // Register clean-up cb to be called on environment destruction.
  inline void RegisterHandleCleanup(uv_handle_t* handle,
                                    HandleCleanupCb cb,
                                    void* arg);

  template <typename T, typename OnCloseCallback>
  inline void CloseHandle(T* handle, OnCloseCallback callback);

  inline void AssignToContext(v8::Local<v8::Context> context,
                              const ContextInfo& info);

  void StartProfilerIdleNotifier();
  void StopProfilerIdleNotifier();
  inline bool profiler_idle_notifier_started() const;

  inline v8::Isolate* isolate() const;
  inline uv_loop_t* event_loop() const;
  inline void TryLoadAddon(
      const char* filename,
      int flags,
      const std::function<bool(binding::DLib*)>& was_loaded);

  static inline Environment* from_timer_handle(uv_timer_t* handle);
  inline uv_timer_t* timer_handle();

  static inline Environment* from_immediate_check_handle(uv_check_t* handle);
  inline uv_check_t* immediate_check_handle();
  inline uv_idle_t* immediate_idle_handle();

  inline void IncreaseWaitingRequestCounter();
  inline void DecreaseWaitingRequestCounter();

  inline AsyncHooks* async_hooks();
  inline ImmediateInfo* immediate_info();
  inline TickInfo* tick_info();
  inline uint64_t timer_base() const;
  inline std::shared_ptr<KVStore> env_vars();
  inline void set_env_vars(std::shared_ptr<KVStore> env_vars);

  inline IsolateData* isolate_data() const;

  // Utilities that allocate memory using the Isolate's ArrayBuffer::Allocator.
  // In particular, using AllocateManaged() will provide a RAII-style object
  // with easy conversion to `Buffer` and `ArrayBuffer` objects.
  inline AllocatedBuffer AllocateManaged(size_t size, bool checked = true);
  inline char* Allocate(size_t size);
  inline char* AllocateUnchecked(size_t size);
  char* Reallocate(char* data, size_t old_size, size_t size);
  inline void Free(char* data, size_t size);

  inline bool printed_error() const;
  inline void set_printed_error(bool value);

  void PrintSyncTrace() const;
  inline void set_trace_sync_io(bool value);

  inline void set_force_context_aware(bool value);
  inline bool force_context_aware() const;

  // This stores whether the --abort-on-uncaught-exception flag was passed
  // to Node.
  inline bool abort_on_uncaught_exception() const;
  inline void set_abort_on_uncaught_exception(bool value);
  // This is a pseudo-boolean that keeps track of whether an uncaught exception
  // should abort the process or not if --abort-on-uncaught-exception was
  // passed to Node. If the flag was not passed, it is ignored.
  inline AliasedUint32Array& should_abort_on_uncaught_toggle();

  inline AliasedInt32Array& stream_base_state();

  // The necessary API for async_hooks.
  inline double new_async_id();
  inline double execution_async_id();
  inline double trigger_async_id();
  inline double get_default_trigger_async_id();

  // List of id's that have been destroyed and need the destroy() cb called.
  inline std::vector<double>* destroy_async_id_list();

  std::set<std::string> native_modules_with_cache;
  std::set<std::string> native_modules_without_cache;

  std::unordered_multimap<int, loader::ModuleWrap*> hash_to_module_map;
  std::unordered_map<uint32_t, loader::ModuleWrap*> id_to_module_map;
  std::unordered_map<uint32_t, contextify::ContextifyScript*>
      id_to_script_map;
  std::unordered_map<uint32_t, contextify::CompiledFnEntry*> id_to_function_map;

  inline uint32_t get_next_module_id();
  inline uint32_t get_next_script_id();
  inline uint32_t get_next_function_id();

  inline double* heap_statistics_buffer() const;
  inline void set_heap_statistics_buffer(double* pointer);

  inline double* heap_space_statistics_buffer() const;
  inline void set_heap_space_statistics_buffer(double* pointer);

  inline double* heap_code_statistics_buffer() const;
  inline void set_heap_code_statistics_buffer(double* pointer);

  inline char* http_parser_buffer() const;
  inline void set_http_parser_buffer(char* buffer);
  inline bool http_parser_buffer_in_use() const;
  inline void set_http_parser_buffer_in_use(bool in_use);

  inline http2::Http2State* http2_state() const;
  inline void set_http2_state(std::unique_ptr<http2::Http2State> state);

  EnabledDebugList* enabled_debug_list() { return &enabled_debug_list_; }

  inline AliasedFloat64Array* fs_stats_field_array();
  inline AliasedBigUint64Array* fs_stats_field_bigint_array();

  inline std::vector<std::unique_ptr<fs::FileHandleReadWrap>>&
      file_handle_read_wrap_freelist();

  inline performance::PerformanceState* performance_state();
  inline std::unordered_map<std::string, uint64_t>* performance_marks();

  void CollectUVExceptionInfo(v8::Local<v8::Value> context,
                              int errorno,
                              const char* syscall = nullptr,
                              const char* message = nullptr,
                              const char* path = nullptr,
                              const char* dest = nullptr);

  // If this flag is set, calls into JS (if they would be observable
  // from userland) must be avoided.  This flag does not indicate whether
  // calling into JS is allowed from a VM perspective at this point.
  inline bool can_call_into_js() const;
  inline void set_can_call_into_js(bool can_call_into_js);

  // Increase or decrease a counter that manages whether this Environment
  // keeps the event loop alive on its own or not. The counter starts out at 0,
  // meaning it does not, and any positive value will make it keep the event
  // loop alive.
  // This is used by Workers to manage their own .ref()/.unref() implementation,
  // as Workers aren't directly associated with their own libuv handles.
  inline void add_refs(int64_t diff);

  inline bool has_run_bootstrapping_code() const;
  inline void set_has_run_bootstrapping_code(bool has_run_bootstrapping_code);

  inline bool has_serialized_options() const;
  inline void set_has_serialized_options(bool has_serialized_options);

  inline bool is_main_thread() const;
  inline bool should_not_register_esm_loader() const;
  inline bool owns_process_state() const;
  inline bool owns_inspector() const;
  inline bool tracks_unmanaged_fds() const;
  inline uint64_t thread_id() const;
  inline worker::Worker* worker_context() const;
  Environment* worker_parent_env() const;
  inline void add_sub_worker_context(worker::Worker* context);
  inline void remove_sub_worker_context(worker::Worker* context);
  void stop_sub_worker_contexts();
  template <typename Fn>
  inline void ForEachWorker(Fn&& iterator);
  inline bool is_stopping() const;
  inline void set_stopping(bool value);
  inline std::list<node_module>* extra_linked_bindings();
  inline node_module* extra_linked_bindings_head();
  inline const Mutex& extra_linked_bindings_mutex() const;

  inline void ThrowError(const char* errmsg);
  inline void ThrowTypeError(const char* errmsg);
  inline void ThrowRangeError(const char* errmsg);
  inline void ThrowErrnoException(int errorno,
                                  const char* syscall = nullptr,
                                  const char* message = nullptr,
                                  const char* path = nullptr);
  inline void ThrowUVException(int errorno,
                               const char* syscall = nullptr,
                               const char* message = nullptr,
                               const char* path = nullptr,
                               const char* dest = nullptr);

  inline v8::Local<v8::FunctionTemplate>
      NewFunctionTemplate(v8::FunctionCallback callback,
                          v8::Local<v8::Signature> signature =
                              v8::Local<v8::Signature>(),
                          v8::ConstructorBehavior behavior =
                              v8::ConstructorBehavior::kAllow,
                          v8::SideEffectType side_effect =
                              v8::SideEffectType::kHasSideEffect);

  // Convenience methods for NewFunctionTemplate().
  inline void SetMethod(v8::Local<v8::Object> that,
                        const char* name,
                        v8::FunctionCallback callback);

  inline void SetProtoMethod(v8::Local<v8::FunctionTemplate> that,
                             const char* name,
                             v8::FunctionCallback callback);

  inline void SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
                                const char* name,
                                v8::FunctionCallback callback);


  // Safe variants denote the function has no side effects.
  inline void SetMethodNoSideEffect(v8::Local<v8::Object> that,
                                    const char* name,
                                    v8::FunctionCallback callback);
  inline void SetProtoMethodNoSideEffect(v8::Local<v8::FunctionTemplate> that,
                                         const char* name,
                                         v8::FunctionCallback callback);

  void AtExit(void (*cb)(void* arg), void* arg);
  void RunAtExitCallbacks();

  void RegisterFinalizationGroupForCleanup(v8::Local<v8::FinalizationGroup> fg);
  void RunWeakRefCleanup();
  void CleanupFinalizationGroups();

  // Strings and private symbols are shared across shared contexts
  // The getters simply proxy to the per-isolate primitive.
#define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
#define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
#define VS(PropertyName, StringValue) V(v8::String, PropertyName)
#define V(TypeName, PropertyName)                                             \
  inline v8::Local<TypeName> PropertyName() const;
  PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
  PER_ISOLATE_SYMBOL_PROPERTIES(VY)
  PER_ISOLATE_STRING_PROPERTIES(VS)
#undef V
#undef VS
#undef VY
#undef VP

#define V(PropertyName, TypeName)                                             \
  inline v8::Local<TypeName> PropertyName() const;                            \
  inline void set_ ## PropertyName(v8::Local<TypeName> value);
  ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
  ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
#undef V

  inline v8::Local<v8::Context> context() const;

#if HAVE_INSPECTOR
  inline inspector::Agent* inspector_agent() const {
    return inspector_agent_.get();
  }

  inline bool is_in_inspector_console_call() const;
  inline void set_is_in_inspector_console_call(bool value);
#endif

  typedef ListHead<HandleWrap, &HandleWrap::handle_wrap_queue_> HandleWrapQueue;
  typedef ListHead<ReqWrapBase, &ReqWrapBase::req_wrap_queue_> ReqWrapQueue;

  inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; }
  inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; }

  inline bool EmitProcessEnvWarning() {
    bool current_value = emit_env_nonstring_warning_;
    emit_env_nonstring_warning_ = false;
    return current_value;
  }

  inline bool EmitErrNameWarning() {
    bool current_value = emit_err_name_warning_;
    emit_err_name_warning_ = false;
    return current_value;
  }

  // cb will be called as cb(env) on the next event loop iteration.
  // Unlike the JS setImmediate() function, nested SetImmediate() calls will
  // be run without returning control to the event loop, similar to nextTick().
  template <typename Fn>
  inline void SetImmediate(
      Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::kRefed);
  template <typename Fn>
  // This behaves like SetImmediate() but can be called from any thread.
  inline void SetImmediateThreadsafe(
      Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::kRefed);
  // This behaves like V8's Isolate::RequestInterrupt(), but also accounts for
  // the event loop (i.e. combines the V8 function with SetImmediate()).
  // The passed callback may not throw exceptions.
  // This function can be called from any thread.
  template <typename Fn>
  inline void RequestInterrupt(Fn&& cb);
  // This needs to be available for the JS-land setImmediate().
  void ToggleImmediateRef(bool ref);

  inline void PushShouldNotAbortOnUncaughtScope();
  inline void PopShouldNotAbortOnUncaughtScope();
  inline bool inside_should_not_abort_on_uncaught_scope() const;

  static inline Environment* ForAsyncHooks(AsyncHooks* hooks);

  v8::Local<v8::Value> GetNow();
  void ScheduleTimer(int64_t duration);
  void ToggleTimerRef(bool ref);

  inline void AddCleanupHook(void (*fn)(void*), void* arg);
  inline void RemoveCleanupHook(void (*fn)(void*), void* arg);
  void RunCleanup();

  static void BuildEmbedderGraph(v8::Isolate* isolate,
                                 v8::EmbedderGraph* graph,
                                 void* data);

  inline std::shared_ptr<EnvironmentOptions> options();
  inline std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port();

  inline int32_t stack_trace_limit() const { return 10; }

  // The BaseObject count is a debugging helper that makes sure that there are
  // no memory leaks caused by BaseObjects staying alive longer than expected
  // (in particular, no circular BaseObjectPtr references).
  inline void modify_base_object_count(int64_t delta);
  inline int64_t base_object_count() const;

#if HAVE_INSPECTOR
  void set_coverage_connection(
      std::unique_ptr<profiler::V8CoverageConnection> connection);
  profiler::V8CoverageConnection* coverage_connection();

  inline void set_coverage_directory(const char* directory);
  inline const std::string& coverage_directory() const;

  void set_cpu_profiler_connection(
      std::unique_ptr<profiler::V8CpuProfilerConnection> connection);
  profiler::V8CpuProfilerConnection* cpu_profiler_connection();

  inline void set_cpu_prof_name(const std::string& name);
  inline const std::string& cpu_prof_name() const;

  inline void set_cpu_prof_interval(uint64_t interval);
  inline uint64_t cpu_prof_interval() const;

  inline void set_cpu_prof_dir(const std::string& dir);
  inline const std::string& cpu_prof_dir() const;

  void set_heap_profiler_connection(
      std::unique_ptr<profiler::V8HeapProfilerConnection> connection);
  profiler::V8HeapProfilerConnection* heap_profiler_connection();

  inline void set_heap_prof_name(const std::string& name);
  inline const std::string& heap_prof_name() const;

  inline void set_heap_prof_dir(const std::string& dir);
  inline const std::string& heap_prof_dir() const;

  inline void set_heap_prof_interval(uint64_t interval);
  inline uint64_t heap_prof_interval() const;

#endif  // HAVE_INSPECTOR

  // Only available if a MultiIsolatePlatform is in use.
  void AddArrayBufferAllocatorToKeepAliveUntilIsolateDispose(
      std::shared_ptr<v8::ArrayBuffer::Allocator>);

  inline void set_main_utf16(std::unique_ptr<v8::String::Value>);
  inline void set_process_exit_handler(
      std::function<void(Environment*, int)>&& handler);

  void RunAndClearNativeImmediates(bool only_refed = false);
  void RunAndClearInterrupts();

  void AddUnmanagedFd(int fd);
  void RemoveUnmanagedFd(int fd);

 private:
  inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
                         const char* errmsg);

  std::list<binding::DLib> loaded_addons_;
  v8::Isolate* const isolate_;
  IsolateData* const isolate_data_;
  uv_timer_t timer_handle_;
  uv_check_t immediate_check_handle_;
  uv_idle_t immediate_idle_handle_;
  uv_prepare_t idle_prepare_handle_;
  uv_check_t idle_check_handle_;
  uv_async_t task_queues_async_;
  int64_t task_queues_async_refs_ = 0;
  bool profiler_idle_notifier_started_ = false;

  AsyncHooks async_hooks_;
  ImmediateInfo immediate_info_;
  TickInfo tick_info_;
  const uint64_t timer_base_;
  std::shared_ptr<KVStore> env_vars_;
  bool printed_error_ = false;
  bool trace_sync_io_ = false;
  bool emit_env_nonstring_warning_ = true;
  bool emit_err_name_warning_ = true;
  size_t async_callback_scope_depth_ = 0;
  std::vector<double> destroy_async_id_list_;

#if HAVE_INSPECTOR
  std::unique_ptr<profiler::V8CoverageConnection> coverage_connection_;
  std::unique_ptr<profiler::V8CpuProfilerConnection> cpu_profiler_connection_;
  std::string coverage_directory_;
  std::string cpu_prof_dir_;
  std::string cpu_prof_name_;
  uint64_t cpu_prof_interval_;
  std::unique_ptr<profiler::V8HeapProfilerConnection> heap_profiler_connection_;
  std::string heap_prof_dir_;
  std::string heap_prof_name_;
  uint64_t heap_prof_interval_;
#endif  // HAVE_INSPECTOR

  std::shared_ptr<EnvironmentOptions> options_;
  // options_ contains debug options parsed from CLI arguments,
  // while inspector_host_port_ stores the actual inspector host
  // and port being used. For example the port is -1 by default
  // and can be specified as 0 (meaning any port allocated when the
  // server starts listening), but when the inspector server starts
  // the inspector_host_port_->port() will be the actual port being
  // used.
  std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port_;
  std::vector<std::string> exec_argv_;
  std::vector<std::string> argv_;
  std::string exec_path_;

  uint32_t module_id_counter_ = 0;
  uint32_t script_id_counter_ = 0;
  uint32_t function_id_counter_ = 0;

  AliasedUint32Array should_abort_on_uncaught_toggle_;
  int should_not_abort_scope_counter_ = 0;

  std::unique_ptr<TrackingTraceStateObserver> trace_state_observer_;

  AliasedInt32Array stream_base_state_;

  std::unique_ptr<performance::PerformanceState> performance_state_;
  std::unordered_map<std::string, uint64_t> performance_marks_;

  bool has_run_bootstrapping_code_ = false;
  bool has_serialized_options_ = false;

  std::atomic_bool can_call_into_js_ { true };
  uint64_t flags_;
  uint64_t thread_id_;
  std::unordered_set<worker::Worker*> sub_worker_contexts_;

  std::deque<v8::Global<v8::FinalizationGroup>> cleanup_finalization_groups_;

  static void* const kNodeContextTagPtr;
  static int const kNodeContextTag;

#if HAVE_INSPECTOR
  std::unique_ptr<inspector::Agent> inspector_agent_;
  bool is_in_inspector_console_call_ = false;
#endif

  // handle_wrap_queue_ and req_wrap_queue_ needs to be at a fixed offset from
  // the start of the class because it is used by
  // src/node_postmortem_metadata.cc to calculate offsets and generate debug
  // symbols for Environment, which assumes that the position of members in
  // memory are predictable. For more information please refer to
  // `doc/guides/node-postmortem-support.md`
  friend int GenDebugSymbols();
  HandleWrapQueue handle_wrap_queue_;
  ReqWrapQueue req_wrap_queue_;
  std::list<HandleCleanup> handle_cleanup_queue_;
  int handle_cleanup_waiting_ = 0;
  int request_waiting_ = 0;

  double* heap_statistics_buffer_ = nullptr;
  double* heap_space_statistics_buffer_ = nullptr;
  double* heap_code_statistics_buffer_ = nullptr;

  char* http_parser_buffer_ = nullptr;
  bool http_parser_buffer_in_use_ = false;
  std::unique_ptr<http2::Http2State> http2_state_;

  EnabledDebugList enabled_debug_list_;
  AliasedFloat64Array fs_stats_field_array_;
  AliasedBigUint64Array fs_stats_field_bigint_array_;

  std::vector<std::unique_ptr<fs::FileHandleReadWrap>>
      file_handle_read_wrap_freelist_;

  std::list<node_module> extra_linked_bindings_;
  Mutex extra_linked_bindings_mutex_;

  static void RunTimers(uv_timer_t* handle);

  struct ExitCallback {
    void (*cb_)(void* arg);
    void* arg_;
  };

  std::list<ExitCallback> at_exit_functions_;

  typedef CallbackQueue<void, Environment*> NativeImmediateQueue;
  NativeImmediateQueue native_immediates_;
  Mutex native_immediates_threadsafe_mutex_;
  NativeImmediateQueue native_immediates_threadsafe_;
  NativeImmediateQueue native_immediates_interrupts_;
  // Also guarded by native_immediates_threadsafe_mutex_. This can be used when
  // trying to post tasks from other threads to an Environment, as the libuv
  // handle for the immediate queues (task_queues_async_) may not be initialized
  // yet or already have been destroyed.
  bool task_queues_async_initialized_ = false;

  std::atomic<Environment**> interrupt_data_ {nullptr};
  void RequestInterruptFromV8();
  static void CheckImmediate(uv_check_t* handle);

  // Use an unordered_set, so that we have efficient insertion and removal.
  std::unordered_set<CleanupHookCallback,
                     CleanupHookCallback::Hash,
                     CleanupHookCallback::Equal> cleanup_hooks_;
  uint64_t cleanup_hook_counter_ = 0;
  bool started_cleanup_ = false;

  int64_t base_object_count_ = 0;
  std::atomic_bool is_stopping_ { false };

  typedef std::unordered_set<std::shared_ptr<v8::ArrayBuffer::Allocator>>
      ArrayBufferAllocatorList;
  ArrayBufferAllocatorList* keep_alive_allocators_ = nullptr;

  std::unordered_set<int> unmanaged_fds_;

  std::function<void(Environment*, int)> process_exit_handler_ {
      DefaultProcessExitHandler };

  template <typename T>
  void ForEachBaseObject(T&& iterator);

#define V(PropertyName, TypeName) v8::Global<TypeName> PropertyName ## _;
  ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
  ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
#undef V

  v8::Global<v8::Context> context_;

  // Keeps the main script source alive is one was passed to LoadEnvironment().
  // We should probably find a way to just use plain `v8::String`s created from
  // the source passed to LoadEnvironment() directly instead.
  std::unique_ptr<v8::String::Value> main_utf16_;
};

}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_ENV_H_