| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187 |
- // include: shell.js
- // include: minimum_runtime_check.js
- (function() {
- // "30.0.0" -> 300000
- function humanReadableVersionToPacked(str) {
- str = str.split("-")[0];
- // Remove any trailing part from e.g. "12.53.3-alpha"
- var vers = str.split(".").slice(0, 3);
- while (vers.length < 3) vers.push("00");
- vers = vers.map((n, i, arr) => n.padStart(2, "0"));
- return vers.join("");
- }
- // 300000 -> "30.0.0"
- var packedVersionToHumanReadable = n => [ n / 1e4 | 0, (n / 100 | 0) % 100, n % 100 ].join(".");
- var TARGET_NOT_SUPPORTED = 2147483647;
- // Note: We use a typeof check here instead of optional chaining using
- // globalThis because older browsers might not have globalThis defined.
- var currentNodeVersion = typeof process !== "undefined" && process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
- if (currentNodeVersion < 180300) {
- throw new Error(`This emscripten-generated code requires node v${packedVersionToHumanReadable(180300)} (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
- }
- var userAgent = typeof navigator !== "undefined" && navigator.userAgent;
- if (!userAgent) {
- return;
- }
- var currentSafariVersion = userAgent.includes("Safari/") && !userAgent.includes("Chrome/") && userAgent.match(/Version\/(\d+\.?\d*\.?\d*)/) ? humanReadableVersionToPacked(userAgent.match(/Version\/(\d+\.?\d*\.?\d*)/)[1]) : TARGET_NOT_SUPPORTED;
- if (currentSafariVersion < 15e4) {
- throw new Error(`This emscripten-generated code requires Safari v${packedVersionToHumanReadable(15e4)} (detected v${currentSafariVersion})`);
- }
- var currentFirefoxVersion = userAgent.match(/Firefox\/(\d+(?:\.\d+)?)/) ? parseFloat(userAgent.match(/Firefox\/(\d+(?:\.\d+)?)/)[1]) : TARGET_NOT_SUPPORTED;
- if (currentFirefoxVersion < 79) {
- throw new Error(`This emscripten-generated code requires Firefox v79 (detected v${currentFirefoxVersion})`);
- }
- var currentChromeVersion = userAgent.match(/Chrome\/(\d+(?:\.\d+)?)/) ? parseFloat(userAgent.match(/Chrome\/(\d+(?:\.\d+)?)/)[1]) : TARGET_NOT_SUPPORTED;
- if (currentChromeVersion < 85) {
- throw new Error(`This emscripten-generated code requires Chrome v85 (detected v${currentChromeVersion})`);
- }
- })();
- // end include: minimum_runtime_check.js
- // The Module object: Our interface to the outside world. We import
- // and export values on it. There are various ways Module can be used:
- // 1. Not defined. We create it here
- // 2. A function parameter, function(moduleArg) => Promise<Module>
- // 3. pre-run appended it, var Module = {}; ..generated code..
- // 4. External script tag defines var Module.
- // We need to check if Module already exists (e.g. case 3 above).
- // Substitution will be replaced with actual code on later stage of the build,
- // this way Closure Compiler will not mangle it (e.g. case 4. above).
- // Note that if you want to run closure, and also to use Module
- // after the generated code, you will need to define var Module = {};
- // before the code. Then that object will be used in the code, and you
- // can continue to use Module afterwards as well.
- var Module = typeof Module != "undefined" ? Module : {};
- // Determine the runtime environment we are in. You can customize this by
- // setting the ENVIRONMENT setting at compile time (see settings.js).
- // Attempt to auto-detect the environment
- var ENVIRONMENT_IS_WEB = !!globalThis.window;
- var ENVIRONMENT_IS_WORKER = !!globalThis.WorkerGlobalScope;
- // N.b. Electron.js environment is simultaneously a NODE-environment, but
- // also a web environment.
- var ENVIRONMENT_IS_NODE = globalThis.process?.versions?.node && globalThis.process?.type != "renderer";
- var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
- // Three configurations we can be running in:
- // 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false)
- // 2) We could be the application main() running directly in a worker. (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false)
- // 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true)
- // The way we signal to a worker that it is hosting a pthread is to construct
- // it with a specific name.
- var ENVIRONMENT_IS_PTHREAD = ENVIRONMENT_IS_WORKER && globalThis.name?.startsWith("em-pthread");
- if (ENVIRONMENT_IS_NODE) {
- var worker_threads = require("node:worker_threads");
- globalThis.Worker = worker_threads.Worker;
- ENVIRONMENT_IS_WORKER = !worker_threads.isMainThread;
- // Under node we set `workerData` to `em-pthread` to signal that the worker
- // is hosting a pthread.
- ENVIRONMENT_IS_PTHREAD = ENVIRONMENT_IS_WORKER && worker_threads.workerData == "em-pthread";
- }
- // --pre-jses are emitted after the Module integration code, so that they can
- // refer to Module (if they choose; they can also define Module)
- // include: /tmp/tmpzje_h4f0.js
- if (!Module["expectedDataFileDownloads"]) Module["expectedDataFileDownloads"] = 0;
- Module["expectedDataFileDownloads"]++;
- (() => {
- // Do not attempt to redownload the virtual filesystem data when in a pthread or a Wasm Worker context.
- var isPthread = typeof ENVIRONMENT_IS_PTHREAD != "undefined" && ENVIRONMENT_IS_PTHREAD;
- var isWasmWorker = typeof ENVIRONMENT_IS_WASM_WORKER != "undefined" && ENVIRONMENT_IS_WASM_WORKER;
- if (isPthread || isWasmWorker) return;
- var isNode = globalThis.process && globalThis.process.versions && globalThis.process.versions.node && globalThis.process.type != "renderer";
- async function loadPackage(metadata) {
- var PACKAGE_PATH = "";
- if (typeof window === "object") {
- PACKAGE_PATH = window["encodeURIComponent"](window.location.pathname.substring(0, window.location.pathname.lastIndexOf("/")) + "/");
- } else if (typeof process === "undefined" && typeof location !== "undefined") {
- // web worker
- PACKAGE_PATH = encodeURIComponent(location.pathname.substring(0, location.pathname.lastIndexOf("/")) + "/");
- }
- var PACKAGE_NAME = "nimсity.data";
- var REMOTE_PACKAGE_BASE = "nimсity.data";
- var REMOTE_PACKAGE_NAME = Module["locateFile"] ? Module["locateFile"](REMOTE_PACKAGE_BASE, "") : REMOTE_PACKAGE_BASE;
- var REMOTE_PACKAGE_SIZE = metadata["remote_package_size"];
- async function fetchRemotePackage(packageName, packageSize) {
- if (isNode) {
- var contents = require("fs").readFileSync(packageName);
- return new Uint8Array(contents).buffer;
- }
- if (!Module["dataFileDownloads"]) Module["dataFileDownloads"] = {};
- try {
- var response = await fetch(packageName);
- } catch (e) {
- throw new Error(`Network Error: ${packageName}`, {
- e
- });
- }
- if (!response.ok) {
- throw new Error(`${response.status}: ${response.url}`);
- }
- const chunks = [];
- const headers = response.headers;
- const total = Number(headers.get("Content-Length") || packageSize);
- let loaded = 0;
- Module["setStatus"] && Module["setStatus"]("Downloading data...");
- const reader = response.body.getReader();
- while (1) {
- var {done, value} = await reader.read();
- if (done) break;
- chunks.push(value);
- loaded += value.length;
- Module["dataFileDownloads"][packageName] = {
- loaded,
- total
- };
- let totalLoaded = 0;
- let totalSize = 0;
- for (const download of Object.values(Module["dataFileDownloads"])) {
- totalLoaded += download.loaded;
- totalSize += download.total;
- }
- Module["setStatus"] && Module["setStatus"](`Downloading data... (${totalLoaded}/${totalSize})`);
- }
- const packageData = new Uint8Array(chunks.map(c => c.length).reduce((a, b) => a + b, 0));
- let offset = 0;
- for (const chunk of chunks) {
- packageData.set(chunk, offset);
- offset += chunk.length;
- }
- return packageData.buffer;
- }
- var fetchPromise;
- var fetched = Module["getPreloadedPackage"] && Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE);
- if (!fetched) {
- // Note that we don't use await here because we want to execute the
- // the rest of this function immediately.
- fetchPromise = fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE);
- }
- async function runWithFS(Module) {
- function assert(check, msg) {
- if (!check) throw new Error(msg);
- }
- Module["FS_createPath"]("/", "assets", true, true);
- async function processPackageData(arrayBuffer) {
- assert(arrayBuffer, "Loading data file failed.");
- assert(arrayBuffer.constructor.name === ArrayBuffer.name, "bad input to processPackageData " + arrayBuffer.constructor.name);
- var byteArray = new Uint8Array(arrayBuffer);
- var curr;
- // Reuse the bytearray from the XHR as the source for file reads.
- for (var file of metadata["files"]) {
- var name = file["filename"];
- var data = byteArray.subarray(file["start"], file["end"]);
- // canOwn this data in the filesystem, it is a slice into the heap that will never change
- Module["FS_createDataFile"](name, null, data, true, true, true);
- }
- Module["removeRunDependency"]("datafile_nimсity.data");
- }
- Module["addRunDependency"]("datafile_nimсity.data");
- if (!Module["preloadResults"]) Module["preloadResults"] = {};
- Module["preloadResults"][PACKAGE_NAME] = {
- fromCache: false
- };
- if (!fetched) {
- fetched = await fetchPromise;
- }
- await processPackageData(fetched);
- }
- // Detect whether the module JS file has already been loaded.
- if (Module["FS_createPath"]) {
- runWithFS(Module);
- } else {
- if (!Module["preRun"]) Module["preRun"] = [];
- Module["preRun"].push(runWithFS);
- }
- }
- loadPackage({
- "files": [ {
- "filename": "/assets/font.png",
- "start": 0,
- "end": 421
- }, {
- "filename": "/assets/font.png.dat",
- "start": 421,
- "end": 515
- }, {
- "filename": "/assets/icon.png",
- "start": 515,
- "end": 861
- } ],
- "remote_package_size": 861
- });
- })();
- // end include: /tmp/tmpzje_h4f0.js
- // include: /tmp/tmpb7xjyrz2.js
- // All the pre-js content up to here must remain later on, we need to run
- // it.
- if ((typeof ENVIRONMENT_IS_WASM_WORKER != "undefined" && ENVIRONMENT_IS_WASM_WORKER) || (typeof ENVIRONMENT_IS_PTHREAD != "undefined" && ENVIRONMENT_IS_PTHREAD) || (typeof ENVIRONMENT_IS_AUDIO_WORKLET != "undefined" && ENVIRONMENT_IS_AUDIO_WORKLET)) Module["preRun"] = [];
- var necessaryPreJSTasks = Module["preRun"].slice();
- // end include: /tmp/tmpb7xjyrz2.js
- // include: /tmp/tmpna887fkc.js
- if (!Module["preRun"]) throw "Module.preRun should exist because file support used it; did a pre-js delete it?";
- necessaryPreJSTasks.forEach(task => {
- if (Module["preRun"].indexOf(task) < 0) throw "All preRun tasks that exist before user pre-js code should remain after; did you replace Module or modify Module.preRun?";
- });
- // end include: /tmp/tmpna887fkc.js
- var programArgs = [];
- var thisProgram = "./this.program";
- var quit_ = (status, toThrow) => {
- throw toThrow;
- };
- // In MODULARIZE mode _scriptName needs to be captured already at the very top of the page immediately when the page is parsed, so it is generated there
- // before the page load. In non-MODULARIZE modes generate it here.
- var _scriptName = globalThis.document?.currentScript?.src;
- if (typeof __filename != "undefined") {
- // Node
- _scriptName = __filename;
- } else if (ENVIRONMENT_IS_WORKER) {
- _scriptName = self.location.href;
- }
- // `/` should be present at the end if `scriptDirectory` is not empty
- var scriptDirectory = "";
- function locateFile(path) {
- if (Module["locateFile"]) {
- return Module["locateFile"](path, scriptDirectory);
- }
- return scriptDirectory + path;
- }
- // Hooks that are implemented differently in different runtime environments.
- var readAsync, readBinary;
- if (ENVIRONMENT_IS_NODE) {
- const isNode = globalThis.process?.versions?.node && globalThis.process?.type != "renderer";
- if (!isNode) throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");
- // These modules will usually be used on Node.js. Load them eagerly to avoid
- // the complexity of lazy-loading.
- var fs = require("node:fs");
- scriptDirectory = __dirname + "/";
- // include: node_shell_read.js
- readBinary = filename => {
- // We need to re-wrap `file://` strings to URLs.
- filename = isFileURI(filename) ? new URL(filename) : filename;
- var ret = fs.readFileSync(filename);
- assert(Buffer.isBuffer(ret));
- return ret;
- };
- readAsync = async (filename, binary = true) => {
- // See the comment in the `readBinary` function.
- filename = isFileURI(filename) ? new URL(filename) : filename;
- var ret = fs.readFileSync(filename, binary ? undefined : "utf8");
- assert(binary ? Buffer.isBuffer(ret) : typeof ret == "string");
- return ret;
- };
- // end include: node_shell_read.js
- if (process.argv.length > 1) {
- thisProgram = process.argv[1].replace(/\\/g, "/");
- }
- programArgs = process.argv.slice(2);
- // MODULARIZE will export the module in the proper place outside, we don't need to export here
- if (typeof module != "undefined") {
- module["exports"] = Module;
- }
- quit_ = (status, toThrow) => {
- process.exitCode = status;
- throw toThrow;
- };
- } else if (ENVIRONMENT_IS_SHELL) {} else // Note that this includes Node.js workers when relevant (pthreads is enabled).
- // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
- // ENVIRONMENT_IS_NODE.
- if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
- try {
- scriptDirectory = new URL(".", _scriptName).href;
- } catch {}
- if (!(globalThis.window || globalThis.WorkerGlobalScope)) throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");
- // Differentiate the Web Worker from the Node Worker case, as reading must
- // be done differently.
- if (!ENVIRONMENT_IS_NODE) {
- // include: web_or_worker_shell_read.js
- if (ENVIRONMENT_IS_WORKER) {
- readBinary = url => {
- var xhr = new XMLHttpRequest;
- xhr.open("GET", url, false);
- xhr.responseType = "arraybuffer";
- xhr.send(null);
- return new Uint8Array(/** @type{!ArrayBuffer} */ (xhr.response));
- };
- }
- readAsync = async url => {
- // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
- // See https://github.com/github/fetch/pull/92#issuecomment-140665932
- // Cordova or Electron apps are typically loaded from a file:// url.
- // So use XHR on webview if URL is a file URL.
- if (isFileURI(url)) {
- return new Promise((resolve, reject) => {
- var xhr = new XMLHttpRequest;
- xhr.open("GET", url, true);
- xhr.responseType = "arraybuffer";
- xhr.onload = () => {
- if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
- // file URLs can return 0
- resolve(xhr.response);
- return;
- }
- reject(xhr.status);
- };
- xhr.onerror = reject;
- xhr.send(null);
- });
- }
- var response = await fetch(url, {
- credentials: "same-origin"
- });
- if (response.ok) {
- return response.arrayBuffer();
- }
- throw new Error(response.status + " : " + response.url);
- };
- }
- } else {
- throw new Error("environment detection error");
- }
- // Set up the out() and err() hooks, which are how we can print to stdout or
- // stderr, respectively.
- // Normally just binding console.log/console.error here works fine, but
- // under node (with workers) we see missing/out-of-order messages so route
- // directly to stdout and stderr.
- // See https://github.com/emscripten-core/emscripten/issues/14804
- var defaultPrint = console.log.bind(console);
- var defaultPrintErr = console.error.bind(console);
- if (ENVIRONMENT_IS_NODE) {
- var utils = require("node:util");
- var stringify = a => typeof a == "object" ? utils.inspect(a) : a;
- defaultPrint = (...args) => fs.writeSync(1, args.map(stringify).join(" ") + "\n");
- defaultPrintErr = (...args) => fs.writeSync(2, args.map(stringify).join(" ") + "\n");
- }
- var out = defaultPrint;
- var err = defaultPrintErr;
- var PROXYFS = "PROXYFS is no longer included by default; build with -lproxyfs.js";
- var WORKERFS = "WORKERFS is no longer included by default; build with -lworkerfs.js";
- var FETCHFS = "FETCHFS is no longer included by default; build with -lfetchfs.js";
- var ICASEFS = "ICASEFS is no longer included by default; build with -licasefs.js";
- var JSFILEFS = "JSFILEFS is no longer included by default; build with -ljsfilefs.js";
- var OPFS = "OPFS is no longer included by default; build with -lopfs.js";
- var NODEFS = "NODEFS is no longer included by default; build with -lnodefs.js";
- // perform assertions in shell.js after we set up out() and err(), as otherwise
- // if an assertion fails it cannot print the message
- assert(ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER || ENVIRONMENT_IS_NODE, "pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");
- assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time (add `shell` to `-sENVIRONMENT` to enable)");
- // end include: shell.js
- // include: preamble.js
- // === Preamble library stuff ===
- // Documentation for the public APIs defined in this file must be updated in:
- // site/source/docs/api_reference/preamble.js.rst
- // A prebuilt local version of the documentation is available at:
- // site/build/text/docs/api_reference/preamble.js.txt
- // You can also build docs locally as HTML or other formats in site/
- // An online HTML version (which may be of a different version of Emscripten)
- // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
- var wasmBinary;
- if (!globalThis.WebAssembly) {
- err("no native wasm support detected");
- }
- // Wasm globals
- // For sending to workers.
- var wasmModule;
- //========================================
- // Runtime essentials
- //========================================
- // whether we are quitting the application. no code should run after this.
- // set in exit() and abort()
- var ABORT = false;
- // set by exit() and abort(). Passed to 'onExit' handler.
- // NOTE: This is also used as the process return code in shell environments
- // but only when noExitRuntime is false.
- var EXITSTATUS;
- // In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we
- // don't define it at all in release modes. This matches the behaviour of
- // MINIMAL_RUNTIME.
- // TODO(sbc): Make this the default even without STRICT enabled.
- /** @type {function(*, string=)} */ function assert(condition, text) {
- if (!condition) {
- abort("Assertion failed" + (text ? ": " + text : ""));
- }
- }
- // We used to include malloc/free by default in the past. Show a helpful error in
- // builds with assertions.
- /**
- * Indicates whether filename is delivered via file protocol (as opposed to http/https)
- * @noinline
- */ var isFileURI = filename => filename.startsWith("file://");
- // include: runtime_common.js
- // include: runtime_stack_check.js
- // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
- function writeStackCookie() {
- var max = _emscripten_stack_get_end();
- assert((max & 3) == 0);
- // If the stack ends at address zero we write our cookies 4 bytes into the
- // stack. This prevents interference with SAFE_HEAP and ASAN which also
- // monitor writes to address zero.
- if (max == 0) {
- max += 4;
- }
- // The stack grow downwards towards _emscripten_stack_get_end.
- // We write cookies to the final two words in the stack and detect if they are
- // ever overwritten.
- (growMemViews(), HEAPU32)[((max) >> 2)] = 34821223;
- (growMemViews(), HEAPU32)[(((max) + (4)) >> 2)] = 2310721022;
- // Also test the global address 0 for integrity.
- (growMemViews(), HEAPU32)[((0) >> 2)] = 1668509029;
- }
- function checkStackCookie() {
- if (ABORT) return;
- var max = _emscripten_stack_get_end();
- // See writeStackCookie().
- if (max == 0) {
- max += 4;
- }
- var cookie1 = (growMemViews(), HEAPU32)[((max) >> 2)];
- var cookie2 = (growMemViews(), HEAPU32)[(((max) + (4)) >> 2)];
- if (cookie1 != 34821223 || cookie2 != 2310721022) {
- abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
- }
- // Also test the global address 0 for integrity.
- if ((growMemViews(), HEAPU32)[((0) >> 2)] != 1668509029) {
- abort("Runtime error: The application has corrupted its heap memory area (address zero)!");
- }
- }
- // end include: runtime_stack_check.js
- // include: runtime_exceptions.js
- // Base Emscripten EH error class
- class EmscriptenEH {}
- class EmscriptenSjLj extends EmscriptenEH {}
- // end include: runtime_exceptions.js
- // include: runtime_debug.js
- var runtimeDebug = true;
- // Switch to false at runtime to disable logging at the right times
- // Used by XXXXX_DEBUG settings to output debug messages.
- function dbg(...args) {
- if (!runtimeDebug && typeof runtimeDebug != "undefined") return;
- // Avoid using the console for debugging in multi-threaded node applications
- // See https://github.com/emscripten-core/emscripten/issues/14804
- if (ENVIRONMENT_IS_NODE) {
- // TODO(sbc): Unify with err/out implementation in shell.sh.
- var fs = require("node:fs");
- var utils = require("node:util");
- function stringify(a) {
- switch (typeof a) {
- case "object":
- return utils.inspect(a);
- case "undefined":
- return "undefined";
- }
- return a;
- }
- fs.writeSync(2, args.map(stringify).join(" ") + "\n");
- } else // TODO(sbc): Make this configurable somehow. Its not always convenient for
- // logging to show up as warnings.
- console.warn(...args);
- }
- // Endianness check
- (() => {
- var h16 = new Int16Array(1);
- var h8 = new Int8Array(h16.buffer);
- h16[0] = 25459;
- if (h8[0] !== 115 || h8[1] !== 99) abort("Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)");
- })();
- function consumedModuleProp(prop) {
- var value = Module[prop];
- var msg = `Attempt to modify \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`;
- if (Array.isArray(value)) {
- value = new Proxy(value, {
- set(target, key, val) {
- abort(msg);
- return false;
- },
- defineProperty(target, key, descriptor) {
- abort(msg);
- return false;
- },
- deleteProperty(target, key) {
- abort(msg);
- return false;
- }
- });
- }
- Object.defineProperty(Module, prop, {
- configurable: true,
- get() {
- return value;
- },
- set() {
- abort(msg);
- }
- });
- }
- function makeInvalidEarlyAccess(name) {
- return () => assert(false, `call to '${name}' via reference taken before Wasm module initialization`);
- }
- function ignoredModuleProp(prop) {
- if (Object.getOwnPropertyDescriptor(Module, prop)) {
- abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`);
- }
- }
- // forcing the filesystem exports a few things by default
- function isExportedByForceFilesystem(name) {
- return name === "FS_createPath" || name === "FS_createDataFile" || name === "FS_createPreloadedFile" || name === "FS_preloadFile" || name === "FS_unlink" || name === "addRunDependency" || // The old FS has some functionality that WasmFS lacks.
- name === "FS_createLazyFile" || name === "FS_createDevice" || name === "removeRunDependency";
- }
- /**
- * Intercept access to a symbols in the global symbol. This enables us to give
- * informative warnings/errors when folks attempt to use symbols they did not
- * include in their build, or no symbols that no longer exist.
- *
- * We don't define this in MODULARIZE mode since in that mode emscripten symbols
- * are never placed in the global scope.
- */ function hookGlobalSymbolAccess(sym, func) {
- if (!Object.getOwnPropertyDescriptor(globalThis, sym)) {
- Object.defineProperty(globalThis, sym, {
- configurable: true,
- get() {
- func();
- return undefined;
- }
- });
- }
- }
- function missingGlobal(sym, msg) {
- hookGlobalSymbolAccess(sym, () => {
- warnOnce(`\`${sym}\` is no longer defined by emscripten. ${msg}`);
- });
- }
- missingGlobal("buffer", "Please use HEAP8.buffer or wasmMemory.buffer");
- missingGlobal("asm", "Please use wasmExports instead");
- function missingLibrarySymbol(sym) {
- hookGlobalSymbolAccess(sym, () => {
- // Can't `abort()` here because it would break code that does runtime
- // checks. e.g. `if (typeof SDL === 'undefined')`.
- var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;
- // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in
- // library.js, which means $name for a JS name with no prefix, or name
- // for a JS name like _name.
- var librarySymbol = sym;
- if (!librarySymbol.startsWith("_")) {
- librarySymbol = "$" + sym;
- }
- msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;
- if (isExportedByForceFilesystem(sym)) {
- msg += ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you";
- }
- warnOnce(msg);
- });
- // Any symbol that is not included from the JS library is also (by definition)
- // not exported on the Module object.
- unexportedRuntimeSymbol(sym);
- }
- function unexportedRuntimeSymbol(sym) {
- if (ENVIRONMENT_IS_PTHREAD) {
- return;
- }
- if (!Object.getOwnPropertyDescriptor(Module, sym)) {
- Object.defineProperty(Module, sym, {
- configurable: true,
- get() {
- var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;
- if (isExportedByForceFilesystem(sym)) {
- msg += ". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you";
- }
- abort(msg);
- }
- });
- }
- }
- /**
- * Override `err`/`out`/`dbg` to report thread / worker information
- */ function initWorkerLogging() {
- function getLogPrefix() {
- var t = 0;
- if (runtimeInitialized && typeof _pthread_self != "undefined") {
- t = _pthread_self();
- }
- return `w:${workerID},t:${ptrToString(t)}:`;
- }
- // Prefix all dbg() messages with the calling thread info.
- var origDbg = dbg;
- dbg = (...args) => origDbg(getLogPrefix(), ...args);
- }
- initWorkerLogging();
- // end include: runtime_debug.js
- // Support for growable heap + pthreads, where the buffer may change, so JS views
- // must be updated.
- function growMemViews() {
- // `updateMemoryViews` updates all the views simultaneously, so it's enough to check any of them.
- if (wasmMemory.buffer != HEAP8.buffer) {
- updateMemoryViews();
- }
- }
- if (ENVIRONMENT_IS_NODE && (ENVIRONMENT_IS_PTHREAD)) {
- // Create as web-worker-like an environment as we can.
- globalThis.self = globalThis;
- var parentPort = worker_threads.parentPort;
- // Deno and Bun already have `postMessage` defined on the global scope and
- // deliver messages to `globalThis.onmessage`, so we must not duplicate that
- // behavior here if `postMessage` is already present.
- if (!globalThis.postMessage) {
- parentPort.on("message", msg => globalThis.onmessage?.({
- data: msg
- }));
- globalThis.postMessage = msg => parentPort.postMessage(msg);
- }
- // Node.js Workers do not pass postMessage()s and uncaught exception events to the parent
- // thread necessarily in the same order where they were generated in sequential program order.
- // See https://github.com/nodejs/node/issues/59617
- // To remedy this, capture all uncaughtExceptions in the Worker, and sequentialize those over
- // to the same postMessage pipe that other messages use.
- process.on("uncaughtException", err => {
- postMessage({
- cmd: 8,
- error: err
- });
- // Also shut down the Worker to match the same semantics as if this uncaughtException
- // handler was not registered.
- // (n.b. this will not shut down the whole Node.js app process, but just the Worker)
- process.exit(1);
- });
- }
- // include: runtime_pthread.js
- // Pthread Web Worker handling code.
- // This code runs only on pthread web workers and handles pthread setup
- // and communication with the main thread via postMessage.
- // Unique ID of the current pthread worker (zero on non-pthread-workers
- // including the main thread).
- var workerID = 0;
- var startWorker;
- if (ENVIRONMENT_IS_PTHREAD) {
- // Thread-local guard variable for one-time init of the JS state
- var initializedJS = false;
- // Turn unhandled rejected promises into errors so that the main thread will be
- // notified about them.
- self.onunhandledrejection = e => {
- throw e.reason || e;
- };
- function handleMessage(e) {
- try {
- var msgData = e.data;
- //dbg('msgData: ' + Object.keys(msgData));
- var cmd = msgData.cmd;
- if (cmd == 1) {
- // Preload command that is called once per worker to parse and load the Emscripten code.
- workerID = msgData.workerID;
- // Until we initialize the runtime, queue up any further incoming messages.
- let messageQueue = [];
- self.onmessage = e => messageQueue.push(e);
- // And add a callback for when the runtime is initialized.
- startWorker = () => {
- // Notify the main thread that this thread has loaded.
- postMessage({
- cmd: 3
- });
- // Process any messages that were queued before the thread was ready.
- for (let msg of messageQueue) {
- handleMessage(msg);
- }
- // Restore the real message handler.
- self.onmessage = handleMessage;
- };
- // Use `const` here to ensure that the variable is scoped only to
- // that iteration, allowing safe reference from a closure.
- for (const handler of msgData.handlers) {
- // If the main module has a handler for a certain event, but no
- // handler exists on the pthread worker, then proxy that handler
- // back to the main thread.
- if (!Module[handler] || Module[handler].proxy) {
- Module[handler] = (...args) => {
- postMessage({
- cmd: 9,
- handler,
- args
- });
- };
- // Rebind the out / err handlers if needed
- if (handler == "print") out = Module[handler];
- if (handler == "printErr") err = Module[handler];
- }
- }
- wasmMemory = msgData.wasmMemory;
- updateMemoryViews();
- wasmModule = msgData.wasmModule;
- createWasm();
- run();
- } else if (cmd == 2) {
- assert(msgData.pthread_ptr);
- assert(wasmMemory, "CMD_RUN received before CMD_LOAD");
- // Call inside JS module to set up the stack frame for this pthread in JS module scope.
- // This needs to be the first thing that we do, as we cannot call to any C/C++ functions
- // until the thread stack is initialized.
- establishStackSpace(msgData.pthread_ptr);
- // Pass the thread address to wasm to store it for fast access.
- __emscripten_thread_init(msgData.pthread_ptr, /*is_main=*/ 0, /*is_runtime=*/ 0, /*can_block=*/ 1, 0, 0);
- PThread.threadInitTLS();
- // Await mailbox notifications with `Atomics.waitAsync` so we can start
- // using the fast `Atomics.notify` notification path.
- __emscripten_thread_mailbox_await(msgData.pthread_ptr);
- if (!initializedJS) {
- initializedJS = true;
- }
- try {
- invokeEntryPoint(msgData.start_routine, msgData.arg);
- } catch (ex) {
- if (ex != "unwind") {
- // The pthread "crashed". Do not call `_emscripten_thread_exit` (which
- // would make this thread joinable). Instead, re-throw the exception
- // and let the top level handler propagate it back to the main thread.
- throw ex;
- }
- }
- } else if (cmd == 4) {
- if (initializedJS) {
- checkMailbox();
- }
- } else if (cmd) {
- // The received message looks like something that should be handled by this message
- // handler, (since there is a cmd field present), but is not one of the
- // recognized commands:
- err(`worker: received unknown command ${cmd}`);
- err(msgData);
- }
- } catch (ex) {
- err(`worker: onmessage() captured an uncaught exception: ${ex}`);
- if (ex?.stack) err(ex.stack);
- if (runtimeInitialized) __emscripten_thread_crashed();
- throw ex;
- }
- }
- self.onmessage = handleMessage;
- }
- // ENVIRONMENT_IS_PTHREAD
- // end include: runtime_pthread.js
- // Memory management
- var runtimeInitialized = false;
- // When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm
- // memory to ArrayBuffer requires some additional logic.
- function getMemoryBuffer() {
- // Deserializing a growable SharedArrayBuffer was broken until Firefox 154
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=2021136
- var firefoxMatch = globalThis.navigator?.userAgent?.match(/Firefox\/(\d+)/);
- if (!firefoxMatch || Number(firefoxMatch[1]) >= 154) {
- try {
- // This method may be missing or could fail with `Memory must have a maximum`
- var b = wasmMemory.toResizableBuffer();
- growMemViews = () => {};
- return b;
- } catch {}
- }
- return wasmMemory.buffer;
- }
- function updateMemoryViews() {
- // If we already have a heap that is resizeable/growable buffer we don't
- // need to do anything in updateMemoryViews.
- if (HEAP8?.buffer?.growable) return;
- var b = getMemoryBuffer();
- HEAP8 = new Int8Array(b);
- HEAP16 = new Int16Array(b);
- HEAPU8 = new Uint8Array(b);
- HEAPU16 = new Uint16Array(b);
- HEAP32 = new Int32Array(b);
- HEAPU32 = new Uint32Array(b);
- HEAPF32 = new Float32Array(b);
- HEAPF64 = new Float64Array(b);
- HEAP64 = new BigInt64Array(b);
- HEAPU64 = new BigUint64Array(b);
- }
- // In non-standalone/normal mode, we create the memory here.
- // include: runtime_init_memory.js
- // Create the wasm memory. (Note: this only applies if IMPORTED_MEMORY is defined)
- // check for full engine support (use string 'subarray' to avoid closure compiler confusion)
- function initMemory() {
- if ((ENVIRONMENT_IS_PTHREAD)) {
- return;
- }
- {
- var INITIAL_MEMORY = 16777216;
- assert(INITIAL_MEMORY >= 65536, `INITIAL_MEMORY should be larger than STACK_SIZE, was ${INITIAL_MEMORY}! (STACK_SIZE=65536)`);
- /** @suppress {checkTypes} */ wasmMemory = new WebAssembly.Memory({
- "initial": INITIAL_MEMORY / 65536,
- // In theory we should not need to emit the maximum if we want "unlimited"
- // or 4GB of memory, but VMs error on that atm, see
- // https://github.com/emscripten-core/emscripten/issues/14130
- // And in the pthreads case we definitely need to emit a maximum. So
- // always emit one.
- "maximum": 32768,
- "shared": true
- });
- }
- updateMemoryViews();
- }
- // end include: runtime_init_memory.js
- // include: memoryprofiler.js
- // end include: memoryprofiler.js
- // end include: runtime_common.js
- assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.subarray && Int32Array.prototype.set, "JS engine does not provide full typed array support");
- function preRun() {
- assert(!ENVIRONMENT_IS_PTHREAD);
- // PThreads reuse the runtime from the main thread.
- var preRun = Module["preRun"];
- if (preRun) {
- if (typeof preRun == "function") preRun = [ preRun ];
- onPreRuns.push(...preRun);
- }
- consumedModuleProp("preRun");
- // Begin ATPRERUNS hooks
- callRuntimeCallbacks(onPreRuns);
- }
- function initRuntime() {
- assert(!runtimeInitialized);
- runtimeInitialized = true;
- if (ENVIRONMENT_IS_PTHREAD) return startWorker();
- checkStackCookie();
- // Begin ATINITS hooks
- if (!Module["noFSInit"] && !FS.initialized) FS.init();
- TTY.init();
- PIPEFS.root = FS.mount(PIPEFS, {}, null);
- // End ATINITS hooks
- wasmExports["__wasm_call_ctors"]();
- // Begin ATPOSTCTORS hooks
- FS.ignorePermissions = false;
- // End ATPOSTCTORS hooks
- checkStackCookie();
- }
- function postRun() {
- checkStackCookie();
- var postRun = Module["postRun"];
- if (postRun) {
- if (typeof postRun == "function") postRun = [ postRun ];
- onPostRuns.push(...postRun);
- }
- consumedModuleProp("postRun");
- // Begin ATPOSTRUNS hooks
- callRuntimeCallbacks(onPostRuns);
- }
- /**
- * @param {string|number=} what
- */ function abort(what) {
- Module["onAbort"]?.(what);
- what = `Aborted(${what})`;
- // TODO(sbc): Should we remove printing and leave it up to whoever
- // catches the exception?
- err(what);
- ABORT = true;
- // Use a wasm runtime error, because a JS error might be seen as a foreign
- // exception, which means we'd run destructors on it. We need the error to
- // simply make the program stop.
- // FIXME This approach does not work in Wasm EH because it currently does not assume
- // all RuntimeErrors are from traps; it decides whether a RuntimeError is from
- // a trap or not based on a hidden field within the object. So at the moment
- // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
- // allows this in the wasm spec.
- // Suppress closure compiler warning here. Closure compiler's builtin extern
- // definition for WebAssembly.RuntimeError claims it takes no arguments even
- // though it can.
- // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
- /** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
- // Throw the error whether or not MODULARIZE is set because abort is used
- // in code paths apart from instantiation where an exception is expected
- // to be thrown when abort is called.
- throw e;
- }
- function createExportWrapper(name, func, nargs) {
- assert(func);
- return (...args) => {
- assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
- // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
- assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
- return func(...args);
- };
- }
- var wasmBinaryFile;
- function findWasmBinary() {
- return locateFile("nimсity.wasm");
- }
- function getBinarySync(file) {
- if (readBinary) {
- return readBinary(file);
- }
- // Throwing a plain string here, even though it not normally advisable since
- // this gets turning into an `abort` in instantiateArrayBuffer.
- throw "both async and sync fetching of the wasm failed";
- }
- async function getWasmBinary(binaryFile) {
- // If we don't have the binary yet, load it asynchronously using readAsync.
- if (!wasmBinary) {
- // Fetch the binary using readAsync
- try {
- var response = await readAsync(binaryFile);
- return new Uint8Array(response);
- } catch {}
- }
- // Otherwise, getBinarySync should be able to get it synchronously
- return getBinarySync(binaryFile);
- }
- async function instantiateArrayBuffer(binaryFile, imports) {
- try {
- var binary = await getWasmBinary(binaryFile);
- var instance = await WebAssembly.instantiate(binary, imports);
- return instance;
- } catch (reason) {
- err(`failed to asynchronously prepare wasm: ${reason}`);
- // Warn on some common problems.
- if (isFileURI(binaryFile)) {
- err(`warning: Loading from a file URI (${binaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`);
- }
- abort(reason);
- }
- }
- async function instantiateAsync(binary, binaryFile, imports) {
- if (!binary && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE) {
- try {
- var response = fetch(binaryFile, {
- credentials: "same-origin"
- });
- var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
- return instantiationResult;
- } catch (reason) {
- // We expect the most common failure cause to be a bad MIME type for the binary,
- // in which case falling back to ArrayBuffer instantiation should work.
- err(`wasm streaming compile failed: ${reason}`);
- err("falling back to ArrayBuffer instantiation");
- }
- }
- return instantiateArrayBuffer(binaryFile, imports);
- }
- function getWasmImports() {
- assignWasmImports();
- // prepare imports
- var imports = {
- "env": wasmImports,
- "wasi_snapshot_preview1": wasmImports
- };
- return imports;
- }
- // Create the wasm instance.
- // Receives the wasm imports, returns the exports.
- async function createWasm() {
- // Load the wasm module and create an instance of using native support in the JS engine.
- // handle a generated wasm instance, receiving its exports and
- // performing other necessary setup
- function receiveInstance(instance, module) {
- wasmExports = instance.exports;
- registerTLSInit(wasmExports["_emscripten_tls_init"]);
- assignWasmExports(wasmExports);
- // We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers.
- wasmModule = module;
- return wasmExports;
- }
- // Prefer streaming instantiation if available.
- // Async compilation can be confusing when an error on the page overwrites Module
- // (for example, if the order of elements is wrong, and the one defining Module is
- // later), so we save Module and check it later.
- var trueModule = Module;
- function receiveInstantiationResult(result) {
- // 'result' is a ResultObject object which has both the module and instance.
- // receiveInstance() will swap in the exports (to Module.asm) so they can be called
- assert(Module === trueModule, "the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");
- trueModule = null;
- return receiveInstance(result["instance"], result["module"]);
- }
- var info = getWasmImports();
- // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
- // to manually instantiate the Wasm module themselves. This allows pages to
- // run the instantiation parallel to any other async startup actions they are
- // performing.
- // Also pthreads and wasm workers initialize the wasm instance through this
- // path.
- var instantiateWasm = Module["instantiateWasm"];
- if (instantiateWasm) {
- return new Promise(resolve => {
- try {
- instantiateWasm(info, (inst, mod) => resolve(receiveInstance(inst, mod)));
- } catch (e) {
- err(`Module.instantiateWasm callback failed with error: ${e}`);
- throw e;
- }
- });
- }
- if ((ENVIRONMENT_IS_PTHREAD)) {
- // Instantiate from the module that was received via postMessage from
- // the main thread. We can just use sync instantiation in the worker.
- assert(wasmModule, "wasmModule should have been received via postMessage");
- var instance = new WebAssembly.Instance(wasmModule, getWasmImports());
- return receiveInstance(instance, wasmModule);
- }
- wasmBinaryFile ??= findWasmBinary();
- var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
- var exports = receiveInstantiationResult(result);
- return exports;
- }
- // end include: preamble.js
- // Begin JS library code
- class ExitStatus {
- name="ExitStatus";
- constructor(status) {
- this.message = `Program terminated with exit(${status})`;
- this.status = status;
- }
- }
- /** @type {!Int16Array} */ var HEAP16;
- /** @type {!Int32Array} */ var HEAP32;
- /** not-@type {!BigInt64Array} */ var HEAP64;
- /** @type {!Int8Array} */ var HEAP8;
- /** @type {!Float32Array} */ var HEAPF32;
- /** @type {!Float64Array} */ var HEAPF64;
- /** @type {!Uint16Array} */ var HEAPU16;
- /** @type {!Uint32Array} */ var HEAPU32;
- /** not-@type {!BigUint64Array} */ var HEAPU64;
- /** @type {!Uint8Array} */ var HEAPU8;
- var terminateWorker = worker => {
- worker.terminate();
- // terminate() can be asynchronous, so in theory the worker can continue
- // to run for some amount of time after termination. However from our POV
- // the worker is now dead and we don't want to hear from it again, so we stub
- // out its message handler here. This avoids having to check in each of
- // the onmessage handlers if the message was coming from a valid worker.
- worker.onmessage = e => {
- var cmd = e.data.cmd;
- err(`received "${cmd}" command from terminated worker: ${worker.workerID}`);
- };
- };
- var cleanupThread = pthread_ptr => {
- assert(!ENVIRONMENT_IS_PTHREAD, "cleanupThread() should only be called from the main thread");
- assert(pthread_ptr, "null pthread_ptr passed to cleanupThread");
- var worker = PThread.pthreads[pthread_ptr];
- assert(worker);
- PThread.returnWorkerToPool(worker);
- };
- var callRuntimeCallbacks = callbacks => {
- while (callbacks.length > 0) {
- // Pass the module as the first argument.
- callbacks.shift()(Module);
- }
- };
- var onPreRuns = [];
- var addOnPreRun = cb => onPreRuns.push(cb);
- var spawnThread = threadParams => {
- assert(!ENVIRONMENT_IS_PTHREAD, "spawnThread() should only be called from the main thread");
- assert(threadParams.pthread_ptr, "spawnThread called with null pthread ptr");
- var worker = PThread.getNewWorker();
- if (!worker) {
- // No available workers in the PThread pool.
- return 6;
- }
- assert(!worker.pthread_ptr);
- // Add to pthreads map
- PThread.pthreads[threadParams.pthread_ptr] = worker;
- worker.pthread_ptr = threadParams.pthread_ptr;
- var msg = {
- cmd: 2,
- start_routine: threadParams.startRoutine,
- arg: threadParams.arg,
- pthread_ptr: threadParams.pthread_ptr
- };
- // Ask the worker to start executing its pthread entry point function.
- worker.postMessage(msg, threadParams.transferList);
- return 0;
- };
- var runtimeKeepaliveCounter = 0;
- var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
- var stackSave = () => _emscripten_stack_get_current();
- var stackRestore = val => __emscripten_stack_restore(val);
- var stackAlloc = sz => __emscripten_stack_alloc(sz);
- /** @type{function(number, (number|boolean), ...number)} */ var proxyToMainThread = (funcIndex, emAsmAddr, proxyMode, ...callArgs) => {
- // EM_ASM proxying is done by passing a pointer to the address of the EM_ASM
- // content as `emAsmAddr`. JS library proxying is done by passing an index
- // into `proxiedJSCallArgs` as `funcIndex`. If `emAsmAddr` is non-zero then
- // `funcIndex` will be ignored.
- // Additional arguments are passed after the first three are the actual
- // function arguments.
- // The serialization buffer contains the number of call params, and then
- // all the args here.
- // We also pass 'proxyMode' to C separately, since C needs to look at it.
- // Allocate a buffer (on the stack), which will be copied if necessary by
- // the C code.
- // First passed parameter specifies the number of arguments to the function.
- // When BigInt support is enabled, we must handle types in a more complex
- // way, detecting at runtime if a value is a BigInt or not (as we have no
- // type info here). To do that, add a "prefix" before each value that
- // indicates if it is a BigInt, which effectively doubles the number of
- // values we serialize for proxying. TODO: pack this?
- var bufSize = 8 * callArgs.length * 2;
- var sp = stackSave();
- var args = stackAlloc(bufSize);
- var b = ((args) >> 3);
- for (var arg of callArgs) {
- if (typeof arg == "bigint") {
- // The prefix is non-zero to indicate a bigint.
- (growMemViews(), HEAP64)[b++] = 1n;
- (growMemViews(), HEAP64)[b++] = arg;
- } else {
- // The prefix is zero to indicate a JS Number.
- (growMemViews(), HEAP64)[b++] = 0n;
- (growMemViews(), HEAPF64)[b++] = arg;
- }
- }
- var rtn = __emscripten_run_js_on_main_thread(funcIndex, emAsmAddr, bufSize, args, proxyMode);
- stackRestore(sp);
- return rtn;
- };
- function _proc_exit(code) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(0, 0, 1, code);
- EXITSTATUS = code;
- if (!keepRuntimeAlive()) {
- PThread.terminateAllThreads();
- Module["onExit"]?.(code);
- ABORT = true;
- }
- quit_(code, new ExitStatus(code));
- }
- function exitOnMainThread(returnCode) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(1, 0, 0, returnCode);
- _exit(returnCode);
- }
- /** @param {boolean|number=} implicit */ var exitJS = (status, implicit) => {
- EXITSTATUS = status;
- checkUnflushedContent();
- if (ENVIRONMENT_IS_PTHREAD) {
- // implicit exit can never happen on a pthread
- assert(!implicit);
- // When running in a pthread we propagate the exit back to the main thread
- // where it can decide if the whole process should be shut down or not.
- // The pthread may have decided not to exit its own runtime, for example
- // because it runs a main loop, but that doesn't affect the main thread.
- exitOnMainThread(status);
- throw "unwind";
- }
- // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
- if (keepRuntimeAlive() && !implicit) {
- var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
- err(msg);
- }
- _proc_exit(status);
- };
- var _exit = exitJS;
- var waitAsyncPolyfilled = (!Atomics.waitAsync || (globalThis.navigator?.userAgent && Number((navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./) || [])[2]) < 91));
- function ptrToString(ptr) {
- assert(typeof ptr === "number", `ptrToString expects a number, got ${typeof ptr}`);
- // Convert to 32-bit unsigned value
- ptr >>>= 0;
- return "0x" + ptr.toString(16).padStart(8, "0");
- }
- var PThread = {
- unusedWorkers: [],
- tlsInitFunctions: [],
- pthreads: {},
- nextWorkerID: 1,
- init() {
- if ((!(ENVIRONMENT_IS_PTHREAD))) {
- PThread.initMainThread();
- }
- },
- initMainThread() {},
- terminateAllThreads: () => {
- assert(!ENVIRONMENT_IS_PTHREAD, "terminateAllThreads() should only be called from the main thread");
- // Attempt to kill all workers. Sadly (at least on the web) there is no
- // way to terminate a worker synchronously, or to be notified when a
- // worker is actually terminated. This means there is some risk that
- // pthreads will continue to be executing after `worker.terminate` has
- // returned. For this reason, we don't call `returnWorkerToPool` here or
- // free the underlying pthread data structures.
- for (var worker of Object.values(PThread.pthreads)) {
- terminateWorker(worker);
- }
- for (var worker of PThread.unusedWorkers) {
- terminateWorker(worker);
- }
- PThread.unusedWorkers = [];
- PThread.pthreads = {};
- },
- terminateRuntime: () => {
- assert(!ENVIRONMENT_IS_PTHREAD, "terminateRuntime() should only be called from the main thread");
- PThread.terminateAllThreads();
- var pthread_ptr = _pthread_self();
- ___set_thread_state(0, 0, 0, 1);
- if (!waitAsyncPolyfilled) {
- // Break the waitAsync loop. Note that checkMailbox will not
- // re-register since the `___set_thread_state` above causes _pthread_self
- // to return 0.
- Atomics.notify((growMemViews(), HEAP32), ((pthread_ptr) >> 2));
- }
- },
- returnWorkerToPool: worker => {
- // We don't want to run main thread queued calls here, since we are doing
- // some operations that leave the worker queue in an invalid state until
- // we are completely done (it would be bad if free() ends up calling a
- // queued pthread_create which looks at the global data structures we are
- // modifying). To achieve that, defer the free() until the very end, when
- // we are all done.
- var pthread_ptr = worker.pthread_ptr;
- delete PThread.pthreads[pthread_ptr];
- // Note: worker is intentionally not terminated so the pool can
- // dynamically grow.
- PThread.unusedWorkers.push(worker);
- // Not a running Worker anymore
- // Detach the worker from the pthread object, and return it to the
- // worker pool as an unused worker.
- worker.pthread_ptr = 0;
- // Finally, free the underlying (and now-unused) pthread structure in
- // linear memory.
- __emscripten_thread_free_data(pthread_ptr);
- },
- threadInitTLS() {
- // Call thread init functions (these are the _emscripten_tls_init for each
- // module loaded.
- PThread.tlsInitFunctions.forEach(f => f());
- },
- loadWasmModuleToWorker: worker => new Promise(onFinishedLoading => {
- worker.onmessage = e => {
- var d = e.data;
- var cmd = d.cmd;
- // If this message is intended to a recipient that is not the main
- // thread, forward it to the target thread. This is currently only
- // used by `CMD_CHECK_MAILBOX`.
- if (d.targetThread) {
- // pthreads should not be relaying messages to themselves.
- assert(d.targetThread != _pthread_self());
- var targetWorker = PThread.pthreads[d.targetThread];
- if (!targetWorker) err(`worker sent message (${cmd}) to pthread (${d.targetThread}) that no longer exists`);
- targetWorker?.postMessage(d);
- return;
- }
- if (d === "setimmediate" || d === "_si") {
- // Worker wants to postMessage() to itself to implement setImmediate()
- // emulation.
- worker.postMessage(d);
- return;
- }
- switch (cmd) {
- case 4:
- checkMailbox();
- break;
- case 5:
- spawnThread(d);
- break;
- case 6:
- // cleanupThread needs to be run via callUserCallback since it calls
- // back into user code to free thread data. Without this it's possible
- // the unwind or ExitStatus exception could escape here.
- callUserCallback(() => cleanupThread(d.thread));
- break;
- case 3:
- if (ENVIRONMENT_IS_NODE && !worker.strongref) {
- // Once worker is loaded & idle, mark it as weakly referenced,
- // so that mere existence of a Worker in the pool does not prevent
- // Node.js from exiting the app.
- worker.unref();
- }
- onFinishedLoading(worker);
- break;
- case 8:
- // Message handler for Node.js specific out-of-order behavior:
- // https://github.com/nodejs/node/issues/59617
- // A pthread sent an uncaught exception event. Re-raise it on the main thread.
- worker.onerror(d.error);
- break;
- case 9:
- Module[d.handler](...d.args);
- break;
- default:
- // The received message looks like something that should be handled by this message
- // handler, (since there is a e.data.cmd field present), but is not one of the
- // recognized commands:
- if (cmd) err(`worker sent an unknown command ${cmd}`);
- }
- };
- worker.onerror = e => {
- var message = "worker sent an error!";
- if (worker.pthread_ptr) {
- message = `Pthread ${ptrToString(worker.pthread_ptr)} sent an error!`;
- }
- err(`${message} ${e.filename}:${e.lineno}: ${e.message}`);
- throw e;
- };
- if (ENVIRONMENT_IS_NODE) {
- worker.on("message", data => worker.onmessage({
- data
- }));
- worker.on("error", e => worker.onerror(e));
- }
- assert(wasmMemory instanceof WebAssembly.Memory, "wasmMemory should have been loaded by now");
- assert(wasmModule instanceof WebAssembly.Module, "wasmModule should have been loaded by now");
- // When running on a pthread, none of the incoming parameters on the module
- // object are present. Proxy known handlers back to the main thread if specified.
- var handlers = [];
- var knownHandlers = [ "onExit", "onAbort", "print", "printErr" ];
- for (var handler of knownHandlers) {
- if (Module.propertyIsEnumerable(handler)) {
- handlers.push(handler);
- }
- }
- // Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation.
- worker.postMessage({
- cmd: 1,
- handlers,
- wasmMemory,
- wasmModule,
- workerID: worker.workerID
- });
- }),
- allocateUnusedWorker() {
- var worker;
- var pthreadMainJs = _scriptName;
- worker = new Worker(pthreadMainJs, {
- // This is the way that we signal to the node worker that it is hosting
- // a pthread.
- "workerData": "em-pthread",
- // This is the way that we signal to the Web Worker that it is hosting
- // a pthread.
- "name": "em-pthread-" + PThread.nextWorkerID
- });
- worker.workerID = PThread.nextWorkerID++;
- PThread.unusedWorkers.push(worker);
- return worker;
- },
- getNewWorker() {
- if (PThread.unusedWorkers.length == 0) {
- // PTHREAD_POOL_SIZE_STRICT should show a warning and, if set to level `2`, return from the function.
- // However, if we're in Node.js, then we can create new workers on the fly and PTHREAD_POOL_SIZE_STRICT
- // should be ignored altogether.
- if (!ENVIRONMENT_IS_NODE) {
- err("Tried to spawn a new thread, but the thread pool is exhausted.\n" + "This might result in a deadlock unless some threads eventually exit or the code explicitly breaks out to the event loop.\n" + "If you want to increase the pool size, use setting `-sPTHREAD_POOL_SIZE=...`." + "\nIf you want to throw an explicit error instead of the risk of deadlocking in those cases, use setting `-sPTHREAD_POOL_SIZE_STRICT=2`.");
- }
- var newWorker = PThread.allocateUnusedWorker();
- PThread.loadWasmModuleToWorker(newWorker);
- }
- return PThread.unusedWorkers.pop();
- }
- };
- var onPostRuns = [];
- var addOnPostRun = cb => onPostRuns.push(cb);
- function establishStackSpace(pthread_ptr) {
- var stackHigh = (growMemViews(), HEAPU32)[(((pthread_ptr) + (48)) >> 2)];
- var stackSize = (growMemViews(), HEAPU32)[(((pthread_ptr) + (52)) >> 2)];
- var stackLow = stackHigh - stackSize;
- assert(stackHigh != 0);
- assert(stackLow != 0);
- assert(stackHigh > stackLow, "stackHigh must be higher then stackLow");
- // Set stack limits used by `emscripten/stack.h` function. These limits are
- // cached in wasm-side globals to make checks as fast as possible.
- _emscripten_stack_set_limits(stackHigh, stackLow);
- // Call inside wasm module to set up the stack frame for this pthread in wasm module scope
- stackRestore(stackHigh);
- // Write the stack cookie last, after we have set up the proper bounds and
- // current position of the stack.
- writeStackCookie();
- }
- /**
- * @param {number} ptr
- * @param {string} type
- */ function getValue(ptr, type = "i8") {
- if (type.endsWith("*")) type = "*";
- switch (type) {
- case "i1":
- return (growMemViews(), HEAP8)[ptr];
- case "i8":
- return (growMemViews(), HEAP8)[ptr];
- case "i16":
- return (growMemViews(), HEAP16)[((ptr) >> 1)];
- case "i32":
- return (growMemViews(), HEAP32)[((ptr) >> 2)];
- case "i64":
- return (growMemViews(), HEAP64)[((ptr) >> 3)];
- case "float":
- return (growMemViews(), HEAPF32)[((ptr) >> 2)];
- case "double":
- return (growMemViews(), HEAPF64)[((ptr) >> 3)];
- case "*":
- return (growMemViews(), HEAPU32)[((ptr) >> 2)];
- default:
- abort(`invalid type for getValue: ${type}`);
- }
- }
- var wasmTableMirror = [];
- var getWasmTableEntry = funcPtr => {
- var func = wasmTableMirror[funcPtr];
- if (!func) {
- /** @suppress {checkTypes} */ wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
- }
- /** @suppress {checkTypes} */ assert(wasmTable.get(funcPtr) == func, "table mirror is out of date");
- return func;
- };
- var invokeEntryPoint = (ptr, arg) => {
- // An old thread on this worker may have been canceled without returning the
- // `runtimeKeepaliveCounter` to zero. Reset it now so the new thread won't
- // be affected.
- runtimeKeepaliveCounter = 0;
- // Same for noExitRuntime. The default for pthreads should always be false
- // otherwise pthreads would never complete and attempts to pthread_join to
- // them would block forever.
- // pthreads can still choose to set `noExitRuntime` explicitly, or
- // call emscripten_unwind_to_js_event_loop to extend their lifetime beyond
- // their main function. See comment in src/runtime_pthread.js for more.
- noExitRuntime = 0;
- // pthread entry points are always of signature 'void *ThreadMain(void *arg)'
- // Native codebases sometimes spawn threads with other thread entry point
- // signatures, such as void ThreadMain(void *arg), void *ThreadMain(), or
- // void ThreadMain(). That is not acceptable per C/C++ specification, but
- // x86 compiler ABI extensions enable that to work. If you find the
- // following line to crash, either change the signature to "proper" void
- // *ThreadMain(void *arg) form, or try linking with the Emscripten linker
- // flag -sEMULATE_FUNCTION_POINTER_CASTS to add in emulation for this x86
- // ABI extension.
- var result = getWasmTableEntry(ptr)(arg);
- checkStackCookie();
- function finish(result) {
- // In MINIMAL_RUNTIME the noExitRuntime concept does not apply to
- // pthreads. To exit a pthread with live runtime, use the function
- // emscripten_unwind_to_js_event_loop() in the pthread body.
- if (keepRuntimeAlive()) {
- EXITSTATUS = result;
- return;
- }
- __emscripten_thread_exit(result);
- }
- finish(result);
- };
- var noExitRuntime = true;
- var registerTLSInit = tlsInitFunc => PThread.tlsInitFunctions.push(tlsInitFunc);
- /**
- * @param {number} ptr
- * @param {number} value
- * @param {string} type
- */ function setValue(ptr, value, type = "i8") {
- if (type.endsWith("*")) type = "*";
- switch (type) {
- case "i1":
- (growMemViews(), HEAP8)[ptr] = value;
- break;
- case "i8":
- (growMemViews(), HEAP8)[ptr] = value;
- break;
- case "i16":
- (growMemViews(), HEAP16)[((ptr) >> 1)] = value;
- break;
- case "i32":
- (growMemViews(), HEAP32)[((ptr) >> 2)] = value;
- break;
- case "i64":
- (growMemViews(), HEAP64)[((ptr) >> 3)] = BigInt(value);
- break;
- case "float":
- (growMemViews(), HEAPF32)[((ptr) >> 2)] = value;
- break;
- case "double":
- (growMemViews(), HEAPF64)[((ptr) >> 3)] = value;
- break;
- case "*":
- (growMemViews(), HEAPU32)[((ptr) >> 2)] = value;
- break;
- default:
- abort(`invalid type for setValue: ${type}`);
- }
- }
- var warnOnce = text => {
- warnOnce.shown ||= {};
- if (!warnOnce.shown[text]) {
- warnOnce.shown[text] = 1;
- if (ENVIRONMENT_IS_NODE) text = "warning: " + text;
- err(text);
- }
- };
- var wasmMemory;
- var UTF8Decoder = globalThis.TextDecoder && new TextDecoder;
- /**
- * heapOrArray is either a regular array, or a JavaScript typed array view.
- * @param {number} idx
- * @param {number=} maxBytesToRead
- * @param {boolean=} ignoreNul
- * @return {number}
- */ var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
- var maxIdx = idx + maxBytesToRead;
- if (ignoreNul) return maxIdx;
- // TextDecoder needs to know the byte length in advance, it doesn't stop on
- // null terminator by itself.
- // As a tiny code save trick, compare idx against maxIdx using a negation,
- // so that maxBytesToRead=undefined/NaN means Infinity.
- while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx;
- return idx;
- };
- /**
- * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
- * array that contains uint8 values, returns a copy of that string as a
- * Javascript String object.
- * heapOrArray is either a regular array, or a JavaScript typed array view.
- * @param {number=} idx
- * @param {number=} maxBytesToRead
- * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
- * @return {string}
- */ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => {
- var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul);
- // When using conditional TextDecoder, skip it for short strings as the overhead of the native call is not worth it.
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
- return UTF8Decoder.decode(heapOrArray.buffer instanceof ArrayBuffer ? heapOrArray.subarray(idx, endPtr) : heapOrArray.slice(idx, endPtr));
- }
- var str = "";
- while (idx < endPtr) {
- // For UTF8 byte structure, see:
- // http://en.wikipedia.org/wiki/UTF-8#Description
- // https://www.ietf.org/rfc/rfc2279.txt
- // https://tools.ietf.org/html/rfc3629
- var u0 = heapOrArray[idx++];
- if (!(u0 & 128)) {
- str += String.fromCharCode(u0);
- continue;
- }
- var u1 = heapOrArray[idx++] & 63;
- if ((u0 & 224) == 192) {
- str += String.fromCharCode(((u0 & 31) << 6) | u1);
- continue;
- }
- var u2 = heapOrArray[idx++] & 63;
- if ((u0 & 240) == 224) {
- u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
- } else {
- if ((u0 & 248) != 240) warnOnce(`Invalid UTF-8 leading byte ${ptrToString(u0)} encountered when deserializing a UTF-8 string in wasm memory to a JS string!`);
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
- }
- if (u0 < 65536) {
- str += String.fromCharCode(u0);
- } else {
- var ch = u0 - 65536;
- str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
- }
- }
- return str;
- };
- /**
- * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
- * emscripten HEAP, returns a copy of that string as a Javascript String object.
- *
- * @param {number} ptr
- * @param {number=} maxBytesToRead - An optional length that specifies the
- * maximum number of bytes to read. You can omit this parameter to scan the
- * string until the first 0 byte. If maxBytesToRead is passed, and the string
- * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
- * string will cut short at that byte index.
- * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
- * @return {string}
- */ var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
- assert(typeof ptr == "number", `UTF8ToString expects a number (got ${typeof ptr})`);
- return ptr ? UTF8ArrayToString((growMemViews(), HEAPU8), ptr, maxBytesToRead, ignoreNul) : "";
- };
- var ___assert_fail = (condition, filename, line, func) => abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
- var ___call_sighandler = (fp, sig) => getWasmTableEntry(fp)(sig);
- function pthreadCreateProxied(pthread_ptr, attr, startRoutine, arg) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(2, 0, 1, pthread_ptr, attr, startRoutine, arg);
- return ___pthread_create_js(pthread_ptr, attr, startRoutine, arg);
- }
- var _emscripten_has_threading_support = () => !!globalThis.SharedArrayBuffer;
- var ___pthread_create_js = (pthread_ptr, attr, startRoutine, arg) => {
- if (!_emscripten_has_threading_support()) {
- dbg("pthread_create: environment does not support SharedArrayBuffer, pthreads are not available");
- return 6;
- }
- // List of JS objects that will transfer ownership to the Worker hosting the thread
- var transferList = [];
- var error = 0;
- // Synchronously proxy the thread creation to main thread if possible. If we
- // need to transfer ownership of objects, then proxy asynchronously via
- // postMessage.
- if (ENVIRONMENT_IS_PTHREAD && (transferList.length === 0 || error)) {
- return pthreadCreateProxied(pthread_ptr, attr, startRoutine, arg);
- }
- // If on the main thread, and accessing Canvas/OffscreenCanvas failed, abort
- // with the detected error.
- if (error) return error;
- var threadParams = {
- startRoutine,
- pthread_ptr,
- arg,
- transferList
- };
- if (ENVIRONMENT_IS_PTHREAD) {
- // The prepopulated pool of web workers that can host pthreads is stored
- // in the main JS thread. Therefore if a pthread is attempting to spawn a
- // new thread, the thread creation must be deferred to the main JS thread.
- threadParams.cmd = 5;
- postMessage(threadParams, transferList);
- // When we defer thread creation this way, we have no way to detect thread
- // creation synchronously today, so we have to assume success and return 0.
- return 0;
- }
- // We are the main thread, so we have the pthread warmup pool in this
- // thread and can fire off JS thread creation directly ourselves.
- return spawnThread(threadParams);
- };
- var PATH = {
- isAbs: path => path.charAt(0) === "/",
- splitPath: filename => {
- var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
- return splitPathRe.exec(filename).slice(1);
- },
- normalizeArray: (parts, allowAboveRoot) => {
- // if the path tries to go above the root, `up` ends up > 0
- var up = 0;
- for (var i = parts.length - 1; i >= 0; i--) {
- var last = parts[i];
- if (last === ".") {
- parts.splice(i, 1);
- } else if (last === "..") {
- parts.splice(i, 1);
- up++;
- } else if (up) {
- parts.splice(i, 1);
- up--;
- }
- }
- // if the path is allowed to go above the root, restore leading ..s
- if (allowAboveRoot) {
- for (;up; up--) {
- parts.unshift("..");
- }
- }
- return parts;
- },
- normalize: path => {
- var isAbsolute = PATH.isAbs(path), trailingSlash = path.slice(-1) === "/";
- // Normalize the path
- path = PATH.normalizeArray(path.split("/").filter(p => !!p), !isAbsolute).join("/");
- if (!path && !isAbsolute) {
- path = ".";
- }
- if (path && trailingSlash) {
- path += "/";
- }
- return (isAbsolute ? "/" : "") + path;
- },
- dirname: path => {
- var result = PATH.splitPath(path), root = result[0], dir = result[1];
- if (!root && !dir) {
- // No dirname whatsoever
- return ".";
- }
- if (dir) {
- // It has a dirname, strip trailing slash
- dir = dir.slice(0, -1);
- }
- return root + dir;
- },
- basename: path => path && path.match(/([^\/]+|\/)\/*$/)[1],
- join: (...paths) => PATH.normalize(paths.join("/")),
- join2: (l, r) => PATH.normalize(l + "/" + r)
- };
- var initRandomFill = () => {
- // This block is not needed on v19+ since crypto.getRandomValues is builtin
- if (ENVIRONMENT_IS_NODE) {
- var nodeCrypto = require("node:crypto");
- return view => (nodeCrypto.randomFillSync(view), 0);
- }
- // like with most Web APIs, we can't use Web Crypto API directly on shared memory,
- // so we need to create an intermediate buffer and copy it to the destination
- return view => (view.set(crypto.getRandomValues(new Uint8Array(view.byteLength))),
- 0);
- };
- var randomFill = view => (randomFill = initRandomFill())(view);
- var PATH_FS = {
- resolve: (...args) => {
- var resolvedPath = "", resolvedAbsolute = false;
- for (var i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
- var path = (i >= 0) ? args[i] : FS.cwd();
- // Skip empty and invalid entries
- if (typeof path != "string") {
- throw new TypeError("Arguments to path.resolve must be strings");
- } else if (!path) {
- return "";
- }
- resolvedPath = path + "/" + resolvedPath;
- resolvedAbsolute = PATH.isAbs(path);
- }
- // At this point the path should be resolved to a full absolute path, but
- // handle relative paths to be safe (might happen when process.cwd() fails)
- resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(p => !!p), !resolvedAbsolute).join("/");
- return ((resolvedAbsolute ? "/" : "") + resolvedPath) || ".";
- },
- relative: (from, to) => {
- from = PATH_FS.resolve(from).slice(1);
- to = PATH_FS.resolve(to).slice(1);
- function trim(arr) {
- var start = 0;
- for (;start < arr.length; start++) {
- if (arr[start] !== "") break;
- }
- var end = arr.length - 1;
- for (;end >= 0; end--) {
- if (arr[end] !== "") break;
- }
- if (start > end) return [];
- return arr.slice(start, end - start + 1);
- }
- var fromParts = trim(from.split("/"));
- var toParts = trim(to.split("/"));
- var length = Math.min(fromParts.length, toParts.length);
- var samePartsLength = length;
- for (var i = 0; i < length; i++) {
- if (fromParts[i] !== toParts[i]) {
- samePartsLength = i;
- break;
- }
- }
- var outputParts = [];
- for (var i = samePartsLength; i < fromParts.length; i++) {
- outputParts.push("..");
- }
- outputParts = outputParts.concat(toParts.slice(samePartsLength));
- return outputParts.join("/");
- }
- };
- var FS_stdin_getChar_buffer = [];
- var lengthBytesUTF8 = str => {
- var len = 0;
- for (var i = 0; i < str.length; ++i) {
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
- // unit, not a Unicode code point of the character! So decode
- // UTF16->UTF32->UTF8.
- // See http://unicode.org/faq/utf_bom.html#utf16-3
- var c = str.charCodeAt(i);
- // possibly a lead surrogate
- if (c <= 127) {
- len++;
- } else if (c <= 2047) {
- len += 2;
- } else if (c >= 55296 && c <= 57343) {
- len += 4;
- ++i;
- } else {
- len += 3;
- }
- }
- return len;
- };
- var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
- assert(typeof str === "string", `stringToUTF8Array expects a string (got ${typeof str})`);
- // Parameter maxBytesToWrite is not optional. Negative values, 0, null,
- // undefined and false each don't write out any bytes.
- if (!(maxBytesToWrite > 0)) return 0;
- var startIdx = outIdx;
- var endIdx = outIdx + maxBytesToWrite - 1;
- // -1 for string null terminator.
- for (var i = 0; i < str.length; ++i) {
- // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description
- // and https://www.ietf.org/rfc/rfc2279.txt
- // and https://tools.ietf.org/html/rfc3629
- var u = str.codePointAt(i);
- if (u <= 127) {
- if (outIdx >= endIdx) break;
- heap[outIdx++] = u;
- } else if (u <= 2047) {
- if (outIdx + 1 >= endIdx) break;
- heap[outIdx++] = 192 | (u >> 6);
- heap[outIdx++] = 128 | (u & 63);
- } else if (u <= 65535) {
- if (outIdx + 2 >= endIdx) break;
- heap[outIdx++] = 224 | (u >> 12);
- heap[outIdx++] = 128 | ((u >> 6) & 63);
- heap[outIdx++] = 128 | (u & 63);
- } else {
- if (outIdx + 3 >= endIdx) break;
- if (u > 1114111) warnOnce(`Invalid Unicode code point ${ptrToString(u)} encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).`);
- heap[outIdx++] = 240 | (u >> 18);
- heap[outIdx++] = 128 | ((u >> 12) & 63);
- heap[outIdx++] = 128 | ((u >> 6) & 63);
- heap[outIdx++] = 128 | (u & 63);
- // Gotcha: if codePoint is over 0xFFFF, it is represented as a surrogate pair in UTF-16.
- // We need to manually skip over the second code unit for correct iteration.
- i++;
- }
- }
- // Null-terminate the pointer to the buffer.
- heap[outIdx] = 0;
- return outIdx - startIdx;
- };
- /** @type {function(string, boolean=, number=)} */ var intArrayFromString = (stringy, dontAddNull, length) => {
- var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
- var u8array = new Array(len);
- var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
- if (dontAddNull) u8array.length = numBytesWritten;
- return u8array;
- };
- var FS_stdin_getChar = () => {
- if (!FS_stdin_getChar_buffer.length) {
- var result = null;
- if (ENVIRONMENT_IS_NODE) {
- // we will read data by chunks of BUFSIZE
- var BUFSIZE = 256;
- var buf = Buffer.alloc(BUFSIZE);
- var bytesRead = 0;
- // For some reason we must suppress a closure warning here, even though
- // fd definitely exists on process.stdin, and is even the proper way to
- // get the fd of stdin,
- // https://github.com/nodejs/help/issues/2136#issuecomment-523649904
- // This started to happen after moving this logic out of library_tty.js,
- // so it is related to the surrounding code in some unclear manner.
- /** @suppress {missingProperties} */ var fd = process.stdin.fd;
- try {
- bytesRead = fs.readSync(fd, buf, 0, BUFSIZE);
- } catch (e) {
- // Cross-platform differences: on Windows, reading EOF throws an
- // exception, but on other OSes, reading EOF returns 0. Uniformize
- // behavior by treating the EOF exception to return 0.
- if (e.toString().includes("EOF")) bytesRead = 0; else throw e;
- }
- if (bytesRead > 0) {
- result = buf.slice(0, bytesRead).toString("utf-8");
- }
- } else if (globalThis.window?.prompt) {
- // Browser.
- result = window.prompt("Input: ");
- // returns null on cancel
- if (result !== null) {
- result += "\n";
- }
- } else {}
- if (!result) {
- return null;
- }
- FS_stdin_getChar_buffer = intArrayFromString(result, true);
- }
- return FS_stdin_getChar_buffer.shift();
- };
- var TTY = {
- ttys: [],
- init() {},
- shutdown() {},
- register(dev, ops) {
- TTY.ttys[dev] = {
- input: [],
- output: [],
- ops
- };
- FS.registerDevice(dev, TTY.stream_ops);
- },
- stream_ops: {
- open(stream) {
- var tty = TTY.ttys[stream.node.rdev];
- if (!tty) {
- throw new FS.ErrnoError(43);
- }
- stream.tty = tty;
- stream.seekable = false;
- },
- close(stream) {
- // flush any pending line data
- stream.tty.ops.fsync(stream.tty);
- },
- fsync(stream) {
- stream.tty.ops.fsync(stream.tty);
- },
- read(stream, buffer, offset, length, pos) {
- if (!stream.tty || !stream.tty.ops.get_char) {
- throw new FS.ErrnoError(60);
- }
- var bytesRead = 0;
- for (var i = 0; i < length; i++) {
- var result;
- try {
- result = stream.tty.ops.get_char(stream.tty);
- } catch (e) {
- throw new FS.ErrnoError(29);
- }
- if (result === undefined && bytesRead === 0) {
- throw new FS.ErrnoError(6);
- }
- if (result === null || result === undefined) break;
- bytesRead++;
- buffer[offset + i] = result;
- }
- if (bytesRead) {
- stream.node.atime = Date.now();
- }
- return bytesRead;
- },
- write(stream, buffer, offset, length, pos) {
- if (!stream.tty || !stream.tty.ops.put_char) {
- throw new FS.ErrnoError(60);
- }
- try {
- for (var i = 0; i < length; i++) {
- stream.tty.ops.put_char(stream.tty, buffer[offset + i]);
- }
- } catch (e) {
- throw new FS.ErrnoError(29);
- }
- if (length) {
- stream.node.mtime = stream.node.ctime = Date.now();
- }
- return i;
- }
- },
- default_tty_ops: {
- get_char(tty) {
- return FS_stdin_getChar();
- },
- put_char(tty, val) {
- if (val === null || val === 10) {
- out(UTF8ArrayToString(tty.output));
- tty.output = [];
- } else {
- if (val != 0) tty.output.push(val);
- }
- },
- fsync(tty) {
- if (tty.output?.length > 0) {
- out(UTF8ArrayToString(tty.output));
- tty.output = [];
- }
- },
- ioctl_tcgets(tty) {
- // typical setting
- return {
- c_iflag: 25856,
- c_oflag: 5,
- c_cflag: 191,
- c_lflag: 35387,
- c_cc: [ 3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 0, 18, 15, 23, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- };
- },
- ioctl_tcsets(tty, optional_actions, data) {
- // currently just ignore
- return 0;
- },
- ioctl_tiocgwinsz(tty) {
- return [ 24, 80 ];
- }
- },
- default_tty1_ops: {
- put_char(tty, val) {
- if (val === null || val === 10) {
- err(UTF8ArrayToString(tty.output));
- tty.output = [];
- } else {
- if (val != 0) tty.output.push(val);
- }
- },
- fsync(tty) {
- if (tty.output?.length > 0) {
- err(UTF8ArrayToString(tty.output));
- tty.output = [];
- }
- }
- }
- };
- var zeroMemory = (ptr, size) => (growMemViews(), HEAPU8).fill(0, ptr, ptr + size);
- var alignMemory = (size, alignment) => {
- assert(alignment, "alignment argument is required");
- return Math.ceil(size / alignment) * alignment;
- };
- var mmapAlloc = size => {
- size = alignMemory(size, 65536);
- var ptr = _emscripten_builtin_memalign(65536, size);
- if (ptr) zeroMemory(ptr, size);
- return ptr;
- };
- var MEMFS = {
- ops_table: null,
- mount(mount) {
- return MEMFS.createNode(null, "/", 16895, 0);
- },
- createNode(parent, name, mode, dev) {
- if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
- // not supported
- throw new FS.ErrnoError(63);
- }
- MEMFS.ops_table ||= {
- dir: {
- node: {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr,
- lookup: MEMFS.node_ops.lookup,
- mknod: MEMFS.node_ops.mknod,
- rename: MEMFS.node_ops.rename,
- unlink: MEMFS.node_ops.unlink,
- rmdir: MEMFS.node_ops.rmdir,
- readdir: MEMFS.node_ops.readdir,
- symlink: MEMFS.node_ops.symlink
- },
- stream: {
- llseek: MEMFS.stream_ops.llseek
- }
- },
- file: {
- node: {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr
- },
- stream: {
- llseek: MEMFS.stream_ops.llseek,
- read: MEMFS.stream_ops.read,
- write: MEMFS.stream_ops.write,
- mmap: MEMFS.stream_ops.mmap,
- msync: MEMFS.stream_ops.msync
- }
- },
- link: {
- node: {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr,
- readlink: MEMFS.node_ops.readlink
- },
- stream: {}
- },
- chrdev: {
- node: {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr
- },
- stream: FS.chrdev_stream_ops
- }
- };
- var node = FS.createNode(parent, name, mode, dev);
- if (FS.isDir(node.mode)) {
- node.node_ops = MEMFS.ops_table.dir.node;
- node.stream_ops = MEMFS.ops_table.dir.stream;
- node.contents = {};
- } else if (FS.isFile(node.mode)) {
- node.node_ops = MEMFS.ops_table.file.node;
- node.stream_ops = MEMFS.ops_table.file.stream;
- // The actual number of bytes used in the typed array, as opposed to
- // contents.length which gives the whole capacity.
- node.usedBytes = 0;
- // The byte data of the file is stored in a typed array.
- // Note: typed arrays are not resizable like normal JS arrays are, so
- // there is a small penalty involved for appending file writes that
- // continuously grow a file similar to std::vector capacity vs used.
- node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0);
- } else if (FS.isLink(node.mode)) {
- node.node_ops = MEMFS.ops_table.link.node;
- node.stream_ops = MEMFS.ops_table.link.stream;
- } else if (FS.isChrdev(node.mode)) {
- node.node_ops = MEMFS.ops_table.chrdev.node;
- node.stream_ops = MEMFS.ops_table.chrdev.stream;
- }
- node.atime = node.mtime = node.ctime = Date.now();
- // add the new node to the parent
- if (parent) {
- parent.contents[name] = node;
- parent.atime = parent.mtime = parent.ctime = node.atime;
- }
- return node;
- },
- getFileDataAsTypedArray(node) {
- assert(FS.isFile(node.mode), "getFileDataAsTypedArray called on non-file");
- return node.contents.subarray(0, node.usedBytes);
- },
- expandFileStorage(node, newCapacity) {
- var prevCapacity = node.contents.length;
- if (prevCapacity >= newCapacity) return;
- // No need to expand, the storage was already large enough.
- // Don't expand strictly to the given requested limit if it's only a very
- // small increase, but instead geometrically grow capacity.
- // For small filesizes (<1MB), perform size*2 geometric increase, but for
- // large sizes, do a much more conservative size*1.125 increase to avoid
- // overshooting the allocation cap by a very large margin.
- var CAPACITY_DOUBLING_MAX = 1024 * 1024;
- newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125)) >>> 0);
- if (prevCapacity) newCapacity = Math.max(newCapacity, 256);
- // At minimum allocate 256b for each file when expanding.
- var oldContents = MEMFS.getFileDataAsTypedArray(node);
- node.contents = new Uint8Array(newCapacity);
- // Allocate new storage.
- node.contents.set(oldContents);
- },
- resizeFileStorage(node, newSize) {
- if (node.usedBytes == newSize) return;
- var oldContents = node.contents;
- node.contents = new Uint8Array(newSize);
- // Allocate new storage.
- node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));
- // Copy old data over to the new storage.
- node.usedBytes = newSize;
- },
- node_ops: {
- getattr(node) {
- var attr = {};
- // device numbers reuse inode numbers.
- attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
- attr.ino = node.id;
- attr.mode = node.mode;
- attr.nlink = 1;
- attr.uid = 0;
- attr.gid = 0;
- attr.rdev = node.rdev;
- if (FS.isDir(node.mode)) {
- attr.size = 4096;
- } else if (FS.isFile(node.mode)) {
- attr.size = node.usedBytes;
- } else if (FS.isLink(node.mode)) {
- attr.size = node.link.length;
- } else {
- attr.size = 0;
- }
- attr.atime = new Date(node.atime);
- attr.mtime = new Date(node.mtime);
- attr.ctime = new Date(node.ctime);
- // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
- // but this is not required by the standard.
- attr.blksize = 4096;
- attr.blocks = Math.ceil(attr.size / attr.blksize);
- return attr;
- },
- setattr(node, attr) {
- for (const key of [ "mode", "atime", "mtime", "ctime" ]) {
- if (attr[key] != null) {
- node[key] = attr[key];
- }
- }
- if (attr.size !== undefined) {
- MEMFS.resizeFileStorage(node, attr.size);
- }
- },
- lookup(parent, name) {
- throw new FS.ErrnoError(44);
- },
- mknod(parent, name, mode, dev) {
- return MEMFS.createNode(parent, name, mode, dev);
- },
- rename(old_node, new_dir, new_name) {
- var new_node;
- try {
- new_node = FS.lookupNode(new_dir, new_name);
- } catch (e) {}
- if (new_node) {
- if (FS.isDir(old_node.mode)) {
- // if we're overwriting a directory at new_name, make sure it's empty.
- for (var i in new_node.contents) {
- throw new FS.ErrnoError(55);
- }
- }
- FS.hashRemoveNode(new_node);
- }
- // do the internal rewiring
- delete old_node.parent.contents[old_node.name];
- new_dir.contents[new_name] = old_node;
- old_node.name = new_name;
- new_dir.ctime = new_dir.mtime = old_node.parent.ctime = old_node.parent.mtime = Date.now();
- },
- unlink(parent, name) {
- delete parent.contents[name];
- parent.ctime = parent.mtime = Date.now();
- },
- rmdir(parent, name) {
- var node = FS.lookupNode(parent, name);
- for (var i in node.contents) {
- throw new FS.ErrnoError(55);
- }
- delete parent.contents[name];
- parent.ctime = parent.mtime = Date.now();
- },
- readdir(node) {
- return [ ".", "..", ...Object.keys(node.contents) ];
- },
- symlink(parent, newname, oldpath) {
- var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
- node.link = oldpath;
- return node;
- },
- readlink(node) {
- if (!FS.isLink(node.mode)) {
- throw new FS.ErrnoError(28);
- }
- return node.link;
- }
- },
- stream_ops: {
- read(stream, buffer, offset, length, position) {
- var contents = stream.node.contents;
- if (position >= stream.node.usedBytes) return 0;
- var size = Math.min(stream.node.usedBytes - position, length);
- assert(size >= 0);
- buffer.set(contents.subarray(position, position + size), offset);
- return size;
- },
- write(stream, buffer, offset, length, position, canOwn) {
- assert(buffer.subarray, "FS.write expects a TypedArray");
- // If the buffer is located in main memory (HEAP), and if
- // memory can grow, we can't hold on to references of the
- // memory buffer, as they may get invalidated. That means we
- // need to copy its contents.
- if (buffer.buffer === (growMemViews(), HEAP8).buffer) {
- canOwn = false;
- }
- if (!length) return 0;
- var node = stream.node;
- node.mtime = node.ctime = Date.now();
- if (canOwn) {
- assert(position === 0, "canOwn must imply no weird position inside the file");
- node.contents = buffer.subarray(offset, offset + length);
- node.usedBytes = length;
- } else if (node.usedBytes === 0 && position === 0) {
- // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
- node.contents = buffer.slice(offset, offset + length);
- node.usedBytes = length;
- } else {
- MEMFS.expandFileStorage(node, position + length);
- // Use typed array write which is available.
- node.contents.set(buffer.subarray(offset, offset + length), position);
- node.usedBytes = Math.max(node.usedBytes, position + length);
- }
- return length;
- },
- llseek(stream, offset, whence) {
- var position = offset;
- if (whence === 1) {
- position += stream.position;
- } else if (whence === 2) {
- if (FS.isFile(stream.node.mode)) {
- position += stream.node.usedBytes;
- }
- }
- if (position < 0) {
- throw new FS.ErrnoError(28);
- }
- return position;
- },
- mmap(stream, length, position, prot, flags) {
- if (!FS.isFile(stream.node.mode)) {
- throw new FS.ErrnoError(43);
- }
- var ptr;
- var allocated;
- var contents = stream.node.contents;
- // Only make a new copy when MAP_PRIVATE is specified.
- if (!(flags & 2) && contents.buffer === (growMemViews(), HEAP8).buffer) {
- // We can't emulate MAP_SHARED when the file is not backed by the
- // buffer we're mapping to (e.g. the HEAP buffer).
- allocated = false;
- ptr = contents.byteOffset;
- } else {
- allocated = true;
- ptr = mmapAlloc(length);
- if (!ptr) {
- throw new FS.ErrnoError(48);
- }
- if (contents) {
- // Try to avoid unnecessary slices.
- if (position > 0 || position + length < contents.length) {
- if (contents.subarray) {
- contents = contents.subarray(position, position + length);
- } else {
- contents = Array.prototype.slice.call(contents, position, position + length);
- }
- }
- (growMemViews(), HEAP8).set(contents, ptr);
- }
- }
- return {
- ptr,
- allocated
- };
- },
- msync(stream, buffer, offset, length, mmapFlags) {
- MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
- // should we check if bytesWritten and length are the same?
- return 0;
- }
- }
- };
- var FS_modeStringToFlags = str => {
- if (typeof str != "string") return str;
- var flagModes = {
- "r": 0,
- "r+": 2,
- "w": 512 | 64 | 1,
- "w+": 512 | 64 | 2,
- "a": 1024 | 64 | 1,
- "a+": 1024 | 64 | 2
- };
- var flags = flagModes[str];
- if (typeof flags == "undefined") {
- throw new Error(`Unknown file open mode: ${str}`);
- }
- return flags;
- };
- var FS_fileDataToTypedArray = data => {
- if (typeof data == "string") {
- data = intArrayFromString(data, true);
- }
- if (!data.subarray) {
- data = new Uint8Array(data);
- }
- return data;
- };
- var FS_getMode = (canRead, canWrite) => {
- var mode = 0;
- if (canRead) mode |= 292 | 73;
- if (canWrite) mode |= 146;
- return mode;
- };
- var IDBFS = {
- dbs: {},
- indexedDB: () => {
- assert(typeof indexedDB != "undefined", "IDBFS used, but indexedDB not supported");
- return indexedDB;
- },
- DB_VERSION: 21,
- DB_STORE_NAME: "FILE_DATA",
- queuePersist: mount => {
- function onPersistComplete() {
- if (mount.idbPersistState === "again") startPersist(); else {
- mount.idbPersistState = 0;
- // Otherwise reset sync state back to idle to wait for a new sync later
- IDBFS.onAutoPersistStateChanged?.(false);
- }
- }
- function startPersist() {
- mount.idbPersistState = "idb";
- // Mark that we are currently running a sync operation
- IDBFS.onAutoPersistStateChanged?.(true);
- IDBFS.syncfs(mount, /*populate:*/ false, onPersistComplete);
- }
- if (!mount.idbPersistState) {
- // Programs typically write/copy/move multiple files in the in-memory
- // filesystem within a single app frame, so when a filesystem sync
- // command is triggered, do not start it immediately, but only after
- // the current frame is finished. This way all the modified files
- // inside the main loop tick will be batched up to the same sync.
- mount.idbPersistState = setTimeout(startPersist, 0);
- } else if (mount.idbPersistState === "idb") {
- // There is an active IndexedDB sync operation in-flight, but we now
- // have accumulated more files to sync. We should therefore queue up
- // a new sync after the current one finishes so that all writes
- // will be properly persisted.
- mount.idbPersistState = "again";
- }
- },
- mount: mount => {
- // reuse core MEMFS functionality
- var mnt = MEMFS.mount(mount);
- // If the automatic IDBFS persistence option has been selected, then automatically persist
- // all modifications to the filesystem as they occur.
- if (mount?.opts?.autoPersist) {
- mount.idbPersistState = 0;
- // IndexedDB sync starts in idle state
- var memfs_node_ops = mnt.node_ops;
- mnt.node_ops = {
- ...mnt.node_ops
- };
- // Clone node_ops to inject write tracking
- mnt.node_ops.mknod = (parent, name, mode, dev) => {
- var node = memfs_node_ops.mknod(parent, name, mode, dev);
- // Propagate injected node_ops to the newly created child node
- node.node_ops = mnt.node_ops;
- // Remember for each IDBFS node which IDBFS mount point they came from so we know which mount to persist on modification.
- node.idbfs_mount = mnt.mount;
- // Remember original MEMFS stream_ops for this node
- node.memfs_stream_ops = node.stream_ops;
- // Clone stream_ops to inject write tracking
- node.stream_ops = {
- ...node.stream_ops
- };
- // Track all file writes
- node.stream_ops.write = (stream, buffer, offset, length, position, canOwn) => {
- // This file has been modified, we must persist IndexedDB when this file closes
- stream.node.isModified = true;
- return node.memfs_stream_ops.write(stream, buffer, offset, length, position, canOwn);
- };
- // Persist IndexedDB on file close
- node.stream_ops.close = stream => {
- var n = stream.node;
- if (n.isModified) {
- IDBFS.queuePersist(n.idbfs_mount);
- n.isModified = false;
- }
- if (n.memfs_stream_ops.close) return n.memfs_stream_ops.close(stream);
- };
- // Persist the node we just created to IndexedDB
- IDBFS.queuePersist(mnt.mount);
- return node;
- };
- // Also kick off persisting the filesystem on other operations that modify the filesystem.
- mnt.node_ops.rmdir = (...args) => (IDBFS.queuePersist(mnt.mount), memfs_node_ops.rmdir(...args));
- mnt.node_ops.symlink = (...args) => (IDBFS.queuePersist(mnt.mount), memfs_node_ops.symlink(...args));
- mnt.node_ops.unlink = (...args) => (IDBFS.queuePersist(mnt.mount), memfs_node_ops.unlink(...args));
- mnt.node_ops.rename = (...args) => (IDBFS.queuePersist(mnt.mount), memfs_node_ops.rename(...args));
- }
- return mnt;
- },
- syncfs: (mount, populate, callback) => {
- IDBFS.getLocalSet(mount, (err, local) => {
- if (err) return callback(err);
- IDBFS.getRemoteSet(mount, (err, remote) => {
- if (err) return callback(err);
- var src = populate ? remote : local;
- var dst = populate ? local : remote;
- IDBFS.reconcile(src, dst, callback);
- });
- });
- },
- quit: () => {
- for (var value of Object.values(IDBFS.dbs)) {
- value.close();
- }
- IDBFS.dbs = {};
- },
- getDB: (name, callback) => {
- // check the cache first
- var db = IDBFS.dbs[name];
- if (db) {
- return callback(null, db);
- }
- var req;
- try {
- req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION);
- } catch (e) {
- return callback(e);
- }
- if (!req) {
- return callback("Unable to connect to IndexedDB");
- }
- req.onupgradeneeded = e => {
- var db = /** @type {IDBDatabase} */ (e.target.result);
- var transaction = e.target.transaction;
- var fileStore;
- if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
- fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME);
- } else {
- fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME);
- }
- if (!fileStore.indexNames.contains("timestamp")) {
- fileStore.createIndex("timestamp", "timestamp", {
- unique: false
- });
- }
- };
- req.onsuccess = () => {
- db = /** @type {IDBDatabase} */ (req.result);
- // add to the cache
- IDBFS.dbs[name] = db;
- callback(null, db);
- };
- req.onerror = e => {
- callback(e.target.error);
- e.preventDefault();
- };
- },
- getLocalSet: (mount, callback) => {
- var entries = {};
- function isRealDir(p) {
- return p !== "." && p !== "..";
- }
- function toAbsolute(root) {
- return p => PATH.join2(root, p);
- }
- var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));
- while (check.length) {
- var path = check.pop();
- var stat;
- try {
- stat = FS.lstat(path);
- } catch (e) {
- return callback(e);
- }
- if (FS.isDir(stat.mode)) {
- check.push(...FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
- }
- entries[path] = {
- "timestamp": stat.mtime
- };
- }
- return callback(null, {
- type: "local",
- entries
- });
- },
- getRemoteSet: (mount, callback) => {
- var entries = {};
- IDBFS.getDB(mount.mountpoint, (err, db) => {
- if (err) return callback(err);
- try {
- var transaction = db.transaction([ IDBFS.DB_STORE_NAME ], "readonly");
- transaction.onerror = e => {
- callback(e.target.error);
- e.preventDefault();
- };
- var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
- var index = store.index("timestamp");
- index.openKeyCursor().onsuccess = event => {
- var cursor = event.target.result;
- if (!cursor) {
- return callback(null, {
- type: "remote",
- db,
- entries
- });
- }
- entries[cursor.primaryKey] = {
- "timestamp": cursor.key
- };
- cursor.continue();
- };
- } catch (e) {
- return callback(e);
- }
- });
- },
- loadLocalEntry: (path, callback) => {
- var stat, node;
- try {
- var lookup = FS.lookupPath(path);
- node = lookup.node;
- stat = FS.lstat(path);
- } catch (e) {
- return callback(e);
- }
- if (FS.isDir(stat.mode)) {
- return callback(null, {
- "timestamp": stat.mtime,
- "mode": stat.mode
- });
- } else if (FS.isLink(stat.mode)) {
- return callback(null, {
- "timestamp": stat.mtime,
- "mode": stat.mode,
- "link": node.link
- });
- } else if (FS.isFile(stat.mode)) {
- // Performance consideration: storing a normal JavaScript array to a IndexedDB is much slower than storing a typed array.
- // Therefore always convert the file contents to a typed array first before writing the data to IndexedDB.
- node.contents = MEMFS.getFileDataAsTypedArray(node);
- return callback(null, {
- "timestamp": stat.mtime,
- "mode": stat.mode,
- "contents": node.contents
- });
- } else {
- return callback(new Error("node type not supported"));
- }
- },
- storeLocalEntry: (path, entry, callback) => {
- try {
- if (FS.isDir(entry["mode"])) {
- FS.mkdirTree(path, entry["mode"]);
- } else if (FS.isLink(entry["mode"])) {
- FS.symlink(entry["link"], path);
- } else if (FS.isFile(entry["mode"])) {
- FS.writeFile(path, entry["contents"], {
- canOwn: true
- });
- } else {
- return callback(new Error("node type not supported"));
- }
- FS.chmod(path, entry["mode"]);
- FS.utime(path, entry["timestamp"], entry["timestamp"]);
- } catch (e) {
- return callback(e);
- }
- callback(null);
- },
- removeLocalEntry: (path, callback) => {
- try {
- var stat = FS.lstat(path);
- if (FS.isDir(stat.mode)) {
- FS.rmdir(path);
- } else {
- FS.unlink(path);
- }
- } catch (e) {
- return callback(e);
- }
- callback(null);
- },
- loadRemoteEntry: (store, path, callback) => {
- var req = store.get(path);
- req.onsuccess = event => callback(null, event.target.result);
- req.onerror = e => {
- callback(e.target.error);
- e.preventDefault();
- };
- },
- storeRemoteEntry: (store, path, entry, callback) => {
- try {
- var req = store.put(entry, path);
- } catch (e) {
- callback(e);
- return;
- }
- req.onsuccess = event => callback();
- req.onerror = e => {
- callback(e.target.error);
- e.preventDefault();
- };
- },
- removeRemoteEntry: (store, path, callback) => {
- var req = store.delete(path);
- req.onsuccess = event => callback();
- req.onerror = e => {
- callback(e.target.error);
- e.preventDefault();
- };
- },
- reconcile: (src, dst, callback) => {
- var total = 0;
- var create = [];
- for (var [key, e] of Object.entries(src.entries)) {
- var e2 = dst.entries[key];
- if (!e2 || e["timestamp"].getTime() != e2["timestamp"].getTime()) {
- create.push(key);
- total++;
- }
- }
- var remove = [];
- for (var key of Object.keys(dst.entries)) {
- if (!src.entries[key]) {
- remove.push(key);
- total++;
- }
- }
- if (!total) {
- return callback(null);
- }
- var errored = false;
- var db = src.type === "remote" ? src.db : dst.db;
- var transaction = db.transaction([ IDBFS.DB_STORE_NAME ], "readwrite");
- var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
- function done(err) {
- if (err && !errored) {
- errored = true;
- return callback(err);
- }
- }
- // transaction may abort if (for example) there is a QuotaExceededError
- transaction.onerror = transaction.onabort = e => {
- done(e.target.error);
- e.preventDefault();
- };
- transaction.oncomplete = e => {
- if (!errored) {
- callback(null);
- }
- };
- // sort paths in ascending order so directory entries are created
- // before the files inside them
- for (const path of create.sort()) {
- if (dst.type === "local") {
- IDBFS.loadRemoteEntry(store, path, (err, entry) => {
- if (err) return done(err);
- IDBFS.storeLocalEntry(path, entry, done);
- });
- } else {
- IDBFS.loadLocalEntry(path, (err, entry) => {
- if (err) return done(err);
- IDBFS.storeRemoteEntry(store, path, entry, done);
- });
- }
- }
- // sort paths in descending order so files are deleted before their
- // parent directories
- for (var path of remove.sort().reverse()) {
- if (dst.type === "local") {
- IDBFS.removeLocalEntry(path, done);
- } else {
- IDBFS.removeRemoteEntry(store, path, done);
- }
- }
- }
- };
- var strError = errno => UTF8ToString(_strerror(errno));
- var ERRNO_CODES = {
- "EPERM": 63,
- "ENOENT": 44,
- "ESRCH": 71,
- "EINTR": 27,
- "EIO": 29,
- "ENXIO": 60,
- "E2BIG": 1,
- "ENOEXEC": 45,
- "EBADF": 8,
- "ECHILD": 12,
- "EAGAIN": 6,
- "EWOULDBLOCK": 6,
- "ENOMEM": 48,
- "EACCES": 2,
- "EFAULT": 21,
- "ENOTBLK": 105,
- "EBUSY": 10,
- "EEXIST": 20,
- "EXDEV": 75,
- "ENODEV": 43,
- "ENOTDIR": 54,
- "EISDIR": 31,
- "EINVAL": 28,
- "ENFILE": 41,
- "EMFILE": 33,
- "ENOTTY": 59,
- "ETXTBSY": 74,
- "EFBIG": 22,
- "ENOSPC": 51,
- "ESPIPE": 70,
- "EROFS": 69,
- "EMLINK": 34,
- "EPIPE": 64,
- "EDOM": 18,
- "ERANGE": 68,
- "ENOMSG": 49,
- "EIDRM": 24,
- "ECHRNG": 106,
- "EL2NSYNC": 156,
- "EL3HLT": 107,
- "EL3RST": 108,
- "ELNRNG": 109,
- "EUNATCH": 110,
- "ENOCSI": 111,
- "EL2HLT": 112,
- "EDEADLK": 16,
- "ENOLCK": 46,
- "EBADE": 113,
- "EBADR": 114,
- "EXFULL": 115,
- "ENOANO": 104,
- "EBADRQC": 103,
- "EBADSLT": 102,
- "EDEADLOCK": 16,
- "EBFONT": 101,
- "ENOSTR": 100,
- "ENODATA": 116,
- "ETIME": 117,
- "ENOSR": 118,
- "ENONET": 119,
- "ENOPKG": 120,
- "EREMOTE": 121,
- "ENOLINK": 47,
- "EADV": 122,
- "ESRMNT": 123,
- "ECOMM": 124,
- "EPROTO": 65,
- "EMULTIHOP": 36,
- "EDOTDOT": 125,
- "EBADMSG": 9,
- "ENOTUNIQ": 126,
- "EBADFD": 127,
- "EREMCHG": 128,
- "ELIBACC": 129,
- "ELIBBAD": 130,
- "ELIBSCN": 131,
- "ELIBMAX": 132,
- "ELIBEXEC": 133,
- "ENOSYS": 52,
- "ENOTEMPTY": 55,
- "ENAMETOOLONG": 37,
- "ELOOP": 32,
- "EOPNOTSUPP": 138,
- "EPFNOSUPPORT": 139,
- "ECONNRESET": 15,
- "ENOBUFS": 42,
- "EAFNOSUPPORT": 5,
- "EPROTOTYPE": 67,
- "ENOTSOCK": 57,
- "ENOPROTOOPT": 50,
- "ESHUTDOWN": 140,
- "ECONNREFUSED": 14,
- "EADDRINUSE": 3,
- "ECONNABORTED": 13,
- "ENETUNREACH": 40,
- "ENETDOWN": 38,
- "ETIMEDOUT": 73,
- "EHOSTDOWN": 142,
- "EHOSTUNREACH": 23,
- "EINPROGRESS": 26,
- "EALREADY": 7,
- "EDESTADDRREQ": 17,
- "EMSGSIZE": 35,
- "EPROTONOSUPPORT": 66,
- "ESOCKTNOSUPPORT": 137,
- "EADDRNOTAVAIL": 4,
- "ENETRESET": 39,
- "EISCONN": 30,
- "ENOTCONN": 53,
- "ETOOMANYREFS": 141,
- "EUSERS": 136,
- "EDQUOT": 19,
- "ESTALE": 72,
- "ENOTSUP": 138,
- "ENOMEDIUM": 148,
- "EILSEQ": 25,
- "EOVERFLOW": 61,
- "ECANCELED": 11,
- "ENOTRECOVERABLE": 56,
- "EOWNERDEAD": 62,
- "ESTRPIPE": 135
- };
- var asyncLoad = async url => {
- var arrayBuffer = await readAsync(url);
- assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`);
- return new Uint8Array(arrayBuffer);
- };
- var FS_createDataFile = (...args) => FS.createDataFile(...args);
- var getUniqueRunDependency = id => {
- var orig = id;
- while (1) {
- if (!runDependencyTracking[id]) return id;
- id = orig + Math.random();
- }
- };
- var dependenciesPromise = null;
- var resolveRunDependencies = async () => dependenciesPromise;
- var runDependencies = 0;
- var runDependencyTracking = {};
- var runDependencyWatcher = null;
- var removeRunDependency = id => {
- runDependencies--;
- Module["monitorRunDependencies"]?.(runDependencies);
- assert(id, "removeRunDependency requires an ID");
- assert(runDependencyTracking[id]);
- delete runDependencyTracking[id];
- if (!runDependencies) {
- if (runDependencyWatcher !== null) {
- clearInterval(runDependencyWatcher);
- runDependencyWatcher = null;
- }
- dependenciesPromise.resolve();
- }
- };
- var addRunDependency = id => {
- if (!runDependencies) {
- var resolve;
- dependenciesPromise = new Promise(r => resolve = r);
- dependenciesPromise.resolve = resolve;
- }
- runDependencies++;
- Module["monitorRunDependencies"]?.(runDependencies);
- assert(id, "addRunDependency requires an ID");
- assert(!runDependencyTracking[id]);
- runDependencyTracking[id] = 1;
- if (runDependencyWatcher === null && globalThis.setInterval) {
- // Check for missing dependencies every few seconds
- runDependencyWatcher = setInterval(() => {
- if (ABORT) {
- clearInterval(runDependencyWatcher);
- runDependencyWatcher = null;
- return;
- }
- var shown = false;
- for (var dep in runDependencyTracking) {
- if (!shown) {
- shown = true;
- err("still waiting on run dependencies:");
- }
- err(`dependency: ${dep}`);
- }
- if (shown) {
- err("(end of list)");
- }
- }, 1e4);
- // Prevent this timer from keeping the runtime alive if nothing
- // else is.
- runDependencyWatcher.unref?.();
- }
- };
- var preloadPlugins = [];
- var FS_handledByPreloadPlugin = async (byteArray, fullname) => {
- // Ensure plugins are ready.
- if (typeof Browser != "undefined") Browser.init();
- for (var plugin of preloadPlugins) {
- if (plugin["canHandle"](fullname)) {
- assert(plugin["handle"].constructor.name === "AsyncFunction", "Filesystem plugin handlers must be async functions (See #24914)");
- return plugin["handle"](byteArray, fullname);
- }
- }
- // If no plugin handled this file then return the original/unmodified
- // byteArray.
- return byteArray;
- };
- var FS_preloadFile = async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => {
- // TODO we should allow people to just pass in a complete filename instead
- // of parent and name being that we just join them anyways
- var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
- var dep = getUniqueRunDependency(`cp ${fullname}`);
- // might have several active requests for the same fullname
- addRunDependency(dep);
- try {
- var byteArray = url;
- if (typeof url == "string") {
- byteArray = await asyncLoad(url);
- }
- byteArray = await FS_handledByPreloadPlugin(byteArray, fullname);
- preFinish?.();
- if (!dontCreateFile) {
- FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
- }
- } finally {
- removeRunDependency(dep);
- }
- };
- var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
- FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
- };
- var FS = {
- root: null,
- mounts: [],
- devices: {},
- streams: [],
- nextInode: 1,
- nameTable: null,
- currentPath: "/",
- initialized: false,
- ignorePermissions: true,
- filesystems: null,
- syncFSRequests: 0,
- ErrnoError: class extends Error {
- name="ErrnoError";
- // We set the `name` property to be able to identify `FS.ErrnoError`
- // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway.
- // - when using PROXYFS, an error can come from an underlying FS
- // as different FS objects have their own FS.ErrnoError each,
- // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs.
- // we'll use the reliable test `err.name == "ErrnoError"` instead
- constructor(errno) {
- super(runtimeInitialized ? strError(errno) : "");
- this.errno = errno;
- for (var key in ERRNO_CODES) {
- if (ERRNO_CODES[key] === errno) {
- this.code = key;
- break;
- }
- }
- }
- },
- FSStream: class {
- shared={};
- get object() {
- return this.node;
- }
- set object(val) {
- this.node = val;
- }
- get isRead() {
- return (this.flags & 2097155) !== 1;
- }
- get isWrite() {
- return (this.flags & 2097155) !== 0;
- }
- get isAppend() {
- return (this.flags & 1024);
- }
- get flags() {
- return this.shared.flags;
- }
- set flags(val) {
- this.shared.flags = val;
- }
- get position() {
- return this.shared.position;
- }
- set position(val) {
- this.shared.position = val;
- }
- },
- FSNode: class {
- node_ops={};
- stream_ops={};
- readMode=292 | 73;
- writeMode=146;
- mounted=null;
- constructor(parent, name, mode, rdev) {
- if (!parent) {
- parent = this;
- }
- this.parent = parent;
- this.mount = parent.mount;
- this.id = FS.nextInode++;
- this.name = name;
- this.mode = mode;
- this.rdev = rdev;
- this.atime = this.mtime = this.ctime = Date.now();
- }
- get read() {
- return (this.mode & this.readMode) === this.readMode;
- }
- set read(val) {
- val ? this.mode |= this.readMode : this.mode &= ~this.readMode;
- }
- get write() {
- return (this.mode & this.writeMode) === this.writeMode;
- }
- set write(val) {
- val ? this.mode |= this.writeMode : this.mode &= ~this.writeMode;
- }
- get isFolder() {
- return FS.isDir(this.mode);
- }
- get isDevice() {
- return FS.isChrdev(this.mode);
- }
- },
- lookupPath(path, opts = {}) {
- if (!path) {
- throw new FS.ErrnoError(44);
- }
- opts.follow_mount ??= true;
- if (!PATH.isAbs(path)) {
- path = FS.cwd() + "/" + path;
- }
- // limit max consecutive symlinks to SYMLOOP_MAX.
- linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
- // split the absolute path
- var parts = path.split("/").filter(p => !!p);
- // start at the root
- var current = FS.root;
- var current_path = "/";
- for (var i = 0; i < parts.length; i++) {
- var islast = (i === parts.length - 1);
- if (islast && opts.parent) {
- // stop resolving
- break;
- }
- if (parts[i] === ".") {
- continue;
- }
- if (parts[i] === "..") {
- current_path = PATH.dirname(current_path);
- if (FS.isRoot(current)) {
- path = current_path + "/" + parts.slice(i + 1).join("/");
- // We're making progress here, don't let many consecutive ..'s
- // lead to ELOOP
- nlinks--;
- continue linkloop;
- } else {
- current = current.parent;
- }
- continue;
- }
- current_path = PATH.join2(current_path, parts[i]);
- try {
- current = FS.lookupNode(current, parts[i]);
- } catch (e) {
- // if noent_okay is true, suppress a ENOENT in the last component
- // and return an object with an undefined node. This is needed for
- // resolving symlinks in the path when creating a file.
- if ((e?.errno === 44) && islast && opts.noent_okay) {
- return {
- path: current_path
- };
- }
- throw e;
- }
- // jump to the mount's root node if this is a mountpoint
- if (FS.isMountpoint(current) && (!islast || opts.follow_mount)) {
- current = current.mounted.root;
- }
- // by default, lookupPath will not follow a symlink if it is the final path component.
- // setting opts.follow = true will override this behavior.
- if (FS.isLink(current.mode) && (!islast || opts.follow)) {
- if (!current.node_ops.readlink) {
- throw new FS.ErrnoError(52);
- }
- var link = current.node_ops.readlink(current);
- if (!PATH.isAbs(link)) {
- link = PATH.dirname(current_path) + "/" + link;
- }
- path = link + "/" + parts.slice(i + 1).join("/");
- continue linkloop;
- }
- }
- return {
- path: current_path,
- node: current
- };
- }
- throw new FS.ErrnoError(32);
- },
- getPath(node) {
- var path;
- while (true) {
- if (FS.isRoot(node)) {
- var mount = node.mount.mountpoint;
- if (!path) return mount;
- return mount[mount.length - 1] !== "/" ? `${mount}/${path}` : mount + path;
- }
- path = path ? `${node.name}/${path}` : node.name;
- node = node.parent;
- }
- },
- hashName(parentid, name) {
- var hash = 0;
- for (var i = 0; i < name.length; i++) {
- hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
- }
- return ((parentid + hash) >>> 0) % FS.nameTable.length;
- },
- hashAddNode(node) {
- var hash = FS.hashName(node.parent.id, node.name);
- node.name_next = FS.nameTable[hash];
- FS.nameTable[hash] = node;
- },
- hashRemoveNode(node) {
- var hash = FS.hashName(node.parent.id, node.name);
- if (FS.nameTable[hash] === node) {
- FS.nameTable[hash] = node.name_next;
- } else {
- var current = FS.nameTable[hash];
- while (current) {
- if (current.name_next === node) {
- current.name_next = node.name_next;
- break;
- }
- current = current.name_next;
- }
- }
- },
- lookupNode(parent, name) {
- var errCode = FS.mayLookup(parent);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- var hash = FS.hashName(parent.id, name);
- for (var node = FS.nameTable[hash]; node; node = node.name_next) {
- var nodeName = node.name;
- if (node.parent.id === parent.id && nodeName === name) {
- return node;
- }
- }
- // if we failed to find it in the cache, call into the VFS
- return FS.lookup(parent, name);
- },
- createNode(parent, name, mode, rdev) {
- assert(typeof parent == "object");
- var node = new FS.FSNode(parent, name, mode, rdev);
- FS.hashAddNode(node);
- return node;
- },
- destroyNode(node) {
- FS.hashRemoveNode(node);
- },
- isRoot(node) {
- return node === node.parent;
- },
- isMountpoint(node) {
- return !!node.mounted;
- },
- isFile(mode) {
- return (mode & 61440) === 32768;
- },
- isDir(mode) {
- return (mode & 61440) === 16384;
- },
- isLink(mode) {
- return (mode & 61440) === 40960;
- },
- isChrdev(mode) {
- return (mode & 61440) === 8192;
- },
- isBlkdev(mode) {
- return (mode & 61440) === 24576;
- },
- isFIFO(mode) {
- return (mode & 61440) === 4096;
- },
- isSocket(mode) {
- return (mode & 49152) === 49152;
- },
- flagsToPermissionString(flag) {
- var perms = [ "r", "w", "rw" ][flag & 3];
- if ((flag & 512)) {
- perms += "w";
- }
- return perms;
- },
- nodePermissions(node, perms) {
- if (FS.ignorePermissions) {
- return 0;
- }
- // return 0 if any user, group or owner bits are set.
- if (perms.includes("r") && !(node.mode & 292)) {
- return 2;
- }
- if (perms.includes("w") && !(node.mode & 146)) {
- return 2;
- }
- if (perms.includes("x") && !(node.mode & 73)) {
- return 2;
- }
- return 0;
- },
- mayLookup(dir) {
- if (!FS.isDir(dir.mode)) return 54;
- var errCode = FS.nodePermissions(dir, "x");
- if (errCode) return errCode;
- if (!dir.node_ops.lookup) return 2;
- return 0;
- },
- mayCreate(dir, name) {
- if (!FS.isDir(dir.mode)) {
- return 54;
- }
- try {
- var node = FS.lookupNode(dir, name);
- return 20;
- } catch (e) {}
- return FS.nodePermissions(dir, "wx");
- },
- mayDelete(dir, name, isdir) {
- var node;
- try {
- node = FS.lookupNode(dir, name);
- } catch (e) {
- return e.errno;
- }
- var errCode = FS.nodePermissions(dir, "wx");
- if (errCode) {
- return errCode;
- }
- if (isdir) {
- if (!FS.isDir(node.mode)) {
- return 54;
- }
- if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
- return 10;
- }
- } else if (FS.isDir(node.mode)) {
- return 31;
- }
- return 0;
- },
- mayOpen(node, flags) {
- if (!node) {
- return 44;
- }
- if (FS.isLink(node.mode)) {
- return 32;
- }
- var mode = FS.flagsToPermissionString(flags);
- if (FS.isDir(node.mode)) {
- // opening for write
- // TODO: check for O_SEARCH? (== search for dir only)
- if (mode !== "r" || (flags & (512 | 64))) {
- return 31;
- }
- }
- return FS.nodePermissions(node, mode);
- },
- checkOpExists(op, err) {
- if (!op) {
- throw new FS.ErrnoError(err);
- }
- return op;
- },
- MAX_OPEN_FDS: 4096,
- nextfd() {
- for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) {
- if (!FS.streams[fd]) {
- return fd;
- }
- }
- throw new FS.ErrnoError(33);
- },
- getStreamChecked(fd) {
- var stream = FS.getStream(fd);
- if (!stream) {
- throw new FS.ErrnoError(8);
- }
- return stream;
- },
- getStream: fd => FS.streams[fd],
- createStream(stream, fd = -1) {
- assert(fd >= -1);
- // clone it, so we can return an instance of FSStream
- stream = Object.assign(new FS.FSStream, stream);
- if (fd == -1) {
- fd = FS.nextfd();
- }
- stream.fd = fd;
- FS.streams[fd] = stream;
- return stream;
- },
- closeStream(fd) {
- FS.streams[fd] = null;
- },
- dupStream(origStream, fd = -1) {
- var stream = FS.createStream(origStream, fd);
- stream.stream_ops?.dup?.(stream);
- return stream;
- },
- doSetAttr(stream, node, attr) {
- var setattr = stream?.stream_ops.setattr;
- var arg = setattr ? stream : node;
- setattr ??= node.node_ops.setattr;
- FS.checkOpExists(setattr, 63);
- try {
- setattr(arg, attr);
- } catch (e) {
- if (e instanceof RangeError) {
- throw new FS.ErrnoError(22);
- }
- throw e;
- }
- },
- chrdev_stream_ops: {
- open(stream) {
- var device = FS.getDevice(stream.node.rdev);
- // override node's stream ops with the device's
- stream.stream_ops = device.stream_ops;
- // forward the open call
- stream.stream_ops.open?.(stream);
- },
- llseek() {
- throw new FS.ErrnoError(70);
- }
- },
- major: dev => ((dev) >> 8),
- minor: dev => ((dev) & 255),
- makedev: (ma, mi) => ((ma) << 8 | (mi)),
- registerDevice(dev, ops) {
- FS.devices[dev] = {
- stream_ops: ops
- };
- },
- getDevice: dev => FS.devices[dev],
- getMounts(mount) {
- var mounts = [];
- var check = [ mount ];
- while (check.length) {
- var m = check.pop();
- mounts.push(m);
- check.push(...m.mounts);
- }
- return mounts;
- },
- syncfs(populate, callback) {
- if (typeof populate == "function") {
- callback = populate;
- populate = false;
- }
- FS.syncFSRequests++;
- if (FS.syncFSRequests > 1) {
- err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`);
- }
- var mounts = FS.getMounts(FS.root.mount);
- var completed = 0;
- function doCallback(errCode) {
- assert(FS.syncFSRequests > 0);
- FS.syncFSRequests--;
- return callback(errCode);
- }
- function done(errCode) {
- if (errCode) {
- if (!done.errored) {
- done.errored = true;
- return doCallback(errCode);
- }
- return;
- }
- if (++completed >= mounts.length) {
- doCallback(null);
- }
- }
- // sync all mounts
- for (var mount of mounts) {
- if (mount.type.syncfs) {
- mount.type.syncfs(mount, populate, done);
- } else {
- done(null);
- }
- }
- },
- mount(type, opts, mountpoint) {
- if (typeof type == "string") {
- // The filesystem was not included, and instead we have an error
- // message stored in the variable.
- throw type;
- }
- var root = mountpoint === "/";
- var pseudo = !mountpoint;
- var node;
- if (root && FS.root) {
- throw new FS.ErrnoError(10);
- } else if (!root && !pseudo) {
- var lookup = FS.lookupPath(mountpoint, {
- follow_mount: false
- });
- mountpoint = lookup.path;
- // use the absolute path
- node = lookup.node;
- if (FS.isMountpoint(node)) {
- throw new FS.ErrnoError(10);
- }
- if (!FS.isDir(node.mode)) {
- throw new FS.ErrnoError(54);
- }
- }
- var mount = {
- type,
- opts,
- mountpoint,
- mounts: []
- };
- // create a root node for the fs
- var mountRoot = type.mount(mount);
- mountRoot.mount = mount;
- mount.root = mountRoot;
- if (root) {
- FS.root = mountRoot;
- } else if (node) {
- // set as a mountpoint
- node.mounted = mount;
- // add the new mount to the current mount's children
- if (node.mount) {
- node.mount.mounts.push(mount);
- }
- }
- return mountRoot;
- },
- unmount(mountpoint) {
- var lookup = FS.lookupPath(mountpoint, {
- follow_mount: false
- });
- if (!FS.isMountpoint(lookup.node)) {
- throw new FS.ErrnoError(28);
- }
- // destroy the nodes for this mount, and all its child mounts
- var node = lookup.node;
- var mount = node.mounted;
- var mounts = FS.getMounts(mount);
- for (var [hash, current] of Object.entries(FS.nameTable)) {
- while (current) {
- var next = current.name_next;
- if (mounts.includes(current.mount)) {
- FS.destroyNode(current);
- }
- current = next;
- }
- }
- // no longer a mountpoint
- node.mounted = null;
- // remove this mount from the child mounts
- var idx = node.mount.mounts.indexOf(mount);
- assert(idx !== -1);
- node.mount.mounts.splice(idx, 1);
- },
- lookup(parent, name) {
- return parent.node_ops.lookup(parent, name);
- },
- mknod(path, mode, dev) {
- var lookup = FS.lookupPath(path, {
- parent: true
- });
- var parent = lookup.node;
- var name = PATH.basename(path);
- if (!name) {
- throw new FS.ErrnoError(28);
- }
- if (name === "." || name === "..") {
- throw new FS.ErrnoError(20);
- }
- var errCode = FS.mayCreate(parent, name);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- if (!parent.node_ops.mknod) {
- throw new FS.ErrnoError(63);
- }
- return parent.node_ops.mknod(parent, name, mode, dev);
- },
- statfs(path) {
- return FS.statfsNode(FS.lookupPath(path, {
- follow: true
- }).node);
- },
- statfsStream(stream) {
- // We keep a separate statfsStream function because noderawfs overrides
- // it. In noderawfs, stream.node is sometimes null. Instead, we need to
- // look at stream.path.
- return FS.statfsNode(stream.node);
- },
- statfsNode(node) {
- // NOTE: None of the defaults here are true. We're just returning safe and
- // sane values. Currently nodefs and rawfs replace these defaults,
- // other file systems leave them alone.
- var rtn = {
- bsize: 4096,
- frsize: 4096,
- blocks: 1e6,
- bfree: 5e5,
- bavail: 5e5,
- files: FS.nextInode,
- ffree: FS.nextInode - 1,
- fsid: 42,
- flags: 2,
- namelen: 255
- };
- if (node.node_ops.statfs) {
- Object.assign(rtn, node.node_ops.statfs(node.mount.opts.root));
- }
- return rtn;
- },
- create(path, mode = 438) {
- mode &= 4095;
- mode |= 32768;
- return FS.mknod(path, mode, 0);
- },
- mkdir(path, mode = 511) {
- mode &= 511 | 512;
- mode |= 16384;
- return FS.mknod(path, mode, 0);
- },
- mkdirTree(path, mode) {
- var dirs = path.split("/");
- var d = "";
- for (var dir of dirs) {
- if (!dir) continue;
- if (d || PATH.isAbs(path)) d += "/";
- d += dir;
- try {
- FS.mkdir(d, mode);
- } catch (e) {
- if (e.errno != 20) throw e;
- }
- }
- },
- mkdev(path, mode, dev) {
- if (typeof dev == "undefined") {
- dev = mode;
- mode = 438;
- }
- mode |= 8192;
- return FS.mknod(path, mode, dev);
- },
- symlink(oldpath, newpath) {
- if (!PATH_FS.resolve(oldpath)) {
- throw new FS.ErrnoError(44);
- }
- var lookup = FS.lookupPath(newpath, {
- parent: true
- });
- var parent = lookup.node;
- if (!parent) {
- throw new FS.ErrnoError(44);
- }
- var newname = PATH.basename(newpath);
- var errCode = FS.mayCreate(parent, newname);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- if (!parent.node_ops.symlink) {
- throw new FS.ErrnoError(63);
- }
- return parent.node_ops.symlink(parent, newname, oldpath);
- },
- rename(old_path, new_path) {
- var old_dirname = PATH.dirname(old_path);
- var new_dirname = PATH.dirname(new_path);
- var old_name = PATH.basename(old_path);
- var new_name = PATH.basename(new_path);
- // parents must exist
- var lookup, old_dir, new_dir;
- // let the errors from non existent directories percolate up
- lookup = FS.lookupPath(old_path, {
- parent: true
- });
- old_dir = lookup.node;
- lookup = FS.lookupPath(new_path, {
- parent: true
- });
- new_dir = lookup.node;
- if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
- // need to be part of the same mount
- if (old_dir.mount !== new_dir.mount) {
- throw new FS.ErrnoError(75);
- }
- // source must exist
- var old_node = FS.lookupNode(old_dir, old_name);
- // old path should not be an ancestor of the new path
- var relative = PATH_FS.relative(old_path, new_dirname);
- if (relative.charAt(0) !== ".") {
- throw new FS.ErrnoError(28);
- }
- // new path should not be an ancestor of the old path
- relative = PATH_FS.relative(new_path, old_dirname);
- if (relative.charAt(0) !== ".") {
- throw new FS.ErrnoError(55);
- }
- // see if the new path already exists
- var new_node;
- try {
- new_node = FS.lookupNode(new_dir, new_name);
- } catch (e) {}
- // early out if nothing needs to change
- if (old_node === new_node) {
- return;
- }
- // we'll need to delete the old entry
- var isdir = FS.isDir(old_node.mode);
- var errCode = FS.mayDelete(old_dir, old_name, isdir);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- // need delete permissions if we'll be overwriting.
- // need create permissions if new doesn't already exist.
- errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- if (!old_dir.node_ops.rename) {
- throw new FS.ErrnoError(63);
- }
- if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
- throw new FS.ErrnoError(10);
- }
- // if we are going to change the parent, check write permissions
- if (new_dir !== old_dir) {
- errCode = FS.nodePermissions(old_dir, "w");
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- }
- // remove the node from the lookup hash
- FS.hashRemoveNode(old_node);
- // do the underlying fs rename
- try {
- old_dir.node_ops.rename(old_node, new_dir, new_name);
- // update old node (we do this here to avoid each backend
- // needing to)
- old_node.parent = new_dir;
- } catch (e) {
- throw e;
- } finally {
- // add the node back to the hash (in case node_ops.rename
- // changed its name)
- FS.hashAddNode(old_node);
- }
- },
- rmdir(path) {
- var lookup = FS.lookupPath(path, {
- parent: true
- });
- var parent = lookup.node;
- var name = PATH.basename(path);
- var node = FS.lookupNode(parent, name);
- var errCode = FS.mayDelete(parent, name, true);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- if (!parent.node_ops.rmdir) {
- throw new FS.ErrnoError(63);
- }
- if (FS.isMountpoint(node)) {
- throw new FS.ErrnoError(10);
- }
- parent.node_ops.rmdir(parent, name);
- FS.destroyNode(node);
- },
- readdir(path) {
- var lookup = FS.lookupPath(path, {
- follow: true
- });
- var node = lookup.node;
- var readdir = FS.checkOpExists(node.node_ops.readdir, 54);
- return readdir(node);
- },
- unlink(path) {
- var lookup = FS.lookupPath(path, {
- parent: true
- });
- var parent = lookup.node;
- if (!parent) {
- throw new FS.ErrnoError(44);
- }
- var name = PATH.basename(path);
- var node = FS.lookupNode(parent, name);
- var errCode = FS.mayDelete(parent, name, false);
- if (errCode) {
- // According to POSIX, we should map EISDIR to EPERM, but
- // we instead do what Linux does (and we must, as we use
- // the musl linux libc).
- throw new FS.ErrnoError(errCode);
- }
- if (!parent.node_ops.unlink) {
- throw new FS.ErrnoError(63);
- }
- if (FS.isMountpoint(node)) {
- throw new FS.ErrnoError(10);
- }
- parent.node_ops.unlink(parent, name);
- FS.destroyNode(node);
- },
- readlink(path) {
- var lookup = FS.lookupPath(path);
- var link = lookup.node;
- if (!link) {
- throw new FS.ErrnoError(44);
- }
- if (!link.node_ops.readlink) {
- throw new FS.ErrnoError(28);
- }
- return link.node_ops.readlink(link);
- },
- stat(path, dontFollow) {
- var lookup = FS.lookupPath(path, {
- follow: !dontFollow
- });
- var node = lookup.node;
- var getattr = FS.checkOpExists(node.node_ops.getattr, 63);
- return getattr(node);
- },
- fstat(fd) {
- var stream = FS.getStreamChecked(fd);
- var node = stream.node;
- var getattr = stream.stream_ops.getattr;
- var arg = getattr ? stream : node;
- getattr ??= node.node_ops.getattr;
- FS.checkOpExists(getattr, 63);
- return getattr(arg);
- },
- lstat(path) {
- return FS.stat(path, true);
- },
- doChmod(stream, node, mode, dontFollow) {
- FS.doSetAttr(stream, node, {
- mode: (mode & 4095) | (node.mode & ~4095),
- ctime: Date.now(),
- dontFollow
- });
- },
- chmod(path, mode, dontFollow) {
- var node;
- if (typeof path == "string") {
- var lookup = FS.lookupPath(path, {
- follow: !dontFollow
- });
- node = lookup.node;
- } else {
- node = path;
- }
- FS.doChmod(null, node, mode, dontFollow);
- },
- lchmod(path, mode) {
- FS.chmod(path, mode, true);
- },
- fchmod(fd, mode) {
- var stream = FS.getStreamChecked(fd);
- FS.doChmod(stream, stream.node, mode, false);
- },
- doChown(stream, node, dontFollow) {
- FS.doSetAttr(stream, node, {
- timestamp: Date.now(),
- dontFollow
- });
- },
- chown(path, uid, gid, dontFollow) {
- var node;
- if (typeof path == "string") {
- var lookup = FS.lookupPath(path, {
- follow: !dontFollow
- });
- node = lookup.node;
- } else {
- node = path;
- }
- FS.doChown(null, node, dontFollow);
- },
- lchown(path, uid, gid) {
- FS.chown(path, uid, gid, true);
- },
- fchown(fd, uid, gid) {
- var stream = FS.getStreamChecked(fd);
- FS.doChown(stream, stream.node, false);
- },
- doTruncate(stream, node, len) {
- if (FS.isDir(node.mode)) {
- throw new FS.ErrnoError(31);
- }
- if (!FS.isFile(node.mode)) {
- throw new FS.ErrnoError(28);
- }
- var errCode = FS.nodePermissions(node, "w");
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- FS.doSetAttr(stream, node, {
- size: len,
- timestamp: Date.now()
- });
- },
- truncate(path, len) {
- if (len < 0) {
- throw new FS.ErrnoError(28);
- }
- var node;
- if (typeof path == "string") {
- var lookup = FS.lookupPath(path, {
- follow: true
- });
- node = lookup.node;
- } else {
- node = path;
- }
- FS.doTruncate(null, node, len);
- },
- ftruncate(fd, len) {
- var stream = FS.getStreamChecked(fd);
- if (len < 0 || (stream.flags & 2097155) === 0) {
- throw new FS.ErrnoError(28);
- }
- FS.doTruncate(stream, stream.node, len);
- },
- utime(path, atime, mtime) {
- var lookup = FS.lookupPath(path, {
- follow: true
- });
- var node = lookup.node;
- var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
- setattr(node, {
- atime,
- mtime
- });
- },
- open(path, flags, mode = 438) {
- if (path === "") {
- throw new FS.ErrnoError(44);
- }
- flags = FS_modeStringToFlags(flags);
- if ((flags & 64)) {
- mode = (mode & 4095) | 32768;
- } else {
- mode = 0;
- }
- var node;
- var isDirPath;
- if (typeof path == "object") {
- node = path;
- } else {
- isDirPath = path.endsWith("/");
- // noent_okay makes it so that if the final component of the path
- // doesn't exist, lookupPath returns `node: undefined`. `path` will be
- // updated to point to the target of all symlinks.
- var lookup = FS.lookupPath(path, {
- follow: !(flags & 131072),
- noent_okay: true
- });
- node = lookup.node;
- path = lookup.path;
- }
- // perhaps we need to create the node
- var created = false;
- if ((flags & 64)) {
- if (node) {
- // if O_CREAT and O_EXCL are set, error out if the node already exists
- if ((flags & 128)) {
- throw new FS.ErrnoError(20);
- }
- } else if (isDirPath) {
- throw new FS.ErrnoError(31);
- } else {
- // node doesn't exist, try to create it
- // Ignore the permission bits here to ensure we can `open` this new
- // file below. We use chmod below to apply the permissions once the
- // file is open.
- node = FS.mknod(path, mode | 511, 0);
- created = true;
- }
- }
- if (!node) {
- throw new FS.ErrnoError(44);
- }
- // can't truncate a device
- if (FS.isChrdev(node.mode)) {
- flags &= ~512;
- }
- // if asked only for a directory, then this must be one
- if ((flags & 65536) && !FS.isDir(node.mode)) {
- throw new FS.ErrnoError(54);
- }
- // check permissions, if this is not a file we just created now (it is ok to
- // create and write to a file with read-only permissions; it is read-only
- // for later use)
- if (!created) {
- var errCode = FS.mayOpen(node, flags);
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- }
- // do truncation if necessary
- if ((flags & 512) && !created) {
- FS.truncate(node, 0);
- }
- // we've already handled these, don't pass down to the underlying vfs
- flags &= ~(128 | 512 | 131072);
- // register the stream with the filesystem
- var stream = FS.createStream({
- node,
- path: FS.getPath(node),
- // we want the absolute path to the node
- flags,
- seekable: true,
- position: 0,
- stream_ops: node.stream_ops,
- // used by the file family libc calls (fopen, fwrite, ferror, etc.)
- ungotten: [],
- error: false
- });
- // call the new stream's open function
- if (stream.stream_ops.open) {
- stream.stream_ops.open(stream);
- }
- if (created) {
- FS.chmod(node, mode & 511);
- }
- return stream;
- },
- close(stream) {
- if (FS.isClosed(stream)) {
- throw new FS.ErrnoError(8);
- }
- if (stream.getdents) stream.getdents = null;
- // free readdir state
- try {
- if (stream.stream_ops.close) {
- stream.stream_ops.close(stream);
- }
- } catch (e) {
- throw e;
- } finally {
- FS.closeStream(stream.fd);
- }
- stream.fd = null;
- },
- isClosed(stream) {
- return stream.fd === null;
- },
- llseek(stream, offset, whence) {
- if (FS.isClosed(stream)) {
- throw new FS.ErrnoError(8);
- }
- if (!stream.seekable || !stream.stream_ops.llseek) {
- throw new FS.ErrnoError(70);
- }
- if (whence != 0 && whence != 1 && whence != 2) {
- throw new FS.ErrnoError(28);
- }
- stream.position = stream.stream_ops.llseek(stream, offset, whence);
- stream.ungotten = [];
- return stream.position;
- },
- read(stream, buffer, offset, length, position) {
- assert(offset >= 0);
- if (length < 0 || position < 0) {
- throw new FS.ErrnoError(28);
- }
- if (FS.isClosed(stream)) {
- throw new FS.ErrnoError(8);
- }
- if ((stream.flags & 2097155) === 1) {
- throw new FS.ErrnoError(8);
- }
- if (FS.isDir(stream.node.mode)) {
- throw new FS.ErrnoError(31);
- }
- if (!stream.stream_ops.read) {
- throw new FS.ErrnoError(28);
- }
- var seeking = typeof position != "undefined";
- if (!seeking) {
- position = stream.position;
- } else if (!stream.seekable) {
- throw new FS.ErrnoError(70);
- }
- var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
- if (!seeking) stream.position += bytesRead;
- return bytesRead;
- },
- write(stream, buffer, offset, length, position, canOwn) {
- assert(offset >= 0);
- assert(buffer.subarray, "FS.write expects a TypedArray");
- if (length < 0 || position < 0) {
- throw new FS.ErrnoError(28);
- }
- if (FS.isClosed(stream)) {
- throw new FS.ErrnoError(8);
- }
- if ((stream.flags & 2097155) === 0) {
- throw new FS.ErrnoError(8);
- }
- if (FS.isDir(stream.node.mode)) {
- throw new FS.ErrnoError(31);
- }
- if (!stream.stream_ops.write) {
- throw new FS.ErrnoError(28);
- }
- if (stream.seekable && stream.flags & 1024) {
- // seek to the end before writing in append mode
- FS.llseek(stream, 0, 2);
- }
- var seeking = typeof position != "undefined";
- if (!seeking) {
- position = stream.position;
- } else if (!stream.seekable) {
- throw new FS.ErrnoError(70);
- }
- var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
- if (!seeking) stream.position += bytesWritten;
- return bytesWritten;
- },
- mmap(stream, length, position, prot, flags) {
- // User requests writing to file (prot & PROT_WRITE != 0).
- // Checking if we have permissions to write to the file unless
- // MAP_PRIVATE flag is set. According to POSIX spec it is possible
- // to write to file opened in read-only mode with MAP_PRIVATE flag,
- // as all modifications will be visible only in the memory of
- // the current process.
- if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {
- throw new FS.ErrnoError(2);
- }
- if ((stream.flags & 2097155) === 1) {
- throw new FS.ErrnoError(2);
- }
- if (!stream.stream_ops.mmap) {
- throw new FS.ErrnoError(43);
- }
- if (!length) {
- throw new FS.ErrnoError(28);
- }
- return stream.stream_ops.mmap(stream, length, position, prot, flags);
- },
- msync(stream, buffer, offset, length, mmapFlags) {
- assert(offset >= 0);
- if (!stream.stream_ops.msync) {
- return 0;
- }
- return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
- },
- ioctl(stream, cmd, arg) {
- if (!stream.stream_ops.ioctl) {
- throw new FS.ErrnoError(59);
- }
- return stream.stream_ops.ioctl(stream, cmd, arg);
- },
- readFile(path, opts = {}) {
- opts.flags = opts.flags ?? 0;
- opts.encoding = opts.encoding ?? "binary";
- if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
- abort(`Invalid encoding type "${opts.encoding}"`);
- }
- var stream = FS.open(path, opts.flags);
- var stat = FS.stat(path);
- var length = stat.size;
- var buf = new Uint8Array(length);
- FS.read(stream, buf, 0, length, 0);
- if (opts.encoding === "utf8") {
- buf = UTF8ArrayToString(buf);
- }
- FS.close(stream);
- return buf;
- },
- writeFile(path, data, opts = {}) {
- opts.flags = opts.flags ?? 577;
- var stream = FS.open(path, opts.flags, opts.mode);
- data = FS_fileDataToTypedArray(data);
- FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
- FS.close(stream);
- },
- cwd: () => FS.currentPath,
- chdir(path) {
- var lookup = FS.lookupPath(path, {
- follow: true
- });
- if (lookup.node === null) {
- throw new FS.ErrnoError(44);
- }
- if (!FS.isDir(lookup.node.mode)) {
- throw new FS.ErrnoError(54);
- }
- var errCode = FS.nodePermissions(lookup.node, "x");
- if (errCode) {
- throw new FS.ErrnoError(errCode);
- }
- FS.currentPath = lookup.path;
- },
- createDefaultDirectories() {
- FS.mkdir("/tmp");
- FS.mkdir("/home");
- FS.mkdir("/home/web_user");
- },
- createDefaultDevices() {
- // create /dev
- FS.mkdir("/dev");
- // setup /dev/null
- FS.registerDevice(FS.makedev(1, 3), {
- read: () => 0,
- write: (stream, buffer, offset, length, pos) => length,
- llseek: () => 0
- });
- FS.mkdev("/dev/null", FS.makedev(1, 3));
- // setup /dev/tty and /dev/tty1
- // stderr needs to print output using err() rather than out()
- // so we register a second tty just for it.
- TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
- TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
- FS.mkdev("/dev/tty", FS.makedev(5, 0));
- FS.mkdev("/dev/tty1", FS.makedev(6, 0));
- // setup /dev/[u]random
- // use a buffer to avoid overhead of individual crypto calls per byte
- var randomBuffer = new Uint8Array(1024), randomLeft = 0;
- var randomByte = () => {
- if (randomLeft === 0) {
- randomFill(randomBuffer);
- randomLeft = randomBuffer.byteLength;
- }
- return randomBuffer[--randomLeft];
- };
- FS.createDevice("/dev", "random", randomByte);
- FS.createDevice("/dev", "urandom", randomByte);
- // we're not going to emulate the actual shm device,
- // just create the tmp dirs that reside in it commonly
- FS.mkdir("/dev/shm");
- FS.mkdir("/dev/shm/tmp");
- },
- createSpecialDirectories() {
- // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the
- // name of the stream for fd 6 (see test_unistd_ttyname)
- FS.mkdir("/proc");
- var proc_self = FS.mkdir("/proc/self");
- FS.mkdir("/proc/self/fd");
- FS.mount({
- mount() {
- var node = FS.createNode(proc_self, "fd", 16895, 73);
- node.stream_ops = {
- llseek: MEMFS.stream_ops.llseek
- };
- node.node_ops = {
- lookup(parent, name) {
- var fd = +name;
- var stream = FS.getStreamChecked(fd);
- var ret = {
- parent: null,
- mount: {
- mountpoint: "fake"
- },
- node_ops: {
- readlink: () => stream.path
- },
- id: fd + 1
- };
- ret.parent = ret;
- // make it look like a simple root node
- return ret;
- },
- readdir() {
- return Array.from(FS.streams.entries()).filter(([k, v]) => v).map(([k, v]) => k.toString());
- }
- };
- return node;
- }
- }, {}, "/proc/self/fd");
- },
- createStandardStreams(input, output, error) {
- // TODO deprecate the old functionality of a single
- // input / output callback and that utilizes FS.createDevice
- // and instead require a unique set of stream ops
- // by default, we symlink the standard streams to the
- // default tty devices. however, if the standard streams
- // have been overwritten we create a unique device for
- // them instead.
- if (input) {
- FS.createDevice("/dev", "stdin", input);
- } else {
- FS.symlink("/dev/tty", "/dev/stdin");
- }
- if (output) {
- FS.createDevice("/dev", "stdout", null, output);
- } else {
- FS.symlink("/dev/tty", "/dev/stdout");
- }
- if (error) {
- FS.createDevice("/dev", "stderr", null, error);
- } else {
- FS.symlink("/dev/tty1", "/dev/stderr");
- }
- // open default streams for the stdin, stdout and stderr devices
- var stdin = FS.open("/dev/stdin", 0);
- var stdout = FS.open("/dev/stdout", 1);
- var stderr = FS.open("/dev/stderr", 1);
- assert(stdin.fd === 0, `invalid handle for stdin (${stdin.fd})`);
- assert(stdout.fd === 1, `invalid handle for stdout (${stdout.fd})`);
- assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`);
- },
- staticInit() {
- FS.nameTable = new Array(4096);
- FS.mount(MEMFS, {}, "/");
- FS.createDefaultDirectories();
- FS.createDefaultDevices();
- FS.createSpecialDirectories();
- FS.filesystems = {
- "MEMFS": MEMFS,
- "IDBFS": IDBFS
- };
- },
- init(input, output, error) {
- assert(!FS.initialized, "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");
- FS.initialized = true;
- // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
- input ??= Module["stdin"];
- output ??= Module["stdout"];
- error ??= Module["stderr"];
- FS.createStandardStreams(input, output, error);
- },
- quit() {
- FS.initialized = false;
- // force-flush all streams, so we get musl std streams printed out
- _fflush(0);
- // close all of our streams
- for (var stream of FS.streams) {
- if (stream) {
- FS.close(stream);
- }
- }
- },
- findObject(path, dontResolveLastLink) {
- var ret = FS.analyzePath(path, dontResolveLastLink);
- if (!ret.exists) {
- return null;
- }
- return ret.object;
- },
- analyzePath(path, dontResolveLastLink) {
- // operate from within the context of the symlink's target
- try {
- var lookup = FS.lookupPath(path, {
- follow: !dontResolveLastLink
- });
- path = lookup.path;
- } catch (e) {}
- var ret = {
- isRoot: false,
- exists: false,
- error: 0,
- name: null,
- path: null,
- object: null,
- parentExists: false,
- parentPath: null,
- parentObject: null
- };
- try {
- var lookup = FS.lookupPath(path, {
- parent: true
- });
- ret.parentExists = true;
- ret.parentPath = lookup.path;
- ret.parentObject = lookup.node;
- ret.name = PATH.basename(path);
- lookup = FS.lookupPath(path, {
- follow: !dontResolveLastLink
- });
- ret.exists = true;
- ret.path = lookup.path;
- ret.object = lookup.node;
- ret.name = lookup.node.name;
- ret.isRoot = lookup.path === "/";
- } catch (e) {
- ret.error = e.errno;
- }
- return ret;
- },
- createPath(parent, path, canRead, canWrite) {
- parent = typeof parent == "string" ? parent : FS.getPath(parent);
- var parts = path.split("/").reverse();
- while (parts.length) {
- var part = parts.pop();
- if (!part) continue;
- var current = PATH.join2(parent, part);
- try {
- FS.mkdir(current);
- } catch (e) {
- if (e.errno != 20) throw e;
- }
- parent = current;
- }
- return current;
- },
- createFile(parent, name, properties, canRead, canWrite) {
- var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
- var mode = FS_getMode(canRead, canWrite);
- return FS.create(path, mode);
- },
- createDataFile(parent, name, data, canRead, canWrite, canOwn) {
- var path = name;
- if (parent) {
- parent = typeof parent == "string" ? parent : FS.getPath(parent);
- path = name ? PATH.join2(parent, name) : parent;
- }
- var mode = FS_getMode(canRead, canWrite);
- var node = FS.create(path, mode);
- if (data) {
- data = FS_fileDataToTypedArray(data);
- // make sure we can write to the file
- FS.chmod(node, mode | 146);
- var stream = FS.open(node, 577);
- FS.write(stream, data, 0, data.length, 0, canOwn);
- FS.close(stream);
- FS.chmod(node, mode);
- }
- },
- createDevice(parent, name, input, output) {
- var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
- var mode = FS_getMode(!!input, !!output);
- FS.createDevice.major ??= 64;
- var dev = FS.makedev(FS.createDevice.major++, 0);
- // Create a fake device that a set of stream ops to emulate
- // the old behavior.
- FS.registerDevice(dev, {
- open(stream) {
- stream.seekable = false;
- },
- close(stream) {
- // flush any pending line data
- if (output?.buffer?.length) {
- output(10);
- }
- },
- read(stream, buffer, offset, length, pos) {
- var bytesRead = 0;
- for (var i = 0; i < length; i++) {
- var result;
- try {
- result = input();
- } catch (e) {
- throw new FS.ErrnoError(29);
- }
- if (result === undefined && bytesRead === 0) {
- throw new FS.ErrnoError(6);
- }
- if (result === null || result === undefined) break;
- bytesRead++;
- buffer[offset + i] = result;
- }
- if (bytesRead) {
- stream.node.atime = Date.now();
- }
- return bytesRead;
- },
- write(stream, buffer, offset, length, pos) {
- for (var i = 0; i < length; i++) {
- try {
- output(buffer[offset + i]);
- } catch (e) {
- throw new FS.ErrnoError(29);
- }
- }
- if (length) {
- stream.node.mtime = stream.node.ctime = Date.now();
- }
- return i;
- }
- });
- return FS.mkdev(path, mode, dev);
- },
- forceLoadFile(obj) {
- if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
- if (globalThis.XMLHttpRequest) {
- abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
- } else {
- // Command-line.
- try {
- obj.contents = readBinary(obj.url);
- } catch (e) {
- throw new FS.ErrnoError(29);
- }
- }
- },
- createLazyFile(parent, name, url, canRead, canWrite) {
- // Lazy chunked Uint8Array (implements get and length from Uint8Array).
- // Actual getting is abstracted away for eventual reuse.
- class LazyUint8Array {
- lengthKnown=false;
- chunks=[];
- // Loaded chunks. Index is the chunk number
- get(idx) {
- if (idx > this.length - 1 || idx < 0) {
- return undefined;
- }
- var chunkOffset = idx % this.chunkSize;
- var chunkNum = (idx / this.chunkSize) | 0;
- return this.getter(chunkNum)[chunkOffset];
- }
- setDataGetter(getter) {
- this.getter = getter;
- }
- cacheLength() {
- // Find length
- var xhr = new XMLHttpRequest;
- xhr.open("HEAD", url, false);
- xhr.send(null);
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
- var datalength = Number(xhr.getResponseHeader("Content-length"));
- var header;
- var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
- var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
- var chunkSize = 1024 * 1024;
- // Chunk size in bytes
- if (!hasByteServing) chunkSize = datalength;
- // Function to get a range from the remote URL.
- var doXHR = (from, to) => {
- if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`);
- if (to > datalength - 1) abort(`only ${datalength} bytes available! programmer error!`);
- // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
- var xhr = new XMLHttpRequest;
- xhr.open("GET", url, false);
- if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
- // Some hints to the browser that we want binary data.
- xhr.responseType = "arraybuffer";
- if (xhr.overrideMimeType) {
- xhr.overrideMimeType("text/plain; charset=x-user-defined");
- }
- xhr.send(null);
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
- if (xhr.response !== undefined) {
- return new Uint8Array(/** @type{Array<number>} */ (xhr.response || []));
- }
- return intArrayFromString(xhr.responseText ?? "", true);
- };
- var lazyArray = this;
- lazyArray.setDataGetter(chunkNum => {
- var start = chunkNum * chunkSize;
- var end = (chunkNum + 1) * chunkSize - 1;
- // including this byte
- end = Math.min(end, datalength - 1);
- // if datalength-1 is selected, this is the last block
- if (typeof lazyArray.chunks[chunkNum] == "undefined") {
- lazyArray.chunks[chunkNum] = doXHR(start, end);
- }
- if (typeof lazyArray.chunks[chunkNum] == "undefined") abort("doXHR failed!");
- return lazyArray.chunks[chunkNum];
- });
- if (usesGzip || !datalength) {
- // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
- chunkSize = datalength = 1;
- // this will force getter(0)/doXHR do download the whole file
- datalength = this.getter(0).length;
- chunkSize = datalength;
- out("LazyFiles on gzip forces download of the whole file when length is accessed");
- }
- this._length = datalength;
- this._chunkSize = chunkSize;
- this.lengthKnown = true;
- }
- get length() {
- if (!this.lengthKnown) {
- this.cacheLength();
- }
- return this._length;
- }
- get chunkSize() {
- if (!this.lengthKnown) {
- this.cacheLength();
- }
- return this._chunkSize;
- }
- }
- if (globalThis.XMLHttpRequest) {
- if (!ENVIRONMENT_IS_WORKER) abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");
- var lazyArray = new LazyUint8Array;
- var properties = {
- isDevice: false,
- contents: lazyArray
- };
- } else {
- var properties = {
- isDevice: false,
- url
- };
- }
- var node = FS.createFile(parent, name, properties, canRead, canWrite);
- // This is a total hack, but I want to get this lazy file code out of the
- // core of MEMFS. If we want to keep this lazy file concept I feel it should
- // be its own thin LAZYFS proxying calls to MEMFS.
- if (properties.contents) {
- node.contents = properties.contents;
- } else if (properties.url) {
- node.contents = null;
- node.url = properties.url;
- }
- // Add a function that defers querying the file size until it is asked the first time.
- Object.defineProperties(node, {
- usedBytes: {
- get: function() {
- return this.contents.length;
- }
- }
- });
- // override each stream op with one that tries to force load the lazy file first
- var stream_ops = {};
- for (const [key, fn] of Object.entries(node.stream_ops)) {
- stream_ops[key] = (...args) => {
- FS.forceLoadFile(node);
- return fn(...args);
- };
- }
- function writeChunks(stream, buffer, offset, length, position) {
- var contents = stream.node.contents;
- if (position >= contents.length) return 0;
- var size = Math.min(contents.length - position, length);
- assert(size >= 0);
- if (contents.slice) {
- // normal array
- for (var i = 0; i < size; i++) {
- buffer[offset + i] = contents[position + i];
- }
- } else {
- for (var i = 0; i < size; i++) {
- // LazyUint8Array from sync binary XHR
- buffer[offset + i] = contents.get(position + i);
- }
- }
- return size;
- }
- // use a custom read function
- stream_ops.read = (stream, buffer, offset, length, position) => {
- FS.forceLoadFile(node);
- return writeChunks(stream, buffer, offset, length, position);
- };
- // use a custom mmap function
- stream_ops.mmap = (stream, length, position, prot, flags) => {
- FS.forceLoadFile(node);
- var ptr = mmapAlloc(length);
- if (!ptr) {
- throw new FS.ErrnoError(48);
- }
- writeChunks(stream, (growMemViews(), HEAP8), ptr, length, position);
- return {
- ptr,
- allocated: true
- };
- };
- node.stream_ops = stream_ops;
- return node;
- }
- };
- var SYSCALLS = {
- currentUmask: 18,
- calculateAt(dirfd, path, allowEmpty) {
- if (PATH.isAbs(path)) {
- return path;
- }
- // relative path
- var dir;
- if (dirfd === -100) {
- dir = FS.cwd();
- } else {
- var dirstream = SYSCALLS.getStreamFromFD(dirfd);
- dir = dirstream.path;
- }
- if (path.length == 0) {
- if (!allowEmpty) {
- throw new FS.ErrnoError(44);
- }
- return dir;
- }
- return dir + "/" + path;
- },
- writeStat(buf, stat) {
- (growMemViews(), HEAPU32)[((buf) >> 2)] = stat.dev;
- (growMemViews(), HEAPU32)[(((buf) + (4)) >> 2)] = stat.mode;
- (growMemViews(), HEAPU32)[(((buf) + (8)) >> 2)] = stat.nlink;
- (growMemViews(), HEAPU32)[(((buf) + (12)) >> 2)] = stat.uid;
- (growMemViews(), HEAPU32)[(((buf) + (16)) >> 2)] = stat.gid;
- (growMemViews(), HEAPU32)[(((buf) + (20)) >> 2)] = stat.rdev;
- (growMemViews(), HEAP64)[(((buf) + (24)) >> 3)] = BigInt(stat.size);
- (growMemViews(), HEAP32)[(((buf) + (32)) >> 2)] = 4096;
- (growMemViews(), HEAP32)[(((buf) + (36)) >> 2)] = stat.blocks;
- var atime = stat.atime.getTime();
- var mtime = stat.mtime.getTime();
- var ctime = stat.ctime.getTime();
- (growMemViews(), HEAP64)[(((buf) + (40)) >> 3)] = BigInt(Math.floor(atime / 1e3));
- (growMemViews(), HEAPU32)[(((buf) + (48)) >> 2)] = (atime % 1e3) * 1e3 * 1e3;
- (growMemViews(), HEAP64)[(((buf) + (56)) >> 3)] = BigInt(Math.floor(mtime / 1e3));
- (growMemViews(), HEAPU32)[(((buf) + (64)) >> 2)] = (mtime % 1e3) * 1e3 * 1e3;
- (growMemViews(), HEAP64)[(((buf) + (72)) >> 3)] = BigInt(Math.floor(ctime / 1e3));
- (growMemViews(), HEAPU32)[(((buf) + (80)) >> 2)] = (ctime % 1e3) * 1e3 * 1e3;
- (growMemViews(), HEAP64)[(((buf) + (88)) >> 3)] = BigInt(stat.ino);
- return 0;
- },
- writeStatFs(buf, stats) {
- (growMemViews(), HEAPU32)[(((buf) + (4)) >> 2)] = stats.bsize;
- (growMemViews(), HEAPU32)[(((buf) + (60)) >> 2)] = stats.bsize;
- (growMemViews(), HEAP64)[(((buf) + (8)) >> 3)] = BigInt(stats.blocks);
- (growMemViews(), HEAP64)[(((buf) + (16)) >> 3)] = BigInt(stats.bfree);
- (growMemViews(), HEAP64)[(((buf) + (24)) >> 3)] = BigInt(stats.bavail);
- (growMemViews(), HEAP64)[(((buf) + (32)) >> 3)] = BigInt(stats.files);
- (growMemViews(), HEAP64)[(((buf) + (40)) >> 3)] = BigInt(stats.ffree);
- (growMemViews(), HEAPU32)[(((buf) + (48)) >> 2)] = stats.fsid;
- (growMemViews(), HEAPU32)[(((buf) + (64)) >> 2)] = stats.flags;
- // ST_NOSUID
- (growMemViews(), HEAPU32)[(((buf) + (56)) >> 2)] = stats.namelen;
- },
- doMsync(addr, stream, len, flags, offset) {
- if (!FS.isFile(stream.node.mode)) {
- throw new FS.ErrnoError(43);
- }
- if (flags & 2) {
- // MAP_PRIVATE calls need not to be synced back to underlying fs
- return 0;
- }
- var buffer = (growMemViews(), HEAPU8).subarray(addr, addr + len);
- FS.msync(stream, buffer, offset, len, flags);
- },
- getStreamFromFD(fd) {
- var stream = FS.getStreamChecked(fd);
- return stream;
- },
- varargs: undefined,
- getStr(ptr) {
- var ret = UTF8ToString(ptr);
- return ret;
- }
- };
- function ___syscall_chdir(path) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(3, 0, 1, path);
- try {
- path = SYSCALLS.getStr(path);
- FS.chdir(path);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- var syscallGetVarargI = () => {
- assert(SYSCALLS.varargs != undefined);
- // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number.
- var ret = (growMemViews(), HEAP32)[((+SYSCALLS.varargs) >> 2)];
- SYSCALLS.varargs += 4;
- return ret;
- };
- var syscallGetVarargP = syscallGetVarargI;
- function ___syscall_fcntl64(fd, cmd, varargs) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(4, 0, 1, fd, cmd, varargs);
- SYSCALLS.varargs = varargs;
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- switch (cmd) {
- case 0:
- {
- var arg = syscallGetVarargI();
- if (arg < 0) {
- return -28;
- }
- while (FS.streams[arg]) {
- arg++;
- }
- var newStream;
- newStream = FS.dupStream(stream, arg);
- return newStream.fd;
- }
- case 1:
- case 2:
- return 0;
- // FD_CLOEXEC makes no sense for a single process.
- case 3:
- return stream.flags;
- case 4:
- {
- var arg = syscallGetVarargI();
- var mask = 289792;
- stream.flags = (stream.flags & ~mask) | (arg & mask);
- return 0;
- }
- case 12:
- {
- var arg = syscallGetVarargP();
- var offset = 0;
- // We're always unlocked.
- (growMemViews(), HEAP16)[(((arg) + (offset)) >> 1)] = 2;
- return 0;
- }
- case 13:
- case 14:
- // Pretend that the locking is successful. These are process-level locks,
- // and Emscripten programs are a single process. If we supported linking a
- // filesystem between programs, we'd need to do more here.
- // See https://github.com/emscripten-core/emscripten/issues/23697
- return 0;
- }
- return -28;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_fstat64(fd, buf) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(5, 0, 1, fd, buf);
- try {
- return SYSCALLS.writeStat(buf, FS.fstat(fd));
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
- assert(typeof maxBytesToWrite == "number", "stringToUTF8 requires a third parameter that specifies the length of the output buffer");
- return stringToUTF8Array(str, (growMemViews(), HEAPU8), outPtr, maxBytesToWrite);
- };
- function ___syscall_getcwd(buf, size) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(6, 0, 1, buf, size);
- try {
- if (size === 0) return -28;
- var cwd = FS.cwd();
- var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
- if (size < cwdLengthInBytes) return -68;
- stringToUTF8(cwd, buf, size);
- return cwdLengthInBytes;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_ioctl(fd, op, varargs) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(7, 0, 1, fd, op, varargs);
- SYSCALLS.varargs = varargs;
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- switch (op) {
- case 21509:
- {
- if (!stream.tty) return -59;
- return 0;
- }
- case 21505:
- {
- if (!stream.tty) return -59;
- if (stream.tty.ops.ioctl_tcgets) {
- var termios = stream.tty.ops.ioctl_tcgets(stream);
- var argp = syscallGetVarargP();
- (growMemViews(), HEAP32)[((argp) >> 2)] = termios.c_iflag || 0;
- (growMemViews(), HEAP32)[(((argp) + (4)) >> 2)] = termios.c_oflag || 0;
- (growMemViews(), HEAP32)[(((argp) + (8)) >> 2)] = termios.c_cflag || 0;
- (growMemViews(), HEAP32)[(((argp) + (12)) >> 2)] = termios.c_lflag || 0;
- for (var i = 0; i < 32; i++) {
- (growMemViews(), HEAP8)[(argp + i) + (17)] = termios.c_cc[i] || 0;
- }
- return 0;
- }
- return 0;
- }
- case 21510:
- case 21511:
- case 21512:
- {
- if (!stream.tty) return -59;
- return 0;
- }
- case 21506:
- case 21507:
- case 21508:
- {
- if (!stream.tty) return -59;
- if (stream.tty.ops.ioctl_tcsets) {
- var argp = syscallGetVarargP();
- var c_iflag = (growMemViews(), HEAP32)[((argp) >> 2)];
- var c_oflag = (growMemViews(), HEAP32)[(((argp) + (4)) >> 2)];
- var c_cflag = (growMemViews(), HEAP32)[(((argp) + (8)) >> 2)];
- var c_lflag = (growMemViews(), HEAP32)[(((argp) + (12)) >> 2)];
- var c_cc = [];
- for (var i = 0; i < 32; i++) {
- c_cc.push((growMemViews(), HEAP8)[(argp + i) + (17)]);
- }
- return stream.tty.ops.ioctl_tcsets(stream.tty, op, {
- c_iflag,
- c_oflag,
- c_cflag,
- c_lflag,
- c_cc
- });
- }
- return 0;
- }
- case 21519:
- {
- if (!stream.tty) return -59;
- var argp = syscallGetVarargP();
- (growMemViews(), HEAP32)[((argp) >> 2)] = 0;
- return 0;
- }
- case 21520:
- {
- if (!stream.tty) return -59;
- return -28;
- }
- case 21537:
- case 21531:
- {
- var argp = syscallGetVarargP();
- return FS.ioctl(stream, op, argp);
- }
- case 21523:
- {
- // TODO: in theory we should write to the winsize struct that gets
- // passed in, but for now musl doesn't read anything on it
- if (!stream.tty) return -59;
- if (stream.tty.ops.ioctl_tiocgwinsz) {
- var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
- var argp = syscallGetVarargP();
- (growMemViews(), HEAP16)[((argp) >> 1)] = winsize[0];
- (growMemViews(), HEAP16)[(((argp) + (2)) >> 1)] = winsize[1];
- }
- return 0;
- }
- case 21524:
- {
- // TODO: technically, this ioctl call should change the window size.
- // but, since emscripten doesn't have any concept of a terminal window
- // yet, we'll just silently throw it away as we do TIOCGWINSZ
- if (!stream.tty) return -59;
- return 0;
- }
- case 21515:
- {
- if (!stream.tty) return -59;
- return 0;
- }
- default:
- return -28;
- }
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_lstat64(path, buf) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(8, 0, 1, path, buf);
- try {
- path = SYSCALLS.getStr(path);
- return SYSCALLS.writeStat(buf, FS.lstat(path));
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_mkdirat(dirfd, path, mode) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(9, 0, 1, dirfd, path, mode);
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- mode &= ~SYSCALLS.currentUmask;
- FS.mkdir(path, mode, 0);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_newfstatat(dirfd, path, buf, flags) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(10, 0, 1, dirfd, path, buf, flags);
- try {
- path = SYSCALLS.getStr(path);
- var nofollow = flags & 256;
- var allowEmpty = flags & 4096;
- flags = flags & (~6400);
- assert(!flags, `unknown flags in __syscall_newfstatat: ${flags}`);
- path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
- return SYSCALLS.writeStat(buf, nofollow ? FS.lstat(path) : FS.stat(path));
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_openat(dirfd, path, flags, varargs) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(11, 0, 1, dirfd, path, flags, varargs);
- SYSCALLS.varargs = varargs;
- try {
- path = SYSCALLS.getStr(path);
- path = SYSCALLS.calculateAt(dirfd, path);
- var mode = varargs ? syscallGetVarargI() : 0;
- if (flags & 64) {
- mode &= ~SYSCALLS.currentUmask;
- }
- return FS.open(path, flags, mode).fd;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- var PIPEFS = {
- BUCKET_BUFFER_SIZE: 8192,
- mount(mount) {
- // Do not pollute the real root directory or its child nodes with pipes
- // Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way
- return FS.createNode(null, "/", 16384 | 511, 0);
- },
- createPipe() {
- var pipe = {
- buckets: [],
- // refcnt 2 because pipe has a read end and a write end. We need to be
- // able to read from the read end after write end is closed.
- refcnt: 2,
- timestamp: new Date,
- readableHandlers: [],
- registerReadableHandler: callback => {
- callback.registerCleanupFunc(() => {
- const i = pipe.readableHandlers.indexOf(callback);
- if (i !== -1) pipe.readableHandlers.splice(i, 1);
- });
- pipe.readableHandlers.push(callback);
- },
- notifyReadableHandlers: () => {
- while (pipe.readableHandlers.length > 0) {
- const cb = pipe.readableHandlers.shift();
- if (cb) cb(64 | 1);
- }
- pipe.readableHandlers = [];
- }
- };
- pipe.buckets.push({
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: 0,
- roffset: 0
- });
- var rName = PIPEFS.nextname();
- var wName = PIPEFS.nextname();
- var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0);
- var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0);
- rNode.pipe = pipe;
- wNode.pipe = pipe;
- var readableStream = FS.createStream({
- path: rName,
- node: rNode,
- flags: 0,
- seekable: false,
- stream_ops: PIPEFS.stream_ops
- });
- rNode.stream = readableStream;
- var writableStream = FS.createStream({
- path: wName,
- node: wNode,
- flags: 1,
- seekable: false,
- stream_ops: PIPEFS.stream_ops
- });
- wNode.stream = writableStream;
- return {
- readable_fd: readableStream.fd,
- writable_fd: writableStream.fd
- };
- },
- stream_ops: {
- getattr(stream) {
- var node = stream.node;
- var timestamp = node.pipe.timestamp;
- return {
- dev: 14,
- ino: node.id,
- mode: 4480,
- nlink: 1,
- uid: 0,
- gid: 0,
- rdev: 0,
- size: 0,
- atime: timestamp,
- mtime: timestamp,
- ctime: timestamp,
- blksize: 4096,
- blocks: 0
- };
- },
- poll(stream, timeout, notifyCallback) {
- var pipe = stream.node.pipe;
- if ((stream.flags & 2097155) === 1) {
- return (256 | 4);
- }
- for (var bucket of pipe.buckets) {
- if (bucket.offset - bucket.roffset > 0) {
- return (64 | 1);
- }
- }
- if (notifyCallback) pipe.registerReadableHandler(notifyCallback);
- return 0;
- },
- dup(stream) {
- stream.node.pipe.refcnt++;
- },
- ioctl(stream, request, argp) {
- if (request == 21531) {
- var pipe = stream.node.pipe;
- var currentLength = 0;
- for (var bucket of pipe.buckets) {
- currentLength += bucket.offset - bucket.roffset;
- }
- (growMemViews(), HEAP32)[((argp) >> 2)] = currentLength;
- return 0;
- }
- return 28;
- },
- fsync(stream) {
- return 28;
- },
- read(stream, buffer, offset, length, position) {
- var pipe = stream.node.pipe;
- var currentLength = 0;
- for (var bucket of pipe.buckets) {
- currentLength += bucket.offset - bucket.roffset;
- }
- assert(buffer instanceof ArrayBuffer || buffer instanceof SharedArrayBuffer || ArrayBuffer.isView(buffer));
- var data = buffer.subarray(offset, offset + length);
- if (length <= 0) {
- return 0;
- }
- if (currentLength == 0) {
- // Behave as if the read end is always non-blocking
- throw new FS.ErrnoError(6);
- }
- var toRead = Math.min(currentLength, length);
- var totalRead = toRead;
- var toRemove = 0;
- for (var bucket of pipe.buckets) {
- var bucketSize = bucket.offset - bucket.roffset;
- if (toRead <= bucketSize) {
- var tmpSlice = bucket.buffer.subarray(bucket.roffset, bucket.offset);
- if (toRead < bucketSize) {
- tmpSlice = tmpSlice.subarray(0, toRead);
- bucket.roffset += toRead;
- } else {
- toRemove++;
- }
- data.set(tmpSlice);
- break;
- } else {
- var tmpSlice = bucket.buffer.subarray(bucket.roffset, bucket.offset);
- data.set(tmpSlice);
- data = data.subarray(tmpSlice.byteLength);
- toRead -= tmpSlice.byteLength;
- toRemove++;
- }
- }
- if (toRemove && toRemove == pipe.buckets.length) {
- // Do not generate excessive garbage in use cases such as
- // write several bytes, read everything, write several bytes, read everything...
- toRemove--;
- pipe.buckets[toRemove].offset = 0;
- pipe.buckets[toRemove].roffset = 0;
- }
- pipe.buckets.splice(0, toRemove);
- return totalRead;
- },
- write(stream, buffer, offset, length, position) {
- var pipe = stream.node.pipe;
- assert(buffer instanceof ArrayBuffer || buffer instanceof SharedArrayBuffer || ArrayBuffer.isView(buffer));
- var data = buffer.subarray(offset, offset + length);
- var dataLen = data.byteLength;
- if (dataLen <= 0) {
- return 0;
- }
- var currBucket = null;
- if (pipe.buckets.length == 0) {
- currBucket = {
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: 0,
- roffset: 0
- };
- pipe.buckets.push(currBucket);
- } else {
- currBucket = pipe.buckets[pipe.buckets.length - 1];
- }
- assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE);
- var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset;
- if (freeBytesInCurrBuffer >= dataLen) {
- currBucket.buffer.set(data, currBucket.offset);
- currBucket.offset += dataLen;
- pipe.notifyReadableHandlers();
- return dataLen;
- } else if (freeBytesInCurrBuffer > 0) {
- currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
- currBucket.offset += freeBytesInCurrBuffer;
- data = data.subarray(freeBytesInCurrBuffer, data.byteLength);
- }
- var numBuckets = (data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0;
- var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE;
- for (var i = 0; i < numBuckets; i++) {
- var newBucket = {
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: PIPEFS.BUCKET_BUFFER_SIZE,
- roffset: 0
- };
- pipe.buckets.push(newBucket);
- newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE));
- data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength);
- }
- if (remElements > 0) {
- var newBucket = {
- buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
- offset: data.byteLength,
- roffset: 0
- };
- pipe.buckets.push(newBucket);
- newBucket.buffer.set(data);
- }
- pipe.notifyReadableHandlers();
- return dataLen;
- },
- close(stream) {
- var pipe = stream.node.pipe;
- pipe.refcnt--;
- if (pipe.refcnt === 0) {
- pipe.buckets = null;
- }
- }
- },
- nextname() {
- if (!PIPEFS.nextname.current) {
- PIPEFS.nextname.current = 0;
- }
- return "pipe[" + (PIPEFS.nextname.current++) + "]";
- }
- };
- function ___syscall_pipe2(fdPtr, flags) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(12, 0, 1, fdPtr, flags);
- try {
- if (fdPtr == 0) {
- throw new FS.ErrnoError(21);
- }
- var validFlags = 524288 | 2048;
- if (flags & ~validFlags) {
- throw new FS.ErrnoError(138);
- }
- var res = PIPEFS.createPipe();
- if (flags & 2048) {
- FS.getStream(res.readable_fd).flags |= 2048;
- FS.getStream(res.writable_fd).flags |= 2048;
- }
- (growMemViews(), HEAP32)[((fdPtr) >> 2)] = res.readable_fd;
- (growMemViews(), HEAP32)[(((fdPtr) + (4)) >> 2)] = res.writable_fd;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function ___syscall_stat64(path, buf) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(13, 0, 1, path, buf);
- try {
- path = SYSCALLS.getStr(path);
- return SYSCALLS.writeStat(buf, FS.stat(path));
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- var __abort_js = () => abort("native code called abort()");
- var __emscripten_init_main_thread_js = tb => {
- var can_block = !ENVIRONMENT_IS_WEB;
- // Feature detect whether the main thread can block.
- try {
- Atomics.wait((growMemViews(), HEAP32), 0, 0, 0);
- can_block = true;
- } catch (e) {}
- // Pass the thread address to the native code where they are stored in wasm
- // globals which act as a form of TLS. Global constructors trying
- // to access this value will read the wrong value, but that is UB anyway.
- __emscripten_thread_init(tb, /*is_main=*/ !ENVIRONMENT_IS_WORKER, /*is_runtime=*/ 1, can_block, /*default_stacksize=*/ 65536, /*start_profiling=*/ false);
- PThread.threadInitTLS();
- };
- var handleException = e => {
- // Certain exception types we do not treat as errors since they are used for
- // internal control flow.
- // 1. ExitStatus, which is thrown by exit()
- // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
- // that wish to return to JS event loop.
- if (e instanceof ExitStatus || e == "unwind") {
- return EXITSTATUS;
- }
- checkStackCookie();
- if (e instanceof WebAssembly.RuntimeError) {
- if (_emscripten_stack_get_current() <= 0) {
- err("Stack overflow detected. You can try increasing -sSTACK_SIZE (currently set to 65536)");
- }
- }
- quit_(1, e);
- };
- var maybeExit = () => {
- if (!keepRuntimeAlive()) {
- try {
- if (ENVIRONMENT_IS_PTHREAD) {
- // exit the current thread, but only if there is one active.
- // TODO(https://github.com/emscripten-core/emscripten/issues/25076):
- // Unify this check with the runtimeExited check above
- if (_pthread_self()) __emscripten_thread_exit(EXITSTATUS);
- return;
- }
- _exit(EXITSTATUS);
- } catch (e) {
- handleException(e);
- }
- }
- };
- var callUserCallback = func => {
- if (ABORT) {
- err("user callback triggered after runtime exited or application aborted. Ignoring.");
- return;
- }
- try {
- return func();
- } catch (e) {
- handleException(e);
- } finally {
- maybeExit();
- }
- };
- var __emscripten_thread_mailbox_await = pthread_ptr => {
- if (!waitAsyncPolyfilled) {
- // Wait on the pthread's initial self-pointer field because it is easy and
- // safe to access from sending threads that need to notify the waiting
- // thread.
- // Note: Under wasm64 only the low 32-bit of the pthread_ptr are
- // read/compared here, but we don't actually care about the exact values
- // here as long as they match.
- var wait = Atomics.waitAsync((growMemViews(), HEAP32), ((pthread_ptr) >> 2), pthread_ptr);
- assert(wait.async);
- wait.value.then(checkMailbox);
- var waitingAsync = pthread_ptr + 112;
- Atomics.store((growMemViews(), HEAP32), ((waitingAsync) >> 2), 1);
- }
- };
- var checkMailbox = () => {
- // checkMailbox can be called after the pthread has shut down. See
- // Pthread.terminateRuntime().
- // In this case we return silently without re-registering using waitAsync.
- // Perhaps there is a more universal way we can detect runtime has exited.
- // TODO(https://github.com/emscripten-core/emscripten/issues/25076)
- var pthread_ptr = _pthread_self();
- if (!pthread_ptr) return;
- callUserCallback(() => {
- // If we are using Atomics.waitAsync as our notification mechanism, wait
- // for a notification before processing the mailbox to avoid missing any
- // work that could otherwise arrive after we've finished processing the
- // mailbox and before we're ready for the next notification.
- __emscripten_thread_mailbox_await(pthread_ptr);
- __emscripten_check_mailbox();
- });
- };
- var __emscripten_notify_mailbox_postmessage = (targetThread, currThreadId) => {
- if (targetThread == currThreadId) {
- setTimeout(checkMailbox);
- } else if (ENVIRONMENT_IS_PTHREAD) {
- postMessage({
- targetThread,
- cmd: 4
- });
- } else {
- var worker = PThread.pthreads[targetThread];
- if (!worker) {
- err(`Cannot send message to thread with ID ${targetThread}, unknown thread ID!`);
- return;
- }
- worker.postMessage({
- cmd: 4
- });
- }
- };
- var proxiedJSCallArgs = [];
- var __emscripten_receive_on_main_thread_js = (funcIndex, emAsmAddr, callingThread, bufSize, args, ctx, ctxArgs) => {
- // Sometimes we need to backproxy events to the calling thread (e.g.
- // HTML5 DOM events handlers such as
- // emscripten_set_mousemove_callback()), so keep track in a globally
- // accessible variable about the thread that initiated the proxying.
- proxiedJSCallArgs.length = 0;
- var b = ((args) >> 3);
- var end = ((args + bufSize) >> 3);
- while (b < end) {
- var arg;
- if ((growMemViews(), HEAP64)[b++]) {
- // It's a BigInt.
- arg = (growMemViews(), HEAP64)[b++];
- } else {
- // It's a Number.
- arg = (growMemViews(), HEAPF64)[b++];
- }
- proxiedJSCallArgs.push(arg);
- }
- // Proxied JS library funcs use funcIndex and EM_ASM functions use emAsmAddr
- var func = emAsmAddr ? ASM_CONSTS[emAsmAddr] : proxiedFunctionTable[funcIndex];
- assert(!(funcIndex && emAsmAddr));
- assert(func.length == proxiedJSCallArgs.length, "Call args mismatch in _emscripten_receive_on_main_thread_js");
- PThread.currentProxiedOperationCallerThread = callingThread;
- var rtn = func(...proxiedJSCallArgs);
- PThread.currentProxiedOperationCallerThread = 0;
- if (ctx) {
- rtn.then(rtn => __emscripten_run_js_on_main_thread_done(ctx, ctxArgs, rtn));
- return;
- }
- // Proxied functions can return any type except bigint. All other types
- // coerce to f64/double (the return type of this function in C) but not
- // bigint.
- assert(typeof rtn != "bigint");
- return rtn;
- };
- var __emscripten_runtime_keepalive_clear = () => {
- noExitRuntime = false;
- runtimeKeepaliveCounter = 0;
- };
- var __emscripten_thread_cleanup = thread => {
- // Called when a thread needs to be cleaned up so it can be reused.
- // A thread is considered reusable when it either returns from its
- // entry point, calls pthread_exit, or acts upon a cancellation.
- // Detached threads are responsible for calling this themselves,
- // otherwise pthread_join is responsible for calling this.
- if (!ENVIRONMENT_IS_PTHREAD) cleanupThread(thread); else postMessage({
- cmd: 6,
- thread
- });
- };
- var __emscripten_thread_set_strongref = thread => {
- // Called when a thread needs to be strongly referenced.
- // Currently only used for:
- // - keeping the "main" thread alive in PROXY_TO_PTHREAD mode;
- // - crashed threads that need to propagate the uncaught exception
- // back to the main thread.
- if (ENVIRONMENT_IS_NODE) {
- var worker = PThread.pthreads[thread];
- worker.ref();
- // Also, record that we called strongref, in case this function is called
- // bafore the 'loaded' callback from the thread (where we would normally
- // `unref` it.
- worker.strongref = 1;
- }
- };
- var isLeapYear = year => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
- var MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ];
- var MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
- var ydayFromDate = date => {
- var leap = isLeapYear(date.getFullYear());
- var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE);
- var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
- // -1 since it's days since Jan 1
- return yday;
- };
- var INT53_MAX = 9007199254740992;
- var INT53_MIN = -9007199254740992;
- var bigintToI53Checked = num => (num < INT53_MIN || num > INT53_MAX) ? NaN : Number(num);
- function __localtime_js(time, tmPtr) {
- time = bigintToI53Checked(time);
- var date = new Date(time * 1e3);
- if (isNaN(date.getTime())) {
- return 1;
- }
- (growMemViews(), HEAP32)[((tmPtr) >> 2)] = date.getSeconds();
- (growMemViews(), HEAP32)[(((tmPtr) + (4)) >> 2)] = date.getMinutes();
- (growMemViews(), HEAP32)[(((tmPtr) + (8)) >> 2)] = date.getHours();
- (growMemViews(), HEAP32)[(((tmPtr) + (12)) >> 2)] = date.getDate();
- (growMemViews(), HEAP32)[(((tmPtr) + (16)) >> 2)] = date.getMonth();
- (growMemViews(), HEAP32)[(((tmPtr) + (20)) >> 2)] = date.getFullYear() - 1900;
- (growMemViews(), HEAP32)[(((tmPtr) + (24)) >> 2)] = date.getDay();
- var yday = ydayFromDate(date) | 0;
- (growMemViews(), HEAP32)[(((tmPtr) + (28)) >> 2)] = yday;
- (growMemViews(), HEAP32)[(((tmPtr) + (36)) >> 2)] = -(date.getTimezoneOffset() * 60);
- // Attention: DST is in December in South, and some regions don't have DST at all.
- var start = new Date(date.getFullYear(), 0, 1);
- var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
- var winterOffset = start.getTimezoneOffset();
- var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
- (growMemViews(), HEAP32)[(((tmPtr) + (32)) >> 2)] = dst;
- return 0;
- }
- function __mmap_js(len, prot, flags, fd, offset, allocated, addr) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(14, 0, 1, len, prot, flags, fd, offset, allocated, addr);
- offset = bigintToI53Checked(offset);
- try {
- // musl's mmap doesn't allow values over a certain limit
- // see OFF_MASK in mmap.c.
- assert(!isNaN(offset));
- var stream = SYSCALLS.getStreamFromFD(fd);
- var res = FS.mmap(stream, len, offset, prot, flags);
- var ptr = res.ptr;
- (growMemViews(), HEAP32)[((allocated) >> 2)] = res.allocated;
- (growMemViews(), HEAPU32)[((addr) >> 2)] = ptr;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- function __munmap_js(addr, len, prot, flags, fd, offset) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(15, 0, 1, addr, len, prot, flags, fd, offset);
- offset = bigintToI53Checked(offset);
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- if (prot & 2) {
- SYSCALLS.doMsync(addr, stream, len, flags, offset);
- }
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return -e.errno;
- }
- }
- var __tzset_js = (timezone, daylight, std_name, dst_name) => {
- // TODO: Use (malleable) environment variables instead of system settings.
- var currentYear = (new Date).getFullYear();
- var winter = new Date(currentYear, 0, 1);
- var summer = new Date(currentYear, 6, 1);
- var winterOffset = winter.getTimezoneOffset();
- var summerOffset = summer.getTimezoneOffset();
- // Local standard timezone offset. Local standard time is not adjusted for
- // daylight savings. This code uses the fact that getTimezoneOffset returns
- // a greater value during Standard Time versus Daylight Saving Time (DST).
- // Thus it determines the expected output during Standard Time, and it
- // compares whether the output of the given date the same (Standard) or less
- // (DST).
- var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
- // timezone is specified as seconds west of UTC ("The external variable
- // `timezone` shall be set to the difference, in seconds, between
- // Coordinated Universal Time (UTC) and local standard time."), the same
- // as returned by stdTimezoneOffset.
- // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
- (growMemViews(), HEAPU32)[((timezone) >> 2)] = stdTimezoneOffset * 60;
- (growMemViews(), HEAP32)[((daylight) >> 2)] = Number(winterOffset != summerOffset);
- var extractZone = timezoneOffset => {
- // Why inverse sign?
- // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
- var sign = timezoneOffset >= 0 ? "-" : "+";
- var absOffset = Math.abs(timezoneOffset);
- var hours = String(Math.floor(absOffset / 60)).padStart(2, "0");
- var minutes = String(absOffset % 60).padStart(2, "0");
- return `UTC${sign}${hours}${minutes}`;
- };
- var winterName = extractZone(winterOffset);
- var summerName = extractZone(summerOffset);
- assert(winterName);
- assert(summerName);
- assert(lengthBytesUTF8(winterName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${winterName})`);
- assert(lengthBytesUTF8(summerName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${summerName})`);
- if (summerOffset < winterOffset) {
- // Northern hemisphere
- stringToUTF8(winterName, std_name, 17);
- stringToUTF8(summerName, dst_name, 17);
- } else {
- stringToUTF8(winterName, dst_name, 17);
- stringToUTF8(summerName, std_name, 17);
- }
- };
- var _emscripten_get_now = () => performance.timeOrigin + performance.now();
- var _emscripten_date_now = () => Date.now();
- var nowIsMonotonic = 1;
- var checkWasiClock = clock_id => clock_id >= 0 && clock_id <= 3;
- function _clock_time_get(clk_id, ignored_precision, ptime) {
- ignored_precision = bigintToI53Checked(ignored_precision);
- if (!checkWasiClock(clk_id)) {
- return 28;
- }
- var now;
- // all wasi clocks but realtime are monotonic
- if (clk_id === 0) {
- now = _emscripten_date_now();
- } else if (nowIsMonotonic) {
- now = _emscripten_get_now();
- } else {
- return 52;
- }
- // "now" is in ms, and wasi times are in ns.
- var nsec = Math.round(now * 1e3 * 1e3);
- (growMemViews(), HEAP64)[((ptime) >> 3)] = BigInt(nsec);
- return 0;
- }
- function getFullscreenElement() {
- return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.webkitCurrentFullScreenElement || document.msFullscreenElement;
- }
- var runtimeKeepalivePush = () => {
- runtimeKeepaliveCounter += 1;
- };
- var runtimeKeepalivePop = () => {
- assert(runtimeKeepaliveCounter > 0);
- runtimeKeepaliveCounter -= 1;
- };
- /** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => {
- runtimeKeepalivePush();
- return setTimeout(() => {
- runtimeKeepalivePop();
- callUserCallback(func);
- }, timeout);
- };
- var Browser = {
- useWebGL: false,
- isFullscreen: false,
- pointerLock: false,
- moduleContextCreatedCallbacks: [],
- preloadedImages: {},
- preloadedAudios: {},
- getCanvas: () => Module["canvas"],
- init() {
- if (Browser.initted) return;
- Browser.initted = true;
- // Support for plugins that can process preloaded files. You can add more of these to
- // your app by creating and appending to preloadPlugins.
- // Each plugin is asked if it can handle a file based on the file's name. If it can,
- // it is given the file's raw data. When it is done, it calls a callback with the file's
- // (possibly modified) data. For example, a plugin might decompress a file, or it
- // might create some side data structure for use later (like an Image element, etc.).
- var imagePlugin = {};
- imagePlugin["canHandle"] = name => !Module["noImageDecoding"] && /\.(jpg|jpeg|png|bmp|webp)$/i.test(name);
- imagePlugin["handle"] = async (byteArray, name) => {
- var b = new Blob([ byteArray ], {
- type: Browser.getMimetype(name)
- });
- if (b.size !== byteArray.length) {
- // Safari bug #118630
- // Safari's Blob can only take an ArrayBuffer
- b = new Blob([ (new Uint8Array(byteArray)).buffer ], {
- type: Browser.getMimetype(name)
- });
- }
- var url = URL.createObjectURL(b);
- return new Promise((resolve, reject) => {
- var img = new Image;
- img.onload = () => {
- assert(img.complete, `Image ${name} could not be decoded`);
- var canvas = /** @type {!HTMLCanvasElement} */ (document.createElement("canvas"));
- canvas.width = img.width;
- canvas.height = img.height;
- var ctx = canvas.getContext("2d");
- ctx.drawImage(img, 0, 0);
- Browser.preloadedImages[name] = canvas;
- URL.revokeObjectURL(url);
- resolve(byteArray);
- };
- img.onerror = event => {
- err(`Image ${url} could not be decoded`);
- reject();
- };
- img.src = url;
- });
- };
- preloadPlugins.push(imagePlugin);
- var audioPlugin = {};
- audioPlugin["canHandle"] = name => !Module["noAudioDecoding"] && name.slice(-4) in {
- ".ogg": 1,
- ".wav": 1,
- ".mp3": 1
- };
- audioPlugin["handle"] = async (byteArray, name) => new Promise((resolve, reject) => {
- var done = false;
- function finish(audio) {
- if (done) return;
- done = true;
- Browser.preloadedAudios[name] = audio;
- resolve(byteArray);
- }
- var b = new Blob([ byteArray ], {
- type: Browser.getMimetype(name)
- });
- var url = URL.createObjectURL(b);
- // XXX we never revoke this!
- var audio = new Audio;
- audio.addEventListener("canplaythrough", () => finish(audio));
- // use addEventListener due to chromium bug 124926
- audio.onerror = event => {
- if (done) return;
- err(`warning: browser could not fully decode audio ${name}, trying slower base64 approach`);
- function encode64(data) {
- var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- var PAD = "=";
- var ret = "";
- var leftchar = 0;
- var leftbits = 0;
- for (var i = 0; i < data.length; i++) {
- leftchar = (leftchar << 8) | data[i];
- leftbits += 8;
- while (leftbits >= 6) {
- var curr = (leftchar >> (leftbits - 6)) & 63;
- leftbits -= 6;
- ret += BASE[curr];
- }
- }
- if (leftbits == 2) {
- ret += BASE[(leftchar & 3) << 4];
- ret += PAD + PAD;
- } else if (leftbits == 4) {
- ret += BASE[(leftchar & 15) << 2];
- ret += PAD;
- }
- return ret;
- }
- audio.src = "data:audio/x-" + name.slice(-3) + ";base64," + encode64(byteArray);
- finish(audio);
- };
- audio.src = url;
- // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
- safeSetTimeout(() => {
- finish(audio);
- }, 1e4);
- });
- preloadPlugins.push(audioPlugin);
- // Canvas event setup
- function pointerLockChange() {
- var canvas = Browser.getCanvas();
- Browser.pointerLock = document.pointerLockElement === canvas;
- }
- var canvas = Browser.getCanvas();
- if (canvas) {
- // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
- // Module['forcedAspectRatio'] = 4 / 3;
- document.addEventListener("pointerlockchange", pointerLockChange);
- if (Module["elementPointerLock"]) {
- canvas.addEventListener("click", ev => {
- if (!Browser.pointerLock && Browser.getCanvas().requestPointerLock) {
- Browser.getCanvas().requestPointerLock();
- ev.preventDefault();
- }
- });
- }
- }
- },
- createContext(/** @type {HTMLCanvasElement} */ canvas, useWebGL, setInModule, webGLContextAttributes) {
- if (useWebGL && Module["ctx"] && canvas == Browser.getCanvas()) return Module["ctx"];
- // no need to recreate GL context if it's already been created for this canvas.
- var ctx;
- var contextHandle;
- if (useWebGL) {
- // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
- var contextAttributes = {
- antialias: false,
- alpha: false,
- majorVersion: 1
- };
- if (webGLContextAttributes) {
- for (var attribute in webGLContextAttributes) {
- contextAttributes[attribute] = webGLContextAttributes[attribute];
- }
- }
- // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not
- // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function
- // Browser.createContext() should not even be emitted.
- if (typeof GL != "undefined") {
- contextHandle = GL.createContext(canvas, contextAttributes);
- if (contextHandle) {
- ctx = GL.getContext(contextHandle).GLctx;
- }
- }
- } else {
- ctx = canvas.getContext("2d");
- }
- if (!ctx) return null;
- if (setInModule) {
- if (!useWebGL) assert(typeof GLctx == "undefined", "cannot set in module if GLctx is used, but we are a non-GL context that would replace it");
- Module["ctx"] = ctx;
- if (useWebGL) GL.makeContextCurrent(contextHandle);
- Browser.useWebGL = useWebGL;
- Browser.moduleContextCreatedCallbacks.forEach(callback => callback());
- Browser.init();
- }
- return ctx;
- },
- fullscreenHandlersInstalled: false,
- lockPointer: undefined,
- resizeCanvas: undefined,
- requestFullscreen(lockPointer, resizeCanvas) {
- Browser.lockPointer = lockPointer;
- Browser.resizeCanvas = resizeCanvas;
- if (typeof Browser.lockPointer == "undefined") Browser.lockPointer = true;
- if (typeof Browser.resizeCanvas == "undefined") Browser.resizeCanvas = false;
- var canvas = Browser.getCanvas();
- function fullscreenChange() {
- Browser.isFullscreen = false;
- var canvasContainer = canvas.parentNode;
- if (getFullscreenElement() === canvasContainer) {
- canvas.exitFullscreen = Browser.exitFullscreen;
- if (Browser.lockPointer) canvas.requestPointerLock();
- Browser.isFullscreen = true;
- if (Browser.resizeCanvas) {
- Browser.setFullscreenCanvasSize();
- } else {
- Browser.updateCanvasDimensions(canvas);
- }
- } else {
- // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
- canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
- canvasContainer.parentNode.removeChild(canvasContainer);
- if (Browser.resizeCanvas) {
- Browser.setWindowedCanvasSize();
- } else {
- Browser.updateCanvasDimensions(canvas);
- }
- }
- }
- if (!Browser.fullscreenHandlersInstalled) {
- Browser.fullscreenHandlersInstalled = true;
- document.addEventListener("fullscreenchange", fullscreenChange);
- document.addEventListener("mozfullscreenchange", fullscreenChange);
- document.addEventListener("webkitfullscreenchange", fullscreenChange);
- document.addEventListener("MSFullscreenChange", fullscreenChange);
- }
- // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root
- var canvasContainer = document.createElement("div");
- canvas.parentNode.insertBefore(canvasContainer, canvas);
- canvasContainer.appendChild(canvas);
- // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
- canvasContainer.requestFullscreen = canvasContainer["requestFullscreen"] || canvasContainer["mozRequestFullScreen"] || canvasContainer["msRequestFullscreen"] || (canvasContainer["webkitRequestFullscreen"] ? () => canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null) || (canvasContainer["webkitRequestFullScreen"] ? () => canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]) : null);
- canvasContainer.requestFullscreen();
- },
- requestFullScreen() {
- abort("Module.requestFullScreen has been replaced by Module.requestFullscreen (without a capital S)");
- },
- exitFullscreen() {
- // This is workaround for chrome. Trying to exit from fullscreen
- // not in fullscreen state will cause "TypeError: Document not active"
- // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236
- if (!Browser.isFullscreen) {
- return false;
- }
- var CFS = document["exitFullscreen"] || document["cancelFullScreen"] || document["mozCancelFullScreen"] || document["msExitFullscreen"] || document["webkitCancelFullScreen"] || (() => {});
- CFS.apply(document, []);
- return true;
- },
- safeSetTimeout(func, timeout) {
- // Legacy function, this is used by the SDL2 port so we need to keep it
- // around at least until that is updated.
- // See https://github.com/libsdl-org/SDL/pull/6304
- return safeSetTimeout(func, timeout);
- },
- getMimetype(name) {
- return {
- "jpg": "image/jpeg",
- "jpeg": "image/jpeg",
- "png": "image/png",
- "bmp": "image/bmp",
- "ogg": "audio/ogg",
- "wav": "audio/wav",
- "mp3": "audio/mpeg"
- }[name.slice(name.lastIndexOf(".") + 1)];
- },
- getUserMedia(func) {
- window.getUserMedia ||= navigator["getUserMedia"] || navigator["mozGetUserMedia"];
- window.getUserMedia(func);
- },
- getMovementX(event) {
- return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0;
- },
- getMovementY(event) {
- return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0;
- },
- getMouseWheelDelta(event) {
- var delta = 0;
- switch (event.type) {
- case "DOMMouseScroll":
- // 3 lines make up a step
- delta = event.detail / 3;
- break;
- case "mousewheel":
- // 120 units make up a step
- delta = event.wheelDelta / 120;
- break;
- case "wheel":
- delta = event.deltaY;
- switch (event.deltaMode) {
- case 0:
- // DOM_DELTA_PIXEL: 100 pixels make up a step
- delta /= 100;
- break;
- case 1:
- // DOM_DELTA_LINE: 3 lines make up a step
- delta /= 3;
- break;
- case 2:
- // DOM_DELTA_PAGE: A page makes up 80 steps
- delta *= 80;
- break;
- default:
- abort("unrecognized mouse wheel delta mode: " + event.deltaMode);
- }
- break;
- default:
- abort("unrecognized mouse wheel event: " + event.type);
- }
- return delta;
- },
- mouseX: 0,
- mouseY: 0,
- mouseMovementX: 0,
- mouseMovementY: 0,
- touches: {},
- lastTouches: {},
- calculateMouseCoords(pageX, pageY) {
- // Calculate the movement based on the changes
- // in the coordinates.
- var canvas = Browser.getCanvas();
- var rect = canvas.getBoundingClientRect();
- var adjustedX = pageX - (window.scrollX + rect.left);
- var adjustedY = pageY - (window.scrollY + rect.top);
- // the canvas might be CSS-scaled compared to its backbuffer;
- // SDL-using content will want mouse coordinates in terms
- // of backbuffer units.
- adjustedX = adjustedX * (canvas.width / rect.width);
- adjustedY = adjustedY * (canvas.height / rect.height);
- return {
- x: adjustedX,
- y: adjustedY
- };
- },
- setMouseCoords(pageX, pageY) {
- const {x, y} = Browser.calculateMouseCoords(pageX, pageY);
- Browser.mouseMovementX = x - Browser.mouseX;
- Browser.mouseMovementY = y - Browser.mouseY;
- Browser.mouseX = x;
- Browser.mouseY = y;
- },
- calculateMouseEvent(event) {
- // event should be mousemove, mousedown or mouseup
- if (Browser.pointerLock) {
- // When the pointer is locked, calculate the coordinates
- // based on the movement of the mouse.
- // Workaround for Firefox bug 764498
- if (event.type != "mousemove" && ("mozMovementX" in event)) {
- Browser.mouseMovementX = Browser.mouseMovementY = 0;
- } else {
- Browser.mouseMovementX = Browser.getMovementX(event);
- Browser.mouseMovementY = Browser.getMovementY(event);
- }
- // add the mouse delta to the current absolute mouse position
- Browser.mouseX += Browser.mouseMovementX;
- Browser.mouseY += Browser.mouseMovementY;
- } else {
- if (event.type === "touchstart" || event.type === "touchend" || event.type === "touchmove") {
- var touch = event.touch;
- if (touch === undefined) {
- return;
- }
- var coords = Browser.calculateMouseCoords(touch.pageX, touch.pageY);
- if (event.type === "touchstart") {
- Browser.lastTouches[touch.identifier] = coords;
- Browser.touches[touch.identifier] = coords;
- } else if (event.type === "touchend" || event.type === "touchmove") {
- var last = Browser.touches[touch.identifier];
- last ||= coords;
- Browser.lastTouches[touch.identifier] = last;
- Browser.touches[touch.identifier] = coords;
- }
- return;
- }
- Browser.setMouseCoords(event.pageX, event.pageY);
- }
- },
- resizeListeners: [],
- updateResizeListeners() {
- var canvas = Browser.getCanvas();
- Browser.resizeListeners.forEach(listener => listener(canvas.width, canvas.height));
- },
- setCanvasSize(width, height, noUpdates) {
- var canvas = Browser.getCanvas();
- Browser.updateCanvasDimensions(canvas, width, height);
- if (!noUpdates) Browser.updateResizeListeners();
- },
- windowedWidth: 0,
- windowedHeight: 0,
- setFullscreenCanvasSize() {
- // check if SDL is available
- if (typeof SDL != "undefined") {
- var flags = (growMemViews(), HEAPU32)[((SDL.screen) >> 2)];
- flags = flags | 8388608;
- // set SDL_FULLSCREEN flag
- (growMemViews(), HEAP32)[((SDL.screen) >> 2)] = flags;
- }
- Browser.updateCanvasDimensions(Browser.getCanvas());
- Browser.updateResizeListeners();
- },
- setWindowedCanvasSize() {
- // check if SDL is available
- if (typeof SDL != "undefined") {
- var flags = (growMemViews(), HEAPU32)[((SDL.screen) >> 2)];
- flags = flags & ~8388608;
- // clear SDL_FULLSCREEN flag
- (growMemViews(), HEAP32)[((SDL.screen) >> 2)] = flags;
- }
- Browser.updateCanvasDimensions(Browser.getCanvas());
- Browser.updateResizeListeners();
- },
- updateCanvasDimensions(canvas, wNative, hNative) {
- if (wNative && hNative) {
- canvas.widthNative = wNative;
- canvas.heightNative = hNative;
- } else {
- wNative = canvas.widthNative;
- hNative = canvas.heightNative;
- }
- var w = wNative;
- var h = hNative;
- if ((getFullscreenElement() === canvas.parentNode) && (typeof screen != "undefined")) {
- var factor = Math.min(screen.width / w, screen.height / h);
- w = Math.round(w * factor);
- h = Math.round(h * factor);
- }
- if (Browser.resizeCanvas) {
- if (canvas.width != w) canvas.width = w;
- if (canvas.height != h) canvas.height = h;
- if (typeof canvas.style != "undefined") {
- canvas.style.removeProperty("width");
- canvas.style.removeProperty("height");
- }
- } else {
- if (canvas.width != wNative) canvas.width = wNative;
- if (canvas.height != hNative) canvas.height = hNative;
- if (typeof canvas.style != "undefined") {
- if (w != wNative || h != hNative) {
- canvas.style.setProperty("width", w + "px", "important");
- canvas.style.setProperty("height", h + "px", "important");
- } else {
- canvas.style.removeProperty("width");
- canvas.style.removeProperty("height");
- }
- }
- }
- }
- };
- var EGL = {
- errorCode: 12288,
- defaultDisplayInitialized: false,
- currentContext: 0,
- currentReadSurface: 0,
- currentDrawSurface: 0,
- contextAttributes: {
- alpha: false,
- depth: false,
- stencil: false,
- antialias: false
- },
- stringCache: {},
- setErrorCode(code) {
- EGL.errorCode = code;
- },
- chooseConfig(display, attribList, config, config_size, numConfigs) {
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (attribList) {
- // read attribList if it is non-null
- for (;;) {
- var param = (growMemViews(), HEAP32)[((attribList) >> 2)];
- if (param == 12321) {
- var alphaSize = (growMemViews(), HEAP32)[(((attribList) + (4)) >> 2)];
- EGL.contextAttributes.alpha = (alphaSize > 0);
- } else if (param == 12325) {
- var depthSize = (growMemViews(), HEAP32)[(((attribList) + (4)) >> 2)];
- EGL.contextAttributes.depth = (depthSize > 0);
- } else if (param == 12326) {
- var stencilSize = (growMemViews(), HEAP32)[(((attribList) + (4)) >> 2)];
- EGL.contextAttributes.stencil = (stencilSize > 0);
- } else if (param == 12337) {
- var samples = (growMemViews(), HEAP32)[(((attribList) + (4)) >> 2)];
- EGL.contextAttributes.antialias = (samples > 0);
- } else if (param == 12338) {
- var samples = (growMemViews(), HEAP32)[(((attribList) + (4)) >> 2)];
- EGL.contextAttributes.antialias = (samples == 1);
- } else if (param == 12544) {
- var requestedPriority = (growMemViews(), HEAP32)[(((attribList) + (4)) >> 2)];
- EGL.contextAttributes.lowLatency = (requestedPriority != 12547);
- } else if (param == 12344) {
- break;
- }
- attribList += 8;
- }
- }
- if ((!config || !config_size) && !numConfigs) {
- EGL.setErrorCode(12300);
- return 0;
- }
- if (numConfigs) {
- (growMemViews(), HEAP32)[((numConfigs) >> 2)] = 1;
- }
- if (config && config_size > 0) {
- (growMemViews(), HEAPU32)[((config) >> 2)] = 62002;
- }
- EGL.setErrorCode(12288);
- return 1;
- }
- };
- function _eglBindAPI(api) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(16, 0, 1, api);
- if (api == 12448) {
- EGL.setErrorCode(12288);
- return 1;
- }
- // if (api == 0x30A1 /* EGL_OPENVG_API */ || api == 0x30A2 /* EGL_OPENGL_API */) {
- EGL.setErrorCode(12300);
- return 0;
- }
- function _eglChooseConfig(display, attrib_list, configs, config_size, numConfigs) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(17, 0, 1, display, attrib_list, configs, config_size, numConfigs);
- return EGL.chooseConfig(display, attrib_list, configs, config_size, numConfigs);
- }
- var GLctx;
- var webgl_enable_ANGLE_instanced_arrays = ctx => {
- // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
- var ext = ctx.getExtension("ANGLE_instanced_arrays");
- // Because this extension is a core function in WebGL 2, assign the extension entry points in place of
- // where the core functions will reside in WebGL 2. This way the calling code can call these without
- // having to dynamically branch depending if running against WebGL 1 or WebGL 2.
- if (ext) {
- ctx["vertexAttribDivisor"] = (index, divisor) => ext["vertexAttribDivisorANGLE"](index, divisor);
- ctx["drawArraysInstanced"] = (mode, first, count, primcount) => ext["drawArraysInstancedANGLE"](mode, first, count, primcount);
- ctx["drawElementsInstanced"] = (mode, count, type, indices, primcount) => ext["drawElementsInstancedANGLE"](mode, count, type, indices, primcount);
- return 1;
- }
- };
- var webgl_enable_OES_vertex_array_object = ctx => {
- // Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2.
- var ext = ctx.getExtension("OES_vertex_array_object");
- if (ext) {
- ctx["createVertexArray"] = () => ext["createVertexArrayOES"]();
- ctx["deleteVertexArray"] = vao => ext["deleteVertexArrayOES"](vao);
- ctx["bindVertexArray"] = vao => ext["bindVertexArrayOES"](vao);
- ctx["isVertexArray"] = vao => ext["isVertexArrayOES"](vao);
- return 1;
- }
- };
- var webgl_enable_WEBGL_draw_buffers = ctx => {
- // Extension available in WebGL 1 from Firefox 28 onwards. Core feature in WebGL 2.
- var ext = ctx.getExtension("WEBGL_draw_buffers");
- if (ext) {
- ctx["drawBuffers"] = (n, bufs) => ext["drawBuffersWEBGL"](n, bufs);
- return 1;
- }
- };
- var webgl_enable_EXT_polygon_offset_clamp = ctx => !!(ctx.extPolygonOffsetClamp = ctx.getExtension("EXT_polygon_offset_clamp"));
- var webgl_enable_EXT_clip_control = ctx => !!(ctx.extClipControl = ctx.getExtension("EXT_clip_control"));
- var webgl_enable_WEBGL_polygon_mode = ctx => !!(ctx.webglPolygonMode = ctx.getExtension("WEBGL_polygon_mode"));
- var webgl_enable_WEBGL_multi_draw = ctx => // Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
- !!(ctx.multiDrawWebgl = ctx.getExtension("WEBGL_multi_draw"));
- var getEmscriptenSupportedExtensions = ctx => {
- // Restrict the list of advertised extensions to those that we actually
- // support.
- var supportedExtensions = [ // WebGL 1 extensions
- "ANGLE_instanced_arrays", "EXT_blend_minmax", "EXT_disjoint_timer_query", "EXT_frag_depth", "EXT_shader_texture_lod", "EXT_sRGB", "OES_element_index_uint", "OES_fbo_render_mipmap", "OES_standard_derivatives", "OES_texture_float", "OES_texture_half_float", "OES_texture_half_float_linear", "OES_vertex_array_object", "WEBGL_color_buffer_float", "WEBGL_depth_texture", "WEBGL_draw_buffers", // WebGL 1 and WebGL 2 extensions
- "EXT_clip_control", "EXT_color_buffer_half_float", "EXT_depth_clamp", "EXT_float_blend", "EXT_polygon_offset_clamp", "EXT_texture_compression_bptc", "EXT_texture_compression_rgtc", "EXT_texture_filter_anisotropic", "KHR_parallel_shader_compile", "OES_texture_float_linear", "WEBGL_blend_func_extended", "WEBGL_compressed_texture_astc", "WEBGL_compressed_texture_etc", "WEBGL_compressed_texture_etc1", "WEBGL_compressed_texture_s3tc", "WEBGL_compressed_texture_s3tc_srgb", "WEBGL_debug_renderer_info", "WEBGL_debug_shaders", "WEBGL_lose_context", "WEBGL_multi_draw", "WEBGL_polygon_mode" ];
- // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
- return ctx.getSupportedExtensions()?.filter(ext => supportedExtensions.includes(ext)) ?? [];
- };
- var GL = {
- counter: 1,
- buffers: [],
- programs: [],
- framebuffers: [],
- renderbuffers: [],
- textures: [],
- shaders: [],
- vaos: [],
- contexts: {},
- offscreenCanvases: {},
- queries: [],
- stringCache: {},
- unpackAlignment: 4,
- unpackRowLength: 0,
- recordError: errorCode => {
- if (!GL.lastError) {
- GL.lastError = errorCode;
- }
- },
- getNewId: table => {
- var ret = GL.counter++;
- for (var i = table.length; i < ret; i++) {
- table[i] = null;
- }
- return ret;
- },
- genObject: (n, buffers, createFunction, objectTable) => {
- for (var i = 0; i < n; i++) {
- var buffer = GLctx[createFunction]();
- var id = buffer && GL.getNewId(objectTable);
- if (buffer) {
- buffer.name = id;
- objectTable[id] = buffer;
- } else {
- GL.recordError(1282);
- }
- (growMemViews(), HEAP32)[(((buffers) + (i * 4)) >> 2)] = id;
- }
- },
- getSource: (shader, count, string, length) => {
- var source = "";
- for (var i = 0; i < count; ++i) {
- var len = length ? (growMemViews(), HEAPU32)[(((length) + (i * 4)) >> 2)] : undefined;
- source += UTF8ToString((growMemViews(), HEAPU32)[(((string) + (i * 4)) >> 2)], len);
- }
- return source;
- },
- createContext: (/** @type {HTMLCanvasElement} */ canvas, webGLContextAttributes) => {
- // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL
- // context on a canvas, calling .getContext() will always return that
- // context independent of which 'webgl' or 'webgl2'
- // context version was passed. See:
- // https://webkit.org/b/222758
- // and:
- // https://github.com/emscripten-core/emscripten/issues/13295.
- // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari
- // version field in above check.
- if (!canvas.getContextSafariWebGL2Fixed) {
- canvas.getContextSafariWebGL2Fixed = canvas.getContext;
- /** @type {function(this:HTMLCanvasElement, string, (Object|null)=): (Object|null)} */ function fixedGetContext(ver, attrs) {
- var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
- return ((ver == "webgl") == (gl instanceof WebGLRenderingContext)) ? gl : null;
- }
- canvas.getContext = fixedGetContext;
- }
- var ctx = canvas.getContext("webgl", webGLContextAttributes);
- if (!ctx) return 0;
- var handle = GL.registerContext(ctx, webGLContextAttributes);
- return handle;
- },
- registerContext: (ctx, webGLContextAttributes) => {
- // with pthreads a context is a location in memory with some synchronized
- // data between threads
- var handle = _malloc(8);
- (growMemViews(), HEAPU32)[(((handle) + (4)) >> 2)] = _pthread_self();
- // the thread pointer of the thread that owns the control of the context
- var context = {
- handle,
- attributes: webGLContextAttributes,
- version: webGLContextAttributes.majorVersion,
- GLctx: ctx
- };
- // Store the created context object so that we can access the context
- // given a canvas without having to pass the parameters again.
- if (ctx.canvas) ctx.canvas.GLctxObject = context;
- GL.contexts[handle] = context;
- if (typeof webGLContextAttributes.enableExtensionsByDefault == "undefined" || webGLContextAttributes.enableExtensionsByDefault) {
- GL.initExtensions(context);
- }
- return handle;
- },
- makeContextCurrent: contextHandle => {
- // Active Emscripten GL layer context object.
- GL.currentContext = GL.contexts[contextHandle];
- // Active WebGL context object.
- Module["ctx"] = GLctx = GL.currentContext?.GLctx;
- return !(contextHandle && !GLctx);
- },
- getContext: contextHandle => GL.contexts[contextHandle],
- deleteContext: contextHandle => {
- if (GL.currentContext === GL.contexts[contextHandle]) {
- GL.currentContext = null;
- }
- if (typeof JSEvents == "object") {
- // Release all JS event handlers on the DOM element that the GL context is
- // associated with since the context is now deleted.
- JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);
- }
- // Make sure the canvas object no longer refers to the context object so
- // there are no GC surprises.
- if (GL.contexts[contextHandle]?.GLctx.canvas) {
- GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
- }
- _free(GL.contexts[contextHandle].handle);
- GL.contexts[contextHandle] = null;
- },
- initExtensions: context => {
- // If this function is called without a specific context object, init the
- // extensions of the currently active context.
- context ||= GL.currentContext;
- if (context.initExtensionsDone) return;
- context.initExtensionsDone = true;
- var GLctx = context.GLctx;
- // Detect the presence of a few extensions manually, since the GL interop
- // layer itself will need to know if they exist.
- // Extensions that are available in both WebGL 1 and WebGL 2
- webgl_enable_WEBGL_multi_draw(GLctx);
- webgl_enable_EXT_polygon_offset_clamp(GLctx);
- webgl_enable_EXT_clip_control(GLctx);
- webgl_enable_WEBGL_polygon_mode(GLctx);
- // Extensions that are only available in WebGL 1 (the calls will be no-ops
- // if called on a WebGL 2 context active)
- webgl_enable_ANGLE_instanced_arrays(GLctx);
- webgl_enable_OES_vertex_array_object(GLctx);
- webgl_enable_WEBGL_draw_buffers(GLctx);
- {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
- }
- for (var ext of getEmscriptenSupportedExtensions(GLctx)) {
- // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders
- // are not enabled by default.
- if (!ext.includes("lose_context") && !ext.includes("debug")) {
- // Call .getExtension() to enable that extension permanently.
- GLctx.getExtension(ext);
- }
- }
- }
- };
- function _eglCreateContext(display, config, hmm, contextAttribs) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(18, 0, 1, display, config, hmm, contextAttribs);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- // EGL 1.4 spec says default EGL_CONTEXT_CLIENT_VERSION is GLES1, but this is not supported by Emscripten.
- // So user must pass EGL_CONTEXT_CLIENT_VERSION == 2 to initialize EGL.
- var glesContextVersion = 1;
- for (;;) {
- var param = (growMemViews(), HEAP32)[((contextAttribs) >> 2)];
- if (param == 12440) {
- glesContextVersion = (growMemViews(), HEAP32)[(((contextAttribs) + (4)) >> 2)];
- } else if (param == 12344) {
- break;
- } else {
- /* EGL1.4 specifies only EGL_CONTEXT_CLIENT_VERSION as supported attribute */ EGL.setErrorCode(12292);
- return 0;
- }
- contextAttribs += 8;
- }
- if (glesContextVersion != 2) {
- EGL.setErrorCode(12293);
- return 0;
- }
- EGL.contextAttributes.majorVersion = glesContextVersion - 1;
- // WebGL 1 is GLES 2, WebGL2 is GLES3
- EGL.contextAttributes.minorVersion = 0;
- EGL.context = GL.createContext(Browser.getCanvas(), EGL.contextAttributes);
- if (EGL.context != 0) {
- EGL.setErrorCode(12288);
- // Run callbacks so that GL emulation works
- GL.makeContextCurrent(EGL.context);
- Browser.useWebGL = true;
- Browser.moduleContextCreatedCallbacks.forEach(callback => callback());
- // Note: This function only creates a context, but it shall not make it active.
- GL.makeContextCurrent(null);
- return 62004;
- } else {
- EGL.setErrorCode(12297);
- // By the EGL 1.4 spec, an implementation that does not support GLES2 (WebGL in this case), this error code is set.
- return 0;
- }
- }
- function _eglCreateWindowSurface(display, config, win, attrib_list) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(19, 0, 1, display, config, win, attrib_list);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (config != 62002) {
- EGL.setErrorCode(12293);
- return 0;
- }
- // TODO: Examine attrib_list! Parameters that can be present there are:
- // - EGL_RENDER_BUFFER (must be EGL_BACK_BUFFER)
- // - EGL_VG_COLORSPACE (can't be set)
- // - EGL_VG_ALPHA_FORMAT (can't be set)
- EGL.setErrorCode(12288);
- return 62006;
- }
- function _eglDestroyContext(display, context) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(20, 0, 1, display, context);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (context != 62004) {
- EGL.setErrorCode(12294);
- return 0;
- }
- GL.deleteContext(EGL.context);
- EGL.setErrorCode(12288);
- if (EGL.currentContext == context) {
- EGL.currentContext = 0;
- }
- return 1;
- }
- function _eglDestroySurface(display, surface) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(21, 0, 1, display, surface);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (surface != 62006) {
- EGL.setErrorCode(12301);
- return 1;
- }
- if (EGL.currentReadSurface == surface) {
- EGL.currentReadSurface = 0;
- }
- if (EGL.currentDrawSurface == surface) {
- EGL.currentDrawSurface = 0;
- }
- EGL.setErrorCode(12288);
- return 1;
- }
- function _eglGetConfigAttrib(display, config, attribute, value) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(22, 0, 1, display, config, attribute, value);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (config != 62002) {
- EGL.setErrorCode(12293);
- return 0;
- }
- if (!value) {
- EGL.setErrorCode(12300);
- return 0;
- }
- EGL.setErrorCode(12288);
- switch (attribute) {
- case 12320:
- // EGL_BUFFER_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = EGL.contextAttributes.alpha ? 32 : 24;
- return 1;
- case 12321:
- // EGL_ALPHA_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = EGL.contextAttributes.alpha ? 8 : 0;
- return 1;
- case 12322:
- // EGL_BLUE_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = 8;
- return 1;
- case 12323:
- // EGL_GREEN_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = 8;
- return 1;
- case 12324:
- // EGL_RED_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = 8;
- return 1;
- case 12325:
- // EGL_DEPTH_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = EGL.contextAttributes.depth ? 24 : 0;
- return 1;
- case 12326:
- // EGL_STENCIL_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = EGL.contextAttributes.stencil ? 8 : 0;
- return 1;
- case 12327:
- // EGL_CONFIG_CAVEAT
- // We can return here one of EGL_NONE (0x3038), EGL_SLOW_CONFIG (0x3050) or EGL_NON_CONFORMANT_CONFIG (0x3051).
- (growMemViews(), HEAP32)[((value) >> 2)] = 12344;
- return 1;
- case 12328:
- // EGL_CONFIG_ID
- (growMemViews(), HEAP32)[((value) >> 2)] = 62002;
- return 1;
- case 12329:
- // EGL_LEVEL
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- case 12330:
- // EGL_MAX_PBUFFER_HEIGHT
- (growMemViews(), HEAP32)[((value) >> 2)] = 4096;
- return 1;
- case 12331:
- // EGL_MAX_PBUFFER_PIXELS
- (growMemViews(), HEAP32)[((value) >> 2)] = 16777216;
- return 1;
- case 12332:
- // EGL_MAX_PBUFFER_WIDTH
- (growMemViews(), HEAP32)[((value) >> 2)] = 4096;
- return 1;
- case 12333:
- // EGL_NATIVE_RENDERABLE
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- case 12334:
- // EGL_NATIVE_VISUAL_ID
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- case 12335:
- // EGL_NATIVE_VISUAL_TYPE
- (growMemViews(), HEAP32)[((value) >> 2)] = 12344;
- return 1;
- case 12337:
- // EGL_SAMPLES
- (growMemViews(), HEAP32)[((value) >> 2)] = EGL.contextAttributes.antialias ? 4 : 0;
- return 1;
- case 12338:
- // EGL_SAMPLE_BUFFERS
- (growMemViews(), HEAP32)[((value) >> 2)] = EGL.contextAttributes.antialias ? 1 : 0;
- return 1;
- case 12339:
- // EGL_SURFACE_TYPE
- (growMemViews(), HEAP32)[((value) >> 2)] = 4;
- return 1;
- case 12340:
- // EGL_TRANSPARENT_TYPE
- // If this returns EGL_TRANSPARENT_RGB (0x3052), transparency is used through color-keying. No such thing applies to Emscripten canvas.
- (growMemViews(), HEAP32)[((value) >> 2)] = 12344;
- return 1;
- case 12341:
- // EGL_TRANSPARENT_BLUE_VALUE
- case 12342:
- // EGL_TRANSPARENT_GREEN_VALUE
- case 12343:
- // EGL_TRANSPARENT_RED_VALUE
- // "If EGL_TRANSPARENT_TYPE is EGL_NONE, then the values for EGL_TRANSPARENT_RED_VALUE, EGL_TRANSPARENT_GREEN_VALUE, and EGL_TRANSPARENT_BLUE_VALUE are undefined."
- (growMemViews(), HEAP32)[((value) >> 2)] = -1;
- return 1;
- case 12345:
- // EGL_BIND_TO_TEXTURE_RGB
- case 12346:
- // EGL_BIND_TO_TEXTURE_RGBA
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- case 12347:
- // EGL_MIN_SWAP_INTERVAL
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- case 12348:
- // EGL_MAX_SWAP_INTERVAL
- (growMemViews(), HEAP32)[((value) >> 2)] = 1;
- return 1;
- case 12349:
- // EGL_LUMINANCE_SIZE
- case 12350:
- // EGL_ALPHA_MASK_SIZE
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- case 12351:
- // EGL_COLOR_BUFFER_TYPE
- // EGL has two types of buffers: EGL_RGB_BUFFER and EGL_LUMINANCE_BUFFER.
- (growMemViews(), HEAP32)[((value) >> 2)] = 12430;
- return 1;
- case 12352:
- // EGL_RENDERABLE_TYPE
- // A bit combination of EGL_OPENGL_ES_BIT,EGL_OPENVG_BIT,EGL_OPENGL_ES2_BIT and EGL_OPENGL_BIT.
- (growMemViews(), HEAP32)[((value) >> 2)] = 4;
- return 1;
- case 12354:
- // EGL_CONFORMANT
- // "EGL_CONFORMANT is a mask indicating if a client API context created with respect to the corresponding EGLConfig will pass the required conformance tests for that API."
- (growMemViews(), HEAP32)[((value) >> 2)] = 0;
- return 1;
- default:
- EGL.setErrorCode(12292);
- return 0;
- }
- }
- function _eglGetDisplay(nativeDisplayType) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(23, 0, 1, nativeDisplayType);
- EGL.setErrorCode(12288);
- // Emscripten EGL implementation "emulates" X11, and eglGetDisplay is
- // expected to accept/receive a pointer to an X11 Display object (or
- // EGL_DEFAULT_DISPLAY).
- if (nativeDisplayType != 0 && nativeDisplayType != 1) {
- return 0;
- }
- return 62e3;
- }
- function _eglGetError() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(24, 0, 1);
- return EGL.errorCode;
- }
- function _eglInitialize(display, majorVersion, minorVersion) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(25, 0, 1, display, majorVersion, minorVersion);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (majorVersion) {
- (growMemViews(), HEAP32)[((majorVersion) >> 2)] = 1;
- }
- if (minorVersion) {
- (growMemViews(), HEAP32)[((minorVersion) >> 2)] = 4;
- }
- EGL.defaultDisplayInitialized = true;
- EGL.setErrorCode(12288);
- return 1;
- }
- function _eglMakeCurrent(display, draw, read, context) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(26, 0, 1, display, draw, read, context);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.
- if (context != 0 && context != 62004) {
- EGL.setErrorCode(12294);
- return 0;
- }
- if ((read != 0 && read != 62006) || (draw != 0 && draw != 62006)) {
- EGL.setErrorCode(12301);
- return 0;
- }
- GL.makeContextCurrent(context ? EGL.context : null);
- EGL.currentContext = context;
- EGL.currentDrawSurface = draw;
- EGL.currentReadSurface = read;
- EGL.setErrorCode(12288);
- return 1;
- }
- var stringToNewUTF8 = str => {
- var size = lengthBytesUTF8(str) + 1;
- var ret = _malloc(size);
- if (ret) stringToUTF8(str, ret, size);
- return ret;
- };
- function _eglQueryString(display, name) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(27, 0, 1, display, name);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.
- EGL.setErrorCode(12288);
- if (EGL.stringCache[name]) return EGL.stringCache[name];
- var ret;
- switch (name) {
- case 12371:
- ret = stringToNewUTF8("Emscripten");
- break;
- case 12372:
- ret = stringToNewUTF8("1.4 Emscripten EGL");
- break;
- case 12373:
- ret = stringToNewUTF8("");
- break;
- // Currently not supporting any EGL extensions.
- case 12429:
- ret = stringToNewUTF8("OpenGL_ES");
- break;
- default:
- EGL.setErrorCode(12300);
- return 0;
- }
- EGL.stringCache[name] = ret;
- return ret;
- }
- function _eglSwapBuffers(dpy, surface) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(28, 0, 1, dpy, surface);
- if (!EGL.defaultDisplayInitialized) {
- EGL.setErrorCode(12289);
- } else if (!GLctx) {
- EGL.setErrorCode(12290);
- } else if (GLctx.isContextLost()) {
- EGL.setErrorCode(12302);
- } else {
- // According to documentation this does an implicit flush.
- // Due to discussion at https://github.com/emscripten-core/emscripten/pull/1871
- // the flush was removed since this _may_ result in slowing code down.
- //_glFlush();
- EGL.setErrorCode(12288);
- return 1;
- }
- return 0;
- }
- /**
- * @param {number=} arg
- * @param {boolean=} noSetTiming
- */ var setMainLoop = (iterFunc, fps, simulateInfiniteLoop, arg, noSetTiming) => {
- assert(!MainLoop.func, "emscripten_set_main_loop: there can only be one main loop function at once");
- MainLoop.func = iterFunc;
- MainLoop.arg = arg;
- var thisMainLoopId = MainLoop.currentlyRunningMainloop;
- function checkIsRunning() {
- if (thisMainLoopId < MainLoop.currentlyRunningMainloop) {
- runtimeKeepalivePop();
- maybeExit();
- return false;
- }
- return true;
- }
- // We create the loop runner here but it is not actually running until
- // _emscripten_set_main_loop_timing is called (which might happen at a
- // later time). This member signifies that the current runner has not
- // yet been started so that we can call runtimeKeepalivePush when it
- // gets its timing set for the first time.
- MainLoop.running = false;
- MainLoop.runner = function MainLoop_runner() {
- if (ABORT) return;
- if (MainLoop.queue.length > 0) {
- var start = Date.now();
- var blocker = MainLoop.queue.shift();
- blocker.func(blocker.arg);
- if (MainLoop.remainingBlockers) {
- var remaining = MainLoop.remainingBlockers;
- var next = remaining % 1 == 0 ? remaining - 1 : Math.floor(remaining);
- if (blocker.counted) {
- MainLoop.remainingBlockers = next;
- } else {
- // not counted, but move the progress along a tiny bit
- next = next + .5;
- // do not steal all the next one's progress
- MainLoop.remainingBlockers = (8 * remaining + next) / 9;
- }
- }
- MainLoop.updateStatus();
- // catches pause/resume main loop from blocker execution
- if (!checkIsRunning()) return;
- setTimeout(MainLoop.runner, 0);
- return;
- }
- // catch pauses from non-main loop sources
- if (!checkIsRunning()) return;
- // Implement very basic swap interval control
- MainLoop.currentFrameNumber = MainLoop.currentFrameNumber + 1 | 0;
- if (MainLoop.timingMode == 1 && MainLoop.timingValue > 1 && MainLoop.currentFrameNumber % MainLoop.timingValue != 0) {
- // Not the scheduled time to render this frame - skip.
- MainLoop.scheduler();
- return;
- } else if (MainLoop.timingMode == 0) {
- MainLoop.tickStartTime = _emscripten_get_now();
- if (Module["ctx"]) {
- warnOnce("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!");
- }
- }
- MainLoop.runIter(iterFunc);
- // catch pauses from the main loop itself
- if (!checkIsRunning()) return;
- MainLoop.scheduler();
- };
- if (!noSetTiming) {
- if (fps > 0) {
- _emscripten_set_main_loop_timing(0, 1e3 / fps);
- } else {
- // Do rAF by rendering each frame (no decimating)
- _emscripten_set_main_loop_timing(1, 1);
- }
- MainLoop.scheduler();
- }
- if (simulateInfiniteLoop) {
- throw "unwind";
- }
- };
- var MainLoop = {
- running: false,
- scheduler: null,
- currentlyRunningMainloop: 0,
- func: null,
- arg: 0,
- timingMode: 0,
- timingValue: 0,
- currentFrameNumber: 0,
- queue: [],
- preMainLoop: [],
- postMainLoop: [],
- pause() {
- MainLoop.scheduler = null;
- // Incrementing this signals the previous main loop that it's now become old, and it must return.
- MainLoop.currentlyRunningMainloop++;
- },
- resume() {
- MainLoop.currentlyRunningMainloop++;
- var timingMode = MainLoop.timingMode;
- var timingValue = MainLoop.timingValue;
- var func = MainLoop.func;
- MainLoop.func = null;
- // do not set timing and call scheduler, we will do it on the next lines
- setMainLoop(func, 0, false, MainLoop.arg, true);
- _emscripten_set_main_loop_timing(timingMode, timingValue);
- MainLoop.scheduler();
- },
- updateStatus() {
- if (Module["setStatus"]) {
- var message = Module["statusMessage"] || "Please wait...";
- var remaining = MainLoop.remainingBlockers ?? 0;
- var expected = MainLoop.expectedBlockers ?? 0;
- if (remaining) {
- if (remaining < expected) {
- Module["setStatus"](`{message} ({expected - remaining}/{expected})`);
- } else {
- Module["setStatus"](message);
- }
- } else {
- Module["setStatus"]("");
- }
- }
- },
- init() {},
- runIter(func) {
- if (ABORT) return;
- for (var pre of MainLoop.preMainLoop) {
- if (pre() === false) {
- return;
- }
- }
- callUserCallback(func);
- for (var post of MainLoop.postMainLoop) {
- post();
- }
- checkStackCookie();
- },
- nextRAF: 0,
- fakeRequestAnimationFrame(func) {
- // try to keep 60fps between calls to here
- var now = Date.now();
- if (MainLoop.nextRAF === 0) {
- MainLoop.nextRAF = now + 1e3 / 60;
- } else {
- while (now + 2 >= MainLoop.nextRAF) {
- // fudge a little, to avoid timer jitter causing us to do lots of delay:0
- MainLoop.nextRAF += 1e3 / 60;
- }
- }
- var delay = Math.max(MainLoop.nextRAF - now, 0);
- setTimeout(func, delay);
- },
- requestAnimationFrame(func) {
- if (globalThis.requestAnimationFrame) {
- requestAnimationFrame(func);
- } else {
- MainLoop.fakeRequestAnimationFrame(func);
- }
- }
- };
- var _emscripten_set_main_loop_timing = (mode, value) => {
- MainLoop.timingMode = mode;
- MainLoop.timingValue = value;
- if (!MainLoop.func) {
- err("emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.");
- return 1;
- }
- if (!MainLoop.running) {
- runtimeKeepalivePush();
- MainLoop.running = true;
- }
- if (mode == 0) {
- MainLoop.scheduler = function MainLoop_scheduler_setTimeout() {
- var timeUntilNextTick = Math.max(0, MainLoop.tickStartTime + value - _emscripten_get_now()) | 0;
- setTimeout(MainLoop.runner, timeUntilNextTick);
- };
- } else if (mode == 1) {
- MainLoop.scheduler = function MainLoop_scheduler_rAF() {
- MainLoop.requestAnimationFrame(MainLoop.runner);
- };
- } else {
- assert(mode == 2);
- if (!MainLoop.setImmediate) {
- if (globalThis.scheduler) {
- // Some modern browsers implement scheduler.postTask, but not all.
- MainLoop.setImmediate = scheduler.postTask.bind(scheduler);
- } else if (globalThis.setImmediate) {
- MainLoop.setImmediate = setImmediate;
- } else {
- // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed)
- var setImmediates = [];
- var emscriptenMainLoopMessageId = "setimmediate";
- /** @param {Event} event */ var MainLoop_setImmediate_messageHandler = event => {
- if (event.data === emscriptenMainLoopMessageId) {
- event.stopPropagation();
- setImmediates.shift()();
- }
- };
- addEventListener("message", MainLoop_setImmediate_messageHandler, true);
- MainLoop.setImmediate = /** @type{function(function(): ?, ...?): number} */ (func => {
- setImmediates.push(func);
- if (ENVIRONMENT_IS_WORKER) {
- // The postMessge API in a Worker, sends message to the main
- // thread and does not support the `targetOrigin` (*) argument.
- postMessage(emscriptenMainLoopMessageId);
- } else {
- postMessage(emscriptenMainLoopMessageId, "*");
- }
- });
- }
- }
- MainLoop.scheduler = function MainLoop_scheduler_setImmediate() {
- MainLoop.setImmediate(MainLoop.runner);
- };
- }
- return 0;
- };
- function _eglSwapInterval(display, interval) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(29, 0, 1, display, interval);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- if (interval == 0) _emscripten_set_main_loop_timing(0, 0); else _emscripten_set_main_loop_timing(1, interval);
- EGL.setErrorCode(12288);
- return 1;
- }
- function _eglTerminate(display) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(30, 0, 1, display);
- if (display != 62e3) {
- EGL.setErrorCode(12296);
- return 0;
- }
- EGL.currentContext = 0;
- EGL.currentReadSurface = 0;
- EGL.currentDrawSurface = 0;
- EGL.defaultDisplayInitialized = false;
- EGL.setErrorCode(12288);
- return 1;
- }
- function _eglWaitClient() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(31, 0, 1);
- EGL.setErrorCode(12288);
- return 1;
- }
- var _eglWaitGL = _eglWaitClient;
- function _eglWaitNative(nativeEngineId) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(32, 0, 1, nativeEngineId);
- EGL.setErrorCode(12288);
- return 1;
- }
- var readEmAsmArgsArray = [];
- var readEmAsmArgs = (sigPtr, buf) => {
- // Nobody should have mutated _readEmAsmArgsArray underneath us to be something else than an array.
- assert(Array.isArray(readEmAsmArgsArray));
- // The input buffer is allocated on the stack, so it must be stack-aligned.
- assert(buf % 16 == 0);
- readEmAsmArgsArray.length = 0;
- var ch;
- // Most arguments are i32s, so shift the buffer pointer so it is a plain
- // index into HEAP32.
- while (ch = (growMemViews(), HEAPU8)[sigPtr++]) {
- var chr = String.fromCharCode(ch);
- var validChars = [ "d", "f", "i", "p" ];
- // In WASM_BIGINT mode we support passing i64 values as bigint.
- validChars.push("j");
- assert(validChars.includes(chr), `Invalid character ${ch}("${chr}") in readEmAsmArgs! Use only [${validChars}], and do not specify "v" for void return argument.`);
- // Floats are always passed as doubles, so all types except for 'i'
- // are 8 bytes and require alignment.
- var wide = (ch != 105);
- wide &= (ch != 112);
- buf += wide && (buf % 8) ? 4 : 0;
- readEmAsmArgsArray.push(// Special case for pointers under wasm64 or CAN_ADDRESS_2GB mode.
- ch == 112 ? (growMemViews(), HEAPU32)[((buf) >> 2)] : ch == 106 ? (growMemViews(),
- HEAP64)[((buf) >> 3)] : ch == 105 ? (growMemViews(), HEAP32)[((buf) >> 2)] : (growMemViews(),
- HEAPF64)[((buf) >> 3)]);
- buf += wide ? 8 : 4;
- }
- return readEmAsmArgsArray;
- };
- var runEmAsmFunction = (code, sigPtr, argbuf) => {
- var args = readEmAsmArgs(sigPtr, argbuf);
- assert(ASM_CONSTS.hasOwnProperty(code), `No EM_ASM constant found at address ${code}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);
- return ASM_CONSTS[code](...args);
- };
- var _emscripten_asm_const_int = (code, sigPtr, argbuf) => runEmAsmFunction(code, sigPtr, argbuf);
- var runMainThreadEmAsm = (emAsmAddr, sigPtr, argbuf, sync) => {
- var args = readEmAsmArgs(sigPtr, argbuf);
- if (ENVIRONMENT_IS_PTHREAD) {
- // EM_ASM functions are variadic, receiving the actual arguments as a buffer
- // in memory. the last parameter (argBuf) points to that data. We need to
- // always un-variadify that, *before proxying*, as in the async case this
- // is a stack allocation that LLVM made, which may go away before the main
- // thread gets the message. For that reason we handle proxying *after* the
- // call to readEmAsmArgs, and therefore we do that manually here instead
- // of using __proxy. (And for simplicity, do the same in the sync
- // case as well, even though it's not strictly necessary, to keep the two
- // code paths as similar as possible on both sides.)
- return proxyToMainThread(0, emAsmAddr, sync, ...args);
- }
- assert(ASM_CONSTS.hasOwnProperty(emAsmAddr), `No EM_ASM constant found at address ${emAsmAddr}. The loaded WebAssembly file is likely out of sync with the generated JavaScript.`);
- return ASM_CONSTS[emAsmAddr](...args);
- };
- var _emscripten_asm_const_int_sync_on_main_thread = (emAsmAddr, sigPtr, argbuf) => runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, 1);
- var _emscripten_asm_const_ptr_sync_on_main_thread = (emAsmAddr, sigPtr, argbuf) => runMainThreadEmAsm(emAsmAddr, sigPtr, argbuf, 1);
- var _emscripten_cancel_main_loop = () => {
- MainLoop.pause();
- MainLoop.func = null;
- };
- var _emscripten_check_blocking_allowed = () => {
- if (ENVIRONMENT_IS_NODE) return;
- if (ENVIRONMENT_IS_WORKER) return;
- // Blocking in a worker/pthread is fine.
- warnOnce("Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread");
- };
- var onExits = [];
- var addOnExit = cb => onExits.push(cb);
- var JSEvents = {
- removeAllEventListeners() {
- while (JSEvents.eventHandlers.length) {
- JSEvents._removeHandler(JSEvents.eventHandlers.length - 1);
- }
- JSEvents.deferredCalls = [];
- },
- inEventHandler: 0,
- deferredCalls: [],
- deferCall(targetFunction, precedence, argsList) {
- function arraysHaveEqualContent(arrA, arrB) {
- if (arrA.length != arrB.length) return false;
- for (var i in arrA) {
- if (arrA[i] != arrB[i]) return false;
- }
- return true;
- }
- // Test if the given call was already queued, and if so, don't add it again.
- for (var call of JSEvents.deferredCalls) {
- if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
- return;
- }
- }
- JSEvents.deferredCalls.push({
- targetFunction,
- precedence,
- argsList
- });
- JSEvents.deferredCalls.sort((x, y) => x.precedence - y.precedence);
- },
- removeDeferredCalls(targetFunction) {
- JSEvents.deferredCalls = JSEvents.deferredCalls.filter(call => call.targetFunction != targetFunction);
- },
- canPerformEventHandlerRequests() {
- // Browsers that support navigator.userActivation.isActive: https://developer.mozilla.org/en-US/docs/Web/API/UserActivation/isActive
- if (navigator.userActivation) {
- // Verify against transient activation status from UserActivation API
- // whether it is possible to perform a request here without needing to defer. See
- // https://developer.mozilla.org/en-US/docs/Web/Security/User_activation#transient_activation
- // and https://caniuse.com/mdn-api_useractivation
- return navigator.userActivation.isActive;
- }
- return JSEvents.inEventHandler && JSEvents.currentEventHandler.allowsDeferredCalls;
- },
- runDeferredCalls() {
- if (!JSEvents.canPerformEventHandlerRequests()) {
- return;
- }
- var deferredCalls = JSEvents.deferredCalls;
- JSEvents.deferredCalls = [];
- for (var call of deferredCalls) {
- call.targetFunction(...call.argsList);
- }
- },
- eventHandlers: [],
- removeAllHandlersOnTarget: (target, eventTypeString) => {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
- if (JSEvents.eventHandlers[i].target == target && (!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
- JSEvents._removeHandler(i--);
- }
- }
- },
- _removeHandler(i) {
- var h = JSEvents.eventHandlers[i];
- h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture);
- JSEvents.eventHandlers.splice(i, 1);
- },
- registerOrRemoveHandler(eventHandler) {
- if (!eventHandler.target) {
- err("registerOrRemoveHandler: the target element for event handler registration does not exist, when processing the following event handler registration:");
- console.dir(eventHandler);
- return -4;
- }
- if (eventHandler.callbackfunc) {
- eventHandler.eventListenerFunc = function(event) {
- // Increment nesting count for the event handler.
- ++JSEvents.inEventHandler;
- JSEvents.currentEventHandler = eventHandler;
- // Process any old deferred calls the user has placed.
- JSEvents.runDeferredCalls();
- // Process the actual event, calls back to user C code handler.
- eventHandler.handlerFunc(event);
- // Process any new deferred calls that were placed right now from this event handler.
- JSEvents.runDeferredCalls();
- // Out of event handler - restore nesting count.
- --JSEvents.inEventHandler;
- };
- eventHandler.target.addEventListener(eventHandler.eventTypeString, eventHandler.eventListenerFunc, eventHandler.useCapture);
- JSEvents.eventHandlers.push(eventHandler);
- } else {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
- if (JSEvents.eventHandlers[i].target == eventHandler.target && JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
- JSEvents._removeHandler(i--);
- }
- }
- }
- return 0;
- },
- removeSingleHandler(eventHandler) {
- let success = false;
- for (let i = 0; i < JSEvents.eventHandlers.length; ++i) {
- const handler = JSEvents.eventHandlers[i];
- if (handler.target === eventHandler.target && handler.eventTypeId === eventHandler.eventTypeId && handler.callbackfunc === eventHandler.callbackfunc && handler.userData === eventHandler.userData) {
- // in some very rare cases (ex: Safari / fullscreen events), there is more than 1 handler (eventTypeString is different)
- JSEvents._removeHandler(i--);
- success = true;
- }
- }
- return success ? 0 : -5;
- },
- getTargetThreadForEventCallback(targetThread) {
- switch (targetThread) {
- case 1:
- // The event callback for the current event should be called on the
- // main browser thread. (0 == don't proxy)
- return 0;
- case 2:
- // The event callback for the current event should be backproxied to
- // the thread that is registering the event.
- // This can be 0 in the case that the caller uses
- // EM_CALLBACK_THREAD_CONTEXT_CALLING_THREAD but on the main thread
- // itself.
- return PThread.currentProxiedOperationCallerThread;
- default:
- // The event callback for the current event should be proxied to the
- // given specific thread.
- return targetThread;
- }
- },
- getNodeNameForTarget(target) {
- if (target == window) return "#window";
- if (target == screen) return "#screen";
- return target?.nodeName ?? "";
- },
- fullscreenEnabled() {
- return document.fullscreenEnabled || document.webkitFullscreenEnabled;
- }
- };
- /** @type {Object} */ var specialHTMLTargets = [ 0, globalThis.document ?? 0, globalThis.window ?? 0 ];
- var maybeCStringToJsString = cString => cString > 2 ? UTF8ToString(cString) : cString;
- var findEventTarget = target => {
- target = maybeCStringToJsString(target);
- var domElement = specialHTMLTargets[target] || globalThis.document?.querySelector(target);
- return domElement;
- };
- var findCanvasEventTarget = findEventTarget;
- var getCanvasSizeCallingThread = (target, width, height) => {
- var canvas = findCanvasEventTarget(target);
- if (!canvas) return -4;
- if (!canvas.controlTransferredOffscreen) {
- (growMemViews(), HEAP32)[((width) >> 2)] = canvas.width;
- (growMemViews(), HEAP32)[((height) >> 2)] = canvas.height;
- } else {
- return -4;
- }
- return 0;
- };
- function getCanvasSizeMainThread(target, width, height) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(34, 0, 1, target, width, height);
- return getCanvasSizeCallingThread(target, width, height);
- }
- var _emscripten_get_canvas_element_size = (target, width, height) => {
- var canvas = findCanvasEventTarget(target);
- if (canvas) {
- return getCanvasSizeCallingThread(target, width, height);
- }
- return getCanvasSizeMainThread(target, width, height);
- };
- var stringToUTF8OnStack = str => {
- var size = lengthBytesUTF8(str) + 1;
- var ret = stackAlloc(size);
- stringToUTF8(str, ret, size);
- return ret;
- };
- var getCanvasElementSize = target => {
- var sp = stackSave();
- var w = stackAlloc(8);
- var h = w + 4;
- var targetInt = stringToUTF8OnStack(target.id);
- var ret = _emscripten_get_canvas_element_size(targetInt, w, h);
- var size = [ (growMemViews(), HEAP32)[((w) >> 2)], (growMemViews(), HEAP32)[((h) >> 2)] ];
- stackRestore(sp);
- return size;
- };
- var setCanvasElementSizeCallingThread = (target, width, height) => {
- var canvas = findCanvasEventTarget(target);
- if (!canvas) return -4;
- if (!canvas.controlTransferredOffscreen) {
- var autoResizeViewport = false;
- if (canvas.GLctxObject?.GLctx) {
- var prevViewport = canvas.GLctxObject.GLctx.getParameter(2978);
- // TODO: Perhaps autoResizeViewport should only be true if FBO 0 is currently active?
- autoResizeViewport = (prevViewport[0] === 0 && prevViewport[1] === 0 && prevViewport[2] === canvas.width && prevViewport[3] === canvas.height);
- }
- canvas.width = width;
- canvas.height = height;
- if (autoResizeViewport) {
- // TODO: Add -sCANVAS_RESIZE_SETS_GL_VIEWPORT=0/1 option (default=1). This is commonly done and several graphics engines depend on this,
- // but this can be quite disruptive.
- canvas.GLctxObject.GLctx.viewport(0, 0, width, height);
- }
- } else {
- return -4;
- }
- return 0;
- };
- function setCanvasElementSizeMainThread(target, width, height) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(35, 0, 1, target, width, height);
- return setCanvasElementSizeCallingThread(target, width, height);
- }
- var _emscripten_set_canvas_element_size = (target, width, height) => {
- var canvas = findCanvasEventTarget(target);
- if (canvas) {
- return setCanvasElementSizeCallingThread(target, width, height);
- }
- return setCanvasElementSizeMainThread(target, width, height);
- };
- var setCanvasElementSize = (target, width, height) => {
- if (!target.controlTransferredOffscreen) {
- target.width = width;
- target.height = height;
- } else {
- // This function is being called from high-level JavaScript code instead of asm.js/Wasm,
- // and it needs to synchronously proxy over to another thread, so marshal the string onto the heap to do the call.
- var sp = stackSave();
- var targetInt = stringToUTF8OnStack(target.id);
- _emscripten_set_canvas_element_size(targetInt, width, height);
- stackRestore(sp);
- }
- };
- var currentFullscreenStrategy = {};
- var registerRestoreOldStyle = canvas => {
- var canvasSize = getCanvasElementSize(canvas);
- var oldWidth = canvasSize[0];
- var oldHeight = canvasSize[1];
- var oldCssWidth = canvas.style.width;
- var oldCssHeight = canvas.style.height;
- var oldBackgroundColor = canvas.style.backgroundColor;
- // Chrome reads color from here.
- var oldDocumentBackgroundColor = document.body.style.backgroundColor;
- // IE11 reads color from here.
- // Firefox always has black background color.
- var oldPaddingLeft = canvas.style.paddingLeft;
- // Chrome, FF, Safari
- var oldPaddingRight = canvas.style.paddingRight;
- var oldPaddingTop = canvas.style.paddingTop;
- var oldPaddingBottom = canvas.style.paddingBottom;
- var oldMarginLeft = canvas.style.marginLeft;
- // IE11
- var oldMarginRight = canvas.style.marginRight;
- var oldMarginTop = canvas.style.marginTop;
- var oldMarginBottom = canvas.style.marginBottom;
- var oldDocumentBodyMargin = document.body.style.margin;
- var oldDocumentOverflow = document.documentElement.style.overflow;
- // Chrome, Firefox
- var oldDocumentScroll = document.body.scroll;
- // IE
- var oldImageRendering = canvas.style.imageRendering;
- function restoreOldStyle() {
- if (!getFullscreenElement()) {
- document.removeEventListener("fullscreenchange", restoreOldStyle);
- // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version.
- document.removeEventListener("webkitfullscreenchange", restoreOldStyle);
- setCanvasElementSize(canvas, oldWidth, oldHeight);
- canvas.style.width = oldCssWidth;
- canvas.style.height = oldCssHeight;
- canvas.style.backgroundColor = oldBackgroundColor;
- // Chrome
- // IE11 hack: assigning 'undefined' or an empty string to document.body.style.backgroundColor has no effect, so first assign back the default color
- // before setting the undefined value. Setting undefined value is also important, or otherwise we would later treat that as something that the user
- // had explicitly set so subsequent fullscreen transitions would not set background color properly.
- if (!oldDocumentBackgroundColor) document.body.style.backgroundColor = "white";
- document.body.style.backgroundColor = oldDocumentBackgroundColor;
- // IE11
- canvas.style.paddingLeft = oldPaddingLeft;
- // Chrome, FF, Safari
- canvas.style.paddingRight = oldPaddingRight;
- canvas.style.paddingTop = oldPaddingTop;
- canvas.style.paddingBottom = oldPaddingBottom;
- canvas.style.marginLeft = oldMarginLeft;
- // IE11
- canvas.style.marginRight = oldMarginRight;
- canvas.style.marginTop = oldMarginTop;
- canvas.style.marginBottom = oldMarginBottom;
- document.body.style.margin = oldDocumentBodyMargin;
- document.documentElement.style.overflow = oldDocumentOverflow;
- // Chrome, Firefox
- document.body.scroll = oldDocumentScroll;
- // IE
- canvas.style.imageRendering = oldImageRendering;
- if (canvas.GLctxObject) canvas.GLctxObject.GLctx.viewport(0, 0, oldWidth, oldHeight);
- if (currentFullscreenStrategy.canvasResizedCallback) {
- if (currentFullscreenStrategy.canvasResizedCallbackTargetThread) __emscripten_run_callback_on_thread(currentFullscreenStrategy.canvasResizedCallbackTargetThread, currentFullscreenStrategy.canvasResizedCallback, 37, 0, currentFullscreenStrategy.canvasResizedCallbackUserData); else getWasmTableEntry(currentFullscreenStrategy.canvasResizedCallback)(37, 0, currentFullscreenStrategy.canvasResizedCallbackUserData);
- }
- }
- }
- document.addEventListener("fullscreenchange", restoreOldStyle);
- // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version.
- document.addEventListener("webkitfullscreenchange", restoreOldStyle);
- return restoreOldStyle;
- };
- var setLetterbox = (element, topBottom, leftRight) => {
- // Cannot use margin to specify letterboxes in FF or Chrome, since those ignore margins in fullscreen mode.
- element.style.paddingLeft = element.style.paddingRight = leftRight + "px";
- element.style.paddingTop = element.style.paddingBottom = topBottom + "px";
- };
- var getBoundingClientRect = e => specialHTMLTargets.indexOf(e) < 0 ? e.getBoundingClientRect() : {
- "left": 0,
- "top": 0
- };
- var JSEvents_resizeCanvasForFullscreen = (target, strategy) => {
- var restoreOldStyle = registerRestoreOldStyle(target);
- var cssWidth = strategy.softFullscreen ? innerWidth : screen.width;
- var cssHeight = strategy.softFullscreen ? innerHeight : screen.height;
- var rect = getBoundingClientRect(target);
- var windowedCssWidth = rect.width;
- var windowedCssHeight = rect.height;
- var canvasSize = getCanvasElementSize(target);
- var windowedRttWidth = canvasSize[0];
- var windowedRttHeight = canvasSize[1];
- if (strategy.scaleMode == 3) {
- setLetterbox(target, (cssHeight - windowedCssHeight) / 2, (cssWidth - windowedCssWidth) / 2);
- cssWidth = windowedCssWidth;
- cssHeight = windowedCssHeight;
- } else if (strategy.scaleMode == 2) {
- if (cssWidth * windowedRttHeight < windowedRttWidth * cssHeight) {
- var desiredCssHeight = windowedRttHeight * cssWidth / windowedRttWidth;
- setLetterbox(target, (cssHeight - desiredCssHeight) / 2, 0);
- cssHeight = desiredCssHeight;
- } else {
- var desiredCssWidth = windowedRttWidth * cssHeight / windowedRttHeight;
- setLetterbox(target, 0, (cssWidth - desiredCssWidth) / 2);
- cssWidth = desiredCssWidth;
- }
- }
- // If we are adding padding, must choose a background color or otherwise Chrome will give the
- // padding a default white color. Do it only if user has not customized their own background color.
- target.style.backgroundColor ||= "black";
- // IE11 does the same, but requires the color to be set in the document body.
- document.body.style.backgroundColor ||= "black";
- // IE11
- // Firefox always shows black letterboxes independent of style color.
- target.style.width = cssWidth + "px";
- target.style.height = cssHeight + "px";
- if (strategy.filteringMode == 1) {
- target.style.imageRendering = "optimizeSpeed";
- target.style.imageRendering = "-moz-crisp-edges";
- target.style.imageRendering = "-o-crisp-edges";
- target.style.imageRendering = "-webkit-optimize-contrast";
- target.style.imageRendering = "optimize-contrast";
- target.style.imageRendering = "crisp-edges";
- target.style.imageRendering = "pixelated";
- }
- var dpiScale = (strategy.canvasResolutionScaleMode == 2) ? devicePixelRatio : 1;
- if (strategy.canvasResolutionScaleMode != 0) {
- var newWidth = (cssWidth * dpiScale) | 0;
- var newHeight = (cssHeight * dpiScale) | 0;
- setCanvasElementSize(target, newWidth, newHeight);
- if (target.GLctxObject) target.GLctxObject.GLctx.viewport(0, 0, newWidth, newHeight);
- }
- return restoreOldStyle;
- };
- var JSEvents_requestFullscreen = (target, strategy) => {
- // EMSCRIPTEN_FULLSCREEN_SCALE_DEFAULT + EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE is a mode where no extra logic is performed to the DOM elements.
- if (strategy.scaleMode != 0 || strategy.canvasResolutionScaleMode != 0) {
- JSEvents_resizeCanvasForFullscreen(target, strategy);
- }
- if (target.requestFullscreen) {
- target.requestFullscreen();
- } else if (target.webkitRequestFullscreen) {
- target.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
- } else {
- return JSEvents.fullscreenEnabled() ? -3 : -1;
- }
- currentFullscreenStrategy = strategy;
- if (strategy.canvasResizedCallback) {
- if (strategy.canvasResizedCallbackTargetThread) __emscripten_run_callback_on_thread(strategy.canvasResizedCallbackTargetThread, strategy.canvasResizedCallback, 37, 0, strategy.canvasResizedCallbackUserData); else getWasmTableEntry(strategy.canvasResizedCallback)(37, 0, strategy.canvasResizedCallbackUserData);
- }
- return 0;
- };
- function _emscripten_exit_fullscreen() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(33, 0, 1);
- if (!JSEvents.fullscreenEnabled()) return -1;
- // Make sure no queued up calls will fire after this.
- JSEvents.removeDeferredCalls(JSEvents_requestFullscreen);
- var d = specialHTMLTargets[1];
- if (d.exitFullscreen) {
- d.fullscreenElement && d.exitFullscreen();
- } else if (d.webkitExitFullscreen) {
- d.webkitFullscreenElement && d.webkitExitFullscreen();
- } else {
- return -1;
- }
- return 0;
- }
- var requestPointerLock = target => {
- if (target.requestPointerLock) {
- target.requestPointerLock();
- } else {
- // document.body is known to accept pointer lock, so use that to differentiate if the user passed a bad element,
- // or if the whole browser just doesn't support the feature.
- if (document.body.requestPointerLock) {
- return -3;
- }
- return -1;
- }
- return 0;
- };
- function _emscripten_exit_pointerlock() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(36, 0, 1);
- // Make sure no queued up calls will fire after this.
- JSEvents.removeDeferredCalls(requestPointerLock);
- if (!document.exitPointerLock) return -1;
- document.exitPointerLock();
- return 0;
- }
- var _emscripten_exit_with_live_runtime = () => {
- runtimeKeepalivePush();
- throw "unwind";
- };
- function _emscripten_force_exit(status) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(37, 0, 1, status);
- warnOnce("emscripten_force_exit cannot actually shut down the runtime, as the build does not have EXIT_RUNTIME set");
- __emscripten_runtime_keepalive_clear();
- _exit(status);
- }
- function _emscripten_get_device_pixel_ratio() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(38, 0, 1);
- return globalThis.devicePixelRatio ?? 1;
- }
- function _emscripten_get_element_css_size(target, width, height) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(39, 0, 1, target, width, height);
- target = findEventTarget(target);
- if (!target) return -4;
- var rect = getBoundingClientRect(target);
- (growMemViews(), HEAPF64)[((width) >> 3)] = rect.width;
- (growMemViews(), HEAPF64)[((height) >> 3)] = rect.height;
- return 0;
- }
- var fillGamepadEventData = (eventStruct, e) => {
- (growMemViews(), HEAPF64)[((eventStruct) >> 3)] = e.timestamp;
- for (var i = 0; i < e.axes.length; ++i) {
- (growMemViews(), HEAPF64)[(((eventStruct + i * 8) + (16)) >> 3)] = e.axes[i];
- }
- for (var i = 0; i < e.buttons.length; ++i) {
- if (typeof e.buttons[i] == "object") {
- (growMemViews(), HEAPF64)[(((eventStruct + i * 8) + (528)) >> 3)] = e.buttons[i].value;
- } else {
- (growMemViews(), HEAPF64)[(((eventStruct + i * 8) + (528)) >> 3)] = e.buttons[i];
- }
- }
- for (var i = 0; i < e.buttons.length; ++i) {
- if (typeof e.buttons[i] == "object") {
- (growMemViews(), HEAP8)[(eventStruct + i) + (1040)] = e.buttons[i].pressed;
- } else {
- // Assigning a boolean to HEAP32, that's ok, but Closure would like to warn about it:
- /** @suppress {checkTypes} */ (growMemViews(), HEAP8)[(eventStruct + i) + (1040)] = e.buttons[i] == 1;
- }
- }
- (growMemViews(), HEAP8)[(eventStruct) + (1104)] = e.connected;
- (growMemViews(), HEAP32)[(((eventStruct) + (1108)) >> 2)] = e.index;
- (growMemViews(), HEAP32)[(((eventStruct) + (8)) >> 2)] = e.axes.length;
- (growMemViews(), HEAP32)[(((eventStruct) + (12)) >> 2)] = e.buttons.length;
- stringToUTF8(e.id, eventStruct + 1112, 64);
- stringToUTF8(e.mapping, eventStruct + 1176, 64);
- };
- function _emscripten_get_gamepad_status(index, gamepadState) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(40, 0, 1, index, gamepadState);
- assert(JSEvents.lastGamepadState, "emscripten_get_gamepad_status() called before emscripten_sample_gamepad_data()");
- // INVALID_PARAM is returned on a Gamepad index that never was there.
- if (index < 0 || index >= JSEvents.lastGamepadState.length) return -5;
- // NO_DATA is returned on a Gamepad index that was removed.
- // For previously disconnected gamepads there should be an empty slot (null/undefined/false) at the index.
- // This is because gamepads must keep their original position in the array.
- // For example, removing the first of two gamepads produces [null/undefined/false, gamepad].
- if (!JSEvents.lastGamepadState[index]) return -7;
- fillGamepadEventData(gamepadState, JSEvents.lastGamepadState[index]);
- return 0;
- }
- function _emscripten_get_num_gamepads() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(41, 0, 1);
- assert(JSEvents.lastGamepadState, "emscripten_get_num_gamepads() called before emscripten_sample_gamepad_data()");
- // N.B. Do not call emscripten_get_num_gamepads() unless having first called emscripten_sample_gamepad_data(), and that has returned EMSCRIPTEN_RESULT_SUCCESS.
- // Otherwise the following line will throw an exception.
- return JSEvents.lastGamepadState.length;
- }
- function _emscripten_get_screen_size(width, height) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(42, 0, 1, width, height);
- (growMemViews(), HEAP32)[((width) >> 2)] = screen.width;
- (growMemViews(), HEAP32)[((height) >> 2)] = screen.height;
- }
- var _emscripten_glActiveTexture = x0 => GLctx.activeTexture(x0);
- var _emscripten_glAttachShader = (program, shader) => {
- GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
- };
- var _emscripten_glBeginQueryEXT = (target, id) => {
- GLctx.disjointTimerQueryExt["beginQueryEXT"](target, GL.queries[id]);
- };
- var _emscripten_glBindAttribLocation = (program, index, name) => {
- GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name));
- };
- var _emscripten_glBindBuffer = (target, buffer) => {
- GLctx.bindBuffer(target, GL.buffers[buffer]);
- };
- var _emscripten_glBindFramebuffer = (target, framebuffer) => {
- GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer]);
- };
- var _emscripten_glBindRenderbuffer = (target, renderbuffer) => {
- GLctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]);
- };
- var _emscripten_glBindTexture = (target, texture) => {
- GLctx.bindTexture(target, GL.textures[texture]);
- };
- var _emscripten_glBindVertexArray = vao => {
- GLctx.bindVertexArray(GL.vaos[vao]);
- };
- var _glBindVertexArray = _emscripten_glBindVertexArray;
- var _emscripten_glBindVertexArrayOES = _glBindVertexArray;
- var _emscripten_glBlendColor = (x0, x1, x2, x3) => GLctx.blendColor(x0, x1, x2, x3);
- var _emscripten_glBlendEquation = x0 => GLctx.blendEquation(x0);
- var _emscripten_glBlendEquationSeparate = (x0, x1) => GLctx.blendEquationSeparate(x0, x1);
- var _emscripten_glBlendFunc = (x0, x1) => GLctx.blendFunc(x0, x1);
- var _emscripten_glBlendFuncSeparate = (x0, x1, x2, x3) => GLctx.blendFuncSeparate(x0, x1, x2, x3);
- var _emscripten_glBufferData = (target, size, data, usage) => {
- // N.b. here first form specifies a heap subarray, second form an integer
- // size, so the ?: code here is polymorphic. It is advised to avoid
- // randomly mixing both uses in calling code, to avoid any potential JS
- // engine JIT issues.
- GLctx.bufferData(target, data ? (growMemViews(), HEAPU8).subarray(data, data + size) : size, usage);
- };
- var webglBufferSubData = (target, offset, size, data, src = (growMemViews(), HEAPU8)) => {
- GLctx.bufferSubData(target, offset, src.subarray(data, data + size));
- };
- var _emscripten_glBufferSubData = (target, offset, size, data) => webglBufferSubData(target, offset, size, data);
- var _emscripten_glCheckFramebufferStatus = x0 => GLctx.checkFramebufferStatus(x0);
- var _emscripten_glClear = x0 => GLctx.clear(x0);
- var _emscripten_glClearColor = (x0, x1, x2, x3) => GLctx.clearColor(x0, x1, x2, x3);
- var _emscripten_glClearDepthf = x0 => GLctx.clearDepth(x0);
- var _emscripten_glClearStencil = x0 => GLctx.clearStencil(x0);
- var _emscripten_glClipControlEXT = (origin, depth) => {
- GLctx.extClipControl["clipControlEXT"](origin, depth);
- };
- var _emscripten_glColorMask = (red, green, blue, alpha) => {
- GLctx.colorMask(!!red, !!green, !!blue, !!alpha);
- };
- var _emscripten_glCompileShader = shader => {
- GLctx.compileShader(GL.shaders[shader]);
- };
- var _emscripten_glCompressedTexImage2D = (target, level, internalFormat, width, height, border, imageSize, data) => {
- // `data` may be null here, which means "allocate uninitialized space but
- // don't upload" in GLES parlance, but `compressedTexImage2D` requires the
- // final data parameter, so we simply pass a heap view starting at zero
- // effectively uploading whatever happens to be near address zero. See
- // https://github.com/emscripten-core/emscripten/issues/19300.
- GLctx.compressedTexImage2D(target, level, internalFormat, width, height, border, (growMemViews(),
- HEAPU8).subarray(data, data + imageSize));
- };
- var _emscripten_glCompressedTexSubImage2D = (target, level, xoffset, yoffset, width, height, format, imageSize, data) => {
- GLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, (growMemViews(),
- HEAPU8).subarray(data, data + imageSize));
- };
- var _emscripten_glCopyTexImage2D = (x0, x1, x2, x3, x4, x5, x6, x7) => GLctx.copyTexImage2D(x0, x1, x2, x3, x4, x5, x6, x7);
- var _emscripten_glCopyTexSubImage2D = (x0, x1, x2, x3, x4, x5, x6, x7) => GLctx.copyTexSubImage2D(x0, x1, x2, x3, x4, x5, x6, x7);
- var _emscripten_glCreateProgram = () => {
- var id = GL.getNewId(GL.programs);
- var program = GLctx.createProgram();
- // Store additional information needed for each shader program:
- program.name = id;
- // Lazy cache results of
- // glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
- program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
- program.uniformIdCounter = 1;
- GL.programs[id] = program;
- return id;
- };
- var _emscripten_glCreateShader = shaderType => {
- var id = GL.getNewId(GL.shaders);
- GL.shaders[id] = GLctx.createShader(shaderType);
- return id;
- };
- var _emscripten_glCullFace = x0 => GLctx.cullFace(x0);
- var _emscripten_glDeleteBuffers = (n, buffers) => {
- for (var i = 0; i < n; i++) {
- var id = (growMemViews(), HEAP32)[(((buffers) + (i * 4)) >> 2)];
- var buffer = GL.buffers[id];
- // From spec: "glDeleteBuffers silently ignores 0's and names that do not
- // correspond to existing buffer objects."
- if (!buffer) continue;
- GLctx.deleteBuffer(buffer);
- buffer.name = 0;
- GL.buffers[id] = null;
- }
- };
- var _emscripten_glDeleteFramebuffers = (n, framebuffers) => {
- for (var i = 0; i < n; ++i) {
- var id = (growMemViews(), HEAP32)[(((framebuffers) + (i * 4)) >> 2)];
- var framebuffer = GL.framebuffers[id];
- if (!framebuffer) continue;
- // GL spec: "glDeleteFramebuffers silently ignores 0s and names that do not correspond to existing framebuffer objects".
- GLctx.deleteFramebuffer(framebuffer);
- framebuffer.name = 0;
- GL.framebuffers[id] = null;
- }
- };
- var _emscripten_glDeleteProgram = id => {
- if (!id) return;
- var program = GL.programs[id];
- if (!program) {
- // glDeleteProgram actually signals an error when deleting a nonexisting
- // object, unlike some other GL delete functions.
- GL.recordError(1281);
- return;
- }
- GLctx.deleteProgram(program);
- program.name = 0;
- GL.programs[id] = null;
- };
- var _emscripten_glDeleteQueriesEXT = (n, ids) => {
- for (var i = 0; i < n; i++) {
- var id = (growMemViews(), HEAP32)[(((ids) + (i * 4)) >> 2)];
- var query = GL.queries[id];
- if (!query) continue;
- // GL spec: "unused names in ids are ignored, as is the name zero."
- GLctx.disjointTimerQueryExt["deleteQueryEXT"](query);
- GL.queries[id] = null;
- }
- };
- var _emscripten_glDeleteRenderbuffers = (n, renderbuffers) => {
- for (var i = 0; i < n; i++) {
- var id = (growMemViews(), HEAP32)[(((renderbuffers) + (i * 4)) >> 2)];
- var renderbuffer = GL.renderbuffers[id];
- if (!renderbuffer) continue;
- // GL spec: "glDeleteRenderbuffers silently ignores 0s and names that do not correspond to existing renderbuffer objects".
- GLctx.deleteRenderbuffer(renderbuffer);
- renderbuffer.name = 0;
- GL.renderbuffers[id] = null;
- }
- };
- var _emscripten_glDeleteShader = id => {
- if (!id) return;
- var shader = GL.shaders[id];
- if (!shader) {
- // glDeleteShader actually signals an error when deleting a nonexisting
- // object, unlike some other GL delete functions.
- GL.recordError(1281);
- return;
- }
- GLctx.deleteShader(shader);
- GL.shaders[id] = null;
- };
- var _emscripten_glDeleteTextures = (n, textures) => {
- for (var i = 0; i < n; i++) {
- var id = (growMemViews(), HEAP32)[(((textures) + (i * 4)) >> 2)];
- var texture = GL.textures[id];
- // GL spec: "glDeleteTextures silently ignores 0s and names that do not
- // correspond to existing textures".
- if (!texture) continue;
- GLctx.deleteTexture(texture);
- texture.name = 0;
- GL.textures[id] = null;
- }
- };
- var _emscripten_glDeleteVertexArrays = (n, vaos) => {
- for (var i = 0; i < n; i++) {
- var id = (growMemViews(), HEAP32)[(((vaos) + (i * 4)) >> 2)];
- GLctx.deleteVertexArray(GL.vaos[id]);
- GL.vaos[id] = null;
- }
- };
- var _glDeleteVertexArrays = _emscripten_glDeleteVertexArrays;
- var _emscripten_glDeleteVertexArraysOES = _glDeleteVertexArrays;
- var _emscripten_glDepthFunc = x0 => GLctx.depthFunc(x0);
- var _emscripten_glDepthMask = flag => {
- GLctx.depthMask(!!flag);
- };
- var _emscripten_glDepthRangef = (x0, x1) => GLctx.depthRange(x0, x1);
- var _emscripten_glDetachShader = (program, shader) => {
- GLctx.detachShader(GL.programs[program], GL.shaders[shader]);
- };
- var _emscripten_glDisable = x0 => GLctx.disable(x0);
- var _emscripten_glDisableVertexAttribArray = index => {
- GLctx.disableVertexAttribArray(index);
- };
- var _emscripten_glDrawArrays = (mode, first, count) => {
- GLctx.drawArrays(mode, first, count);
- };
- var _emscripten_glDrawArraysInstanced = (mode, first, count, primcount) => {
- GLctx.drawArraysInstanced(mode, first, count, primcount);
- };
- var _glDrawArraysInstanced = _emscripten_glDrawArraysInstanced;
- var _emscripten_glDrawArraysInstancedANGLE = _glDrawArraysInstanced;
- var tempFixedLengthArray = [];
- var _emscripten_glDrawBuffers = (n, bufs) => {
- var bufArray = tempFixedLengthArray[n];
- for (var i = 0; i < n; i++) {
- bufArray[i] = (growMemViews(), HEAP32)[(((bufs) + (i * 4)) >> 2)];
- }
- GLctx.drawBuffers(bufArray);
- };
- var _glDrawBuffers = _emscripten_glDrawBuffers;
- var _emscripten_glDrawBuffersWEBGL = _glDrawBuffers;
- var _emscripten_glDrawElements = (mode, count, type, indices) => {
- GLctx.drawElements(mode, count, type, indices);
- };
- var _emscripten_glDrawElementsInstanced = (mode, count, type, indices, primcount) => {
- GLctx.drawElementsInstanced(mode, count, type, indices, primcount);
- };
- var _glDrawElementsInstanced = _emscripten_glDrawElementsInstanced;
- var _emscripten_glDrawElementsInstancedANGLE = _glDrawElementsInstanced;
- var _emscripten_glEnable = x0 => GLctx.enable(x0);
- var _emscripten_glEnableVertexAttribArray = index => {
- GLctx.enableVertexAttribArray(index);
- };
- var _emscripten_glEndQueryEXT = target => {
- GLctx.disjointTimerQueryExt["endQueryEXT"](target);
- };
- var _emscripten_glFinish = () => GLctx.finish();
- var _emscripten_glFlush = () => GLctx.flush();
- var _emscripten_glFramebufferRenderbuffer = (target, attachment, renderbuffertarget, renderbuffer) => {
- GLctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, GL.renderbuffers[renderbuffer]);
- };
- var _emscripten_glFramebufferTexture2D = (target, attachment, textarget, texture, level) => {
- GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level);
- };
- var _emscripten_glFrontFace = x0 => GLctx.frontFace(x0);
- var _emscripten_glGenBuffers = (n, buffers) => {
- GL.genObject(n, buffers, "createBuffer", GL.buffers);
- };
- var _emscripten_glGenFramebuffers = (n, ids) => {
- GL.genObject(n, ids, "createFramebuffer", GL.framebuffers);
- };
- var _emscripten_glGenQueriesEXT = (n, ids) => {
- for (var i = 0; i < n; i++) {
- var query = GLctx.disjointTimerQueryExt["createQueryEXT"]();
- if (!query) {
- GL.recordError(1282);
- while (i < n) (growMemViews(), HEAP32)[(((ids) + (i++ * 4)) >> 2)] = 0;
- return;
- }
- var id = GL.getNewId(GL.queries);
- query.name = id;
- GL.queries[id] = query;
- (growMemViews(), HEAP32)[(((ids) + (i * 4)) >> 2)] = id;
- }
- };
- var _emscripten_glGenRenderbuffers = (n, renderbuffers) => {
- GL.genObject(n, renderbuffers, "createRenderbuffer", GL.renderbuffers);
- };
- var _emscripten_glGenTextures = (n, textures) => {
- GL.genObject(n, textures, "createTexture", GL.textures);
- };
- var _emscripten_glGenVertexArrays = (n, arrays) => {
- GL.genObject(n, arrays, "createVertexArray", GL.vaos);
- };
- var _glGenVertexArrays = _emscripten_glGenVertexArrays;
- var _emscripten_glGenVertexArraysOES = _glGenVertexArrays;
- var _emscripten_glGenerateMipmap = x0 => GLctx.generateMipmap(x0);
- var __glGetActiveAttribOrUniform = (funcName, program, index, bufSize, length, size, type, name) => {
- program = GL.programs[program];
- var info = GLctx[funcName](program, index);
- if (info) {
- // If an error occurs, nothing will be written to length, size and type and name.
- var numBytesWrittenExclNull = name && stringToUTF8(info.name, name, bufSize);
- if (length) (growMemViews(), HEAP32)[((length) >> 2)] = numBytesWrittenExclNull;
- if (size) (growMemViews(), HEAP32)[((size) >> 2)] = info.size;
- if (type) (growMemViews(), HEAP32)[((type) >> 2)] = info.type;
- }
- };
- var _emscripten_glGetActiveAttrib = (program, index, bufSize, length, size, type, name) => __glGetActiveAttribOrUniform("getActiveAttrib", program, index, bufSize, length, size, type, name);
- var _emscripten_glGetActiveUniform = (program, index, bufSize, length, size, type, name) => __glGetActiveAttribOrUniform("getActiveUniform", program, index, bufSize, length, size, type, name);
- var _emscripten_glGetAttachedShaders = (program, maxCount, count, shaders) => {
- var result = GLctx.getAttachedShaders(GL.programs[program]);
- var len = result.length;
- if (len > maxCount) {
- len = maxCount;
- }
- (growMemViews(), HEAP32)[((count) >> 2)] = len;
- for (var i = 0; i < len; ++i) {
- var id = GL.shaders.indexOf(result[i]);
- (growMemViews(), HEAP32)[(((shaders) + (i * 4)) >> 2)] = id;
- }
- };
- var _emscripten_glGetAttribLocation = (program, name) => GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
- var readI53FromI64 = ptr => (growMemViews(), HEAPU32)[((ptr) >> 2)] + (growMemViews(),
- HEAP32)[(((ptr) + (4)) >> 2)] * 4294967296;
- var readI53FromU64 = ptr => (growMemViews(), HEAPU32)[((ptr) >> 2)] + (growMemViews(),
- HEAPU32)[(((ptr) + (4)) >> 2)] * 4294967296;
- var writeI53ToI64 = (ptr, num) => {
- (growMemViews(), HEAPU32)[((ptr) >> 2)] = num;
- var lower = (growMemViews(), HEAPU32)[((ptr) >> 2)];
- (growMemViews(), HEAPU32)[(((ptr) + (4)) >> 2)] = (num - lower) / 4294967296;
- var deserialized = (num >= 0) ? readI53FromU64(ptr) : readI53FromI64(ptr);
- var offset = ((ptr) >> 2);
- if (deserialized != num) warnOnce(`writeI53ToI64() out of range: serialized JS Number ${num} to Wasm heap as bytes lo=${ptrToString((growMemViews(),
- HEAPU32)[offset])}, hi=${ptrToString((growMemViews(), HEAPU32)[offset + 1])}, which deserializes back to ${deserialized} instead!`);
- };
- var emscriptenWebGLGet = (name_, p, type) => {
- // Guard against user passing a null pointer.
- // Note that GLES2 spec does not say anything about how passing a null
- // pointer should be treated. Testing on desktop core GL 3, the application
- // crashes on glGetIntegerv to a null pointer, but better to report an error
- // instead of doing anything random.
- if (!p) {
- GL.recordError(1281);
- return;
- }
- var ret = undefined;
- switch (name_) {
- // Handle a few trivial GLES values
- case 36346:
- // GL_SHADER_COMPILER
- ret = 1;
- break;
- case 36344:
- // GL_SHADER_BINARY_FORMATS
- if (type != 0 && type != 1) {
- GL.recordError(1280);
- }
- // Do not write anything to the out pointer, since no binary formats are
- // supported.
- return;
- case 36345:
- // GL_NUM_SHADER_BINARY_FORMATS
- ret = 0;
- break;
- case 34466:
- // GL_NUM_COMPRESSED_TEXTURE_FORMATS
- // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete
- // since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be
- // queried for length), so implement it ourselves to allow C++ GLES2
- // code to get the length.
- var formats = GLctx.getParameter(34467);
- ret = formats ? formats.length : 0;
- break;
- }
- if (ret === undefined) {
- var result = GLctx.getParameter(name_);
- switch (typeof result) {
- case "number":
- ret = result;
- break;
- case "boolean":
- ret = result ? 1 : 0;
- break;
- case "string":
- GL.recordError(1280);
- // GL_INVALID_ENUM
- return;
- case "object":
- if (result === null) {
- // null is a valid result for some (e.g., which buffer is bound -
- // perhaps nothing is bound), but otherwise can mean an invalid
- // name_, which we need to report as an error
- switch (name_) {
- case 34964:
- // ARRAY_BUFFER_BINDING
- case 35725:
- // CURRENT_PROGRAM
- case 34965:
- // ELEMENT_ARRAY_BUFFER_BINDING
- case 36006:
- // FRAMEBUFFER_BINDING or DRAW_FRAMEBUFFER_BINDING
- case 36007:
- // RENDERBUFFER_BINDING
- case 32873:
- // TEXTURE_BINDING_2D
- case 34229:
- // WebGL 2 GL_VERTEX_ARRAY_BINDING, or WebGL 1 extension OES_vertex_array_object GL_VERTEX_ARRAY_BINDING_OES
- case 34068:
- {
- // TEXTURE_BINDING_CUBE_MAP
- ret = 0;
- break;
- }
- default:
- {
- GL.recordError(1280);
- // GL_INVALID_ENUM
- return;
- }
- }
- } else if (result instanceof Float32Array || result instanceof Uint32Array || result instanceof Int32Array || result instanceof Array) {
- for (var i = 0; i < result.length; ++i) {
- switch (type) {
- case 0:
- (growMemViews(), HEAP32)[(((p) + (i * 4)) >> 2)] = result[i];
- break;
- case 2:
- (growMemViews(), HEAPF32)[(((p) + (i * 4)) >> 2)] = result[i];
- break;
- case 4:
- (growMemViews(), HEAP8)[(p) + (i)] = result[i] ? 1 : 0;
- break;
- }
- }
- return;
- } else {
- try {
- ret = result.name | 0;
- } catch (e) {
- GL.recordError(1280);
- // GL_INVALID_ENUM
- err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);
- return;
- }
- }
- break;
- default:
- GL.recordError(1280);
- // GL_INVALID_ENUM
- err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof (result)}!`);
- return;
- }
- }
- switch (type) {
- case 1:
- writeI53ToI64(p, ret);
- break;
- case 0:
- (growMemViews(), HEAP32)[((p) >> 2)] = ret;
- break;
- case 2:
- (growMemViews(), HEAPF32)[((p) >> 2)] = ret;
- break;
- case 4:
- (growMemViews(), HEAP8)[p] = ret ? 1 : 0;
- break;
- }
- };
- var _emscripten_glGetBooleanv = (name_, p) => emscriptenWebGLGet(name_, p, 4);
- var _emscripten_glGetBufferParameteriv = (target, value, data) => {
- if (!data) {
- // GLES2 specification does not specify how to behave if data is a null
- // pointer. Since calling this function does not make sense if data ==
- // null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- (growMemViews(), HEAP32)[((data) >> 2)] = GLctx.getBufferParameter(target, value);
- };
- var _emscripten_glGetError = () => {
- var error = GLctx.getError() || GL.lastError;
- GL.lastError = 0;
- return error;
- };
- var _emscripten_glGetFloatv = (name_, p) => emscriptenWebGLGet(name_, p, 2);
- var _emscripten_glGetFramebufferAttachmentParameteriv = (target, attachment, pname, params) => {
- var result = GLctx.getFramebufferAttachmentParameter(target, attachment, pname);
- if (result instanceof WebGLRenderbuffer || result instanceof WebGLTexture) {
- result = result.name | 0;
- }
- (growMemViews(), HEAP32)[((params) >> 2)] = result;
- };
- var _emscripten_glGetIntegerv = (name_, p) => emscriptenWebGLGet(name_, p, 0);
- var _emscripten_glGetProgramInfoLog = (program, maxLength, length, infoLog) => {
- var log = GLctx.getProgramInfoLog(GL.programs[program]);
- if (log === null) log = "(unknown error)";
- var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0;
- if (length) (growMemViews(), HEAP32)[((length) >> 2)] = numBytesWrittenExclNull;
- };
- var _emscripten_glGetProgramiv = (program, pname, p) => {
- if (!p) {
- // GLES2 specification does not specify how to behave if p is a null
- // pointer. Since calling this function does not make sense if p == null,
- // issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- if (program >= GL.counter) {
- GL.recordError(1281);
- return;
- }
- program = GL.programs[program];
- if (pname == 35716) {
- // GL_INFO_LOG_LENGTH
- var log = GLctx.getProgramInfoLog(program);
- if (log === null) log = "(unknown error)";
- (growMemViews(), HEAP32)[((p) >> 2)] = log.length + 1;
- } else if (pname == 35719) {
- if (!program.maxUniformLength) {
- var numActiveUniforms = GLctx.getProgramParameter(program, 35718);
- for (var i = 0; i < numActiveUniforms; ++i) {
- program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length + 1);
- }
- }
- (growMemViews(), HEAP32)[((p) >> 2)] = program.maxUniformLength;
- } else if (pname == 35722) {
- if (!program.maxAttributeLength) {
- var numActiveAttributes = GLctx.getProgramParameter(program, 35721);
- for (var i = 0; i < numActiveAttributes; ++i) {
- program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length + 1);
- }
- }
- (growMemViews(), HEAP32)[((p) >> 2)] = program.maxAttributeLength;
- } else if (pname == 35381) {
- if (!program.maxUniformBlockNameLength) {
- var numActiveUniformBlocks = GLctx.getProgramParameter(program, 35382);
- for (var i = 0; i < numActiveUniformBlocks; ++i) {
- program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length + 1);
- }
- }
- (growMemViews(), HEAP32)[((p) >> 2)] = program.maxUniformBlockNameLength;
- } else {
- (growMemViews(), HEAP32)[((p) >> 2)] = GLctx.getProgramParameter(program, pname);
- }
- };
- var _emscripten_glGetQueryObjecti64vEXT = (id, pname, params) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
- // if p == null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- var query = GL.queries[id];
- var param;
- {
- param = GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query, pname);
- }
- var ret;
- if (typeof param == "boolean") {
- ret = param ? 1 : 0;
- } else {
- ret = param;
- }
- writeI53ToI64(params, ret);
- };
- var _emscripten_glGetQueryObjectivEXT = (id, pname, params) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
- // if p == null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- var query = GL.queries[id];
- var param = GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query, pname);
- var ret;
- if (typeof param == "boolean") {
- ret = param ? 1 : 0;
- } else {
- ret = param;
- }
- (growMemViews(), HEAP32)[((params) >> 2)] = ret;
- };
- var _glGetQueryObjecti64vEXT = _emscripten_glGetQueryObjecti64vEXT;
- var _emscripten_glGetQueryObjectui64vEXT = _glGetQueryObjecti64vEXT;
- var _glGetQueryObjectivEXT = _emscripten_glGetQueryObjectivEXT;
- var _emscripten_glGetQueryObjectuivEXT = _glGetQueryObjectivEXT;
- var _emscripten_glGetQueryivEXT = (target, pname, params) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
- // if p == null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- (growMemViews(), HEAP32)[((params) >> 2)] = GLctx.disjointTimerQueryExt["getQueryEXT"](target, pname);
- };
- var _emscripten_glGetRenderbufferParameteriv = (target, pname, params) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
- // if params == null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- (growMemViews(), HEAP32)[((params) >> 2)] = GLctx.getRenderbufferParameter(target, pname);
- };
- var _emscripten_glGetShaderInfoLog = (shader, maxLength, length, infoLog) => {
- var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
- if (log === null) log = "(unknown error)";
- var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0;
- if (length) (growMemViews(), HEAP32)[((length) >> 2)] = numBytesWrittenExclNull;
- };
- var _emscripten_glGetShaderPrecisionFormat = (shaderType, precisionType, range, precision) => {
- var result = GLctx.getShaderPrecisionFormat(shaderType, precisionType);
- (growMemViews(), HEAP32)[((range) >> 2)] = result.rangeMin;
- (growMemViews(), HEAP32)[(((range) + (4)) >> 2)] = result.rangeMax;
- (growMemViews(), HEAP32)[((precision) >> 2)] = result.precision;
- };
- var _emscripten_glGetShaderSource = (shader, bufSize, length, source) => {
- var result = GLctx.getShaderSource(GL.shaders[shader]);
- if (!result) return;
- // If an error occurs, nothing will be written to length or source.
- var numBytesWrittenExclNull = (bufSize > 0 && source) ? stringToUTF8(result, source, bufSize) : 0;
- if (length) (growMemViews(), HEAP32)[((length) >> 2)] = numBytesWrittenExclNull;
- };
- var _emscripten_glGetShaderiv = (shader, pname, p) => {
- if (!p) {
- // GLES2 specification does not specify how to behave if p is a null
- // pointer. Since calling this function does not make sense if p == null,
- // issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- if (pname == 35716) {
- // GL_INFO_LOG_LENGTH
- var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
- if (log === null) log = "(unknown error)";
- // The GLES2 specification says that if the shader has an empty info log,
- // a value of 0 is returned. Otherwise the log has a null char appended.
- // (An empty string is falsey, so we can just check that instead of
- // looking at log.length.)
- var logLength = log ? log.length + 1 : 0;
- (growMemViews(), HEAP32)[((p) >> 2)] = logLength;
- } else if (pname == 35720) {
- // GL_SHADER_SOURCE_LENGTH
- var source = GLctx.getShaderSource(GL.shaders[shader]);
- // source may be a null, or the empty string, both of which are falsey
- // values that we report a 0 length for.
- var sourceLength = source ? source.length + 1 : 0;
- (growMemViews(), HEAP32)[((p) >> 2)] = sourceLength;
- } else {
- (growMemViews(), HEAP32)[((p) >> 2)] = GLctx.getShaderParameter(GL.shaders[shader], pname);
- }
- };
- var webglGetExtensions = () => {
- var exts = getEmscriptenSupportedExtensions(GLctx);
- exts = exts.concat(exts.map(e => "GL_" + e));
- return exts;
- };
- var _emscripten_glGetString = name_ => {
- var ret = GL.stringCache[name_];
- if (!ret) {
- switch (name_) {
- case 7939:
- ret = stringToNewUTF8(webglGetExtensions().join(" "));
- break;
- case 7936:
- case 7937:
- case 37445:
- case 37446:
- var s = GLctx.getParameter(name_);
- if (!s) {
- GL.recordError(1280);
- }
- ret = s ? stringToNewUTF8(s) : 0;
- break;
- case 7938:
- var webGLVersion = GLctx.getParameter(7938);
- // return GLES version string corresponding to the version of the WebGL context
- var glVersion = `OpenGL ES 2.0 (${webGLVersion})`;
- ret = stringToNewUTF8(glVersion);
- break;
- case 35724:
- var glslVersion = GLctx.getParameter(35724);
- // extract the version number 'N.M' from the string 'WebGL GLSL ES N.M ...'
- var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
- var ver_num = glslVersion.match(ver_re);
- if (ver_num !== null) {
- if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + "0";
- // ensure minor version has 2 digits
- glslVersion = `OpenGL ES GLSL ES ${ver_num[1]} (${glslVersion})`;
- }
- ret = stringToNewUTF8(glslVersion);
- break;
- default:
- GL.recordError(1280);
- }
- GL.stringCache[name_] = ret;
- }
- return ret;
- };
- var _emscripten_glGetTexParameterfv = (target, pname, params) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null
- // pointer. Since calling this function does not make sense if p == null,
- // issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- (growMemViews(), HEAPF32)[((params) >> 2)] = GLctx.getTexParameter(target, pname);
- };
- var _emscripten_glGetTexParameteriv = (target, pname, params) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null
- // pointer. Since calling this function does not make sense if p == null,
- // issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- (growMemViews(), HEAP32)[((params) >> 2)] = GLctx.getTexParameter(target, pname);
- };
- /** @suppress {checkTypes} */ var jstoi_q = str => parseInt(str);
- /** @noinline */ var webglGetLeftBracePos = name => name.slice(-1) == "]" && name.lastIndexOf("[");
- var webglPrepareUniformLocationsBeforeFirstUse = program => {
- var uniformLocsById = program.uniformLocsById, // Maps GLuint -> WebGLUniformLocation
- uniformSizeAndIdsByName = program.uniformSizeAndIdsByName, // Maps name -> [uniform array length, GLuint]
- i, j;
- // On the first time invocation of glGetUniformLocation on this shader program:
- // initialize cache data structures and discover which uniforms are arrays.
- if (!uniformLocsById) {
- // maps GLint integer locations to WebGLUniformLocations
- program.uniformLocsById = uniformLocsById = {};
- // maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
- program.uniformArrayNamesById = {};
- var numActiveUniforms = GLctx.getProgramParameter(program, 35718);
- for (i = 0; i < numActiveUniforms; ++i) {
- var u = GLctx.getActiveUniform(program, i);
- var nm = u.name;
- var sz = u.size;
- var lb = webglGetLeftBracePos(nm);
- var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
- // Assign a new location.
- var id = program.uniformIdCounter;
- program.uniformIdCounter += sz;
- // Eagerly get the location of the uniformArray[0] base element.
- // The remaining indices >0 will be left for lazy evaluation to
- // improve performance. Those may never be needed to fetch, if the
- // application fills arrays always in full starting from the first
- // element of the array.
- uniformSizeAndIdsByName[arrayName] = [ sz, id ];
- // Store placeholder integers in place that highlight that these
- // >0 index locations are array indices pending population.
- for (j = 0; j < sz; ++j) {
- uniformLocsById[id] = j;
- program.uniformArrayNamesById[id++] = arrayName;
- }
- }
- }
- };
- var _emscripten_glGetUniformLocation = (program, name) => {
- name = UTF8ToString(name);
- if (program = GL.programs[program]) {
- webglPrepareUniformLocationsBeforeFirstUse(program);
- var uniformLocsById = program.uniformLocsById;
- // Maps GLuint -> WebGLUniformLocation
- var arrayIndex = 0;
- var uniformBaseName = name;
- // Invariant: when populating integer IDs for uniform locations, we must
- // maintain the precondition that arrays reside in contiguous addresses,
- // i.e. for a 'vec4 colors[10];', colors[4] must be at location
- // colors[0]+4. However, user might call glGetUniformLocation(program,
- // "colors") for an array, so we cannot discover based on the user input
- // arguments whether the uniform we are dealing with is an array. The only
- // way to discover which uniforms are arrays is to enumerate over all the
- // active uniforms in the program.
- var leftBrace = webglGetLeftBracePos(name);
- // If user passed an array accessor "[index]", parse the array index off the accessor.
- if (leftBrace > 0) {
- arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0;
- // "index]", coerce parseInt(']') with >>>0 to treat "foo[]" as "foo[0]" and foo[-1] as unsigned out-of-bounds.
- uniformBaseName = name.slice(0, leftBrace);
- }
- // Have we cached the location of this uniform before?
- // A pair [array length, GLint of the uniform location]
- var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName];
- // If a uniform with this name exists, and if its index is within the
- // array limits (if it's even an array), query the WebGLlocation, or
- // return an existing cached location.
- if (sizeAndId && arrayIndex < sizeAndId[0]) {
- arrayIndex += sizeAndId[1];
- // Add the base location of the uniform to the array index offset.
- if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
- return arrayIndex;
- }
- }
- } else {
- // N.b. we are currently unable to distinguish between GL program IDs that
- // never existed vs GL program IDs that have been deleted, so report
- // GL_INVALID_VALUE in both cases.
- GL.recordError(1281);
- }
- return -1;
- };
- var webglGetProgramUniformLocation = (program, location) => {
- if (program) {
- var webglLoc = program.uniformLocsById[location];
- // program.uniformLocsById[location] stores either an integer, or a
- // WebGLUniformLocation.
- // If an integer, we have not yet bound the location, so do it now. The
- // integer value specifies the array index we should bind to.
- if (typeof webglLoc == "number") {
- program.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(program, program.uniformArrayNamesById[location] + (webglLoc > 0 ? `[${webglLoc}]` : ""));
- }
- // Else an already cached WebGLUniformLocation, return it.
- return webglLoc;
- } else {
- GL.recordError(1282);
- }
- };
- /** @suppress{checkTypes} */ var emscriptenWebGLGetUniform = (program, location, params, type) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null
- // pointer. Since calling this function does not make sense if params ==
- // null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- program = GL.programs[program];
- webglPrepareUniformLocationsBeforeFirstUse(program);
- var data = GLctx.getUniform(program, webglGetProgramUniformLocation(program, location));
- if (typeof data == "number" || typeof data == "boolean") {
- switch (type) {
- case 0:
- (growMemViews(), HEAP32)[((params) >> 2)] = data;
- break;
- case 2:
- (growMemViews(), HEAPF32)[((params) >> 2)] = data;
- break;
- }
- } else {
- for (var i = 0; i < data.length; i++) {
- switch (type) {
- case 0:
- (growMemViews(), HEAP32)[(((params) + (i * 4)) >> 2)] = data[i];
- break;
- case 2:
- (growMemViews(), HEAPF32)[(((params) + (i * 4)) >> 2)] = data[i];
- break;
- }
- }
- }
- };
- var _emscripten_glGetUniformfv = (program, location, params) => {
- emscriptenWebGLGetUniform(program, location, params, 2);
- };
- var _emscripten_glGetUniformiv = (program, location, params) => {
- emscriptenWebGLGetUniform(program, location, params, 0);
- };
- var _emscripten_glGetVertexAttribPointerv = (index, pname, pointer) => {
- if (!pointer) {
- // GLES2 specification does not specify how to behave if pointer is a null
- // pointer. Since calling this function does not make sense if pointer ==
- // null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- (growMemViews(), HEAP32)[((pointer) >> 2)] = GLctx.getVertexAttribOffset(index, pname);
- };
- /** @suppress{checkTypes} */ var emscriptenWebGLGetVertexAttrib = (index, pname, params, type) => {
- if (!params) {
- // GLES2 specification does not specify how to behave if params is a null
- // pointer. Since calling this function does not make sense if params ==
- // null, issue a GL error to notify user about it.
- GL.recordError(1281);
- return;
- }
- var data = GLctx.getVertexAttrib(index, pname);
- if (pname == 34975) {
- (growMemViews(), HEAP32)[((params) >> 2)] = data && data["name"];
- } else if (typeof data == "number" || typeof data == "boolean") {
- switch (type) {
- case 0:
- (growMemViews(), HEAP32)[((params) >> 2)] = data;
- break;
- case 2:
- (growMemViews(), HEAPF32)[((params) >> 2)] = data;
- break;
- case 5:
- (growMemViews(), HEAP32)[((params) >> 2)] = Math.fround(data);
- break;
- }
- } else {
- for (var i = 0; i < data.length; i++) {
- switch (type) {
- case 0:
- (growMemViews(), HEAP32)[(((params) + (i * 4)) >> 2)] = data[i];
- break;
- case 2:
- (growMemViews(), HEAPF32)[(((params) + (i * 4)) >> 2)] = data[i];
- break;
- case 5:
- (growMemViews(), HEAP32)[(((params) + (i * 4)) >> 2)] = Math.fround(data[i]);
- break;
- }
- }
- }
- };
- var _emscripten_glGetVertexAttribfv = (index, pname, params) => {
- // N.B. This function may only be called if the vertex attribute was
- // specified using the function glVertexAttrib*f(), otherwise the results
- // are undefined. (GLES3 spec 6.1.12)
- emscriptenWebGLGetVertexAttrib(index, pname, params, 2);
- };
- var _emscripten_glGetVertexAttribiv = (index, pname, params) => {
- // N.B. This function may only be called if the vertex attribute was
- // specified using the function glVertexAttrib*f(), otherwise the results
- // are undefined. (GLES3 spec 6.1.12)
- emscriptenWebGLGetVertexAttrib(index, pname, params, 5);
- };
- var _emscripten_glHint = (x0, x1) => GLctx.hint(x0, x1);
- var _emscripten_glIsBuffer = buffer => {
- var b = GL.buffers[buffer];
- if (!b) return 0;
- return GLctx.isBuffer(b);
- };
- var _emscripten_glIsEnabled = x0 => GLctx.isEnabled(x0);
- var _emscripten_glIsFramebuffer = framebuffer => {
- var fb = GL.framebuffers[framebuffer];
- if (!fb) return 0;
- return GLctx.isFramebuffer(fb);
- };
- var _emscripten_glIsProgram = program => {
- program = GL.programs[program];
- if (!program) return 0;
- return GLctx.isProgram(program);
- };
- var _emscripten_glIsQueryEXT = id => {
- var query = GL.queries[id];
- if (!query) return 0;
- return GLctx.disjointTimerQueryExt["isQueryEXT"](query);
- };
- var _emscripten_glIsRenderbuffer = renderbuffer => {
- var rb = GL.renderbuffers[renderbuffer];
- if (!rb) return 0;
- return GLctx.isRenderbuffer(rb);
- };
- var _emscripten_glIsShader = shader => {
- var s = GL.shaders[shader];
- if (!s) return 0;
- return GLctx.isShader(s);
- };
- var _emscripten_glIsTexture = id => {
- var texture = GL.textures[id];
- if (!texture) return 0;
- return GLctx.isTexture(texture);
- };
- var _emscripten_glIsVertexArray = array => {
- var vao = GL.vaos[array];
- if (!vao) return 0;
- return GLctx.isVertexArray(vao);
- };
- var _glIsVertexArray = _emscripten_glIsVertexArray;
- var _emscripten_glIsVertexArrayOES = _glIsVertexArray;
- var _emscripten_glLineWidth = x0 => GLctx.lineWidth(x0);
- var _emscripten_glLinkProgram = program => {
- program = GL.programs[program];
- GLctx.linkProgram(program);
- // Invalidate earlier computed uniform->ID mappings, those have now become stale
- program.uniformLocsById = 0;
- // Mark as null-like so that glGetUniformLocation() knows to populate this again.
- program.uniformSizeAndIdsByName = {};
- };
- var _emscripten_glPixelStorei = (pname, param) => {
- if (pname == 3317) {
- GL.unpackAlignment = param;
- } else if (pname == 3314) {
- GL.unpackRowLength = param;
- }
- GLctx.pixelStorei(pname, param);
- };
- var _emscripten_glPolygonModeWEBGL = (face, mode) => {
- GLctx.webglPolygonMode["polygonModeWEBGL"](face, mode);
- };
- var _emscripten_glPolygonOffset = (x0, x1) => GLctx.polygonOffset(x0, x1);
- var _emscripten_glPolygonOffsetClampEXT = (factor, units, clamp) => {
- GLctx.extPolygonOffsetClamp["polygonOffsetClampEXT"](factor, units, clamp);
- };
- var _emscripten_glQueryCounterEXT = (id, target) => {
- GLctx.disjointTimerQueryExt["queryCounterEXT"](GL.queries[id], target);
- };
- var computeUnpackAlignedImageSize = (width, height, sizePerPixel) => {
- function roundedToNextMultipleOf(x, y) {
- return (x + y - 1) & -y;
- }
- var plainRowSize = (GL.unpackRowLength || width) * sizePerPixel;
- var alignedRowSize = roundedToNextMultipleOf(plainRowSize, GL.unpackAlignment);
- return height * alignedRowSize;
- };
- var colorChannelsInGlTextureFormat = format => {
- // Micro-optimizations for size: map format to size by subtracting smallest
- // enum value (0x1902) from all values first. Also omit the most common
- // size value (1) from the list, which is assumed by formats not on the
- // list.
- var colorChannels = {
- // 0x1902 /* GL_DEPTH_COMPONENT */ - 0x1902: 1,
- // 0x1906 /* GL_ALPHA */ - 0x1902: 1,
- 5: 3,
- 6: 4,
- // 0x1909 /* GL_LUMINANCE */ - 0x1902: 1,
- 8: 2,
- 29502: 3,
- 29504: 4
- };
- return colorChannels[format - 6402] || 1;
- };
- var heapObjectForWebGLType = type => {
- // Micro-optimization for size: Subtract lowest GL enum number (0x1400/* GL_BYTE */) from type to compare
- // smaller values for the heap, for shorter generated code size.
- // Also the type HEAPU16 is not tested for explicitly, but any unrecognized type will return out HEAPU16.
- // (since most types are HEAPU16)
- type -= 5120;
- if (type == 1) return (growMemViews(), HEAPU8);
- if (type == 4) return (growMemViews(), HEAP32);
- if (type == 6) return (growMemViews(), HEAPF32);
- if (type == 5 || type == 28922) return (growMemViews(), HEAPU32);
- return (growMemViews(), HEAPU16);
- };
- var toTypedArrayIndex = (pointer, heap) => pointer >>> (31 - Math.clz32(heap.BYTES_PER_ELEMENT));
- var emscriptenWebGLGetTexPixelData = (type, format, width, height, pixels) => {
- var heap = heapObjectForWebGLType(type);
- var sizePerPixel = colorChannelsInGlTextureFormat(format) * heap.BYTES_PER_ELEMENT;
- var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel);
- return heap.subarray(toTypedArrayIndex(pixels, heap), toTypedArrayIndex(pixels + bytes, heap));
- };
- var _emscripten_glReadPixels = (x, y, width, height, format, type, pixels) => {
- var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels);
- if (!pixelData) {
- GL.recordError(1280);
- return;
- }
- GLctx.readPixels(x, y, width, height, format, type, pixelData);
- };
- var _emscripten_glReleaseShaderCompiler = () => {};
- var _emscripten_glRenderbufferStorage = (x0, x1, x2, x3) => GLctx.renderbufferStorage(x0, x1, x2, x3);
- var _emscripten_glSampleCoverage = (value, invert) => {
- GLctx.sampleCoverage(value, !!invert);
- };
- var _emscripten_glScissor = (x0, x1, x2, x3) => GLctx.scissor(x0, x1, x2, x3);
- var _emscripten_glShaderBinary = (count, shaders, binaryformat, binary, length) => {
- GL.recordError(1280);
- };
- var _emscripten_glShaderSource = (shader, count, string, length) => {
- var source = GL.getSource(shader, count, string, length);
- GLctx.shaderSource(GL.shaders[shader], source);
- };
- var _emscripten_glStencilFunc = (x0, x1, x2) => GLctx.stencilFunc(x0, x1, x2);
- var _emscripten_glStencilFuncSeparate = (x0, x1, x2, x3) => GLctx.stencilFuncSeparate(x0, x1, x2, x3);
- var _emscripten_glStencilMask = x0 => GLctx.stencilMask(x0);
- var _emscripten_glStencilMaskSeparate = (x0, x1) => GLctx.stencilMaskSeparate(x0, x1);
- var _emscripten_glStencilOp = (x0, x1, x2) => GLctx.stencilOp(x0, x1, x2);
- var _emscripten_glStencilOpSeparate = (x0, x1, x2, x3) => GLctx.stencilOpSeparate(x0, x1, x2, x3);
- var _emscripten_glTexImage2D = (target, level, internalFormat, width, height, border, format, type, pixels) => {
- var pixelData = pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels) : null;
- GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixelData);
- };
- var _emscripten_glTexParameterf = (x0, x1, x2) => GLctx.texParameterf(x0, x1, x2);
- var _emscripten_glTexParameterfv = (target, pname, params) => {
- var param = (growMemViews(), HEAPF32)[((params) >> 2)];
- GLctx.texParameterf(target, pname, param);
- };
- var _emscripten_glTexParameteri = (x0, x1, x2) => GLctx.texParameteri(x0, x1, x2);
- var _emscripten_glTexParameteriv = (target, pname, params) => {
- var param = (growMemViews(), HEAP32)[((params) >> 2)];
- GLctx.texParameteri(target, pname, param);
- };
- var _emscripten_glTexSubImage2D = (target, level, xoffset, yoffset, width, height, format, type, pixels) => {
- var pixelData = pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels) : null;
- GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixelData);
- };
- var webglGetUniformLocation = location => webglGetProgramUniformLocation(GLctx.currentProgram, location);
- var _emscripten_glUniform1f = (location, v0) => {
- GLctx.uniform1f(webglGetUniformLocation(location), v0);
- };
- var miniTempWebGLFloatBuffers = [];
- var _emscripten_glUniform1fv = (location, count, value) => {
- if (count <= 288) {
- // avoid allocation when uploading few enough uniforms
- var view = miniTempWebGLFloatBuffers[count];
- for (var i = 0; i < count; ++i) {
- view[i] = (growMemViews(), HEAPF32)[(((value) + (4 * i)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 4) >> 2));
- }
- GLctx.uniform1fv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform1i = (location, v0) => {
- GLctx.uniform1i(webglGetUniformLocation(location), v0);
- };
- var miniTempWebGLIntBuffers = [];
- var _emscripten_glUniform1iv = (location, count, value) => {
- if (count <= 288) {
- // avoid allocation when uploading few enough uniforms
- var view = miniTempWebGLIntBuffers[count];
- for (var i = 0; i < count; ++i) {
- view[i] = (growMemViews(), HEAP32)[(((value) + (4 * i)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAP32).subarray((((value) >> 2)), ((value + count * 4) >> 2));
- }
- GLctx.uniform1iv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform2f = (location, v0, v1) => {
- GLctx.uniform2f(webglGetUniformLocation(location), v0, v1);
- };
- var _emscripten_glUniform2fv = (location, count, value) => {
- if (count <= 144) {
- // avoid allocation when uploading few enough uniforms
- count *= 2;
- var view = miniTempWebGLFloatBuffers[count];
- for (var i = 0; i < count; i += 2) {
- view[i] = (growMemViews(), HEAPF32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 4)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 8) >> 2));
- }
- GLctx.uniform2fv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform2i = (location, v0, v1) => {
- GLctx.uniform2i(webglGetUniformLocation(location), v0, v1);
- };
- var _emscripten_glUniform2iv = (location, count, value) => {
- if (count <= 144) {
- // avoid allocation when uploading few enough uniforms
- count *= 2;
- var view = miniTempWebGLIntBuffers[count];
- for (var i = 0; i < count; i += 2) {
- view[i] = (growMemViews(), HEAP32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAP32)[(((value) + (4 * i + 4)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAP32).subarray((((value) >> 2)), ((value + count * 8) >> 2));
- }
- GLctx.uniform2iv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform3f = (location, v0, v1, v2) => {
- GLctx.uniform3f(webglGetUniformLocation(location), v0, v1, v2);
- };
- var _emscripten_glUniform3fv = (location, count, value) => {
- if (count <= 96) {
- // avoid allocation when uploading few enough uniforms
- count *= 3;
- var view = miniTempWebGLFloatBuffers[count];
- for (var i = 0; i < count; i += 3) {
- view[i] = (growMemViews(), HEAPF32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 4)) >> 2)];
- view[i + 2] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 8)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 12) >> 2));
- }
- GLctx.uniform3fv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform3i = (location, v0, v1, v2) => {
- GLctx.uniform3i(webglGetUniformLocation(location), v0, v1, v2);
- };
- var _emscripten_glUniform3iv = (location, count, value) => {
- if (count <= 96) {
- // avoid allocation when uploading few enough uniforms
- count *= 3;
- var view = miniTempWebGLIntBuffers[count];
- for (var i = 0; i < count; i += 3) {
- view[i] = (growMemViews(), HEAP32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAP32)[(((value) + (4 * i + 4)) >> 2)];
- view[i + 2] = (growMemViews(), HEAP32)[(((value) + (4 * i + 8)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAP32).subarray((((value) >> 2)), ((value + count * 12) >> 2));
- }
- GLctx.uniform3iv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform4f = (location, v0, v1, v2, v3) => {
- GLctx.uniform4f(webglGetUniformLocation(location), v0, v1, v2, v3);
- };
- var _emscripten_glUniform4fv = (location, count, value) => {
- if (count <= 72) {
- // avoid allocation when uploading few enough uniforms
- var view = miniTempWebGLFloatBuffers[4 * count];
- // hoist the heap out of the loop for size and for pthreads+growth.
- var heap = (growMemViews(), HEAPF32);
- value = ((value) >> 2);
- count *= 4;
- for (var i = 0; i < count; i += 4) {
- var dst = value + i;
- view[i] = heap[dst];
- view[i + 1] = heap[dst + 1];
- view[i + 2] = heap[dst + 2];
- view[i + 3] = heap[dst + 3];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 16) >> 2));
- }
- GLctx.uniform4fv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniform4i = (location, v0, v1, v2, v3) => {
- GLctx.uniform4i(webglGetUniformLocation(location), v0, v1, v2, v3);
- };
- var _emscripten_glUniform4iv = (location, count, value) => {
- if (count <= 72) {
- // avoid allocation when uploading few enough uniforms
- count *= 4;
- var view = miniTempWebGLIntBuffers[count];
- for (var i = 0; i < count; i += 4) {
- view[i] = (growMemViews(), HEAP32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAP32)[(((value) + (4 * i + 4)) >> 2)];
- view[i + 2] = (growMemViews(), HEAP32)[(((value) + (4 * i + 8)) >> 2)];
- view[i + 3] = (growMemViews(), HEAP32)[(((value) + (4 * i + 12)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAP32).subarray((((value) >> 2)), ((value + count * 16) >> 2));
- }
- GLctx.uniform4iv(webglGetUniformLocation(location), view);
- };
- var _emscripten_glUniformMatrix2fv = (location, count, transpose, value) => {
- if (count <= 72) {
- // avoid allocation when uploading few enough uniforms
- count *= 4;
- var view = miniTempWebGLFloatBuffers[count];
- for (var i = 0; i < count; i += 4) {
- view[i] = (growMemViews(), HEAPF32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 4)) >> 2)];
- view[i + 2] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 8)) >> 2)];
- view[i + 3] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 12)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 16) >> 2));
- }
- GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, view);
- };
- var _emscripten_glUniformMatrix3fv = (location, count, transpose, value) => {
- if (count <= 32) {
- // avoid allocation when uploading few enough uniforms
- count *= 9;
- var view = miniTempWebGLFloatBuffers[count];
- for (var i = 0; i < count; i += 9) {
- view[i] = (growMemViews(), HEAPF32)[(((value) + (4 * i)) >> 2)];
- view[i + 1] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 4)) >> 2)];
- view[i + 2] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 8)) >> 2)];
- view[i + 3] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 12)) >> 2)];
- view[i + 4] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 16)) >> 2)];
- view[i + 5] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 20)) >> 2)];
- view[i + 6] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 24)) >> 2)];
- view[i + 7] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 28)) >> 2)];
- view[i + 8] = (growMemViews(), HEAPF32)[(((value) + (4 * i + 32)) >> 2)];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 36) >> 2));
- }
- GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, view);
- };
- var _emscripten_glUniformMatrix4fv = (location, count, transpose, value) => {
- if (count <= 18) {
- // avoid allocation when uploading few enough uniforms
- var view = miniTempWebGLFloatBuffers[16 * count];
- // hoist the heap out of the loop for size and for pthreads+growth.
- var heap = (growMemViews(), HEAPF32);
- value = ((value) >> 2);
- count *= 16;
- for (var i = 0; i < count; i += 16) {
- var dst = value + i;
- view[i] = heap[dst];
- view[i + 1] = heap[dst + 1];
- view[i + 2] = heap[dst + 2];
- view[i + 3] = heap[dst + 3];
- view[i + 4] = heap[dst + 4];
- view[i + 5] = heap[dst + 5];
- view[i + 6] = heap[dst + 6];
- view[i + 7] = heap[dst + 7];
- view[i + 8] = heap[dst + 8];
- view[i + 9] = heap[dst + 9];
- view[i + 10] = heap[dst + 10];
- view[i + 11] = heap[dst + 11];
- view[i + 12] = heap[dst + 12];
- view[i + 13] = heap[dst + 13];
- view[i + 14] = heap[dst + 14];
- view[i + 15] = heap[dst + 15];
- }
- } else {
- var view = (growMemViews(), HEAPF32).subarray((((value) >> 2)), ((value + count * 64) >> 2));
- }
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view);
- };
- var _emscripten_glUseProgram = program => {
- program = GL.programs[program];
- GLctx.useProgram(program);
- // Record the currently active program so that we can access the uniform
- // mapping table of that program.
- GLctx.currentProgram = program;
- };
- var _emscripten_glValidateProgram = program => {
- GLctx.validateProgram(GL.programs[program]);
- };
- var _emscripten_glVertexAttrib1f = (x0, x1) => GLctx.vertexAttrib1f(x0, x1);
- var _emscripten_glVertexAttrib1fv = (index, v) => {
- GLctx.vertexAttrib1f(index, (growMemViews(), HEAPF32)[v >> 2]);
- };
- var _emscripten_glVertexAttrib2f = (x0, x1, x2) => GLctx.vertexAttrib2f(x0, x1, x2);
- var _emscripten_glVertexAttrib2fv = (index, v) => {
- GLctx.vertexAttrib2f(index, (growMemViews(), HEAPF32)[v >> 2], (growMemViews(),
- HEAPF32)[v + 4 >> 2]);
- };
- var _emscripten_glVertexAttrib3f = (x0, x1, x2, x3) => GLctx.vertexAttrib3f(x0, x1, x2, x3);
- var _emscripten_glVertexAttrib3fv = (index, v) => {
- GLctx.vertexAttrib3f(index, (growMemViews(), HEAPF32)[v >> 2], (growMemViews(),
- HEAPF32)[v + 4 >> 2], (growMemViews(), HEAPF32)[v + 8 >> 2]);
- };
- var _emscripten_glVertexAttrib4f = (x0, x1, x2, x3, x4) => GLctx.vertexAttrib4f(x0, x1, x2, x3, x4);
- var _emscripten_glVertexAttrib4fv = (index, v) => {
- GLctx.vertexAttrib4f(index, (growMemViews(), HEAPF32)[v >> 2], (growMemViews(),
- HEAPF32)[v + 4 >> 2], (growMemViews(), HEAPF32)[v + 8 >> 2], (growMemViews(), HEAPF32)[v + 12 >> 2]);
- };
- var _emscripten_glVertexAttribDivisor = (index, divisor) => {
- GLctx.vertexAttribDivisor(index, divisor);
- };
- var _glVertexAttribDivisor = _emscripten_glVertexAttribDivisor;
- var _emscripten_glVertexAttribDivisorANGLE = _glVertexAttribDivisor;
- var _emscripten_glVertexAttribPointer = (index, size, type, normalized, stride, ptr) => {
- GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
- };
- var _emscripten_glViewport = (x0, x1, x2, x3) => GLctx.viewport(x0, x1, x2, x3);
- var _emscripten_has_asyncify = () => 0;
- var doRequestFullscreen = (target, strategy) => {
- if (!JSEvents.fullscreenEnabled()) return -1;
- target = findEventTarget(target);
- if (!target) return -4;
- if (!target.requestFullscreen && !target.webkitRequestFullscreen) {
- return -3;
- }
- // Queue this function call if we're not currently in an event handler and
- // the user saw it appropriate to do so.
- if (!JSEvents.canPerformEventHandlerRequests()) {
- if (strategy.deferUntilInEventHandler) {
- JSEvents.deferCall(JSEvents_requestFullscreen, 1, [ target, strategy ]);
- return 1;
- }
- return -2;
- }
- return JSEvents_requestFullscreen(target, strategy);
- };
- function _emscripten_request_fullscreen_strategy(target, deferUntilInEventHandler, fullscreenStrategy) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(43, 0, 1, target, deferUntilInEventHandler, fullscreenStrategy);
- var strategy = {
- scaleMode: (growMemViews(), HEAP32)[((fullscreenStrategy) >> 2)],
- canvasResolutionScaleMode: (growMemViews(), HEAP32)[(((fullscreenStrategy) + (4)) >> 2)],
- filteringMode: (growMemViews(), HEAP32)[(((fullscreenStrategy) + (8)) >> 2)],
- deferUntilInEventHandler,
- canvasResizedCallbackTargetThread: (growMemViews(), HEAP32)[(((fullscreenStrategy) + (20)) >> 2)],
- canvasResizedCallback: (growMemViews(), HEAP32)[(((fullscreenStrategy) + (12)) >> 2)],
- canvasResizedCallbackUserData: (growMemViews(), HEAP32)[(((fullscreenStrategy) + (16)) >> 2)]
- };
- return doRequestFullscreen(target, strategy);
- }
- function _emscripten_request_pointerlock(target, deferUntilInEventHandler) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(44, 0, 1, target, deferUntilInEventHandler);
- target = findEventTarget(target);
- if (!target) return -4;
- if (!target.requestPointerLock) {
- return -1;
- }
- // Queue this function call if we're not currently in an event handler and
- // the user saw it appropriate to do so.
- if (!JSEvents.canPerformEventHandlerRequests()) {
- if (deferUntilInEventHandler) {
- JSEvents.deferCall(requestPointerLock, 2, [ target ]);
- return 1;
- }
- return -2;
- }
- return requestPointerLock(target);
- }
- var getHeapMax = () => // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
- // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
- // for any code that deals with heap sizes, which would require special
- // casing all heap size related code to treat 0 specially.
- 2147483648;
- var growMemory = size => {
- var oldHeapSize = wasmMemory.buffer.byteLength;
- var pages = ((size - oldHeapSize + 65535) / 65536) | 0;
- try {
- // round size grow request up to wasm page size (fixed 64KB per spec)
- wasmMemory.grow(pages);
- // .grow() takes a delta compared to the previous size
- updateMemoryViews();
- return 1;
- } catch (e) {
- err(`growMemory: Attempted to grow heap from ${oldHeapSize} bytes to ${size} bytes, but got error: ${e}`);
- }
- };
- var _emscripten_resize_heap = requestedSize => {
- var oldSize = (growMemViews(), HEAPU8).length;
- // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
- requestedSize >>>= 0;
- // With multithreaded builds, races can happen (another thread might increase the size
- // in between), so return a failure, and let the caller retry.
- if (requestedSize <= oldSize) {
- return false;
- }
- // Memory resize rules:
- // 1. Always increase heap size to at least the requested size, rounded up
- // to next page multiple.
- // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
- // geometrically: increase the heap size according to
- // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
- // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
- // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
- // linearly: increase the heap size by at least
- // MEMORY_GROWTH_LINEAR_STEP bytes.
- // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
- // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
- // 4. If we were unable to allocate as much memory, it may be due to
- // over-eager decision to excessively reserve due to (3) above.
- // Hence if an allocation fails, cut down on the amount of excess
- // growth, in an attempt to succeed to perform a smaller allocation.
- // A limit is set for how much we can grow. We should not exceed that
- // (the wasm binary specifies it, so if we tried, we'd fail anyhow).
- var maxHeapSize = getHeapMax();
- if (requestedSize > maxHeapSize) {
- err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
- return false;
- }
- // Loop through potential heap size increases. If we attempt a too eager
- // reservation that fails, cut down on the attempted size and reserve a
- // smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
- var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
- // ensure geometric growth
- // but limit overreserving (default to capping at +96MB overgrowth at most)
- overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
- var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536));
- var replacement = growMemory(newSize);
- if (replacement) {
- return true;
- }
- }
- err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);
- return false;
- };
- /** @suppress {checkTypes} */ function _emscripten_sample_gamepad_data() {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(45, 0, 1);
- try {
- if (navigator.getGamepads) return (JSEvents.lastGamepadState = navigator.getGamepads()) ? 0 : -1;
- } catch (e) {
- err(`navigator.getGamepads() exists, but failed to execute with exception ${e}. Disabling Gamepad access.`);
- navigator.getGamepads = null;
- }
- return -1;
- }
- var registerBeforeUnloadEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString) => {
- var beforeUnloadEventHandlerFunc = e => {
- // Note: This is always called on the main browser thread, since it needs synchronously return a value!
- var confirmationMessage = getWasmTableEntry(callbackfunc)(eventTypeId, 0, userData);
- if (confirmationMessage) {
- confirmationMessage = UTF8ToString(confirmationMessage);
- }
- if (confirmationMessage) {
- e.preventDefault();
- e.returnValue = confirmationMessage;
- return confirmationMessage;
- }
- };
- var eventHandler = {
- target: findEventTarget(target),
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: beforeUnloadEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_beforeunload_callback_on_thread(userData, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(46, 0, 1, userData, callbackfunc, targetThread);
- if (typeof onbeforeunload == "undefined") return -1;
- // beforeunload callback can only be registered on the main browser thread, because the page will go away immediately after returning from the handler,
- // and there is no time to start proxying it anywhere.
- if (targetThread !== 1) return -5;
- return registerBeforeUnloadEventCallback(2, userData, true, callbackfunc, 28, "beforeunload");
- }
- var registerFocusEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 256;
- JSEvents.focusEvent ||= _malloc(eventSize);
- var focusEventHandlerFunc = e => {
- var nodeName = JSEvents.getNodeNameForTarget(e.target);
- var id = e.target.id ?? "";
- var focusEvent = JSEvents.focusEvent;
- stringToUTF8(nodeName, focusEvent + 0, 128);
- stringToUTF8(id, focusEvent + 128, 128);
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, focusEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, focusEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target: findEventTarget(target),
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: focusEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_blur_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(47, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerFocusEventCallback(target, userData, useCapture, callbackfunc, 12, "blur", targetThread);
- }
- function _emscripten_set_element_css_size(target, width, height) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(48, 0, 1, target, width, height);
- target = findEventTarget(target);
- if (!target) return -4;
- target.style.width = width + "px";
- target.style.height = height + "px";
- return 0;
- }
- function _emscripten_set_focus_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(49, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerFocusEventCallback(target, userData, useCapture, callbackfunc, 13, "focus", targetThread);
- }
- var fillFullscreenChangeEventData = eventStruct => {
- var fullscreenElement = getFullscreenElement();
- var isFullscreen = !!fullscreenElement;
- // Assigning a boolean to HEAP32 with expected type coercion.
- /** @suppress{checkTypes} */ (growMemViews(), HEAP8)[eventStruct] = isFullscreen;
- (growMemViews(), HEAP8)[(eventStruct) + (1)] = JSEvents.fullscreenEnabled();
- // If transitioning to fullscreen, report info about the element that is now fullscreen.
- // If transitioning to windowed mode, report info about the element that just was fullscreen.
- var reportedElement = isFullscreen ? fullscreenElement : JSEvents.previousFullscreenElement;
- var nodeName = JSEvents.getNodeNameForTarget(reportedElement);
- var id = reportedElement?.id ?? "";
- stringToUTF8(nodeName, eventStruct + 2, 128);
- stringToUTF8(id, eventStruct + 130, 128);
- (growMemViews(), HEAP32)[(((eventStruct) + (260)) >> 2)] = reportedElement?.clientWidth ?? 0;
- (growMemViews(), HEAP32)[(((eventStruct) + (264)) >> 2)] = reportedElement?.clientHeight ?? 0;
- (growMemViews(), HEAP32)[(((eventStruct) + (268)) >> 2)] = screen.width;
- (growMemViews(), HEAP32)[(((eventStruct) + (272)) >> 2)] = screen.height;
- if (isFullscreen) {
- JSEvents.previousFullscreenElement = fullscreenElement;
- }
- };
- var registerFullscreenChangeEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 276;
- JSEvents.fullscreenChangeEvent ||= _malloc(eventSize);
- var fullscreenChangeEventHandlerFunc = e => {
- var fullscreenChangeEvent = JSEvents.fullscreenChangeEvent;
- fillFullscreenChangeEventData(fullscreenChangeEvent);
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, fullscreenChangeEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, fullscreenChangeEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: fullscreenChangeEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_fullscreenchange_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(50, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- if (!JSEvents.fullscreenEnabled()) return -1;
- target = findEventTarget(target);
- if (!target) return -4;
- // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version.
- // TODO: When this block is removed, also change test/test_html5_remove_event_listener.c test expectation on emscripten_set_fullscreenchange_callback().
- registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "webkitfullscreenchange", targetThread);
- return registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "fullscreenchange", targetThread);
- }
- var registerGamepadEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 1240;
- JSEvents.gamepadEvent ||= _malloc(eventSize);
- var gamepadEventHandlerFunc = e => {
- var gamepadEvent = JSEvents.gamepadEvent;
- fillGamepadEventData(gamepadEvent, e["gamepad"]);
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, gamepadEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, gamepadEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target: findEventTarget(target),
- allowsDeferredCalls: true,
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: gamepadEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_gamepadconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(51, 0, 1, userData, useCapture, callbackfunc, targetThread);
- if (_emscripten_sample_gamepad_data()) return -1;
- return registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 26, "gamepadconnected", targetThread);
- }
- function _emscripten_set_gamepaddisconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(52, 0, 1, userData, useCapture, callbackfunc, targetThread);
- if (_emscripten_sample_gamepad_data()) return -1;
- return registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 27, "gamepaddisconnected", targetThread);
- }
- var registerKeyEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 160;
- JSEvents.keyEvent ||= _malloc(eventSize);
- var keyEventHandlerFunc = e => {
- assert(e);
- var keyEventData = JSEvents.keyEvent;
- (growMemViews(), HEAPF64)[((keyEventData) >> 3)] = e.timeStamp;
- var idx = ((keyEventData) >> 2);
- (growMemViews(), HEAP32)[idx + 2] = e.location;
- (growMemViews(), HEAP8)[keyEventData + 12] = e.ctrlKey;
- (growMemViews(), HEAP8)[keyEventData + 13] = e.shiftKey;
- (growMemViews(), HEAP8)[keyEventData + 14] = e.altKey;
- (growMemViews(), HEAP8)[keyEventData + 15] = e.metaKey;
- (growMemViews(), HEAP8)[keyEventData + 16] = e.repeat;
- (growMemViews(), HEAP32)[idx + 5] = e.charCode;
- (growMemViews(), HEAP32)[idx + 6] = e.keyCode;
- (growMemViews(), HEAP32)[idx + 7] = e.which;
- stringToUTF8(e.key ?? "", keyEventData + 32, 32);
- stringToUTF8(e.code ?? "", keyEventData + 64, 32);
- stringToUTF8(e.char ?? "", keyEventData + 96, 32);
- stringToUTF8(e.locale ?? "", keyEventData + 128, 32);
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, keyEventData, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, keyEventData, userData)) e.preventDefault();
- };
- var eventHandler = {
- target: findEventTarget(target),
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: keyEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_keydown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(53, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerKeyEventCallback(target, userData, useCapture, callbackfunc, 2, "keydown", targetThread);
- }
- function _emscripten_set_keypress_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(54, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerKeyEventCallback(target, userData, useCapture, callbackfunc, 1, "keypress", targetThread);
- }
- function _emscripten_set_keyup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(55, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerKeyEventCallback(target, userData, useCapture, callbackfunc, 3, "keyup", targetThread);
- }
- var _emscripten_set_main_loop = (func, fps, simulateInfiniteLoop) => {
- var iterFunc = getWasmTableEntry(func);
- setMainLoop(iterFunc, fps, simulateInfiniteLoop);
- };
- var fillMouseEventData = (eventStruct, e, target) => {
- assert(eventStruct % 4 == 0);
- (growMemViews(), HEAPF64)[((eventStruct) >> 3)] = e.timeStamp;
- var idx = ((eventStruct) >> 2);
- (growMemViews(), HEAP32)[idx + 2] = e.screenX;
- (growMemViews(), HEAP32)[idx + 3] = e.screenY;
- (growMemViews(), HEAP32)[idx + 4] = e.clientX;
- (growMemViews(), HEAP32)[idx + 5] = e.clientY;
- (growMemViews(), HEAP8)[eventStruct + 24] = e.ctrlKey;
- (growMemViews(), HEAP8)[eventStruct + 25] = e.shiftKey;
- (growMemViews(), HEAP8)[eventStruct + 26] = e.altKey;
- (growMemViews(), HEAP8)[eventStruct + 27] = e.metaKey;
- (growMemViews(), HEAP16)[idx * 2 + 14] = e.button;
- (growMemViews(), HEAP16)[idx * 2 + 15] = e.buttons;
- (growMemViews(), HEAP32)[idx + 8] = e["movementX"];
- (growMemViews(), HEAP32)[idx + 9] = e["movementY"];
- // Note: rect contains doubles (truncated to placate SAFE_HEAP, which is the same behaviour when writing to HEAP32 anyway)
- var rect = getBoundingClientRect(target);
- (growMemViews(), HEAP32)[idx + 10] = e.clientX - (rect.left | 0);
- (growMemViews(), HEAP32)[idx + 11] = e.clientY - (rect.top | 0);
- };
- var registerMouseEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 64;
- JSEvents.mouseEvent ||= _malloc(eventSize);
- target = findEventTarget(target);
- var mouseEventHandlerFunc = e => {
- // TODO: Make this access thread safe, or this could update live while app is reading it.
- fillMouseEventData(JSEvents.mouseEvent, e, target);
- if (targetThread) {
- __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, JSEvents.mouseEvent, eventSize, userData);
- } else if (getWasmTableEntry(callbackfunc)(eventTypeId, JSEvents.mouseEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- allowsDeferredCalls: eventTypeString != "mousemove" && eventTypeString != "mouseenter" && eventTypeString != "mouseleave",
- // Mouse move events do not allow fullscreen/pointer lock requests to be handled in them!
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: mouseEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_mousedown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(56, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerMouseEventCallback(target, userData, useCapture, callbackfunc, 5, "mousedown", targetThread);
- }
- function _emscripten_set_mouseenter_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(57, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerMouseEventCallback(target, userData, useCapture, callbackfunc, 33, "mouseenter", targetThread);
- }
- function _emscripten_set_mouseleave_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(58, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerMouseEventCallback(target, userData, useCapture, callbackfunc, 34, "mouseleave", targetThread);
- }
- function _emscripten_set_mousemove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(59, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerMouseEventCallback(target, userData, useCapture, callbackfunc, 8, "mousemove", targetThread);
- }
- function _emscripten_set_mouseup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(60, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerMouseEventCallback(target, userData, useCapture, callbackfunc, 6, "mouseup", targetThread);
- }
- var fillPointerlockChangeEventData = eventStruct => {
- var pointerLockElement = document.pointerLockElement;
- var isPointerlocked = !!pointerLockElement;
- // Assigning a boolean to HEAP32 with expected type coercion.
- /** @suppress{checkTypes} */ (growMemViews(), HEAP8)[eventStruct] = isPointerlocked;
- var nodeName = JSEvents.getNodeNameForTarget(pointerLockElement);
- var id = pointerLockElement?.id ?? "";
- stringToUTF8(nodeName, eventStruct + 1, 128);
- stringToUTF8(id, eventStruct + 129, 128);
- };
- var registerPointerlockChangeEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 257;
- JSEvents.pointerlockChangeEvent ||= _malloc(eventSize);
- var pointerlockChangeEventHandlerFunc = e => {
- var pointerlockChangeEvent = JSEvents.pointerlockChangeEvent;
- fillPointerlockChangeEventData(pointerlockChangeEvent);
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, pointerlockChangeEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, pointerlockChangeEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: pointerlockChangeEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_pointerlockchange_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(61, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- if (!document.body?.requestPointerLock) {
- return -1;
- }
- target = findEventTarget(target);
- if (!target) return -4;
- return registerPointerlockChangeEventCallback(target, userData, useCapture, callbackfunc, 20, "pointerlockchange", targetThread);
- }
- var registerUiEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 36;
- JSEvents.uiEvent ||= _malloc(eventSize);
- target = findEventTarget(target);
- var uiEventHandlerFunc = e => {
- if (e.target != target) {
- // Never take ui events such as scroll via a 'bubbled' route, but always from the direct element that
- // was targeted. Otherwise e.g. if app logs a message in response to a page scroll, the Emscripten log
- // message box could cause to scroll, generating a new (bubbled) scroll message, causing a new log print,
- // causing a new scroll, etc..
- return;
- }
- var b = document.body;
- // Take document.body to a variable, Closure compiler does not outline access to it on its own.
- if (!b) {
- // During a page unload 'body' can be null, with "Cannot read property 'clientWidth' of null" being thrown
- return;
- }
- var uiEvent = JSEvents.uiEvent;
- (growMemViews(), HEAP32)[((uiEvent) >> 2)] = 0;
- // always zero for resize and scroll
- (growMemViews(), HEAP32)[(((uiEvent) + (4)) >> 2)] = b.clientWidth;
- (growMemViews(), HEAP32)[(((uiEvent) + (8)) >> 2)] = b.clientHeight;
- (growMemViews(), HEAP32)[(((uiEvent) + (12)) >> 2)] = innerWidth;
- (growMemViews(), HEAP32)[(((uiEvent) + (16)) >> 2)] = innerHeight;
- (growMemViews(), HEAP32)[(((uiEvent) + (20)) >> 2)] = outerWidth;
- (growMemViews(), HEAP32)[(((uiEvent) + (24)) >> 2)] = outerHeight;
- (growMemViews(), HEAP32)[(((uiEvent) + (28)) >> 2)] = pageXOffset | 0;
- // scroll offsets are float
- (growMemViews(), HEAP32)[(((uiEvent) + (32)) >> 2)] = pageYOffset | 0;
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, uiEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, uiEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: uiEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_resize_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(62, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerUiEventCallback(target, userData, useCapture, callbackfunc, 10, "resize", targetThread);
- }
- var registerTouchEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 1552;
- JSEvents.touchEvent ||= _malloc(eventSize);
- target = findEventTarget(target);
- var touchEventHandlerFunc = e => {
- assert(e);
- var t, touches = {}, et = e.touches;
- // To ease marshalling different kinds of touches that browser reports (all touches are listed in e.touches,
- // only changed touches in e.changedTouches, and touches on target at a.targetTouches), mark a boolean in
- // each Touch object so that we can later loop only once over all touches we see to marshall over to Wasm.
- for (let t of et) {
- // Browser might recycle the generated Touch objects between each frame (Firefox on Android), so reset any
- // changed/target states we may have set from previous frame.
- t.isChanged = t.onTarget = 0;
- touches[t.identifier] = t;
- }
- // Mark which touches are part of the changedTouches list.
- for (let t of e.changedTouches) {
- t.isChanged = 1;
- touches[t.identifier] = t;
- }
- // Mark which touches are part of the targetTouches list.
- for (let t of e.targetTouches) {
- touches[t.identifier].onTarget = 1;
- }
- var touchEvent = JSEvents.touchEvent;
- (growMemViews(), HEAPF64)[((touchEvent) >> 3)] = e.timeStamp;
- (growMemViews(), HEAP8)[touchEvent + 12] = e.ctrlKey;
- (growMemViews(), HEAP8)[touchEvent + 13] = e.shiftKey;
- (growMemViews(), HEAP8)[touchEvent + 14] = e.altKey;
- (growMemViews(), HEAP8)[touchEvent + 15] = e.metaKey;
- var idx = touchEvent + 16;
- var targetRect = getBoundingClientRect(target);
- var numTouches = 0;
- for (let t of Object.values(touches)) {
- var idx32 = ((idx) >> 2);
- // Pre-shift the ptr to index to HEAP32 to save code size
- (growMemViews(), HEAP32)[idx32 + 0] = t.identifier;
- (growMemViews(), HEAP32)[idx32 + 1] = t.screenX;
- (growMemViews(), HEAP32)[idx32 + 2] = t.screenY;
- (growMemViews(), HEAP32)[idx32 + 3] = t.clientX;
- (growMemViews(), HEAP32)[idx32 + 4] = t.clientY;
- (growMemViews(), HEAP32)[idx32 + 5] = t.pageX;
- (growMemViews(), HEAP32)[idx32 + 6] = t.pageY;
- (growMemViews(), HEAP8)[idx + 28] = t.isChanged;
- (growMemViews(), HEAP8)[idx + 29] = t.onTarget;
- (growMemViews(), HEAP32)[idx32 + 8] = t.clientX - (targetRect.left | 0);
- (growMemViews(), HEAP32)[idx32 + 9] = t.clientY - (targetRect.top | 0);
- idx += 48;
- if (++numTouches > 31) {
- break;
- }
- }
- (growMemViews(), HEAP32)[(((touchEvent) + (8)) >> 2)] = numTouches;
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, touchEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, touchEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- allowsDeferredCalls: eventTypeString == "touchstart" || eventTypeString == "touchend",
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: touchEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_touchcancel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(63, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerTouchEventCallback(target, userData, useCapture, callbackfunc, 25, "touchcancel", targetThread);
- }
- function _emscripten_set_touchend_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(64, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerTouchEventCallback(target, userData, useCapture, callbackfunc, 23, "touchend", targetThread);
- }
- function _emscripten_set_touchmove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(65, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerTouchEventCallback(target, userData, useCapture, callbackfunc, 24, "touchmove", targetThread);
- }
- function _emscripten_set_touchstart_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(66, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- return registerTouchEventCallback(target, userData, useCapture, callbackfunc, 22, "touchstart", targetThread);
- }
- var fillVisibilityChangeEventData = eventStruct => {
- var visibilityStates = [ "hidden", "visible", "prerender", "unloaded" ];
- var visibilityState = visibilityStates.indexOf(document.visibilityState);
- // Assigning a boolean to HEAP32 with expected type coercion.
- /** @suppress{checkTypes} */ (growMemViews(), HEAP8)[eventStruct] = document.hidden;
- (growMemViews(), HEAP32)[(((eventStruct) + (4)) >> 2)] = visibilityState;
- };
- var registerVisibilityChangeEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 8;
- JSEvents.visibilityChangeEvent ||= _malloc(eventSize);
- var visibilityChangeEventHandlerFunc = e => {
- var visibilityChangeEvent = JSEvents.visibilityChangeEvent;
- fillVisibilityChangeEventData(visibilityChangeEvent);
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, visibilityChangeEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, visibilityChangeEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: visibilityChangeEventHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_visibilitychange_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(67, 0, 1, userData, useCapture, callbackfunc, targetThread);
- if (!specialHTMLTargets[1]) {
- return -4;
- }
- return registerVisibilityChangeEventCallback(specialHTMLTargets[1], userData, useCapture, callbackfunc, 21, "visibilitychange", targetThread);
- }
- var registerWheelEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- targetThread = JSEvents.getTargetThreadForEventCallback(targetThread);
- var eventSize = 96;
- JSEvents.wheelEvent ||= _malloc(eventSize);
- // The DOM Level 3 events spec event 'wheel'
- var wheelHandlerFunc = e => {
- var wheelEvent = JSEvents.wheelEvent;
- fillMouseEventData(wheelEvent, e, target);
- (growMemViews(), HEAPF64)[(((wheelEvent) + (64)) >> 3)] = e["deltaX"];
- (growMemViews(), HEAPF64)[(((wheelEvent) + (72)) >> 3)] = e["deltaY"];
- (growMemViews(), HEAPF64)[(((wheelEvent) + (80)) >> 3)] = e["deltaZ"];
- (growMemViews(), HEAP32)[(((wheelEvent) + (88)) >> 2)] = e["deltaMode"];
- if (targetThread) __emscripten_run_callback_on_thread(targetThread, callbackfunc, eventTypeId, wheelEvent, eventSize, userData); else if (getWasmTableEntry(callbackfunc)(eventTypeId, wheelEvent, userData)) e.preventDefault();
- };
- var eventHandler = {
- target,
- allowsDeferredCalls: true,
- eventTypeString,
- eventTypeId,
- userData,
- callbackfunc,
- handlerFunc: wheelHandlerFunc,
- useCapture
- };
- return JSEvents.registerOrRemoveHandler(eventHandler);
- };
- function _emscripten_set_wheel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(68, 0, 1, target, userData, useCapture, callbackfunc, targetThread);
- target = findEventTarget(target);
- if (!target) return -4;
- if (typeof target.onwheel != "undefined") {
- return registerWheelEventCallback(target, userData, useCapture, callbackfunc, 9, "wheel", targetThread);
- } else {
- return -1;
- }
- }
- function _emscripten_set_window_title(title) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(69, 0, 1, title);
- return document.title = UTF8ToString(title);
- }
- var _emscripten_sleep = () => {
- abort("Please compile your program with async support in order to use asynchronous operations like emscripten_sleep");
- };
- var ENV = {};
- var getExecutableName = () => thisProgram;
- var getEnvStrings = () => {
- if (!getEnvStrings.strings) {
- // Default values.
- var lang = (globalThis.navigator?.language ?? "C").replace("-", "_") + ".UTF-8";
- var env = {
- "USER": "web_user",
- "LOGNAME": "web_user",
- "PATH": "/",
- "PWD": "/",
- "HOME": "/home/web_user",
- "LANG": lang,
- "_": getExecutableName()
- };
- // Apply the user-provided values, if any.
- for (var x in ENV) {
- // x is a key in ENV; if ENV[x] is undefined, that means it was
- // explicitly set to be so. We allow user code to do that to
- // force variables with default values to remain unset.
- if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x];
- }
- var strings = [];
- for (var x in env) {
- strings.push(`${x}=${env[x]}`);
- }
- getEnvStrings.strings = strings;
- }
- return getEnvStrings.strings;
- };
- function _environ_get(__environ, environ_buf) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(70, 0, 1, __environ, environ_buf);
- var bufSize = 0;
- var envp = 0;
- for (var string of getEnvStrings()) {
- var ptr = environ_buf + bufSize;
- (growMemViews(), HEAPU32)[(((__environ) + (envp)) >> 2)] = ptr;
- bufSize += stringToUTF8(string, ptr, Infinity) + 1;
- envp += 4;
- }
- return 0;
- }
- function _environ_sizes_get(penviron_count, penviron_buf_size) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(71, 0, 1, penviron_count, penviron_buf_size);
- var strings = getEnvStrings();
- (growMemViews(), HEAPU32)[((penviron_count) >> 2)] = strings.length;
- var bufSize = 0;
- for (var string of strings) {
- bufSize += lengthBytesUTF8(string) + 1;
- }
- (growMemViews(), HEAPU32)[((penviron_buf_size) >> 2)] = bufSize;
- return 0;
- }
- function _fd_close(fd) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(72, 0, 1, fd);
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- FS.close(stream);
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
- }
- /** @param {number=} offset */ var doReadv = (stream, iov, iovcnt, offset) => {
- var ret = 0;
- for (var i = 0; i < iovcnt; i++) {
- var ptr = (growMemViews(), HEAPU32)[((iov) >> 2)];
- var len = (growMemViews(), HEAPU32)[(((iov) + (4)) >> 2)];
- iov += 8;
- var curr = FS.read(stream, (growMemViews(), HEAP8), ptr, len, offset);
- if (curr < 0) return -1;
- ret += curr;
- if (curr < len) break;
- // nothing more to read
- if (typeof offset != "undefined") {
- offset += curr;
- }
- }
- return ret;
- };
- function _fd_read(fd, iov, iovcnt, pnum) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(73, 0, 1, fd, iov, iovcnt, pnum);
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- var num = doReadv(stream, iov, iovcnt);
- (growMemViews(), HEAPU32)[((pnum) >> 2)] = num;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
- }
- function _fd_seek(fd, offset, whence, newOffset) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(74, 0, 1, fd, offset, whence, newOffset);
- offset = bigintToI53Checked(offset);
- try {
- if (isNaN(offset)) return 22;
- var stream = SYSCALLS.getStreamFromFD(fd);
- FS.llseek(stream, offset, whence);
- (growMemViews(), HEAP64)[((newOffset) >> 3)] = BigInt(stream.position);
- if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
- // reset readdir state
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
- }
- /** @param {number=} offset */ var doWritev = (stream, iov, iovcnt, offset) => {
- var ret = 0;
- for (var i = 0; i < iovcnt; i++) {
- var ptr = (growMemViews(), HEAPU32)[((iov) >> 2)];
- var len = (growMemViews(), HEAPU32)[(((iov) + (4)) >> 2)];
- iov += 8;
- var curr = FS.write(stream, (growMemViews(), HEAP8), ptr, len, offset);
- if (curr < 0) return -1;
- ret += curr;
- if (curr < len) {
- // No more space to write.
- break;
- }
- if (typeof offset != "undefined") {
- offset += curr;
- }
- }
- return ret;
- };
- function _fd_write(fd, iov, iovcnt, pnum) {
- if (ENVIRONMENT_IS_PTHREAD) return proxyToMainThread(75, 0, 1, fd, iov, iovcnt, pnum);
- try {
- var stream = SYSCALLS.getStreamFromFD(fd);
- var num = doWritev(stream, iov, iovcnt);
- (growMemViews(), HEAPU32)[((pnum) >> 2)] = num;
- return 0;
- } catch (e) {
- if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e;
- return e.errno;
- }
- }
- function _posix_spawnp(...args) {
- abort("missing function: posix_spawnp");
- }
- _posix_spawnp.stub = true;
- var autoResumeAudioContext = ctx => {
- for (var event of [ "keydown", "mousedown", "touchstart" ]) {
- for (var element of [ document, document.getElementById("canvas") ]) {
- element?.addEventListener(event, () => {
- if (ctx.state === "suspended") ctx.resume();
- }, {
- "once": true
- });
- }
- }
- };
- var dynCall = (sig, ptr, args = [], promising = false) => {
- assert(ptr, `null function pointer in dynCall`);
- assert(!promising, "async dynCall is not supported in this mode");
- assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`);
- var func = getWasmTableEntry(ptr);
- var rtn = func(...args);
- function convert(rtn) {
- return rtn;
- }
- return convert(rtn);
- };
- var getCFunc = ident => {
- var func = Module["_" + ident];
- // closure exported function
- assert(func, `Cannot call unknown function ${ident}, make sure it is exported`);
- return func;
- };
- var writeArrayToMemory = (array, buffer) => {
- assert(array.length >= 0, "writeArrayToMemory array must have a length (should be an array or typed array)");
- (growMemViews(), HEAP8).set(array, buffer);
- };
- /**
- * @param {string|null=} returnType
- * @param {Array=} argTypes
- * @param {Array=} args
- * @param {Object=} opts
- */ var ccall = (ident, returnType, argTypes, args, opts) => {
- // For fast lookup of conversion functions
- var toC = {
- "string": str => {
- var ret = 0;
- if (str !== null && str !== undefined && str !== 0) {
- // null string
- ret = stringToUTF8OnStack(str);
- }
- return ret;
- },
- "array": arr => {
- var ret = stackAlloc(arr.length);
- writeArrayToMemory(arr, ret);
- return ret;
- }
- };
- function convertReturnValue(ret) {
- if (returnType === "string") {
- return UTF8ToString(ret);
- }
- if (returnType === "boolean") return Boolean(ret);
- return ret;
- }
- var func = getCFunc(ident);
- var cArgs = [];
- var stack = 0;
- assert(returnType !== "array", 'return type should not be "array"');
- if (args) {
- for (var i = 0; i < args.length; i++) {
- var converter = toC[argTypes[i]];
- if (converter) {
- if (stack === 0) stack = stackSave();
- cArgs[i] = converter(args[i]);
- } else {
- cArgs[i] = args[i];
- }
- }
- }
- var ret = func(...cArgs);
- function onDone(ret) {
- if (stack !== 0) stackRestore(stack);
- return convertReturnValue(ret);
- }
- ret = onDone(ret);
- return ret;
- };
- /**
- * @param {string=} returnType
- * @param {Array=} argTypes
- * @param {Object=} opts
- */ var cwrap = (ident, returnType, argTypes, opts) => (...args) => ccall(ident, returnType, argTypes, args, opts);
- var print = out;
- var FS_createPath = (...args) => FS.createPath(...args);
- var FS_unlink = (...args) => FS.unlink(...args);
- var FS_createLazyFile = (...args) => FS.createLazyFile(...args);
- var FS_createDevice = (...args) => FS.createDevice(...args);
- var createContext = Browser.createContext;
- PThread.init();
- FS.createPreloadedFile = FS_createPreloadedFile;
- FS.preloadFile = FS_preloadFile;
- FS.staticInit();
- Module["requestAnimationFrame"] = MainLoop.requestAnimationFrame;
- Module["pauseMainLoop"] = MainLoop.pause;
- Module["resumeMainLoop"] = MainLoop.resume;
- MainLoop.init();
- for (let i = 0; i < 32; ++i) tempFixedLengthArray.push(new Array(i));
- var miniTempWebGLFloatBuffersStorage = new Float32Array(288);
- // Create GL_POOL_TEMP_BUFFERS_SIZE+1 temporary buffers, for uploads of size 0 through GL_POOL_TEMP_BUFFERS_SIZE inclusive
- for (/**@suppress{duplicate}*/ var i = 0; i <= 288; ++i) {
- miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i);
- }
- var miniTempWebGLIntBuffersStorage = new Int32Array(288);
- // Create GL_POOL_TEMP_BUFFERS_SIZE+1 temporary buffers, for uploads of size 0 through GL_POOL_TEMP_BUFFERS_SIZE inclusive
- for (/**@suppress{duplicate}*/ var i = 0; i <= 288; ++i) {
- miniTempWebGLIntBuffers[i] = miniTempWebGLIntBuffersStorage.subarray(0, i);
- }
- // End JS library code
- // include: postlibrary.js
- // This file is included after the automatically-generated JS library code
- // but before the wasm module is created.
- {
- // With WASM_ESM_INTEGRATION this has to happen at the top level and not
- // delayed until processModuleArgs.
- initMemory();
- // Begin ATMODULES hooks
- if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"];
- if (Module["print"]) out = Module["print"];
- if (Module["printErr"]) err = Module["printErr"];
- // End ATMODULES hooks
- checkIncomingModuleAPI();
- if (Module["arguments"]) programArgs = Module["arguments"];
- if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
- // Assertions on removed incoming Module JS APIs.
- assert(typeof Module["memoryInitializerPrefixURL"] == "undefined", "Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");
- assert(typeof Module["pthreadMainPrefixURL"] == "undefined", "Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");
- assert(typeof Module["cdInitializerPrefixURL"] == "undefined", "Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");
- assert(typeof Module["filePackagePrefixURL"] == "undefined", "Module.filePackagePrefixURL option was removed, use Module.locateFile instead");
- assert(typeof Module["read"] == "undefined", "Module.read option was removed");
- assert(typeof Module["readAsync"] == "undefined", "Module.readAsync option was removed (modify readAsync in JS)");
- assert(typeof Module["readBinary"] == "undefined", "Module.readBinary option was removed (modify readBinary in JS)");
- assert(typeof Module["setWindowTitle"] == "undefined", "Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)");
- assert(typeof Module["TOTAL_MEMORY"] == "undefined", "Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");
- assert(typeof Module["ENVIRONMENT"] == "undefined", "Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)");
- assert(typeof Module["STACK_SIZE"] == "undefined", "STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time");
- var preInit = Module["preInit"];
- if (preInit) {
- if (typeof preInit == "function") Module["preInit"] = preInit = [ preInit ];
- // Written as a loop so that preInit functions that themselves add more
- // preInit functions. Is this actually needed?
- while (preInit.length > 0) {
- preInit.shift()();
- }
- }
- consumedModuleProp("preInit");
- }
- // Begin runtime exports
- Module["addRunDependency"] = addRunDependency;
- Module["removeRunDependency"] = removeRunDependency;
- Module["ccall"] = ccall;
- Module["cwrap"] = cwrap;
- Module["createContext"] = createContext;
- Module["FS_preloadFile"] = FS_preloadFile;
- Module["FS_unlink"] = FS_unlink;
- Module["FS_createPath"] = FS_createPath;
- Module["FS_createDevice"] = FS_createDevice;
- Module["FS_createDataFile"] = FS_createDataFile;
- Module["FS_createLazyFile"] = FS_createLazyFile;
- Module["print"] = print;
- var missingLibrarySymbols = [ "writeI53ToI64Clamped", "writeI53ToI64Signaling", "writeI53ToU64Clamped", "writeI53ToU64Signaling", "convertI32PairToI53", "convertI32PairToI53Checked", "convertU32PairToI53", "getTempRet0", "setTempRet0", "createNamedFunction", "withStackSave", "inetPton4", "inetNtop4", "inetPton6", "inetNtop6", "readSockaddr", "writeSockaddr", "getDynCaller", "asmjsMangle", "HandleAllocator", "addOnInit", "addOnPostCtor", "addOnPreMain", "STACK_SIZE", "STACK_ALIGN", "POINTER_SIZE", "ASSERTIONS", "convertJsFunctionToWasm", "getEmptyTableSlot", "updateTableMap", "getFunctionAddress", "addFunction", "removeFunction", "intArrayToString", "AsciiToString", "stringToAscii", "UTF16ToString", "stringToUTF16", "lengthBytesUTF16", "UTF32ToString", "stringToUTF32", "lengthBytesUTF32", "fillDeviceOrientationEventData", "registerDeviceOrientationEventCallback", "fillDeviceMotionEventData", "registerDeviceMotionEventCallback", "screenOrientation", "fillOrientationChangeEventData", "registerOrientationChangeEventCallback", "hideEverythingExceptGivenElement", "restoreHiddenElements", "softFullscreenResizeWebGLRenderTarget", "registerPointerlockErrorEventCallback", "fillBatteryEventData", "registerBatteryEventCallback", "jsStackTrace", "getCallstack", "convertPCtoSourceLocation", "wasiRightsToMuslOFlags", "wasiOFlagsToMuslOFlags", "setImmediateWrapped", "safeRequestAnimationFrame", "clearImmediateWrapped", "registerPostMainLoop", "registerPreMainLoop", "getPromise", "makePromise", "addPromise", "idsToPromises", "makePromiseCallback", "ExceptionInfo", "findMatchingCatch", "incrementUncaughtExceptionCount", "decrementUncaughtExceptionCount", "Browser_asyncPrepareDataCounter", "arraySum", "addDays", "getSocketFromFD", "getSocketAddress", "FS_mkdirTree", "_setNetworkCallback", "writeGLArray", "emscripten_webgl_destroy_context_before_on_calling_thread", "registerWebGlEventCallback", "runAndAbortIfError", "ALLOC_NORMAL", "ALLOC_STACK", "allocate", "writeStringToMemory", "writeAsciiToMemory", "allocateUTF8", "allocateUTF8OnStack", "demangle", "stackTrace", "getNativeTypeSize" ];
- missingLibrarySymbols.forEach(missingLibrarySymbol);
- var unexportedSymbols = [ "run", "out", "err", "callMain", "abort", "wasmExports", "writeStackCookie", "checkStackCookie", "writeI53ToI64", "readI53FromI64", "readI53FromU64", "INT53_MAX", "INT53_MIN", "bigintToI53Checked", "HEAP8", "HEAPU8", "HEAP16", "HEAPU16", "HEAP32", "HEAPU32", "HEAPF32", "HEAPF64", "HEAP64", "HEAPU64", "stackSave", "stackRestore", "stackAlloc", "ptrToString", "zeroMemory", "exitJS", "getHeapMax", "growMemory", "ENV", "ERRNO_CODES", "strError", "DNS", "Protocols", "Sockets", "timers", "warnOnce", "readEmAsmArgsArray", "readEmAsmArgs", "runEmAsmFunction", "runMainThreadEmAsm", "jstoi_q", "getExecutableName", "autoResumeAudioContext", "dynCall", "handleException", "keepRuntimeAlive", "runtimeKeepalivePush", "runtimeKeepalivePop", "callUserCallback", "maybeExit", "asyncLoad", "alignMemory", "mmapAlloc", "wasmTable", "wasmMemory", "getUniqueRunDependency", "noExitRuntime", "addOnPreRun", "addOnExit", "addOnPostRun", "freeTableIndexes", "functionsInTableMap", "setValue", "getValue", "PATH", "PATH_FS", "UTF8Decoder", "UTF8ArrayToString", "UTF8ToString", "stringToUTF8Array", "stringToUTF8", "lengthBytesUTF8", "intArrayFromString", "UTF16Decoder", "stringToNewUTF8", "stringToUTF8OnStack", "writeArrayToMemory", "JSEvents", "registerKeyEventCallback", "specialHTMLTargets", "maybeCStringToJsString", "findEventTarget", "findCanvasEventTarget", "getBoundingClientRect", "fillMouseEventData", "registerMouseEventCallback", "registerWheelEventCallback", "registerUiEventCallback", "registerFocusEventCallback", "fillFullscreenChangeEventData", "registerFullscreenChangeEventCallback", "JSEvents_requestFullscreen", "JSEvents_resizeCanvasForFullscreen", "registerRestoreOldStyle", "setLetterbox", "currentFullscreenStrategy", "restoreOldWindowedStyle", "doRequestFullscreen", "fillPointerlockChangeEventData", "registerPointerlockChangeEventCallback", "requestPointerLock", "fillVisibilityChangeEventData", "registerVisibilityChangeEventCallback", "registerTouchEventCallback", "fillGamepadEventData", "registerGamepadEventCallback", "registerBeforeUnloadEventCallback", "setCanvasElementSizeCallingThread", "setCanvasElementSizeMainThread", "setCanvasElementSize", "getCanvasSizeCallingThread", "getCanvasSizeMainThread", "getCanvasElementSize", "UNWIND_CACHE", "ExitStatus", "getEnvStrings", "checkWasiClock", "doReadv", "doWritev", "initRandomFill", "randomFill", "safeSetTimeout", "emSetImmediate", "emClearImmediate_deps", "emClearImmediate", "promiseMap", "uncaughtExceptionCount", "exceptionCaught", "Browser", "requestFullscreen", "requestFullScreen", "setCanvasSize", "getUserMedia", "getPreloadedImageData__data", "wget", "MONTH_DAYS_REGULAR", "MONTH_DAYS_LEAP", "MONTH_DAYS_REGULAR_CUMULATIVE", "MONTH_DAYS_LEAP_CUMULATIVE", "isLeapYear", "ydayFromDate", "SYSCALLS", "preloadPlugins", "FS_createPreloadedFile", "FS_modeStringToFlags", "FS_getMode", "FS_fileDataToTypedArray", "FS_stdin_getChar_buffer", "FS_stdin_getChar", "FS_readFile", "FS", "FS_root", "FS_mounts", "FS_devices", "FS_streams", "FS_nextInode", "FS_nameTable", "FS_currentPath", "FS_initialized", "FS_ignorePermissions", "FS_filesystems", "FS_syncFSRequests", "FS_lookupPath", "FS_getPath", "FS_hashName", "FS_hashAddNode", "FS_hashRemoveNode", "FS_lookupNode", "FS_createNode", "FS_destroyNode", "FS_isRoot", "FS_isMountpoint", "FS_isFile", "FS_isDir", "FS_isLink", "FS_isChrdev", "FS_isBlkdev", "FS_isFIFO", "FS_isSocket", "FS_flagsToPermissionString", "FS_nodePermissions", "FS_mayLookup", "FS_mayCreate", "FS_mayDelete", "FS_mayOpen", "FS_checkOpExists", "FS_nextfd", "FS_getStreamChecked", "FS_getStream", "FS_createStream", "FS_closeStream", "FS_dupStream", "FS_doSetAttr", "FS_chrdev_stream_ops", "FS_major", "FS_minor", "FS_makedev", "FS_registerDevice", "FS_getDevice", "FS_getMounts", "FS_syncfs", "FS_mount", "FS_unmount", "FS_lookup", "FS_mknod", "FS_statfs", "FS_statfsStream", "FS_statfsNode", "FS_create", "FS_mkdir", "FS_mkdev", "FS_symlink", "FS_rename", "FS_rmdir", "FS_readdir", "FS_readlink", "FS_stat", "FS_fstat", "FS_lstat", "FS_doChmod", "FS_chmod", "FS_lchmod", "FS_fchmod", "FS_doChown", "FS_chown", "FS_lchown", "FS_fchown", "FS_doTruncate", "FS_truncate", "FS_ftruncate", "FS_utime", "FS_open", "FS_close", "FS_isClosed", "FS_llseek", "FS_read", "FS_write", "FS_mmap", "FS_msync", "FS_ioctl", "FS_writeFile", "FS_cwd", "FS_chdir", "FS_createDefaultDirectories", "FS_createDefaultDevices", "FS_createSpecialDirectories", "FS_createStandardStreams", "FS_staticInit", "FS_init", "FS_quit", "FS_findObject", "FS_analyzePath", "FS_createFile", "FS_forceLoadFile", "MEMFS", "TTY", "PIPEFS", "SOCKFS", "tempFixedLengthArray", "miniTempWebGLFloatBuffers", "miniTempWebGLIntBuffers", "heapObjectForWebGLType", "toTypedArrayIndex", "webgl_enable_ANGLE_instanced_arrays", "webgl_enable_OES_vertex_array_object", "webgl_enable_WEBGL_draw_buffers", "webgl_enable_WEBGL_multi_draw", "webgl_enable_EXT_polygon_offset_clamp", "webgl_enable_EXT_clip_control", "webgl_enable_WEBGL_polygon_mode", "GL", "emscriptenWebGLGet", "computeUnpackAlignedImageSize", "colorChannelsInGlTextureFormat", "emscriptenWebGLGetTexPixelData", "emscriptenWebGLGetUniform", "webglGetProgramUniformLocation", "webglGetUniformLocation", "webglPrepareUniformLocationsBeforeFirstUse", "webglGetLeftBracePos", "emscriptenWebGLGetVertexAttrib", "__glGetActiveAttribOrUniform", "AL", "GLUT", "EGL", "GLEW", "IDBStore", "waitAsyncPolyfilled", "printErr", "jstoi_s", "PThread", "terminateWorker", "cleanupThread", "registerTLSInit", "spawnThread", "exitOnMainThread", "proxyToMainThread", "proxiedJSCallArgs", "invokeEntryPoint", "checkMailbox", "IDBFS" ];
- unexportedSymbols.forEach(unexportedRuntimeSymbol);
- // End runtime exports
- // Begin JS library exports
- // End JS library exports
- // end include: postlibrary.js
- // proxiedFunctionTable specifies the list of functions that can be called
- // either synchronously or asynchronously from other threads in postMessage()d
- // or internally queued events. This way a pthread in a Worker can synchronously
- // access e.g. the DOM on the main thread.
- var proxiedFunctionTable = [ _proc_exit, exitOnMainThread, pthreadCreateProxied, ___syscall_chdir, ___syscall_fcntl64, ___syscall_fstat64, ___syscall_getcwd, ___syscall_ioctl, ___syscall_lstat64, ___syscall_mkdirat, ___syscall_newfstatat, ___syscall_openat, ___syscall_pipe2, ___syscall_stat64, __mmap_js, __munmap_js, _eglBindAPI, _eglChooseConfig, _eglCreateContext, _eglCreateWindowSurface, _eglDestroyContext, _eglDestroySurface, _eglGetConfigAttrib, _eglGetDisplay, _eglGetError, _eglInitialize, _eglMakeCurrent, _eglQueryString, _eglSwapBuffers, _eglSwapInterval, _eglTerminate, _eglWaitClient, _eglWaitNative, _emscripten_exit_fullscreen, getCanvasSizeMainThread, setCanvasElementSizeMainThread, _emscripten_exit_pointerlock, _emscripten_force_exit, _emscripten_get_device_pixel_ratio, _emscripten_get_element_css_size, _emscripten_get_gamepad_status, _emscripten_get_num_gamepads, _emscripten_get_screen_size, _emscripten_request_fullscreen_strategy, _emscripten_request_pointerlock, _emscripten_sample_gamepad_data, _emscripten_set_beforeunload_callback_on_thread, _emscripten_set_blur_callback_on_thread, _emscripten_set_element_css_size, _emscripten_set_focus_callback_on_thread, _emscripten_set_fullscreenchange_callback_on_thread, _emscripten_set_gamepadconnected_callback_on_thread, _emscripten_set_gamepaddisconnected_callback_on_thread, _emscripten_set_keydown_callback_on_thread, _emscripten_set_keypress_callback_on_thread, _emscripten_set_keyup_callback_on_thread, _emscripten_set_mousedown_callback_on_thread, _emscripten_set_mouseenter_callback_on_thread, _emscripten_set_mouseleave_callback_on_thread, _emscripten_set_mousemove_callback_on_thread, _emscripten_set_mouseup_callback_on_thread, _emscripten_set_pointerlockchange_callback_on_thread, _emscripten_set_resize_callback_on_thread, _emscripten_set_touchcancel_callback_on_thread, _emscripten_set_touchend_callback_on_thread, _emscripten_set_touchmove_callback_on_thread, _emscripten_set_touchstart_callback_on_thread, _emscripten_set_visibilitychange_callback_on_thread, _emscripten_set_wheel_callback_on_thread, _emscripten_set_window_title, _environ_get, _environ_sizes_get, _fd_close, _fd_read, _fd_seek, _fd_write ];
- function checkIncomingModuleAPI() {
- ignoredModuleProp("fetchSettings");
- ignoredModuleProp("logReadFiles");
- ignoredModuleProp("loadSplitModule");
- ignoredModuleProp("onMalloc");
- ignoredModuleProp("onRealloc");
- ignoredModuleProp("onFree");
- ignoredModuleProp("onSbrkGrow");
- ignoredModuleProp("onCOSCacheHit");
- ignoredModuleProp("onCOSCacheMiss");
- ignoredModuleProp("onCOSStore");
- ignoredModuleProp("GL_MAX_TEXTURE_IMAGE_UNITS");
- ignoredModuleProp("SDL_canPlayWithWebAudio");
- ignoredModuleProp("SDL_numSimultaneouslyQueuedBuffers");
- ignoredModuleProp("freePreloadedMediaOnUse");
- ignoredModuleProp("preinitializedWebGLContext");
- ignoredModuleProp("keyboardListeningElement");
- ignoredModuleProp("doNotCaptureKeyboard");
- ignoredModuleProp("extraStackTrace");
- ignoredModuleProp("preloadPlugins");
- ignoredModuleProp("preMainLoop");
- ignoredModuleProp("postMainLoop");
- ignoredModuleProp("forcedAspectRatio");
- ignoredModuleProp("mainScriptUrlOrBlob");
- ignoredModuleProp("onFullScreen");
- ignoredModuleProp("INITIAL_MEMORY");
- ignoredModuleProp("wasmMemory");
- ignoredModuleProp("wasmBinary");
- }
- var ASM_CONSTS = {
- 206960: () => {
- FS.mkdir("/IDBFS");
- FS.mount(IDBFS, {}, "/IDBFS");
- Module.print("start file sync..");
- Module.syncdone = 0;
- FS.syncfs(true, function(err) {
- Module.print("syncfs done");
- Module.print(err);
- assert(!err);
- ccall("initConfigDone", "v");
- Module.print("end file sync..");
- Module.syncdone = 1;
- });
- },
- 207247: $0 => {
- var str = UTF8ToString($0) + "\n\n" + "Abort/Retry/Ignore/AlwaysIgnore? [ariA] :";
- var reply = window.prompt(str, "i");
- if (reply === null) {
- reply = "i";
- }
- return reply.length === 1 ? reply.charCodeAt(0) : -1;
- },
- 207462: () => {
- if (typeof (AudioContext) !== "undefined") {
- return true;
- } else if (typeof (webkitAudioContext) !== "undefined") {
- return true;
- }
- return false;
- },
- 207609: () => {
- if ((typeof (navigator.mediaDevices) !== "undefined") && (typeof (navigator.mediaDevices.getUserMedia) !== "undefined")) {
- return true;
- } else if (typeof (navigator.webkitGetUserMedia) !== "undefined") {
- return true;
- }
- return false;
- },
- 207843: $0 => {
- if (typeof (Module["SDL2"]) === "undefined") {
- Module["SDL2"] = {};
- }
- var SDL2 = Module["SDL2"];
- if (!$0) {
- SDL2.audio = {};
- } else {
- SDL2.capture = {};
- }
- if (!SDL2.audioContext) {
- if (typeof (AudioContext) !== "undefined") {
- SDL2.audioContext = new AudioContext;
- } else if (typeof (webkitAudioContext) !== "undefined") {
- SDL2.audioContext = new webkitAudioContext;
- }
- if (SDL2.audioContext) {
- if ((typeof navigator.userActivation) === "undefined") {
- autoResumeAudioContext(SDL2.audioContext);
- }
- }
- }
- return SDL2.audioContext === undefined ? -1 : 0;
- },
- 208395: () => {
- var SDL2 = Module["SDL2"];
- return SDL2.audioContext.sampleRate;
- },
- 208463: ($0, $1, $2, $3) => {
- var SDL2 = Module["SDL2"];
- var have_microphone = function(stream) {
- if (SDL2.capture.silenceTimer !== undefined) {
- clearInterval(SDL2.capture.silenceTimer);
- SDL2.capture.silenceTimer = undefined;
- SDL2.capture.silenceBuffer = undefined;
- }
- SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream);
- SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
- SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {
- if ((SDL2 === undefined) || (SDL2.capture === undefined)) {
- return;
- }
- audioProcessingEvent.outputBuffer.getChannelData(0).fill(0);
- SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
- dynCall("vp", $2, [ $3 ]);
- };
- SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
- SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
- SDL2.capture.stream = stream;
- };
- var no_microphone = function(error) {};
- SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
- SDL2.capture.silenceBuffer.getChannelData(0).fill(0);
- var silence_callback = function() {
- SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
- dynCall("vp", $2, [ $3 ]);
- };
- SDL2.capture.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1e3);
- if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
- navigator.mediaDevices.getUserMedia({
- audio: true,
- video: false
- }).then(have_microphone).catch(no_microphone);
- } else if (navigator.webkitGetUserMedia !== undefined) {
- navigator.webkitGetUserMedia({
- audio: true,
- video: false
- }, have_microphone, no_microphone);
- }
- },
- 210156: ($0, $1, $2, $3) => {
- var SDL2 = Module["SDL2"];
- SDL2.audio.scriptProcessorNode = SDL2.audioContext["createScriptProcessor"]($1, 0, $0);
- SDL2.audio.scriptProcessorNode["onaudioprocess"] = function(e) {
- if ((SDL2 === undefined) || (SDL2.audio === undefined)) {
- return;
- }
- if (SDL2.audio.silenceTimer !== undefined) {
- clearInterval(SDL2.audio.silenceTimer);
- SDL2.audio.silenceTimer = undefined;
- SDL2.audio.silenceBuffer = undefined;
- }
- SDL2.audio.currentOutputBuffer = e["outputBuffer"];
- dynCall("vp", $2, [ $3 ]);
- };
- SDL2.audio.scriptProcessorNode["connect"](SDL2.audioContext["destination"]);
- if (SDL2.audioContext.state === "suspended") {
- SDL2.audio.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
- SDL2.audio.silenceBuffer.getChannelData(0).fill(0);
- var silence_callback = function() {
- if ((typeof navigator.userActivation) !== "undefined") {
- if (navigator.userActivation.hasBeenActive) {
- SDL2.audioContext.resume();
- }
- }
- SDL2.audio.currentOutputBuffer = SDL2.audio.silenceBuffer;
- dynCall("vp", $2, [ $3 ]);
- SDL2.audio.currentOutputBuffer = undefined;
- };
- SDL2.audio.silenceTimer = setInterval(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1e3);
- }
- },
- 211331: ($0, $1) => {
- var SDL2 = Module["SDL2"];
- var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
- for (var c = 0; c < numChannels; ++c) {
- var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c);
- if (channelData.length != $1) {
- throw "Web Audio capture buffer length mismatch! Destination size: " + channelData.length + " samples vs expected " + $1 + " samples!";
- }
- if (numChannels == 1) {
- for (var j = 0; j < $1; ++j) {
- setValue($0 + (j * 4), channelData[j], "float");
- }
- } else {
- for (var j = 0; j < $1; ++j) {
- setValue($0 + (((j * numChannels) + c) * 4), channelData[j], "float");
- }
- }
- }
- },
- 211936: ($0, $1) => {
- var SDL2 = Module["SDL2"];
- var buf = $0 >>> 2;
- var numChannels = SDL2.audio.currentOutputBuffer["numberOfChannels"];
- for (var c = 0; c < numChannels; ++c) {
- var channelData = SDL2.audio.currentOutputBuffer["getChannelData"](c);
- if (channelData.length != $1) {
- throw "Web Audio output buffer length mismatch! Destination size: " + channelData.length + " samples vs expected " + $1 + " samples!";
- }
- for (var j = 0; j < $1; ++j) {
- channelData[j] = (growMemViews(), HEAPF32)[buf + (j * numChannels + c)];
- }
- }
- },
- 212425: $0 => {
- var SDL2 = Module["SDL2"];
- if ($0) {
- if (SDL2.capture.silenceTimer !== undefined) {
- clearInterval(SDL2.capture.silenceTimer);
- }
- if (SDL2.capture.stream !== undefined) {
- var tracks = SDL2.capture.stream.getAudioTracks();
- for (var i = 0; i < tracks.length; i++) {
- SDL2.capture.stream.removeTrack(tracks[i]);
- }
- }
- if (SDL2.capture.scriptProcessorNode !== undefined) {
- SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
- SDL2.capture.scriptProcessorNode.disconnect();
- }
- if (SDL2.capture.mediaStreamNode !== undefined) {
- SDL2.capture.mediaStreamNode.disconnect();
- }
- SDL2.capture = undefined;
- } else {
- if (SDL2.audio.scriptProcessorNode != undefined) {
- SDL2.audio.scriptProcessorNode.disconnect();
- }
- if (SDL2.audio.silenceTimer !== undefined) {
- clearInterval(SDL2.audio.silenceTimer);
- }
- SDL2.audio = undefined;
- }
- if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
- SDL2.audioContext.close();
- SDL2.audioContext = undefined;
- }
- },
- 213431: ($0, $1, $2) => {
- var w = $0;
- var h = $1;
- var pixels = $2;
- if (!Module["SDL2"]) Module["SDL2"] = {};
- var SDL2 = Module["SDL2"];
- if (SDL2.ctxCanvas !== Module["canvas"]) {
- SDL2.ctx = Browser.createContext(Module["canvas"], false, true);
- SDL2.ctxCanvas = Module["canvas"];
- }
- if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) {
- SDL2.image = SDL2.ctx.createImageData(w, h);
- SDL2.w = w;
- SDL2.h = h;
- SDL2.imageCtx = SDL2.ctx;
- }
- var data = SDL2.image.data;
- var src = pixels / 4;
- var dst = 0;
- var num;
- if (typeof CanvasPixelArray !== "undefined" && data instanceof CanvasPixelArray) {
- num = data.length;
- while (dst < num) {
- var val = (growMemViews(), HEAP32)[src];
- data[dst] = val & 255;
- data[dst + 1] = (val >> 8) & 255;
- data[dst + 2] = (val >> 16) & 255;
- data[dst + 3] = 255;
- src++;
- dst += 4;
- }
- } else {
- if (SDL2.data32Data !== data) {
- SDL2.data32 = new Int32Array(data.buffer);
- SDL2.data8 = new Uint8Array(data.buffer);
- SDL2.data32Data = data;
- }
- var data32 = SDL2.data32;
- num = data32.length;
- data32.set((growMemViews(), HEAP32).subarray(src, src + num));
- var data8 = SDL2.data8;
- var i = 3;
- var j = i + 4 * num;
- if (num % 8 == 0) {
- while (i < j) {
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- data8[i] = 255;
- i = i + 4 | 0;
- }
- } else {
- while (i < j) {
- data8[i] = 255;
- i = i + 4 | 0;
- }
- }
- }
- SDL2.ctx.putImageData(SDL2.image, 0, 0);
- },
- 214897: ($0, $1, $2, $3, $4) => {
- var w = $0;
- var h = $1;
- var hot_x = $2;
- var hot_y = $3;
- var pixels = $4;
- var canvas = document.createElement("canvas");
- canvas.width = w;
- canvas.height = h;
- var ctx = canvas.getContext("2d");
- var image = ctx.createImageData(w, h);
- var data = image.data;
- var src = pixels / 4;
- var dst = 0;
- var num;
- if (typeof CanvasPixelArray !== "undefined" && data instanceof CanvasPixelArray) {
- num = data.length;
- while (dst < num) {
- var val = (growMemViews(), HEAP32)[src];
- data[dst] = val & 255;
- data[dst + 1] = (val >> 8) & 255;
- data[dst + 2] = (val >> 16) & 255;
- data[dst + 3] = (val >> 24) & 255;
- src++;
- dst += 4;
- }
- } else {
- var data32 = new Int32Array(data.buffer);
- num = data32.length;
- data32.set((growMemViews(), HEAP32).subarray(src, src + num));
- }
- ctx.putImageData(image, 0, 0);
- var url = hot_x === 0 && hot_y === 0 ? "url(" + canvas.toDataURL() + "), auto" : "url(" + canvas.toDataURL() + ") " + hot_x + " " + hot_y + ", auto";
- var urlBuf = _malloc(url.length + 1);
- stringToUTF8(url, urlBuf, url.length + 1);
- return urlBuf;
- },
- 215885: $0 => {
- if (Module["canvas"]) {
- Module["canvas"].style["cursor"] = UTF8ToString($0);
- }
- },
- 215968: () => {
- if (Module["canvas"]) {
- Module["canvas"].style["cursor"] = "none";
- }
- },
- 216037: () => window.innerWidth,
- 216067: () => window.innerHeight
- };
- // Imports from the Wasm binary.
- var _strerror = makeInvalidEarlyAccess("_strerror");
- var _fflush = makeInvalidEarlyAccess("_fflush");
- var _free = makeInvalidEarlyAccess("_free");
- var _malloc = makeInvalidEarlyAccess("_malloc");
- var _initConfigDone = Module["_initConfigDone"] = makeInvalidEarlyAccess("_initConfigDone");
- var _main = Module["_main"] = makeInvalidEarlyAccess("_main");
- var _pthread_self = makeInvalidEarlyAccess("_pthread_self");
- var __emscripten_tls_init = makeInvalidEarlyAccess("__emscripten_tls_init");
- var _emscripten_builtin_memalign = makeInvalidEarlyAccess("_emscripten_builtin_memalign");
- var __emscripten_run_callback_on_thread = makeInvalidEarlyAccess("__emscripten_run_callback_on_thread");
- var __emscripten_thread_init = makeInvalidEarlyAccess("__emscripten_thread_init");
- var ___set_thread_state = makeInvalidEarlyAccess("___set_thread_state");
- var __emscripten_thread_crashed = makeInvalidEarlyAccess("__emscripten_thread_crashed");
- var _emscripten_stack_get_end = makeInvalidEarlyAccess("_emscripten_stack_get_end");
- var _emscripten_stack_get_base = makeInvalidEarlyAccess("_emscripten_stack_get_base");
- var __emscripten_run_js_on_main_thread_done = makeInvalidEarlyAccess("__emscripten_run_js_on_main_thread_done");
- var __emscripten_run_js_on_main_thread = makeInvalidEarlyAccess("__emscripten_run_js_on_main_thread");
- var __emscripten_thread_free_data = makeInvalidEarlyAccess("__emscripten_thread_free_data");
- var __emscripten_thread_exit = makeInvalidEarlyAccess("__emscripten_thread_exit");
- var __emscripten_check_mailbox = makeInvalidEarlyAccess("__emscripten_check_mailbox");
- var _emscripten_stack_init = makeInvalidEarlyAccess("_emscripten_stack_init");
- var _emscripten_stack_set_limits = makeInvalidEarlyAccess("_emscripten_stack_set_limits");
- var _emscripten_stack_get_free = makeInvalidEarlyAccess("_emscripten_stack_get_free");
- var __emscripten_stack_restore = makeInvalidEarlyAccess("__emscripten_stack_restore");
- var __emscripten_stack_alloc = makeInvalidEarlyAccess("__emscripten_stack_alloc");
- var _emscripten_stack_get_current = makeInvalidEarlyAccess("_emscripten_stack_get_current");
- var __indirect_function_table = makeInvalidEarlyAccess("__indirect_function_table");
- var wasmTable = makeInvalidEarlyAccess("wasmTable");
- function assignWasmExports(wasmExports) {
- assert(typeof wasmExports["strerror"] != "undefined", "missing Wasm export: strerror");
- assert(typeof wasmExports["fflush"] != "undefined", "missing Wasm export: fflush");
- assert(typeof wasmExports["free"] != "undefined", "missing Wasm export: free");
- assert(typeof wasmExports["malloc"] != "undefined", "missing Wasm export: malloc");
- assert(typeof wasmExports["initConfigDone"] != "undefined", "missing Wasm export: initConfigDone");
- assert(typeof wasmExports["main"] != "undefined", "missing Wasm export: main");
- assert(typeof wasmExports["pthread_self"] != "undefined", "missing Wasm export: pthread_self");
- assert(typeof wasmExports["_emscripten_tls_init"] != "undefined", "missing Wasm export: _emscripten_tls_init");
- assert(typeof wasmExports["emscripten_builtin_memalign"] != "undefined", "missing Wasm export: emscripten_builtin_memalign");
- assert(typeof wasmExports["_emscripten_run_callback_on_thread"] != "undefined", "missing Wasm export: _emscripten_run_callback_on_thread");
- assert(typeof wasmExports["_emscripten_thread_init"] != "undefined", "missing Wasm export: _emscripten_thread_init");
- assert(typeof wasmExports["__set_thread_state"] != "undefined", "missing Wasm export: __set_thread_state");
- assert(typeof wasmExports["_emscripten_thread_crashed"] != "undefined", "missing Wasm export: _emscripten_thread_crashed");
- assert(typeof wasmExports["emscripten_stack_get_end"] != "undefined", "missing Wasm export: emscripten_stack_get_end");
- assert(typeof wasmExports["emscripten_stack_get_base"] != "undefined", "missing Wasm export: emscripten_stack_get_base");
- assert(typeof wasmExports["_emscripten_run_js_on_main_thread_done"] != "undefined", "missing Wasm export: _emscripten_run_js_on_main_thread_done");
- assert(typeof wasmExports["_emscripten_run_js_on_main_thread"] != "undefined", "missing Wasm export: _emscripten_run_js_on_main_thread");
- assert(typeof wasmExports["_emscripten_thread_free_data"] != "undefined", "missing Wasm export: _emscripten_thread_free_data");
- assert(typeof wasmExports["_emscripten_thread_exit"] != "undefined", "missing Wasm export: _emscripten_thread_exit");
- assert(typeof wasmExports["_emscripten_check_mailbox"] != "undefined", "missing Wasm export: _emscripten_check_mailbox");
- assert(typeof wasmExports["emscripten_stack_init"] != "undefined", "missing Wasm export: emscripten_stack_init");
- assert(typeof wasmExports["emscripten_stack_set_limits"] != "undefined", "missing Wasm export: emscripten_stack_set_limits");
- assert(typeof wasmExports["emscripten_stack_get_free"] != "undefined", "missing Wasm export: emscripten_stack_get_free");
- assert(typeof wasmExports["_emscripten_stack_restore"] != "undefined", "missing Wasm export: _emscripten_stack_restore");
- assert(typeof wasmExports["_emscripten_stack_alloc"] != "undefined", "missing Wasm export: _emscripten_stack_alloc");
- assert(typeof wasmExports["emscripten_stack_get_current"] != "undefined", "missing Wasm export: emscripten_stack_get_current");
- assert(typeof wasmExports["__indirect_function_table"] != "undefined", "missing Wasm export: __indirect_function_table");
- _strerror = createExportWrapper("strerror", wasmExports["strerror"], 1);
- _fflush = createExportWrapper("fflush", wasmExports["fflush"], 1);
- _free = createExportWrapper("free", wasmExports["free"], 1);
- _malloc = createExportWrapper("malloc", wasmExports["malloc"], 1);
- _initConfigDone = Module["_initConfigDone"] = createExportWrapper("initConfigDone", wasmExports["initConfigDone"], 0);
- _main = Module["_main"] = createExportWrapper("main", wasmExports["main"], 3);
- _pthread_self = wasmExports["pthread_self"];
- __emscripten_tls_init = createExportWrapper("_emscripten_tls_init", wasmExports["_emscripten_tls_init"], 0);
- _emscripten_builtin_memalign = createExportWrapper("emscripten_builtin_memalign", wasmExports["emscripten_builtin_memalign"], 2);
- __emscripten_run_callback_on_thread = createExportWrapper("_emscripten_run_callback_on_thread", wasmExports["_emscripten_run_callback_on_thread"], 6);
- __emscripten_thread_init = createExportWrapper("_emscripten_thread_init", wasmExports["_emscripten_thread_init"], 6);
- ___set_thread_state = createExportWrapper("__set_thread_state", wasmExports["__set_thread_state"], 4);
- __emscripten_thread_crashed = createExportWrapper("_emscripten_thread_crashed", wasmExports["_emscripten_thread_crashed"], 0);
- _emscripten_stack_get_end = wasmExports["emscripten_stack_get_end"];
- _emscripten_stack_get_base = wasmExports["emscripten_stack_get_base"];
- __emscripten_run_js_on_main_thread_done = createExportWrapper("_emscripten_run_js_on_main_thread_done", wasmExports["_emscripten_run_js_on_main_thread_done"], 3);
- __emscripten_run_js_on_main_thread = createExportWrapper("_emscripten_run_js_on_main_thread", wasmExports["_emscripten_run_js_on_main_thread"], 5);
- __emscripten_thread_free_data = createExportWrapper("_emscripten_thread_free_data", wasmExports["_emscripten_thread_free_data"], 1);
- __emscripten_thread_exit = createExportWrapper("_emscripten_thread_exit", wasmExports["_emscripten_thread_exit"], 1);
- __emscripten_check_mailbox = createExportWrapper("_emscripten_check_mailbox", wasmExports["_emscripten_check_mailbox"], 0);
- _emscripten_stack_init = wasmExports["emscripten_stack_init"];
- _emscripten_stack_set_limits = wasmExports["emscripten_stack_set_limits"];
- _emscripten_stack_get_free = wasmExports["emscripten_stack_get_free"];
- __emscripten_stack_restore = wasmExports["_emscripten_stack_restore"];
- __emscripten_stack_alloc = wasmExports["_emscripten_stack_alloc"];
- _emscripten_stack_get_current = wasmExports["emscripten_stack_get_current"];
- __indirect_function_table = wasmTable = wasmExports["__indirect_function_table"];
- }
- var wasmImports;
- function assignWasmImports() {
- wasmImports = {
- /** @export */ __assert_fail: ___assert_fail,
- /** @export */ __call_sighandler: ___call_sighandler,
- /** @export */ __pthread_create_js: ___pthread_create_js,
- /** @export */ __syscall_chdir: ___syscall_chdir,
- /** @export */ __syscall_fcntl64: ___syscall_fcntl64,
- /** @export */ __syscall_fstat64: ___syscall_fstat64,
- /** @export */ __syscall_getcwd: ___syscall_getcwd,
- /** @export */ __syscall_ioctl: ___syscall_ioctl,
- /** @export */ __syscall_lstat64: ___syscall_lstat64,
- /** @export */ __syscall_mkdirat: ___syscall_mkdirat,
- /** @export */ __syscall_newfstatat: ___syscall_newfstatat,
- /** @export */ __syscall_openat: ___syscall_openat,
- /** @export */ __syscall_pipe2: ___syscall_pipe2,
- /** @export */ __syscall_stat64: ___syscall_stat64,
- /** @export */ _abort_js: __abort_js,
- /** @export */ _emscripten_init_main_thread_js: __emscripten_init_main_thread_js,
- /** @export */ _emscripten_notify_mailbox_postmessage: __emscripten_notify_mailbox_postmessage,
- /** @export */ _emscripten_receive_on_main_thread_js: __emscripten_receive_on_main_thread_js,
- /** @export */ _emscripten_runtime_keepalive_clear: __emscripten_runtime_keepalive_clear,
- /** @export */ _emscripten_thread_cleanup: __emscripten_thread_cleanup,
- /** @export */ _emscripten_thread_mailbox_await: __emscripten_thread_mailbox_await,
- /** @export */ _emscripten_thread_set_strongref: __emscripten_thread_set_strongref,
- /** @export */ _localtime_js: __localtime_js,
- /** @export */ _mmap_js: __mmap_js,
- /** @export */ _munmap_js: __munmap_js,
- /** @export */ _tzset_js: __tzset_js,
- /** @export */ clock_time_get: _clock_time_get,
- /** @export */ eglBindAPI: _eglBindAPI,
- /** @export */ eglChooseConfig: _eglChooseConfig,
- /** @export */ eglCreateContext: _eglCreateContext,
- /** @export */ eglCreateWindowSurface: _eglCreateWindowSurface,
- /** @export */ eglDestroyContext: _eglDestroyContext,
- /** @export */ eglDestroySurface: _eglDestroySurface,
- /** @export */ eglGetConfigAttrib: _eglGetConfigAttrib,
- /** @export */ eglGetDisplay: _eglGetDisplay,
- /** @export */ eglGetError: _eglGetError,
- /** @export */ eglInitialize: _eglInitialize,
- /** @export */ eglMakeCurrent: _eglMakeCurrent,
- /** @export */ eglQueryString: _eglQueryString,
- /** @export */ eglSwapBuffers: _eglSwapBuffers,
- /** @export */ eglSwapInterval: _eglSwapInterval,
- /** @export */ eglTerminate: _eglTerminate,
- /** @export */ eglWaitGL: _eglWaitGL,
- /** @export */ eglWaitNative: _eglWaitNative,
- /** @export */ emscripten_asm_const_int: _emscripten_asm_const_int,
- /** @export */ emscripten_asm_const_int_sync_on_main_thread: _emscripten_asm_const_int_sync_on_main_thread,
- /** @export */ emscripten_asm_const_ptr_sync_on_main_thread: _emscripten_asm_const_ptr_sync_on_main_thread,
- /** @export */ emscripten_cancel_main_loop: _emscripten_cancel_main_loop,
- /** @export */ emscripten_check_blocking_allowed: _emscripten_check_blocking_allowed,
- /** @export */ emscripten_date_now: _emscripten_date_now,
- /** @export */ emscripten_exit_fullscreen: _emscripten_exit_fullscreen,
- /** @export */ emscripten_exit_pointerlock: _emscripten_exit_pointerlock,
- /** @export */ emscripten_exit_with_live_runtime: _emscripten_exit_with_live_runtime,
- /** @export */ emscripten_force_exit: _emscripten_force_exit,
- /** @export */ emscripten_get_device_pixel_ratio: _emscripten_get_device_pixel_ratio,
- /** @export */ emscripten_get_element_css_size: _emscripten_get_element_css_size,
- /** @export */ emscripten_get_gamepad_status: _emscripten_get_gamepad_status,
- /** @export */ emscripten_get_now: _emscripten_get_now,
- /** @export */ emscripten_get_num_gamepads: _emscripten_get_num_gamepads,
- /** @export */ emscripten_get_screen_size: _emscripten_get_screen_size,
- /** @export */ emscripten_glActiveTexture: _emscripten_glActiveTexture,
- /** @export */ emscripten_glAttachShader: _emscripten_glAttachShader,
- /** @export */ emscripten_glBeginQueryEXT: _emscripten_glBeginQueryEXT,
- /** @export */ emscripten_glBindAttribLocation: _emscripten_glBindAttribLocation,
- /** @export */ emscripten_glBindBuffer: _emscripten_glBindBuffer,
- /** @export */ emscripten_glBindFramebuffer: _emscripten_glBindFramebuffer,
- /** @export */ emscripten_glBindRenderbuffer: _emscripten_glBindRenderbuffer,
- /** @export */ emscripten_glBindTexture: _emscripten_glBindTexture,
- /** @export */ emscripten_glBindVertexArrayOES: _emscripten_glBindVertexArrayOES,
- /** @export */ emscripten_glBlendColor: _emscripten_glBlendColor,
- /** @export */ emscripten_glBlendEquation: _emscripten_glBlendEquation,
- /** @export */ emscripten_glBlendEquationSeparate: _emscripten_glBlendEquationSeparate,
- /** @export */ emscripten_glBlendFunc: _emscripten_glBlendFunc,
- /** @export */ emscripten_glBlendFuncSeparate: _emscripten_glBlendFuncSeparate,
- /** @export */ emscripten_glBufferData: _emscripten_glBufferData,
- /** @export */ emscripten_glBufferSubData: _emscripten_glBufferSubData,
- /** @export */ emscripten_glCheckFramebufferStatus: _emscripten_glCheckFramebufferStatus,
- /** @export */ emscripten_glClear: _emscripten_glClear,
- /** @export */ emscripten_glClearColor: _emscripten_glClearColor,
- /** @export */ emscripten_glClearDepthf: _emscripten_glClearDepthf,
- /** @export */ emscripten_glClearStencil: _emscripten_glClearStencil,
- /** @export */ emscripten_glClipControlEXT: _emscripten_glClipControlEXT,
- /** @export */ emscripten_glColorMask: _emscripten_glColorMask,
- /** @export */ emscripten_glCompileShader: _emscripten_glCompileShader,
- /** @export */ emscripten_glCompressedTexImage2D: _emscripten_glCompressedTexImage2D,
- /** @export */ emscripten_glCompressedTexSubImage2D: _emscripten_glCompressedTexSubImage2D,
- /** @export */ emscripten_glCopyTexImage2D: _emscripten_glCopyTexImage2D,
- /** @export */ emscripten_glCopyTexSubImage2D: _emscripten_glCopyTexSubImage2D,
- /** @export */ emscripten_glCreateProgram: _emscripten_glCreateProgram,
- /** @export */ emscripten_glCreateShader: _emscripten_glCreateShader,
- /** @export */ emscripten_glCullFace: _emscripten_glCullFace,
- /** @export */ emscripten_glDeleteBuffers: _emscripten_glDeleteBuffers,
- /** @export */ emscripten_glDeleteFramebuffers: _emscripten_glDeleteFramebuffers,
- /** @export */ emscripten_glDeleteProgram: _emscripten_glDeleteProgram,
- /** @export */ emscripten_glDeleteQueriesEXT: _emscripten_glDeleteQueriesEXT,
- /** @export */ emscripten_glDeleteRenderbuffers: _emscripten_glDeleteRenderbuffers,
- /** @export */ emscripten_glDeleteShader: _emscripten_glDeleteShader,
- /** @export */ emscripten_glDeleteTextures: _emscripten_glDeleteTextures,
- /** @export */ emscripten_glDeleteVertexArraysOES: _emscripten_glDeleteVertexArraysOES,
- /** @export */ emscripten_glDepthFunc: _emscripten_glDepthFunc,
- /** @export */ emscripten_glDepthMask: _emscripten_glDepthMask,
- /** @export */ emscripten_glDepthRangef: _emscripten_glDepthRangef,
- /** @export */ emscripten_glDetachShader: _emscripten_glDetachShader,
- /** @export */ emscripten_glDisable: _emscripten_glDisable,
- /** @export */ emscripten_glDisableVertexAttribArray: _emscripten_glDisableVertexAttribArray,
- /** @export */ emscripten_glDrawArrays: _emscripten_glDrawArrays,
- /** @export */ emscripten_glDrawArraysInstancedANGLE: _emscripten_glDrawArraysInstancedANGLE,
- /** @export */ emscripten_glDrawBuffersWEBGL: _emscripten_glDrawBuffersWEBGL,
- /** @export */ emscripten_glDrawElements: _emscripten_glDrawElements,
- /** @export */ emscripten_glDrawElementsInstancedANGLE: _emscripten_glDrawElementsInstancedANGLE,
- /** @export */ emscripten_glEnable: _emscripten_glEnable,
- /** @export */ emscripten_glEnableVertexAttribArray: _emscripten_glEnableVertexAttribArray,
- /** @export */ emscripten_glEndQueryEXT: _emscripten_glEndQueryEXT,
- /** @export */ emscripten_glFinish: _emscripten_glFinish,
- /** @export */ emscripten_glFlush: _emscripten_glFlush,
- /** @export */ emscripten_glFramebufferRenderbuffer: _emscripten_glFramebufferRenderbuffer,
- /** @export */ emscripten_glFramebufferTexture2D: _emscripten_glFramebufferTexture2D,
- /** @export */ emscripten_glFrontFace: _emscripten_glFrontFace,
- /** @export */ emscripten_glGenBuffers: _emscripten_glGenBuffers,
- /** @export */ emscripten_glGenFramebuffers: _emscripten_glGenFramebuffers,
- /** @export */ emscripten_glGenQueriesEXT: _emscripten_glGenQueriesEXT,
- /** @export */ emscripten_glGenRenderbuffers: _emscripten_glGenRenderbuffers,
- /** @export */ emscripten_glGenTextures: _emscripten_glGenTextures,
- /** @export */ emscripten_glGenVertexArraysOES: _emscripten_glGenVertexArraysOES,
- /** @export */ emscripten_glGenerateMipmap: _emscripten_glGenerateMipmap,
- /** @export */ emscripten_glGetActiveAttrib: _emscripten_glGetActiveAttrib,
- /** @export */ emscripten_glGetActiveUniform: _emscripten_glGetActiveUniform,
- /** @export */ emscripten_glGetAttachedShaders: _emscripten_glGetAttachedShaders,
- /** @export */ emscripten_glGetAttribLocation: _emscripten_glGetAttribLocation,
- /** @export */ emscripten_glGetBooleanv: _emscripten_glGetBooleanv,
- /** @export */ emscripten_glGetBufferParameteriv: _emscripten_glGetBufferParameteriv,
- /** @export */ emscripten_glGetError: _emscripten_glGetError,
- /** @export */ emscripten_glGetFloatv: _emscripten_glGetFloatv,
- /** @export */ emscripten_glGetFramebufferAttachmentParameteriv: _emscripten_glGetFramebufferAttachmentParameteriv,
- /** @export */ emscripten_glGetIntegerv: _emscripten_glGetIntegerv,
- /** @export */ emscripten_glGetProgramInfoLog: _emscripten_glGetProgramInfoLog,
- /** @export */ emscripten_glGetProgramiv: _emscripten_glGetProgramiv,
- /** @export */ emscripten_glGetQueryObjecti64vEXT: _emscripten_glGetQueryObjecti64vEXT,
- /** @export */ emscripten_glGetQueryObjectivEXT: _emscripten_glGetQueryObjectivEXT,
- /** @export */ emscripten_glGetQueryObjectui64vEXT: _emscripten_glGetQueryObjectui64vEXT,
- /** @export */ emscripten_glGetQueryObjectuivEXT: _emscripten_glGetQueryObjectuivEXT,
- /** @export */ emscripten_glGetQueryivEXT: _emscripten_glGetQueryivEXT,
- /** @export */ emscripten_glGetRenderbufferParameteriv: _emscripten_glGetRenderbufferParameteriv,
- /** @export */ emscripten_glGetShaderInfoLog: _emscripten_glGetShaderInfoLog,
- /** @export */ emscripten_glGetShaderPrecisionFormat: _emscripten_glGetShaderPrecisionFormat,
- /** @export */ emscripten_glGetShaderSource: _emscripten_glGetShaderSource,
- /** @export */ emscripten_glGetShaderiv: _emscripten_glGetShaderiv,
- /** @export */ emscripten_glGetString: _emscripten_glGetString,
- /** @export */ emscripten_glGetTexParameterfv: _emscripten_glGetTexParameterfv,
- /** @export */ emscripten_glGetTexParameteriv: _emscripten_glGetTexParameteriv,
- /** @export */ emscripten_glGetUniformLocation: _emscripten_glGetUniformLocation,
- /** @export */ emscripten_glGetUniformfv: _emscripten_glGetUniformfv,
- /** @export */ emscripten_glGetUniformiv: _emscripten_glGetUniformiv,
- /** @export */ emscripten_glGetVertexAttribPointerv: _emscripten_glGetVertexAttribPointerv,
- /** @export */ emscripten_glGetVertexAttribfv: _emscripten_glGetVertexAttribfv,
- /** @export */ emscripten_glGetVertexAttribiv: _emscripten_glGetVertexAttribiv,
- /** @export */ emscripten_glHint: _emscripten_glHint,
- /** @export */ emscripten_glIsBuffer: _emscripten_glIsBuffer,
- /** @export */ emscripten_glIsEnabled: _emscripten_glIsEnabled,
- /** @export */ emscripten_glIsFramebuffer: _emscripten_glIsFramebuffer,
- /** @export */ emscripten_glIsProgram: _emscripten_glIsProgram,
- /** @export */ emscripten_glIsQueryEXT: _emscripten_glIsQueryEXT,
- /** @export */ emscripten_glIsRenderbuffer: _emscripten_glIsRenderbuffer,
- /** @export */ emscripten_glIsShader: _emscripten_glIsShader,
- /** @export */ emscripten_glIsTexture: _emscripten_glIsTexture,
- /** @export */ emscripten_glIsVertexArrayOES: _emscripten_glIsVertexArrayOES,
- /** @export */ emscripten_glLineWidth: _emscripten_glLineWidth,
- /** @export */ emscripten_glLinkProgram: _emscripten_glLinkProgram,
- /** @export */ emscripten_glPixelStorei: _emscripten_glPixelStorei,
- /** @export */ emscripten_glPolygonModeWEBGL: _emscripten_glPolygonModeWEBGL,
- /** @export */ emscripten_glPolygonOffset: _emscripten_glPolygonOffset,
- /** @export */ emscripten_glPolygonOffsetClampEXT: _emscripten_glPolygonOffsetClampEXT,
- /** @export */ emscripten_glQueryCounterEXT: _emscripten_glQueryCounterEXT,
- /** @export */ emscripten_glReadPixels: _emscripten_glReadPixels,
- /** @export */ emscripten_glReleaseShaderCompiler: _emscripten_glReleaseShaderCompiler,
- /** @export */ emscripten_glRenderbufferStorage: _emscripten_glRenderbufferStorage,
- /** @export */ emscripten_glSampleCoverage: _emscripten_glSampleCoverage,
- /** @export */ emscripten_glScissor: _emscripten_glScissor,
- /** @export */ emscripten_glShaderBinary: _emscripten_glShaderBinary,
- /** @export */ emscripten_glShaderSource: _emscripten_glShaderSource,
- /** @export */ emscripten_glStencilFunc: _emscripten_glStencilFunc,
- /** @export */ emscripten_glStencilFuncSeparate: _emscripten_glStencilFuncSeparate,
- /** @export */ emscripten_glStencilMask: _emscripten_glStencilMask,
- /** @export */ emscripten_glStencilMaskSeparate: _emscripten_glStencilMaskSeparate,
- /** @export */ emscripten_glStencilOp: _emscripten_glStencilOp,
- /** @export */ emscripten_glStencilOpSeparate: _emscripten_glStencilOpSeparate,
- /** @export */ emscripten_glTexImage2D: _emscripten_glTexImage2D,
- /** @export */ emscripten_glTexParameterf: _emscripten_glTexParameterf,
- /** @export */ emscripten_glTexParameterfv: _emscripten_glTexParameterfv,
- /** @export */ emscripten_glTexParameteri: _emscripten_glTexParameteri,
- /** @export */ emscripten_glTexParameteriv: _emscripten_glTexParameteriv,
- /** @export */ emscripten_glTexSubImage2D: _emscripten_glTexSubImage2D,
- /** @export */ emscripten_glUniform1f: _emscripten_glUniform1f,
- /** @export */ emscripten_glUniform1fv: _emscripten_glUniform1fv,
- /** @export */ emscripten_glUniform1i: _emscripten_glUniform1i,
- /** @export */ emscripten_glUniform1iv: _emscripten_glUniform1iv,
- /** @export */ emscripten_glUniform2f: _emscripten_glUniform2f,
- /** @export */ emscripten_glUniform2fv: _emscripten_glUniform2fv,
- /** @export */ emscripten_glUniform2i: _emscripten_glUniform2i,
- /** @export */ emscripten_glUniform2iv: _emscripten_glUniform2iv,
- /** @export */ emscripten_glUniform3f: _emscripten_glUniform3f,
- /** @export */ emscripten_glUniform3fv: _emscripten_glUniform3fv,
- /** @export */ emscripten_glUniform3i: _emscripten_glUniform3i,
- /** @export */ emscripten_glUniform3iv: _emscripten_glUniform3iv,
- /** @export */ emscripten_glUniform4f: _emscripten_glUniform4f,
- /** @export */ emscripten_glUniform4fv: _emscripten_glUniform4fv,
- /** @export */ emscripten_glUniform4i: _emscripten_glUniform4i,
- /** @export */ emscripten_glUniform4iv: _emscripten_glUniform4iv,
- /** @export */ emscripten_glUniformMatrix2fv: _emscripten_glUniformMatrix2fv,
- /** @export */ emscripten_glUniformMatrix3fv: _emscripten_glUniformMatrix3fv,
- /** @export */ emscripten_glUniformMatrix4fv: _emscripten_glUniformMatrix4fv,
- /** @export */ emscripten_glUseProgram: _emscripten_glUseProgram,
- /** @export */ emscripten_glValidateProgram: _emscripten_glValidateProgram,
- /** @export */ emscripten_glVertexAttrib1f: _emscripten_glVertexAttrib1f,
- /** @export */ emscripten_glVertexAttrib1fv: _emscripten_glVertexAttrib1fv,
- /** @export */ emscripten_glVertexAttrib2f: _emscripten_glVertexAttrib2f,
- /** @export */ emscripten_glVertexAttrib2fv: _emscripten_glVertexAttrib2fv,
- /** @export */ emscripten_glVertexAttrib3f: _emscripten_glVertexAttrib3f,
- /** @export */ emscripten_glVertexAttrib3fv: _emscripten_glVertexAttrib3fv,
- /** @export */ emscripten_glVertexAttrib4f: _emscripten_glVertexAttrib4f,
- /** @export */ emscripten_glVertexAttrib4fv: _emscripten_glVertexAttrib4fv,
- /** @export */ emscripten_glVertexAttribDivisorANGLE: _emscripten_glVertexAttribDivisorANGLE,
- /** @export */ emscripten_glVertexAttribPointer: _emscripten_glVertexAttribPointer,
- /** @export */ emscripten_glViewport: _emscripten_glViewport,
- /** @export */ emscripten_has_asyncify: _emscripten_has_asyncify,
- /** @export */ emscripten_request_fullscreen_strategy: _emscripten_request_fullscreen_strategy,
- /** @export */ emscripten_request_pointerlock: _emscripten_request_pointerlock,
- /** @export */ emscripten_resize_heap: _emscripten_resize_heap,
- /** @export */ emscripten_sample_gamepad_data: _emscripten_sample_gamepad_data,
- /** @export */ emscripten_set_beforeunload_callback_on_thread: _emscripten_set_beforeunload_callback_on_thread,
- /** @export */ emscripten_set_blur_callback_on_thread: _emscripten_set_blur_callback_on_thread,
- /** @export */ emscripten_set_canvas_element_size: _emscripten_set_canvas_element_size,
- /** @export */ emscripten_set_element_css_size: _emscripten_set_element_css_size,
- /** @export */ emscripten_set_focus_callback_on_thread: _emscripten_set_focus_callback_on_thread,
- /** @export */ emscripten_set_fullscreenchange_callback_on_thread: _emscripten_set_fullscreenchange_callback_on_thread,
- /** @export */ emscripten_set_gamepadconnected_callback_on_thread: _emscripten_set_gamepadconnected_callback_on_thread,
- /** @export */ emscripten_set_gamepaddisconnected_callback_on_thread: _emscripten_set_gamepaddisconnected_callback_on_thread,
- /** @export */ emscripten_set_keydown_callback_on_thread: _emscripten_set_keydown_callback_on_thread,
- /** @export */ emscripten_set_keypress_callback_on_thread: _emscripten_set_keypress_callback_on_thread,
- /** @export */ emscripten_set_keyup_callback_on_thread: _emscripten_set_keyup_callback_on_thread,
- /** @export */ emscripten_set_main_loop: _emscripten_set_main_loop,
- /** @export */ emscripten_set_mousedown_callback_on_thread: _emscripten_set_mousedown_callback_on_thread,
- /** @export */ emscripten_set_mouseenter_callback_on_thread: _emscripten_set_mouseenter_callback_on_thread,
- /** @export */ emscripten_set_mouseleave_callback_on_thread: _emscripten_set_mouseleave_callback_on_thread,
- /** @export */ emscripten_set_mousemove_callback_on_thread: _emscripten_set_mousemove_callback_on_thread,
- /** @export */ emscripten_set_mouseup_callback_on_thread: _emscripten_set_mouseup_callback_on_thread,
- /** @export */ emscripten_set_pointerlockchange_callback_on_thread: _emscripten_set_pointerlockchange_callback_on_thread,
- /** @export */ emscripten_set_resize_callback_on_thread: _emscripten_set_resize_callback_on_thread,
- /** @export */ emscripten_set_touchcancel_callback_on_thread: _emscripten_set_touchcancel_callback_on_thread,
- /** @export */ emscripten_set_touchend_callback_on_thread: _emscripten_set_touchend_callback_on_thread,
- /** @export */ emscripten_set_touchmove_callback_on_thread: _emscripten_set_touchmove_callback_on_thread,
- /** @export */ emscripten_set_touchstart_callback_on_thread: _emscripten_set_touchstart_callback_on_thread,
- /** @export */ emscripten_set_visibilitychange_callback_on_thread: _emscripten_set_visibilitychange_callback_on_thread,
- /** @export */ emscripten_set_wheel_callback_on_thread: _emscripten_set_wheel_callback_on_thread,
- /** @export */ emscripten_set_window_title: _emscripten_set_window_title,
- /** @export */ emscripten_sleep: _emscripten_sleep,
- /** @export */ environ_get: _environ_get,
- /** @export */ environ_sizes_get: _environ_sizes_get,
- /** @export */ exit: _exit,
- /** @export */ fd_close: _fd_close,
- /** @export */ fd_read: _fd_read,
- /** @export */ fd_seek: _fd_seek,
- /** @export */ fd_write: _fd_write,
- /** @export */ memory: wasmMemory,
- /** @export */ posix_spawnp: _posix_spawnp,
- /** @export */ proc_exit: _proc_exit
- };
- }
- // include: postamble.js
- // === Auto-generated postamble setup entry stuff ===
- var calledRun;
- function callMain(args = []) {
- assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
- assert(typeof onPreRuns === "undefined" || onPreRuns.length == 0, "cannot call main when preRun functions remain to be called");
- var entryFunction = _main;
- args.unshift(thisProgram);
- var argc = args.length;
- var argv = stackAlloc((argc + 1) * 4);
- var argv_ptr = argv;
- for (var arg of args) {
- (growMemViews(), HEAPU32)[((argv_ptr) >> 2)] = stringToUTF8OnStack(arg);
- argv_ptr += 4;
- }
- (growMemViews(), HEAPU32)[((argv_ptr) >> 2)] = 0;
- try {
- var ret = entryFunction(argc, argv);
- // if we're not running an evented main loop, it's time to exit
- exitJS(ret, /* implicit = */ true);
- return ret;
- } catch (e) {
- return handleException(e);
- }
- }
- function stackCheckInit() {
- // This is normally called automatically during __wasm_call_ctors but need to
- // get these values before even running any of the ctors so we call it redundantly
- // here.
- // See $establishStackSpace for the equivalent code that runs on a thread
- assert(!ENVIRONMENT_IS_PTHREAD);
- _emscripten_stack_init();
- // TODO(sbc): Move writeStackCookie to native to to avoid this.
- writeStackCookie();
- }
- async function run(args = programArgs) {
- assert(!calledRun);
- calledRun = true;
- if ((ENVIRONMENT_IS_PTHREAD)) {
- initRuntime();
- return;
- }
- stackCheckInit();
- preRun();
- if (runDependencies) {
- await resolveRunDependencies();
- }
- var setStatus = Module["setStatus"];
- if (setStatus) {
- setStatus("Running...");
- // Yield to the event loop to allow the browser to paint "Running..."
- await new Promise(resolve => setTimeout(resolve, 1));
- // Then we want to clear the status text, but only after the rest of this function runs.
- setTimeout(setStatus, 1, "");
- }
- if (ABORT) return;
- initRuntime();
- // No ATMAINS hooks
- Module["onRuntimeInitialized"]?.();
- consumedModuleProp("onRuntimeInitialized");
- var noInitialRun = Module["noInitialRun"] || false;
- if (!noInitialRun) callMain(args);
- postRun();
- }
- function checkUnflushedContent() {
- // Compiler settings do not allow exiting the runtime, so flushing
- // the streams is not possible. but in ASSERTIONS mode we check
- // if there was something to flush, and if so tell the user they
- // should request that the runtime be exitable.
- // Normally we would not even include flush() at all, but in ASSERTIONS
- // builds we do so just for this check, and here we see if there is any
- // content to flush, that is, we check if there would have been
- // something a non-ASSERTIONS build would have not seen.
- // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0
- // mode (which has its own special function for this; otherwise, all
- // the code is inside libc)
- var oldOut = out;
- var oldErr = err;
- var has = false;
- out = err = x => {
- has = true;
- };
- try {
- // it doesn't matter if it fails
- _fflush(0);
- // also flush in the JS FS layer
- for (var name of [ "stdout", "stderr" ]) {
- var info = FS.analyzePath("/dev/" + name);
- if (!info) return;
- var stream = info.object;
- var rdev = stream.rdev;
- var tty = TTY.ttys[rdev];
- if (tty?.output?.length) {
- has = true;
- }
- }
- } catch (e) {}
- out = oldOut;
- err = oldErr;
- if (has) {
- warnOnce("stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the Emscripten FAQ), or make sure to emit a newline when you printf etc.");
- }
- }
- var wasmExports;
- if ((!(ENVIRONMENT_IS_PTHREAD))) {
- // Call createWasm on startup if we are the main thread.
- // Worker threads call this once they receive the module via postMessage
- // With async instantation wasmExports is assigned asynchronously when the
- // instance is received.
- createWasm().then(() => run());
- }
|