From 6ad3e6a5e36c9b8385cbf3bec7a49c960fcdf97b Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Wed, 17 Jul 2024 20:53:12 -0700 Subject: [PATCH] Fixes #2532 (#12633) Co-authored-by: Jarred-Sumner --- src/bun.js/bindings/NodeHTTP.cpp | 31 ++- src/js/node/http.ts | 27 +- test/bun.lockb | Bin 325186 -> 347442 bytes .../node/http/node-http-primoridals.test.ts | 118 ++++++++ .../remix/remix-build/server/index.js | 262 ++++++++++++++++++ test/js/third_party/remix/remix.test.ts | 44 +++ test/package.json | 3 + 7 files changed, 473 insertions(+), 12 deletions(-) create mode 100644 test/js/node/http/node-http-primoridals.test.ts create mode 100644 test/js/third_party/remix/remix-build/server/index.js create mode 100644 test/js/third_party/remix/remix.test.ts diff --git a/src/bun.js/bindings/NodeHTTP.cpp b/src/bun.js/bindings/NodeHTTP.cpp index a49e17adcd..2f5c810ebf 100644 --- a/src/bun.js/bindings/NodeHTTP.cpp +++ b/src/bun.js/bindings/NodeHTTP.cpp @@ -1,4 +1,5 @@ #include "root.h" +#include "JSDOMGlobalObjectInlines.h" #include "ZigGlobalObject.h" #include #include "helpers.h" @@ -259,10 +260,11 @@ JSC_DEFINE_HOST_FUNCTION(jsHTTPAssignHeaders, (JSGlobalObject * globalObject, Ca auto& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - JSValue requestValue = callFrame->argument(0); - JSObject* objectValue = callFrame->argument(1).getObject(); - - JSC::InternalFieldTuple* tuple = JSC::InternalFieldTuple::create(vm, globalObject->m_internalFieldTupleStructure.get()); + // This is an internal binding. + JSValue requestValue = callFrame->uncheckedArgument(0); + JSObject* objectValue = callFrame->uncheckedArgument(1).getObject(); + JSC::InternalFieldTuple* tuple = jsCast(callFrame->uncheckedArgument(2)); + ASSERT(callFrame->argumentCount() == 3); JSValue headersValue = JSValue(); JSValue urlValue = JSValue(); @@ -409,13 +411,28 @@ JSValue createNodeHTTPInternalBinding(Zig::GlobalObject* globalObject) VM& vm = globalObject->vm(); obj->putDirect( vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "setHeader"_s)), - JSC::JSFunction::create(vm, globalObject, 3, "setHeader"_s, jsHTTPSetHeader, ImplementationVisibility::Public), NoIntrinsic); + JSC::JSFunction::create(vm, globalObject, 3, "setHeader"_s, jsHTTPSetHeader, ImplementationVisibility::Public), 0); obj->putDirect( vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "getHeader"_s)), - JSC::JSFunction::create(vm, globalObject, 2, "getHeader"_s, jsHTTPGetHeader, ImplementationVisibility::Public), NoIntrinsic); + JSC::JSFunction::create(vm, globalObject, 2, "getHeader"_s, jsHTTPGetHeader, ImplementationVisibility::Public), 0); obj->putDirect( vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "assignHeaders"_s)), - JSC::JSFunction::create(vm, globalObject, 2, "assignHeaders"_s, jsHTTPAssignHeaders, ImplementationVisibility::Public), NoIntrinsic); + JSC::JSFunction::create(vm, globalObject, 2, "assignHeaders"_s, jsHTTPAssignHeaders, ImplementationVisibility::Public), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "Response"_s)), + globalObject->JSResponseConstructor(), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "Request"_s)), + globalObject->JSRequestConstructor(), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "Blob"_s)), + globalObject->JSBlobConstructor(), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "Headers"_s)), + WebCore::JSFetchHeaders::getConstructor(vm, globalObject), 0); + obj->putDirect( + vm, JSC::PropertyName(JSC::Identifier::fromString(vm, "headersTuple"_s)), + JSC::InternalFieldTuple::create(vm, globalObject->m_internalFieldTupleStructure.get()), 0); return obj; } diff --git a/src/js/node/http.ts b/src/js/node/http.ts index 87e1a47338..18c3c0a107 100644 --- a/src/js/node/http.ts +++ b/src/js/node/http.ts @@ -7,7 +7,21 @@ const { getHeader, setHeader, assignHeaders: assignHeadersFast, -} = $cpp("NodeHTTP.cpp", "createNodeHTTPInternalBinding"); + Response, + Request, + Headers, + Blob, + headersTuple, +} = $cpp("NodeHTTP.cpp", "createNodeHTTPInternalBinding") as { + getHeader: (headers: Headers, name: string) => string | undefined; + setHeader: (headers: Headers, name: string, value: string) => void; + assignHeaders: (object: any, req: Request, headersTuple: any) => boolean; + Response: (typeof globalThis)["Response"]; + Request: (typeof globalThis)["Request"]; + Headers: (typeof globalThis)["Headers"]; + Blob: (typeof globalThis)["Blob"]; + headersTuple: any; +}; const ObjectDefineProperty = Object.defineProperty; const ObjectSetPrototypeOf = Object.setPrototypeOf; @@ -664,10 +678,13 @@ function assignHeadersSlow(object, req) { function assignHeaders(object, req) { // This fast path is an 8% speedup for a "hello world" node:http server, and a 7% speedup for a "hello world" express server - const tuple = assignHeadersFast(req, object); - if (tuple !== null) { - object.headers = $getInternalField(tuple, 0); - object.rawHeaders = $getInternalField(tuple, 1); + if (assignHeadersFast(req, object, headersTuple)) { + const headers = $getInternalField(headersTuple, 0); + const rawHeaders = $getInternalField(headersTuple, 1); + $putInternalField(headersTuple, 0, undefined); + $putInternalField(headersTuple, 1, undefined); + object.headers = headers; + object.rawHeaders = rawHeaders; return true; } else { assignHeadersSlow(object, req); diff --git a/test/bun.lockb b/test/bun.lockb index b2294918f4e0c33be8a4cf4e74222a3002c556e4..9508f9459a97d8e404bb3ee2917e037dd0e7bae5 100755 GIT binary patch delta 61962 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

