napi-inl.h 159 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998
  1. #ifndef SRC_NAPI_INL_H_
  2. #define SRC_NAPI_INL_H_
  3. ////////////////////////////////////////////////////////////////////////////////
  4. // N-API C++ Wrapper Classes
  5. //
  6. // Inline header-only implementations for "N-API" ABI-stable C APIs for Node.js.
  7. ////////////////////////////////////////////////////////////////////////////////
  8. // Note: Do not include this file directly! Include "napi.h" instead.
  9. #include <algorithm>
  10. #include <cstring>
  11. #include <mutex>
  12. #include <type_traits>
  13. namespace Napi {
  14. // Helpers to handle functions exposed from C++.
  15. namespace details {
  16. // Attach a data item to an object and delete it when the object gets
  17. // garbage-collected.
  18. // TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
  19. // available on all supported versions of Node.js.
  20. template <typename FreeType>
  21. static inline napi_status AttachData(napi_env env,
  22. napi_value obj,
  23. FreeType* data,
  24. napi_finalize finalizer = nullptr,
  25. void* hint = nullptr) {
  26. napi_status status;
  27. if (finalizer == nullptr) {
  28. finalizer = [](napi_env /*env*/, void* data, void* /*hint*/) {
  29. delete static_cast<FreeType*>(data);
  30. };
  31. }
  32. #if (NAPI_VERSION < 5)
  33. napi_value symbol, external;
  34. status = napi_create_symbol(env, nullptr, &symbol);
  35. if (status == napi_ok) {
  36. status = napi_create_external(env,
  37. data,
  38. finalizer,
  39. hint,
  40. &external);
  41. if (status == napi_ok) {
  42. napi_property_descriptor desc = {
  43. nullptr,
  44. symbol,
  45. nullptr,
  46. nullptr,
  47. nullptr,
  48. external,
  49. napi_default,
  50. nullptr
  51. };
  52. status = napi_define_properties(env, obj, 1, &desc);
  53. }
  54. }
  55. #else // NAPI_VERSION >= 5
  56. status = napi_add_finalizer(env, obj, data, finalizer, hint, nullptr);
  57. #endif
  58. return status;
  59. }
  60. // For use in JS to C++ callback wrappers to catch any Napi::Error exceptions
  61. // and rethrow them as JavaScript exceptions before returning from the callback.
  62. template <typename Callable>
  63. inline napi_value WrapCallback(Callable callback) {
  64. #ifdef NAPI_CPP_EXCEPTIONS
  65. try {
  66. return callback();
  67. } catch (const Error& e) {
  68. e.ThrowAsJavaScriptException();
  69. return nullptr;
  70. }
  71. #else // NAPI_CPP_EXCEPTIONS
  72. // When C++ exceptions are disabled, errors are immediately thrown as JS
  73. // exceptions, so there is no need to catch and rethrow them here.
  74. return callback();
  75. #endif // NAPI_CPP_EXCEPTIONS
  76. }
  77. template <typename Callable, typename Return>
  78. struct CallbackData {
  79. static inline
  80. napi_value Wrapper(napi_env env, napi_callback_info info) {
  81. return details::WrapCallback([&] {
  82. CallbackInfo callbackInfo(env, info);
  83. CallbackData* callbackData =
  84. static_cast<CallbackData*>(callbackInfo.Data());
  85. callbackInfo.SetData(callbackData->data);
  86. return callbackData->callback(callbackInfo);
  87. });
  88. }
  89. Callable callback;
  90. void* data;
  91. };
  92. template <typename Callable>
  93. struct CallbackData<Callable, void> {
  94. static inline
  95. napi_value Wrapper(napi_env env, napi_callback_info info) {
  96. return details::WrapCallback([&] {
  97. CallbackInfo callbackInfo(env, info);
  98. CallbackData* callbackData =
  99. static_cast<CallbackData*>(callbackInfo.Data());
  100. callbackInfo.SetData(callbackData->data);
  101. callbackData->callback(callbackInfo);
  102. return nullptr;
  103. });
  104. }
  105. Callable callback;
  106. void* data;
  107. };
  108. template <typename T, typename Finalizer, typename Hint = void>
  109. struct FinalizeData {
  110. static inline
  111. void Wrapper(napi_env env, void* data, void* finalizeHint) {
  112. FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
  113. finalizeData->callback(Env(env), static_cast<T*>(data));
  114. delete finalizeData;
  115. }
  116. static inline
  117. void WrapperWithHint(napi_env env, void* data, void* finalizeHint) {
  118. FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
  119. finalizeData->callback(Env(env), static_cast<T*>(data), finalizeData->hint);
  120. delete finalizeData;
  121. }
  122. Finalizer callback;
  123. Hint* hint;
  124. };
  125. #if (NAPI_VERSION > 3)
  126. template <typename ContextType=void,
  127. typename Finalizer=std::function<void(Env, void*, ContextType*)>,
  128. typename FinalizerDataType=void>
  129. struct ThreadSafeFinalize {
  130. static inline
  131. void Wrapper(napi_env env, void* rawFinalizeData, void* /* rawContext */) {
  132. if (rawFinalizeData == nullptr)
  133. return;
  134. ThreadSafeFinalize* finalizeData =
  135. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  136. finalizeData->callback(Env(env));
  137. delete finalizeData;
  138. }
  139. static inline
  140. void FinalizeWrapperWithData(napi_env env,
  141. void* rawFinalizeData,
  142. void* /* rawContext */) {
  143. if (rawFinalizeData == nullptr)
  144. return;
  145. ThreadSafeFinalize* finalizeData =
  146. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  147. finalizeData->callback(Env(env), finalizeData->data);
  148. delete finalizeData;
  149. }
  150. static inline
  151. void FinalizeWrapperWithContext(napi_env env,
  152. void* rawFinalizeData,
  153. void* rawContext) {
  154. if (rawFinalizeData == nullptr)
  155. return;
  156. ThreadSafeFinalize* finalizeData =
  157. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  158. finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
  159. delete finalizeData;
  160. }
  161. static inline
  162. void FinalizeFinalizeWrapperWithDataAndContext(napi_env env,
  163. void* rawFinalizeData,
  164. void* rawContext) {
  165. if (rawFinalizeData == nullptr)
  166. return;
  167. ThreadSafeFinalize* finalizeData =
  168. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  169. finalizeData->callback(Env(env), finalizeData->data,
  170. static_cast<ContextType*>(rawContext));
  171. delete finalizeData;
  172. }
  173. FinalizerDataType* data;
  174. Finalizer callback;
  175. };
  176. #endif
  177. template <typename Getter, typename Setter>
  178. struct AccessorCallbackData {
  179. static inline
  180. napi_value GetterWrapper(napi_env env, napi_callback_info info) {
  181. return details::WrapCallback([&] {
  182. CallbackInfo callbackInfo(env, info);
  183. AccessorCallbackData* callbackData =
  184. static_cast<AccessorCallbackData*>(callbackInfo.Data());
  185. callbackInfo.SetData(callbackData->data);
  186. return callbackData->getterCallback(callbackInfo);
  187. });
  188. }
  189. static inline
  190. napi_value SetterWrapper(napi_env env, napi_callback_info info) {
  191. return details::WrapCallback([&] {
  192. CallbackInfo callbackInfo(env, info);
  193. AccessorCallbackData* callbackData =
  194. static_cast<AccessorCallbackData*>(callbackInfo.Data());
  195. callbackInfo.SetData(callbackData->data);
  196. callbackData->setterCallback(callbackInfo);
  197. return nullptr;
  198. });
  199. }
  200. Getter getterCallback;
  201. Setter setterCallback;
  202. void* data;
  203. };
  204. } // namespace details
  205. #ifndef NODE_ADDON_API_DISABLE_DEPRECATED
  206. # include "napi-inl.deprecated.h"
  207. #endif // !NODE_ADDON_API_DISABLE_DEPRECATED
  208. ////////////////////////////////////////////////////////////////////////////////
  209. // Module registration
  210. ////////////////////////////////////////////////////////////////////////////////
  211. #define NODE_API_MODULE(modname, regfunc) \
  212. napi_value __napi_ ## regfunc(napi_env env, \
  213. napi_value exports) { \
  214. return Napi::RegisterModule(env, exports, regfunc); \
  215. } \
  216. NAPI_MODULE(modname, __napi_ ## regfunc)
  217. // Adapt the NAPI_MODULE registration function:
  218. // - Wrap the arguments in NAPI wrappers.
  219. // - Catch any NAPI errors and rethrow as JS exceptions.
  220. inline napi_value RegisterModule(napi_env env,
  221. napi_value exports,
  222. ModuleRegisterCallback registerCallback) {
  223. return details::WrapCallback([&] {
  224. return napi_value(registerCallback(Napi::Env(env),
  225. Napi::Object(env, exports)));
  226. });
  227. }
  228. ////////////////////////////////////////////////////////////////////////////////
  229. // Env class
  230. ////////////////////////////////////////////////////////////////////////////////
  231. inline Env::Env(napi_env env) : _env(env) {
  232. }
  233. inline Env::operator napi_env() const {
  234. return _env;
  235. }
  236. inline Object Env::Global() const {
  237. napi_value value;
  238. napi_status status = napi_get_global(*this, &value);
  239. NAPI_THROW_IF_FAILED(*this, status, Object());
  240. return Object(*this, value);
  241. }
  242. inline Value Env::Undefined() const {
  243. napi_value value;
  244. napi_status status = napi_get_undefined(*this, &value);
  245. NAPI_THROW_IF_FAILED(*this, status, Value());
  246. return Value(*this, value);
  247. }
  248. inline Value Env::Null() const {
  249. napi_value value;
  250. napi_status status = napi_get_null(*this, &value);
  251. NAPI_THROW_IF_FAILED(*this, status, Value());
  252. return Value(*this, value);
  253. }
  254. inline bool Env::IsExceptionPending() const {
  255. bool result;
  256. napi_status status = napi_is_exception_pending(_env, &result);
  257. if (status != napi_ok) result = false; // Checking for a pending exception shouldn't throw.
  258. return result;
  259. }
  260. inline Error Env::GetAndClearPendingException() {
  261. napi_value value;
  262. napi_status status = napi_get_and_clear_last_exception(_env, &value);
  263. if (status != napi_ok) {
  264. // Don't throw another exception when failing to get the exception!
  265. return Error();
  266. }
  267. return Error(_env, value);
  268. }
  269. inline Value Env::RunScript(const char* utf8script) {
  270. String script = String::New(_env, utf8script);
  271. return RunScript(script);
  272. }
  273. inline Value Env::RunScript(const std::string& utf8script) {
  274. return RunScript(utf8script.c_str());
  275. }
  276. inline Value Env::RunScript(String script) {
  277. napi_value result;
  278. napi_status status = napi_run_script(_env, script, &result);
  279. NAPI_THROW_IF_FAILED(_env, status, Undefined());
  280. return Value(_env, result);
  281. }
  282. #if NAPI_VERSION > 5
  283. template <typename T, Env::Finalizer<T> fini>
  284. inline void Env::SetInstanceData(T* data) {
  285. napi_status status =
  286. napi_set_instance_data(_env, data, [](napi_env env, void* data, void*) {
  287. fini(env, static_cast<T*>(data));
  288. }, nullptr);
  289. NAPI_THROW_IF_FAILED_VOID(_env, status);
  290. }
  291. template <typename DataType,
  292. typename HintType,
  293. Napi::Env::FinalizerWithHint<DataType, HintType> fini>
  294. inline void Env::SetInstanceData(DataType* data, HintType* hint) {
  295. napi_status status =
  296. napi_set_instance_data(_env, data,
  297. [](napi_env env, void* data, void* hint) {
  298. fini(env, static_cast<DataType*>(data), static_cast<HintType*>(hint));
  299. }, hint);
  300. NAPI_THROW_IF_FAILED_VOID(_env, status);
  301. }
  302. template <typename T>
  303. inline T* Env::GetInstanceData() {
  304. void* data = nullptr;
  305. napi_status status = napi_get_instance_data(_env, &data);
  306. NAPI_THROW_IF_FAILED(_env, status, nullptr);
  307. return static_cast<T*>(data);
  308. }
  309. template <typename T> void Env::DefaultFini(Env, T* data) {
  310. delete data;
  311. }
  312. template <typename DataType, typename HintType>
  313. void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) {
  314. delete data;
  315. }
  316. #endif // NAPI_VERSION > 5
  317. ////////////////////////////////////////////////////////////////////////////////
  318. // Value class
  319. ////////////////////////////////////////////////////////////////////////////////
  320. inline Value::Value() : _env(nullptr), _value(nullptr) {
  321. }
  322. inline Value::Value(napi_env env, napi_value value) : _env(env), _value(value) {
  323. }
  324. inline Value::operator napi_value() const {
  325. return _value;
  326. }
  327. inline bool Value::operator ==(const Value& other) const {
  328. return StrictEquals(other);
  329. }
  330. inline bool Value::operator !=(const Value& other) const {
  331. return !this->operator ==(other);
  332. }
  333. inline bool Value::StrictEquals(const Value& other) const {
  334. bool result;
  335. napi_status status = napi_strict_equals(_env, *this, other, &result);
  336. NAPI_THROW_IF_FAILED(_env, status, false);
  337. return result;
  338. }
  339. inline Napi::Env Value::Env() const {
  340. return Napi::Env(_env);
  341. }
  342. inline bool Value::IsEmpty() const {
  343. return _value == nullptr;
  344. }
  345. inline napi_valuetype Value::Type() const {
  346. if (IsEmpty()) {
  347. return napi_undefined;
  348. }
  349. napi_valuetype type;
  350. napi_status status = napi_typeof(_env, _value, &type);
  351. NAPI_THROW_IF_FAILED(_env, status, napi_undefined);
  352. return type;
  353. }
  354. inline bool Value::IsUndefined() const {
  355. return Type() == napi_undefined;
  356. }
  357. inline bool Value::IsNull() const {
  358. return Type() == napi_null;
  359. }
  360. inline bool Value::IsBoolean() const {
  361. return Type() == napi_boolean;
  362. }
  363. inline bool Value::IsNumber() const {
  364. return Type() == napi_number;
  365. }
  366. #if NAPI_VERSION > 5
  367. inline bool Value::IsBigInt() const {
  368. return Type() == napi_bigint;
  369. }
  370. #endif // NAPI_VERSION > 5
  371. #if (NAPI_VERSION > 4)
  372. inline bool Value::IsDate() const {
  373. if (IsEmpty()) {
  374. return false;
  375. }
  376. bool result;
  377. napi_status status = napi_is_date(_env, _value, &result);
  378. NAPI_THROW_IF_FAILED(_env, status, false);
  379. return result;
  380. }
  381. #endif
  382. inline bool Value::IsString() const {
  383. return Type() == napi_string;
  384. }
  385. inline bool Value::IsSymbol() const {
  386. return Type() == napi_symbol;
  387. }
  388. inline bool Value::IsArray() const {
  389. if (IsEmpty()) {
  390. return false;
  391. }
  392. bool result;
  393. napi_status status = napi_is_array(_env, _value, &result);
  394. NAPI_THROW_IF_FAILED(_env, status, false);
  395. return result;
  396. }
  397. inline bool Value::IsArrayBuffer() const {
  398. if (IsEmpty()) {
  399. return false;
  400. }
  401. bool result;
  402. napi_status status = napi_is_arraybuffer(_env, _value, &result);
  403. NAPI_THROW_IF_FAILED(_env, status, false);
  404. return result;
  405. }
  406. inline bool Value::IsTypedArray() const {
  407. if (IsEmpty()) {
  408. return false;
  409. }
  410. bool result;
  411. napi_status status = napi_is_typedarray(_env, _value, &result);
  412. NAPI_THROW_IF_FAILED(_env, status, false);
  413. return result;
  414. }
  415. inline bool Value::IsObject() const {
  416. return Type() == napi_object || IsFunction();
  417. }
  418. inline bool Value::IsFunction() const {
  419. return Type() == napi_function;
  420. }
  421. inline bool Value::IsPromise() const {
  422. if (IsEmpty()) {
  423. return false;
  424. }
  425. bool result;
  426. napi_status status = napi_is_promise(_env, _value, &result);
  427. NAPI_THROW_IF_FAILED(_env, status, false);
  428. return result;
  429. }
  430. inline bool Value::IsDataView() const {
  431. if (IsEmpty()) {
  432. return false;
  433. }
  434. bool result;
  435. napi_status status = napi_is_dataview(_env, _value, &result);
  436. NAPI_THROW_IF_FAILED(_env, status, false);
  437. return result;
  438. }
  439. inline bool Value::IsBuffer() const {
  440. if (IsEmpty()) {
  441. return false;
  442. }
  443. bool result;
  444. napi_status status = napi_is_buffer(_env, _value, &result);
  445. NAPI_THROW_IF_FAILED(_env, status, false);
  446. return result;
  447. }
  448. inline bool Value::IsExternal() const {
  449. return Type() == napi_external;
  450. }
  451. template <typename T>
  452. inline T Value::As() const {
  453. return T(_env, _value);
  454. }
  455. inline Boolean Value::ToBoolean() const {
  456. napi_value result;
  457. napi_status status = napi_coerce_to_bool(_env, _value, &result);
  458. NAPI_THROW_IF_FAILED(_env, status, Boolean());
  459. return Boolean(_env, result);
  460. }
  461. inline Number Value::ToNumber() const {
  462. napi_value result;
  463. napi_status status = napi_coerce_to_number(_env, _value, &result);
  464. NAPI_THROW_IF_FAILED(_env, status, Number());
  465. return Number(_env, result);
  466. }
  467. inline String Value::ToString() const {
  468. napi_value result;
  469. napi_status status = napi_coerce_to_string(_env, _value, &result);
  470. NAPI_THROW_IF_FAILED(_env, status, String());
  471. return String(_env, result);
  472. }
  473. inline Object Value::ToObject() const {
  474. napi_value result;
  475. napi_status status = napi_coerce_to_object(_env, _value, &result);
  476. NAPI_THROW_IF_FAILED(_env, status, Object());
  477. return Object(_env, result);
  478. }
  479. ////////////////////////////////////////////////////////////////////////////////
  480. // Boolean class
  481. ////////////////////////////////////////////////////////////////////////////////
  482. inline Boolean Boolean::New(napi_env env, bool val) {
  483. napi_value value;
  484. napi_status status = napi_get_boolean(env, val, &value);
  485. NAPI_THROW_IF_FAILED(env, status, Boolean());
  486. return Boolean(env, value);
  487. }
  488. inline Boolean::Boolean() : Napi::Value() {
  489. }
  490. inline Boolean::Boolean(napi_env env, napi_value value) : Napi::Value(env, value) {
  491. }
  492. inline Boolean::operator bool() const {
  493. return Value();
  494. }
  495. inline bool Boolean::Value() const {
  496. bool result;
  497. napi_status status = napi_get_value_bool(_env, _value, &result);
  498. NAPI_THROW_IF_FAILED(_env, status, false);
  499. return result;
  500. }
  501. ////////////////////////////////////////////////////////////////////////////////
  502. // Number class
  503. ////////////////////////////////////////////////////////////////////////////////
  504. inline Number Number::New(napi_env env, double val) {
  505. napi_value value;
  506. napi_status status = napi_create_double(env, val, &value);
  507. NAPI_THROW_IF_FAILED(env, status, Number());
  508. return Number(env, value);
  509. }
  510. inline Number::Number() : Value() {
  511. }
  512. inline Number::Number(napi_env env, napi_value value) : Value(env, value) {
  513. }
  514. inline Number::operator int32_t() const {
  515. return Int32Value();
  516. }
  517. inline Number::operator uint32_t() const {
  518. return Uint32Value();
  519. }
  520. inline Number::operator int64_t() const {
  521. return Int64Value();
  522. }
  523. inline Number::operator float() const {
  524. return FloatValue();
  525. }
  526. inline Number::operator double() const {
  527. return DoubleValue();
  528. }
  529. inline int32_t Number::Int32Value() const {
  530. int32_t result;
  531. napi_status status = napi_get_value_int32(_env, _value, &result);
  532. NAPI_THROW_IF_FAILED(_env, status, 0);
  533. return result;
  534. }
  535. inline uint32_t Number::Uint32Value() const {
  536. uint32_t result;
  537. napi_status status = napi_get_value_uint32(_env, _value, &result);
  538. NAPI_THROW_IF_FAILED(_env, status, 0);
  539. return result;
  540. }
  541. inline int64_t Number::Int64Value() const {
  542. int64_t result;
  543. napi_status status = napi_get_value_int64(_env, _value, &result);
  544. NAPI_THROW_IF_FAILED(_env, status, 0);
  545. return result;
  546. }
  547. inline float Number::FloatValue() const {
  548. return static_cast<float>(DoubleValue());
  549. }
  550. inline double Number::DoubleValue() const {
  551. double result;
  552. napi_status status = napi_get_value_double(_env, _value, &result);
  553. NAPI_THROW_IF_FAILED(_env, status, 0);
  554. return result;
  555. }
  556. #if NAPI_VERSION > 5
  557. ////////////////////////////////////////////////////////////////////////////////
  558. // BigInt Class
  559. ////////////////////////////////////////////////////////////////////////////////
  560. inline BigInt BigInt::New(napi_env env, int64_t val) {
  561. napi_value value;
  562. napi_status status = napi_create_bigint_int64(env, val, &value);
  563. NAPI_THROW_IF_FAILED(env, status, BigInt());
  564. return BigInt(env, value);
  565. }
  566. inline BigInt BigInt::New(napi_env env, uint64_t val) {
  567. napi_value value;
  568. napi_status status = napi_create_bigint_uint64(env, val, &value);
  569. NAPI_THROW_IF_FAILED(env, status, BigInt());
  570. return BigInt(env, value);
  571. }
  572. inline BigInt BigInt::New(napi_env env, int sign_bit, size_t word_count, const uint64_t* words) {
  573. napi_value value;
  574. napi_status status = napi_create_bigint_words(env, sign_bit, word_count, words, &value);
  575. NAPI_THROW_IF_FAILED(env, status, BigInt());
  576. return BigInt(env, value);
  577. }
  578. inline BigInt::BigInt() : Value() {
  579. }
  580. inline BigInt::BigInt(napi_env env, napi_value value) : Value(env, value) {
  581. }
  582. inline int64_t BigInt::Int64Value(bool* lossless) const {
  583. int64_t result;
  584. napi_status status = napi_get_value_bigint_int64(
  585. _env, _value, &result, lossless);
  586. NAPI_THROW_IF_FAILED(_env, status, 0);
  587. return result;
  588. }
  589. inline uint64_t BigInt::Uint64Value(bool* lossless) const {
  590. uint64_t result;
  591. napi_status status = napi_get_value_bigint_uint64(
  592. _env, _value, &result, lossless);
  593. NAPI_THROW_IF_FAILED(_env, status, 0);
  594. return result;
  595. }
  596. inline size_t BigInt::WordCount() const {
  597. size_t word_count;
  598. napi_status status = napi_get_value_bigint_words(
  599. _env, _value, nullptr, &word_count, nullptr);
  600. NAPI_THROW_IF_FAILED(_env, status, 0);
  601. return word_count;
  602. }
  603. inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words) {
  604. napi_status status = napi_get_value_bigint_words(
  605. _env, _value, sign_bit, word_count, words);
  606. NAPI_THROW_IF_FAILED_VOID(_env, status);
  607. }
  608. #endif // NAPI_VERSION > 5
  609. #if (NAPI_VERSION > 4)
  610. ////////////////////////////////////////////////////////////////////////////////
  611. // Date Class
  612. ////////////////////////////////////////////////////////////////////////////////
  613. inline Date Date::New(napi_env env, double val) {
  614. napi_value value;
  615. napi_status status = napi_create_date(env, val, &value);
  616. NAPI_THROW_IF_FAILED(env, status, Date());
  617. return Date(env, value);
  618. }
  619. inline Date::Date() : Value() {
  620. }
  621. inline Date::Date(napi_env env, napi_value value) : Value(env, value) {
  622. }
  623. inline Date::operator double() const {
  624. return ValueOf();
  625. }
  626. inline double Date::ValueOf() const {
  627. double result;
  628. napi_status status = napi_get_date_value(
  629. _env, _value, &result);
  630. NAPI_THROW_IF_FAILED(_env, status, 0);
  631. return result;
  632. }
  633. #endif
  634. ////////////////////////////////////////////////////////////////////////////////
  635. // Name class
  636. ////////////////////////////////////////////////////////////////////////////////
  637. inline Name::Name() : Value() {
  638. }
  639. inline Name::Name(napi_env env, napi_value value) : Value(env, value) {
  640. }
  641. ////////////////////////////////////////////////////////////////////////////////
  642. // String class
  643. ////////////////////////////////////////////////////////////////////////////////
  644. inline String String::New(napi_env env, const std::string& val) {
  645. return String::New(env, val.c_str(), val.size());
  646. }
  647. inline String String::New(napi_env env, const std::u16string& val) {
  648. return String::New(env, val.c_str(), val.size());
  649. }
  650. inline String String::New(napi_env env, const char* val) {
  651. napi_value value;
  652. napi_status status = napi_create_string_utf8(env, val, std::strlen(val), &value);
  653. NAPI_THROW_IF_FAILED(env, status, String());
  654. return String(env, value);
  655. }
  656. inline String String::New(napi_env env, const char16_t* val) {
  657. napi_value value;
  658. napi_status status = napi_create_string_utf16(env, val, std::u16string(val).size(), &value);
  659. NAPI_THROW_IF_FAILED(env, status, String());
  660. return String(env, value);
  661. }
  662. inline String String::New(napi_env env, const char* val, size_t length) {
  663. napi_value value;
  664. napi_status status = napi_create_string_utf8(env, val, length, &value);
  665. NAPI_THROW_IF_FAILED(env, status, String());
  666. return String(env, value);
  667. }
  668. inline String String::New(napi_env env, const char16_t* val, size_t length) {
  669. napi_value value;
  670. napi_status status = napi_create_string_utf16(env, val, length, &value);
  671. NAPI_THROW_IF_FAILED(env, status, String());
  672. return String(env, value);
  673. }
  674. inline String::String() : Name() {
  675. }
  676. inline String::String(napi_env env, napi_value value) : Name(env, value) {
  677. }
  678. inline String::operator std::string() const {
  679. return Utf8Value();
  680. }
  681. inline String::operator std::u16string() const {
  682. return Utf16Value();
  683. }
  684. inline std::string String::Utf8Value() const {
  685. size_t length;
  686. napi_status status = napi_get_value_string_utf8(_env, _value, nullptr, 0, &length);
  687. NAPI_THROW_IF_FAILED(_env, status, "");
  688. std::string value;
  689. value.reserve(length + 1);
  690. value.resize(length);
  691. status = napi_get_value_string_utf8(_env, _value, &value[0], value.capacity(), nullptr);
  692. NAPI_THROW_IF_FAILED(_env, status, "");
  693. return value;
  694. }
  695. inline std::u16string String::Utf16Value() const {
  696. size_t length;
  697. napi_status status = napi_get_value_string_utf16(_env, _value, nullptr, 0, &length);
  698. NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT(""));
  699. std::u16string value;
  700. value.reserve(length + 1);
  701. value.resize(length);
  702. status = napi_get_value_string_utf16(_env, _value, &value[0], value.capacity(), nullptr);
  703. NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT(""));
  704. return value;
  705. }
  706. ////////////////////////////////////////////////////////////////////////////////
  707. // Symbol class
  708. ////////////////////////////////////////////////////////////////////////////////
  709. inline Symbol Symbol::New(napi_env env, const char* description) {
  710. napi_value descriptionValue = description != nullptr ?
  711. String::New(env, description) : static_cast<napi_value>(nullptr);
  712. return Symbol::New(env, descriptionValue);
  713. }
  714. inline Symbol Symbol::New(napi_env env, const std::string& description) {
  715. napi_value descriptionValue = String::New(env, description);
  716. return Symbol::New(env, descriptionValue);
  717. }
  718. inline Symbol Symbol::New(napi_env env, String description) {
  719. napi_value descriptionValue = description;
  720. return Symbol::New(env, descriptionValue);
  721. }
  722. inline Symbol Symbol::New(napi_env env, napi_value description) {
  723. napi_value value;
  724. napi_status status = napi_create_symbol(env, description, &value);
  725. NAPI_THROW_IF_FAILED(env, status, Symbol());
  726. return Symbol(env, value);
  727. }
  728. inline Symbol Symbol::WellKnown(napi_env env, const std::string& name) {
  729. return Napi::Env(env).Global().Get("Symbol").As<Object>().Get(name).As<Symbol>();
  730. }
  731. inline Symbol::Symbol() : Name() {
  732. }
  733. inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) {
  734. }
  735. ////////////////////////////////////////////////////////////////////////////////
  736. // Automagic value creation
  737. ////////////////////////////////////////////////////////////////////////////////
  738. namespace details {
  739. template <typename T>
  740. struct vf_number {
  741. static Number From(napi_env env, T value) {
  742. return Number::New(env, static_cast<double>(value));
  743. }
  744. };
  745. template<>
  746. struct vf_number<bool> {
  747. static Boolean From(napi_env env, bool value) {
  748. return Boolean::New(env, value);
  749. }
  750. };
  751. struct vf_utf8_charp {
  752. static String From(napi_env env, const char* value) {
  753. return String::New(env, value);
  754. }
  755. };
  756. struct vf_utf16_charp {
  757. static String From(napi_env env, const char16_t* value) {
  758. return String::New(env, value);
  759. }
  760. };
  761. struct vf_utf8_string {
  762. static String From(napi_env env, const std::string& value) {
  763. return String::New(env, value);
  764. }
  765. };
  766. struct vf_utf16_string {
  767. static String From(napi_env env, const std::u16string& value) {
  768. return String::New(env, value);
  769. }
  770. };
  771. template <typename T>
  772. struct vf_fallback {
  773. static Value From(napi_env env, const T& value) {
  774. return Value(env, value);
  775. }
  776. };
  777. template <typename...> struct disjunction : std::false_type {};
  778. template <typename B> struct disjunction<B> : B {};
  779. template <typename B, typename... Bs>
  780. struct disjunction<B, Bs...>
  781. : std::conditional<bool(B::value), B, disjunction<Bs...>>::type {};
  782. template <typename T>
  783. struct can_make_string
  784. : disjunction<typename std::is_convertible<T, const char *>::type,
  785. typename std::is_convertible<T, const char16_t *>::type,
  786. typename std::is_convertible<T, std::string>::type,
  787. typename std::is_convertible<T, std::u16string>::type> {};
  788. }
  789. template <typename T>
  790. Value Value::From(napi_env env, const T& value) {
  791. using Helper = typename std::conditional<
  792. std::is_integral<T>::value || std::is_floating_point<T>::value,
  793. details::vf_number<T>,
  794. typename std::conditional<
  795. details::can_make_string<T>::value,
  796. String,
  797. details::vf_fallback<T>
  798. >::type
  799. >::type;
  800. return Helper::From(env, value);
  801. }
  802. template <typename T>
  803. String String::From(napi_env env, const T& value) {
  804. struct Dummy {};
  805. using Helper = typename std::conditional<
  806. std::is_convertible<T, const char*>::value,
  807. details::vf_utf8_charp,
  808. typename std::conditional<
  809. std::is_convertible<T, const char16_t*>::value,
  810. details::vf_utf16_charp,
  811. typename std::conditional<
  812. std::is_convertible<T, std::string>::value,
  813. details::vf_utf8_string,
  814. typename std::conditional<
  815. std::is_convertible<T, std::u16string>::value,
  816. details::vf_utf16_string,
  817. Dummy
  818. >::type
  819. >::type
  820. >::type
  821. >::type;
  822. return Helper::From(env, value);
  823. }
  824. ////////////////////////////////////////////////////////////////////////////////
  825. // Object class
  826. ////////////////////////////////////////////////////////////////////////////////
  827. template <typename Key>
  828. inline Object::PropertyLValue<Key>::operator Value() const {
  829. return Object(_env, _object).Get(_key);
  830. }
  831. template <typename Key> template <typename ValueType>
  832. inline Object::PropertyLValue<Key>& Object::PropertyLValue<Key>::operator =(ValueType value) {
  833. Object(_env, _object).Set(_key, value);
  834. return *this;
  835. }
  836. template <typename Key>
  837. inline Object::PropertyLValue<Key>::PropertyLValue(Object object, Key key)
  838. : _env(object.Env()), _object(object), _key(key) {}
  839. inline Object Object::New(napi_env env) {
  840. napi_value value;
  841. napi_status status = napi_create_object(env, &value);
  842. NAPI_THROW_IF_FAILED(env, status, Object());
  843. return Object(env, value);
  844. }
  845. inline Object::Object() : Value() {
  846. }
  847. inline Object::Object(napi_env env, napi_value value) : Value(env, value) {
  848. }
  849. inline Object::PropertyLValue<std::string> Object::operator [](const char* utf8name) {
  850. return PropertyLValue<std::string>(*this, utf8name);
  851. }
  852. inline Object::PropertyLValue<std::string> Object::operator [](const std::string& utf8name) {
  853. return PropertyLValue<std::string>(*this, utf8name);
  854. }
  855. inline Object::PropertyLValue<uint32_t> Object::operator [](uint32_t index) {
  856. return PropertyLValue<uint32_t>(*this, index);
  857. }
  858. inline Value Object::operator [](const char* utf8name) const {
  859. return Get(utf8name);
  860. }
  861. inline Value Object::operator [](const std::string& utf8name) const {
  862. return Get(utf8name);
  863. }
  864. inline Value Object::operator [](uint32_t index) const {
  865. return Get(index);
  866. }
  867. inline bool Object::Has(napi_value key) const {
  868. bool result;
  869. napi_status status = napi_has_property(_env, _value, key, &result);
  870. NAPI_THROW_IF_FAILED(_env, status, false);
  871. return result;
  872. }
  873. inline bool Object::Has(Value key) const {
  874. bool result;
  875. napi_status status = napi_has_property(_env, _value, key, &result);
  876. NAPI_THROW_IF_FAILED(_env, status, false);
  877. return result;
  878. }
  879. inline bool Object::Has(const char* utf8name) const {
  880. bool result;
  881. napi_status status = napi_has_named_property(_env, _value, utf8name, &result);
  882. NAPI_THROW_IF_FAILED(_env, status, false);
  883. return result;
  884. }
  885. inline bool Object::Has(const std::string& utf8name) const {
  886. return Has(utf8name.c_str());
  887. }
  888. inline bool Object::HasOwnProperty(napi_value key) const {
  889. bool result;
  890. napi_status status = napi_has_own_property(_env, _value, key, &result);
  891. NAPI_THROW_IF_FAILED(_env, status, false);
  892. return result;
  893. }
  894. inline bool Object::HasOwnProperty(Value key) const {
  895. bool result;
  896. napi_status status = napi_has_own_property(_env, _value, key, &result);
  897. NAPI_THROW_IF_FAILED(_env, status, false);
  898. return result;
  899. }
  900. inline bool Object::HasOwnProperty(const char* utf8name) const {
  901. napi_value key;
  902. napi_status status = napi_create_string_utf8(_env, utf8name, std::strlen(utf8name), &key);
  903. NAPI_THROW_IF_FAILED(_env, status, false);
  904. return HasOwnProperty(key);
  905. }
  906. inline bool Object::HasOwnProperty(const std::string& utf8name) const {
  907. return HasOwnProperty(utf8name.c_str());
  908. }
  909. inline Value Object::Get(napi_value key) const {
  910. napi_value result;
  911. napi_status status = napi_get_property(_env, _value, key, &result);
  912. NAPI_THROW_IF_FAILED(_env, status, Value());
  913. return Value(_env, result);
  914. }
  915. inline Value Object::Get(Value key) const {
  916. napi_value result;
  917. napi_status status = napi_get_property(_env, _value, key, &result);
  918. NAPI_THROW_IF_FAILED(_env, status, Value());
  919. return Value(_env, result);
  920. }
  921. inline Value Object::Get(const char* utf8name) const {
  922. napi_value result;
  923. napi_status status = napi_get_named_property(_env, _value, utf8name, &result);
  924. NAPI_THROW_IF_FAILED(_env, status, Value());
  925. return Value(_env, result);
  926. }
  927. inline Value Object::Get(const std::string& utf8name) const {
  928. return Get(utf8name.c_str());
  929. }
  930. template <typename ValueType>
  931. inline void Object::Set(napi_value key, const ValueType& value) {
  932. napi_status status =
  933. napi_set_property(_env, _value, key, Value::From(_env, value));
  934. NAPI_THROW_IF_FAILED_VOID(_env, status);
  935. }
  936. template <typename ValueType>
  937. inline void Object::Set(Value key, const ValueType& value) {
  938. napi_status status =
  939. napi_set_property(_env, _value, key, Value::From(_env, value));
  940. NAPI_THROW_IF_FAILED_VOID(_env, status);
  941. }
  942. template <typename ValueType>
  943. inline void Object::Set(const char* utf8name, const ValueType& value) {
  944. napi_status status =
  945. napi_set_named_property(_env, _value, utf8name, Value::From(_env, value));
  946. NAPI_THROW_IF_FAILED_VOID(_env, status);
  947. }
  948. template <typename ValueType>
  949. inline void Object::Set(const std::string& utf8name, const ValueType& value) {
  950. Set(utf8name.c_str(), value);
  951. }
  952. inline bool Object::Delete(napi_value key) {
  953. bool result;
  954. napi_status status = napi_delete_property(_env, _value, key, &result);
  955. NAPI_THROW_IF_FAILED(_env, status, false);
  956. return result;
  957. }
  958. inline bool Object::Delete(Value key) {
  959. bool result;
  960. napi_status status = napi_delete_property(_env, _value, key, &result);
  961. NAPI_THROW_IF_FAILED(_env, status, false);
  962. return result;
  963. }
  964. inline bool Object::Delete(const char* utf8name) {
  965. return Delete(String::New(_env, utf8name));
  966. }
  967. inline bool Object::Delete(const std::string& utf8name) {
  968. return Delete(String::New(_env, utf8name));
  969. }
  970. inline bool Object::Has(uint32_t index) const {
  971. bool result;
  972. napi_status status = napi_has_element(_env, _value, index, &result);
  973. NAPI_THROW_IF_FAILED(_env, status, false);
  974. return result;
  975. }
  976. inline Value Object::Get(uint32_t index) const {
  977. napi_value value;
  978. napi_status status = napi_get_element(_env, _value, index, &value);
  979. NAPI_THROW_IF_FAILED(_env, status, Value());
  980. return Value(_env, value);
  981. }
  982. template <typename ValueType>
  983. inline void Object::Set(uint32_t index, const ValueType& value) {
  984. napi_status status =
  985. napi_set_element(_env, _value, index, Value::From(_env, value));
  986. NAPI_THROW_IF_FAILED_VOID(_env, status);
  987. }
  988. inline bool Object::Delete(uint32_t index) {
  989. bool result;
  990. napi_status status = napi_delete_element(_env, _value, index, &result);
  991. NAPI_THROW_IF_FAILED(_env, status, false);
  992. return result;
  993. }
  994. inline Array Object::GetPropertyNames() const {
  995. napi_value result;
  996. napi_status status = napi_get_property_names(_env, _value, &result);
  997. NAPI_THROW_IF_FAILED(_env, status, Array());
  998. return Array(_env, result);
  999. }
  1000. inline void Object::DefineProperty(const PropertyDescriptor& property) {
  1001. napi_status status = napi_define_properties(_env, _value, 1,
  1002. reinterpret_cast<const napi_property_descriptor*>(&property));
  1003. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1004. }
  1005. inline void Object::DefineProperties(const std::initializer_list<PropertyDescriptor>& properties) {
  1006. napi_status status = napi_define_properties(_env, _value, properties.size(),
  1007. reinterpret_cast<const napi_property_descriptor*>(properties.begin()));
  1008. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1009. }
  1010. inline void Object::DefineProperties(const std::vector<PropertyDescriptor>& properties) {
  1011. napi_status status = napi_define_properties(_env, _value, properties.size(),
  1012. reinterpret_cast<const napi_property_descriptor*>(properties.data()));
  1013. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1014. }
  1015. inline bool Object::InstanceOf(const Function& constructor) const {
  1016. bool result;
  1017. napi_status status = napi_instanceof(_env, _value, constructor, &result);
  1018. NAPI_THROW_IF_FAILED(_env, status, false);
  1019. return result;
  1020. }
  1021. template <typename Finalizer, typename T>
  1022. inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
  1023. details::FinalizeData<T, Finalizer>* finalizeData =
  1024. new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
  1025. napi_status status =
  1026. details::AttachData(_env,
  1027. *this,
  1028. data,
  1029. details::FinalizeData<T, Finalizer>::Wrapper,
  1030. finalizeData);
  1031. if (status != napi_ok) {
  1032. delete finalizeData;
  1033. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1034. }
  1035. }
  1036. template <typename Finalizer, typename T, typename Hint>
  1037. inline void Object::AddFinalizer(Finalizer finalizeCallback,
  1038. T* data,
  1039. Hint* finalizeHint) {
  1040. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  1041. new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
  1042. napi_status status =
  1043. details::AttachData(_env,
  1044. *this,
  1045. data,
  1046. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
  1047. finalizeData);
  1048. if (status != napi_ok) {
  1049. delete finalizeData;
  1050. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1051. }
  1052. }
  1053. ////////////////////////////////////////////////////////////////////////////////
  1054. // External class
  1055. ////////////////////////////////////////////////////////////////////////////////
  1056. template <typename T>
  1057. inline External<T> External<T>::New(napi_env env, T* data) {
  1058. napi_value value;
  1059. napi_status status = napi_create_external(env, data, nullptr, nullptr, &value);
  1060. NAPI_THROW_IF_FAILED(env, status, External());
  1061. return External(env, value);
  1062. }
  1063. template <typename T>
  1064. template <typename Finalizer>
  1065. inline External<T> External<T>::New(napi_env env,
  1066. T* data,
  1067. Finalizer finalizeCallback) {
  1068. napi_value value;
  1069. details::FinalizeData<T, Finalizer>* finalizeData =
  1070. new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
  1071. napi_status status = napi_create_external(
  1072. env,
  1073. data,
  1074. details::FinalizeData<T, Finalizer>::Wrapper,
  1075. finalizeData,
  1076. &value);
  1077. if (status != napi_ok) {
  1078. delete finalizeData;
  1079. NAPI_THROW_IF_FAILED(env, status, External());
  1080. }
  1081. return External(env, value);
  1082. }
  1083. template <typename T>
  1084. template <typename Finalizer, typename Hint>
  1085. inline External<T> External<T>::New(napi_env env,
  1086. T* data,
  1087. Finalizer finalizeCallback,
  1088. Hint* finalizeHint) {
  1089. napi_value value;
  1090. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  1091. new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
  1092. napi_status status = napi_create_external(
  1093. env,
  1094. data,
  1095. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
  1096. finalizeData,
  1097. &value);
  1098. if (status != napi_ok) {
  1099. delete finalizeData;
  1100. NAPI_THROW_IF_FAILED(env, status, External());
  1101. }
  1102. return External(env, value);
  1103. }
  1104. template <typename T>
  1105. inline External<T>::External() : Value() {
  1106. }
  1107. template <typename T>
  1108. inline External<T>::External(napi_env env, napi_value value) : Value(env, value) {
  1109. }
  1110. template <typename T>
  1111. inline T* External<T>::Data() const {
  1112. void* data;
  1113. napi_status status = napi_get_value_external(_env, _value, &data);
  1114. NAPI_THROW_IF_FAILED(_env, status, nullptr);
  1115. return reinterpret_cast<T*>(data);
  1116. }
  1117. ////////////////////////////////////////////////////////////////////////////////
  1118. // Array class
  1119. ////////////////////////////////////////////////////////////////////////////////
  1120. inline Array Array::New(napi_env env) {
  1121. napi_value value;
  1122. napi_status status = napi_create_array(env, &value);
  1123. NAPI_THROW_IF_FAILED(env, status, Array());
  1124. return Array(env, value);
  1125. }
  1126. inline Array Array::New(napi_env env, size_t length) {
  1127. napi_value value;
  1128. napi_status status = napi_create_array_with_length(env, length, &value);
  1129. NAPI_THROW_IF_FAILED(env, status, Array());
  1130. return Array(env, value);
  1131. }
  1132. inline Array::Array() : Object() {
  1133. }
  1134. inline Array::Array(napi_env env, napi_value value) : Object(env, value) {
  1135. }
  1136. inline uint32_t Array::Length() const {
  1137. uint32_t result;
  1138. napi_status status = napi_get_array_length(_env, _value, &result);
  1139. NAPI_THROW_IF_FAILED(_env, status, 0);
  1140. return result;
  1141. }
  1142. ////////////////////////////////////////////////////////////////////////////////
  1143. // ArrayBuffer class
  1144. ////////////////////////////////////////////////////////////////////////////////
  1145. inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
  1146. napi_value value;
  1147. void* data;
  1148. napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value);
  1149. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1150. return ArrayBuffer(env, value);
  1151. }
  1152. inline ArrayBuffer ArrayBuffer::New(napi_env env,
  1153. void* externalData,
  1154. size_t byteLength) {
  1155. napi_value value;
  1156. napi_status status = napi_create_external_arraybuffer(
  1157. env, externalData, byteLength, nullptr, nullptr, &value);
  1158. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1159. return ArrayBuffer(env, value);
  1160. }
  1161. template <typename Finalizer>
  1162. inline ArrayBuffer ArrayBuffer::New(napi_env env,
  1163. void* externalData,
  1164. size_t byteLength,
  1165. Finalizer finalizeCallback) {
  1166. napi_value value;
  1167. details::FinalizeData<void, Finalizer>* finalizeData =
  1168. new details::FinalizeData<void, Finalizer>({ finalizeCallback, nullptr });
  1169. napi_status status = napi_create_external_arraybuffer(
  1170. env,
  1171. externalData,
  1172. byteLength,
  1173. details::FinalizeData<void, Finalizer>::Wrapper,
  1174. finalizeData,
  1175. &value);
  1176. if (status != napi_ok) {
  1177. delete finalizeData;
  1178. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1179. }
  1180. return ArrayBuffer(env, value);
  1181. }
  1182. template <typename Finalizer, typename Hint>
  1183. inline ArrayBuffer ArrayBuffer::New(napi_env env,
  1184. void* externalData,
  1185. size_t byteLength,
  1186. Finalizer finalizeCallback,
  1187. Hint* finalizeHint) {
  1188. napi_value value;
  1189. details::FinalizeData<void, Finalizer, Hint>* finalizeData =
  1190. new details::FinalizeData<void, Finalizer, Hint>({ finalizeCallback, finalizeHint });
  1191. napi_status status = napi_create_external_arraybuffer(
  1192. env,
  1193. externalData,
  1194. byteLength,
  1195. details::FinalizeData<void, Finalizer, Hint>::WrapperWithHint,
  1196. finalizeData,
  1197. &value);
  1198. if (status != napi_ok) {
  1199. delete finalizeData;
  1200. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1201. }
  1202. return ArrayBuffer(env, value);
  1203. }
  1204. inline ArrayBuffer::ArrayBuffer() : Object() {
  1205. }
  1206. inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
  1207. : Object(env, value) {
  1208. }
  1209. inline void* ArrayBuffer::Data() {
  1210. void* data;
  1211. napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
  1212. NAPI_THROW_IF_FAILED(_env, status, nullptr);
  1213. return data;
  1214. }
  1215. inline size_t ArrayBuffer::ByteLength() {
  1216. size_t length;
  1217. napi_status status = napi_get_arraybuffer_info(_env, _value, nullptr, &length);
  1218. NAPI_THROW_IF_FAILED(_env, status, 0);
  1219. return length;
  1220. }
  1221. ////////////////////////////////////////////////////////////////////////////////
  1222. // DataView class
  1223. ////////////////////////////////////////////////////////////////////////////////
  1224. inline DataView DataView::New(napi_env env,
  1225. Napi::ArrayBuffer arrayBuffer) {
  1226. return New(env, arrayBuffer, 0, arrayBuffer.ByteLength());
  1227. }
  1228. inline DataView DataView::New(napi_env env,
  1229. Napi::ArrayBuffer arrayBuffer,
  1230. size_t byteOffset) {
  1231. if (byteOffset > arrayBuffer.ByteLength()) {
  1232. NAPI_THROW(RangeError::New(env,
  1233. "Start offset is outside the bounds of the buffer"),
  1234. DataView());
  1235. }
  1236. return New(env, arrayBuffer, byteOffset,
  1237. arrayBuffer.ByteLength() - byteOffset);
  1238. }
  1239. inline DataView DataView::New(napi_env env,
  1240. Napi::ArrayBuffer arrayBuffer,
  1241. size_t byteOffset,
  1242. size_t byteLength) {
  1243. if (byteOffset + byteLength > arrayBuffer.ByteLength()) {
  1244. NAPI_THROW(RangeError::New(env, "Invalid DataView length"),
  1245. DataView());
  1246. }
  1247. napi_value value;
  1248. napi_status status = napi_create_dataview(
  1249. env, byteLength, arrayBuffer, byteOffset, &value);
  1250. NAPI_THROW_IF_FAILED(env, status, DataView());
  1251. return DataView(env, value);
  1252. }
  1253. inline DataView::DataView() : Object() {
  1254. }
  1255. inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) {
  1256. napi_status status = napi_get_dataview_info(
  1257. _env,
  1258. _value /* dataView */,
  1259. &_length /* byteLength */,
  1260. &_data /* data */,
  1261. nullptr /* arrayBuffer */,
  1262. nullptr /* byteOffset */);
  1263. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1264. }
  1265. inline Napi::ArrayBuffer DataView::ArrayBuffer() const {
  1266. napi_value arrayBuffer;
  1267. napi_status status = napi_get_dataview_info(
  1268. _env,
  1269. _value /* dataView */,
  1270. nullptr /* byteLength */,
  1271. nullptr /* data */,
  1272. &arrayBuffer /* arrayBuffer */,
  1273. nullptr /* byteOffset */);
  1274. NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
  1275. return Napi::ArrayBuffer(_env, arrayBuffer);
  1276. }
  1277. inline size_t DataView::ByteOffset() const {
  1278. size_t byteOffset;
  1279. napi_status status = napi_get_dataview_info(
  1280. _env,
  1281. _value /* dataView */,
  1282. nullptr /* byteLength */,
  1283. nullptr /* data */,
  1284. nullptr /* arrayBuffer */,
  1285. &byteOffset /* byteOffset */);
  1286. NAPI_THROW_IF_FAILED(_env, status, 0);
  1287. return byteOffset;
  1288. }
  1289. inline size_t DataView::ByteLength() const {
  1290. return _length;
  1291. }
  1292. inline void* DataView::Data() const {
  1293. return _data;
  1294. }
  1295. inline float DataView::GetFloat32(size_t byteOffset) const {
  1296. return ReadData<float>(byteOffset);
  1297. }
  1298. inline double DataView::GetFloat64(size_t byteOffset) const {
  1299. return ReadData<double>(byteOffset);
  1300. }
  1301. inline int8_t DataView::GetInt8(size_t byteOffset) const {
  1302. return ReadData<int8_t>(byteOffset);
  1303. }
  1304. inline int16_t DataView::GetInt16(size_t byteOffset) const {
  1305. return ReadData<int16_t>(byteOffset);
  1306. }
  1307. inline int32_t DataView::GetInt32(size_t byteOffset) const {
  1308. return ReadData<int32_t>(byteOffset);
  1309. }
  1310. inline uint8_t DataView::GetUint8(size_t byteOffset) const {
  1311. return ReadData<uint8_t>(byteOffset);
  1312. }
  1313. inline uint16_t DataView::GetUint16(size_t byteOffset) const {
  1314. return ReadData<uint16_t>(byteOffset);
  1315. }
  1316. inline uint32_t DataView::GetUint32(size_t byteOffset) const {
  1317. return ReadData<uint32_t>(byteOffset);
  1318. }
  1319. inline void DataView::SetFloat32(size_t byteOffset, float value) const {
  1320. WriteData<float>(byteOffset, value);
  1321. }
  1322. inline void DataView::SetFloat64(size_t byteOffset, double value) const {
  1323. WriteData<double>(byteOffset, value);
  1324. }
  1325. inline void DataView::SetInt8(size_t byteOffset, int8_t value) const {
  1326. WriteData<int8_t>(byteOffset, value);
  1327. }
  1328. inline void DataView::SetInt16(size_t byteOffset, int16_t value) const {
  1329. WriteData<int16_t>(byteOffset, value);
  1330. }
  1331. inline void DataView::SetInt32(size_t byteOffset, int32_t value) const {
  1332. WriteData<int32_t>(byteOffset, value);
  1333. }
  1334. inline void DataView::SetUint8(size_t byteOffset, uint8_t value) const {
  1335. WriteData<uint8_t>(byteOffset, value);
  1336. }
  1337. inline void DataView::SetUint16(size_t byteOffset, uint16_t value) const {
  1338. WriteData<uint16_t>(byteOffset, value);
  1339. }
  1340. inline void DataView::SetUint32(size_t byteOffset, uint32_t value) const {
  1341. WriteData<uint32_t>(byteOffset, value);
  1342. }
  1343. template <typename T>
  1344. inline T DataView::ReadData(size_t byteOffset) const {
  1345. if (byteOffset + sizeof(T) > _length ||
  1346. byteOffset + sizeof(T) < byteOffset) { // overflow
  1347. NAPI_THROW(RangeError::New(_env,
  1348. "Offset is outside the bounds of the DataView"), 0);
  1349. }
  1350. return *reinterpret_cast<T*>(static_cast<uint8_t*>(_data) + byteOffset);
  1351. }
  1352. template <typename T>
  1353. inline void DataView::WriteData(size_t byteOffset, T value) const {
  1354. if (byteOffset + sizeof(T) > _length ||
  1355. byteOffset + sizeof(T) < byteOffset) { // overflow
  1356. NAPI_THROW_VOID(RangeError::New(_env,
  1357. "Offset is outside the bounds of the DataView"));
  1358. }
  1359. *reinterpret_cast<T*>(static_cast<uint8_t*>(_data) + byteOffset) = value;
  1360. }
  1361. ////////////////////////////////////////////////////////////////////////////////
  1362. // TypedArray class
  1363. ////////////////////////////////////////////////////////////////////////////////
  1364. inline TypedArray::TypedArray()
  1365. : Object(), _type(TypedArray::unknown_array_type), _length(0) {
  1366. }
  1367. inline TypedArray::TypedArray(napi_env env, napi_value value)
  1368. : Object(env, value), _type(TypedArray::unknown_array_type), _length(0) {
  1369. }
  1370. inline TypedArray::TypedArray(napi_env env,
  1371. napi_value value,
  1372. napi_typedarray_type type,
  1373. size_t length)
  1374. : Object(env, value), _type(type), _length(length) {
  1375. }
  1376. inline napi_typedarray_type TypedArray::TypedArrayType() const {
  1377. if (_type == TypedArray::unknown_array_type) {
  1378. napi_status status = napi_get_typedarray_info(_env, _value,
  1379. &const_cast<TypedArray*>(this)->_type, &const_cast<TypedArray*>(this)->_length,
  1380. nullptr, nullptr, nullptr);
  1381. NAPI_THROW_IF_FAILED(_env, status, napi_int8_array);
  1382. }
  1383. return _type;
  1384. }
  1385. inline uint8_t TypedArray::ElementSize() const {
  1386. switch (TypedArrayType()) {
  1387. case napi_int8_array:
  1388. case napi_uint8_array:
  1389. case napi_uint8_clamped_array:
  1390. return 1;
  1391. case napi_int16_array:
  1392. case napi_uint16_array:
  1393. return 2;
  1394. case napi_int32_array:
  1395. case napi_uint32_array:
  1396. case napi_float32_array:
  1397. return 4;
  1398. case napi_float64_array:
  1399. #if (NAPI_VERSION > 5)
  1400. case napi_bigint64_array:
  1401. case napi_biguint64_array:
  1402. #endif // (NAPI_VERSION > 5)
  1403. return 8;
  1404. default:
  1405. return 0;
  1406. }
  1407. }
  1408. inline size_t TypedArray::ElementLength() const {
  1409. if (_type == TypedArray::unknown_array_type) {
  1410. napi_status status = napi_get_typedarray_info(_env, _value,
  1411. &const_cast<TypedArray*>(this)->_type, &const_cast<TypedArray*>(this)->_length,
  1412. nullptr, nullptr, nullptr);
  1413. NAPI_THROW_IF_FAILED(_env, status, 0);
  1414. }
  1415. return _length;
  1416. }
  1417. inline size_t TypedArray::ByteOffset() const {
  1418. size_t byteOffset;
  1419. napi_status status = napi_get_typedarray_info(
  1420. _env, _value, nullptr, nullptr, nullptr, nullptr, &byteOffset);
  1421. NAPI_THROW_IF_FAILED(_env, status, 0);
  1422. return byteOffset;
  1423. }
  1424. inline size_t TypedArray::ByteLength() const {
  1425. return ElementSize() * ElementLength();
  1426. }
  1427. inline Napi::ArrayBuffer TypedArray::ArrayBuffer() const {
  1428. napi_value arrayBuffer;
  1429. napi_status status = napi_get_typedarray_info(
  1430. _env, _value, nullptr, nullptr, nullptr, &arrayBuffer, nullptr);
  1431. NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
  1432. return Napi::ArrayBuffer(_env, arrayBuffer);
  1433. }
  1434. ////////////////////////////////////////////////////////////////////////////////
  1435. // TypedArrayOf<T> class
  1436. ////////////////////////////////////////////////////////////////////////////////
  1437. template <typename T>
  1438. inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
  1439. size_t elementLength,
  1440. napi_typedarray_type type) {
  1441. Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(env, elementLength * sizeof (T));
  1442. return New(env, elementLength, arrayBuffer, 0, type);
  1443. }
  1444. template <typename T>
  1445. inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
  1446. size_t elementLength,
  1447. Napi::ArrayBuffer arrayBuffer,
  1448. size_t bufferOffset,
  1449. napi_typedarray_type type) {
  1450. napi_value value;
  1451. napi_status status = napi_create_typedarray(
  1452. env, type, elementLength, arrayBuffer, bufferOffset, &value);
  1453. NAPI_THROW_IF_FAILED(env, status, TypedArrayOf<T>());
  1454. return TypedArrayOf<T>(
  1455. env, value, type, elementLength,
  1456. reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(arrayBuffer.Data()) + bufferOffset));
  1457. }
  1458. template <typename T>
  1459. inline TypedArrayOf<T>::TypedArrayOf() : TypedArray(), _data(nullptr) {
  1460. }
  1461. template <typename T>
  1462. inline TypedArrayOf<T>::TypedArrayOf(napi_env env, napi_value value)
  1463. : TypedArray(env, value), _data(nullptr) {
  1464. napi_status status = napi_get_typedarray_info(
  1465. _env, _value, &_type, &_length, reinterpret_cast<void**>(&_data), nullptr, nullptr);
  1466. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1467. }
  1468. template <typename T>
  1469. inline TypedArrayOf<T>::TypedArrayOf(napi_env env,
  1470. napi_value value,
  1471. napi_typedarray_type type,
  1472. size_t length,
  1473. T* data)
  1474. : TypedArray(env, value, type, length), _data(data) {
  1475. if (!(type == TypedArrayTypeForPrimitiveType<T>() ||
  1476. (type == napi_uint8_clamped_array && std::is_same<T, uint8_t>::value))) {
  1477. NAPI_THROW_VOID(TypeError::New(env, "Array type must match the template parameter. "
  1478. "(Uint8 arrays may optionally have the \"clamped\" array type.)"));
  1479. }
  1480. }
  1481. template <typename T>
  1482. inline T& TypedArrayOf<T>::operator [](size_t index) {
  1483. return _data[index];
  1484. }
  1485. template <typename T>
  1486. inline const T& TypedArrayOf<T>::operator [](size_t index) const {
  1487. return _data[index];
  1488. }
  1489. template <typename T>
  1490. inline T* TypedArrayOf<T>::Data() {
  1491. return _data;
  1492. }
  1493. template <typename T>
  1494. inline const T* TypedArrayOf<T>::Data() const {
  1495. return _data;
  1496. }
  1497. ////////////////////////////////////////////////////////////////////////////////
  1498. // Function class
  1499. ////////////////////////////////////////////////////////////////////////////////
  1500. template <typename CbData>
  1501. static inline napi_status
  1502. CreateFunction(napi_env env,
  1503. const char* utf8name,
  1504. napi_callback cb,
  1505. CbData* data,
  1506. napi_value* result) {
  1507. napi_status status =
  1508. napi_create_function(env, utf8name, NAPI_AUTO_LENGTH, cb, data, result);
  1509. if (status == napi_ok) {
  1510. status = Napi::details::AttachData(env, *result, data);
  1511. }
  1512. return status;
  1513. }
  1514. template <Function::VoidCallback cb>
  1515. inline Function Function::New(napi_env env, const char* utf8name, void* data) {
  1516. napi_value result = nullptr;
  1517. napi_status status = napi_create_function(
  1518. env, utf8name, NAPI_AUTO_LENGTH,
  1519. [](napi_env env, napi_callback_info info) {
  1520. CallbackInfo callbackInfo(env, info);
  1521. return details::WrapCallback([&] {
  1522. cb(callbackInfo);
  1523. return nullptr;
  1524. });
  1525. }, data, &result);
  1526. NAPI_THROW_IF_FAILED(env, status, Function());
  1527. return Function(env, result);
  1528. }
  1529. template <Function::Callback cb>
  1530. inline Function Function::New(napi_env env, const char* utf8name, void* data) {
  1531. napi_value result = nullptr;
  1532. napi_status status = napi_create_function(
  1533. env, utf8name, NAPI_AUTO_LENGTH,
  1534. [](napi_env env, napi_callback_info info) {
  1535. CallbackInfo callbackInfo(env, info);
  1536. return details::WrapCallback([&] {
  1537. return cb(callbackInfo);
  1538. });
  1539. }, data, &result);
  1540. NAPI_THROW_IF_FAILED(env, status, Function());
  1541. return Function(env, result);
  1542. }
  1543. template <Function::VoidCallback cb>
  1544. inline Function Function::New(napi_env env,
  1545. const std::string& utf8name,
  1546. void* data) {
  1547. return Function::New<cb>(env, utf8name.c_str(), data);
  1548. }
  1549. template <Function::Callback cb>
  1550. inline Function Function::New(napi_env env,
  1551. const std::string& utf8name,
  1552. void* data) {
  1553. return Function::New<cb>(env, utf8name.c_str(), data);
  1554. }
  1555. template <typename Callable>
  1556. inline Function Function::New(napi_env env,
  1557. Callable cb,
  1558. const char* utf8name,
  1559. void* data) {
  1560. typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
  1561. typedef details::CallbackData<Callable, ReturnType> CbData;
  1562. auto callbackData = new CbData({ cb, data });
  1563. napi_value value;
  1564. napi_status status = CreateFunction(env,
  1565. utf8name,
  1566. CbData::Wrapper,
  1567. callbackData,
  1568. &value);
  1569. if (status != napi_ok) {
  1570. delete callbackData;
  1571. NAPI_THROW_IF_FAILED(env, status, Function());
  1572. }
  1573. return Function(env, value);
  1574. }
  1575. template <typename Callable>
  1576. inline Function Function::New(napi_env env,
  1577. Callable cb,
  1578. const std::string& utf8name,
  1579. void* data) {
  1580. return New(env, cb, utf8name.c_str(), data);
  1581. }
  1582. inline Function::Function() : Object() {
  1583. }
  1584. inline Function::Function(napi_env env, napi_value value) : Object(env, value) {
  1585. }
  1586. inline Value Function::operator ()(const std::initializer_list<napi_value>& args) const {
  1587. return Call(Env().Undefined(), args);
  1588. }
  1589. inline Value Function::Call(const std::initializer_list<napi_value>& args) const {
  1590. return Call(Env().Undefined(), args);
  1591. }
  1592. inline Value Function::Call(const std::vector<napi_value>& args) const {
  1593. return Call(Env().Undefined(), args);
  1594. }
  1595. inline Value Function::Call(size_t argc, const napi_value* args) const {
  1596. return Call(Env().Undefined(), argc, args);
  1597. }
  1598. inline Value Function::Call(napi_value recv, const std::initializer_list<napi_value>& args) const {
  1599. return Call(recv, args.size(), args.begin());
  1600. }
  1601. inline Value Function::Call(napi_value recv, const std::vector<napi_value>& args) const {
  1602. return Call(recv, args.size(), args.data());
  1603. }
  1604. inline Value Function::Call(napi_value recv, size_t argc, const napi_value* args) const {
  1605. napi_value result;
  1606. napi_status status = napi_call_function(
  1607. _env, recv, _value, argc, args, &result);
  1608. NAPI_THROW_IF_FAILED(_env, status, Value());
  1609. return Value(_env, result);
  1610. }
  1611. inline Value Function::MakeCallback(
  1612. napi_value recv,
  1613. const std::initializer_list<napi_value>& args,
  1614. napi_async_context context) const {
  1615. return MakeCallback(recv, args.size(), args.begin(), context);
  1616. }
  1617. inline Value Function::MakeCallback(
  1618. napi_value recv,
  1619. const std::vector<napi_value>& args,
  1620. napi_async_context context) const {
  1621. return MakeCallback(recv, args.size(), args.data(), context);
  1622. }
  1623. inline Value Function::MakeCallback(
  1624. napi_value recv,
  1625. size_t argc,
  1626. const napi_value* args,
  1627. napi_async_context context) const {
  1628. napi_value result;
  1629. napi_status status = napi_make_callback(
  1630. _env, context, recv, _value, argc, args, &result);
  1631. NAPI_THROW_IF_FAILED(_env, status, Value());
  1632. return Value(_env, result);
  1633. }
  1634. inline Object Function::New(const std::initializer_list<napi_value>& args) const {
  1635. return New(args.size(), args.begin());
  1636. }
  1637. inline Object Function::New(const std::vector<napi_value>& args) const {
  1638. return New(args.size(), args.data());
  1639. }
  1640. inline Object Function::New(size_t argc, const napi_value* args) const {
  1641. napi_value result;
  1642. napi_status status = napi_new_instance(
  1643. _env, _value, argc, args, &result);
  1644. NAPI_THROW_IF_FAILED(_env, status, Object());
  1645. return Object(_env, result);
  1646. }
  1647. ////////////////////////////////////////////////////////////////////////////////
  1648. // Promise class
  1649. ////////////////////////////////////////////////////////////////////////////////
  1650. inline Promise::Deferred Promise::Deferred::New(napi_env env) {
  1651. return Promise::Deferred(env);
  1652. }
  1653. inline Promise::Deferred::Deferred(napi_env env) : _env(env) {
  1654. napi_status status = napi_create_promise(_env, &_deferred, &_promise);
  1655. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1656. }
  1657. inline Promise Promise::Deferred::Promise() const {
  1658. return Napi::Promise(_env, _promise);
  1659. }
  1660. inline Napi::Env Promise::Deferred::Env() const {
  1661. return Napi::Env(_env);
  1662. }
  1663. inline void Promise::Deferred::Resolve(napi_value value) const {
  1664. napi_status status = napi_resolve_deferred(_env, _deferred, value);
  1665. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1666. }
  1667. inline void Promise::Deferred::Reject(napi_value value) const {
  1668. napi_status status = napi_reject_deferred(_env, _deferred, value);
  1669. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1670. }
  1671. inline Promise::Promise(napi_env env, napi_value value) : Object(env, value) {
  1672. }
  1673. ////////////////////////////////////////////////////////////////////////////////
  1674. // Buffer<T> class
  1675. ////////////////////////////////////////////////////////////////////////////////
  1676. template <typename T>
  1677. inline Buffer<T> Buffer<T>::New(napi_env env, size_t length) {
  1678. napi_value value;
  1679. void* data;
  1680. napi_status status = napi_create_buffer(env, length * sizeof (T), &data, &value);
  1681. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  1682. return Buffer(env, value, length, static_cast<T*>(data));
  1683. }
  1684. template <typename T>
  1685. inline Buffer<T> Buffer<T>::New(napi_env env, T* data, size_t length) {
  1686. napi_value value;
  1687. napi_status status = napi_create_external_buffer(
  1688. env, length * sizeof (T), data, nullptr, nullptr, &value);
  1689. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  1690. return Buffer(env, value, length, data);
  1691. }
  1692. template <typename T>
  1693. template <typename Finalizer>
  1694. inline Buffer<T> Buffer<T>::New(napi_env env,
  1695. T* data,
  1696. size_t length,
  1697. Finalizer finalizeCallback) {
  1698. napi_value value;
  1699. details::FinalizeData<T, Finalizer>* finalizeData =
  1700. new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
  1701. napi_status status = napi_create_external_buffer(
  1702. env,
  1703. length * sizeof (T),
  1704. data,
  1705. details::FinalizeData<T, Finalizer>::Wrapper,
  1706. finalizeData,
  1707. &value);
  1708. if (status != napi_ok) {
  1709. delete finalizeData;
  1710. NAPI_THROW_IF_FAILED(env, status, Buffer());
  1711. }
  1712. return Buffer(env, value, length, data);
  1713. }
  1714. template <typename T>
  1715. template <typename Finalizer, typename Hint>
  1716. inline Buffer<T> Buffer<T>::New(napi_env env,
  1717. T* data,
  1718. size_t length,
  1719. Finalizer finalizeCallback,
  1720. Hint* finalizeHint) {
  1721. napi_value value;
  1722. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  1723. new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
  1724. napi_status status = napi_create_external_buffer(
  1725. env,
  1726. length * sizeof (T),
  1727. data,
  1728. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
  1729. finalizeData,
  1730. &value);
  1731. if (status != napi_ok) {
  1732. delete finalizeData;
  1733. NAPI_THROW_IF_FAILED(env, status, Buffer());
  1734. }
  1735. return Buffer(env, value, length, data);
  1736. }
  1737. template <typename T>
  1738. inline Buffer<T> Buffer<T>::Copy(napi_env env, const T* data, size_t length) {
  1739. napi_value value;
  1740. napi_status status = napi_create_buffer_copy(
  1741. env, length * sizeof (T), data, nullptr, &value);
  1742. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  1743. return Buffer<T>(env, value);
  1744. }
  1745. template <typename T>
  1746. inline Buffer<T>::Buffer() : Uint8Array(), _length(0), _data(nullptr) {
  1747. }
  1748. template <typename T>
  1749. inline Buffer<T>::Buffer(napi_env env, napi_value value)
  1750. : Uint8Array(env, value), _length(0), _data(nullptr) {
  1751. }
  1752. template <typename T>
  1753. inline Buffer<T>::Buffer(napi_env env, napi_value value, size_t length, T* data)
  1754. : Uint8Array(env, value), _length(length), _data(data) {
  1755. }
  1756. template <typename T>
  1757. inline size_t Buffer<T>::Length() const {
  1758. EnsureInfo();
  1759. return _length;
  1760. }
  1761. template <typename T>
  1762. inline T* Buffer<T>::Data() const {
  1763. EnsureInfo();
  1764. return _data;
  1765. }
  1766. template <typename T>
  1767. inline void Buffer<T>::EnsureInfo() const {
  1768. // The Buffer instance may have been constructed from a napi_value whose
  1769. // length/data are not yet known. Fetch and cache these values just once,
  1770. // since they can never change during the lifetime of the Buffer.
  1771. if (_data == nullptr) {
  1772. size_t byteLength;
  1773. void* voidData;
  1774. napi_status status = napi_get_buffer_info(_env, _value, &voidData, &byteLength);
  1775. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1776. _length = byteLength / sizeof (T);
  1777. _data = static_cast<T*>(voidData);
  1778. }
  1779. }
  1780. ////////////////////////////////////////////////////////////////////////////////
  1781. // Error class
  1782. ////////////////////////////////////////////////////////////////////////////////
  1783. inline Error Error::New(napi_env env) {
  1784. napi_status status;
  1785. napi_value error = nullptr;
  1786. bool is_exception_pending;
  1787. const napi_extended_error_info* info;
  1788. // We must retrieve the last error info before doing anything else, because
  1789. // doing anything else will replace the last error info.
  1790. status = napi_get_last_error_info(env, &info);
  1791. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
  1792. status = napi_is_exception_pending(env, &is_exception_pending);
  1793. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
  1794. // A pending exception takes precedence over any internal error status.
  1795. if (is_exception_pending) {
  1796. status = napi_get_and_clear_last_exception(env, &error);
  1797. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
  1798. }
  1799. else {
  1800. const char* error_message = info->error_message != nullptr ?
  1801. info->error_message : "Error in native callback";
  1802. napi_value message;
  1803. status = napi_create_string_utf8(
  1804. env,
  1805. error_message,
  1806. std::strlen(error_message),
  1807. &message);
  1808. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
  1809. switch (info->error_code) {
  1810. case napi_object_expected:
  1811. case napi_string_expected:
  1812. case napi_boolean_expected:
  1813. case napi_number_expected:
  1814. status = napi_create_type_error(env, nullptr, message, &error);
  1815. break;
  1816. default:
  1817. status = napi_create_error(env, nullptr, message, &error);
  1818. break;
  1819. }
  1820. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
  1821. }
  1822. return Error(env, error);
  1823. }
  1824. inline Error Error::New(napi_env env, const char* message) {
  1825. return Error::New<Error>(env, message, std::strlen(message), napi_create_error);
  1826. }
  1827. inline Error Error::New(napi_env env, const std::string& message) {
  1828. return Error::New<Error>(env, message.c_str(), message.size(), napi_create_error);
  1829. }
  1830. inline NAPI_NO_RETURN void Error::Fatal(const char* location, const char* message) {
  1831. napi_fatal_error(location, NAPI_AUTO_LENGTH, message, NAPI_AUTO_LENGTH);
  1832. }
  1833. inline Error::Error() : ObjectReference() {
  1834. }
  1835. inline Error::Error(napi_env env, napi_value value) : ObjectReference(env, nullptr) {
  1836. if (value != nullptr) {
  1837. napi_status status = napi_create_reference(env, value, 1, &_ref);
  1838. // Avoid infinite recursion in the failure case.
  1839. // Don't try to construct & throw another Error instance.
  1840. NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_reference");
  1841. }
  1842. }
  1843. inline Error::Error(Error&& other) : ObjectReference(std::move(other)) {
  1844. }
  1845. inline Error& Error::operator =(Error&& other) {
  1846. static_cast<Reference<Object>*>(this)->operator=(std::move(other));
  1847. return *this;
  1848. }
  1849. inline Error::Error(const Error& other) : ObjectReference(other) {
  1850. }
  1851. inline Error& Error::operator =(const Error& other) {
  1852. Reset();
  1853. _env = other.Env();
  1854. HandleScope scope(_env);
  1855. napi_value value = other.Value();
  1856. if (value != nullptr) {
  1857. napi_status status = napi_create_reference(_env, value, 1, &_ref);
  1858. NAPI_THROW_IF_FAILED(_env, status, *this);
  1859. }
  1860. return *this;
  1861. }
  1862. inline const std::string& Error::Message() const NAPI_NOEXCEPT {
  1863. if (_message.size() == 0 && _env != nullptr) {
  1864. #ifdef NAPI_CPP_EXCEPTIONS
  1865. try {
  1866. _message = Get("message").As<String>();
  1867. }
  1868. catch (...) {
  1869. // Catch all errors here, to include e.g. a std::bad_alloc from
  1870. // the std::string::operator=, because this method may not throw.
  1871. }
  1872. #else // NAPI_CPP_EXCEPTIONS
  1873. _message = Get("message").As<String>();
  1874. #endif // NAPI_CPP_EXCEPTIONS
  1875. }
  1876. return _message;
  1877. }
  1878. inline void Error::ThrowAsJavaScriptException() const {
  1879. HandleScope scope(_env);
  1880. if (!IsEmpty()) {
  1881. // We intentionally don't use `NAPI_THROW_*` macros here to ensure
  1882. // that there is no possible recursion as `ThrowAsJavaScriptException`
  1883. // is part of `NAPI_THROW_*` macro definition for noexcept.
  1884. napi_status status = napi_throw(_env, Value());
  1885. #ifdef NAPI_CPP_EXCEPTIONS
  1886. if (status != napi_ok) {
  1887. throw Error::New(_env);
  1888. }
  1889. #else // NAPI_CPP_EXCEPTIONS
  1890. NAPI_FATAL_IF_FAILED(status, "Error::ThrowAsJavaScriptException", "napi_throw");
  1891. #endif // NAPI_CPP_EXCEPTIONS
  1892. }
  1893. }
  1894. #ifdef NAPI_CPP_EXCEPTIONS
  1895. inline const char* Error::what() const NAPI_NOEXCEPT {
  1896. return Message().c_str();
  1897. }
  1898. #endif // NAPI_CPP_EXCEPTIONS
  1899. template <typename TError>
  1900. inline TError Error::New(napi_env env,
  1901. const char* message,
  1902. size_t length,
  1903. create_error_fn create_error) {
  1904. napi_value str;
  1905. napi_status status = napi_create_string_utf8(env, message, length, &str);
  1906. NAPI_THROW_IF_FAILED(env, status, TError());
  1907. napi_value error;
  1908. status = create_error(env, nullptr, str, &error);
  1909. NAPI_THROW_IF_FAILED(env, status, TError());
  1910. return TError(env, error);
  1911. }
  1912. inline TypeError TypeError::New(napi_env env, const char* message) {
  1913. return Error::New<TypeError>(env, message, std::strlen(message), napi_create_type_error);
  1914. }
  1915. inline TypeError TypeError::New(napi_env env, const std::string& message) {
  1916. return Error::New<TypeError>(env, message.c_str(), message.size(), napi_create_type_error);
  1917. }
  1918. inline TypeError::TypeError() : Error() {
  1919. }
  1920. inline TypeError::TypeError(napi_env env, napi_value value) : Error(env, value) {
  1921. }
  1922. inline RangeError RangeError::New(napi_env env, const char* message) {
  1923. return Error::New<RangeError>(env, message, std::strlen(message), napi_create_range_error);
  1924. }
  1925. inline RangeError RangeError::New(napi_env env, const std::string& message) {
  1926. return Error::New<RangeError>(env, message.c_str(), message.size(), napi_create_range_error);
  1927. }
  1928. inline RangeError::RangeError() : Error() {
  1929. }
  1930. inline RangeError::RangeError(napi_env env, napi_value value) : Error(env, value) {
  1931. }
  1932. ////////////////////////////////////////////////////////////////////////////////
  1933. // Reference<T> class
  1934. ////////////////////////////////////////////////////////////////////////////////
  1935. template <typename T>
  1936. inline Reference<T> Reference<T>::New(const T& value, uint32_t initialRefcount) {
  1937. napi_env env = value.Env();
  1938. napi_value val = value;
  1939. if (val == nullptr) {
  1940. return Reference<T>(env, nullptr);
  1941. }
  1942. napi_ref ref;
  1943. napi_status status = napi_create_reference(env, value, initialRefcount, &ref);
  1944. NAPI_THROW_IF_FAILED(env, status, Reference<T>());
  1945. return Reference<T>(env, ref);
  1946. }
  1947. template <typename T>
  1948. inline Reference<T>::Reference() : _env(nullptr), _ref(nullptr), _suppressDestruct(false) {
  1949. }
  1950. template <typename T>
  1951. inline Reference<T>::Reference(napi_env env, napi_ref ref)
  1952. : _env(env), _ref(ref), _suppressDestruct(false) {
  1953. }
  1954. template <typename T>
  1955. inline Reference<T>::~Reference() {
  1956. if (_ref != nullptr) {
  1957. if (!_suppressDestruct) {
  1958. napi_delete_reference(_env, _ref);
  1959. }
  1960. _ref = nullptr;
  1961. }
  1962. }
  1963. template <typename T>
  1964. inline Reference<T>::Reference(Reference<T>&& other)
  1965. : _env(other._env), _ref(other._ref), _suppressDestruct(other._suppressDestruct) {
  1966. other._env = nullptr;
  1967. other._ref = nullptr;
  1968. other._suppressDestruct = false;
  1969. }
  1970. template <typename T>
  1971. inline Reference<T>& Reference<T>::operator =(Reference<T>&& other) {
  1972. Reset();
  1973. _env = other._env;
  1974. _ref = other._ref;
  1975. _suppressDestruct = other._suppressDestruct;
  1976. other._env = nullptr;
  1977. other._ref = nullptr;
  1978. other._suppressDestruct = false;
  1979. return *this;
  1980. }
  1981. template <typename T>
  1982. inline Reference<T>::Reference(const Reference<T>& other)
  1983. : _env(other._env), _ref(nullptr), _suppressDestruct(false) {
  1984. HandleScope scope(_env);
  1985. napi_value value = other.Value();
  1986. if (value != nullptr) {
  1987. // Copying is a limited scenario (currently only used for Error object) and always creates a
  1988. // strong reference to the given value even if the incoming reference is weak.
  1989. napi_status status = napi_create_reference(_env, value, 1, &_ref);
  1990. NAPI_FATAL_IF_FAILED(status, "Reference<T>::Reference", "napi_create_reference");
  1991. }
  1992. }
  1993. template <typename T>
  1994. inline Reference<T>::operator napi_ref() const {
  1995. return _ref;
  1996. }
  1997. template <typename T>
  1998. inline bool Reference<T>::operator ==(const Reference<T> &other) const {
  1999. HandleScope scope(_env);
  2000. return this->Value().StrictEquals(other.Value());
  2001. }
  2002. template <typename T>
  2003. inline bool Reference<T>::operator !=(const Reference<T> &other) const {
  2004. return !this->operator ==(other);
  2005. }
  2006. template <typename T>
  2007. inline Napi::Env Reference<T>::Env() const {
  2008. return Napi::Env(_env);
  2009. }
  2010. template <typename T>
  2011. inline bool Reference<T>::IsEmpty() const {
  2012. return _ref == nullptr;
  2013. }
  2014. template <typename T>
  2015. inline T Reference<T>::Value() const {
  2016. if (_ref == nullptr) {
  2017. return T(_env, nullptr);
  2018. }
  2019. napi_value value;
  2020. napi_status status = napi_get_reference_value(_env, _ref, &value);
  2021. NAPI_THROW_IF_FAILED(_env, status, T());
  2022. return T(_env, value);
  2023. }
  2024. template <typename T>
  2025. inline uint32_t Reference<T>::Ref() {
  2026. uint32_t result;
  2027. napi_status status = napi_reference_ref(_env, _ref, &result);
  2028. NAPI_THROW_IF_FAILED(_env, status, 1);
  2029. return result;
  2030. }
  2031. template <typename T>
  2032. inline uint32_t Reference<T>::Unref() {
  2033. uint32_t result;
  2034. napi_status status = napi_reference_unref(_env, _ref, &result);
  2035. NAPI_THROW_IF_FAILED(_env, status, 1);
  2036. return result;
  2037. }
  2038. template <typename T>
  2039. inline void Reference<T>::Reset() {
  2040. if (_ref != nullptr) {
  2041. napi_status status = napi_delete_reference(_env, _ref);
  2042. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2043. _ref = nullptr;
  2044. }
  2045. }
  2046. template <typename T>
  2047. inline void Reference<T>::Reset(const T& value, uint32_t refcount) {
  2048. Reset();
  2049. _env = value.Env();
  2050. napi_value val = value;
  2051. if (val != nullptr) {
  2052. napi_status status = napi_create_reference(_env, value, refcount, &_ref);
  2053. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2054. }
  2055. }
  2056. template <typename T>
  2057. inline void Reference<T>::SuppressDestruct() {
  2058. _suppressDestruct = true;
  2059. }
  2060. template <typename T>
  2061. inline Reference<T> Weak(T value) {
  2062. return Reference<T>::New(value, 0);
  2063. }
  2064. inline ObjectReference Weak(Object value) {
  2065. return Reference<Object>::New(value, 0);
  2066. }
  2067. inline FunctionReference Weak(Function value) {
  2068. return Reference<Function>::New(value, 0);
  2069. }
  2070. template <typename T>
  2071. inline Reference<T> Persistent(T value) {
  2072. return Reference<T>::New(value, 1);
  2073. }
  2074. inline ObjectReference Persistent(Object value) {
  2075. return Reference<Object>::New(value, 1);
  2076. }
  2077. inline FunctionReference Persistent(Function value) {
  2078. return Reference<Function>::New(value, 1);
  2079. }
  2080. ////////////////////////////////////////////////////////////////////////////////
  2081. // ObjectReference class
  2082. ////////////////////////////////////////////////////////////////////////////////
  2083. inline ObjectReference::ObjectReference(): Reference<Object>() {
  2084. }
  2085. inline ObjectReference::ObjectReference(napi_env env, napi_ref ref): Reference<Object>(env, ref) {
  2086. }
  2087. inline ObjectReference::ObjectReference(Reference<Object>&& other)
  2088. : Reference<Object>(std::move(other)) {
  2089. }
  2090. inline ObjectReference& ObjectReference::operator =(Reference<Object>&& other) {
  2091. static_cast<Reference<Object>*>(this)->operator=(std::move(other));
  2092. return *this;
  2093. }
  2094. inline ObjectReference::ObjectReference(ObjectReference&& other)
  2095. : Reference<Object>(std::move(other)) {
  2096. }
  2097. inline ObjectReference& ObjectReference::operator =(ObjectReference&& other) {
  2098. static_cast<Reference<Object>*>(this)->operator=(std::move(other));
  2099. return *this;
  2100. }
  2101. inline ObjectReference::ObjectReference(const ObjectReference& other)
  2102. : Reference<Object>(other) {
  2103. }
  2104. inline Napi::Value ObjectReference::Get(const char* utf8name) const {
  2105. EscapableHandleScope scope(_env);
  2106. return scope.Escape(Value().Get(utf8name));
  2107. }
  2108. inline Napi::Value ObjectReference::Get(const std::string& utf8name) const {
  2109. EscapableHandleScope scope(_env);
  2110. return scope.Escape(Value().Get(utf8name));
  2111. }
  2112. inline void ObjectReference::Set(const char* utf8name, napi_value value) {
  2113. HandleScope scope(_env);
  2114. Value().Set(utf8name, value);
  2115. }
  2116. inline void ObjectReference::Set(const char* utf8name, Napi::Value value) {
  2117. HandleScope scope(_env);
  2118. Value().Set(utf8name, value);
  2119. }
  2120. inline void ObjectReference::Set(const char* utf8name, const char* utf8value) {
  2121. HandleScope scope(_env);
  2122. Value().Set(utf8name, utf8value);
  2123. }
  2124. inline void ObjectReference::Set(const char* utf8name, bool boolValue) {
  2125. HandleScope scope(_env);
  2126. Value().Set(utf8name, boolValue);
  2127. }
  2128. inline void ObjectReference::Set(const char* utf8name, double numberValue) {
  2129. HandleScope scope(_env);
  2130. Value().Set(utf8name, numberValue);
  2131. }
  2132. inline void ObjectReference::Set(const std::string& utf8name, napi_value value) {
  2133. HandleScope scope(_env);
  2134. Value().Set(utf8name, value);
  2135. }
  2136. inline void ObjectReference::Set(const std::string& utf8name, Napi::Value value) {
  2137. HandleScope scope(_env);
  2138. Value().Set(utf8name, value);
  2139. }
  2140. inline void ObjectReference::Set(const std::string& utf8name, std::string& utf8value) {
  2141. HandleScope scope(_env);
  2142. Value().Set(utf8name, utf8value);
  2143. }
  2144. inline void ObjectReference::Set(const std::string& utf8name, bool boolValue) {
  2145. HandleScope scope(_env);
  2146. Value().Set(utf8name, boolValue);
  2147. }
  2148. inline void ObjectReference::Set(const std::string& utf8name, double numberValue) {
  2149. HandleScope scope(_env);
  2150. Value().Set(utf8name, numberValue);
  2151. }
  2152. inline Napi::Value ObjectReference::Get(uint32_t index) const {
  2153. EscapableHandleScope scope(_env);
  2154. return scope.Escape(Value().Get(index));
  2155. }
  2156. inline void ObjectReference::Set(uint32_t index, napi_value value) {
  2157. HandleScope scope(_env);
  2158. Value().Set(index, value);
  2159. }
  2160. inline void ObjectReference::Set(uint32_t index, Napi::Value value) {
  2161. HandleScope scope(_env);
  2162. Value().Set(index, value);
  2163. }
  2164. inline void ObjectReference::Set(uint32_t index, const char* utf8value) {
  2165. HandleScope scope(_env);
  2166. Value().Set(index, utf8value);
  2167. }
  2168. inline void ObjectReference::Set(uint32_t index, const std::string& utf8value) {
  2169. HandleScope scope(_env);
  2170. Value().Set(index, utf8value);
  2171. }
  2172. inline void ObjectReference::Set(uint32_t index, bool boolValue) {
  2173. HandleScope scope(_env);
  2174. Value().Set(index, boolValue);
  2175. }
  2176. inline void ObjectReference::Set(uint32_t index, double numberValue) {
  2177. HandleScope scope(_env);
  2178. Value().Set(index, numberValue);
  2179. }
  2180. ////////////////////////////////////////////////////////////////////////////////
  2181. // FunctionReference class
  2182. ////////////////////////////////////////////////////////////////////////////////
  2183. inline FunctionReference::FunctionReference(): Reference<Function>() {
  2184. }
  2185. inline FunctionReference::FunctionReference(napi_env env, napi_ref ref)
  2186. : Reference<Function>(env, ref) {
  2187. }
  2188. inline FunctionReference::FunctionReference(Reference<Function>&& other)
  2189. : Reference<Function>(std::move(other)) {
  2190. }
  2191. inline FunctionReference& FunctionReference::operator =(Reference<Function>&& other) {
  2192. static_cast<Reference<Function>*>(this)->operator=(std::move(other));
  2193. return *this;
  2194. }
  2195. inline FunctionReference::FunctionReference(FunctionReference&& other)
  2196. : Reference<Function>(std::move(other)) {
  2197. }
  2198. inline FunctionReference& FunctionReference::operator =(FunctionReference&& other) {
  2199. static_cast<Reference<Function>*>(this)->operator=(std::move(other));
  2200. return *this;
  2201. }
  2202. inline Napi::Value FunctionReference::operator ()(
  2203. const std::initializer_list<napi_value>& args) const {
  2204. EscapableHandleScope scope(_env);
  2205. return scope.Escape(Value()(args));
  2206. }
  2207. inline Napi::Value FunctionReference::Call(const std::initializer_list<napi_value>& args) const {
  2208. EscapableHandleScope scope(_env);
  2209. Napi::Value result = Value().Call(args);
  2210. if (scope.Env().IsExceptionPending()) {
  2211. return Value();
  2212. }
  2213. return scope.Escape(result);
  2214. }
  2215. inline Napi::Value FunctionReference::Call(const std::vector<napi_value>& args) const {
  2216. EscapableHandleScope scope(_env);
  2217. Napi::Value result = Value().Call(args);
  2218. if (scope.Env().IsExceptionPending()) {
  2219. return Value();
  2220. }
  2221. return scope.Escape(result);
  2222. }
  2223. inline Napi::Value FunctionReference::Call(
  2224. napi_value recv, const std::initializer_list<napi_value>& args) const {
  2225. EscapableHandleScope scope(_env);
  2226. Napi::Value result = Value().Call(recv, args);
  2227. if (scope.Env().IsExceptionPending()) {
  2228. return Value();
  2229. }
  2230. return scope.Escape(result);
  2231. }
  2232. inline Napi::Value FunctionReference::Call(
  2233. napi_value recv, const std::vector<napi_value>& args) const {
  2234. EscapableHandleScope scope(_env);
  2235. Napi::Value result = Value().Call(recv, args);
  2236. if (scope.Env().IsExceptionPending()) {
  2237. return Value();
  2238. }
  2239. return scope.Escape(result);
  2240. }
  2241. inline Napi::Value FunctionReference::Call(
  2242. napi_value recv, size_t argc, const napi_value* args) const {
  2243. EscapableHandleScope scope(_env);
  2244. Napi::Value result = Value().Call(recv, argc, args);
  2245. if (scope.Env().IsExceptionPending()) {
  2246. return Value();
  2247. }
  2248. return scope.Escape(result);
  2249. }
  2250. inline Napi::Value FunctionReference::MakeCallback(
  2251. napi_value recv,
  2252. const std::initializer_list<napi_value>& args,
  2253. napi_async_context context) const {
  2254. EscapableHandleScope scope(_env);
  2255. Napi::Value result = Value().MakeCallback(recv, args, context);
  2256. if (scope.Env().IsExceptionPending()) {
  2257. return Value();
  2258. }
  2259. return scope.Escape(result);
  2260. }
  2261. inline Napi::Value FunctionReference::MakeCallback(
  2262. napi_value recv,
  2263. const std::vector<napi_value>& args,
  2264. napi_async_context context) const {
  2265. EscapableHandleScope scope(_env);
  2266. Napi::Value result = Value().MakeCallback(recv, args, context);
  2267. if (scope.Env().IsExceptionPending()) {
  2268. return Value();
  2269. }
  2270. return scope.Escape(result);
  2271. }
  2272. inline Napi::Value FunctionReference::MakeCallback(
  2273. napi_value recv,
  2274. size_t argc,
  2275. const napi_value* args,
  2276. napi_async_context context) const {
  2277. EscapableHandleScope scope(_env);
  2278. Napi::Value result = Value().MakeCallback(recv, argc, args, context);
  2279. if (scope.Env().IsExceptionPending()) {
  2280. return Value();
  2281. }
  2282. return scope.Escape(result);
  2283. }
  2284. inline Object FunctionReference::New(const std::initializer_list<napi_value>& args) const {
  2285. EscapableHandleScope scope(_env);
  2286. return scope.Escape(Value().New(args)).As<Object>();
  2287. }
  2288. inline Object FunctionReference::New(const std::vector<napi_value>& args) const {
  2289. EscapableHandleScope scope(_env);
  2290. return scope.Escape(Value().New(args)).As<Object>();
  2291. }
  2292. ////////////////////////////////////////////////////////////////////////////////
  2293. // CallbackInfo class
  2294. ////////////////////////////////////////////////////////////////////////////////
  2295. inline CallbackInfo::CallbackInfo(napi_env env, napi_callback_info info)
  2296. : _env(env), _info(info), _this(nullptr), _dynamicArgs(nullptr), _data(nullptr) {
  2297. _argc = _staticArgCount;
  2298. _argv = _staticArgs;
  2299. napi_status status = napi_get_cb_info(env, info, &_argc, _argv, &_this, &_data);
  2300. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2301. if (_argc > _staticArgCount) {
  2302. // Use either a fixed-size array (on the stack) or a dynamically-allocated
  2303. // array (on the heap) depending on the number of args.
  2304. _dynamicArgs = new napi_value[_argc];
  2305. _argv = _dynamicArgs;
  2306. status = napi_get_cb_info(env, info, &_argc, _argv, nullptr, nullptr);
  2307. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2308. }
  2309. }
  2310. inline CallbackInfo::~CallbackInfo() {
  2311. if (_dynamicArgs != nullptr) {
  2312. delete[] _dynamicArgs;
  2313. }
  2314. }
  2315. inline Value CallbackInfo::NewTarget() const {
  2316. napi_value newTarget;
  2317. napi_status status = napi_get_new_target(_env, _info, &newTarget);
  2318. NAPI_THROW_IF_FAILED(_env, status, Value());
  2319. return Value(_env, newTarget);
  2320. }
  2321. inline bool CallbackInfo::IsConstructCall() const {
  2322. return !NewTarget().IsEmpty();
  2323. }
  2324. inline Napi::Env CallbackInfo::Env() const {
  2325. return Napi::Env(_env);
  2326. }
  2327. inline size_t CallbackInfo::Length() const {
  2328. return _argc;
  2329. }
  2330. inline const Value CallbackInfo::operator [](size_t index) const {
  2331. return index < _argc ? Value(_env, _argv[index]) : Env().Undefined();
  2332. }
  2333. inline Value CallbackInfo::This() const {
  2334. if (_this == nullptr) {
  2335. return Env().Undefined();
  2336. }
  2337. return Object(_env, _this);
  2338. }
  2339. inline void* CallbackInfo::Data() const {
  2340. return _data;
  2341. }
  2342. inline void CallbackInfo::SetData(void* data) {
  2343. _data = data;
  2344. }
  2345. ////////////////////////////////////////////////////////////////////////////////
  2346. // PropertyDescriptor class
  2347. ////////////////////////////////////////////////////////////////////////////////
  2348. template <typename PropertyDescriptor::GetterCallback Getter>
  2349. PropertyDescriptor
  2350. PropertyDescriptor::Accessor(const char* utf8name,
  2351. napi_property_attributes attributes,
  2352. void* data) {
  2353. napi_property_descriptor desc = napi_property_descriptor();
  2354. desc.utf8name = utf8name;
  2355. desc.getter = &GetterCallbackWrapper<Getter>;
  2356. desc.attributes = attributes;
  2357. desc.data = data;
  2358. return desc;
  2359. }
  2360. template <typename PropertyDescriptor::GetterCallback Getter>
  2361. PropertyDescriptor
  2362. PropertyDescriptor::Accessor(const std::string& utf8name,
  2363. napi_property_attributes attributes,
  2364. void* data) {
  2365. return Accessor<Getter>(utf8name.c_str(), attributes, data);
  2366. }
  2367. template <typename PropertyDescriptor::GetterCallback Getter>
  2368. PropertyDescriptor
  2369. PropertyDescriptor::Accessor(Name name,
  2370. napi_property_attributes attributes,
  2371. void* data) {
  2372. napi_property_descriptor desc = napi_property_descriptor();
  2373. desc.name = name;
  2374. desc.getter = &GetterCallbackWrapper<Getter>;
  2375. desc.attributes = attributes;
  2376. desc.data = data;
  2377. return desc;
  2378. }
  2379. template <
  2380. typename PropertyDescriptor::GetterCallback Getter,
  2381. typename PropertyDescriptor::SetterCallback Setter>
  2382. PropertyDescriptor
  2383. PropertyDescriptor::Accessor(const char* utf8name,
  2384. napi_property_attributes attributes,
  2385. void* data) {
  2386. napi_property_descriptor desc = napi_property_descriptor();
  2387. desc.utf8name = utf8name;
  2388. desc.getter = &GetterCallbackWrapper<Getter>;
  2389. desc.setter = &SetterCallbackWrapper<Setter>;
  2390. desc.attributes = attributes;
  2391. desc.data = data;
  2392. return desc;
  2393. }
  2394. template <
  2395. typename PropertyDescriptor::GetterCallback Getter,
  2396. typename PropertyDescriptor::SetterCallback Setter>
  2397. PropertyDescriptor
  2398. PropertyDescriptor::Accessor(const std::string& utf8name,
  2399. napi_property_attributes attributes,
  2400. void* data) {
  2401. return Accessor<Getter, Setter>(utf8name.c_str(), attributes, data);
  2402. }
  2403. template <
  2404. typename PropertyDescriptor::GetterCallback Getter,
  2405. typename PropertyDescriptor::SetterCallback Setter>
  2406. PropertyDescriptor
  2407. PropertyDescriptor::Accessor(Name name,
  2408. napi_property_attributes attributes,
  2409. void* data) {
  2410. napi_property_descriptor desc = napi_property_descriptor();
  2411. desc.name = name;
  2412. desc.getter = &GetterCallbackWrapper<Getter>;
  2413. desc.setter = &SetterCallbackWrapper<Setter>;
  2414. desc.attributes = attributes;
  2415. desc.data = data;
  2416. return desc;
  2417. }
  2418. template <typename PropertyDescriptor::GetterCallback Getter>
  2419. napi_value
  2420. PropertyDescriptor::GetterCallbackWrapper(napi_env env,
  2421. napi_callback_info info) {
  2422. CallbackInfo cbInfo(env, info);
  2423. return Getter(cbInfo);
  2424. }
  2425. template <typename PropertyDescriptor::SetterCallback Setter>
  2426. napi_value
  2427. PropertyDescriptor::SetterCallbackWrapper(napi_env env,
  2428. napi_callback_info info) {
  2429. CallbackInfo cbInfo(env, info);
  2430. Setter(cbInfo);
  2431. return nullptr;
  2432. }
  2433. template <typename Getter>
  2434. inline PropertyDescriptor
  2435. PropertyDescriptor::Accessor(Napi::Env env,
  2436. Napi::Object object,
  2437. const char* utf8name,
  2438. Getter getter,
  2439. napi_property_attributes attributes,
  2440. void* data) {
  2441. typedef details::CallbackData<Getter, Napi::Value> CbData;
  2442. auto callbackData = new CbData({ getter, data });
  2443. napi_status status = AttachData(env, object, callbackData);
  2444. if (status != napi_ok) {
  2445. delete callbackData;
  2446. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  2447. }
  2448. return PropertyDescriptor({
  2449. utf8name,
  2450. nullptr,
  2451. nullptr,
  2452. CbData::Wrapper,
  2453. nullptr,
  2454. nullptr,
  2455. attributes,
  2456. callbackData
  2457. });
  2458. }
  2459. template <typename Getter>
  2460. inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
  2461. Napi::Object object,
  2462. const std::string& utf8name,
  2463. Getter getter,
  2464. napi_property_attributes attributes,
  2465. void* data) {
  2466. return Accessor(env, object, utf8name.c_str(), getter, attributes, data);
  2467. }
  2468. template <typename Getter>
  2469. inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
  2470. Napi::Object object,
  2471. Name name,
  2472. Getter getter,
  2473. napi_property_attributes attributes,
  2474. void* data) {
  2475. typedef details::CallbackData<Getter, Napi::Value> CbData;
  2476. auto callbackData = new CbData({ getter, data });
  2477. napi_status status = AttachData(env, object, callbackData);
  2478. if (status != napi_ok) {
  2479. delete callbackData;
  2480. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  2481. }
  2482. return PropertyDescriptor({
  2483. nullptr,
  2484. name,
  2485. nullptr,
  2486. CbData::Wrapper,
  2487. nullptr,
  2488. nullptr,
  2489. attributes,
  2490. callbackData
  2491. });
  2492. }
  2493. template <typename Getter, typename Setter>
  2494. inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
  2495. Napi::Object object,
  2496. const char* utf8name,
  2497. Getter getter,
  2498. Setter setter,
  2499. napi_property_attributes attributes,
  2500. void* data) {
  2501. typedef details::AccessorCallbackData<Getter, Setter> CbData;
  2502. auto callbackData = new CbData({ getter, setter, data });
  2503. napi_status status = AttachData(env, object, callbackData);
  2504. if (status != napi_ok) {
  2505. delete callbackData;
  2506. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  2507. }
  2508. return PropertyDescriptor({
  2509. utf8name,
  2510. nullptr,
  2511. nullptr,
  2512. CbData::GetterWrapper,
  2513. CbData::SetterWrapper,
  2514. nullptr,
  2515. attributes,
  2516. callbackData
  2517. });
  2518. }
  2519. template <typename Getter, typename Setter>
  2520. inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
  2521. Napi::Object object,
  2522. const std::string& utf8name,
  2523. Getter getter,
  2524. Setter setter,
  2525. napi_property_attributes attributes,
  2526. void* data) {
  2527. return Accessor(env, object, utf8name.c_str(), getter, setter, attributes, data);
  2528. }
  2529. template <typename Getter, typename Setter>
  2530. inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
  2531. Napi::Object object,
  2532. Name name,
  2533. Getter getter,
  2534. Setter setter,
  2535. napi_property_attributes attributes,
  2536. void* data) {
  2537. typedef details::AccessorCallbackData<Getter, Setter> CbData;
  2538. auto callbackData = new CbData({ getter, setter, data });
  2539. napi_status status = AttachData(env, object, callbackData);
  2540. if (status != napi_ok) {
  2541. delete callbackData;
  2542. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  2543. }
  2544. return PropertyDescriptor({
  2545. nullptr,
  2546. name,
  2547. nullptr,
  2548. CbData::GetterWrapper,
  2549. CbData::SetterWrapper,
  2550. nullptr,
  2551. attributes,
  2552. callbackData
  2553. });
  2554. }
  2555. template <typename Callable>
  2556. inline PropertyDescriptor PropertyDescriptor::Function(Napi::Env env,
  2557. Napi::Object /*object*/,
  2558. const char* utf8name,
  2559. Callable cb,
  2560. napi_property_attributes attributes,
  2561. void* data) {
  2562. return PropertyDescriptor({
  2563. utf8name,
  2564. nullptr,
  2565. nullptr,
  2566. nullptr,
  2567. nullptr,
  2568. Napi::Function::New(env, cb, utf8name, data),
  2569. attributes,
  2570. nullptr
  2571. });
  2572. }
  2573. template <typename Callable>
  2574. inline PropertyDescriptor PropertyDescriptor::Function(Napi::Env env,
  2575. Napi::Object object,
  2576. const std::string& utf8name,
  2577. Callable cb,
  2578. napi_property_attributes attributes,
  2579. void* data) {
  2580. return Function(env, object, utf8name.c_str(), cb, attributes, data);
  2581. }
  2582. template <typename Callable>
  2583. inline PropertyDescriptor PropertyDescriptor::Function(Napi::Env env,
  2584. Napi::Object /*object*/,
  2585. Name name,
  2586. Callable cb,
  2587. napi_property_attributes attributes,
  2588. void* data) {
  2589. return PropertyDescriptor({
  2590. nullptr,
  2591. name,
  2592. nullptr,
  2593. nullptr,
  2594. nullptr,
  2595. Napi::Function::New(env, cb, nullptr, data),
  2596. attributes,
  2597. nullptr
  2598. });
  2599. }
  2600. inline PropertyDescriptor PropertyDescriptor::Value(const char* utf8name,
  2601. napi_value value,
  2602. napi_property_attributes attributes) {
  2603. return PropertyDescriptor({
  2604. utf8name, nullptr, nullptr, nullptr, nullptr, value, attributes, nullptr
  2605. });
  2606. }
  2607. inline PropertyDescriptor PropertyDescriptor::Value(const std::string& utf8name,
  2608. napi_value value,
  2609. napi_property_attributes attributes) {
  2610. return Value(utf8name.c_str(), value, attributes);
  2611. }
  2612. inline PropertyDescriptor PropertyDescriptor::Value(napi_value name,
  2613. napi_value value,
  2614. napi_property_attributes attributes) {
  2615. return PropertyDescriptor({
  2616. nullptr, name, nullptr, nullptr, nullptr, value, attributes, nullptr
  2617. });
  2618. }
  2619. inline PropertyDescriptor PropertyDescriptor::Value(Name name,
  2620. Napi::Value value,
  2621. napi_property_attributes attributes) {
  2622. napi_value nameValue = name;
  2623. napi_value valueValue = value;
  2624. return PropertyDescriptor::Value(nameValue, valueValue, attributes);
  2625. }
  2626. inline PropertyDescriptor::PropertyDescriptor(napi_property_descriptor desc)
  2627. : _desc(desc) {
  2628. }
  2629. inline PropertyDescriptor::operator napi_property_descriptor&() {
  2630. return _desc;
  2631. }
  2632. inline PropertyDescriptor::operator const napi_property_descriptor&() const {
  2633. return _desc;
  2634. }
  2635. ////////////////////////////////////////////////////////////////////////////////
  2636. // ObjectWrap<T> class
  2637. ////////////////////////////////////////////////////////////////////////////////
  2638. template <typename T>
  2639. inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
  2640. napi_env env = callbackInfo.Env();
  2641. napi_value wrapper = callbackInfo.This();
  2642. napi_status status;
  2643. napi_ref ref;
  2644. status = napi_wrap(env, wrapper, this, FinalizeCallback, nullptr, &ref);
  2645. NAPI_THROW_IF_FAILED_VOID(env, status);
  2646. Reference<Object>* instanceRef = this;
  2647. *instanceRef = Reference<Object>(env, ref);
  2648. }
  2649. template <typename T>
  2650. inline ObjectWrap<T>::~ObjectWrap() {
  2651. // If the JS object still exists at this point, remove the finalizer added
  2652. // through `napi_wrap()`.
  2653. if (!IsEmpty()) {
  2654. Object object = Value();
  2655. // It is not valid to call `napi_remove_wrap()` with an empty `object`.
  2656. // This happens e.g. during garbage collection.
  2657. if (!object.IsEmpty() && _construction_failed) {
  2658. napi_remove_wrap(Env(), object, nullptr);
  2659. }
  2660. }
  2661. }
  2662. template<typename T>
  2663. inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
  2664. T* unwrapped;
  2665. napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
  2666. NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
  2667. return unwrapped;
  2668. }
  2669. template <typename T>
  2670. inline Function
  2671. ObjectWrap<T>::DefineClass(Napi::Env env,
  2672. const char* utf8name,
  2673. const size_t props_count,
  2674. const napi_property_descriptor* descriptors,
  2675. void* data) {
  2676. napi_status status;
  2677. std::vector<napi_property_descriptor> props(props_count);
  2678. // We copy the descriptors to a local array because before defining the class
  2679. // we must replace static method property descriptors with value property
  2680. // descriptors such that the value is a function-valued `napi_value` created
  2681. // with `CreateFunction()`.
  2682. //
  2683. // This replacement could be made for instance methods as well, but V8 aborts
  2684. // if we do that, because it expects methods defined on the prototype template
  2685. // to have `FunctionTemplate`s.
  2686. for (size_t index = 0; index < props_count; index++) {
  2687. props[index] = descriptors[index];
  2688. napi_property_descriptor* prop = &props[index];
  2689. if (prop->method == T::StaticMethodCallbackWrapper) {
  2690. status = CreateFunction(env,
  2691. utf8name,
  2692. prop->method,
  2693. static_cast<StaticMethodCallbackData*>(prop->data),
  2694. &(prop->value));
  2695. NAPI_THROW_IF_FAILED(env, status, Function());
  2696. prop->method = nullptr;
  2697. prop->data = nullptr;
  2698. } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
  2699. status = CreateFunction(env,
  2700. utf8name,
  2701. prop->method,
  2702. static_cast<StaticVoidMethodCallbackData*>(prop->data),
  2703. &(prop->value));
  2704. NAPI_THROW_IF_FAILED(env, status, Function());
  2705. prop->method = nullptr;
  2706. prop->data = nullptr;
  2707. }
  2708. }
  2709. napi_value value;
  2710. status = napi_define_class(env,
  2711. utf8name,
  2712. NAPI_AUTO_LENGTH,
  2713. T::ConstructorCallbackWrapper,
  2714. data,
  2715. props_count,
  2716. props.data(),
  2717. &value);
  2718. NAPI_THROW_IF_FAILED(env, status, Function());
  2719. // After defining the class we iterate once more over the property descriptors
  2720. // and attach the data associated with accessors and instance methods to the
  2721. // newly created JavaScript class.
  2722. for (size_t idx = 0; idx < props_count; idx++) {
  2723. const napi_property_descriptor* prop = &props[idx];
  2724. if (prop->getter == T::StaticGetterCallbackWrapper ||
  2725. prop->setter == T::StaticSetterCallbackWrapper) {
  2726. status = Napi::details::AttachData(env,
  2727. value,
  2728. static_cast<StaticAccessorCallbackData*>(prop->data));
  2729. NAPI_THROW_IF_FAILED(env, status, Function());
  2730. } else if (prop->getter == T::InstanceGetterCallbackWrapper ||
  2731. prop->setter == T::InstanceSetterCallbackWrapper) {
  2732. status = Napi::details::AttachData(env,
  2733. value,
  2734. static_cast<InstanceAccessorCallbackData*>(prop->data));
  2735. NAPI_THROW_IF_FAILED(env, status, Function());
  2736. } else if (prop->method != nullptr && !(prop->attributes & napi_static)) {
  2737. if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
  2738. status = Napi::details::AttachData(env,
  2739. value,
  2740. static_cast<InstanceVoidMethodCallbackData*>(prop->data));
  2741. NAPI_THROW_IF_FAILED(env, status, Function());
  2742. } else if (prop->method == T::InstanceMethodCallbackWrapper) {
  2743. status = Napi::details::AttachData(env,
  2744. value,
  2745. static_cast<InstanceMethodCallbackData*>(prop->data));
  2746. NAPI_THROW_IF_FAILED(env, status, Function());
  2747. }
  2748. }
  2749. }
  2750. return Function(env, value);
  2751. }
  2752. template <typename T>
  2753. inline Function ObjectWrap<T>::DefineClass(
  2754. Napi::Env env,
  2755. const char* utf8name,
  2756. const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
  2757. void* data) {
  2758. return DefineClass(env,
  2759. utf8name,
  2760. properties.size(),
  2761. reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
  2762. data);
  2763. }
  2764. template <typename T>
  2765. inline Function ObjectWrap<T>::DefineClass(
  2766. Napi::Env env,
  2767. const char* utf8name,
  2768. const std::vector<ClassPropertyDescriptor<T>>& properties,
  2769. void* data) {
  2770. return DefineClass(env,
  2771. utf8name,
  2772. properties.size(),
  2773. reinterpret_cast<const napi_property_descriptor*>(properties.data()),
  2774. data);
  2775. }
  2776. template <typename T>
  2777. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2778. const char* utf8name,
  2779. StaticVoidMethodCallback method,
  2780. napi_property_attributes attributes,
  2781. void* data) {
  2782. StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
  2783. napi_property_descriptor desc = napi_property_descriptor();
  2784. desc.utf8name = utf8name;
  2785. desc.method = T::StaticVoidMethodCallbackWrapper;
  2786. desc.data = callbackData;
  2787. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2788. return desc;
  2789. }
  2790. template <typename T>
  2791. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2792. const char* utf8name,
  2793. StaticMethodCallback method,
  2794. napi_property_attributes attributes,
  2795. void* data) {
  2796. StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
  2797. napi_property_descriptor desc = napi_property_descriptor();
  2798. desc.utf8name = utf8name;
  2799. desc.method = T::StaticMethodCallbackWrapper;
  2800. desc.data = callbackData;
  2801. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2802. return desc;
  2803. }
  2804. template <typename T>
  2805. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2806. Symbol name,
  2807. StaticVoidMethodCallback method,
  2808. napi_property_attributes attributes,
  2809. void* data) {
  2810. StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
  2811. napi_property_descriptor desc = napi_property_descriptor();
  2812. desc.name = name;
  2813. desc.method = T::StaticVoidMethodCallbackWrapper;
  2814. desc.data = callbackData;
  2815. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2816. return desc;
  2817. }
  2818. template <typename T>
  2819. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2820. Symbol name,
  2821. StaticMethodCallback method,
  2822. napi_property_attributes attributes,
  2823. void* data) {
  2824. StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
  2825. napi_property_descriptor desc = napi_property_descriptor();
  2826. desc.name = name;
  2827. desc.method = T::StaticMethodCallbackWrapper;
  2828. desc.data = callbackData;
  2829. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2830. return desc;
  2831. }
  2832. template <typename T>
  2833. template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
  2834. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2835. const char* utf8name,
  2836. napi_property_attributes attributes,
  2837. void* data) {
  2838. napi_property_descriptor desc = napi_property_descriptor();
  2839. desc.utf8name = utf8name;
  2840. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  2841. desc.data = data;
  2842. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2843. return desc;
  2844. }
  2845. template <typename T>
  2846. template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
  2847. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2848. Symbol name,
  2849. napi_property_attributes attributes,
  2850. void* data) {
  2851. napi_property_descriptor desc = napi_property_descriptor();
  2852. desc.name = name;
  2853. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  2854. desc.data = data;
  2855. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2856. return desc;
  2857. }
  2858. template <typename T>
  2859. template <typename ObjectWrap<T>::StaticMethodCallback method>
  2860. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2861. const char* utf8name,
  2862. napi_property_attributes attributes,
  2863. void* data) {
  2864. napi_property_descriptor desc = napi_property_descriptor();
  2865. desc.utf8name = utf8name;
  2866. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  2867. desc.data = data;
  2868. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2869. return desc;
  2870. }
  2871. template <typename T>
  2872. template <typename ObjectWrap<T>::StaticMethodCallback method>
  2873. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  2874. Symbol name,
  2875. napi_property_attributes attributes,
  2876. void* data) {
  2877. napi_property_descriptor desc = napi_property_descriptor();
  2878. desc.name = name;
  2879. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  2880. desc.data = data;
  2881. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2882. return desc;
  2883. }
  2884. template <typename T>
  2885. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  2886. const char* utf8name,
  2887. StaticGetterCallback getter,
  2888. StaticSetterCallback setter,
  2889. napi_property_attributes attributes,
  2890. void* data) {
  2891. StaticAccessorCallbackData* callbackData =
  2892. new StaticAccessorCallbackData({ getter, setter, data });
  2893. napi_property_descriptor desc = napi_property_descriptor();
  2894. desc.utf8name = utf8name;
  2895. desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
  2896. desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
  2897. desc.data = callbackData;
  2898. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2899. return desc;
  2900. }
  2901. template <typename T>
  2902. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  2903. Symbol name,
  2904. StaticGetterCallback getter,
  2905. StaticSetterCallback setter,
  2906. napi_property_attributes attributes,
  2907. void* data) {
  2908. StaticAccessorCallbackData* callbackData =
  2909. new StaticAccessorCallbackData({ getter, setter, data });
  2910. napi_property_descriptor desc = napi_property_descriptor();
  2911. desc.name = name;
  2912. desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
  2913. desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
  2914. desc.data = callbackData;
  2915. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2916. return desc;
  2917. }
  2918. template <typename T>
  2919. template <typename ObjectWrap<T>::StaticGetterCallback getter,
  2920. typename ObjectWrap<T>::StaticSetterCallback setter>
  2921. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  2922. const char* utf8name,
  2923. napi_property_attributes attributes,
  2924. void* data) {
  2925. napi_property_descriptor desc = napi_property_descriptor();
  2926. desc.utf8name = utf8name;
  2927. desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
  2928. desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
  2929. desc.data = data;
  2930. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2931. return desc;
  2932. }
  2933. template <typename T>
  2934. template <typename ObjectWrap<T>::StaticGetterCallback getter,
  2935. typename ObjectWrap<T>::StaticSetterCallback setter>
  2936. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  2937. Symbol name,
  2938. napi_property_attributes attributes,
  2939. void* data) {
  2940. napi_property_descriptor desc = napi_property_descriptor();
  2941. desc.name = name;
  2942. desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
  2943. desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
  2944. desc.data = data;
  2945. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  2946. return desc;
  2947. }
  2948. template <typename T>
  2949. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  2950. const char* utf8name,
  2951. InstanceVoidMethodCallback method,
  2952. napi_property_attributes attributes,
  2953. void* data) {
  2954. InstanceVoidMethodCallbackData* callbackData =
  2955. new InstanceVoidMethodCallbackData({ method, data});
  2956. napi_property_descriptor desc = napi_property_descriptor();
  2957. desc.utf8name = utf8name;
  2958. desc.method = T::InstanceVoidMethodCallbackWrapper;
  2959. desc.data = callbackData;
  2960. desc.attributes = attributes;
  2961. return desc;
  2962. }
  2963. template <typename T>
  2964. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  2965. const char* utf8name,
  2966. InstanceMethodCallback method,
  2967. napi_property_attributes attributes,
  2968. void* data) {
  2969. InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
  2970. napi_property_descriptor desc = napi_property_descriptor();
  2971. desc.utf8name = utf8name;
  2972. desc.method = T::InstanceMethodCallbackWrapper;
  2973. desc.data = callbackData;
  2974. desc.attributes = attributes;
  2975. return desc;
  2976. }
  2977. template <typename T>
  2978. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  2979. Symbol name,
  2980. InstanceVoidMethodCallback method,
  2981. napi_property_attributes attributes,
  2982. void* data) {
  2983. InstanceVoidMethodCallbackData* callbackData =
  2984. new InstanceVoidMethodCallbackData({ method, data});
  2985. napi_property_descriptor desc = napi_property_descriptor();
  2986. desc.name = name;
  2987. desc.method = T::InstanceVoidMethodCallbackWrapper;
  2988. desc.data = callbackData;
  2989. desc.attributes = attributes;
  2990. return desc;
  2991. }
  2992. template <typename T>
  2993. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  2994. Symbol name,
  2995. InstanceMethodCallback method,
  2996. napi_property_attributes attributes,
  2997. void* data) {
  2998. InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
  2999. napi_property_descriptor desc = napi_property_descriptor();
  3000. desc.name = name;
  3001. desc.method = T::InstanceMethodCallbackWrapper;
  3002. desc.data = callbackData;
  3003. desc.attributes = attributes;
  3004. return desc;
  3005. }
  3006. template <typename T>
  3007. template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
  3008. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  3009. const char* utf8name,
  3010. napi_property_attributes attributes,
  3011. void* data) {
  3012. napi_property_descriptor desc = napi_property_descriptor();
  3013. desc.utf8name = utf8name;
  3014. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  3015. desc.data = data;
  3016. desc.attributes = attributes;
  3017. return desc;
  3018. }
  3019. template <typename T>
  3020. template <typename ObjectWrap<T>::InstanceMethodCallback method>
  3021. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  3022. const char* utf8name,
  3023. napi_property_attributes attributes,
  3024. void* data) {
  3025. napi_property_descriptor desc = napi_property_descriptor();
  3026. desc.utf8name = utf8name;
  3027. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  3028. desc.data = data;
  3029. desc.attributes = attributes;
  3030. return desc;
  3031. }
  3032. template <typename T>
  3033. template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
  3034. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  3035. Symbol name,
  3036. napi_property_attributes attributes,
  3037. void* data) {
  3038. napi_property_descriptor desc = napi_property_descriptor();
  3039. desc.name = name;
  3040. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  3041. desc.data = data;
  3042. desc.attributes = attributes;
  3043. return desc;
  3044. }
  3045. template <typename T>
  3046. template <typename ObjectWrap<T>::InstanceMethodCallback method>
  3047. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
  3048. Symbol name,
  3049. napi_property_attributes attributes,
  3050. void* data) {
  3051. napi_property_descriptor desc = napi_property_descriptor();
  3052. desc.name = name;
  3053. desc.method = &ObjectWrap<T>::WrappedMethod<method>;
  3054. desc.data = data;
  3055. desc.attributes = attributes;
  3056. return desc;
  3057. }
  3058. template <typename T>
  3059. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
  3060. const char* utf8name,
  3061. InstanceGetterCallback getter,
  3062. InstanceSetterCallback setter,
  3063. napi_property_attributes attributes,
  3064. void* data) {
  3065. InstanceAccessorCallbackData* callbackData =
  3066. new InstanceAccessorCallbackData({ getter, setter, data });
  3067. napi_property_descriptor desc = napi_property_descriptor();
  3068. desc.utf8name = utf8name;
  3069. desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
  3070. desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
  3071. desc.data = callbackData;
  3072. desc.attributes = attributes;
  3073. return desc;
  3074. }
  3075. template <typename T>
  3076. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
  3077. Symbol name,
  3078. InstanceGetterCallback getter,
  3079. InstanceSetterCallback setter,
  3080. napi_property_attributes attributes,
  3081. void* data) {
  3082. InstanceAccessorCallbackData* callbackData =
  3083. new InstanceAccessorCallbackData({ getter, setter, data });
  3084. napi_property_descriptor desc = napi_property_descriptor();
  3085. desc.name = name;
  3086. desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
  3087. desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
  3088. desc.data = callbackData;
  3089. desc.attributes = attributes;
  3090. return desc;
  3091. }
  3092. template <typename T>
  3093. template <typename ObjectWrap<T>::InstanceGetterCallback getter,
  3094. typename ObjectWrap<T>::InstanceSetterCallback setter>
  3095. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
  3096. const char* utf8name,
  3097. napi_property_attributes attributes,
  3098. void* data) {
  3099. napi_property_descriptor desc = napi_property_descriptor();
  3100. desc.utf8name = utf8name;
  3101. desc.getter = This::WrapGetter(This::GetterTag<getter>());
  3102. desc.setter = This::WrapSetter(This::SetterTag<setter>());
  3103. desc.data = data;
  3104. desc.attributes = attributes;
  3105. return desc;
  3106. }
  3107. template <typename T>
  3108. template <typename ObjectWrap<T>::InstanceGetterCallback getter,
  3109. typename ObjectWrap<T>::InstanceSetterCallback setter>
  3110. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
  3111. Symbol name,
  3112. napi_property_attributes attributes,
  3113. void* data) {
  3114. napi_property_descriptor desc = napi_property_descriptor();
  3115. desc.name = name;
  3116. desc.getter = This::WrapGetter(This::GetterTag<getter>());
  3117. desc.setter = This::WrapSetter(This::SetterTag<setter>());
  3118. desc.data = data;
  3119. desc.attributes = attributes;
  3120. return desc;
  3121. }
  3122. template <typename T>
  3123. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8name,
  3124. Napi::Value value, napi_property_attributes attributes) {
  3125. napi_property_descriptor desc = napi_property_descriptor();
  3126. desc.utf8name = utf8name;
  3127. desc.value = value;
  3128. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  3129. return desc;
  3130. }
  3131. template <typename T>
  3132. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
  3133. Napi::Value value, napi_property_attributes attributes) {
  3134. napi_property_descriptor desc = napi_property_descriptor();
  3135. desc.name = name;
  3136. desc.value = value;
  3137. desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
  3138. return desc;
  3139. }
  3140. template <typename T>
  3141. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
  3142. const char* utf8name,
  3143. Napi::Value value,
  3144. napi_property_attributes attributes) {
  3145. napi_property_descriptor desc = napi_property_descriptor();
  3146. desc.utf8name = utf8name;
  3147. desc.value = value;
  3148. desc.attributes = attributes;
  3149. return desc;
  3150. }
  3151. template <typename T>
  3152. inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
  3153. Symbol name,
  3154. Napi::Value value,
  3155. napi_property_attributes attributes) {
  3156. napi_property_descriptor desc = napi_property_descriptor();
  3157. desc.name = name;
  3158. desc.value = value;
  3159. desc.attributes = attributes;
  3160. return desc;
  3161. }
  3162. template <typename T>
  3163. inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
  3164. template <typename T>
  3165. inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
  3166. napi_env env,
  3167. napi_callback_info info) {
  3168. napi_value new_target;
  3169. napi_status status = napi_get_new_target(env, info, &new_target);
  3170. if (status != napi_ok) return nullptr;
  3171. bool isConstructCall = (new_target != nullptr);
  3172. if (!isConstructCall) {
  3173. napi_throw_type_error(env, nullptr, "Class constructors cannot be invoked without 'new'");
  3174. return nullptr;
  3175. }
  3176. napi_value wrapper = details::WrapCallback([&] {
  3177. CallbackInfo callbackInfo(env, info);
  3178. T* instance = new T(callbackInfo);
  3179. #ifdef NAPI_CPP_EXCEPTIONS
  3180. instance->_construction_failed = false;
  3181. #else
  3182. if (callbackInfo.Env().IsExceptionPending()) {
  3183. // We need to clear the exception so that removing the wrap might work.
  3184. Error e = callbackInfo.Env().GetAndClearPendingException();
  3185. delete instance;
  3186. e.ThrowAsJavaScriptException();
  3187. } else {
  3188. instance->_construction_failed = false;
  3189. }
  3190. # endif // NAPI_CPP_EXCEPTIONS
  3191. return callbackInfo.This();
  3192. });
  3193. return wrapper;
  3194. }
  3195. template <typename T>
  3196. inline napi_value ObjectWrap<T>::StaticVoidMethodCallbackWrapper(
  3197. napi_env env,
  3198. napi_callback_info info) {
  3199. return details::WrapCallback([&] {
  3200. CallbackInfo callbackInfo(env, info);
  3201. StaticVoidMethodCallbackData* callbackData =
  3202. reinterpret_cast<StaticVoidMethodCallbackData*>(callbackInfo.Data());
  3203. callbackInfo.SetData(callbackData->data);
  3204. callbackData->callback(callbackInfo);
  3205. return nullptr;
  3206. });
  3207. }
  3208. template <typename T>
  3209. inline napi_value ObjectWrap<T>::StaticMethodCallbackWrapper(
  3210. napi_env env,
  3211. napi_callback_info info) {
  3212. return details::WrapCallback([&] {
  3213. CallbackInfo callbackInfo(env, info);
  3214. StaticMethodCallbackData* callbackData =
  3215. reinterpret_cast<StaticMethodCallbackData*>(callbackInfo.Data());
  3216. callbackInfo.SetData(callbackData->data);
  3217. return callbackData->callback(callbackInfo);
  3218. });
  3219. }
  3220. template <typename T>
  3221. inline napi_value ObjectWrap<T>::StaticGetterCallbackWrapper(
  3222. napi_env env,
  3223. napi_callback_info info) {
  3224. return details::WrapCallback([&] {
  3225. CallbackInfo callbackInfo(env, info);
  3226. StaticAccessorCallbackData* callbackData =
  3227. reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
  3228. callbackInfo.SetData(callbackData->data);
  3229. return callbackData->getterCallback(callbackInfo);
  3230. });
  3231. }
  3232. template <typename T>
  3233. inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
  3234. napi_env env,
  3235. napi_callback_info info) {
  3236. return details::WrapCallback([&] {
  3237. CallbackInfo callbackInfo(env, info);
  3238. StaticAccessorCallbackData* callbackData =
  3239. reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
  3240. callbackInfo.SetData(callbackData->data);
  3241. callbackData->setterCallback(callbackInfo, callbackInfo[0]);
  3242. return nullptr;
  3243. });
  3244. }
  3245. template <typename T>
  3246. inline napi_value ObjectWrap<T>::InstanceVoidMethodCallbackWrapper(
  3247. napi_env env,
  3248. napi_callback_info info) {
  3249. return details::WrapCallback([&] {
  3250. CallbackInfo callbackInfo(env, info);
  3251. InstanceVoidMethodCallbackData* callbackData =
  3252. reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
  3253. callbackInfo.SetData(callbackData->data);
  3254. T* instance = Unwrap(callbackInfo.This().As<Object>());
  3255. auto cb = callbackData->callback;
  3256. (instance->*cb)(callbackInfo);
  3257. return nullptr;
  3258. });
  3259. }
  3260. template <typename T>
  3261. inline napi_value ObjectWrap<T>::InstanceMethodCallbackWrapper(
  3262. napi_env env,
  3263. napi_callback_info info) {
  3264. return details::WrapCallback([&] {
  3265. CallbackInfo callbackInfo(env, info);
  3266. InstanceMethodCallbackData* callbackData =
  3267. reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
  3268. callbackInfo.SetData(callbackData->data);
  3269. T* instance = Unwrap(callbackInfo.This().As<Object>());
  3270. auto cb = callbackData->callback;
  3271. return (instance->*cb)(callbackInfo);
  3272. });
  3273. }
  3274. template <typename T>
  3275. inline napi_value ObjectWrap<T>::InstanceGetterCallbackWrapper(
  3276. napi_env env,
  3277. napi_callback_info info) {
  3278. return details::WrapCallback([&] {
  3279. CallbackInfo callbackInfo(env, info);
  3280. InstanceAccessorCallbackData* callbackData =
  3281. reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
  3282. callbackInfo.SetData(callbackData->data);
  3283. T* instance = Unwrap(callbackInfo.This().As<Object>());
  3284. auto cb = callbackData->getterCallback;
  3285. return (instance->*cb)(callbackInfo);
  3286. });
  3287. }
  3288. template <typename T>
  3289. inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
  3290. napi_env env,
  3291. napi_callback_info info) {
  3292. return details::WrapCallback([&] {
  3293. CallbackInfo callbackInfo(env, info);
  3294. InstanceAccessorCallbackData* callbackData =
  3295. reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
  3296. callbackInfo.SetData(callbackData->data);
  3297. T* instance = Unwrap(callbackInfo.This().As<Object>());
  3298. auto cb = callbackData->setterCallback;
  3299. (instance->*cb)(callbackInfo, callbackInfo[0]);
  3300. return nullptr;
  3301. });
  3302. }
  3303. template <typename T>
  3304. inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
  3305. ObjectWrap<T>* instance = static_cast<ObjectWrap<T>*>(data);
  3306. instance->Finalize(Napi::Env(env));
  3307. delete instance;
  3308. }
  3309. template <typename T>
  3310. template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
  3311. inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
  3312. return details::WrapCallback([&] {
  3313. method(CallbackInfo(env, info));
  3314. return nullptr;
  3315. });
  3316. }
  3317. template <typename T>
  3318. template <typename ObjectWrap<T>::StaticMethodCallback method>
  3319. inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
  3320. return details::WrapCallback([&] {
  3321. return method(CallbackInfo(env, info));
  3322. });
  3323. }
  3324. template <typename T>
  3325. template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
  3326. inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
  3327. return details::WrapCallback([&] {
  3328. const CallbackInfo cbInfo(env, info);
  3329. T* instance = Unwrap(cbInfo.This().As<Object>());
  3330. (instance->*method)(cbInfo);
  3331. return nullptr;
  3332. });
  3333. }
  3334. template <typename T>
  3335. template <typename ObjectWrap<T>::InstanceMethodCallback method>
  3336. inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
  3337. return details::WrapCallback([&] {
  3338. const CallbackInfo cbInfo(env, info);
  3339. T* instance = Unwrap(cbInfo.This().As<Object>());
  3340. return (instance->*method)(cbInfo);
  3341. });
  3342. }
  3343. template <typename T>
  3344. template <typename ObjectWrap<T>::StaticSetterCallback method>
  3345. inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
  3346. return details::WrapCallback([&] {
  3347. const CallbackInfo cbInfo(env, info);
  3348. method(cbInfo, cbInfo[0]);
  3349. return nullptr;
  3350. });
  3351. }
  3352. template <typename T>
  3353. template <typename ObjectWrap<T>::InstanceSetterCallback method>
  3354. inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
  3355. return details::WrapCallback([&] {
  3356. const CallbackInfo cbInfo(env, info);
  3357. T* instance = Unwrap(cbInfo.This().As<Object>());
  3358. (instance->*method)(cbInfo, cbInfo[0]);
  3359. return nullptr;
  3360. });
  3361. }
  3362. ////////////////////////////////////////////////////////////////////////////////
  3363. // HandleScope class
  3364. ////////////////////////////////////////////////////////////////////////////////
  3365. inline HandleScope::HandleScope(napi_env env, napi_handle_scope scope)
  3366. : _env(env), _scope(scope) {
  3367. }
  3368. inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
  3369. napi_status status = napi_open_handle_scope(_env, &_scope);
  3370. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3371. }
  3372. inline HandleScope::~HandleScope() {
  3373. napi_status status = napi_close_handle_scope(_env, _scope);
  3374. NAPI_FATAL_IF_FAILED(status,
  3375. "HandleScope::~HandleScope",
  3376. "napi_close_handle_scope");
  3377. }
  3378. inline HandleScope::operator napi_handle_scope() const {
  3379. return _scope;
  3380. }
  3381. inline Napi::Env HandleScope::Env() const {
  3382. return Napi::Env(_env);
  3383. }
  3384. ////////////////////////////////////////////////////////////////////////////////
  3385. // EscapableHandleScope class
  3386. ////////////////////////////////////////////////////////////////////////////////
  3387. inline EscapableHandleScope::EscapableHandleScope(
  3388. napi_env env, napi_escapable_handle_scope scope) : _env(env), _scope(scope) {
  3389. }
  3390. inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
  3391. napi_status status = napi_open_escapable_handle_scope(_env, &_scope);
  3392. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3393. }
  3394. inline EscapableHandleScope::~EscapableHandleScope() {
  3395. napi_status status = napi_close_escapable_handle_scope(_env, _scope);
  3396. NAPI_FATAL_IF_FAILED(status,
  3397. "EscapableHandleScope::~EscapableHandleScope",
  3398. "napi_close_escapable_handle_scope");
  3399. }
  3400. inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
  3401. return _scope;
  3402. }
  3403. inline Napi::Env EscapableHandleScope::Env() const {
  3404. return Napi::Env(_env);
  3405. }
  3406. inline Value EscapableHandleScope::Escape(napi_value escapee) {
  3407. napi_value result;
  3408. napi_status status = napi_escape_handle(_env, _scope, escapee, &result);
  3409. NAPI_THROW_IF_FAILED(_env, status, Value());
  3410. return Value(_env, result);
  3411. }
  3412. #if (NAPI_VERSION > 2)
  3413. ////////////////////////////////////////////////////////////////////////////////
  3414. // CallbackScope class
  3415. ////////////////////////////////////////////////////////////////////////////////
  3416. inline CallbackScope::CallbackScope(
  3417. napi_env env, napi_callback_scope scope) : _env(env), _scope(scope) {
  3418. }
  3419. inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
  3420. : _env(env) {
  3421. napi_status status = napi_open_callback_scope(
  3422. _env, Object::New(env), context, &_scope);
  3423. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3424. }
  3425. inline CallbackScope::~CallbackScope() {
  3426. napi_status status = napi_close_callback_scope(_env, _scope);
  3427. NAPI_FATAL_IF_FAILED(status,
  3428. "CallbackScope::~CallbackScope",
  3429. "napi_close_callback_scope");
  3430. }
  3431. inline CallbackScope::operator napi_callback_scope() const {
  3432. return _scope;
  3433. }
  3434. inline Napi::Env CallbackScope::Env() const {
  3435. return Napi::Env(_env);
  3436. }
  3437. #endif
  3438. ////////////////////////////////////////////////////////////////////////////////
  3439. // AsyncContext class
  3440. ////////////////////////////////////////////////////////////////////////////////
  3441. inline AsyncContext::AsyncContext(napi_env env, const char* resource_name)
  3442. : AsyncContext(env, resource_name, Object::New(env)) {
  3443. }
  3444. inline AsyncContext::AsyncContext(napi_env env,
  3445. const char* resource_name,
  3446. const Object& resource)
  3447. : _env(env),
  3448. _context(nullptr) {
  3449. napi_value resource_id;
  3450. napi_status status = napi_create_string_utf8(
  3451. _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
  3452. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3453. status = napi_async_init(_env, resource, resource_id, &_context);
  3454. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3455. }
  3456. inline AsyncContext::~AsyncContext() {
  3457. if (_context != nullptr) {
  3458. napi_async_destroy(_env, _context);
  3459. _context = nullptr;
  3460. }
  3461. }
  3462. inline AsyncContext::AsyncContext(AsyncContext&& other) {
  3463. _env = other._env;
  3464. other._env = nullptr;
  3465. _context = other._context;
  3466. other._context = nullptr;
  3467. }
  3468. inline AsyncContext& AsyncContext::operator =(AsyncContext&& other) {
  3469. _env = other._env;
  3470. other._env = nullptr;
  3471. _context = other._context;
  3472. other._context = nullptr;
  3473. return *this;
  3474. }
  3475. inline AsyncContext::operator napi_async_context() const {
  3476. return _context;
  3477. }
  3478. inline Napi::Env AsyncContext::Env() const {
  3479. return Napi::Env(_env);
  3480. }
  3481. ////////////////////////////////////////////////////////////////////////////////
  3482. // AsyncWorker class
  3483. ////////////////////////////////////////////////////////////////////////////////
  3484. inline AsyncWorker::AsyncWorker(const Function& callback)
  3485. : AsyncWorker(callback, "generic") {
  3486. }
  3487. inline AsyncWorker::AsyncWorker(const Function& callback,
  3488. const char* resource_name)
  3489. : AsyncWorker(callback, resource_name, Object::New(callback.Env())) {
  3490. }
  3491. inline AsyncWorker::AsyncWorker(const Function& callback,
  3492. const char* resource_name,
  3493. const Object& resource)
  3494. : AsyncWorker(Object::New(callback.Env()),
  3495. callback,
  3496. resource_name,
  3497. resource) {
  3498. }
  3499. inline AsyncWorker::AsyncWorker(const Object& receiver,
  3500. const Function& callback)
  3501. : AsyncWorker(receiver, callback, "generic") {
  3502. }
  3503. inline AsyncWorker::AsyncWorker(const Object& receiver,
  3504. const Function& callback,
  3505. const char* resource_name)
  3506. : AsyncWorker(receiver,
  3507. callback,
  3508. resource_name,
  3509. Object::New(callback.Env())) {
  3510. }
  3511. inline AsyncWorker::AsyncWorker(const Object& receiver,
  3512. const Function& callback,
  3513. const char* resource_name,
  3514. const Object& resource)
  3515. : _env(callback.Env()),
  3516. _receiver(Napi::Persistent(receiver)),
  3517. _callback(Napi::Persistent(callback)),
  3518. _suppress_destruct(false) {
  3519. napi_value resource_id;
  3520. napi_status status = napi_create_string_latin1(
  3521. _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
  3522. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3523. status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
  3524. OnAsyncWorkComplete, this, &_work);
  3525. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3526. }
  3527. inline AsyncWorker::AsyncWorker(Napi::Env env)
  3528. : AsyncWorker(env, "generic") {
  3529. }
  3530. inline AsyncWorker::AsyncWorker(Napi::Env env,
  3531. const char* resource_name)
  3532. : AsyncWorker(env, resource_name, Object::New(env)) {
  3533. }
  3534. inline AsyncWorker::AsyncWorker(Napi::Env env,
  3535. const char* resource_name,
  3536. const Object& resource)
  3537. : _env(env),
  3538. _receiver(),
  3539. _callback(),
  3540. _suppress_destruct(false) {
  3541. napi_value resource_id;
  3542. napi_status status = napi_create_string_latin1(
  3543. _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
  3544. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3545. status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
  3546. OnAsyncWorkComplete, this, &_work);
  3547. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3548. }
  3549. inline AsyncWorker::~AsyncWorker() {
  3550. if (_work != nullptr) {
  3551. napi_delete_async_work(_env, _work);
  3552. _work = nullptr;
  3553. }
  3554. }
  3555. inline void AsyncWorker::Destroy() {
  3556. delete this;
  3557. }
  3558. inline AsyncWorker::AsyncWorker(AsyncWorker&& other) {
  3559. _env = other._env;
  3560. other._env = nullptr;
  3561. _work = other._work;
  3562. other._work = nullptr;
  3563. _receiver = std::move(other._receiver);
  3564. _callback = std::move(other._callback);
  3565. _error = std::move(other._error);
  3566. _suppress_destruct = other._suppress_destruct;
  3567. }
  3568. inline AsyncWorker& AsyncWorker::operator =(AsyncWorker&& other) {
  3569. _env = other._env;
  3570. other._env = nullptr;
  3571. _work = other._work;
  3572. other._work = nullptr;
  3573. _receiver = std::move(other._receiver);
  3574. _callback = std::move(other._callback);
  3575. _error = std::move(other._error);
  3576. _suppress_destruct = other._suppress_destruct;
  3577. return *this;
  3578. }
  3579. inline AsyncWorker::operator napi_async_work() const {
  3580. return _work;
  3581. }
  3582. inline Napi::Env AsyncWorker::Env() const {
  3583. return Napi::Env(_env);
  3584. }
  3585. inline void AsyncWorker::Queue() {
  3586. napi_status status = napi_queue_async_work(_env, _work);
  3587. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3588. }
  3589. inline void AsyncWorker::Cancel() {
  3590. napi_status status = napi_cancel_async_work(_env, _work);
  3591. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3592. }
  3593. inline ObjectReference& AsyncWorker::Receiver() {
  3594. return _receiver;
  3595. }
  3596. inline FunctionReference& AsyncWorker::Callback() {
  3597. return _callback;
  3598. }
  3599. inline void AsyncWorker::SuppressDestruct() {
  3600. _suppress_destruct = true;
  3601. }
  3602. inline void AsyncWorker::OnOK() {
  3603. if (!_callback.IsEmpty()) {
  3604. _callback.Call(_receiver.Value(), GetResult(_callback.Env()));
  3605. }
  3606. }
  3607. inline void AsyncWorker::OnError(const Error& e) {
  3608. if (!_callback.IsEmpty()) {
  3609. _callback.Call(_receiver.Value(), std::initializer_list<napi_value>{ e.Value() });
  3610. }
  3611. }
  3612. inline void AsyncWorker::SetError(const std::string& error) {
  3613. _error = error;
  3614. }
  3615. inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
  3616. return {};
  3617. }
  3618. // The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT
  3619. // use it within this method, as it does not run on the JavaScript thread and
  3620. // must not run any method that would cause JavaScript to run. In practice,
  3621. // this means that almost any use of napi_env will be incorrect.
  3622. inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) {
  3623. AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
  3624. self->OnExecute(env);
  3625. }
  3626. // The OnExecute method receives an napi_env argument. However, do NOT
  3627. // use it within this method, as it does not run on the JavaScript thread and
  3628. // must not run any method that would cause JavaScript to run. In practice,
  3629. // this means that almost any use of napi_env will be incorrect.
  3630. inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) {
  3631. #ifdef NAPI_CPP_EXCEPTIONS
  3632. try {
  3633. Execute();
  3634. } catch (const std::exception& e) {
  3635. SetError(e.what());
  3636. }
  3637. #else // NAPI_CPP_EXCEPTIONS
  3638. Execute();
  3639. #endif // NAPI_CPP_EXCEPTIONS
  3640. }
  3641. inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
  3642. napi_status status,
  3643. void* asyncworker) {
  3644. AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
  3645. self->OnWorkComplete(env, status);
  3646. }
  3647. inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
  3648. if (status != napi_cancelled) {
  3649. HandleScope scope(_env);
  3650. details::WrapCallback([&] {
  3651. if (_error.size() == 0) {
  3652. OnOK();
  3653. }
  3654. else {
  3655. OnError(Error::New(_env, _error));
  3656. }
  3657. return nullptr;
  3658. });
  3659. }
  3660. if (!_suppress_destruct) {
  3661. Destroy();
  3662. }
  3663. }
  3664. #if (NAPI_VERSION > 3)
  3665. ////////////////////////////////////////////////////////////////////////////////
  3666. // ThreadSafeFunction class
  3667. ////////////////////////////////////////////////////////////////////////////////
  3668. // static
  3669. template <typename ResourceString>
  3670. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3671. const Function& callback,
  3672. ResourceString resourceName,
  3673. size_t maxQueueSize,
  3674. size_t initialThreadCount) {
  3675. return New(env, callback, Object(), resourceName, maxQueueSize,
  3676. initialThreadCount);
  3677. }
  3678. // static
  3679. template <typename ResourceString, typename ContextType>
  3680. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3681. const Function& callback,
  3682. ResourceString resourceName,
  3683. size_t maxQueueSize,
  3684. size_t initialThreadCount,
  3685. ContextType* context) {
  3686. return New(env, callback, Object(), resourceName, maxQueueSize,
  3687. initialThreadCount, context);
  3688. }
  3689. // static
  3690. template <typename ResourceString, typename Finalizer>
  3691. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3692. const Function& callback,
  3693. ResourceString resourceName,
  3694. size_t maxQueueSize,
  3695. size_t initialThreadCount,
  3696. Finalizer finalizeCallback) {
  3697. return New(env, callback, Object(), resourceName, maxQueueSize,
  3698. initialThreadCount, finalizeCallback);
  3699. }
  3700. // static
  3701. template <typename ResourceString, typename Finalizer,
  3702. typename FinalizerDataType>
  3703. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3704. const Function& callback,
  3705. ResourceString resourceName,
  3706. size_t maxQueueSize,
  3707. size_t initialThreadCount,
  3708. Finalizer finalizeCallback,
  3709. FinalizerDataType* data) {
  3710. return New(env, callback, Object(), resourceName, maxQueueSize,
  3711. initialThreadCount, finalizeCallback, data);
  3712. }
  3713. // static
  3714. template <typename ResourceString, typename ContextType, typename Finalizer>
  3715. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3716. const Function& callback,
  3717. ResourceString resourceName,
  3718. size_t maxQueueSize,
  3719. size_t initialThreadCount,
  3720. ContextType* context,
  3721. Finalizer finalizeCallback) {
  3722. return New(env, callback, Object(), resourceName, maxQueueSize,
  3723. initialThreadCount, context, finalizeCallback);
  3724. }
  3725. // static
  3726. template <typename ResourceString, typename ContextType,
  3727. typename Finalizer, typename FinalizerDataType>
  3728. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3729. const Function& callback,
  3730. ResourceString resourceName,
  3731. size_t maxQueueSize,
  3732. size_t initialThreadCount,
  3733. ContextType* context,
  3734. Finalizer finalizeCallback,
  3735. FinalizerDataType* data) {
  3736. return New(env, callback, Object(), resourceName, maxQueueSize,
  3737. initialThreadCount, context, finalizeCallback, data);
  3738. }
  3739. // static
  3740. template <typename ResourceString>
  3741. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3742. const Function& callback,
  3743. const Object& resource,
  3744. ResourceString resourceName,
  3745. size_t maxQueueSize,
  3746. size_t initialThreadCount) {
  3747. return New(env, callback, resource, resourceName, maxQueueSize,
  3748. initialThreadCount, static_cast<void*>(nullptr) /* context */);
  3749. }
  3750. // static
  3751. template <typename ResourceString, typename ContextType>
  3752. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3753. const Function& callback,
  3754. const Object& resource,
  3755. ResourceString resourceName,
  3756. size_t maxQueueSize,
  3757. size_t initialThreadCount,
  3758. ContextType* context) {
  3759. return New(env, callback, resource, resourceName, maxQueueSize,
  3760. initialThreadCount, context,
  3761. [](Env, ContextType*) {} /* empty finalizer */);
  3762. }
  3763. // static
  3764. template <typename ResourceString, typename Finalizer>
  3765. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3766. const Function& callback,
  3767. const Object& resource,
  3768. ResourceString resourceName,
  3769. size_t maxQueueSize,
  3770. size_t initialThreadCount,
  3771. Finalizer finalizeCallback) {
  3772. return New(env, callback, resource, resourceName, maxQueueSize,
  3773. initialThreadCount, static_cast<void*>(nullptr) /* context */,
  3774. finalizeCallback, static_cast<void*>(nullptr) /* data */,
  3775. details::ThreadSafeFinalize<void, Finalizer>::Wrapper);
  3776. }
  3777. // static
  3778. template <typename ResourceString, typename Finalizer,
  3779. typename FinalizerDataType>
  3780. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3781. const Function& callback,
  3782. const Object& resource,
  3783. ResourceString resourceName,
  3784. size_t maxQueueSize,
  3785. size_t initialThreadCount,
  3786. Finalizer finalizeCallback,
  3787. FinalizerDataType* data) {
  3788. return New(env, callback, resource, resourceName, maxQueueSize,
  3789. initialThreadCount, static_cast<void*>(nullptr) /* context */,
  3790. finalizeCallback, data,
  3791. details::ThreadSafeFinalize<
  3792. void, Finalizer, FinalizerDataType>::FinalizeWrapperWithData);
  3793. }
  3794. // static
  3795. template <typename ResourceString, typename ContextType, typename Finalizer>
  3796. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3797. const Function& callback,
  3798. const Object& resource,
  3799. ResourceString resourceName,
  3800. size_t maxQueueSize,
  3801. size_t initialThreadCount,
  3802. ContextType* context,
  3803. Finalizer finalizeCallback) {
  3804. return New(env, callback, resource, resourceName, maxQueueSize,
  3805. initialThreadCount, context, finalizeCallback,
  3806. static_cast<void*>(nullptr) /* data */,
  3807. details::ThreadSafeFinalize<
  3808. ContextType, Finalizer>::FinalizeWrapperWithContext);
  3809. }
  3810. // static
  3811. template <typename ResourceString, typename ContextType,
  3812. typename Finalizer, typename FinalizerDataType>
  3813. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3814. const Function& callback,
  3815. const Object& resource,
  3816. ResourceString resourceName,
  3817. size_t maxQueueSize,
  3818. size_t initialThreadCount,
  3819. ContextType* context,
  3820. Finalizer finalizeCallback,
  3821. FinalizerDataType* data) {
  3822. return New(env, callback, resource, resourceName, maxQueueSize,
  3823. initialThreadCount, context, finalizeCallback, data,
  3824. details::ThreadSafeFinalize<ContextType, Finalizer,
  3825. FinalizerDataType>::FinalizeFinalizeWrapperWithDataAndContext);
  3826. }
  3827. inline ThreadSafeFunction::ThreadSafeFunction()
  3828. : _tsfn() {
  3829. }
  3830. inline ThreadSafeFunction::ThreadSafeFunction(
  3831. napi_threadsafe_function tsfn)
  3832. : _tsfn(tsfn) {
  3833. }
  3834. inline ThreadSafeFunction::operator napi_threadsafe_function() const {
  3835. return _tsfn;
  3836. }
  3837. inline napi_status ThreadSafeFunction::BlockingCall() const {
  3838. return CallInternal(nullptr, napi_tsfn_blocking);
  3839. }
  3840. template <>
  3841. inline napi_status ThreadSafeFunction::BlockingCall(
  3842. void* data) const {
  3843. return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
  3844. }
  3845. template <typename Callback>
  3846. inline napi_status ThreadSafeFunction::BlockingCall(
  3847. Callback callback) const {
  3848. return CallInternal(new CallbackWrapper(callback), napi_tsfn_blocking);
  3849. }
  3850. template <typename DataType, typename Callback>
  3851. inline napi_status ThreadSafeFunction::BlockingCall(
  3852. DataType* data, Callback callback) const {
  3853. auto wrapper = [data, callback](Env env, Function jsCallback) {
  3854. callback(env, jsCallback, data);
  3855. };
  3856. return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_blocking);
  3857. }
  3858. inline napi_status ThreadSafeFunction::NonBlockingCall() const {
  3859. return CallInternal(nullptr, napi_tsfn_nonblocking);
  3860. }
  3861. template <>
  3862. inline napi_status ThreadSafeFunction::NonBlockingCall(
  3863. void* data) const {
  3864. return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
  3865. }
  3866. template <typename Callback>
  3867. inline napi_status ThreadSafeFunction::NonBlockingCall(
  3868. Callback callback) const {
  3869. return CallInternal(new CallbackWrapper(callback), napi_tsfn_nonblocking);
  3870. }
  3871. template <typename DataType, typename Callback>
  3872. inline napi_status ThreadSafeFunction::NonBlockingCall(
  3873. DataType* data, Callback callback) const {
  3874. auto wrapper = [data, callback](Env env, Function jsCallback) {
  3875. callback(env, jsCallback, data);
  3876. };
  3877. return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
  3878. }
  3879. inline void ThreadSafeFunction::Ref(napi_env env) const {
  3880. if (_tsfn != nullptr) {
  3881. napi_status status = napi_ref_threadsafe_function(env, _tsfn);
  3882. NAPI_THROW_IF_FAILED_VOID(env, status);
  3883. }
  3884. }
  3885. inline void ThreadSafeFunction::Unref(napi_env env) const {
  3886. if (_tsfn != nullptr) {
  3887. napi_status status = napi_unref_threadsafe_function(env, _tsfn);
  3888. NAPI_THROW_IF_FAILED_VOID(env, status);
  3889. }
  3890. }
  3891. inline napi_status ThreadSafeFunction::Acquire() const {
  3892. return napi_acquire_threadsafe_function(_tsfn);
  3893. }
  3894. inline napi_status ThreadSafeFunction::Release() {
  3895. return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
  3896. }
  3897. inline napi_status ThreadSafeFunction::Abort() {
  3898. return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
  3899. }
  3900. inline ThreadSafeFunction::ConvertibleContext
  3901. ThreadSafeFunction::GetContext() const {
  3902. void* context;
  3903. napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
  3904. NAPI_FATAL_IF_FAILED(status, "ThreadSafeFunction::GetContext", "napi_get_threadsafe_function_context");
  3905. return ConvertibleContext({ context });
  3906. }
  3907. // static
  3908. template <typename ResourceString, typename ContextType,
  3909. typename Finalizer, typename FinalizerDataType>
  3910. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  3911. const Function& callback,
  3912. const Object& resource,
  3913. ResourceString resourceName,
  3914. size_t maxQueueSize,
  3915. size_t initialThreadCount,
  3916. ContextType* context,
  3917. Finalizer finalizeCallback,
  3918. FinalizerDataType* data,
  3919. napi_finalize wrapper) {
  3920. static_assert(details::can_make_string<ResourceString>::value
  3921. || std::is_convertible<ResourceString, napi_value>::value,
  3922. "Resource name should be convertible to the string type");
  3923. ThreadSafeFunction tsfn;
  3924. auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
  3925. FinalizerDataType>({ data, finalizeCallback });
  3926. napi_status status = napi_create_threadsafe_function(env, callback, resource,
  3927. Value::From(env, resourceName), maxQueueSize, initialThreadCount,
  3928. finalizeData, wrapper, context, CallJS, &tsfn._tsfn);
  3929. if (status != napi_ok) {
  3930. delete finalizeData;
  3931. NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
  3932. }
  3933. return tsfn;
  3934. }
  3935. inline napi_status ThreadSafeFunction::CallInternal(
  3936. CallbackWrapper* callbackWrapper,
  3937. napi_threadsafe_function_call_mode mode) const {
  3938. napi_status status = napi_call_threadsafe_function(
  3939. _tsfn, callbackWrapper, mode);
  3940. if (status != napi_ok && callbackWrapper != nullptr) {
  3941. delete callbackWrapper;
  3942. }
  3943. return status;
  3944. }
  3945. // static
  3946. inline void ThreadSafeFunction::CallJS(napi_env env,
  3947. napi_value jsCallback,
  3948. void* /* context */,
  3949. void* data) {
  3950. if (env == nullptr && jsCallback == nullptr) {
  3951. return;
  3952. }
  3953. if (data != nullptr) {
  3954. auto* callbackWrapper = static_cast<CallbackWrapper*>(data);
  3955. (*callbackWrapper)(env, Function(env, jsCallback));
  3956. delete callbackWrapper;
  3957. } else if (jsCallback != nullptr) {
  3958. Function(env, jsCallback).Call({});
  3959. }
  3960. }
  3961. ////////////////////////////////////////////////////////////////////////////////
  3962. // Async Progress Worker Base class
  3963. ////////////////////////////////////////////////////////////////////////////////
  3964. template <typename DataType>
  3965. inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(const Object& receiver,
  3966. const Function& callback,
  3967. const char* resource_name,
  3968. const Object& resource,
  3969. size_t queue_size)
  3970. : AsyncWorker(receiver, callback, resource_name, resource) {
  3971. // Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
  3972. _tsfn = ThreadSafeFunction::New(callback.Env(),
  3973. callback,
  3974. resource,
  3975. resource_name,
  3976. queue_size,
  3977. /** initialThreadCount */ 1,
  3978. /** context */ this,
  3979. OnThreadSafeFunctionFinalize,
  3980. /** finalizeData */ this);
  3981. }
  3982. #if NAPI_VERSION > 4
  3983. template <typename DataType>
  3984. inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(Napi::Env env,
  3985. const char* resource_name,
  3986. const Object& resource,
  3987. size_t queue_size)
  3988. : AsyncWorker(env, resource_name, resource) {
  3989. // TODO: Once the changes to make the callback optional for threadsafe
  3990. // functions are available on all versions we can remove the dummy Function here.
  3991. Function callback;
  3992. // Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
  3993. _tsfn = ThreadSafeFunction::New(env,
  3994. callback,
  3995. resource,
  3996. resource_name,
  3997. queue_size,
  3998. /** initialThreadCount */ 1,
  3999. /** context */ this,
  4000. OnThreadSafeFunctionFinalize,
  4001. /** finalizeData */ this);
  4002. }
  4003. #endif
  4004. template<typename DataType>
  4005. inline AsyncProgressWorkerBase<DataType>::~AsyncProgressWorkerBase() {
  4006. // Abort pending tsfn call.
  4007. // Don't send progress events after we've already completed.
  4008. // It's ok to call ThreadSafeFunction::Abort and ThreadSafeFunction::Release duplicated.
  4009. _tsfn.Abort();
  4010. }
  4011. template <typename DataType>
  4012. inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(Napi::Env /* env */,
  4013. Napi::Function /* jsCallback */,
  4014. void* data) {
  4015. ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
  4016. tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
  4017. }
  4018. template <typename DataType>
  4019. inline napi_status AsyncProgressWorkerBase<DataType>::NonBlockingCall(DataType* data) {
  4020. auto tsd = new AsyncProgressWorkerBase::ThreadSafeData(this, data);
  4021. return _tsfn.NonBlockingCall(tsd, OnAsyncWorkProgress);
  4022. }
  4023. template <typename DataType>
  4024. inline void AsyncProgressWorkerBase<DataType>::OnWorkComplete(Napi::Env /* env */, napi_status status) {
  4025. _work_completed = true;
  4026. _complete_status = status;
  4027. _tsfn.Release();
  4028. }
  4029. template <typename DataType>
  4030. inline void AsyncProgressWorkerBase<DataType>::OnThreadSafeFunctionFinalize(Napi::Env env, void* /* data */, AsyncProgressWorkerBase* context) {
  4031. if (context->_work_completed) {
  4032. context->AsyncWorker::OnWorkComplete(env, context->_complete_status);
  4033. }
  4034. }
  4035. ////////////////////////////////////////////////////////////////////////////////
  4036. // Async Progress Worker class
  4037. ////////////////////////////////////////////////////////////////////////////////
  4038. template<class T>
  4039. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback)
  4040. : AsyncProgressWorker(callback, "generic") {
  4041. }
  4042. template<class T>
  4043. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
  4044. const char* resource_name)
  4045. : AsyncProgressWorker(callback, resource_name, Object::New(callback.Env())) {
  4046. }
  4047. template<class T>
  4048. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
  4049. const char* resource_name,
  4050. const Object& resource)
  4051. : AsyncProgressWorker(Object::New(callback.Env()),
  4052. callback,
  4053. resource_name,
  4054. resource) {
  4055. }
  4056. template<class T>
  4057. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
  4058. const Function& callback)
  4059. : AsyncProgressWorker(receiver, callback, "generic") {
  4060. }
  4061. template<class T>
  4062. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
  4063. const Function& callback,
  4064. const char* resource_name)
  4065. : AsyncProgressWorker(receiver,
  4066. callback,
  4067. resource_name,
  4068. Object::New(callback.Env())) {
  4069. }
  4070. template<class T>
  4071. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
  4072. const Function& callback,
  4073. const char* resource_name,
  4074. const Object& resource)
  4075. : AsyncProgressWorkerBase(receiver, callback, resource_name, resource),
  4076. _asyncdata(nullptr),
  4077. _asyncsize(0) {
  4078. }
  4079. #if NAPI_VERSION > 4
  4080. template<class T>
  4081. inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
  4082. : AsyncProgressWorker(env, "generic") {
  4083. }
  4084. template<class T>
  4085. inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
  4086. const char* resource_name)
  4087. : AsyncProgressWorker(env, resource_name, Object::New(env)) {
  4088. }
  4089. template<class T>
  4090. inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
  4091. const char* resource_name,
  4092. const Object& resource)
  4093. : AsyncProgressWorkerBase(env, resource_name, resource),
  4094. _asyncdata(nullptr),
  4095. _asyncsize(0) {
  4096. }
  4097. #endif
  4098. template<class T>
  4099. inline AsyncProgressWorker<T>::~AsyncProgressWorker() {
  4100. {
  4101. std::lock_guard<std::mutex> lock(this->_mutex);
  4102. _asyncdata = nullptr;
  4103. _asyncsize = 0;
  4104. }
  4105. }
  4106. template<class T>
  4107. inline void AsyncProgressWorker<T>::Execute() {
  4108. ExecutionProgress progress(this);
  4109. Execute(progress);
  4110. }
  4111. template<class T>
  4112. inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
  4113. T* data;
  4114. size_t size;
  4115. {
  4116. std::lock_guard<std::mutex> lock(this->_mutex);
  4117. data = this->_asyncdata;
  4118. size = this->_asyncsize;
  4119. this->_asyncdata = nullptr;
  4120. this->_asyncsize = 0;
  4121. }
  4122. this->OnProgress(data, size);
  4123. delete[] data;
  4124. }
  4125. template<class T>
  4126. inline void AsyncProgressWorker<T>::SendProgress_(const T* data, size_t count) {
  4127. T* new_data = new T[count];
  4128. std::copy(data, data + count, new_data);
  4129. T* old_data;
  4130. {
  4131. std::lock_guard<std::mutex> lock(this->_mutex);
  4132. old_data = _asyncdata;
  4133. _asyncdata = new_data;
  4134. _asyncsize = count;
  4135. }
  4136. this->NonBlockingCall(nullptr);
  4137. delete[] old_data;
  4138. }
  4139. template<class T>
  4140. inline void AsyncProgressWorker<T>::Signal() const {
  4141. this->NonBlockingCall(static_cast<T*>(nullptr));
  4142. }
  4143. template<class T>
  4144. inline void AsyncProgressWorker<T>::ExecutionProgress::Signal() const {
  4145. _worker->Signal();
  4146. }
  4147. template<class T>
  4148. inline void AsyncProgressWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
  4149. _worker->SendProgress_(data, count);
  4150. }
  4151. ////////////////////////////////////////////////////////////////////////////////
  4152. // Async Progress Queue Worker class
  4153. ////////////////////////////////////////////////////////////////////////////////
  4154. template<class T>
  4155. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback)
  4156. : AsyncProgressQueueWorker(callback, "generic") {
  4157. }
  4158. template<class T>
  4159. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
  4160. const char* resource_name)
  4161. : AsyncProgressQueueWorker(callback, resource_name, Object::New(callback.Env())) {
  4162. }
  4163. template<class T>
  4164. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
  4165. const char* resource_name,
  4166. const Object& resource)
  4167. : AsyncProgressQueueWorker(Object::New(callback.Env()),
  4168. callback,
  4169. resource_name,
  4170. resource) {
  4171. }
  4172. template<class T>
  4173. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
  4174. const Function& callback)
  4175. : AsyncProgressQueueWorker(receiver, callback, "generic") {
  4176. }
  4177. template<class T>
  4178. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
  4179. const Function& callback,
  4180. const char* resource_name)
  4181. : AsyncProgressQueueWorker(receiver,
  4182. callback,
  4183. resource_name,
  4184. Object::New(callback.Env())) {
  4185. }
  4186. template<class T>
  4187. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
  4188. const Function& callback,
  4189. const char* resource_name,
  4190. const Object& resource)
  4191. : AsyncProgressWorkerBase<std::pair<T*, size_t>>(receiver, callback, resource_name, resource, /** unlimited queue size */0) {
  4192. }
  4193. #if NAPI_VERSION > 4
  4194. template<class T>
  4195. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env)
  4196. : AsyncProgressQueueWorker(env, "generic") {
  4197. }
  4198. template<class T>
  4199. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
  4200. const char* resource_name)
  4201. : AsyncProgressQueueWorker(env, resource_name, Object::New(env)) {
  4202. }
  4203. template<class T>
  4204. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
  4205. const char* resource_name,
  4206. const Object& resource)
  4207. : AsyncProgressWorkerBase<std::pair<T*, size_t>>(env, resource_name, resource, /** unlimited queue size */0) {
  4208. }
  4209. #endif
  4210. template<class T>
  4211. inline void AsyncProgressQueueWorker<T>::Execute() {
  4212. ExecutionProgress progress(this);
  4213. Execute(progress);
  4214. }
  4215. template<class T>
  4216. inline void AsyncProgressQueueWorker<T>::OnWorkProgress(std::pair<T*, size_t>* datapair) {
  4217. if (datapair == nullptr) {
  4218. return;
  4219. }
  4220. T *data = datapair->first;
  4221. size_t size = datapair->second;
  4222. this->OnProgress(data, size);
  4223. delete datapair;
  4224. delete[] data;
  4225. }
  4226. template<class T>
  4227. inline void AsyncProgressQueueWorker<T>::SendProgress_(const T* data, size_t count) {
  4228. T* new_data = new T[count];
  4229. std::copy(data, data + count, new_data);
  4230. auto pair = new std::pair<T*, size_t>(new_data, count);
  4231. this->NonBlockingCall(pair);
  4232. }
  4233. template<class T>
  4234. inline void AsyncProgressQueueWorker<T>::Signal() const {
  4235. this->NonBlockingCall(nullptr);
  4236. }
  4237. template<class T>
  4238. inline void AsyncProgressQueueWorker<T>::OnWorkComplete(Napi::Env env, napi_status status) {
  4239. // Draining queued items in TSFN.
  4240. AsyncProgressWorkerBase<std::pair<T*, size_t>>::OnWorkComplete(env, status);
  4241. }
  4242. template<class T>
  4243. inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Signal() const {
  4244. _worker->Signal();
  4245. }
  4246. template<class T>
  4247. inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
  4248. _worker->SendProgress_(data, count);
  4249. }
  4250. #endif
  4251. ////////////////////////////////////////////////////////////////////////////////
  4252. // Memory Management class
  4253. ////////////////////////////////////////////////////////////////////////////////
  4254. inline int64_t MemoryManagement::AdjustExternalMemory(Env env, int64_t change_in_bytes) {
  4255. int64_t result;
  4256. napi_status status = napi_adjust_external_memory(env, change_in_bytes, &result);
  4257. NAPI_THROW_IF_FAILED(env, status, 0);
  4258. return result;
  4259. }
  4260. ////////////////////////////////////////////////////////////////////////////////
  4261. // Version Management class
  4262. ////////////////////////////////////////////////////////////////////////////////
  4263. inline uint32_t VersionManagement::GetNapiVersion(Env env) {
  4264. uint32_t result;
  4265. napi_status status = napi_get_version(env, &result);
  4266. NAPI_THROW_IF_FAILED(env, status, 0);
  4267. return result;
  4268. }
  4269. inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
  4270. const napi_node_version* result;
  4271. napi_status status = napi_get_node_version(env, &result);
  4272. NAPI_THROW_IF_FAILED(env, status, 0);
  4273. return result;
  4274. }
  4275. } // namespace Napi
  4276. #endif // SRC_NAPI_INL_H_