s5Hlnj zghya*k=zowwehISor^macc#;jGmsx3JOF$L*$3g?%|pT}$ZE(M$lBic!{g3M$VA8_ z$OuRuNLNTVNEgU&=urr;C8Q0cE~GM~Dx?e~7bG|23y2%!BhvGf`VPV`;O^HJwR6gA z;~_N@aujk5avX9J@+0I7O=UQn>08DKcJHiEDx*zsR*eAsRF4A zsRqf0vB?hMSB%d?E`tO0BHo_2{HuI1kx13Q=uE=Inup^yn(!h@ML%mas$F6%M}QZJ(u`gga>ZkwM_={ z#wilg3(^Bp9g>2^4TemCOoeztR|xVYCcdBkn4~eked*G z1$G!@ID{YmO68vskWrA)kTH<4kZ};60{Px}Gh_=S6w(PYAB{~0_J`Dh)P&TAY=oXi zR31OSg{*?`tn?D{6!Hvm4RRH70df&yyM#ZdAg3W`AQND|V2mF>`!oa%@Q2ic1VDTt zevrBl73oGmazb)L@<9H8MLs~LKseuvK#D?)5NF6E|qP79gJY%DfNeeeW*FH;`qJW)R-vvd~~iIS6l2*P>IeAwiG^ zka~~+2tTUDa3I9S4=A=nkD5W6LwKiG2$BQh0{Im!eg)wz#dXLz$XUoi$oCMv*Qm^n zHKgtn8p<2BZHQw}S0lUv!uv1sOAy9gGJYunB)t(C4PjUpZCYoi7PkMdy6=vw>S+4s z-g7NjK@q`A5wI)0*ioX1CMs5pB^Iin^kP?R*c)mb6%;}21v@G#_HG1;C3eIv7<<%c ze7|${TrW|0e$V^<_v7SXot@o1=NgXN2&71)6bQ|A)kd;Gvi<7%2t+1JmQgVf`;TG z=O8gho#{P5+G6}8yMY@>>`mFL@?^~uHBZ?5IX!#VD@g2V*@xUlf*+CH2$yATu{(KB zUJ=sIlpG;hs6Nu(2+1yPx?`Ug3O5FAQWL8^?zp@bn4Hs^^271;Z^sEk&o}+(uZq1NdAhkkbA5w%mzDM33sU2@= zx5kARQcDzSgPda>Pvp&zw?+OP5@YxoV>stZxiV(l9f|vv`?@Qxxlg^3vlBar%DB(F z;hLZEHBVx7z^51P=kk_fPh9XgoP#tF*W6MLBDtlk3D&~T$a($KAE_@AuYvk0*Ib6N z>`58N*MpE+pt7OJLy&@zh9GfBz@b3^l0T9k4}}p(ivSKq4jBw$kPkuhzfa(m)RJ3xbWJddAByW5^QZZHYx%ARRgIH|X#K!~MIP@z&AyRU zRUBW|)wY58wA4sly&QELE%nj{!S^x$0ava?B)3i!7dBe0xBB~Ok*{90ifDO{TX)VXe-~YN52zQK&rf{A#Xe{LF4}ci}D_$jkSJQKBvYvSiD78R|*}0%% zU$dHOJ!KAUMp1mGW*LvHALaAiDB3m-ib#g$O;PG~qpZC_hI?$(Dj2D=g9pL`as)ti zl8U(0K>Eyg_h=lKvV)E-QEE@0=9d=j#{~VQlwhk`L}wYU)TIlyx#VhliU*3{g$%@{Bw@rXMPDz}_&@h(c23_Dgg;j}+m2ye}1^K^hZb_o51Y-)H zAl1SvRs$wUH7%VC5@6&!p63n-3(>SH@Pyi3nmV|lw`GenDa(T%WAe%bxQqg-I}zUD zxH6(HS7{zztwyIGxr~DgkLLH_#x`h_-5!q5+=+nhb7td(-F*iV+s z)zwU?<7BC`+R%(vzLw0?CT6sCGQ3u8Iz1U+JNg8aHq%@T!S^F4zbL4?!d$ItgfYi| z+sJtexQR^r3&sPhtXq73y*F=y%mFu@L^l_lV8$4ol2=sJdaypy8=>9*o>m z0bu_zto5SlQF%8`0sxgVU?Yr}-G%D{|Ivq+uf%{{fhX)3GD!gJI(~X*GE#M+j0DL>B|M615M$NnKMQ!Y)G5Q0^ZW`bz^fPC(Xx22a z`khwePCL7v=&Rn{&wBeB?G(+Erv{=|)1-;oHVuS=E_?s5_UXKQH>DA1e@B`(9UiL( z0BpnE#)s~|v2DjD0Ggs+xU>NZk5!r?!=Sk4*ieFg}g zjiHcOGM)h`CsN}XQWv#ZBN{zJ>Wt~~fcq{0i~#77b|!P-upcAzfa9RB6`Oae95}hoc%H+YVWd#x z6)Ktyh2S&gIjHFswM1s|32-*qjDU3m(+B^(-sH>RDCbC#b0jnOYK}thlbX$+biaD# zQF??GC_F(K*RihNEBWIiJ;k05%#qFK1y|LBD$d27($XU|0PUvex#$oPduaK0vsp>r zjz`kW&m1*@%uw(bkJ1J2pvtsh=kB71KOJi_z;;J>YguJ-^&yloABJCg zCyH(((?m38HaRDPX%clxM1>znwE)drk|?>U)=<_~#~!2crB%_n!?v@lc}+1%Rq4_2;Y;wRtS+97OZ*z&!>9;o2uOs@4E*q##vaaGFB# zGyP~-)!O8(o{~g2nO6oKR(KsHK~%i{M_=??&>EMNv-?%C*E3?o2=AJced>?QGWMU9sb zDiu$-qJwljNivVm!7V$E=C#g+ZEModKwsZog_6-X?_jgvkEe62D+lZbuN6uq({kJ1 z2X|hnFH^RIFr0#*sJ3w*pMTKHXs%Fh^{M~kh(k;56$D#j z?D?woYE>INVNnMm=cv`RXw5z6?^6BsTw|$Cl9Z$pZP8u>j)Tnuvv1r;%{vO8jfJK> zRGw4SWFFBaPd9KTm&o@ijO`AEA<&@t$r!$)=s3!_Py0~_adY;G#EO;5L2#ZkG5;7$ zDklt}*-vMlxg^yZiIM4shzLG6gzT5Y-%O%kmrF@%#n%2$=J3DnbTq$|j-%5nq+y+W zx`-iRt-d?3`?F_}Y86M5h{p{|x5-k3pwv{juqrF0@|2t+)w2Izv8I9)$p^pl!D`pu zgHSviu3Sk!`tznLh}BrfaB&8rLs*5=S4u8QAgHZ|US?DIV|u-RJo`^K)VuC>^yf-+ zv_m(+uy6LWGRe1!8UO%0;9i?d7qZdAy;I@3CsI_ZWL|wqcQGjIc02i~Ue-%QY4d1# zDk7`ZlnuIe3+NmQ#AV)WS^I!hV=!a00<%ndl?qSoK=sq4F7_q*lIGlu5>%U+nkMyC zVJ@;+iz=q|67zA`u~p;S+`8HwaXHJ2$V}ebFvku-OW+iJsgfyiJ?`@8!fIq|XB8U)eFnh&vI0mN+oa6>qkrWyz*&xL?t;SJX-e1f z;jJbw?I%-YQ~#5?peF4oj0JXRBRu~MJQO!$n*92tRPMo!5<< z-9KO~^D@H?9V*M*MQOLvEb6vK%K7)BuUaZZr?j>B|KEkmbQ%$=pxNuB95uFf2Cl~h zstjgDOF}QTTJ{%ud0*LfSB3C3+4N@&_gI~l5_v^cM;?@WA z;8+om$##j)RW?B9D`*Td?GxbGLfQ;`Is8Mr6b^8e!1@(sFzzGeZjwxDyRZrj2M8s8 zKkB<>S%<%`EQ5L0F%V#FN*&P+NlVYviVE9PQ2;o2TtUto^I^Pj0YA zp*-Apzi0UNrHC4x9h%EVD)))0wX2)KJYO-KqRR|>@Tl$lcU;KvLD8*C{K<0*EW8d7?6O9iKWO7>Xo0b! zL%34Z7IaGon#EafTD=8RK_2Db!`){3o3oSTm4QroC^DLxA=RorWQhD~{)B?)U7yMh z8ZZS@9c5*}7wxA(TP1V*5iBm$Cvj9ZKW3!Es-qZQIb|a5{@j`>ibU<{hlCFMSrc zmOHT^v)PFu( z9xj+>Ip57U`mTH%0N8B7G>5VcbZ; zHlCL5ff3xI^LwzJ@{qK9arc(G?!|tFG+H>Pc}qJ4ztnDUlxJ(KEHJ@2Z9_DnvbRxdoefFr%dMLMo+1zZYEiu?k3jxHBlAYx2A^pvzN79@l$c~faL2078d;)Dh zDE+4Lp^1pnfJs7DQZ&a?6QUy#&8ZI2<7||!Hl0EbNiOOdGic=@_~`yKgnK$OoO~WOmyrwr{1pC&DAQ;*3D#3bc(K{&D!a+#Ejc3 zBPF+q(H%Y{P*nSbsvZS^j|zF*^iw5Y|KYC`#Oeb*#0a}V?T%trnMWIe!#d;mQJi^Y z!;iB>XN$`8@v4{Y0k|t-d&rFN+2I(BFOxbPgX(uu{BfAf$751W4LT-=GLC`E9qM`l znV#s4m?-rmrd$CX*S7!rAyE)}hgT;sWC(wL_y zdO%}PScXm`R6lipb;C$cv0g^r=MY5*VO2tOi_+Vsv>rd-$jbN++EUb6y1tde&UrKp zXP(;I*sNoU~RhsDU9d$JWoE{}q*8^Kq1c2_p0KlhMv*vwD&a^Xrq6drz zg*SR0c-1Zcrd|7EdP*`KKvC^30C37M!E$t0)%~%TCg=ed=>-7TV5@imGM}S17f{pG zb;5}Z-(nNjZ@1HL`V-FS>&3v!e{0(G=F})k%t5Jm+K5a$XM^B=-}~A6i!1W64<%3MSbi*{+YDbt z_PKy>q7J#JL^+v7h>)H6YcBk;Dm?T2MM+ZOggiG7xOwyxnRf10!B*|r$F@ZmGx_*T zNS#F1zoWhD0ARoH>%Ie>cUu^G%fnu7)^3Hew1HJ#mi107cID2-4&X5gLs59gX}@FE zskoggT#_d69>wfS=*+UQ!bk!?ZERuLJf6>saP-ffW-Mi2Liq4)+$0}|Kr^#<2p@Dq zJG}MBiIJ;Oln?K*a6v>>t5ChNYa&`qW3OUSJTp_c=w53^Z?PKN zfES9&`w@Ax?J9ce5PfEDHTDWz`5EoX-CmW}THyvg)F#(Iut{URPgG}Kty*X=yQ;qf zpqwZ=(!@U?w+|%&r)owQaA)BSI8O};M!$rHPEjQTjwpabaA;n0O=@Jf1c+Kdl)n2j znz~;D<7qSu+0X>Ur5vh!3RP{5v~ABvntYs(DY4OhA=$2)3kvzDJL&sJgO@TGawic;6DQRXn=}%ZS1~PhHLxUOa8| zgNa718h|J4@;Z>sb;y-KEs<$Uuj3s>0N`H2OCHU!Jci(<7wtg@xQYRE&!)CF;HQnV1)}4@U!=&>gE^YOTL@f7Dd9YW1|_tR{*E z+=OyUoc|FP;RPj11OOBCM#jwmBaViCOK4YUlzBpu<(J<`Swgn~a9<065dfZ(LW+`o zoA3(_Y{zI|CMd?BoOQeI(EnoD;h^y9A61+p=iAuFkw^0%Kvf6oeQNcSmf_N2pir7c zEhOJt?A?#h*jwoKT1Uh*@b~hT^&7Z)S^~(k225rdW!#cI;V0l#LN1kDhdF+#rPFOZ z6uj`$De-(KAlfKY&GXRihMNAi*JeGHIm*FI9XiiA7t-EAwv$wxiMy`HkBeUM?lARr zO{*$63xL3~M!pSIuK>&TaR)goDQIfq6YZM=ScK|S@th{#kz74K0>EP^-6ws+(zE@r zHxDy`G2)fQ6M}{5qP~@4rp2BEg}29{MdK4xcn69pVLM(yi1(4SnlgfgPhMf2(Gf;C zKtTX3Zv*|uHfWIK0RX3pBR^ur@^U_Y!?RM6m=K+Tt>5yX-@*@09?Y3i2Y{7Veni2FsY5j1A#PUoP0HlZ`~r+5 z>m0EkwD?(2>bMu^U;bXiccn0^eI zJt$v(kILdQB|pGyS^qNSAlHTg$+qq@xbX9b`MwBjWKRc0-6P9~=;%gQglE_Eap`rw z?1tk2C_5cvsry4{Zpc;9Cl!|GUz<{{z*XkJGZS1v%0rCsk5t5rHvb{|ds?}ME4r-O zzE+kA+n4-Wu+1ZAL_X3rwL(~viZfbvp$`|wzD#ZNHj9H{oZf;WAN2By8K=B5w3LHh zK=Ip%;OhQKIq#jW*%Um;xW!04uTlv_q?zve3W>{sS>6;M+spoeEpV+%{;wR)(0 zB5bY}$H6sNS*4r^gW^O3o=A^%yZYap4E*{OW?jP0zk6Q3upX_gl+t~r+kMef?$Cef zI|BvOsSs^Ecvq}|`qt=~{Bid9>asEL`&TZPDINfe=K$EEWy}2xC$ufx_M;4t$62)k z+F2+Csp}PxMG>MrA962}CR&v8f}*Rtfl~opEP@GND-c6>)$YmHwPp{QB`-DLg&&jk zGYC~esKYNLVr(n#g9?XQTb|_{?+G(4aA{ky#pMnQ6#<=iYfXNKR7BsD`wXuw45dF& zfs$E#eI|;ipIth7LUB6UD-VS^t#AHoWDoO~SpV_4x@$9hhC@+*!cpV*^=JPnnOT@U z5_(**`BvzM!9J_?K&MA^2nhF%K$t_3mbFqIZ_KJ~rAPQG6rW0u69W5=?x3fPrpnKu zk3|4*sJJsJ`^t?6tCr~jTgVFlyjs|waU%-_&ZMeYM7M1XoiteVaI}K&!e|}Sn7SR*tKGfZm0x;*Jj-85tcI6Juci(~0k+93rqw!=1;IxqooPu#f=X z=plz@4$!u7+y@HYg<$g;5*TYA84(?OH^5r3WktgIK~p&=*4m>jU{UywjW@*5Jv zUkY=*lTf35(S$wm`ZvE5Kw-D{)27esA2%qfq^ErQ>LQ{S%$CjuC2?ymUNK*$5{@~g z?t~_d69WC@309tgziz9MuC3I4pH!Vztdnf%Mw+x(!=WYp!~13PR!PJD%L7}yhl8)8 z|Gzr3jW7MoHZD9M#6JXY{GSVIQ{JUKFQPrf%4@QgV_ zK$G@2&h#9$tpzAb>{CidhM*^BgB>r245R%m94l9-gF=cMTL}seb+?=j8?0QrH`Uw4 zUQl=dHtD!*RR_Z@OXZ4WH&$Bb)16yV&9cgp0k6B7#5ZM29`{nT69$b3NgEn9m}5!d1>^BLjzuSk@pVCB0lP!U}^MfvQf=?5$=i@ zZs=i9xY>V|J3V~xu1z>pmfMEde*q}GcHeNR&xRATwz3jgAFzs*pl}cO+4Rdxo6sJ- zNx>8h?~kCEf)cTG%A<6vLwJuu=H?D|rN0jl6cKG7=<6SBVEZ^>*1?>`D1@2c!IdmF zOBUK{?}cCN>0jk?0G?25^2Qg7)jeOGm z>JOjVC`Dn3rL+L=7?)BV%9PT8ct}!uq0(*iD|;(uZl(9XZ}_M%-&p_PcX98h_&i;( z3mby2@j~-{(Z2qHF$M;QOspoS%;nR3!N2m2C(ZlVl zZe1HYCub%o%CT@rjJ^D;jU%Q6J#gq62YVUM`v5S`PD+`vWd|g+p1nF;Z7V8*f}#U` z1NiqaZLP`N(zeGe6mrGF1UA@xp`;BeaY-Ssz0Cg+_7pICckhrJE1sdBc))q6iO@C;v+?Ini{|AvlvysEbKku$)EvO)hevS<#Wi={bmNr7(tkpyA$jS zo<|z%%aranOL6q^F!9p-Ire~25wGCJn6>;6GObq-CUf?}&?@@LKNenO{==)c%;z6l zq^C#*D!ELLf;Gby`DOG*M_`f98(i{lYl55lO4J1Ma%s#%i7iibdkO5|Rq^v3g59Ha zGpk;{Toz|_@@u|eQxZGDt#qA!qo4RM6U(BC z=z@b29bpSEq)O5?ykV8`LaN#HHTD2GKy^#sIrRsha1VKL=HLd`XQWoi+Y%RNf4sK6 zz7sZ2V0|(LZ%)!D6t=`tT%NHF8-)C*N!@c)55e262KN<$rO3ZC>({Cqp;;fKzJ;yJ?-6exxwNc`kE5~$pyqBRe@9-7M^}&>h$Y+ z{#ZL{UP~^zcHpBQe6p!yF##*5=Qk(8|#|iHh5C#qlX7(F8fP*_q&Pw*{Gwvqnz8zU;nw1 zv07uDx!|0pn?*%YN-ja&lQfoI|K@^{GR+=Z=7~Rc$mn7f@vjdTyA^8`O8hKY)c)pi z3|J|P7-mMfy)?G;QzuOgRdcd2!*#?AjWInwq_K@JR+ei(LHTEn^&-T?qRC((f=!m%3Ku8vA z?;n8$Z6LnI)Yvuna;u0fGuAO}9lvhuH`C#`=B*6)FkvHH`JO zkBbhmkBuOsjT+lZB6f!WxS+uUGz}VZVFhCE7Z(&17!B&T5A9vaxueFeO^Nj=4N}ZY zUSV*HSZ47o273pgqk=+0DY2)$6gwTKS_<|3$=b(9FqQ_G_ptGG6C~%)Y~YLqdK1LIaDJi3#>aT@lbS z+7s(LgkFr$SX%$<5!ikWGQO#)TVJQvOVhjdKY-DGGes!?N(s^denjYo<2_f!5gub#1AsSKQO<1~*{3ON=+0=bAd! z|F(K|3JQoX0Xpocv7_)AnzD4Uv!*shmeJT+D&tUg^FSBBwRfW29w@PCyv7JyUe59y zVpCnWy9c!HlD4I2>NeMH2!f!y!~nwrNU;UKkZ|AVQE;BI!QmKzzM&zb1LZqP_10LJ zDyt`yhKH6HQe2u;=^8uh;%ET=U7TCiTVvN8y;Q6U!2bP!rvf31g2K2B43EJ`lP#qF z*H76nzIg^$tuoQr)zGa(fze$;j8u5>I$|#s1aZN}fmH|Vz|S`(#NXaGE*AfhhPS3E zsZBJtHT4gAgYx{tRFmaCyS;Nk}?%~H@xZv6z ziz4=d5HH3*I4~eCG%z|eA|fUbE^Rm&2WYJ9zue+KWI)m4w`d%%i&1zeyNh9gvM#Nv ziEGy2m*+V_ntGJ=TB9XfGfnOKUyJ%hCS~Ge(Xg5%1An|XJ(2_Tr4gUjyN{6)o delta 48937 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

WNH3 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 { + const Response = globalThis.Response; + const Request = globalThis.Request; + const Headers = globalThis.Headers; + const Blob = globalThis.Blob; + + globalThis.Response = class MyResponse { + get body() { + throw new Error("body getter should not be called"); + } + + get headers() { + throw new Error("headers getter should not be called"); + } + + get status() { + throw new Error("status getter should not be called"); + } + + get statusText() { + throw new Error("statusText getter should not be called"); + } + + get ok() { + throw new Error("ok getter should not be called"); + } + + get url() { + throw new Error("url getter should not be called"); + } + + get type() { + throw new Error("type getter should not be called"); + } + }; + globalThis.Request = class MyRequest {}; + globalThis.Headers = class MyHeaders { + entries() { + throw new Error("entries should not be called"); + } + + get() { + throw new Error("get should not be called"); + } + + has() { + throw new Error("has should not be called"); + } + + keys() { + throw new Error("keys should not be called"); + } + + values() { + throw new Error("values should not be called"); + } + + forEach() { + throw new Error("forEach should not be called"); + } + + [Symbol.iterator]() { + throw new Error("[Symbol.iterator] should not be called"); + } + + [Symbol.toStringTag]() { + throw new Error("[Symbol.toStringTag] should not be called"); + } + + append() { + throw new Error("append should not be called"); + } + }; + globalThis.Blob = class MyBlob {}; + + const http = require("http"); + const server = http.createServer((req, res) => { + res.end("Hello World\n"); + }); + const { promise, resolve, reject } = Promise.withResolvers(); + + server.listen(0, () => { + const { port } = server.address(); + // client request + const req = http + .request(`http://localhost:${port}`, res => { + res + .on("data", data => { + expect(data.toString()).toBe("Hello World\n"); + }) + .on("end", () => { + server.close(); + console.log("closing time"); + }); + }) + .on("error", reject) + .end(); + }); + + server.on("close", () => { + resolve(); + }); + server.on("error", err => { + reject(err); + }); + + try { + await promise; + } finally { + globalThis.Response = Response; + globalThis.Request = Request; + globalThis.Headers = Headers; + globalThis.Blob = Blob; + } +}); diff --git a/test/js/third_party/remix/remix-build/server/index.js b/test/js/third_party/remix/remix-build/server/index.js new file mode 100644 index 0000000000..4e62ccc331 --- /dev/null +++ b/test/js/third_party/remix/remix-build/server/index.js @@ -0,0 +1,262 @@ +import { jsx, jsxs } from "react/jsx-runtime"; +import { PassThrough } from "node:stream"; +import { createReadableStreamFromReadable } from "@remix-run/node"; +import { RemixServer, Outlet, Meta, Links, ScrollRestoration, Scripts } from "@remix-run/react"; +import { isbot } from "isbot"; +import { renderToPipeableStream } from "react-dom/server"; +const ABORT_DELAY = 5e3; +function handleRequest(request, responseStatusCode, responseHeaders, remixContext, loadContext) { + return isbot(request.headers.get("user-agent") || "") + ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) + : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext); +} +function handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + /* @__PURE__ */ jsx(RemixServer, { + context: remixContext, + url: request.url, + abortDelay: ABORT_DELAY, + }), + { + onAllReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + responseHeaders.set("Content-Type", "text/html"); + console.log(responseHeaders); + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + pipe(body); + }, + onShellError(error) { + reject(error); + }, + onError(error) { + responseStatusCode = 500; + if (shellRendered) { + console.error(error); + } + }, + }, + ); + setTimeout(abort, ABORT_DELAY); + }); +} +function handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + /* @__PURE__ */ jsx(RemixServer, { + context: remixContext, + url: request.url, + abortDelay: ABORT_DELAY, + }), + { + onShellReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + responseHeaders.set("Content-Type", "text/html"); + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + pipe(body); + }, + onShellError(error) { + reject(error); + }, + onError(error) { + responseStatusCode = 500; + if (shellRendered) { + console.error(error); + } + }, + }, + ); + setTimeout(abort, ABORT_DELAY); + }); +} +const entryServer = /* @__PURE__ */ Object.freeze( + /* @__PURE__ */ Object.defineProperty( + { + __proto__: null, + default: handleRequest, + }, + Symbol.toStringTag, + { value: "Module" }, + ), +); +function Layout({ children }) { + return /* @__PURE__ */ jsxs("html", { + lang: "en", + children: [ + /* @__PURE__ */ jsxs("head", { + children: [ + /* @__PURE__ */ jsx("meta", { charSet: "utf-8" }), + /* @__PURE__ */ jsx("meta", { + name: "viewport", + content: "width=device-width, initial-scale=1", + }), + /* @__PURE__ */ jsx(Meta, {}), + /* @__PURE__ */ jsx(Links, {}), + ], + }), + /* @__PURE__ */ jsxs("body", { + children: [children, /* @__PURE__ */ jsx(ScrollRestoration, {}), /* @__PURE__ */ jsx(Scripts, {})], + }), + ], + }); +} +function App() { + return /* @__PURE__ */ jsx(Outlet, {}); +} +const route0 = /* @__PURE__ */ Object.freeze( + /* @__PURE__ */ Object.defineProperty( + { + __proto__: null, + Layout, + default: App, + }, + Symbol.toStringTag, + { value: "Module" }, + ), +); +const meta = () => { + return [{ title: "New Remix App" }, { name: "description", content: "Welcome to Remix!" }]; +}; +function Index() { + return /* @__PURE__ */ jsxs("div", { + className: "font-sans p-4", + children: [ + /* @__PURE__ */ jsx("h1", { + className: "text-3xl", + children: "Welcome to Remix", + }), + /* @__PURE__ */ jsxs("ul", { + className: "list-disc mt-4 pl-6 space-y-2", + children: [ + /* @__PURE__ */ jsx("li", { + children: /* @__PURE__ */ jsx("a", { + className: "text-blue-700 underline visited:text-purple-900", + target: "_blank", + href: "https://remix.run/start/quickstart", + rel: "noreferrer", + children: "5m Quick Start", + }), + }), + /* @__PURE__ */ jsx("li", { + children: /* @__PURE__ */ jsx("a", { + className: "text-blue-700 underline visited:text-purple-900", + target: "_blank", + href: "https://remix.run/start/tutorial", + rel: "noreferrer", + children: "30m Tutorial", + }), + }), + /* @__PURE__ */ jsx("li", { + children: /* @__PURE__ */ jsx("a", { + className: "text-blue-700 underline visited:text-purple-900", + target: "_blank", + href: "https://remix.run/docs", + rel: "noreferrer", + children: "Remix Docs", + }), + }), + ], + }), + ], + }); +} +const route1 = /* @__PURE__ */ Object.freeze( + /* @__PURE__ */ Object.defineProperty( + { + __proto__: null, + default: Index, + meta, + }, + Symbol.toStringTag, + { value: "Module" }, + ), +); +const serverManifest = { + entry: { + module: "/assets/entry.client-ER-smVHW.js", + imports: ["/assets/jsx-runtime-56DGgGmo.js", "/assets/components-BI_hnQlH.js"], + css: [], + }, + routes: { + root: { + id: "root", + parentId: void 0, + path: "", + index: void 0, + caseSensitive: void 0, + hasAction: false, + hasLoader: false, + hasClientAction: false, + hasClientLoader: false, + hasErrorBoundary: false, + module: "/assets/root-CBMuz_vA.js", + imports: ["/assets/jsx-runtime-56DGgGmo.js", "/assets/components-BI_hnQlH.js"], + css: ["/assets/root-BFUH26ow.css"], + }, + "routes/_index": { + id: "routes/_index", + parentId: "root", + path: void 0, + index: true, + caseSensitive: void 0, + hasAction: false, + hasLoader: false, + hasClientAction: false, + hasClientLoader: false, + hasErrorBoundary: false, + module: "/assets/_index-B6hwyHK-.js", + imports: ["/assets/jsx-runtime-56DGgGmo.js"], + css: [], + }, + }, + url: "/assets/manifest-c2e02a52.js", + version: "c2e02a52", +}; +const mode = "production"; +const assetsBuildDirectory = "build/client"; +const basename = "/"; +const future = { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + unstable_singleFetch: false, + unstable_fogOfWar: false, +}; +const isSpaMode = false; +const publicPath = "/"; +const entry = { module: entryServer }; +const routes = { + root: { + id: "root", + parentId: void 0, + path: "", + index: void 0, + caseSensitive: void 0, + module: route0, + }, + "routes/_index": { + id: "routes/_index", + parentId: "root", + path: void 0, + index: true, + caseSensitive: void 0, + module: route1, + }, +}; +export { serverManifest as assets, assetsBuildDirectory, basename, entry, future, isSpaMode, mode, publicPath, routes }; diff --git a/test/js/third_party/remix/remix.test.ts b/test/js/third_party/remix/remix.test.ts new file mode 100644 index 0000000000..16667e0f11 --- /dev/null +++ b/test/js/third_party/remix/remix.test.ts @@ -0,0 +1,44 @@ +import { describe, it, expect, test } from "bun:test"; +test("remix works", async () => { + process.env.PORT = "0"; + process.exitCode = 1; + process.env.NODE_ENV = "production"; + process.env.HOST = "localhost"; + process.argv = [process.argv[0], ".", require("path").join(__dirname, "remix-build", "server", "index.js")]; + const http = require("node:http"); + const originalListen = http.Server.prototype.listen; + let { promise, resolve, reject } = Promise.withResolvers(); + http.Server.prototype.listen = function listen(...args) { + setTimeout(() => { + resolve(this.address()); + }, 10); + return originalListen.apply(this, args); + }; + + require("@remix-run/serve/dist/cli.js"); + + // Wait long enough for the server's setTimeout to run. + await Bun.sleep(10); + + const port = (await promise).port; + + ({ promise, resolve, reject } = Promise.withResolvers()); + let chunks = []; + const req = http + .request(`http://localhost:${port}`, res => { + res + .on("data", data => { + chunks.push(data); + }) + .on("end", () => { + resolve(); + }) + .on("error", reject); + }) + .end(); + + await promise; + const data = Buffer.concat(chunks).toString(); + expect(data).toContain("Remix Docs"); + process.exitCode = 0; +}); diff --git a/test/package.json b/test/package.json index e0a9a275a3..96c4bd14c1 100644 --- a/test/package.json +++ b/test/package.json @@ -11,6 +11,8 @@ "@grpc/proto-loader": "0.7.10", "@napi-rs/canvas": "0.1.47", "@prisma/client": "5.8.0", + "@remix-run/react": "2.10.3", + "@remix-run/serve": "2.10.3", "@resvg/resvg-js": "2.4.1", "@swc/core": "1.3.38", "@types/ws": "8.5.10", @@ -23,6 +25,7 @@ "express": "4.18.2", "fast-glob": "3.3.1", "iconv-lite": "0.6.3", + "isbot": "5.1.13", "jest-extended": "4.0.0", "jsonwebtoken": "9.0.2", "jws": "4.0.0",