napi-inl.h 214 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607
  1. #ifndef SRC_NAPI_INL_H_
  2. #define SRC_NAPI_INL_H_
  3. ////////////////////////////////////////////////////////////////////////////////
  4. // Node-API C++ Wrapper Classes
  5. //
  6. // Inline header-only implementations for "Node-API" ABI-stable C APIs for
  7. // Node.js.
  8. ////////////////////////////////////////////////////////////////////////////////
  9. // Note: Do not include this file directly! Include "napi.h" instead.
  10. #include <algorithm>
  11. #include <cstring>
  12. #if NAPI_HAS_THREADS
  13. #include <mutex>
  14. #endif // NAPI_HAS_THREADS
  15. #include <type_traits>
  16. #include <utility>
  17. namespace Napi {
  18. #ifdef NAPI_CPP_CUSTOM_NAMESPACE
  19. namespace NAPI_CPP_CUSTOM_NAMESPACE {
  20. #endif
  21. // Helpers to handle functions exposed from C++ and internal constants.
  22. namespace details {
  23. // New napi_status constants not yet available in all supported versions of
  24. // Node.js releases. Only necessary when they are used in napi.h and napi-inl.h.
  25. constexpr int napi_no_external_buffers_allowed = 22;
  26. template <typename FreeType>
  27. inline void default_finalizer(napi_env /*env*/, void* data, void* /*hint*/) {
  28. delete static_cast<FreeType*>(data);
  29. }
  30. // Attach a data item to an object and delete it when the object gets
  31. // garbage-collected.
  32. // TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
  33. // available on all supported versions of Node.js.
  34. template <typename FreeType,
  35. napi_finalize finalizer = default_finalizer<FreeType>>
  36. inline napi_status AttachData(napi_env env,
  37. napi_value obj,
  38. FreeType* data,
  39. void* hint = nullptr) {
  40. napi_status status;
  41. #if (NAPI_VERSION < 5)
  42. napi_value symbol, external;
  43. status = napi_create_symbol(env, nullptr, &symbol);
  44. if (status == napi_ok) {
  45. status = napi_create_external(env, data, finalizer, hint, &external);
  46. if (status == napi_ok) {
  47. napi_property_descriptor desc = {nullptr,
  48. symbol,
  49. nullptr,
  50. nullptr,
  51. nullptr,
  52. external,
  53. napi_default,
  54. nullptr};
  55. status = napi_define_properties(env, obj, 1, &desc);
  56. }
  57. }
  58. #else // NAPI_VERSION >= 5
  59. status = napi_add_finalizer(env, obj, data, finalizer, hint, nullptr);
  60. #endif
  61. return status;
  62. }
  63. // For use in JS to C++ callback wrappers to catch any Napi::Error exceptions
  64. // and rethrow them as JavaScript exceptions before returning from the callback.
  65. template <typename Callable>
  66. inline napi_value WrapCallback(Callable callback) {
  67. #ifdef NAPI_CPP_EXCEPTIONS
  68. try {
  69. return callback();
  70. } catch (const Error& e) {
  71. e.ThrowAsJavaScriptException();
  72. return nullptr;
  73. }
  74. #else // NAPI_CPP_EXCEPTIONS
  75. // When C++ exceptions are disabled, errors are immediately thrown as JS
  76. // exceptions, so there is no need to catch and rethrow them here.
  77. return callback();
  78. #endif // NAPI_CPP_EXCEPTIONS
  79. }
  80. // For use in JS to C++ void callback wrappers to catch any Napi::Error
  81. // exceptions and rethrow them as JavaScript exceptions before returning from
  82. // the callback.
  83. template <typename Callable>
  84. inline void WrapVoidCallback(Callable callback) {
  85. #ifdef NAPI_CPP_EXCEPTIONS
  86. try {
  87. callback();
  88. } catch (const Error& e) {
  89. e.ThrowAsJavaScriptException();
  90. }
  91. #else // NAPI_CPP_EXCEPTIONS
  92. // When C++ exceptions are disabled, errors are immediately thrown as JS
  93. // exceptions, so there is no need to catch and rethrow them here.
  94. callback();
  95. #endif // NAPI_CPP_EXCEPTIONS
  96. }
  97. template <typename Callable, typename Return>
  98. struct CallbackData {
  99. static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
  100. return details::WrapCallback([&] {
  101. CallbackInfo callbackInfo(env, info);
  102. CallbackData* callbackData =
  103. static_cast<CallbackData*>(callbackInfo.Data());
  104. callbackInfo.SetData(callbackData->data);
  105. return callbackData->callback(callbackInfo);
  106. });
  107. }
  108. Callable callback;
  109. void* data;
  110. };
  111. template <typename Callable>
  112. struct CallbackData<Callable, void> {
  113. static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
  114. return details::WrapCallback([&] {
  115. CallbackInfo callbackInfo(env, info);
  116. CallbackData* callbackData =
  117. static_cast<CallbackData*>(callbackInfo.Data());
  118. callbackInfo.SetData(callbackData->data);
  119. callbackData->callback(callbackInfo);
  120. return nullptr;
  121. });
  122. }
  123. Callable callback;
  124. void* data;
  125. };
  126. template <void (*Callback)(const CallbackInfo& info)>
  127. napi_value TemplatedVoidCallback(napi_env env,
  128. napi_callback_info info) NAPI_NOEXCEPT {
  129. return details::WrapCallback([&] {
  130. CallbackInfo cbInfo(env, info);
  131. Callback(cbInfo);
  132. return nullptr;
  133. });
  134. }
  135. template <Napi::Value (*Callback)(const CallbackInfo& info)>
  136. napi_value TemplatedCallback(napi_env env,
  137. napi_callback_info info) NAPI_NOEXCEPT {
  138. return details::WrapCallback([&] {
  139. CallbackInfo cbInfo(env, info);
  140. return Callback(cbInfo);
  141. });
  142. }
  143. template <typename T,
  144. Napi::Value (T::*UnwrapCallback)(const CallbackInfo& info)>
  145. napi_value TemplatedInstanceCallback(napi_env env,
  146. napi_callback_info info) NAPI_NOEXCEPT {
  147. return details::WrapCallback([&] {
  148. CallbackInfo cbInfo(env, info);
  149. T* instance = T::Unwrap(cbInfo.This().As<Object>());
  150. return instance ? (instance->*UnwrapCallback)(cbInfo) : Napi::Value();
  151. });
  152. }
  153. template <typename T, void (T::*UnwrapCallback)(const CallbackInfo& info)>
  154. napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info)
  155. NAPI_NOEXCEPT {
  156. return details::WrapCallback([&] {
  157. CallbackInfo cbInfo(env, info);
  158. T* instance = T::Unwrap(cbInfo.This().As<Object>());
  159. if (instance) (instance->*UnwrapCallback)(cbInfo);
  160. return nullptr;
  161. });
  162. }
  163. template <typename T, typename Finalizer, typename Hint = void>
  164. struct FinalizeData {
  165. static inline void Wrapper(napi_env env,
  166. void* data,
  167. void* finalizeHint) NAPI_NOEXCEPT {
  168. WrapVoidCallback([&] {
  169. FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
  170. finalizeData->callback(Env(env), static_cast<T*>(data));
  171. delete finalizeData;
  172. });
  173. }
  174. static inline void WrapperWithHint(napi_env env,
  175. void* data,
  176. void* finalizeHint) NAPI_NOEXCEPT {
  177. WrapVoidCallback([&] {
  178. FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
  179. finalizeData->callback(
  180. Env(env), static_cast<T*>(data), finalizeData->hint);
  181. delete finalizeData;
  182. });
  183. }
  184. Finalizer callback;
  185. Hint* hint;
  186. };
  187. #if (NAPI_VERSION > 3 && NAPI_HAS_THREADS)
  188. template <typename ContextType = void,
  189. typename Finalizer = std::function<void(Env, void*, ContextType*)>,
  190. typename FinalizerDataType = void>
  191. struct ThreadSafeFinalize {
  192. static inline void Wrapper(napi_env env,
  193. void* rawFinalizeData,
  194. void* /* rawContext */) {
  195. if (rawFinalizeData == nullptr) return;
  196. ThreadSafeFinalize* finalizeData =
  197. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  198. finalizeData->callback(Env(env));
  199. delete finalizeData;
  200. }
  201. static inline void FinalizeWrapperWithData(napi_env env,
  202. void* rawFinalizeData,
  203. void* /* rawContext */) {
  204. if (rawFinalizeData == nullptr) return;
  205. ThreadSafeFinalize* finalizeData =
  206. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  207. finalizeData->callback(Env(env), finalizeData->data);
  208. delete finalizeData;
  209. }
  210. static inline void FinalizeWrapperWithContext(napi_env env,
  211. void* rawFinalizeData,
  212. void* rawContext) {
  213. if (rawFinalizeData == nullptr) return;
  214. ThreadSafeFinalize* finalizeData =
  215. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  216. finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
  217. delete finalizeData;
  218. }
  219. static inline void FinalizeFinalizeWrapperWithDataAndContext(
  220. napi_env env, void* rawFinalizeData, void* rawContext) {
  221. if (rawFinalizeData == nullptr) return;
  222. ThreadSafeFinalize* finalizeData =
  223. static_cast<ThreadSafeFinalize*>(rawFinalizeData);
  224. finalizeData->callback(
  225. Env(env), finalizeData->data, static_cast<ContextType*>(rawContext));
  226. delete finalizeData;
  227. }
  228. FinalizerDataType* data;
  229. Finalizer callback;
  230. };
  231. template <typename ContextType, typename DataType, typename CallJs, CallJs call>
  232. inline typename std::enable_if<call != static_cast<CallJs>(nullptr)>::type
  233. CallJsWrapper(napi_env env, napi_value jsCallback, void* context, void* data) {
  234. details::WrapVoidCallback([&]() {
  235. call(env,
  236. Function(env, jsCallback),
  237. static_cast<ContextType*>(context),
  238. static_cast<DataType*>(data));
  239. });
  240. }
  241. template <typename ContextType, typename DataType, typename CallJs, CallJs call>
  242. inline typename std::enable_if<call == static_cast<CallJs>(nullptr)>::type
  243. CallJsWrapper(napi_env env,
  244. napi_value jsCallback,
  245. void* /*context*/,
  246. void* /*data*/) {
  247. details::WrapVoidCallback([&]() {
  248. if (jsCallback != nullptr) {
  249. Function(env, jsCallback).Call(0, nullptr);
  250. }
  251. });
  252. }
  253. #if NAPI_VERSION > 4
  254. template <typename CallbackType, typename TSFN>
  255. napi_value DefaultCallbackWrapper(napi_env /*env*/, std::nullptr_t /*cb*/) {
  256. return nullptr;
  257. }
  258. template <typename CallbackType, typename TSFN>
  259. napi_value DefaultCallbackWrapper(napi_env /*env*/, Napi::Function cb) {
  260. return cb;
  261. }
  262. #else
  263. template <typename CallbackType, typename TSFN>
  264. napi_value DefaultCallbackWrapper(napi_env env, Napi::Function cb) {
  265. if (cb.IsEmpty()) {
  266. return TSFN::EmptyFunctionFactory(env);
  267. }
  268. return cb;
  269. }
  270. #endif // NAPI_VERSION > 4
  271. #endif // NAPI_VERSION > 3 && NAPI_HAS_THREADS
  272. template <typename Getter, typename Setter>
  273. struct AccessorCallbackData {
  274. static inline napi_value GetterWrapper(napi_env env,
  275. napi_callback_info info) {
  276. return details::WrapCallback([&] {
  277. CallbackInfo callbackInfo(env, info);
  278. AccessorCallbackData* callbackData =
  279. static_cast<AccessorCallbackData*>(callbackInfo.Data());
  280. callbackInfo.SetData(callbackData->data);
  281. return callbackData->getterCallback(callbackInfo);
  282. });
  283. }
  284. static inline napi_value SetterWrapper(napi_env env,
  285. napi_callback_info info) {
  286. return details::WrapCallback([&] {
  287. CallbackInfo callbackInfo(env, info);
  288. AccessorCallbackData* callbackData =
  289. static_cast<AccessorCallbackData*>(callbackInfo.Data());
  290. callbackInfo.SetData(callbackData->data);
  291. callbackData->setterCallback(callbackInfo);
  292. return nullptr;
  293. });
  294. }
  295. Getter getterCallback;
  296. Setter setterCallback;
  297. void* data;
  298. };
  299. } // namespace details
  300. #ifndef NODE_ADDON_API_DISABLE_DEPRECATED
  301. #include "napi-inl.deprecated.h"
  302. #endif // !NODE_ADDON_API_DISABLE_DEPRECATED
  303. ////////////////////////////////////////////////////////////////////////////////
  304. // Module registration
  305. ////////////////////////////////////////////////////////////////////////////////
  306. // Register an add-on based on an initializer function.
  307. #define NODE_API_MODULE(modname, regfunc) \
  308. static napi_value __napi_##regfunc(napi_env env, napi_value exports) { \
  309. return Napi::RegisterModule(env, exports, regfunc); \
  310. } \
  311. NAPI_MODULE(modname, __napi_##regfunc)
  312. // Register an add-on based on a subclass of `Addon<T>` with a custom Node.js
  313. // module name.
  314. #define NODE_API_NAMED_ADDON(modname, classname) \
  315. static napi_value __napi_##classname(napi_env env, napi_value exports) { \
  316. return Napi::RegisterModule(env, exports, &classname::Init); \
  317. } \
  318. NAPI_MODULE(modname, __napi_##classname)
  319. // Register an add-on based on a subclass of `Addon<T>` with the Node.js module
  320. // name given by node-gyp from the `target_name` in binding.gyp.
  321. #define NODE_API_ADDON(classname) \
  322. NODE_API_NAMED_ADDON(NODE_GYP_MODULE_NAME, classname)
  323. // Adapt the NAPI_MODULE registration function:
  324. // - Wrap the arguments in NAPI wrappers.
  325. // - Catch any NAPI errors and rethrow as JS exceptions.
  326. inline napi_value RegisterModule(napi_env env,
  327. napi_value exports,
  328. ModuleRegisterCallback registerCallback) {
  329. return details::WrapCallback([&] {
  330. return napi_value(
  331. registerCallback(Napi::Env(env), Napi::Object(env, exports)));
  332. });
  333. }
  334. ////////////////////////////////////////////////////////////////////////////////
  335. // Maybe class
  336. ////////////////////////////////////////////////////////////////////////////////
  337. template <class T>
  338. bool Maybe<T>::IsNothing() const {
  339. return !_has_value;
  340. }
  341. template <class T>
  342. bool Maybe<T>::IsJust() const {
  343. return _has_value;
  344. }
  345. template <class T>
  346. void Maybe<T>::Check() const {
  347. NAPI_CHECK(IsJust(), "Napi::Maybe::Check", "Maybe value is Nothing.");
  348. }
  349. template <class T>
  350. T Maybe<T>::Unwrap() const {
  351. NAPI_CHECK(IsJust(), "Napi::Maybe::Unwrap", "Maybe value is Nothing.");
  352. return _value;
  353. }
  354. template <class T>
  355. T Maybe<T>::UnwrapOr(const T& default_value) const {
  356. return _has_value ? _value : default_value;
  357. }
  358. template <class T>
  359. bool Maybe<T>::UnwrapTo(T* out) const {
  360. if (IsJust()) {
  361. *out = _value;
  362. return true;
  363. };
  364. return false;
  365. }
  366. template <class T>
  367. bool Maybe<T>::operator==(const Maybe& other) const {
  368. return (IsJust() == other.IsJust()) &&
  369. (!IsJust() || Unwrap() == other.Unwrap());
  370. }
  371. template <class T>
  372. bool Maybe<T>::operator!=(const Maybe& other) const {
  373. return !operator==(other);
  374. }
  375. template <class T>
  376. Maybe<T>::Maybe() : _has_value(false) {}
  377. template <class T>
  378. Maybe<T>::Maybe(const T& t) : _has_value(true), _value(t) {}
  379. template <class T>
  380. inline Maybe<T> Nothing() {
  381. return Maybe<T>();
  382. }
  383. template <class T>
  384. inline Maybe<T> Just(const T& t) {
  385. return Maybe<T>(t);
  386. }
  387. ////////////////////////////////////////////////////////////////////////////////
  388. // Env class
  389. ////////////////////////////////////////////////////////////////////////////////
  390. inline Env::Env(napi_env env) : _env(env) {}
  391. inline Env::operator napi_env() const {
  392. return _env;
  393. }
  394. inline Object Env::Global() const {
  395. napi_value value;
  396. napi_status status = napi_get_global(*this, &value);
  397. NAPI_THROW_IF_FAILED(*this, status, Object());
  398. return Object(*this, value);
  399. }
  400. inline Value Env::Undefined() const {
  401. napi_value value;
  402. napi_status status = napi_get_undefined(*this, &value);
  403. NAPI_THROW_IF_FAILED(*this, status, Value());
  404. return Value(*this, value);
  405. }
  406. inline Value Env::Null() const {
  407. napi_value value;
  408. napi_status status = napi_get_null(*this, &value);
  409. NAPI_THROW_IF_FAILED(*this, status, Value());
  410. return Value(*this, value);
  411. }
  412. inline bool Env::IsExceptionPending() const {
  413. bool result;
  414. napi_status status = napi_is_exception_pending(_env, &result);
  415. if (status != napi_ok)
  416. result = false; // Checking for a pending exception shouldn't throw.
  417. return result;
  418. }
  419. inline Error Env::GetAndClearPendingException() const {
  420. napi_value value;
  421. napi_status status = napi_get_and_clear_last_exception(_env, &value);
  422. if (status != napi_ok) {
  423. // Don't throw another exception when failing to get the exception!
  424. return Error();
  425. }
  426. return Error(_env, value);
  427. }
  428. inline MaybeOrValue<Value> Env::RunScript(const char* utf8script) const {
  429. String script = String::New(_env, utf8script);
  430. return RunScript(script);
  431. }
  432. inline MaybeOrValue<Value> Env::RunScript(const std::string& utf8script) const {
  433. return RunScript(utf8script.c_str());
  434. }
  435. inline MaybeOrValue<Value> Env::RunScript(String script) const {
  436. napi_value result;
  437. napi_status status = napi_run_script(_env, script, &result);
  438. NAPI_RETURN_OR_THROW_IF_FAILED(
  439. _env, status, Napi::Value(_env, result), Napi::Value);
  440. }
  441. #if NAPI_VERSION > 2
  442. template <typename Hook, typename Arg>
  443. void Env::CleanupHook<Hook, Arg>::Wrapper(void* data) NAPI_NOEXCEPT {
  444. auto* cleanupData =
  445. static_cast<typename Napi::Env::CleanupHook<Hook, Arg>::CleanupData*>(
  446. data);
  447. cleanupData->hook();
  448. delete cleanupData;
  449. }
  450. template <typename Hook, typename Arg>
  451. void Env::CleanupHook<Hook, Arg>::WrapperWithArg(void* data) NAPI_NOEXCEPT {
  452. auto* cleanupData =
  453. static_cast<typename Napi::Env::CleanupHook<Hook, Arg>::CleanupData*>(
  454. data);
  455. cleanupData->hook(static_cast<Arg*>(cleanupData->arg));
  456. delete cleanupData;
  457. }
  458. #endif // NAPI_VERSION > 2
  459. #if NAPI_VERSION > 5
  460. template <typename T, Env::Finalizer<T> fini>
  461. inline void Env::SetInstanceData(T* data) const {
  462. napi_status status = napi_set_instance_data(
  463. _env,
  464. data,
  465. [](napi_env env, void* data, void*) { fini(env, static_cast<T*>(data)); },
  466. nullptr);
  467. NAPI_THROW_IF_FAILED_VOID(_env, status);
  468. }
  469. template <typename DataType,
  470. typename HintType,
  471. Napi::Env::FinalizerWithHint<DataType, HintType> fini>
  472. inline void Env::SetInstanceData(DataType* data, HintType* hint) const {
  473. napi_status status = napi_set_instance_data(
  474. _env,
  475. data,
  476. [](napi_env env, void* data, void* hint) {
  477. fini(env, static_cast<DataType*>(data), static_cast<HintType*>(hint));
  478. },
  479. hint);
  480. NAPI_THROW_IF_FAILED_VOID(_env, status);
  481. }
  482. template <typename T>
  483. inline T* Env::GetInstanceData() const {
  484. void* data = nullptr;
  485. napi_status status = napi_get_instance_data(_env, &data);
  486. NAPI_THROW_IF_FAILED(_env, status, nullptr);
  487. return static_cast<T*>(data);
  488. }
  489. template <typename T>
  490. void Env::DefaultFini(Env, T* data) {
  491. delete data;
  492. }
  493. template <typename DataType, typename HintType>
  494. void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) {
  495. delete data;
  496. }
  497. #endif // NAPI_VERSION > 5
  498. #if NAPI_VERSION > 8
  499. inline const char* Env::GetModuleFileName() const {
  500. const char* result;
  501. napi_status status = node_api_get_module_file_name(_env, &result);
  502. NAPI_THROW_IF_FAILED(*this, status, nullptr);
  503. return result;
  504. }
  505. #endif // NAPI_VERSION > 8
  506. ////////////////////////////////////////////////////////////////////////////////
  507. // Value class
  508. ////////////////////////////////////////////////////////////////////////////////
  509. inline Value::Value() : _env(nullptr), _value(nullptr) {}
  510. inline Value::Value(napi_env env, napi_value value)
  511. : _env(env), _value(value) {}
  512. inline Value::operator napi_value() const {
  513. return _value;
  514. }
  515. inline bool Value::operator==(const Value& other) const {
  516. return StrictEquals(other);
  517. }
  518. inline bool Value::operator!=(const Value& other) const {
  519. return !this->operator==(other);
  520. }
  521. inline bool Value::StrictEquals(const Value& other) const {
  522. bool result;
  523. napi_status status = napi_strict_equals(_env, *this, other, &result);
  524. NAPI_THROW_IF_FAILED(_env, status, false);
  525. return result;
  526. }
  527. inline Napi::Env Value::Env() const {
  528. return Napi::Env(_env);
  529. }
  530. inline bool Value::IsEmpty() const {
  531. return _value == nullptr;
  532. }
  533. inline napi_valuetype Value::Type() const {
  534. if (IsEmpty()) {
  535. return napi_undefined;
  536. }
  537. napi_valuetype type;
  538. napi_status status = napi_typeof(_env, _value, &type);
  539. NAPI_THROW_IF_FAILED(_env, status, napi_undefined);
  540. return type;
  541. }
  542. inline bool Value::IsUndefined() const {
  543. return Type() == napi_undefined;
  544. }
  545. inline bool Value::IsNull() const {
  546. return Type() == napi_null;
  547. }
  548. inline bool Value::IsBoolean() const {
  549. return Type() == napi_boolean;
  550. }
  551. inline bool Value::IsNumber() const {
  552. return Type() == napi_number;
  553. }
  554. #if NAPI_VERSION > 5
  555. inline bool Value::IsBigInt() const {
  556. return Type() == napi_bigint;
  557. }
  558. #endif // NAPI_VERSION > 5
  559. #if (NAPI_VERSION > 4)
  560. inline bool Value::IsDate() const {
  561. if (IsEmpty()) {
  562. return false;
  563. }
  564. bool result;
  565. napi_status status = napi_is_date(_env, _value, &result);
  566. NAPI_THROW_IF_FAILED(_env, status, false);
  567. return result;
  568. }
  569. #endif
  570. inline bool Value::IsString() const {
  571. return Type() == napi_string;
  572. }
  573. inline bool Value::IsSymbol() const {
  574. return Type() == napi_symbol;
  575. }
  576. inline bool Value::IsArray() const {
  577. if (IsEmpty()) {
  578. return false;
  579. }
  580. bool result;
  581. napi_status status = napi_is_array(_env, _value, &result);
  582. NAPI_THROW_IF_FAILED(_env, status, false);
  583. return result;
  584. }
  585. inline bool Value::IsArrayBuffer() const {
  586. if (IsEmpty()) {
  587. return false;
  588. }
  589. bool result;
  590. napi_status status = napi_is_arraybuffer(_env, _value, &result);
  591. NAPI_THROW_IF_FAILED(_env, status, false);
  592. return result;
  593. }
  594. inline bool Value::IsTypedArray() const {
  595. if (IsEmpty()) {
  596. return false;
  597. }
  598. bool result;
  599. napi_status status = napi_is_typedarray(_env, _value, &result);
  600. NAPI_THROW_IF_FAILED(_env, status, false);
  601. return result;
  602. }
  603. inline bool Value::IsObject() const {
  604. return Type() == napi_object || IsFunction();
  605. }
  606. inline bool Value::IsFunction() const {
  607. return Type() == napi_function;
  608. }
  609. inline bool Value::IsPromise() const {
  610. if (IsEmpty()) {
  611. return false;
  612. }
  613. bool result;
  614. napi_status status = napi_is_promise(_env, _value, &result);
  615. NAPI_THROW_IF_FAILED(_env, status, false);
  616. return result;
  617. }
  618. inline bool Value::IsDataView() const {
  619. if (IsEmpty()) {
  620. return false;
  621. }
  622. bool result;
  623. napi_status status = napi_is_dataview(_env, _value, &result);
  624. NAPI_THROW_IF_FAILED(_env, status, false);
  625. return result;
  626. }
  627. inline bool Value::IsBuffer() const {
  628. if (IsEmpty()) {
  629. return false;
  630. }
  631. bool result;
  632. napi_status status = napi_is_buffer(_env, _value, &result);
  633. NAPI_THROW_IF_FAILED(_env, status, false);
  634. return result;
  635. }
  636. inline bool Value::IsExternal() const {
  637. return Type() == napi_external;
  638. }
  639. template <typename T>
  640. inline T Value::As() const {
  641. #ifdef NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS
  642. T::CheckCast(_env, _value);
  643. #endif
  644. return T(_env, _value);
  645. }
  646. inline MaybeOrValue<Boolean> Value::ToBoolean() const {
  647. napi_value result;
  648. napi_status status = napi_coerce_to_bool(_env, _value, &result);
  649. NAPI_RETURN_OR_THROW_IF_FAILED(
  650. _env, status, Napi::Boolean(_env, result), Napi::Boolean);
  651. }
  652. inline MaybeOrValue<Number> Value::ToNumber() const {
  653. napi_value result;
  654. napi_status status = napi_coerce_to_number(_env, _value, &result);
  655. NAPI_RETURN_OR_THROW_IF_FAILED(
  656. _env, status, Napi::Number(_env, result), Napi::Number);
  657. }
  658. inline MaybeOrValue<String> Value::ToString() const {
  659. napi_value result;
  660. napi_status status = napi_coerce_to_string(_env, _value, &result);
  661. NAPI_RETURN_OR_THROW_IF_FAILED(
  662. _env, status, Napi::String(_env, result), Napi::String);
  663. }
  664. inline MaybeOrValue<Object> Value::ToObject() const {
  665. napi_value result;
  666. napi_status status = napi_coerce_to_object(_env, _value, &result);
  667. NAPI_RETURN_OR_THROW_IF_FAILED(
  668. _env, status, Napi::Object(_env, result), Napi::Object);
  669. }
  670. ////////////////////////////////////////////////////////////////////////////////
  671. // Boolean class
  672. ////////////////////////////////////////////////////////////////////////////////
  673. inline Boolean Boolean::New(napi_env env, bool val) {
  674. napi_value value;
  675. napi_status status = napi_get_boolean(env, val, &value);
  676. NAPI_THROW_IF_FAILED(env, status, Boolean());
  677. return Boolean(env, value);
  678. }
  679. inline void Boolean::CheckCast(napi_env env, napi_value value) {
  680. NAPI_CHECK(value != nullptr, "Boolean::CheckCast", "empty value");
  681. napi_valuetype type;
  682. napi_status status = napi_typeof(env, value, &type);
  683. NAPI_CHECK(status == napi_ok, "Boolean::CheckCast", "napi_typeof failed");
  684. NAPI_CHECK(
  685. type == napi_boolean, "Boolean::CheckCast", "value is not napi_boolean");
  686. }
  687. inline Boolean::Boolean() : Napi::Value() {}
  688. inline Boolean::Boolean(napi_env env, napi_value value)
  689. : Napi::Value(env, value) {}
  690. inline Boolean::operator bool() const {
  691. return Value();
  692. }
  693. inline bool Boolean::Value() const {
  694. bool result;
  695. napi_status status = napi_get_value_bool(_env, _value, &result);
  696. NAPI_THROW_IF_FAILED(_env, status, false);
  697. return result;
  698. }
  699. ////////////////////////////////////////////////////////////////////////////////
  700. // Number class
  701. ////////////////////////////////////////////////////////////////////////////////
  702. inline Number Number::New(napi_env env, double val) {
  703. napi_value value;
  704. napi_status status = napi_create_double(env, val, &value);
  705. NAPI_THROW_IF_FAILED(env, status, Number());
  706. return Number(env, value);
  707. }
  708. inline void Number::CheckCast(napi_env env, napi_value value) {
  709. NAPI_CHECK(value != nullptr, "Number::CheckCast", "empty value");
  710. napi_valuetype type;
  711. napi_status status = napi_typeof(env, value, &type);
  712. NAPI_CHECK(status == napi_ok, "Number::CheckCast", "napi_typeof failed");
  713. NAPI_CHECK(
  714. type == napi_number, "Number::CheckCast", "value is not napi_number");
  715. }
  716. inline Number::Number() : Value() {}
  717. inline Number::Number(napi_env env, napi_value value) : Value(env, value) {}
  718. inline Number::operator int32_t() const {
  719. return Int32Value();
  720. }
  721. inline Number::operator uint32_t() const {
  722. return Uint32Value();
  723. }
  724. inline Number::operator int64_t() const {
  725. return Int64Value();
  726. }
  727. inline Number::operator float() const {
  728. return FloatValue();
  729. }
  730. inline Number::operator double() const {
  731. return DoubleValue();
  732. }
  733. inline int32_t Number::Int32Value() const {
  734. int32_t result;
  735. napi_status status = napi_get_value_int32(_env, _value, &result);
  736. NAPI_THROW_IF_FAILED(_env, status, 0);
  737. return result;
  738. }
  739. inline uint32_t Number::Uint32Value() const {
  740. uint32_t result;
  741. napi_status status = napi_get_value_uint32(_env, _value, &result);
  742. NAPI_THROW_IF_FAILED(_env, status, 0);
  743. return result;
  744. }
  745. inline int64_t Number::Int64Value() const {
  746. int64_t result;
  747. napi_status status = napi_get_value_int64(_env, _value, &result);
  748. NAPI_THROW_IF_FAILED(_env, status, 0);
  749. return result;
  750. }
  751. inline float Number::FloatValue() const {
  752. return static_cast<float>(DoubleValue());
  753. }
  754. inline double Number::DoubleValue() const {
  755. double result;
  756. napi_status status = napi_get_value_double(_env, _value, &result);
  757. NAPI_THROW_IF_FAILED(_env, status, 0);
  758. return result;
  759. }
  760. #if NAPI_VERSION > 5
  761. ////////////////////////////////////////////////////////////////////////////////
  762. // BigInt Class
  763. ////////////////////////////////////////////////////////////////////////////////
  764. inline BigInt BigInt::New(napi_env env, int64_t val) {
  765. napi_value value;
  766. napi_status status = napi_create_bigint_int64(env, val, &value);
  767. NAPI_THROW_IF_FAILED(env, status, BigInt());
  768. return BigInt(env, value);
  769. }
  770. inline BigInt BigInt::New(napi_env env, uint64_t val) {
  771. napi_value value;
  772. napi_status status = napi_create_bigint_uint64(env, val, &value);
  773. NAPI_THROW_IF_FAILED(env, status, BigInt());
  774. return BigInt(env, value);
  775. }
  776. inline BigInt BigInt::New(napi_env env,
  777. int sign_bit,
  778. size_t word_count,
  779. const uint64_t* words) {
  780. napi_value value;
  781. napi_status status =
  782. napi_create_bigint_words(env, sign_bit, word_count, words, &value);
  783. NAPI_THROW_IF_FAILED(env, status, BigInt());
  784. return BigInt(env, value);
  785. }
  786. inline void BigInt::CheckCast(napi_env env, napi_value value) {
  787. NAPI_CHECK(value != nullptr, "BigInt::CheckCast", "empty value");
  788. napi_valuetype type;
  789. napi_status status = napi_typeof(env, value, &type);
  790. NAPI_CHECK(status == napi_ok, "BigInt::CheckCast", "napi_typeof failed");
  791. NAPI_CHECK(
  792. type == napi_bigint, "BigInt::CheckCast", "value is not napi_bigint");
  793. }
  794. inline BigInt::BigInt() : Value() {}
  795. inline BigInt::BigInt(napi_env env, napi_value value) : Value(env, value) {}
  796. inline int64_t BigInt::Int64Value(bool* lossless) const {
  797. int64_t result;
  798. napi_status status =
  799. napi_get_value_bigint_int64(_env, _value, &result, lossless);
  800. NAPI_THROW_IF_FAILED(_env, status, 0);
  801. return result;
  802. }
  803. inline uint64_t BigInt::Uint64Value(bool* lossless) const {
  804. uint64_t result;
  805. napi_status status =
  806. napi_get_value_bigint_uint64(_env, _value, &result, lossless);
  807. NAPI_THROW_IF_FAILED(_env, status, 0);
  808. return result;
  809. }
  810. inline size_t BigInt::WordCount() const {
  811. size_t word_count;
  812. napi_status status =
  813. napi_get_value_bigint_words(_env, _value, nullptr, &word_count, nullptr);
  814. NAPI_THROW_IF_FAILED(_env, status, 0);
  815. return word_count;
  816. }
  817. inline void BigInt::ToWords(int* sign_bit,
  818. size_t* word_count,
  819. uint64_t* words) {
  820. napi_status status =
  821. napi_get_value_bigint_words(_env, _value, sign_bit, word_count, words);
  822. NAPI_THROW_IF_FAILED_VOID(_env, status);
  823. }
  824. #endif // NAPI_VERSION > 5
  825. #if (NAPI_VERSION > 4)
  826. ////////////////////////////////////////////////////////////////////////////////
  827. // Date Class
  828. ////////////////////////////////////////////////////////////////////////////////
  829. inline Date Date::New(napi_env env, double val) {
  830. napi_value value;
  831. napi_status status = napi_create_date(env, val, &value);
  832. NAPI_THROW_IF_FAILED(env, status, Date());
  833. return Date(env, value);
  834. }
  835. inline void Date::CheckCast(napi_env env, napi_value value) {
  836. NAPI_CHECK(value != nullptr, "Date::CheckCast", "empty value");
  837. bool result;
  838. napi_status status = napi_is_date(env, value, &result);
  839. NAPI_CHECK(status == napi_ok, "Date::CheckCast", "napi_is_date failed");
  840. NAPI_CHECK(result, "Date::CheckCast", "value is not date");
  841. }
  842. inline Date::Date() : Value() {}
  843. inline Date::Date(napi_env env, napi_value value) : Value(env, value) {}
  844. inline Date::operator double() const {
  845. return ValueOf();
  846. }
  847. inline double Date::ValueOf() const {
  848. double result;
  849. napi_status status = napi_get_date_value(_env, _value, &result);
  850. NAPI_THROW_IF_FAILED(_env, status, 0);
  851. return result;
  852. }
  853. #endif
  854. ////////////////////////////////////////////////////////////////////////////////
  855. // Name class
  856. ////////////////////////////////////////////////////////////////////////////////
  857. inline void Name::CheckCast(napi_env env, napi_value value) {
  858. NAPI_CHECK(value != nullptr, "Name::CheckCast", "empty value");
  859. napi_valuetype type;
  860. napi_status status = napi_typeof(env, value, &type);
  861. NAPI_CHECK(status == napi_ok, "Name::CheckCast", "napi_typeof failed");
  862. NAPI_CHECK(type == napi_string || type == napi_symbol,
  863. "Name::CheckCast",
  864. "value is not napi_string or napi_symbol");
  865. }
  866. inline Name::Name() : Value() {}
  867. inline Name::Name(napi_env env, napi_value value) : Value(env, value) {}
  868. ////////////////////////////////////////////////////////////////////////////////
  869. // String class
  870. ////////////////////////////////////////////////////////////////////////////////
  871. inline String String::New(napi_env env, const std::string& val) {
  872. return String::New(env, val.c_str(), val.size());
  873. }
  874. inline String String::New(napi_env env, const std::u16string& val) {
  875. return String::New(env, val.c_str(), val.size());
  876. }
  877. inline String String::New(napi_env env, const char* val) {
  878. // TODO(@gabrielschulhof) Remove if-statement when core's error handling is
  879. // available in all supported versions.
  880. if (val == nullptr) {
  881. // Throw an error that looks like it came from core.
  882. NAPI_THROW_IF_FAILED(env, napi_invalid_arg, String());
  883. }
  884. napi_value value;
  885. napi_status status =
  886. napi_create_string_utf8(env, val, std::strlen(val), &value);
  887. NAPI_THROW_IF_FAILED(env, status, String());
  888. return String(env, value);
  889. }
  890. inline String String::New(napi_env env, const char16_t* val) {
  891. napi_value value;
  892. // TODO(@gabrielschulhof) Remove if-statement when core's error handling is
  893. // available in all supported versions.
  894. if (val == nullptr) {
  895. // Throw an error that looks like it came from core.
  896. NAPI_THROW_IF_FAILED(env, napi_invalid_arg, String());
  897. }
  898. napi_status status =
  899. napi_create_string_utf16(env, val, std::u16string(val).size(), &value);
  900. NAPI_THROW_IF_FAILED(env, status, String());
  901. return String(env, value);
  902. }
  903. inline String String::New(napi_env env, const char* val, size_t length) {
  904. napi_value value;
  905. napi_status status = napi_create_string_utf8(env, val, length, &value);
  906. NAPI_THROW_IF_FAILED(env, status, String());
  907. return String(env, value);
  908. }
  909. inline String String::New(napi_env env, const char16_t* val, size_t length) {
  910. napi_value value;
  911. napi_status status = napi_create_string_utf16(env, val, length, &value);
  912. NAPI_THROW_IF_FAILED(env, status, String());
  913. return String(env, value);
  914. }
  915. inline void String::CheckCast(napi_env env, napi_value value) {
  916. NAPI_CHECK(value != nullptr, "String::CheckCast", "empty value");
  917. napi_valuetype type;
  918. napi_status status = napi_typeof(env, value, &type);
  919. NAPI_CHECK(status == napi_ok, "String::CheckCast", "napi_typeof failed");
  920. NAPI_CHECK(
  921. type == napi_string, "String::CheckCast", "value is not napi_string");
  922. }
  923. inline String::String() : Name() {}
  924. inline String::String(napi_env env, napi_value value) : Name(env, value) {}
  925. inline String::operator std::string() const {
  926. return Utf8Value();
  927. }
  928. inline String::operator std::u16string() const {
  929. return Utf16Value();
  930. }
  931. inline std::string String::Utf8Value() const {
  932. size_t length;
  933. napi_status status =
  934. napi_get_value_string_utf8(_env, _value, nullptr, 0, &length);
  935. NAPI_THROW_IF_FAILED(_env, status, "");
  936. std::string value;
  937. value.reserve(length + 1);
  938. value.resize(length);
  939. status = napi_get_value_string_utf8(
  940. _env, _value, &value[0], value.capacity(), nullptr);
  941. NAPI_THROW_IF_FAILED(_env, status, "");
  942. return value;
  943. }
  944. inline std::u16string String::Utf16Value() const {
  945. size_t length;
  946. napi_status status =
  947. napi_get_value_string_utf16(_env, _value, nullptr, 0, &length);
  948. NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT(""));
  949. std::u16string value;
  950. value.reserve(length + 1);
  951. value.resize(length);
  952. status = napi_get_value_string_utf16(
  953. _env, _value, &value[0], value.capacity(), nullptr);
  954. NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT(""));
  955. return value;
  956. }
  957. ////////////////////////////////////////////////////////////////////////////////
  958. // Symbol class
  959. ////////////////////////////////////////////////////////////////////////////////
  960. inline Symbol Symbol::New(napi_env env, const char* description) {
  961. napi_value descriptionValue = description != nullptr
  962. ? String::New(env, description)
  963. : static_cast<napi_value>(nullptr);
  964. return Symbol::New(env, descriptionValue);
  965. }
  966. inline Symbol Symbol::New(napi_env env, const std::string& description) {
  967. napi_value descriptionValue = String::New(env, description);
  968. return Symbol::New(env, descriptionValue);
  969. }
  970. inline Symbol Symbol::New(napi_env env, String description) {
  971. napi_value descriptionValue = description;
  972. return Symbol::New(env, descriptionValue);
  973. }
  974. inline Symbol Symbol::New(napi_env env, napi_value description) {
  975. napi_value value;
  976. napi_status status = napi_create_symbol(env, description, &value);
  977. NAPI_THROW_IF_FAILED(env, status, Symbol());
  978. return Symbol(env, value);
  979. }
  980. inline MaybeOrValue<Symbol> Symbol::WellKnown(napi_env env,
  981. const std::string& name) {
  982. #if defined(NODE_ADDON_API_ENABLE_MAYBE)
  983. Value symbol_obj;
  984. Value symbol_value;
  985. if (Napi::Env(env).Global().Get("Symbol").UnwrapTo(&symbol_obj) &&
  986. symbol_obj.As<Object>().Get(name).UnwrapTo(&symbol_value)) {
  987. return Just<Symbol>(symbol_value.As<Symbol>());
  988. }
  989. return Nothing<Symbol>();
  990. #else
  991. return Napi::Env(env)
  992. .Global()
  993. .Get("Symbol")
  994. .As<Object>()
  995. .Get(name)
  996. .As<Symbol>();
  997. #endif
  998. }
  999. inline MaybeOrValue<Symbol> Symbol::For(napi_env env,
  1000. const std::string& description) {
  1001. napi_value descriptionValue = String::New(env, description);
  1002. return Symbol::For(env, descriptionValue);
  1003. }
  1004. inline MaybeOrValue<Symbol> Symbol::For(napi_env env, const char* description) {
  1005. napi_value descriptionValue = String::New(env, description);
  1006. return Symbol::For(env, descriptionValue);
  1007. }
  1008. inline MaybeOrValue<Symbol> Symbol::For(napi_env env, String description) {
  1009. return Symbol::For(env, static_cast<napi_value>(description));
  1010. }
  1011. inline MaybeOrValue<Symbol> Symbol::For(napi_env env, napi_value description) {
  1012. #if defined(NODE_ADDON_API_ENABLE_MAYBE)
  1013. Value symbol_obj;
  1014. Value symbol_for_value;
  1015. Value symbol_value;
  1016. if (Napi::Env(env).Global().Get("Symbol").UnwrapTo(&symbol_obj) &&
  1017. symbol_obj.As<Object>().Get("for").UnwrapTo(&symbol_for_value) &&
  1018. symbol_for_value.As<Function>()
  1019. .Call(symbol_obj, {description})
  1020. .UnwrapTo(&symbol_value)) {
  1021. return Just<Symbol>(symbol_value.As<Symbol>());
  1022. }
  1023. return Nothing<Symbol>();
  1024. #else
  1025. Object symbol_obj = Napi::Env(env).Global().Get("Symbol").As<Object>();
  1026. return symbol_obj.Get("for")
  1027. .As<Function>()
  1028. .Call(symbol_obj, {description})
  1029. .As<Symbol>();
  1030. #endif
  1031. }
  1032. inline void Symbol::CheckCast(napi_env env, napi_value value) {
  1033. NAPI_CHECK(value != nullptr, "Symbol::CheckCast", "empty value");
  1034. napi_valuetype type;
  1035. napi_status status = napi_typeof(env, value, &type);
  1036. NAPI_CHECK(status == napi_ok, "Symbol::CheckCast", "napi_typeof failed");
  1037. NAPI_CHECK(
  1038. type == napi_symbol, "Symbol::CheckCast", "value is not napi_symbol");
  1039. }
  1040. inline Symbol::Symbol() : Name() {}
  1041. inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) {}
  1042. ////////////////////////////////////////////////////////////////////////////////
  1043. // Automagic value creation
  1044. ////////////////////////////////////////////////////////////////////////////////
  1045. namespace details {
  1046. template <typename T>
  1047. struct vf_number {
  1048. static Number From(napi_env env, T value) {
  1049. return Number::New(env, static_cast<double>(value));
  1050. }
  1051. };
  1052. template <>
  1053. struct vf_number<bool> {
  1054. static Boolean From(napi_env env, bool value) {
  1055. return Boolean::New(env, value);
  1056. }
  1057. };
  1058. struct vf_utf8_charp {
  1059. static String From(napi_env env, const char* value) {
  1060. return String::New(env, value);
  1061. }
  1062. };
  1063. struct vf_utf16_charp {
  1064. static String From(napi_env env, const char16_t* value) {
  1065. return String::New(env, value);
  1066. }
  1067. };
  1068. struct vf_utf8_string {
  1069. static String From(napi_env env, const std::string& value) {
  1070. return String::New(env, value);
  1071. }
  1072. };
  1073. struct vf_utf16_string {
  1074. static String From(napi_env env, const std::u16string& value) {
  1075. return String::New(env, value);
  1076. }
  1077. };
  1078. template <typename T>
  1079. struct vf_fallback {
  1080. static Value From(napi_env env, const T& value) { return Value(env, value); }
  1081. };
  1082. template <typename...>
  1083. struct disjunction : std::false_type {};
  1084. template <typename B>
  1085. struct disjunction<B> : B {};
  1086. template <typename B, typename... Bs>
  1087. struct disjunction<B, Bs...>
  1088. : std::conditional<bool(B::value), B, disjunction<Bs...>>::type {};
  1089. template <typename T>
  1090. struct can_make_string
  1091. : disjunction<typename std::is_convertible<T, const char*>::type,
  1092. typename std::is_convertible<T, const char16_t*>::type,
  1093. typename std::is_convertible<T, std::string>::type,
  1094. typename std::is_convertible<T, std::u16string>::type> {};
  1095. } // namespace details
  1096. template <typename T>
  1097. Value Value::From(napi_env env, const T& value) {
  1098. using Helper = typename std::conditional<
  1099. std::is_integral<T>::value || std::is_floating_point<T>::value,
  1100. details::vf_number<T>,
  1101. typename std::conditional<details::can_make_string<T>::value,
  1102. String,
  1103. details::vf_fallback<T>>::type>::type;
  1104. return Helper::From(env, value);
  1105. }
  1106. template <typename T>
  1107. String String::From(napi_env env, const T& value) {
  1108. struct Dummy {};
  1109. using Helper = typename std::conditional<
  1110. std::is_convertible<T, const char*>::value,
  1111. details::vf_utf8_charp,
  1112. typename std::conditional<
  1113. std::is_convertible<T, const char16_t*>::value,
  1114. details::vf_utf16_charp,
  1115. typename std::conditional<
  1116. std::is_convertible<T, std::string>::value,
  1117. details::vf_utf8_string,
  1118. typename std::conditional<
  1119. std::is_convertible<T, std::u16string>::value,
  1120. details::vf_utf16_string,
  1121. Dummy>::type>::type>::type>::type;
  1122. return Helper::From(env, value);
  1123. }
  1124. ////////////////////////////////////////////////////////////////////////////////
  1125. // TypeTaggable class
  1126. ////////////////////////////////////////////////////////////////////////////////
  1127. inline TypeTaggable::TypeTaggable() : Value() {}
  1128. inline TypeTaggable::TypeTaggable(napi_env _env, napi_value _value)
  1129. : Value(_env, _value) {}
  1130. #if NAPI_VERSION >= 8
  1131. inline void TypeTaggable::TypeTag(const napi_type_tag* type_tag) const {
  1132. napi_status status = napi_type_tag_object(_env, _value, type_tag);
  1133. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1134. }
  1135. inline bool TypeTaggable::CheckTypeTag(const napi_type_tag* type_tag) const {
  1136. bool result;
  1137. napi_status status =
  1138. napi_check_object_type_tag(_env, _value, type_tag, &result);
  1139. NAPI_THROW_IF_FAILED(_env, status, false);
  1140. return result;
  1141. }
  1142. #endif // NAPI_VERSION >= 8
  1143. ////////////////////////////////////////////////////////////////////////////////
  1144. // Object class
  1145. ////////////////////////////////////////////////////////////////////////////////
  1146. template <typename Key>
  1147. inline Object::PropertyLValue<Key>::operator Value() const {
  1148. MaybeOrValue<Value> val = Object(_env, _object).Get(_key);
  1149. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  1150. return val.Unwrap();
  1151. #else
  1152. return val;
  1153. #endif
  1154. }
  1155. template <typename Key>
  1156. template <typename ValueType>
  1157. inline Object::PropertyLValue<Key>& Object::PropertyLValue<Key>::operator=(
  1158. ValueType value) {
  1159. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  1160. MaybeOrValue<bool> result =
  1161. #endif
  1162. Object(_env, _object).Set(_key, value);
  1163. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  1164. result.Unwrap();
  1165. #endif
  1166. return *this;
  1167. }
  1168. template <typename Key>
  1169. inline Object::PropertyLValue<Key>::PropertyLValue(Object object, Key key)
  1170. : _env(object.Env()), _object(object), _key(key) {}
  1171. inline Object Object::New(napi_env env) {
  1172. napi_value value;
  1173. napi_status status = napi_create_object(env, &value);
  1174. NAPI_THROW_IF_FAILED(env, status, Object());
  1175. return Object(env, value);
  1176. }
  1177. inline void Object::CheckCast(napi_env env, napi_value value) {
  1178. NAPI_CHECK(value != nullptr, "Object::CheckCast", "empty value");
  1179. napi_valuetype type;
  1180. napi_status status = napi_typeof(env, value, &type);
  1181. NAPI_CHECK(status == napi_ok, "Object::CheckCast", "napi_typeof failed");
  1182. NAPI_CHECK(
  1183. type == napi_object, "Object::CheckCast", "value is not napi_object");
  1184. }
  1185. inline Object::Object() : TypeTaggable() {}
  1186. inline Object::Object(napi_env env, napi_value value)
  1187. : TypeTaggable(env, value) {}
  1188. inline Object::PropertyLValue<std::string> Object::operator[](
  1189. const char* utf8name) {
  1190. return PropertyLValue<std::string>(*this, utf8name);
  1191. }
  1192. inline Object::PropertyLValue<std::string> Object::operator[](
  1193. const std::string& utf8name) {
  1194. return PropertyLValue<std::string>(*this, utf8name);
  1195. }
  1196. inline Object::PropertyLValue<uint32_t> Object::operator[](uint32_t index) {
  1197. return PropertyLValue<uint32_t>(*this, index);
  1198. }
  1199. inline Object::PropertyLValue<Value> Object::operator[](Value index) const {
  1200. return PropertyLValue<Value>(*this, index);
  1201. }
  1202. inline MaybeOrValue<Value> Object::operator[](const char* utf8name) const {
  1203. return Get(utf8name);
  1204. }
  1205. inline MaybeOrValue<Value> Object::operator[](
  1206. const std::string& utf8name) const {
  1207. return Get(utf8name);
  1208. }
  1209. inline MaybeOrValue<Value> Object::operator[](uint32_t index) const {
  1210. return Get(index);
  1211. }
  1212. inline MaybeOrValue<bool> Object::Has(napi_value key) const {
  1213. bool result;
  1214. napi_status status = napi_has_property(_env, _value, key, &result);
  1215. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1216. }
  1217. inline MaybeOrValue<bool> Object::Has(Value key) const {
  1218. bool result;
  1219. napi_status status = napi_has_property(_env, _value, key, &result);
  1220. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1221. }
  1222. inline MaybeOrValue<bool> Object::Has(const char* utf8name) const {
  1223. bool result;
  1224. napi_status status = napi_has_named_property(_env, _value, utf8name, &result);
  1225. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1226. }
  1227. inline MaybeOrValue<bool> Object::Has(const std::string& utf8name) const {
  1228. return Has(utf8name.c_str());
  1229. }
  1230. inline MaybeOrValue<bool> Object::HasOwnProperty(napi_value key) const {
  1231. bool result;
  1232. napi_status status = napi_has_own_property(_env, _value, key, &result);
  1233. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1234. }
  1235. inline MaybeOrValue<bool> Object::HasOwnProperty(Value key) const {
  1236. bool result;
  1237. napi_status status = napi_has_own_property(_env, _value, key, &result);
  1238. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1239. }
  1240. inline MaybeOrValue<bool> Object::HasOwnProperty(const char* utf8name) const {
  1241. napi_value key;
  1242. napi_status status =
  1243. napi_create_string_utf8(_env, utf8name, std::strlen(utf8name), &key);
  1244. NAPI_MAYBE_THROW_IF_FAILED(_env, status, bool);
  1245. return HasOwnProperty(key);
  1246. }
  1247. inline MaybeOrValue<bool> Object::HasOwnProperty(
  1248. const std::string& utf8name) const {
  1249. return HasOwnProperty(utf8name.c_str());
  1250. }
  1251. inline MaybeOrValue<Value> Object::Get(napi_value key) const {
  1252. napi_value result;
  1253. napi_status status = napi_get_property(_env, _value, key, &result);
  1254. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value);
  1255. }
  1256. inline MaybeOrValue<Value> Object::Get(Value key) const {
  1257. napi_value result;
  1258. napi_status status = napi_get_property(_env, _value, key, &result);
  1259. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value);
  1260. }
  1261. inline MaybeOrValue<Value> Object::Get(const char* utf8name) const {
  1262. napi_value result;
  1263. napi_status status = napi_get_named_property(_env, _value, utf8name, &result);
  1264. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value);
  1265. }
  1266. inline MaybeOrValue<Value> Object::Get(const std::string& utf8name) const {
  1267. return Get(utf8name.c_str());
  1268. }
  1269. template <typename ValueType>
  1270. inline MaybeOrValue<bool> Object::Set(napi_value key,
  1271. const ValueType& value) const {
  1272. napi_status status =
  1273. napi_set_property(_env, _value, key, Value::From(_env, value));
  1274. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1275. }
  1276. template <typename ValueType>
  1277. inline MaybeOrValue<bool> Object::Set(Value key, const ValueType& value) const {
  1278. napi_status status =
  1279. napi_set_property(_env, _value, key, Value::From(_env, value));
  1280. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1281. }
  1282. template <typename ValueType>
  1283. inline MaybeOrValue<bool> Object::Set(const char* utf8name,
  1284. const ValueType& value) const {
  1285. napi_status status =
  1286. napi_set_named_property(_env, _value, utf8name, Value::From(_env, value));
  1287. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1288. }
  1289. template <typename ValueType>
  1290. inline MaybeOrValue<bool> Object::Set(const std::string& utf8name,
  1291. const ValueType& value) const {
  1292. return Set(utf8name.c_str(), value);
  1293. }
  1294. inline MaybeOrValue<bool> Object::Delete(napi_value key) const {
  1295. bool result;
  1296. napi_status status = napi_delete_property(_env, _value, key, &result);
  1297. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1298. }
  1299. inline MaybeOrValue<bool> Object::Delete(Value key) const {
  1300. bool result;
  1301. napi_status status = napi_delete_property(_env, _value, key, &result);
  1302. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1303. }
  1304. inline MaybeOrValue<bool> Object::Delete(const char* utf8name) const {
  1305. return Delete(String::New(_env, utf8name));
  1306. }
  1307. inline MaybeOrValue<bool> Object::Delete(const std::string& utf8name) const {
  1308. return Delete(String::New(_env, utf8name));
  1309. }
  1310. inline MaybeOrValue<bool> Object::Has(uint32_t index) const {
  1311. bool result;
  1312. napi_status status = napi_has_element(_env, _value, index, &result);
  1313. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1314. }
  1315. inline MaybeOrValue<Value> Object::Get(uint32_t index) const {
  1316. napi_value value;
  1317. napi_status status = napi_get_element(_env, _value, index, &value);
  1318. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, value), Value);
  1319. }
  1320. template <typename ValueType>
  1321. inline MaybeOrValue<bool> Object::Set(uint32_t index,
  1322. const ValueType& value) const {
  1323. napi_status status =
  1324. napi_set_element(_env, _value, index, Value::From(_env, value));
  1325. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1326. }
  1327. inline MaybeOrValue<bool> Object::Delete(uint32_t index) const {
  1328. bool result;
  1329. napi_status status = napi_delete_element(_env, _value, index, &result);
  1330. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1331. }
  1332. inline MaybeOrValue<Array> Object::GetPropertyNames() const {
  1333. napi_value result;
  1334. napi_status status = napi_get_property_names(_env, _value, &result);
  1335. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Array(_env, result), Array);
  1336. }
  1337. inline MaybeOrValue<bool> Object::DefineProperty(
  1338. const PropertyDescriptor& property) const {
  1339. napi_status status = napi_define_properties(
  1340. _env,
  1341. _value,
  1342. 1,
  1343. reinterpret_cast<const napi_property_descriptor*>(&property));
  1344. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1345. }
  1346. inline MaybeOrValue<bool> Object::DefineProperties(
  1347. const std::initializer_list<PropertyDescriptor>& properties) const {
  1348. napi_status status = napi_define_properties(
  1349. _env,
  1350. _value,
  1351. properties.size(),
  1352. reinterpret_cast<const napi_property_descriptor*>(properties.begin()));
  1353. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1354. }
  1355. inline MaybeOrValue<bool> Object::DefineProperties(
  1356. const std::vector<PropertyDescriptor>& properties) const {
  1357. napi_status status = napi_define_properties(
  1358. _env,
  1359. _value,
  1360. properties.size(),
  1361. reinterpret_cast<const napi_property_descriptor*>(properties.data()));
  1362. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1363. }
  1364. inline MaybeOrValue<bool> Object::InstanceOf(
  1365. const Function& constructor) const {
  1366. bool result;
  1367. napi_status status = napi_instanceof(_env, _value, constructor, &result);
  1368. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
  1369. }
  1370. template <typename Finalizer, typename T>
  1371. inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) const {
  1372. details::FinalizeData<T, Finalizer>* finalizeData =
  1373. new details::FinalizeData<T, Finalizer>(
  1374. {std::move(finalizeCallback), nullptr});
  1375. napi_status status =
  1376. details::AttachData<T, details::FinalizeData<T, Finalizer>::Wrapper>(
  1377. _env, *this, data, finalizeData);
  1378. if (status != napi_ok) {
  1379. delete finalizeData;
  1380. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1381. }
  1382. }
  1383. template <typename Finalizer, typename T, typename Hint>
  1384. inline void Object::AddFinalizer(Finalizer finalizeCallback,
  1385. T* data,
  1386. Hint* finalizeHint) const {
  1387. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  1388. new details::FinalizeData<T, Finalizer, Hint>(
  1389. {std::move(finalizeCallback), finalizeHint});
  1390. napi_status status = details::
  1391. AttachData<T, details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint>(
  1392. _env, *this, data, finalizeData);
  1393. if (status != napi_ok) {
  1394. delete finalizeData;
  1395. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1396. }
  1397. }
  1398. #ifdef NAPI_CPP_EXCEPTIONS
  1399. inline Object::const_iterator::const_iterator(const Object* object,
  1400. const Type type) {
  1401. _object = object;
  1402. _keys = object->GetPropertyNames();
  1403. _index = type == Type::BEGIN ? 0 : _keys.Length();
  1404. }
  1405. inline Object::const_iterator Napi::Object::begin() const {
  1406. const_iterator it(this, Object::const_iterator::Type::BEGIN);
  1407. return it;
  1408. }
  1409. inline Object::const_iterator Napi::Object::end() const {
  1410. const_iterator it(this, Object::const_iterator::Type::END);
  1411. return it;
  1412. }
  1413. inline Object::const_iterator& Object::const_iterator::operator++() {
  1414. ++_index;
  1415. return *this;
  1416. }
  1417. inline bool Object::const_iterator::operator==(
  1418. const const_iterator& other) const {
  1419. return _index == other._index;
  1420. }
  1421. inline bool Object::const_iterator::operator!=(
  1422. const const_iterator& other) const {
  1423. return _index != other._index;
  1424. }
  1425. inline const std::pair<Value, Object::PropertyLValue<Value>>
  1426. Object::const_iterator::operator*() const {
  1427. const Value key = _keys[_index];
  1428. const PropertyLValue<Value> value = (*_object)[key];
  1429. return {key, value};
  1430. }
  1431. inline Object::iterator::iterator(Object* object, const Type type) {
  1432. _object = object;
  1433. _keys = object->GetPropertyNames();
  1434. _index = type == Type::BEGIN ? 0 : _keys.Length();
  1435. }
  1436. inline Object::iterator Napi::Object::begin() {
  1437. iterator it(this, Object::iterator::Type::BEGIN);
  1438. return it;
  1439. }
  1440. inline Object::iterator Napi::Object::end() {
  1441. iterator it(this, Object::iterator::Type::END);
  1442. return it;
  1443. }
  1444. inline Object::iterator& Object::iterator::operator++() {
  1445. ++_index;
  1446. return *this;
  1447. }
  1448. inline bool Object::iterator::operator==(const iterator& other) const {
  1449. return _index == other._index;
  1450. }
  1451. inline bool Object::iterator::operator!=(const iterator& other) const {
  1452. return _index != other._index;
  1453. }
  1454. inline std::pair<Value, Object::PropertyLValue<Value>>
  1455. Object::iterator::operator*() {
  1456. Value key = _keys[_index];
  1457. PropertyLValue<Value> value = (*_object)[key];
  1458. return {key, value};
  1459. }
  1460. #endif // NAPI_CPP_EXCEPTIONS
  1461. #if NAPI_VERSION >= 8
  1462. inline MaybeOrValue<bool> Object::Freeze() const {
  1463. napi_status status = napi_object_freeze(_env, _value);
  1464. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1465. }
  1466. inline MaybeOrValue<bool> Object::Seal() const {
  1467. napi_status status = napi_object_seal(_env, _value);
  1468. NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
  1469. }
  1470. #endif // NAPI_VERSION >= 8
  1471. ////////////////////////////////////////////////////////////////////////////////
  1472. // External class
  1473. ////////////////////////////////////////////////////////////////////////////////
  1474. template <typename T>
  1475. inline External<T> External<T>::New(napi_env env, T* data) {
  1476. napi_value value;
  1477. napi_status status =
  1478. napi_create_external(env, data, nullptr, nullptr, &value);
  1479. NAPI_THROW_IF_FAILED(env, status, External());
  1480. return External(env, value);
  1481. }
  1482. template <typename T>
  1483. template <typename Finalizer>
  1484. inline External<T> External<T>::New(napi_env env,
  1485. T* data,
  1486. Finalizer finalizeCallback) {
  1487. napi_value value;
  1488. details::FinalizeData<T, Finalizer>* finalizeData =
  1489. new details::FinalizeData<T, Finalizer>(
  1490. {std::move(finalizeCallback), nullptr});
  1491. napi_status status =
  1492. napi_create_external(env,
  1493. data,
  1494. details::FinalizeData<T, Finalizer>::Wrapper,
  1495. finalizeData,
  1496. &value);
  1497. if (status != napi_ok) {
  1498. delete finalizeData;
  1499. NAPI_THROW_IF_FAILED(env, status, External());
  1500. }
  1501. return External(env, value);
  1502. }
  1503. template <typename T>
  1504. template <typename Finalizer, typename Hint>
  1505. inline External<T> External<T>::New(napi_env env,
  1506. T* data,
  1507. Finalizer finalizeCallback,
  1508. Hint* finalizeHint) {
  1509. napi_value value;
  1510. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  1511. new details::FinalizeData<T, Finalizer, Hint>(
  1512. {std::move(finalizeCallback), finalizeHint});
  1513. napi_status status = napi_create_external(
  1514. env,
  1515. data,
  1516. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
  1517. finalizeData,
  1518. &value);
  1519. if (status != napi_ok) {
  1520. delete finalizeData;
  1521. NAPI_THROW_IF_FAILED(env, status, External());
  1522. }
  1523. return External(env, value);
  1524. }
  1525. template <typename T>
  1526. inline void External<T>::CheckCast(napi_env env, napi_value value) {
  1527. NAPI_CHECK(value != nullptr, "External::CheckCast", "empty value");
  1528. napi_valuetype type;
  1529. napi_status status = napi_typeof(env, value, &type);
  1530. NAPI_CHECK(status == napi_ok, "External::CheckCast", "napi_typeof failed");
  1531. NAPI_CHECK(type == napi_external,
  1532. "External::CheckCast",
  1533. "value is not napi_external");
  1534. }
  1535. template <typename T>
  1536. inline External<T>::External() : TypeTaggable() {}
  1537. template <typename T>
  1538. inline External<T>::External(napi_env env, napi_value value)
  1539. : TypeTaggable(env, value) {}
  1540. template <typename T>
  1541. inline T* External<T>::Data() const {
  1542. void* data;
  1543. napi_status status = napi_get_value_external(_env, _value, &data);
  1544. NAPI_THROW_IF_FAILED(_env, status, nullptr);
  1545. return reinterpret_cast<T*>(data);
  1546. }
  1547. ////////////////////////////////////////////////////////////////////////////////
  1548. // Array class
  1549. ////////////////////////////////////////////////////////////////////////////////
  1550. inline Array Array::New(napi_env env) {
  1551. napi_value value;
  1552. napi_status status = napi_create_array(env, &value);
  1553. NAPI_THROW_IF_FAILED(env, status, Array());
  1554. return Array(env, value);
  1555. }
  1556. inline Array Array::New(napi_env env, size_t length) {
  1557. napi_value value;
  1558. napi_status status = napi_create_array_with_length(env, length, &value);
  1559. NAPI_THROW_IF_FAILED(env, status, Array());
  1560. return Array(env, value);
  1561. }
  1562. inline void Array::CheckCast(napi_env env, napi_value value) {
  1563. NAPI_CHECK(value != nullptr, "Array::CheckCast", "empty value");
  1564. bool result;
  1565. napi_status status = napi_is_array(env, value, &result);
  1566. NAPI_CHECK(status == napi_ok, "Array::CheckCast", "napi_is_array failed");
  1567. NAPI_CHECK(result, "Array::CheckCast", "value is not array");
  1568. }
  1569. inline Array::Array() : Object() {}
  1570. inline Array::Array(napi_env env, napi_value value) : Object(env, value) {}
  1571. inline uint32_t Array::Length() const {
  1572. uint32_t result;
  1573. napi_status status = napi_get_array_length(_env, _value, &result);
  1574. NAPI_THROW_IF_FAILED(_env, status, 0);
  1575. return result;
  1576. }
  1577. ////////////////////////////////////////////////////////////////////////////////
  1578. // ArrayBuffer class
  1579. ////////////////////////////////////////////////////////////////////////////////
  1580. inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
  1581. napi_value value;
  1582. void* data;
  1583. napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value);
  1584. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1585. return ArrayBuffer(env, value);
  1586. }
  1587. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  1588. inline ArrayBuffer ArrayBuffer::New(napi_env env,
  1589. void* externalData,
  1590. size_t byteLength) {
  1591. napi_value value;
  1592. napi_status status = napi_create_external_arraybuffer(
  1593. env, externalData, byteLength, nullptr, nullptr, &value);
  1594. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1595. return ArrayBuffer(env, value);
  1596. }
  1597. template <typename Finalizer>
  1598. inline ArrayBuffer ArrayBuffer::New(napi_env env,
  1599. void* externalData,
  1600. size_t byteLength,
  1601. Finalizer finalizeCallback) {
  1602. napi_value value;
  1603. details::FinalizeData<void, Finalizer>* finalizeData =
  1604. new details::FinalizeData<void, Finalizer>(
  1605. {std::move(finalizeCallback), nullptr});
  1606. napi_status status = napi_create_external_arraybuffer(
  1607. env,
  1608. externalData,
  1609. byteLength,
  1610. details::FinalizeData<void, Finalizer>::Wrapper,
  1611. finalizeData,
  1612. &value);
  1613. if (status != napi_ok) {
  1614. delete finalizeData;
  1615. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1616. }
  1617. return ArrayBuffer(env, value);
  1618. }
  1619. template <typename Finalizer, typename Hint>
  1620. inline ArrayBuffer ArrayBuffer::New(napi_env env,
  1621. void* externalData,
  1622. size_t byteLength,
  1623. Finalizer finalizeCallback,
  1624. Hint* finalizeHint) {
  1625. napi_value value;
  1626. details::FinalizeData<void, Finalizer, Hint>* finalizeData =
  1627. new details::FinalizeData<void, Finalizer, Hint>(
  1628. {std::move(finalizeCallback), finalizeHint});
  1629. napi_status status = napi_create_external_arraybuffer(
  1630. env,
  1631. externalData,
  1632. byteLength,
  1633. details::FinalizeData<void, Finalizer, Hint>::WrapperWithHint,
  1634. finalizeData,
  1635. &value);
  1636. if (status != napi_ok) {
  1637. delete finalizeData;
  1638. NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
  1639. }
  1640. return ArrayBuffer(env, value);
  1641. }
  1642. #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  1643. inline void ArrayBuffer::CheckCast(napi_env env, napi_value value) {
  1644. NAPI_CHECK(value != nullptr, "ArrayBuffer::CheckCast", "empty value");
  1645. bool result;
  1646. napi_status status = napi_is_arraybuffer(env, value, &result);
  1647. NAPI_CHECK(status == napi_ok,
  1648. "ArrayBuffer::CheckCast",
  1649. "napi_is_arraybuffer failed");
  1650. NAPI_CHECK(result, "ArrayBuffer::CheckCast", "value is not arraybuffer");
  1651. }
  1652. inline ArrayBuffer::ArrayBuffer() : Object() {}
  1653. inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
  1654. : Object(env, value) {}
  1655. inline void* ArrayBuffer::Data() {
  1656. void* data;
  1657. napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
  1658. NAPI_THROW_IF_FAILED(_env, status, nullptr);
  1659. return data;
  1660. }
  1661. inline size_t ArrayBuffer::ByteLength() {
  1662. size_t length;
  1663. napi_status status =
  1664. napi_get_arraybuffer_info(_env, _value, nullptr, &length);
  1665. NAPI_THROW_IF_FAILED(_env, status, 0);
  1666. return length;
  1667. }
  1668. #if NAPI_VERSION >= 7
  1669. inline bool ArrayBuffer::IsDetached() const {
  1670. bool detached;
  1671. napi_status status = napi_is_detached_arraybuffer(_env, _value, &detached);
  1672. NAPI_THROW_IF_FAILED(_env, status, false);
  1673. return detached;
  1674. }
  1675. inline void ArrayBuffer::Detach() {
  1676. napi_status status = napi_detach_arraybuffer(_env, _value);
  1677. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1678. }
  1679. #endif // NAPI_VERSION >= 7
  1680. ////////////////////////////////////////////////////////////////////////////////
  1681. // DataView class
  1682. ////////////////////////////////////////////////////////////////////////////////
  1683. inline DataView DataView::New(napi_env env, Napi::ArrayBuffer arrayBuffer) {
  1684. return New(env, arrayBuffer, 0, arrayBuffer.ByteLength());
  1685. }
  1686. inline DataView DataView::New(napi_env env,
  1687. Napi::ArrayBuffer arrayBuffer,
  1688. size_t byteOffset) {
  1689. if (byteOffset > arrayBuffer.ByteLength()) {
  1690. NAPI_THROW(RangeError::New(
  1691. env, "Start offset is outside the bounds of the buffer"),
  1692. DataView());
  1693. }
  1694. return New(
  1695. env, arrayBuffer, byteOffset, arrayBuffer.ByteLength() - byteOffset);
  1696. }
  1697. inline DataView DataView::New(napi_env env,
  1698. Napi::ArrayBuffer arrayBuffer,
  1699. size_t byteOffset,
  1700. size_t byteLength) {
  1701. if (byteOffset + byteLength > arrayBuffer.ByteLength()) {
  1702. NAPI_THROW(RangeError::New(env, "Invalid DataView length"), DataView());
  1703. }
  1704. napi_value value;
  1705. napi_status status =
  1706. napi_create_dataview(env, byteLength, arrayBuffer, byteOffset, &value);
  1707. NAPI_THROW_IF_FAILED(env, status, DataView());
  1708. return DataView(env, value);
  1709. }
  1710. inline void DataView::CheckCast(napi_env env, napi_value value) {
  1711. NAPI_CHECK(value != nullptr, "DataView::CheckCast", "empty value");
  1712. bool result;
  1713. napi_status status = napi_is_dataview(env, value, &result);
  1714. NAPI_CHECK(
  1715. status == napi_ok, "DataView::CheckCast", "napi_is_dataview failed");
  1716. NAPI_CHECK(result, "DataView::CheckCast", "value is not dataview");
  1717. }
  1718. inline DataView::DataView() : Object() {}
  1719. inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) {
  1720. napi_status status = napi_get_dataview_info(_env,
  1721. _value /* dataView */,
  1722. &_length /* byteLength */,
  1723. &_data /* data */,
  1724. nullptr /* arrayBuffer */,
  1725. nullptr /* byteOffset */);
  1726. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1727. }
  1728. inline Napi::ArrayBuffer DataView::ArrayBuffer() const {
  1729. napi_value arrayBuffer;
  1730. napi_status status = napi_get_dataview_info(_env,
  1731. _value /* dataView */,
  1732. nullptr /* byteLength */,
  1733. nullptr /* data */,
  1734. &arrayBuffer /* arrayBuffer */,
  1735. nullptr /* byteOffset */);
  1736. NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
  1737. return Napi::ArrayBuffer(_env, arrayBuffer);
  1738. }
  1739. inline size_t DataView::ByteOffset() const {
  1740. size_t byteOffset;
  1741. napi_status status = napi_get_dataview_info(_env,
  1742. _value /* dataView */,
  1743. nullptr /* byteLength */,
  1744. nullptr /* data */,
  1745. nullptr /* arrayBuffer */,
  1746. &byteOffset /* byteOffset */);
  1747. NAPI_THROW_IF_FAILED(_env, status, 0);
  1748. return byteOffset;
  1749. }
  1750. inline size_t DataView::ByteLength() const {
  1751. return _length;
  1752. }
  1753. inline void* DataView::Data() const {
  1754. return _data;
  1755. }
  1756. inline float DataView::GetFloat32(size_t byteOffset) const {
  1757. return ReadData<float>(byteOffset);
  1758. }
  1759. inline double DataView::GetFloat64(size_t byteOffset) const {
  1760. return ReadData<double>(byteOffset);
  1761. }
  1762. inline int8_t DataView::GetInt8(size_t byteOffset) const {
  1763. return ReadData<int8_t>(byteOffset);
  1764. }
  1765. inline int16_t DataView::GetInt16(size_t byteOffset) const {
  1766. return ReadData<int16_t>(byteOffset);
  1767. }
  1768. inline int32_t DataView::GetInt32(size_t byteOffset) const {
  1769. return ReadData<int32_t>(byteOffset);
  1770. }
  1771. inline uint8_t DataView::GetUint8(size_t byteOffset) const {
  1772. return ReadData<uint8_t>(byteOffset);
  1773. }
  1774. inline uint16_t DataView::GetUint16(size_t byteOffset) const {
  1775. return ReadData<uint16_t>(byteOffset);
  1776. }
  1777. inline uint32_t DataView::GetUint32(size_t byteOffset) const {
  1778. return ReadData<uint32_t>(byteOffset);
  1779. }
  1780. inline void DataView::SetFloat32(size_t byteOffset, float value) const {
  1781. WriteData<float>(byteOffset, value);
  1782. }
  1783. inline void DataView::SetFloat64(size_t byteOffset, double value) const {
  1784. WriteData<double>(byteOffset, value);
  1785. }
  1786. inline void DataView::SetInt8(size_t byteOffset, int8_t value) const {
  1787. WriteData<int8_t>(byteOffset, value);
  1788. }
  1789. inline void DataView::SetInt16(size_t byteOffset, int16_t value) const {
  1790. WriteData<int16_t>(byteOffset, value);
  1791. }
  1792. inline void DataView::SetInt32(size_t byteOffset, int32_t value) const {
  1793. WriteData<int32_t>(byteOffset, value);
  1794. }
  1795. inline void DataView::SetUint8(size_t byteOffset, uint8_t value) const {
  1796. WriteData<uint8_t>(byteOffset, value);
  1797. }
  1798. inline void DataView::SetUint16(size_t byteOffset, uint16_t value) const {
  1799. WriteData<uint16_t>(byteOffset, value);
  1800. }
  1801. inline void DataView::SetUint32(size_t byteOffset, uint32_t value) const {
  1802. WriteData<uint32_t>(byteOffset, value);
  1803. }
  1804. template <typename T>
  1805. inline T DataView::ReadData(size_t byteOffset) const {
  1806. if (byteOffset + sizeof(T) > _length ||
  1807. byteOffset + sizeof(T) < byteOffset) { // overflow
  1808. NAPI_THROW(
  1809. RangeError::New(_env, "Offset is outside the bounds of the DataView"),
  1810. 0);
  1811. }
  1812. return *reinterpret_cast<T*>(static_cast<uint8_t*>(_data) + byteOffset);
  1813. }
  1814. template <typename T>
  1815. inline void DataView::WriteData(size_t byteOffset, T value) const {
  1816. if (byteOffset + sizeof(T) > _length ||
  1817. byteOffset + sizeof(T) < byteOffset) { // overflow
  1818. NAPI_THROW_VOID(
  1819. RangeError::New(_env, "Offset is outside the bounds of the DataView"));
  1820. }
  1821. *reinterpret_cast<T*>(static_cast<uint8_t*>(_data) + byteOffset) = value;
  1822. }
  1823. ////////////////////////////////////////////////////////////////////////////////
  1824. // TypedArray class
  1825. ////////////////////////////////////////////////////////////////////////////////
  1826. inline void TypedArray::CheckCast(napi_env env, napi_value value) {
  1827. NAPI_CHECK(value != nullptr, "TypedArray::CheckCast", "empty value");
  1828. bool result;
  1829. napi_status status = napi_is_typedarray(env, value, &result);
  1830. NAPI_CHECK(
  1831. status == napi_ok, "TypedArray::CheckCast", "napi_is_typedarray failed");
  1832. NAPI_CHECK(result, "TypedArray::CheckCast", "value is not typedarray");
  1833. }
  1834. inline TypedArray::TypedArray()
  1835. : Object(), _type(napi_typedarray_type::napi_int8_array), _length(0) {}
  1836. inline TypedArray::TypedArray(napi_env env, napi_value value)
  1837. : Object(env, value),
  1838. _type(napi_typedarray_type::napi_int8_array),
  1839. _length(0) {
  1840. if (value != nullptr) {
  1841. napi_status status =
  1842. napi_get_typedarray_info(_env,
  1843. _value,
  1844. &const_cast<TypedArray*>(this)->_type,
  1845. &const_cast<TypedArray*>(this)->_length,
  1846. nullptr,
  1847. nullptr,
  1848. nullptr);
  1849. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1850. }
  1851. }
  1852. inline TypedArray::TypedArray(napi_env env,
  1853. napi_value value,
  1854. napi_typedarray_type type,
  1855. size_t length)
  1856. : Object(env, value), _type(type), _length(length) {}
  1857. inline napi_typedarray_type TypedArray::TypedArrayType() const {
  1858. return _type;
  1859. }
  1860. inline uint8_t TypedArray::ElementSize() const {
  1861. switch (_type) {
  1862. case napi_int8_array:
  1863. case napi_uint8_array:
  1864. case napi_uint8_clamped_array:
  1865. return 1;
  1866. case napi_int16_array:
  1867. case napi_uint16_array:
  1868. return 2;
  1869. case napi_int32_array:
  1870. case napi_uint32_array:
  1871. case napi_float32_array:
  1872. return 4;
  1873. case napi_float64_array:
  1874. #if (NAPI_VERSION > 5)
  1875. case napi_bigint64_array:
  1876. case napi_biguint64_array:
  1877. #endif // (NAPI_VERSION > 5)
  1878. return 8;
  1879. default:
  1880. return 0;
  1881. }
  1882. }
  1883. inline size_t TypedArray::ElementLength() const {
  1884. return _length;
  1885. }
  1886. inline size_t TypedArray::ByteOffset() const {
  1887. size_t byteOffset;
  1888. napi_status status = napi_get_typedarray_info(
  1889. _env, _value, nullptr, nullptr, nullptr, nullptr, &byteOffset);
  1890. NAPI_THROW_IF_FAILED(_env, status, 0);
  1891. return byteOffset;
  1892. }
  1893. inline size_t TypedArray::ByteLength() const {
  1894. return ElementSize() * ElementLength();
  1895. }
  1896. inline Napi::ArrayBuffer TypedArray::ArrayBuffer() const {
  1897. napi_value arrayBuffer;
  1898. napi_status status = napi_get_typedarray_info(
  1899. _env, _value, nullptr, nullptr, nullptr, &arrayBuffer, nullptr);
  1900. NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
  1901. return Napi::ArrayBuffer(_env, arrayBuffer);
  1902. }
  1903. ////////////////////////////////////////////////////////////////////////////////
  1904. // TypedArrayOf<T> class
  1905. ////////////////////////////////////////////////////////////////////////////////
  1906. template <typename T>
  1907. inline void TypedArrayOf<T>::CheckCast(napi_env env, napi_value value) {
  1908. TypedArray::CheckCast(env, value);
  1909. napi_typedarray_type type;
  1910. napi_status status = napi_get_typedarray_info(
  1911. env, value, &type, nullptr, nullptr, nullptr, nullptr);
  1912. NAPI_CHECK(status == napi_ok,
  1913. "TypedArrayOf::CheckCast",
  1914. "napi_is_typedarray failed");
  1915. NAPI_CHECK(
  1916. (type == TypedArrayTypeForPrimitiveType<T>() ||
  1917. (type == napi_uint8_clamped_array && std::is_same<T, uint8_t>::value)),
  1918. "TypedArrayOf::CheckCast",
  1919. "Array type must match the template parameter. (Uint8 arrays may "
  1920. "optionally have the \"clamped\" array type.)");
  1921. }
  1922. template <typename T>
  1923. inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
  1924. size_t elementLength,
  1925. napi_typedarray_type type) {
  1926. Napi::ArrayBuffer arrayBuffer =
  1927. Napi::ArrayBuffer::New(env, elementLength * sizeof(T));
  1928. return New(env, elementLength, arrayBuffer, 0, type);
  1929. }
  1930. template <typename T>
  1931. inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
  1932. size_t elementLength,
  1933. Napi::ArrayBuffer arrayBuffer,
  1934. size_t bufferOffset,
  1935. napi_typedarray_type type) {
  1936. napi_value value;
  1937. napi_status status = napi_create_typedarray(
  1938. env, type, elementLength, arrayBuffer, bufferOffset, &value);
  1939. NAPI_THROW_IF_FAILED(env, status, TypedArrayOf<T>());
  1940. return TypedArrayOf<T>(
  1941. env,
  1942. value,
  1943. type,
  1944. elementLength,
  1945. reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(arrayBuffer.Data()) +
  1946. bufferOffset));
  1947. }
  1948. template <typename T>
  1949. inline TypedArrayOf<T>::TypedArrayOf() : TypedArray(), _data(nullptr) {}
  1950. template <typename T>
  1951. inline TypedArrayOf<T>::TypedArrayOf(napi_env env, napi_value value)
  1952. : TypedArray(env, value), _data(nullptr) {
  1953. napi_status status = napi_ok;
  1954. if (value != nullptr) {
  1955. void* data = nullptr;
  1956. status = napi_get_typedarray_info(
  1957. _env, _value, &_type, &_length, &data, nullptr, nullptr);
  1958. _data = static_cast<T*>(data);
  1959. } else {
  1960. _type = TypedArrayTypeForPrimitiveType<T>();
  1961. _length = 0;
  1962. }
  1963. NAPI_THROW_IF_FAILED_VOID(_env, status);
  1964. }
  1965. template <typename T>
  1966. inline TypedArrayOf<T>::TypedArrayOf(napi_env env,
  1967. napi_value value,
  1968. napi_typedarray_type type,
  1969. size_t length,
  1970. T* data)
  1971. : TypedArray(env, value, type, length), _data(data) {
  1972. if (!(type == TypedArrayTypeForPrimitiveType<T>() ||
  1973. (type == napi_uint8_clamped_array &&
  1974. std::is_same<T, uint8_t>::value))) {
  1975. NAPI_THROW_VOID(TypeError::New(
  1976. env,
  1977. "Array type must match the template parameter. "
  1978. "(Uint8 arrays may optionally have the \"clamped\" array type.)"));
  1979. }
  1980. }
  1981. template <typename T>
  1982. inline T& TypedArrayOf<T>::operator[](size_t index) {
  1983. return _data[index];
  1984. }
  1985. template <typename T>
  1986. inline const T& TypedArrayOf<T>::operator[](size_t index) const {
  1987. return _data[index];
  1988. }
  1989. template <typename T>
  1990. inline T* TypedArrayOf<T>::Data() {
  1991. return _data;
  1992. }
  1993. template <typename T>
  1994. inline const T* TypedArrayOf<T>::Data() const {
  1995. return _data;
  1996. }
  1997. ////////////////////////////////////////////////////////////////////////////////
  1998. // Function class
  1999. ////////////////////////////////////////////////////////////////////////////////
  2000. template <typename CbData>
  2001. inline napi_status CreateFunction(napi_env env,
  2002. const char* utf8name,
  2003. napi_callback cb,
  2004. CbData* data,
  2005. napi_value* result) {
  2006. napi_status status =
  2007. napi_create_function(env, utf8name, NAPI_AUTO_LENGTH, cb, data, result);
  2008. if (status == napi_ok) {
  2009. status = Napi::details::AttachData(env, *result, data);
  2010. }
  2011. return status;
  2012. }
  2013. template <Function::VoidCallback cb>
  2014. inline Function Function::New(napi_env env, const char* utf8name, void* data) {
  2015. napi_value result = nullptr;
  2016. napi_status status = napi_create_function(env,
  2017. utf8name,
  2018. NAPI_AUTO_LENGTH,
  2019. details::TemplatedVoidCallback<cb>,
  2020. data,
  2021. &result);
  2022. NAPI_THROW_IF_FAILED(env, status, Function());
  2023. return Function(env, result);
  2024. }
  2025. template <Function::Callback cb>
  2026. inline Function Function::New(napi_env env, const char* utf8name, void* data) {
  2027. napi_value result = nullptr;
  2028. napi_status status = napi_create_function(env,
  2029. utf8name,
  2030. NAPI_AUTO_LENGTH,
  2031. details::TemplatedCallback<cb>,
  2032. data,
  2033. &result);
  2034. NAPI_THROW_IF_FAILED(env, status, Function());
  2035. return Function(env, result);
  2036. }
  2037. template <Function::VoidCallback cb>
  2038. inline Function Function::New(napi_env env,
  2039. const std::string& utf8name,
  2040. void* data) {
  2041. return Function::New<cb>(env, utf8name.c_str(), data);
  2042. }
  2043. template <Function::Callback cb>
  2044. inline Function Function::New(napi_env env,
  2045. const std::string& utf8name,
  2046. void* data) {
  2047. return Function::New<cb>(env, utf8name.c_str(), data);
  2048. }
  2049. template <typename Callable>
  2050. inline Function Function::New(napi_env env,
  2051. Callable cb,
  2052. const char* utf8name,
  2053. void* data) {
  2054. using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr)));
  2055. using CbData = details::CallbackData<Callable, ReturnType>;
  2056. auto callbackData = new CbData{std::move(cb), data};
  2057. napi_value value;
  2058. napi_status status =
  2059. CreateFunction(env, utf8name, CbData::Wrapper, callbackData, &value);
  2060. if (status != napi_ok) {
  2061. delete callbackData;
  2062. NAPI_THROW_IF_FAILED(env, status, Function());
  2063. }
  2064. return Function(env, value);
  2065. }
  2066. template <typename Callable>
  2067. inline Function Function::New(napi_env env,
  2068. Callable cb,
  2069. const std::string& utf8name,
  2070. void* data) {
  2071. return New(env, cb, utf8name.c_str(), data);
  2072. }
  2073. inline void Function::CheckCast(napi_env env, napi_value value) {
  2074. NAPI_CHECK(value != nullptr, "Function::CheckCast", "empty value");
  2075. napi_valuetype type;
  2076. napi_status status = napi_typeof(env, value, &type);
  2077. NAPI_CHECK(status == napi_ok, "Function::CheckCast", "napi_typeof failed");
  2078. NAPI_CHECK(type == napi_function,
  2079. "Function::CheckCast",
  2080. "value is not napi_function");
  2081. }
  2082. inline Function::Function() : Object() {}
  2083. inline Function::Function(napi_env env, napi_value value)
  2084. : Object(env, value) {}
  2085. inline MaybeOrValue<Value> Function::operator()(
  2086. const std::initializer_list<napi_value>& args) const {
  2087. return Call(Env().Undefined(), args);
  2088. }
  2089. inline MaybeOrValue<Value> Function::Call(
  2090. const std::initializer_list<napi_value>& args) const {
  2091. return Call(Env().Undefined(), args);
  2092. }
  2093. inline MaybeOrValue<Value> Function::Call(
  2094. const std::vector<napi_value>& args) const {
  2095. return Call(Env().Undefined(), args);
  2096. }
  2097. inline MaybeOrValue<Value> Function::Call(
  2098. const std::vector<Value>& args) const {
  2099. return Call(Env().Undefined(), args);
  2100. }
  2101. inline MaybeOrValue<Value> Function::Call(size_t argc,
  2102. const napi_value* args) const {
  2103. return Call(Env().Undefined(), argc, args);
  2104. }
  2105. inline MaybeOrValue<Value> Function::Call(
  2106. napi_value recv, const std::initializer_list<napi_value>& args) const {
  2107. return Call(recv, args.size(), args.begin());
  2108. }
  2109. inline MaybeOrValue<Value> Function::Call(
  2110. napi_value recv, const std::vector<napi_value>& args) const {
  2111. return Call(recv, args.size(), args.data());
  2112. }
  2113. inline MaybeOrValue<Value> Function::Call(
  2114. napi_value recv, const std::vector<Value>& args) const {
  2115. const size_t argc = args.size();
  2116. const size_t stackArgsCount = 6;
  2117. napi_value stackArgs[stackArgsCount];
  2118. std::vector<napi_value> heapArgs;
  2119. napi_value* argv;
  2120. if (argc <= stackArgsCount) {
  2121. argv = stackArgs;
  2122. } else {
  2123. heapArgs.resize(argc);
  2124. argv = heapArgs.data();
  2125. }
  2126. for (size_t index = 0; index < argc; index++) {
  2127. argv[index] = static_cast<napi_value>(args[index]);
  2128. }
  2129. return Call(recv, argc, argv);
  2130. }
  2131. inline MaybeOrValue<Value> Function::Call(napi_value recv,
  2132. size_t argc,
  2133. const napi_value* args) const {
  2134. napi_value result;
  2135. napi_status status =
  2136. napi_call_function(_env, recv, _value, argc, args, &result);
  2137. NAPI_RETURN_OR_THROW_IF_FAILED(
  2138. _env, status, Napi::Value(_env, result), Napi::Value);
  2139. }
  2140. inline MaybeOrValue<Value> Function::MakeCallback(
  2141. napi_value recv,
  2142. const std::initializer_list<napi_value>& args,
  2143. napi_async_context context) const {
  2144. return MakeCallback(recv, args.size(), args.begin(), context);
  2145. }
  2146. inline MaybeOrValue<Value> Function::MakeCallback(
  2147. napi_value recv,
  2148. const std::vector<napi_value>& args,
  2149. napi_async_context context) const {
  2150. return MakeCallback(recv, args.size(), args.data(), context);
  2151. }
  2152. inline MaybeOrValue<Value> Function::MakeCallback(
  2153. napi_value recv,
  2154. size_t argc,
  2155. const napi_value* args,
  2156. napi_async_context context) const {
  2157. napi_value result;
  2158. napi_status status =
  2159. napi_make_callback(_env, context, recv, _value, argc, args, &result);
  2160. NAPI_RETURN_OR_THROW_IF_FAILED(
  2161. _env, status, Napi::Value(_env, result), Napi::Value);
  2162. }
  2163. inline MaybeOrValue<Object> Function::New(
  2164. const std::initializer_list<napi_value>& args) const {
  2165. return New(args.size(), args.begin());
  2166. }
  2167. inline MaybeOrValue<Object> Function::New(
  2168. const std::vector<napi_value>& args) const {
  2169. return New(args.size(), args.data());
  2170. }
  2171. inline MaybeOrValue<Object> Function::New(size_t argc,
  2172. const napi_value* args) const {
  2173. napi_value result;
  2174. napi_status status = napi_new_instance(_env, _value, argc, args, &result);
  2175. NAPI_RETURN_OR_THROW_IF_FAILED(
  2176. _env, status, Napi::Object(_env, result), Napi::Object);
  2177. }
  2178. ////////////////////////////////////////////////////////////////////////////////
  2179. // Promise class
  2180. ////////////////////////////////////////////////////////////////////////////////
  2181. inline Promise::Deferred Promise::Deferred::New(napi_env env) {
  2182. return Promise::Deferred(env);
  2183. }
  2184. inline Promise::Deferred::Deferred(napi_env env) : _env(env) {
  2185. napi_status status = napi_create_promise(_env, &_deferred, &_promise);
  2186. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2187. }
  2188. inline Promise Promise::Deferred::Promise() const {
  2189. return Napi::Promise(_env, _promise);
  2190. }
  2191. inline Napi::Env Promise::Deferred::Env() const {
  2192. return Napi::Env(_env);
  2193. }
  2194. inline void Promise::Deferred::Resolve(napi_value value) const {
  2195. napi_status status = napi_resolve_deferred(_env, _deferred, value);
  2196. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2197. }
  2198. inline void Promise::Deferred::Reject(napi_value value) const {
  2199. napi_status status = napi_reject_deferred(_env, _deferred, value);
  2200. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2201. }
  2202. inline void Promise::CheckCast(napi_env env, napi_value value) {
  2203. NAPI_CHECK(value != nullptr, "Promise::CheckCast", "empty value");
  2204. bool result;
  2205. napi_status status = napi_is_promise(env, value, &result);
  2206. NAPI_CHECK(status == napi_ok, "Promise::CheckCast", "napi_is_promise failed");
  2207. NAPI_CHECK(result, "Promise::CheckCast", "value is not promise");
  2208. }
  2209. inline Promise::Promise(napi_env env, napi_value value) : Object(env, value) {}
  2210. ////////////////////////////////////////////////////////////////////////////////
  2211. // Buffer<T> class
  2212. ////////////////////////////////////////////////////////////////////////////////
  2213. template <typename T>
  2214. inline Buffer<T> Buffer<T>::New(napi_env env, size_t length) {
  2215. napi_value value;
  2216. void* data;
  2217. napi_status status =
  2218. napi_create_buffer(env, length * sizeof(T), &data, &value);
  2219. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  2220. return Buffer(env, value);
  2221. }
  2222. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2223. template <typename T>
  2224. inline Buffer<T> Buffer<T>::New(napi_env env, T* data, size_t length) {
  2225. napi_value value;
  2226. napi_status status = napi_create_external_buffer(
  2227. env, length * sizeof(T), data, nullptr, nullptr, &value);
  2228. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  2229. return Buffer(env, value);
  2230. }
  2231. template <typename T>
  2232. template <typename Finalizer>
  2233. inline Buffer<T> Buffer<T>::New(napi_env env,
  2234. T* data,
  2235. size_t length,
  2236. Finalizer finalizeCallback) {
  2237. napi_value value;
  2238. details::FinalizeData<T, Finalizer>* finalizeData =
  2239. new details::FinalizeData<T, Finalizer>(
  2240. {std::move(finalizeCallback), nullptr});
  2241. napi_status status =
  2242. napi_create_external_buffer(env,
  2243. length * sizeof(T),
  2244. data,
  2245. details::FinalizeData<T, Finalizer>::Wrapper,
  2246. finalizeData,
  2247. &value);
  2248. if (status != napi_ok) {
  2249. delete finalizeData;
  2250. NAPI_THROW_IF_FAILED(env, status, Buffer());
  2251. }
  2252. return Buffer(env, value);
  2253. }
  2254. template <typename T>
  2255. template <typename Finalizer, typename Hint>
  2256. inline Buffer<T> Buffer<T>::New(napi_env env,
  2257. T* data,
  2258. size_t length,
  2259. Finalizer finalizeCallback,
  2260. Hint* finalizeHint) {
  2261. napi_value value;
  2262. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  2263. new details::FinalizeData<T, Finalizer, Hint>(
  2264. {std::move(finalizeCallback), finalizeHint});
  2265. napi_status status = napi_create_external_buffer(
  2266. env,
  2267. length * sizeof(T),
  2268. data,
  2269. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
  2270. finalizeData,
  2271. &value);
  2272. if (status != napi_ok) {
  2273. delete finalizeData;
  2274. NAPI_THROW_IF_FAILED(env, status, Buffer());
  2275. }
  2276. return Buffer(env, value);
  2277. }
  2278. #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2279. template <typename T>
  2280. inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env, T* data, size_t length) {
  2281. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2282. napi_value value;
  2283. napi_status status = napi_create_external_buffer(
  2284. env, length * sizeof(T), data, nullptr, nullptr, &value);
  2285. if (status == details::napi_no_external_buffers_allowed) {
  2286. #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2287. // If we can't create an external buffer, we'll just copy the data.
  2288. return Buffer<T>::Copy(env, data, length);
  2289. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2290. }
  2291. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  2292. return Buffer(env, value);
  2293. #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2294. }
  2295. template <typename T>
  2296. template <typename Finalizer>
  2297. inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
  2298. T* data,
  2299. size_t length,
  2300. Finalizer finalizeCallback) {
  2301. details::FinalizeData<T, Finalizer>* finalizeData =
  2302. new details::FinalizeData<T, Finalizer>(
  2303. {std::move(finalizeCallback), nullptr});
  2304. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2305. napi_value value;
  2306. napi_status status =
  2307. napi_create_external_buffer(env,
  2308. length * sizeof(T),
  2309. data,
  2310. details::FinalizeData<T, Finalizer>::Wrapper,
  2311. finalizeData,
  2312. &value);
  2313. if (status == details::napi_no_external_buffers_allowed) {
  2314. #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2315. // If we can't create an external buffer, we'll just copy the data.
  2316. Buffer<T> ret = Buffer<T>::Copy(env, data, length);
  2317. details::FinalizeData<T, Finalizer>::Wrapper(env, data, finalizeData);
  2318. return ret;
  2319. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2320. }
  2321. if (status != napi_ok) {
  2322. delete finalizeData;
  2323. NAPI_THROW_IF_FAILED(env, status, Buffer());
  2324. }
  2325. return Buffer(env, value);
  2326. #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2327. }
  2328. template <typename T>
  2329. template <typename Finalizer, typename Hint>
  2330. inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
  2331. T* data,
  2332. size_t length,
  2333. Finalizer finalizeCallback,
  2334. Hint* finalizeHint) {
  2335. details::FinalizeData<T, Finalizer, Hint>* finalizeData =
  2336. new details::FinalizeData<T, Finalizer, Hint>(
  2337. {std::move(finalizeCallback), finalizeHint});
  2338. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2339. napi_value value;
  2340. napi_status status = napi_create_external_buffer(
  2341. env,
  2342. length * sizeof(T),
  2343. data,
  2344. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
  2345. finalizeData,
  2346. &value);
  2347. if (status == details::napi_no_external_buffers_allowed) {
  2348. #endif
  2349. // If we can't create an external buffer, we'll just copy the data.
  2350. Buffer<T> ret = Buffer<T>::Copy(env, data, length);
  2351. details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint(
  2352. env, data, finalizeData);
  2353. return ret;
  2354. #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
  2355. }
  2356. if (status != napi_ok) {
  2357. delete finalizeData;
  2358. NAPI_THROW_IF_FAILED(env, status, Buffer());
  2359. }
  2360. return Buffer(env, value);
  2361. #endif
  2362. }
  2363. template <typename T>
  2364. inline Buffer<T> Buffer<T>::Copy(napi_env env, const T* data, size_t length) {
  2365. napi_value value;
  2366. napi_status status =
  2367. napi_create_buffer_copy(env, length * sizeof(T), data, nullptr, &value);
  2368. NAPI_THROW_IF_FAILED(env, status, Buffer<T>());
  2369. return Buffer<T>(env, value);
  2370. }
  2371. template <typename T>
  2372. inline void Buffer<T>::CheckCast(napi_env env, napi_value value) {
  2373. NAPI_CHECK(value != nullptr, "Buffer::CheckCast", "empty value");
  2374. bool result;
  2375. napi_status status = napi_is_buffer(env, value, &result);
  2376. NAPI_CHECK(status == napi_ok, "Buffer::CheckCast", "napi_is_buffer failed");
  2377. NAPI_CHECK(result, "Buffer::CheckCast", "value is not buffer");
  2378. }
  2379. template <typename T>
  2380. inline Buffer<T>::Buffer() : Uint8Array() {}
  2381. template <typename T>
  2382. inline Buffer<T>::Buffer(napi_env env, napi_value value)
  2383. : Uint8Array(env, value) {}
  2384. template <typename T>
  2385. inline size_t Buffer<T>::Length() const {
  2386. return ByteLength() / sizeof(T);
  2387. }
  2388. template <typename T>
  2389. inline T* Buffer<T>::Data() const {
  2390. return reinterpret_cast<T*>(const_cast<uint8_t*>(Uint8Array::Data()));
  2391. }
  2392. ////////////////////////////////////////////////////////////////////////////////
  2393. // Error class
  2394. ////////////////////////////////////////////////////////////////////////////////
  2395. inline Error Error::New(napi_env env) {
  2396. napi_status status;
  2397. napi_value error = nullptr;
  2398. bool is_exception_pending;
  2399. napi_extended_error_info last_error_info_copy;
  2400. {
  2401. // We must retrieve the last error info before doing anything else because
  2402. // doing anything else will replace the last error info.
  2403. const napi_extended_error_info* last_error_info;
  2404. status = napi_get_last_error_info(env, &last_error_info);
  2405. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
  2406. // All fields of the `napi_extended_error_info` structure gets reset in
  2407. // subsequent Node-API function calls on the same `env`. This includes a
  2408. // call to `napi_is_exception_pending()`. So here it is necessary to make a
  2409. // copy of the information as the `error_code` field is used later on.
  2410. memcpy(&last_error_info_copy,
  2411. last_error_info,
  2412. sizeof(napi_extended_error_info));
  2413. }
  2414. status = napi_is_exception_pending(env, &is_exception_pending);
  2415. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
  2416. // A pending exception takes precedence over any internal error status.
  2417. if (is_exception_pending) {
  2418. status = napi_get_and_clear_last_exception(env, &error);
  2419. NAPI_FATAL_IF_FAILED(
  2420. status, "Error::New", "napi_get_and_clear_last_exception");
  2421. } else {
  2422. const char* error_message = last_error_info_copy.error_message != nullptr
  2423. ? last_error_info_copy.error_message
  2424. : "Error in native callback";
  2425. napi_value message;
  2426. status = napi_create_string_utf8(
  2427. env, error_message, std::strlen(error_message), &message);
  2428. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
  2429. switch (last_error_info_copy.error_code) {
  2430. case napi_object_expected:
  2431. case napi_string_expected:
  2432. case napi_boolean_expected:
  2433. case napi_number_expected:
  2434. status = napi_create_type_error(env, nullptr, message, &error);
  2435. break;
  2436. default:
  2437. status = napi_create_error(env, nullptr, message, &error);
  2438. break;
  2439. }
  2440. NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
  2441. }
  2442. return Error(env, error);
  2443. }
  2444. inline Error Error::New(napi_env env, const char* message) {
  2445. return Error::New<Error>(
  2446. env, message, std::strlen(message), napi_create_error);
  2447. }
  2448. inline Error Error::New(napi_env env, const std::string& message) {
  2449. return Error::New<Error>(
  2450. env, message.c_str(), message.size(), napi_create_error);
  2451. }
  2452. inline NAPI_NO_RETURN void Error::Fatal(const char* location,
  2453. const char* message) {
  2454. napi_fatal_error(location, NAPI_AUTO_LENGTH, message, NAPI_AUTO_LENGTH);
  2455. }
  2456. inline Error::Error() : ObjectReference() {}
  2457. inline Error::Error(napi_env env, napi_value value)
  2458. : ObjectReference(env, nullptr) {
  2459. if (value != nullptr) {
  2460. // Attempting to create a reference on the error object.
  2461. // If it's not a Object/Function/Symbol, this call will return an error
  2462. // status.
  2463. napi_status status = napi_create_reference(env, value, 1, &_ref);
  2464. if (status != napi_ok) {
  2465. napi_value wrappedErrorObj;
  2466. // Create an error object
  2467. status = napi_create_object(env, &wrappedErrorObj);
  2468. NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_object");
  2469. // property flag that we attach to show the error object is wrapped
  2470. napi_property_descriptor wrapObjFlag = {
  2471. ERROR_WRAP_VALUE(), // Unique GUID identifier since Symbol isn't a
  2472. // viable option
  2473. nullptr,
  2474. nullptr,
  2475. nullptr,
  2476. nullptr,
  2477. Value::From(env, value),
  2478. napi_enumerable,
  2479. nullptr};
  2480. status = napi_define_properties(env, wrappedErrorObj, 1, &wrapObjFlag);
  2481. #ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
  2482. if (status == napi_pending_exception) {
  2483. // Test if the pending exception was reported because the environment is
  2484. // shutting down. We assume that a status of napi_pending_exception
  2485. // coupled with the absence of an actual pending exception means that
  2486. // the environment is shutting down. If so, we replace the
  2487. // napi_pending_exception status with napi_ok.
  2488. bool is_exception_pending = false;
  2489. status = napi_is_exception_pending(env, &is_exception_pending);
  2490. if (status == napi_ok && !is_exception_pending) {
  2491. status = napi_ok;
  2492. } else {
  2493. status = napi_pending_exception;
  2494. }
  2495. }
  2496. #endif // NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
  2497. NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_define_properties");
  2498. // Create a reference on the newly wrapped object
  2499. status = napi_create_reference(env, wrappedErrorObj, 1, &_ref);
  2500. }
  2501. // Avoid infinite recursion in the failure case.
  2502. NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_reference");
  2503. }
  2504. }
  2505. inline Object Error::Value() const {
  2506. if (_ref == nullptr) {
  2507. return Object(_env, nullptr);
  2508. }
  2509. napi_value refValue;
  2510. napi_status status = napi_get_reference_value(_env, _ref, &refValue);
  2511. NAPI_THROW_IF_FAILED(_env, status, Object());
  2512. napi_valuetype type;
  2513. status = napi_typeof(_env, refValue, &type);
  2514. NAPI_THROW_IF_FAILED(_env, status, Object());
  2515. // If refValue isn't a symbol, then we proceed to whether the refValue has the
  2516. // wrapped error flag
  2517. if (type != napi_symbol) {
  2518. // We are checking if the object is wrapped
  2519. bool isWrappedObject = false;
  2520. status = napi_has_property(_env,
  2521. refValue,
  2522. String::From(_env, ERROR_WRAP_VALUE()),
  2523. &isWrappedObject);
  2524. // Don't care about status
  2525. if (isWrappedObject) {
  2526. napi_value unwrappedValue;
  2527. status = napi_get_property(_env,
  2528. refValue,
  2529. String::From(_env, ERROR_WRAP_VALUE()),
  2530. &unwrappedValue);
  2531. NAPI_THROW_IF_FAILED(_env, status, Object());
  2532. return Object(_env, unwrappedValue);
  2533. }
  2534. }
  2535. return Object(_env, refValue);
  2536. }
  2537. inline Error::Error(Error&& other) : ObjectReference(std::move(other)) {}
  2538. inline Error& Error::operator=(Error&& other) {
  2539. static_cast<Reference<Object>*>(this)->operator=(std::move(other));
  2540. return *this;
  2541. }
  2542. inline Error::Error(const Error& other) : ObjectReference(other) {}
  2543. inline Error& Error::operator=(const Error& other) {
  2544. Reset();
  2545. _env = other.Env();
  2546. HandleScope scope(_env);
  2547. napi_value value = other.Value();
  2548. if (value != nullptr) {
  2549. napi_status status = napi_create_reference(_env, value, 1, &_ref);
  2550. NAPI_THROW_IF_FAILED(_env, status, *this);
  2551. }
  2552. return *this;
  2553. }
  2554. inline const std::string& Error::Message() const NAPI_NOEXCEPT {
  2555. if (_message.size() == 0 && _env != nullptr) {
  2556. #ifdef NAPI_CPP_EXCEPTIONS
  2557. try {
  2558. _message = Get("message").As<String>();
  2559. } catch (...) {
  2560. // Catch all errors here, to include e.g. a std::bad_alloc from
  2561. // the std::string::operator=, because this method may not throw.
  2562. }
  2563. #else // NAPI_CPP_EXCEPTIONS
  2564. #if defined(NODE_ADDON_API_ENABLE_MAYBE)
  2565. Napi::Value message_val;
  2566. if (Get("message").UnwrapTo(&message_val)) {
  2567. _message = message_val.As<String>();
  2568. }
  2569. #else
  2570. _message = Get("message").As<String>();
  2571. #endif
  2572. #endif // NAPI_CPP_EXCEPTIONS
  2573. }
  2574. return _message;
  2575. }
  2576. // we created an object on the &_ref
  2577. inline void Error::ThrowAsJavaScriptException() const {
  2578. HandleScope scope(_env);
  2579. if (!IsEmpty()) {
  2580. #ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
  2581. bool pendingException = false;
  2582. // check if there is already a pending exception. If so don't try to throw a
  2583. // new one as that is not allowed/possible
  2584. napi_status status = napi_is_exception_pending(_env, &pendingException);
  2585. if ((status != napi_ok) ||
  2586. ((status == napi_ok) && (pendingException == false))) {
  2587. // We intentionally don't use `NAPI_THROW_*` macros here to ensure
  2588. // that there is no possible recursion as `ThrowAsJavaScriptException`
  2589. // is part of `NAPI_THROW_*` macro definition for noexcept.
  2590. status = napi_throw(_env, Value());
  2591. if (status == napi_pending_exception) {
  2592. // The environment must be terminating as we checked earlier and there
  2593. // was no pending exception. In this case continuing will result
  2594. // in a fatal error and there is nothing the author has done incorrectly
  2595. // in their code that is worth flagging through a fatal error
  2596. return;
  2597. }
  2598. } else {
  2599. status = napi_pending_exception;
  2600. }
  2601. #else
  2602. // We intentionally don't use `NAPI_THROW_*` macros here to ensure
  2603. // that there is no possible recursion as `ThrowAsJavaScriptException`
  2604. // is part of `NAPI_THROW_*` macro definition for noexcept.
  2605. napi_status status = napi_throw(_env, Value());
  2606. #endif
  2607. #ifdef NAPI_CPP_EXCEPTIONS
  2608. if (status != napi_ok) {
  2609. throw Error::New(_env);
  2610. }
  2611. #else // NAPI_CPP_EXCEPTIONS
  2612. NAPI_FATAL_IF_FAILED(
  2613. status, "Error::ThrowAsJavaScriptException", "napi_throw");
  2614. #endif // NAPI_CPP_EXCEPTIONS
  2615. }
  2616. }
  2617. #ifdef NAPI_CPP_EXCEPTIONS
  2618. inline const char* Error::what() const NAPI_NOEXCEPT {
  2619. return Message().c_str();
  2620. }
  2621. #endif // NAPI_CPP_EXCEPTIONS
  2622. inline const char* Error::ERROR_WRAP_VALUE() NAPI_NOEXCEPT {
  2623. return "4bda9e7e-4913-4dbc-95de-891cbf66598e-errorVal";
  2624. }
  2625. template <typename TError>
  2626. inline TError Error::New(napi_env env,
  2627. const char* message,
  2628. size_t length,
  2629. create_error_fn create_error) {
  2630. napi_value str;
  2631. napi_status status = napi_create_string_utf8(env, message, length, &str);
  2632. NAPI_THROW_IF_FAILED(env, status, TError());
  2633. napi_value error;
  2634. status = create_error(env, nullptr, str, &error);
  2635. NAPI_THROW_IF_FAILED(env, status, TError());
  2636. return TError(env, error);
  2637. }
  2638. inline TypeError TypeError::New(napi_env env, const char* message) {
  2639. return Error::New<TypeError>(
  2640. env, message, std::strlen(message), napi_create_type_error);
  2641. }
  2642. inline TypeError TypeError::New(napi_env env, const std::string& message) {
  2643. return Error::New<TypeError>(
  2644. env, message.c_str(), message.size(), napi_create_type_error);
  2645. }
  2646. inline TypeError::TypeError() : Error() {}
  2647. inline TypeError::TypeError(napi_env env, napi_value value)
  2648. : Error(env, value) {}
  2649. inline RangeError RangeError::New(napi_env env, const char* message) {
  2650. return Error::New<RangeError>(
  2651. env, message, std::strlen(message), napi_create_range_error);
  2652. }
  2653. inline RangeError RangeError::New(napi_env env, const std::string& message) {
  2654. return Error::New<RangeError>(
  2655. env, message.c_str(), message.size(), napi_create_range_error);
  2656. }
  2657. inline RangeError::RangeError() : Error() {}
  2658. inline RangeError::RangeError(napi_env env, napi_value value)
  2659. : Error(env, value) {}
  2660. #if NAPI_VERSION > 8
  2661. inline SyntaxError SyntaxError::New(napi_env env, const char* message) {
  2662. return Error::New<SyntaxError>(
  2663. env, message, std::strlen(message), node_api_create_syntax_error);
  2664. }
  2665. inline SyntaxError SyntaxError::New(napi_env env, const std::string& message) {
  2666. return Error::New<SyntaxError>(
  2667. env, message.c_str(), message.size(), node_api_create_syntax_error);
  2668. }
  2669. inline SyntaxError::SyntaxError() : Error() {}
  2670. inline SyntaxError::SyntaxError(napi_env env, napi_value value)
  2671. : Error(env, value) {}
  2672. #endif // NAPI_VERSION > 8
  2673. ////////////////////////////////////////////////////////////////////////////////
  2674. // Reference<T> class
  2675. ////////////////////////////////////////////////////////////////////////////////
  2676. template <typename T>
  2677. inline Reference<T> Reference<T>::New(const T& value,
  2678. uint32_t initialRefcount) {
  2679. napi_env env = value.Env();
  2680. napi_value val = value;
  2681. if (val == nullptr) {
  2682. return Reference<T>(env, nullptr);
  2683. }
  2684. napi_ref ref;
  2685. napi_status status = napi_create_reference(env, value, initialRefcount, &ref);
  2686. NAPI_THROW_IF_FAILED(env, status, Reference<T>());
  2687. return Reference<T>(env, ref);
  2688. }
  2689. template <typename T>
  2690. inline Reference<T>::Reference()
  2691. : _env(nullptr), _ref(nullptr), _suppressDestruct(false) {}
  2692. template <typename T>
  2693. inline Reference<T>::Reference(napi_env env, napi_ref ref)
  2694. : _env(env), _ref(ref), _suppressDestruct(false) {}
  2695. template <typename T>
  2696. inline Reference<T>::~Reference() {
  2697. if (_ref != nullptr) {
  2698. if (!_suppressDestruct) {
  2699. napi_delete_reference(_env, _ref);
  2700. }
  2701. _ref = nullptr;
  2702. }
  2703. }
  2704. template <typename T>
  2705. inline Reference<T>::Reference(Reference<T>&& other)
  2706. : _env(other._env),
  2707. _ref(other._ref),
  2708. _suppressDestruct(other._suppressDestruct) {
  2709. other._env = nullptr;
  2710. other._ref = nullptr;
  2711. other._suppressDestruct = false;
  2712. }
  2713. template <typename T>
  2714. inline Reference<T>& Reference<T>::operator=(Reference<T>&& other) {
  2715. Reset();
  2716. _env = other._env;
  2717. _ref = other._ref;
  2718. _suppressDestruct = other._suppressDestruct;
  2719. other._env = nullptr;
  2720. other._ref = nullptr;
  2721. other._suppressDestruct = false;
  2722. return *this;
  2723. }
  2724. template <typename T>
  2725. inline Reference<T>::Reference(const Reference<T>& other)
  2726. : _env(other._env), _ref(nullptr), _suppressDestruct(false) {
  2727. HandleScope scope(_env);
  2728. napi_value value = other.Value();
  2729. if (value != nullptr) {
  2730. // Copying is a limited scenario (currently only used for Error object) and
  2731. // always creates a strong reference to the given value even if the incoming
  2732. // reference is weak.
  2733. napi_status status = napi_create_reference(_env, value, 1, &_ref);
  2734. NAPI_FATAL_IF_FAILED(
  2735. status, "Reference<T>::Reference", "napi_create_reference");
  2736. }
  2737. }
  2738. template <typename T>
  2739. inline Reference<T>::operator napi_ref() const {
  2740. return _ref;
  2741. }
  2742. template <typename T>
  2743. inline bool Reference<T>::operator==(const Reference<T>& other) const {
  2744. HandleScope scope(_env);
  2745. return this->Value().StrictEquals(other.Value());
  2746. }
  2747. template <typename T>
  2748. inline bool Reference<T>::operator!=(const Reference<T>& other) const {
  2749. return !this->operator==(other);
  2750. }
  2751. template <typename T>
  2752. inline Napi::Env Reference<T>::Env() const {
  2753. return Napi::Env(_env);
  2754. }
  2755. template <typename T>
  2756. inline bool Reference<T>::IsEmpty() const {
  2757. return _ref == nullptr;
  2758. }
  2759. template <typename T>
  2760. inline T Reference<T>::Value() const {
  2761. if (_ref == nullptr) {
  2762. return T(_env, nullptr);
  2763. }
  2764. napi_value value;
  2765. napi_status status = napi_get_reference_value(_env, _ref, &value);
  2766. NAPI_THROW_IF_FAILED(_env, status, T());
  2767. return T(_env, value);
  2768. }
  2769. template <typename T>
  2770. inline uint32_t Reference<T>::Ref() const {
  2771. uint32_t result;
  2772. napi_status status = napi_reference_ref(_env, _ref, &result);
  2773. NAPI_THROW_IF_FAILED(_env, status, 0);
  2774. return result;
  2775. }
  2776. template <typename T>
  2777. inline uint32_t Reference<T>::Unref() const {
  2778. uint32_t result;
  2779. napi_status status = napi_reference_unref(_env, _ref, &result);
  2780. NAPI_THROW_IF_FAILED(_env, status, 0);
  2781. return result;
  2782. }
  2783. template <typename T>
  2784. inline void Reference<T>::Reset() {
  2785. if (_ref != nullptr) {
  2786. napi_status status = napi_delete_reference(_env, _ref);
  2787. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2788. _ref = nullptr;
  2789. }
  2790. }
  2791. template <typename T>
  2792. inline void Reference<T>::Reset(const T& value, uint32_t refcount) {
  2793. Reset();
  2794. _env = value.Env();
  2795. napi_value val = value;
  2796. if (val != nullptr) {
  2797. napi_status status = napi_create_reference(_env, value, refcount, &_ref);
  2798. NAPI_THROW_IF_FAILED_VOID(_env, status);
  2799. }
  2800. }
  2801. template <typename T>
  2802. inline void Reference<T>::SuppressDestruct() {
  2803. _suppressDestruct = true;
  2804. }
  2805. template <typename T>
  2806. inline Reference<T> Weak(T value) {
  2807. return Reference<T>::New(value, 0);
  2808. }
  2809. inline ObjectReference Weak(Object value) {
  2810. return Reference<Object>::New(value, 0);
  2811. }
  2812. inline FunctionReference Weak(Function value) {
  2813. return Reference<Function>::New(value, 0);
  2814. }
  2815. template <typename T>
  2816. inline Reference<T> Persistent(T value) {
  2817. return Reference<T>::New(value, 1);
  2818. }
  2819. inline ObjectReference Persistent(Object value) {
  2820. return Reference<Object>::New(value, 1);
  2821. }
  2822. inline FunctionReference Persistent(Function value) {
  2823. return Reference<Function>::New(value, 1);
  2824. }
  2825. ////////////////////////////////////////////////////////////////////////////////
  2826. // ObjectReference class
  2827. ////////////////////////////////////////////////////////////////////////////////
  2828. inline ObjectReference::ObjectReference() : Reference<Object>() {}
  2829. inline ObjectReference::ObjectReference(napi_env env, napi_ref ref)
  2830. : Reference<Object>(env, ref) {}
  2831. inline ObjectReference::ObjectReference(Reference<Object>&& other)
  2832. : Reference<Object>(std::move(other)) {}
  2833. inline ObjectReference& ObjectReference::operator=(Reference<Object>&& other) {
  2834. static_cast<Reference<Object>*>(this)->operator=(std::move(other));
  2835. return *this;
  2836. }
  2837. inline ObjectReference::ObjectReference(ObjectReference&& other)
  2838. : Reference<Object>(std::move(other)) {}
  2839. inline ObjectReference& ObjectReference::operator=(ObjectReference&& other) {
  2840. static_cast<Reference<Object>*>(this)->operator=(std::move(other));
  2841. return *this;
  2842. }
  2843. inline ObjectReference::ObjectReference(const ObjectReference& other)
  2844. : Reference<Object>(other) {}
  2845. inline MaybeOrValue<Napi::Value> ObjectReference::Get(
  2846. const char* utf8name) const {
  2847. EscapableHandleScope scope(_env);
  2848. MaybeOrValue<Napi::Value> result = Value().Get(utf8name);
  2849. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  2850. if (result.IsJust()) {
  2851. return Just(scope.Escape(result.Unwrap()));
  2852. }
  2853. return result;
  2854. #else
  2855. if (scope.Env().IsExceptionPending()) {
  2856. return Value();
  2857. }
  2858. return scope.Escape(result);
  2859. #endif
  2860. }
  2861. inline MaybeOrValue<Napi::Value> ObjectReference::Get(
  2862. const std::string& utf8name) const {
  2863. EscapableHandleScope scope(_env);
  2864. MaybeOrValue<Napi::Value> result = Value().Get(utf8name);
  2865. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  2866. if (result.IsJust()) {
  2867. return Just(scope.Escape(result.Unwrap()));
  2868. }
  2869. return result;
  2870. #else
  2871. if (scope.Env().IsExceptionPending()) {
  2872. return Value();
  2873. }
  2874. return scope.Escape(result);
  2875. #endif
  2876. }
  2877. inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
  2878. napi_value value) const {
  2879. HandleScope scope(_env);
  2880. return Value().Set(utf8name, value);
  2881. }
  2882. inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
  2883. Napi::Value value) const {
  2884. HandleScope scope(_env);
  2885. return Value().Set(utf8name, value);
  2886. }
  2887. inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
  2888. const char* utf8value) const {
  2889. HandleScope scope(_env);
  2890. return Value().Set(utf8name, utf8value);
  2891. }
  2892. inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
  2893. bool boolValue) const {
  2894. HandleScope scope(_env);
  2895. return Value().Set(utf8name, boolValue);
  2896. }
  2897. inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
  2898. double numberValue) const {
  2899. HandleScope scope(_env);
  2900. return Value().Set(utf8name, numberValue);
  2901. }
  2902. inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
  2903. napi_value value) const {
  2904. HandleScope scope(_env);
  2905. return Value().Set(utf8name, value);
  2906. }
  2907. inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
  2908. Napi::Value value) const {
  2909. HandleScope scope(_env);
  2910. return Value().Set(utf8name, value);
  2911. }
  2912. inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
  2913. std::string& utf8value) const {
  2914. HandleScope scope(_env);
  2915. return Value().Set(utf8name, utf8value);
  2916. }
  2917. inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
  2918. bool boolValue) const {
  2919. HandleScope scope(_env);
  2920. return Value().Set(utf8name, boolValue);
  2921. }
  2922. inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
  2923. double numberValue) const {
  2924. HandleScope scope(_env);
  2925. return Value().Set(utf8name, numberValue);
  2926. }
  2927. inline MaybeOrValue<Napi::Value> ObjectReference::Get(uint32_t index) const {
  2928. EscapableHandleScope scope(_env);
  2929. MaybeOrValue<Napi::Value> result = Value().Get(index);
  2930. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  2931. if (result.IsJust()) {
  2932. return Just(scope.Escape(result.Unwrap()));
  2933. }
  2934. return result;
  2935. #else
  2936. if (scope.Env().IsExceptionPending()) {
  2937. return Value();
  2938. }
  2939. return scope.Escape(result);
  2940. #endif
  2941. }
  2942. inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
  2943. napi_value value) const {
  2944. HandleScope scope(_env);
  2945. return Value().Set(index, value);
  2946. }
  2947. inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
  2948. Napi::Value value) const {
  2949. HandleScope scope(_env);
  2950. return Value().Set(index, value);
  2951. }
  2952. inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
  2953. const char* utf8value) const {
  2954. HandleScope scope(_env);
  2955. return Value().Set(index, utf8value);
  2956. }
  2957. inline MaybeOrValue<bool> ObjectReference::Set(
  2958. uint32_t index, const std::string& utf8value) const {
  2959. HandleScope scope(_env);
  2960. return Value().Set(index, utf8value);
  2961. }
  2962. inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
  2963. bool boolValue) const {
  2964. HandleScope scope(_env);
  2965. return Value().Set(index, boolValue);
  2966. }
  2967. inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
  2968. double numberValue) const {
  2969. HandleScope scope(_env);
  2970. return Value().Set(index, numberValue);
  2971. }
  2972. ////////////////////////////////////////////////////////////////////////////////
  2973. // FunctionReference class
  2974. ////////////////////////////////////////////////////////////////////////////////
  2975. inline FunctionReference::FunctionReference() : Reference<Function>() {}
  2976. inline FunctionReference::FunctionReference(napi_env env, napi_ref ref)
  2977. : Reference<Function>(env, ref) {}
  2978. inline FunctionReference::FunctionReference(Reference<Function>&& other)
  2979. : Reference<Function>(std::move(other)) {}
  2980. inline FunctionReference& FunctionReference::operator=(
  2981. Reference<Function>&& other) {
  2982. static_cast<Reference<Function>*>(this)->operator=(std::move(other));
  2983. return *this;
  2984. }
  2985. inline FunctionReference::FunctionReference(FunctionReference&& other)
  2986. : Reference<Function>(std::move(other)) {}
  2987. inline FunctionReference& FunctionReference::operator=(
  2988. FunctionReference&& other) {
  2989. static_cast<Reference<Function>*>(this)->operator=(std::move(other));
  2990. return *this;
  2991. }
  2992. inline MaybeOrValue<Napi::Value> FunctionReference::operator()(
  2993. const std::initializer_list<napi_value>& args) const {
  2994. EscapableHandleScope scope(_env);
  2995. MaybeOrValue<Napi::Value> result = Value()(args);
  2996. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  2997. if (result.IsJust()) {
  2998. return Just(scope.Escape(result.Unwrap()));
  2999. }
  3000. return result;
  3001. #else
  3002. if (scope.Env().IsExceptionPending()) {
  3003. return Value();
  3004. }
  3005. return scope.Escape(result);
  3006. #endif
  3007. }
  3008. inline MaybeOrValue<Napi::Value> FunctionReference::Call(
  3009. const std::initializer_list<napi_value>& args) const {
  3010. EscapableHandleScope scope(_env);
  3011. MaybeOrValue<Napi::Value> result = Value().Call(args);
  3012. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3013. if (result.IsJust()) {
  3014. return Just(scope.Escape(result.Unwrap()));
  3015. }
  3016. return result;
  3017. #else
  3018. if (scope.Env().IsExceptionPending()) {
  3019. return Value();
  3020. }
  3021. return scope.Escape(result);
  3022. #endif
  3023. }
  3024. inline MaybeOrValue<Napi::Value> FunctionReference::Call(
  3025. const std::vector<napi_value>& args) const {
  3026. EscapableHandleScope scope(_env);
  3027. MaybeOrValue<Napi::Value> result = Value().Call(args);
  3028. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3029. if (result.IsJust()) {
  3030. return Just(scope.Escape(result.Unwrap()));
  3031. }
  3032. return result;
  3033. #else
  3034. if (scope.Env().IsExceptionPending()) {
  3035. return Value();
  3036. }
  3037. return scope.Escape(result);
  3038. #endif
  3039. }
  3040. inline MaybeOrValue<Napi::Value> FunctionReference::Call(
  3041. napi_value recv, const std::initializer_list<napi_value>& args) const {
  3042. EscapableHandleScope scope(_env);
  3043. MaybeOrValue<Napi::Value> result = Value().Call(recv, args);
  3044. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3045. if (result.IsJust()) {
  3046. return Just(scope.Escape(result.Unwrap()));
  3047. }
  3048. return result;
  3049. #else
  3050. if (scope.Env().IsExceptionPending()) {
  3051. return Value();
  3052. }
  3053. return scope.Escape(result);
  3054. #endif
  3055. }
  3056. inline MaybeOrValue<Napi::Value> FunctionReference::Call(
  3057. napi_value recv, const std::vector<napi_value>& args) const {
  3058. EscapableHandleScope scope(_env);
  3059. MaybeOrValue<Napi::Value> result = Value().Call(recv, args);
  3060. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3061. if (result.IsJust()) {
  3062. return Just(scope.Escape(result.Unwrap()));
  3063. }
  3064. return result;
  3065. #else
  3066. if (scope.Env().IsExceptionPending()) {
  3067. return Value();
  3068. }
  3069. return scope.Escape(result);
  3070. #endif
  3071. }
  3072. inline MaybeOrValue<Napi::Value> FunctionReference::Call(
  3073. napi_value recv, size_t argc, const napi_value* args) const {
  3074. EscapableHandleScope scope(_env);
  3075. MaybeOrValue<Napi::Value> result = Value().Call(recv, argc, args);
  3076. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3077. if (result.IsJust()) {
  3078. return Just(scope.Escape(result.Unwrap()));
  3079. }
  3080. return result;
  3081. #else
  3082. if (scope.Env().IsExceptionPending()) {
  3083. return Value();
  3084. }
  3085. return scope.Escape(result);
  3086. #endif
  3087. }
  3088. inline MaybeOrValue<Napi::Value> FunctionReference::MakeCallback(
  3089. napi_value recv,
  3090. const std::initializer_list<napi_value>& args,
  3091. napi_async_context context) const {
  3092. EscapableHandleScope scope(_env);
  3093. MaybeOrValue<Napi::Value> result = Value().MakeCallback(recv, args, context);
  3094. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3095. if (result.IsJust()) {
  3096. return Just(scope.Escape(result.Unwrap()));
  3097. }
  3098. return result;
  3099. #else
  3100. if (scope.Env().IsExceptionPending()) {
  3101. return Value();
  3102. }
  3103. return scope.Escape(result);
  3104. #endif
  3105. }
  3106. inline MaybeOrValue<Napi::Value> FunctionReference::MakeCallback(
  3107. napi_value recv,
  3108. const std::vector<napi_value>& args,
  3109. napi_async_context context) const {
  3110. EscapableHandleScope scope(_env);
  3111. MaybeOrValue<Napi::Value> result = Value().MakeCallback(recv, args, context);
  3112. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3113. if (result.IsJust()) {
  3114. return Just(scope.Escape(result.Unwrap()));
  3115. }
  3116. return result;
  3117. #else
  3118. if (scope.Env().IsExceptionPending()) {
  3119. return Value();
  3120. }
  3121. return scope.Escape(result);
  3122. #endif
  3123. }
  3124. inline MaybeOrValue<Napi::Value> FunctionReference::MakeCallback(
  3125. napi_value recv,
  3126. size_t argc,
  3127. const napi_value* args,
  3128. napi_async_context context) const {
  3129. EscapableHandleScope scope(_env);
  3130. MaybeOrValue<Napi::Value> result =
  3131. Value().MakeCallback(recv, argc, args, context);
  3132. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3133. if (result.IsJust()) {
  3134. return Just(scope.Escape(result.Unwrap()));
  3135. }
  3136. return result;
  3137. #else
  3138. if (scope.Env().IsExceptionPending()) {
  3139. return Value();
  3140. }
  3141. return scope.Escape(result);
  3142. #endif
  3143. }
  3144. inline MaybeOrValue<Object> FunctionReference::New(
  3145. const std::initializer_list<napi_value>& args) const {
  3146. EscapableHandleScope scope(_env);
  3147. MaybeOrValue<Object> result = Value().New(args);
  3148. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3149. if (result.IsJust()) {
  3150. return Just(scope.Escape(result.Unwrap()).As<Object>());
  3151. }
  3152. return result;
  3153. #else
  3154. if (scope.Env().IsExceptionPending()) {
  3155. return Object();
  3156. }
  3157. return scope.Escape(result).As<Object>();
  3158. #endif
  3159. }
  3160. inline MaybeOrValue<Object> FunctionReference::New(
  3161. const std::vector<napi_value>& args) const {
  3162. EscapableHandleScope scope(_env);
  3163. MaybeOrValue<Object> result = Value().New(args);
  3164. #ifdef NODE_ADDON_API_ENABLE_MAYBE
  3165. if (result.IsJust()) {
  3166. return Just(scope.Escape(result.Unwrap()).As<Object>());
  3167. }
  3168. return result;
  3169. #else
  3170. if (scope.Env().IsExceptionPending()) {
  3171. return Object();
  3172. }
  3173. return scope.Escape(result).As<Object>();
  3174. #endif
  3175. }
  3176. ////////////////////////////////////////////////////////////////////////////////
  3177. // CallbackInfo class
  3178. ////////////////////////////////////////////////////////////////////////////////
  3179. inline CallbackInfo::CallbackInfo(napi_env env, napi_callback_info info)
  3180. : _env(env),
  3181. _info(info),
  3182. _this(nullptr),
  3183. _dynamicArgs(nullptr),
  3184. _data(nullptr) {
  3185. _argc = _staticArgCount;
  3186. _argv = _staticArgs;
  3187. napi_status status =
  3188. napi_get_cb_info(env, info, &_argc, _argv, &_this, &_data);
  3189. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3190. if (_argc > _staticArgCount) {
  3191. // Use either a fixed-size array (on the stack) or a dynamically-allocated
  3192. // array (on the heap) depending on the number of args.
  3193. _dynamicArgs = new napi_value[_argc];
  3194. _argv = _dynamicArgs;
  3195. status = napi_get_cb_info(env, info, &_argc, _argv, nullptr, nullptr);
  3196. NAPI_THROW_IF_FAILED_VOID(_env, status);
  3197. }
  3198. }
  3199. inline CallbackInfo::~CallbackInfo() {
  3200. if (_dynamicArgs != nullptr) {
  3201. delete[] _dynamicArgs;
  3202. }
  3203. }
  3204. inline CallbackInfo::operator napi_callback_info() const {
  3205. return _info;
  3206. }
  3207. inline Value CallbackInfo::NewTarget() const {
  3208. napi_value newTarget;
  3209. napi_status status = napi_get_new_target(_env, _info, &newTarget);
  3210. NAPI_THROW_IF_FAILED(_env, status, Value());
  3211. return Value(_env, newTarget);
  3212. }
  3213. inline bool CallbackInfo::IsConstructCall() const {
  3214. return !NewTarget().IsEmpty();
  3215. }
  3216. inline Napi::Env CallbackInfo::Env() const {
  3217. return Napi::Env(_env);
  3218. }
  3219. inline size_t CallbackInfo::Length() const {
  3220. return _argc;
  3221. }
  3222. inline const Value CallbackInfo::operator[](size_t index) const {
  3223. return index < _argc ? Value(_env, _argv[index]) : Env().Undefined();
  3224. }
  3225. inline Value CallbackInfo::This() const {
  3226. if (_this == nullptr) {
  3227. return Env().Undefined();
  3228. }
  3229. return Object(_env, _this);
  3230. }
  3231. inline void* CallbackInfo::Data() const {
  3232. return _data;
  3233. }
  3234. inline void CallbackInfo::SetData(void* data) {
  3235. _data = data;
  3236. }
  3237. ////////////////////////////////////////////////////////////////////////////////
  3238. // PropertyDescriptor class
  3239. ////////////////////////////////////////////////////////////////////////////////
  3240. template <typename PropertyDescriptor::GetterCallback Getter>
  3241. PropertyDescriptor PropertyDescriptor::Accessor(
  3242. const char* utf8name, napi_property_attributes attributes, void* data) {
  3243. napi_property_descriptor desc = napi_property_descriptor();
  3244. desc.utf8name = utf8name;
  3245. desc.getter = details::TemplatedCallback<Getter>;
  3246. desc.attributes = attributes;
  3247. desc.data = data;
  3248. return desc;
  3249. }
  3250. template <typename PropertyDescriptor::GetterCallback Getter>
  3251. PropertyDescriptor PropertyDescriptor::Accessor(
  3252. const std::string& utf8name,
  3253. napi_property_attributes attributes,
  3254. void* data) {
  3255. return Accessor<Getter>(utf8name.c_str(), attributes, data);
  3256. }
  3257. template <typename PropertyDescriptor::GetterCallback Getter>
  3258. PropertyDescriptor PropertyDescriptor::Accessor(
  3259. Name name, napi_property_attributes attributes, void* data) {
  3260. napi_property_descriptor desc = napi_property_descriptor();
  3261. desc.name = name;
  3262. desc.getter = details::TemplatedCallback<Getter>;
  3263. desc.attributes = attributes;
  3264. desc.data = data;
  3265. return desc;
  3266. }
  3267. template <typename PropertyDescriptor::GetterCallback Getter,
  3268. typename PropertyDescriptor::SetterCallback Setter>
  3269. PropertyDescriptor PropertyDescriptor::Accessor(
  3270. const char* utf8name, napi_property_attributes attributes, void* data) {
  3271. napi_property_descriptor desc = napi_property_descriptor();
  3272. desc.utf8name = utf8name;
  3273. desc.getter = details::TemplatedCallback<Getter>;
  3274. desc.setter = details::TemplatedVoidCallback<Setter>;
  3275. desc.attributes = attributes;
  3276. desc.data = data;
  3277. return desc;
  3278. }
  3279. template <typename PropertyDescriptor::GetterCallback Getter,
  3280. typename PropertyDescriptor::SetterCallback Setter>
  3281. PropertyDescriptor PropertyDescriptor::Accessor(
  3282. const std::string& utf8name,
  3283. napi_property_attributes attributes,
  3284. void* data) {
  3285. return Accessor<Getter, Setter>(utf8name.c_str(), attributes, data);
  3286. }
  3287. template <typename PropertyDescriptor::GetterCallback Getter,
  3288. typename PropertyDescriptor::SetterCallback Setter>
  3289. PropertyDescriptor PropertyDescriptor::Accessor(
  3290. Name name, napi_property_attributes attributes, void* data) {
  3291. napi_property_descriptor desc = napi_property_descriptor();
  3292. desc.name = name;
  3293. desc.getter = details::TemplatedCallback<Getter>;
  3294. desc.setter = details::TemplatedVoidCallback<Setter>;
  3295. desc.attributes = attributes;
  3296. desc.data = data;
  3297. return desc;
  3298. }
  3299. template <typename Getter>
  3300. inline PropertyDescriptor PropertyDescriptor::Accessor(
  3301. Napi::Env env,
  3302. Napi::Object object,
  3303. const char* utf8name,
  3304. Getter getter,
  3305. napi_property_attributes attributes,
  3306. void* data) {
  3307. using CbData = details::CallbackData<Getter, Napi::Value>;
  3308. auto callbackData = new CbData({getter, data});
  3309. napi_status status = AttachData(env, object, callbackData);
  3310. if (status != napi_ok) {
  3311. delete callbackData;
  3312. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  3313. }
  3314. return PropertyDescriptor({utf8name,
  3315. nullptr,
  3316. nullptr,
  3317. CbData::Wrapper,
  3318. nullptr,
  3319. nullptr,
  3320. attributes,
  3321. callbackData});
  3322. }
  3323. template <typename Getter>
  3324. inline PropertyDescriptor PropertyDescriptor::Accessor(
  3325. Napi::Env env,
  3326. Napi::Object object,
  3327. const std::string& utf8name,
  3328. Getter getter,
  3329. napi_property_attributes attributes,
  3330. void* data) {
  3331. return Accessor(env, object, utf8name.c_str(), getter, attributes, data);
  3332. }
  3333. template <typename Getter>
  3334. inline PropertyDescriptor PropertyDescriptor::Accessor(
  3335. Napi::Env env,
  3336. Napi::Object object,
  3337. Name name,
  3338. Getter getter,
  3339. napi_property_attributes attributes,
  3340. void* data) {
  3341. using CbData = details::CallbackData<Getter, Napi::Value>;
  3342. auto callbackData = new CbData({getter, data});
  3343. napi_status status = AttachData(env, object, callbackData);
  3344. if (status != napi_ok) {
  3345. delete callbackData;
  3346. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  3347. }
  3348. return PropertyDescriptor({nullptr,
  3349. name,
  3350. nullptr,
  3351. CbData::Wrapper,
  3352. nullptr,
  3353. nullptr,
  3354. attributes,
  3355. callbackData});
  3356. }
  3357. template <typename Getter, typename Setter>
  3358. inline PropertyDescriptor PropertyDescriptor::Accessor(
  3359. Napi::Env env,
  3360. Napi::Object object,
  3361. const char* utf8name,
  3362. Getter getter,
  3363. Setter setter,
  3364. napi_property_attributes attributes,
  3365. void* data) {
  3366. using CbData = details::AccessorCallbackData<Getter, Setter>;
  3367. auto callbackData = new CbData({getter, setter, data});
  3368. napi_status status = AttachData(env, object, callbackData);
  3369. if (status != napi_ok) {
  3370. delete callbackData;
  3371. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  3372. }
  3373. return PropertyDescriptor({utf8name,
  3374. nullptr,
  3375. nullptr,
  3376. CbData::GetterWrapper,
  3377. CbData::SetterWrapper,
  3378. nullptr,
  3379. attributes,
  3380. callbackData});
  3381. }
  3382. template <typename Getter, typename Setter>
  3383. inline PropertyDescriptor PropertyDescriptor::Accessor(
  3384. Napi::Env env,
  3385. Napi::Object object,
  3386. const std::string& utf8name,
  3387. Getter getter,
  3388. Setter setter,
  3389. napi_property_attributes attributes,
  3390. void* data) {
  3391. return Accessor(
  3392. env, object, utf8name.c_str(), getter, setter, attributes, data);
  3393. }
  3394. template <typename Getter, typename Setter>
  3395. inline PropertyDescriptor PropertyDescriptor::Accessor(
  3396. Napi::Env env,
  3397. Napi::Object object,
  3398. Name name,
  3399. Getter getter,
  3400. Setter setter,
  3401. napi_property_attributes attributes,
  3402. void* data) {
  3403. using CbData = details::AccessorCallbackData<Getter, Setter>;
  3404. auto callbackData = new CbData({getter, setter, data});
  3405. napi_status status = AttachData(env, object, callbackData);
  3406. if (status != napi_ok) {
  3407. delete callbackData;
  3408. NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor());
  3409. }
  3410. return PropertyDescriptor({nullptr,
  3411. name,
  3412. nullptr,
  3413. CbData::GetterWrapper,
  3414. CbData::SetterWrapper,
  3415. nullptr,
  3416. attributes,
  3417. callbackData});
  3418. }
  3419. template <typename Callable>
  3420. inline PropertyDescriptor PropertyDescriptor::Function(
  3421. Napi::Env env,
  3422. Napi::Object /*object*/,
  3423. const char* utf8name,
  3424. Callable cb,
  3425. napi_property_attributes attributes,
  3426. void* data) {
  3427. return PropertyDescriptor({utf8name,
  3428. nullptr,
  3429. nullptr,
  3430. nullptr,
  3431. nullptr,
  3432. Napi::Function::New(env, cb, utf8name, data),
  3433. attributes,
  3434. nullptr});
  3435. }
  3436. template <typename Callable>
  3437. inline PropertyDescriptor PropertyDescriptor::Function(
  3438. Napi::Env env,
  3439. Napi::Object object,
  3440. const std::string& utf8name,
  3441. Callable cb,
  3442. napi_property_attributes attributes,
  3443. void* data) {
  3444. return Function(env, object, utf8name.c_str(), cb, attributes, data);
  3445. }
  3446. template <typename Callable>
  3447. inline PropertyDescriptor PropertyDescriptor::Function(
  3448. Napi::Env env,
  3449. Napi::Object /*object*/,
  3450. Name name,
  3451. Callable cb,
  3452. napi_property_attributes attributes,
  3453. void* data) {
  3454. return PropertyDescriptor({nullptr,
  3455. name,
  3456. nullptr,
  3457. nullptr,
  3458. nullptr,
  3459. Napi::Function::New(env, cb, nullptr, data),
  3460. attributes,
  3461. nullptr});
  3462. }
  3463. inline PropertyDescriptor PropertyDescriptor::Value(
  3464. const char* utf8name,
  3465. napi_value value,
  3466. napi_property_attributes attributes) {
  3467. return PropertyDescriptor({utf8name,
  3468. nullptr,
  3469. nullptr,
  3470. nullptr,
  3471. nullptr,
  3472. value,
  3473. attributes,
  3474. nullptr});
  3475. }
  3476. inline PropertyDescriptor PropertyDescriptor::Value(
  3477. const std::string& utf8name,
  3478. napi_value value,
  3479. napi_property_attributes attributes) {
  3480. return Value(utf8name.c_str(), value, attributes);
  3481. }
  3482. inline PropertyDescriptor PropertyDescriptor::Value(
  3483. napi_value name, napi_value value, napi_property_attributes attributes) {
  3484. return PropertyDescriptor(
  3485. {nullptr, name, nullptr, nullptr, nullptr, value, attributes, nullptr});
  3486. }
  3487. inline PropertyDescriptor PropertyDescriptor::Value(
  3488. Name name, Napi::Value value, napi_property_attributes attributes) {
  3489. napi_value nameValue = name;
  3490. napi_value valueValue = value;
  3491. return PropertyDescriptor::Value(nameValue, valueValue, attributes);
  3492. }
  3493. inline PropertyDescriptor::PropertyDescriptor(napi_property_descriptor desc)
  3494. : _desc(desc) {}
  3495. inline PropertyDescriptor::operator napi_property_descriptor&() {
  3496. return _desc;
  3497. }
  3498. inline PropertyDescriptor::operator const napi_property_descriptor&() const {
  3499. return _desc;
  3500. }
  3501. ////////////////////////////////////////////////////////////////////////////////
  3502. // InstanceWrap<T> class
  3503. ////////////////////////////////////////////////////////////////////////////////
  3504. template <typename T>
  3505. inline void InstanceWrap<T>::AttachPropData(
  3506. napi_env env, napi_value value, const napi_property_descriptor* prop) {
  3507. napi_status status;
  3508. if (!(prop->attributes & napi_static)) {
  3509. if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
  3510. status = Napi::details::AttachData(
  3511. env, value, static_cast<InstanceVoidMethodCallbackData*>(prop->data));
  3512. NAPI_THROW_IF_FAILED_VOID(env, status);
  3513. } else if (prop->method == T::InstanceMethodCallbackWrapper) {
  3514. status = Napi::details::AttachData(
  3515. env, value, static_cast<InstanceMethodCallbackData*>(prop->data));
  3516. NAPI_THROW_IF_FAILED_VOID(env, status);
  3517. } else if (prop->getter == T::InstanceGetterCallbackWrapper ||
  3518. prop->setter == T::InstanceSetterCallbackWrapper) {
  3519. status = Napi::details::AttachData(
  3520. env, value, static_cast<InstanceAccessorCallbackData*>(prop->data));
  3521. NAPI_THROW_IF_FAILED_VOID(env, status);
  3522. }
  3523. }
  3524. }
  3525. template <typename T>
  3526. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3527. const char* utf8name,
  3528. InstanceVoidMethodCallback method,
  3529. napi_property_attributes attributes,
  3530. void* data) {
  3531. InstanceVoidMethodCallbackData* callbackData =
  3532. new InstanceVoidMethodCallbackData({method, data});
  3533. napi_property_descriptor desc = napi_property_descriptor();
  3534. desc.utf8name = utf8name;
  3535. desc.method = T::InstanceVoidMethodCallbackWrapper;
  3536. desc.data = callbackData;
  3537. desc.attributes = attributes;
  3538. return desc;
  3539. }
  3540. template <typename T>
  3541. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3542. const char* utf8name,
  3543. InstanceMethodCallback method,
  3544. napi_property_attributes attributes,
  3545. void* data) {
  3546. InstanceMethodCallbackData* callbackData =
  3547. new InstanceMethodCallbackData({method, data});
  3548. napi_property_descriptor desc = napi_property_descriptor();
  3549. desc.utf8name = utf8name;
  3550. desc.method = T::InstanceMethodCallbackWrapper;
  3551. desc.data = callbackData;
  3552. desc.attributes = attributes;
  3553. return desc;
  3554. }
  3555. template <typename T>
  3556. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3557. Symbol name,
  3558. InstanceVoidMethodCallback method,
  3559. napi_property_attributes attributes,
  3560. void* data) {
  3561. InstanceVoidMethodCallbackData* callbackData =
  3562. new InstanceVoidMethodCallbackData({method, data});
  3563. napi_property_descriptor desc = napi_property_descriptor();
  3564. desc.name = name;
  3565. desc.method = T::InstanceVoidMethodCallbackWrapper;
  3566. desc.data = callbackData;
  3567. desc.attributes = attributes;
  3568. return desc;
  3569. }
  3570. template <typename T>
  3571. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3572. Symbol name,
  3573. InstanceMethodCallback method,
  3574. napi_property_attributes attributes,
  3575. void* data) {
  3576. InstanceMethodCallbackData* callbackData =
  3577. new InstanceMethodCallbackData({method, data});
  3578. napi_property_descriptor desc = napi_property_descriptor();
  3579. desc.name = name;
  3580. desc.method = T::InstanceMethodCallbackWrapper;
  3581. desc.data = callbackData;
  3582. desc.attributes = attributes;
  3583. return desc;
  3584. }
  3585. template <typename T>
  3586. template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
  3587. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3588. const char* utf8name, napi_property_attributes attributes, void* data) {
  3589. napi_property_descriptor desc = napi_property_descriptor();
  3590. desc.utf8name = utf8name;
  3591. desc.method = details::TemplatedInstanceVoidCallback<T, method>;
  3592. desc.data = data;
  3593. desc.attributes = attributes;
  3594. return desc;
  3595. }
  3596. template <typename T>
  3597. template <typename InstanceWrap<T>::InstanceMethodCallback method>
  3598. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3599. const char* utf8name, napi_property_attributes attributes, void* data) {
  3600. napi_property_descriptor desc = napi_property_descriptor();
  3601. desc.utf8name = utf8name;
  3602. desc.method = details::TemplatedInstanceCallback<T, method>;
  3603. desc.data = data;
  3604. desc.attributes = attributes;
  3605. return desc;
  3606. }
  3607. template <typename T>
  3608. template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
  3609. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3610. Symbol name, napi_property_attributes attributes, void* data) {
  3611. napi_property_descriptor desc = napi_property_descriptor();
  3612. desc.name = name;
  3613. desc.method = details::TemplatedInstanceVoidCallback<T, method>;
  3614. desc.data = data;
  3615. desc.attributes = attributes;
  3616. return desc;
  3617. }
  3618. template <typename T>
  3619. template <typename InstanceWrap<T>::InstanceMethodCallback method>
  3620. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
  3621. Symbol name, napi_property_attributes attributes, void* data) {
  3622. napi_property_descriptor desc = napi_property_descriptor();
  3623. desc.name = name;
  3624. desc.method = details::TemplatedInstanceCallback<T, method>;
  3625. desc.data = data;
  3626. desc.attributes = attributes;
  3627. return desc;
  3628. }
  3629. template <typename T>
  3630. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
  3631. const char* utf8name,
  3632. InstanceGetterCallback getter,
  3633. InstanceSetterCallback setter,
  3634. napi_property_attributes attributes,
  3635. void* data) {
  3636. InstanceAccessorCallbackData* callbackData =
  3637. new InstanceAccessorCallbackData({getter, setter, data});
  3638. napi_property_descriptor desc = napi_property_descriptor();
  3639. desc.utf8name = utf8name;
  3640. desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
  3641. desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
  3642. desc.data = callbackData;
  3643. desc.attributes = attributes;
  3644. return desc;
  3645. }
  3646. template <typename T>
  3647. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
  3648. Symbol name,
  3649. InstanceGetterCallback getter,
  3650. InstanceSetterCallback setter,
  3651. napi_property_attributes attributes,
  3652. void* data) {
  3653. InstanceAccessorCallbackData* callbackData =
  3654. new InstanceAccessorCallbackData({getter, setter, data});
  3655. napi_property_descriptor desc = napi_property_descriptor();
  3656. desc.name = name;
  3657. desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
  3658. desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
  3659. desc.data = callbackData;
  3660. desc.attributes = attributes;
  3661. return desc;
  3662. }
  3663. template <typename T>
  3664. template <typename InstanceWrap<T>::InstanceGetterCallback getter,
  3665. typename InstanceWrap<T>::InstanceSetterCallback setter>
  3666. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
  3667. const char* utf8name, napi_property_attributes attributes, void* data) {
  3668. napi_property_descriptor desc = napi_property_descriptor();
  3669. desc.utf8name = utf8name;
  3670. desc.getter = details::TemplatedInstanceCallback<T, getter>;
  3671. desc.setter = This::WrapSetter(This::SetterTag<setter>());
  3672. desc.data = data;
  3673. desc.attributes = attributes;
  3674. return desc;
  3675. }
  3676. template <typename T>
  3677. template <typename InstanceWrap<T>::InstanceGetterCallback getter,
  3678. typename InstanceWrap<T>::InstanceSetterCallback setter>
  3679. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
  3680. Symbol name, napi_property_attributes attributes, void* data) {
  3681. napi_property_descriptor desc = napi_property_descriptor();
  3682. desc.name = name;
  3683. desc.getter = details::TemplatedInstanceCallback<T, getter>;
  3684. desc.setter = This::WrapSetter(This::SetterTag<setter>());
  3685. desc.data = data;
  3686. desc.attributes = attributes;
  3687. return desc;
  3688. }
  3689. template <typename T>
  3690. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
  3691. const char* utf8name,
  3692. Napi::Value value,
  3693. napi_property_attributes attributes) {
  3694. napi_property_descriptor desc = napi_property_descriptor();
  3695. desc.utf8name = utf8name;
  3696. desc.value = value;
  3697. desc.attributes = attributes;
  3698. return desc;
  3699. }
  3700. template <typename T>
  3701. inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
  3702. Symbol name, Napi::Value value, napi_property_attributes attributes) {
  3703. napi_property_descriptor desc = napi_property_descriptor();
  3704. desc.name = name;
  3705. desc.value = value;
  3706. desc.attributes = attributes;
  3707. return desc;
  3708. }
  3709. template <typename T>
  3710. inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
  3711. napi_env env, napi_callback_info info) {
  3712. return details::WrapCallback([&] {
  3713. CallbackInfo callbackInfo(env, info);
  3714. InstanceVoidMethodCallbackData* callbackData =
  3715. reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
  3716. callbackInfo.SetData(callbackData->data);
  3717. T* instance = T::Unwrap(callbackInfo.This().As<Object>());
  3718. auto cb = callbackData->callback;
  3719. if (instance) (instance->*cb)(callbackInfo);
  3720. return nullptr;
  3721. });
  3722. }
  3723. template <typename T>
  3724. inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
  3725. napi_env env, napi_callback_info info) {
  3726. return details::WrapCallback([&] {
  3727. CallbackInfo callbackInfo(env, info);
  3728. InstanceMethodCallbackData* callbackData =
  3729. reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
  3730. callbackInfo.SetData(callbackData->data);
  3731. T* instance = T::Unwrap(callbackInfo.This().As<Object>());
  3732. auto cb = callbackData->callback;
  3733. return instance ? (instance->*cb)(callbackInfo) : Napi::Value();
  3734. });
  3735. }
  3736. template <typename T>
  3737. inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
  3738. napi_env env, napi_callback_info info) {
  3739. return details::WrapCallback([&] {
  3740. CallbackInfo callbackInfo(env, info);
  3741. InstanceAccessorCallbackData* callbackData =
  3742. reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
  3743. callbackInfo.SetData(callbackData->data);
  3744. T* instance = T::Unwrap(callbackInfo.This().As<Object>());
  3745. auto cb = callbackData->getterCallback;
  3746. return instance ? (instance->*cb)(callbackInfo) : Napi::Value();
  3747. });
  3748. }
  3749. template <typename T>
  3750. inline napi_value InstanceWrap<T>::InstanceSetterCallbackWrapper(
  3751. napi_env env, napi_callback_info info) {
  3752. return details::WrapCallback([&] {
  3753. CallbackInfo callbackInfo(env, info);
  3754. InstanceAccessorCallbackData* callbackData =
  3755. reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
  3756. callbackInfo.SetData(callbackData->data);
  3757. T* instance = T::Unwrap(callbackInfo.This().As<Object>());
  3758. auto cb = callbackData->setterCallback;
  3759. if (instance) (instance->*cb)(callbackInfo, callbackInfo[0]);
  3760. return nullptr;
  3761. });
  3762. }
  3763. template <typename T>
  3764. template <typename InstanceWrap<T>::InstanceSetterCallback method>
  3765. inline napi_value InstanceWrap<T>::WrappedMethod(
  3766. napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
  3767. return details::WrapCallback([&] {
  3768. const CallbackInfo cbInfo(env, info);
  3769. T* instance = T::Unwrap(cbInfo.This().As<Object>());
  3770. if (instance) (instance->*method)(cbInfo, cbInfo[0]);
  3771. return nullptr;
  3772. });
  3773. }
  3774. ////////////////////////////////////////////////////////////////////////////////
  3775. // ObjectWrap<T> class
  3776. ////////////////////////////////////////////////////////////////////////////////
  3777. template <typename T>
  3778. inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
  3779. napi_env env = callbackInfo.Env();
  3780. napi_value wrapper = callbackInfo.This();
  3781. napi_status status;
  3782. napi_ref ref;
  3783. T* instance = static_cast<T*>(this);
  3784. status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
  3785. NAPI_THROW_IF_FAILED_VOID(env, status);
  3786. Reference<Object>* instanceRef = instance;
  3787. *instanceRef = Reference<Object>(env, ref);
  3788. }
  3789. template <typename T>
  3790. inline ObjectWrap<T>::~ObjectWrap() {
  3791. // If the JS object still exists at this point, remove the finalizer added
  3792. // through `napi_wrap()`.
  3793. if (!IsEmpty()) {
  3794. Object object = Value();
  3795. // It is not valid to call `napi_remove_wrap()` with an empty `object`.
  3796. // This happens e.g. during garbage collection.
  3797. if (!object.IsEmpty() && _construction_failed) {
  3798. napi_remove_wrap(Env(), object, nullptr);
  3799. }
  3800. }
  3801. }
  3802. template <typename T>
  3803. inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
  3804. void* unwrapped;
  3805. napi_status status = napi_unwrap(wrapper.Env(), wrapper, &unwrapped);
  3806. NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
  3807. return static_cast<T*>(unwrapped);
  3808. }
  3809. template <typename T>
  3810. inline Function ObjectWrap<T>::DefineClass(
  3811. Napi::Env env,
  3812. const char* utf8name,
  3813. const size_t props_count,
  3814. const napi_property_descriptor* descriptors,
  3815. void* data) {
  3816. napi_status status;
  3817. std::vector<napi_property_descriptor> props(props_count);
  3818. // We copy the descriptors to a local array because before defining the class
  3819. // we must replace static method property descriptors with value property
  3820. // descriptors such that the value is a function-valued `napi_value` created
  3821. // with `CreateFunction()`.
  3822. //
  3823. // This replacement could be made for instance methods as well, but V8 aborts
  3824. // if we do that, because it expects methods defined on the prototype template
  3825. // to have `FunctionTemplate`s.
  3826. for (size_t index = 0; index < props_count; index++) {
  3827. props[index] = descriptors[index];
  3828. napi_property_descriptor* prop = &props[index];
  3829. if (prop->method == T::StaticMethodCallbackWrapper) {
  3830. status =
  3831. CreateFunction(env,
  3832. utf8name,
  3833. prop->method,
  3834. static_cast<StaticMethodCallbackData*>(prop->data),
  3835. &(prop->value));
  3836. NAPI_THROW_IF_FAILED(env, status, Function());
  3837. prop->method = nullptr;
  3838. prop->data = nullptr;
  3839. } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
  3840. status =
  3841. CreateFunction(env,
  3842. utf8name,
  3843. prop->method,
  3844. static_cast<StaticVoidMethodCallbackData*>(prop->data),
  3845. &(prop->value));
  3846. NAPI_THROW_IF_FAILED(env, status, Function());
  3847. prop->method = nullptr;
  3848. prop->data = nullptr;
  3849. }
  3850. }
  3851. napi_value value;
  3852. status = napi_define_class(env,
  3853. utf8name,
  3854. NAPI_AUTO_LENGTH,
  3855. T::ConstructorCallbackWrapper,
  3856. data,
  3857. props_count,
  3858. props.data(),
  3859. &value);
  3860. NAPI_THROW_IF_FAILED(env, status, Function());
  3861. // After defining the class we iterate once more over the property descriptors
  3862. // and attach the data associated with accessors and instance methods to the
  3863. // newly created JavaScript class.
  3864. for (size_t idx = 0; idx < props_count; idx++) {
  3865. const napi_property_descriptor* prop = &props[idx];
  3866. if (prop->getter == T::StaticGetterCallbackWrapper ||
  3867. prop->setter == T::StaticSetterCallbackWrapper) {
  3868. status = Napi::details::AttachData(
  3869. env, value, static_cast<StaticAccessorCallbackData*>(prop->data));
  3870. NAPI_THROW_IF_FAILED(env, status, Function());
  3871. } else {
  3872. // InstanceWrap<T>::AttachPropData is responsible for attaching the data
  3873. // of instance methods and accessors.
  3874. T::AttachPropData(env, value, prop);
  3875. }
  3876. }
  3877. return Function(env, value);
  3878. }
  3879. template <typename T>
  3880. inline Function ObjectWrap<T>::DefineClass(
  3881. Napi::Env env,
  3882. const char* utf8name,
  3883. const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
  3884. void* data) {
  3885. return DefineClass(
  3886. env,
  3887. utf8name,
  3888. properties.size(),
  3889. reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
  3890. data);
  3891. }
  3892. template <typename T>
  3893. inline Function ObjectWrap<T>::DefineClass(
  3894. Napi::Env env,
  3895. const char* utf8name,
  3896. const std::vector<ClassPropertyDescriptor<T>>& properties,
  3897. void* data) {
  3898. return DefineClass(
  3899. env,
  3900. utf8name,
  3901. properties.size(),
  3902. reinterpret_cast<const napi_property_descriptor*>(properties.data()),
  3903. data);
  3904. }
  3905. template <typename T>
  3906. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3907. const char* utf8name,
  3908. StaticVoidMethodCallback method,
  3909. napi_property_attributes attributes,
  3910. void* data) {
  3911. StaticVoidMethodCallbackData* callbackData =
  3912. new StaticVoidMethodCallbackData({method, data});
  3913. napi_property_descriptor desc = napi_property_descriptor();
  3914. desc.utf8name = utf8name;
  3915. desc.method = T::StaticVoidMethodCallbackWrapper;
  3916. desc.data = callbackData;
  3917. desc.attributes =
  3918. static_cast<napi_property_attributes>(attributes | napi_static);
  3919. return desc;
  3920. }
  3921. template <typename T>
  3922. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3923. const char* utf8name,
  3924. StaticMethodCallback method,
  3925. napi_property_attributes attributes,
  3926. void* data) {
  3927. StaticMethodCallbackData* callbackData =
  3928. new StaticMethodCallbackData({method, data});
  3929. napi_property_descriptor desc = napi_property_descriptor();
  3930. desc.utf8name = utf8name;
  3931. desc.method = T::StaticMethodCallbackWrapper;
  3932. desc.data = callbackData;
  3933. desc.attributes =
  3934. static_cast<napi_property_attributes>(attributes | napi_static);
  3935. return desc;
  3936. }
  3937. template <typename T>
  3938. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3939. Symbol name,
  3940. StaticVoidMethodCallback method,
  3941. napi_property_attributes attributes,
  3942. void* data) {
  3943. StaticVoidMethodCallbackData* callbackData =
  3944. new StaticVoidMethodCallbackData({method, data});
  3945. napi_property_descriptor desc = napi_property_descriptor();
  3946. desc.name = name;
  3947. desc.method = T::StaticVoidMethodCallbackWrapper;
  3948. desc.data = callbackData;
  3949. desc.attributes =
  3950. static_cast<napi_property_attributes>(attributes | napi_static);
  3951. return desc;
  3952. }
  3953. template <typename T>
  3954. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3955. Symbol name,
  3956. StaticMethodCallback method,
  3957. napi_property_attributes attributes,
  3958. void* data) {
  3959. StaticMethodCallbackData* callbackData =
  3960. new StaticMethodCallbackData({method, data});
  3961. napi_property_descriptor desc = napi_property_descriptor();
  3962. desc.name = name;
  3963. desc.method = T::StaticMethodCallbackWrapper;
  3964. desc.data = callbackData;
  3965. desc.attributes =
  3966. static_cast<napi_property_attributes>(attributes | napi_static);
  3967. return desc;
  3968. }
  3969. template <typename T>
  3970. template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
  3971. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3972. const char* utf8name, napi_property_attributes attributes, void* data) {
  3973. napi_property_descriptor desc = napi_property_descriptor();
  3974. desc.utf8name = utf8name;
  3975. desc.method = details::TemplatedVoidCallback<method>;
  3976. desc.data = data;
  3977. desc.attributes =
  3978. static_cast<napi_property_attributes>(attributes | napi_static);
  3979. return desc;
  3980. }
  3981. template <typename T>
  3982. template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
  3983. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3984. Symbol name, napi_property_attributes attributes, void* data) {
  3985. napi_property_descriptor desc = napi_property_descriptor();
  3986. desc.name = name;
  3987. desc.method = details::TemplatedVoidCallback<method>;
  3988. desc.data = data;
  3989. desc.attributes =
  3990. static_cast<napi_property_attributes>(attributes | napi_static);
  3991. return desc;
  3992. }
  3993. template <typename T>
  3994. template <typename ObjectWrap<T>::StaticMethodCallback method>
  3995. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  3996. const char* utf8name, napi_property_attributes attributes, void* data) {
  3997. napi_property_descriptor desc = napi_property_descriptor();
  3998. desc.utf8name = utf8name;
  3999. desc.method = details::TemplatedCallback<method>;
  4000. desc.data = data;
  4001. desc.attributes =
  4002. static_cast<napi_property_attributes>(attributes | napi_static);
  4003. return desc;
  4004. }
  4005. template <typename T>
  4006. template <typename ObjectWrap<T>::StaticMethodCallback method>
  4007. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
  4008. Symbol name, napi_property_attributes attributes, void* data) {
  4009. napi_property_descriptor desc = napi_property_descriptor();
  4010. desc.name = name;
  4011. desc.method = details::TemplatedCallback<method>;
  4012. desc.data = data;
  4013. desc.attributes =
  4014. static_cast<napi_property_attributes>(attributes | napi_static);
  4015. return desc;
  4016. }
  4017. template <typename T>
  4018. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  4019. const char* utf8name,
  4020. StaticGetterCallback getter,
  4021. StaticSetterCallback setter,
  4022. napi_property_attributes attributes,
  4023. void* data) {
  4024. StaticAccessorCallbackData* callbackData =
  4025. new StaticAccessorCallbackData({getter, setter, data});
  4026. napi_property_descriptor desc = napi_property_descriptor();
  4027. desc.utf8name = utf8name;
  4028. desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
  4029. desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
  4030. desc.data = callbackData;
  4031. desc.attributes =
  4032. static_cast<napi_property_attributes>(attributes | napi_static);
  4033. return desc;
  4034. }
  4035. template <typename T>
  4036. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  4037. Symbol name,
  4038. StaticGetterCallback getter,
  4039. StaticSetterCallback setter,
  4040. napi_property_attributes attributes,
  4041. void* data) {
  4042. StaticAccessorCallbackData* callbackData =
  4043. new StaticAccessorCallbackData({getter, setter, data});
  4044. napi_property_descriptor desc = napi_property_descriptor();
  4045. desc.name = name;
  4046. desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
  4047. desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
  4048. desc.data = callbackData;
  4049. desc.attributes =
  4050. static_cast<napi_property_attributes>(attributes | napi_static);
  4051. return desc;
  4052. }
  4053. template <typename T>
  4054. template <typename ObjectWrap<T>::StaticGetterCallback getter,
  4055. typename ObjectWrap<T>::StaticSetterCallback setter>
  4056. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  4057. const char* utf8name, napi_property_attributes attributes, void* data) {
  4058. napi_property_descriptor desc = napi_property_descriptor();
  4059. desc.utf8name = utf8name;
  4060. desc.getter = details::TemplatedCallback<getter>;
  4061. desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
  4062. desc.data = data;
  4063. desc.attributes =
  4064. static_cast<napi_property_attributes>(attributes | napi_static);
  4065. return desc;
  4066. }
  4067. template <typename T>
  4068. template <typename ObjectWrap<T>::StaticGetterCallback getter,
  4069. typename ObjectWrap<T>::StaticSetterCallback setter>
  4070. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
  4071. Symbol name, napi_property_attributes attributes, void* data) {
  4072. napi_property_descriptor desc = napi_property_descriptor();
  4073. desc.name = name;
  4074. desc.getter = details::TemplatedCallback<getter>;
  4075. desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
  4076. desc.data = data;
  4077. desc.attributes =
  4078. static_cast<napi_property_attributes>(attributes | napi_static);
  4079. return desc;
  4080. }
  4081. template <typename T>
  4082. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(
  4083. const char* utf8name,
  4084. Napi::Value value,
  4085. napi_property_attributes attributes) {
  4086. napi_property_descriptor desc = napi_property_descriptor();
  4087. desc.utf8name = utf8name;
  4088. desc.value = value;
  4089. desc.attributes =
  4090. static_cast<napi_property_attributes>(attributes | napi_static);
  4091. return desc;
  4092. }
  4093. template <typename T>
  4094. inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(
  4095. Symbol name, Napi::Value value, napi_property_attributes attributes) {
  4096. napi_property_descriptor desc = napi_property_descriptor();
  4097. desc.name = name;
  4098. desc.value = value;
  4099. desc.attributes =
  4100. static_cast<napi_property_attributes>(attributes | napi_static);
  4101. return desc;
  4102. }
  4103. template <typename T>
  4104. inline Value ObjectWrap<T>::OnCalledAsFunction(
  4105. const Napi::CallbackInfo& callbackInfo) {
  4106. NAPI_THROW(
  4107. TypeError::New(callbackInfo.Env(),
  4108. "Class constructors cannot be invoked without 'new'"),
  4109. Napi::Value());
  4110. }
  4111. template <typename T>
  4112. inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
  4113. template <typename T>
  4114. inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
  4115. napi_env env, napi_callback_info info) {
  4116. napi_value new_target;
  4117. napi_status status = napi_get_new_target(env, info, &new_target);
  4118. if (status != napi_ok) return nullptr;
  4119. bool isConstructCall = (new_target != nullptr);
  4120. if (!isConstructCall) {
  4121. return details::WrapCallback(
  4122. [&] { return T::OnCalledAsFunction(CallbackInfo(env, info)); });
  4123. }
  4124. napi_value wrapper = details::WrapCallback([&] {
  4125. CallbackInfo callbackInfo(env, info);
  4126. T* instance = new T(callbackInfo);
  4127. #ifdef NAPI_CPP_EXCEPTIONS
  4128. instance->_construction_failed = false;
  4129. #else
  4130. if (callbackInfo.Env().IsExceptionPending()) {
  4131. // We need to clear the exception so that removing the wrap might work.
  4132. Error e = callbackInfo.Env().GetAndClearPendingException();
  4133. delete instance;
  4134. e.ThrowAsJavaScriptException();
  4135. } else {
  4136. instance->_construction_failed = false;
  4137. }
  4138. #endif // NAPI_CPP_EXCEPTIONS
  4139. return callbackInfo.This();
  4140. });
  4141. return wrapper;
  4142. }
  4143. template <typename T>
  4144. inline napi_value ObjectWrap<T>::StaticVoidMethodCallbackWrapper(
  4145. napi_env env, napi_callback_info info) {
  4146. return details::WrapCallback([&] {
  4147. CallbackInfo callbackInfo(env, info);
  4148. StaticVoidMethodCallbackData* callbackData =
  4149. reinterpret_cast<StaticVoidMethodCallbackData*>(callbackInfo.Data());
  4150. callbackInfo.SetData(callbackData->data);
  4151. callbackData->callback(callbackInfo);
  4152. return nullptr;
  4153. });
  4154. }
  4155. template <typename T>
  4156. inline napi_value ObjectWrap<T>::StaticMethodCallbackWrapper(
  4157. napi_env env, napi_callback_info info) {
  4158. return details::WrapCallback([&] {
  4159. CallbackInfo callbackInfo(env, info);
  4160. StaticMethodCallbackData* callbackData =
  4161. reinterpret_cast<StaticMethodCallbackData*>(callbackInfo.Data());
  4162. callbackInfo.SetData(callbackData->data);
  4163. return callbackData->callback(callbackInfo);
  4164. });
  4165. }
  4166. template <typename T>
  4167. inline napi_value ObjectWrap<T>::StaticGetterCallbackWrapper(
  4168. napi_env env, napi_callback_info info) {
  4169. return details::WrapCallback([&] {
  4170. CallbackInfo callbackInfo(env, info);
  4171. StaticAccessorCallbackData* callbackData =
  4172. reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
  4173. callbackInfo.SetData(callbackData->data);
  4174. return callbackData->getterCallback(callbackInfo);
  4175. });
  4176. }
  4177. template <typename T>
  4178. inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
  4179. napi_env env, napi_callback_info info) {
  4180. return details::WrapCallback([&] {
  4181. CallbackInfo callbackInfo(env, info);
  4182. StaticAccessorCallbackData* callbackData =
  4183. reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
  4184. callbackInfo.SetData(callbackData->data);
  4185. callbackData->setterCallback(callbackInfo, callbackInfo[0]);
  4186. return nullptr;
  4187. });
  4188. }
  4189. template <typename T>
  4190. inline void ObjectWrap<T>::FinalizeCallback(napi_env env,
  4191. void* data,
  4192. void* /*hint*/) {
  4193. HandleScope scope(env);
  4194. T* instance = static_cast<T*>(data);
  4195. instance->Finalize(Napi::Env(env));
  4196. delete instance;
  4197. }
  4198. template <typename T>
  4199. template <typename ObjectWrap<T>::StaticSetterCallback method>
  4200. inline napi_value ObjectWrap<T>::WrappedMethod(
  4201. napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
  4202. return details::WrapCallback([&] {
  4203. const CallbackInfo cbInfo(env, info);
  4204. method(cbInfo, cbInfo[0]);
  4205. return nullptr;
  4206. });
  4207. }
  4208. ////////////////////////////////////////////////////////////////////////////////
  4209. // HandleScope class
  4210. ////////////////////////////////////////////////////////////////////////////////
  4211. inline HandleScope::HandleScope(napi_env env, napi_handle_scope scope)
  4212. : _env(env), _scope(scope) {}
  4213. inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
  4214. napi_status status = napi_open_handle_scope(_env, &_scope);
  4215. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4216. }
  4217. inline HandleScope::~HandleScope() {
  4218. napi_status status = napi_close_handle_scope(_env, _scope);
  4219. NAPI_FATAL_IF_FAILED(
  4220. status, "HandleScope::~HandleScope", "napi_close_handle_scope");
  4221. }
  4222. inline HandleScope::operator napi_handle_scope() const {
  4223. return _scope;
  4224. }
  4225. inline Napi::Env HandleScope::Env() const {
  4226. return Napi::Env(_env);
  4227. }
  4228. ////////////////////////////////////////////////////////////////////////////////
  4229. // EscapableHandleScope class
  4230. ////////////////////////////////////////////////////////////////////////////////
  4231. inline EscapableHandleScope::EscapableHandleScope(
  4232. napi_env env, napi_escapable_handle_scope scope)
  4233. : _env(env), _scope(scope) {}
  4234. inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
  4235. napi_status status = napi_open_escapable_handle_scope(_env, &_scope);
  4236. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4237. }
  4238. inline EscapableHandleScope::~EscapableHandleScope() {
  4239. napi_status status = napi_close_escapable_handle_scope(_env, _scope);
  4240. NAPI_FATAL_IF_FAILED(status,
  4241. "EscapableHandleScope::~EscapableHandleScope",
  4242. "napi_close_escapable_handle_scope");
  4243. }
  4244. inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
  4245. return _scope;
  4246. }
  4247. inline Napi::Env EscapableHandleScope::Env() const {
  4248. return Napi::Env(_env);
  4249. }
  4250. inline Value EscapableHandleScope::Escape(napi_value escapee) {
  4251. napi_value result;
  4252. napi_status status = napi_escape_handle(_env, _scope, escapee, &result);
  4253. NAPI_THROW_IF_FAILED(_env, status, Value());
  4254. return Value(_env, result);
  4255. }
  4256. #if (NAPI_VERSION > 2)
  4257. ////////////////////////////////////////////////////////////////////////////////
  4258. // CallbackScope class
  4259. ////////////////////////////////////////////////////////////////////////////////
  4260. inline CallbackScope::CallbackScope(napi_env env, napi_callback_scope scope)
  4261. : _env(env), _scope(scope) {}
  4262. inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
  4263. : _env(env) {
  4264. napi_status status =
  4265. napi_open_callback_scope(_env, Object::New(env), context, &_scope);
  4266. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4267. }
  4268. inline CallbackScope::~CallbackScope() {
  4269. napi_status status = napi_close_callback_scope(_env, _scope);
  4270. NAPI_FATAL_IF_FAILED(
  4271. status, "CallbackScope::~CallbackScope", "napi_close_callback_scope");
  4272. }
  4273. inline CallbackScope::operator napi_callback_scope() const {
  4274. return _scope;
  4275. }
  4276. inline Napi::Env CallbackScope::Env() const {
  4277. return Napi::Env(_env);
  4278. }
  4279. #endif
  4280. ////////////////////////////////////////////////////////////////////////////////
  4281. // AsyncContext class
  4282. ////////////////////////////////////////////////////////////////////////////////
  4283. inline AsyncContext::AsyncContext(napi_env env, const char* resource_name)
  4284. : AsyncContext(env, resource_name, Object::New(env)) {}
  4285. inline AsyncContext::AsyncContext(napi_env env,
  4286. const char* resource_name,
  4287. const Object& resource)
  4288. : _env(env), _context(nullptr) {
  4289. napi_value resource_id;
  4290. napi_status status = napi_create_string_utf8(
  4291. _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
  4292. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4293. status = napi_async_init(_env, resource, resource_id, &_context);
  4294. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4295. }
  4296. inline AsyncContext::~AsyncContext() {
  4297. if (_context != nullptr) {
  4298. napi_async_destroy(_env, _context);
  4299. _context = nullptr;
  4300. }
  4301. }
  4302. inline AsyncContext::AsyncContext(AsyncContext&& other) {
  4303. _env = other._env;
  4304. other._env = nullptr;
  4305. _context = other._context;
  4306. other._context = nullptr;
  4307. }
  4308. inline AsyncContext& AsyncContext::operator=(AsyncContext&& other) {
  4309. _env = other._env;
  4310. other._env = nullptr;
  4311. _context = other._context;
  4312. other._context = nullptr;
  4313. return *this;
  4314. }
  4315. inline AsyncContext::operator napi_async_context() const {
  4316. return _context;
  4317. }
  4318. inline Napi::Env AsyncContext::Env() const {
  4319. return Napi::Env(_env);
  4320. }
  4321. ////////////////////////////////////////////////////////////////////////////////
  4322. // AsyncWorker class
  4323. ////////////////////////////////////////////////////////////////////////////////
  4324. #if NAPI_HAS_THREADS
  4325. inline AsyncWorker::AsyncWorker(const Function& callback)
  4326. : AsyncWorker(callback, "generic") {}
  4327. inline AsyncWorker::AsyncWorker(const Function& callback,
  4328. const char* resource_name)
  4329. : AsyncWorker(callback, resource_name, Object::New(callback.Env())) {}
  4330. inline AsyncWorker::AsyncWorker(const Function& callback,
  4331. const char* resource_name,
  4332. const Object& resource)
  4333. : AsyncWorker(
  4334. Object::New(callback.Env()), callback, resource_name, resource) {}
  4335. inline AsyncWorker::AsyncWorker(const Object& receiver,
  4336. const Function& callback)
  4337. : AsyncWorker(receiver, callback, "generic") {}
  4338. inline AsyncWorker::AsyncWorker(const Object& receiver,
  4339. const Function& callback,
  4340. const char* resource_name)
  4341. : AsyncWorker(
  4342. receiver, callback, resource_name, Object::New(callback.Env())) {}
  4343. inline AsyncWorker::AsyncWorker(const Object& receiver,
  4344. const Function& callback,
  4345. const char* resource_name,
  4346. const Object& resource)
  4347. : _env(callback.Env()),
  4348. _receiver(Napi::Persistent(receiver)),
  4349. _callback(Napi::Persistent(callback)),
  4350. _suppress_destruct(false) {
  4351. napi_value resource_id;
  4352. napi_status status = napi_create_string_latin1(
  4353. _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
  4354. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4355. status = napi_create_async_work(_env,
  4356. resource,
  4357. resource_id,
  4358. OnAsyncWorkExecute,
  4359. OnAsyncWorkComplete,
  4360. this,
  4361. &_work);
  4362. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4363. }
  4364. inline AsyncWorker::AsyncWorker(Napi::Env env) : AsyncWorker(env, "generic") {}
  4365. inline AsyncWorker::AsyncWorker(Napi::Env env, const char* resource_name)
  4366. : AsyncWorker(env, resource_name, Object::New(env)) {}
  4367. inline AsyncWorker::AsyncWorker(Napi::Env env,
  4368. const char* resource_name,
  4369. const Object& resource)
  4370. : _env(env), _receiver(), _callback(), _suppress_destruct(false) {
  4371. napi_value resource_id;
  4372. napi_status status = napi_create_string_latin1(
  4373. _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
  4374. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4375. status = napi_create_async_work(_env,
  4376. resource,
  4377. resource_id,
  4378. OnAsyncWorkExecute,
  4379. OnAsyncWorkComplete,
  4380. this,
  4381. &_work);
  4382. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4383. }
  4384. inline AsyncWorker::~AsyncWorker() {
  4385. if (_work != nullptr) {
  4386. napi_delete_async_work(_env, _work);
  4387. _work = nullptr;
  4388. }
  4389. }
  4390. inline void AsyncWorker::Destroy() {
  4391. delete this;
  4392. }
  4393. inline AsyncWorker::operator napi_async_work() const {
  4394. return _work;
  4395. }
  4396. inline Napi::Env AsyncWorker::Env() const {
  4397. return Napi::Env(_env);
  4398. }
  4399. inline void AsyncWorker::Queue() {
  4400. napi_status status = napi_queue_async_work(_env, _work);
  4401. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4402. }
  4403. inline void AsyncWorker::Cancel() {
  4404. napi_status status = napi_cancel_async_work(_env, _work);
  4405. NAPI_THROW_IF_FAILED_VOID(_env, status);
  4406. }
  4407. inline ObjectReference& AsyncWorker::Receiver() {
  4408. return _receiver;
  4409. }
  4410. inline FunctionReference& AsyncWorker::Callback() {
  4411. return _callback;
  4412. }
  4413. inline void AsyncWorker::SuppressDestruct() {
  4414. _suppress_destruct = true;
  4415. }
  4416. inline void AsyncWorker::OnOK() {
  4417. if (!_callback.IsEmpty()) {
  4418. _callback.Call(_receiver.Value(), GetResult(_callback.Env()));
  4419. }
  4420. }
  4421. inline void AsyncWorker::OnError(const Error& e) {
  4422. if (!_callback.IsEmpty()) {
  4423. _callback.Call(_receiver.Value(),
  4424. std::initializer_list<napi_value>{e.Value()});
  4425. }
  4426. }
  4427. inline void AsyncWorker::SetError(const std::string& error) {
  4428. _error = error;
  4429. }
  4430. inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
  4431. return {};
  4432. }
  4433. // The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT
  4434. // use it within this method, as it does not run on the JavaScript thread and
  4435. // must not run any method that would cause JavaScript to run. In practice,
  4436. // this means that almost any use of napi_env will be incorrect.
  4437. inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) {
  4438. AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
  4439. self->OnExecute(env);
  4440. }
  4441. // The OnExecute method receives an napi_env argument. However, do NOT
  4442. // use it within this method, as it does not run on the JavaScript thread and
  4443. // must not run any method that would cause JavaScript to run. In practice,
  4444. // this means that almost any use of napi_env will be incorrect.
  4445. inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) {
  4446. #ifdef NAPI_CPP_EXCEPTIONS
  4447. try {
  4448. Execute();
  4449. } catch (const std::exception& e) {
  4450. SetError(e.what());
  4451. }
  4452. #else // NAPI_CPP_EXCEPTIONS
  4453. Execute();
  4454. #endif // NAPI_CPP_EXCEPTIONS
  4455. }
  4456. inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
  4457. napi_status status,
  4458. void* asyncworker) {
  4459. AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
  4460. self->OnWorkComplete(env, status);
  4461. }
  4462. inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
  4463. if (status != napi_cancelled) {
  4464. HandleScope scope(_env);
  4465. details::WrapCallback([&] {
  4466. if (_error.size() == 0) {
  4467. OnOK();
  4468. } else {
  4469. OnError(Error::New(_env, _error));
  4470. }
  4471. return nullptr;
  4472. });
  4473. }
  4474. if (!_suppress_destruct) {
  4475. Destroy();
  4476. }
  4477. }
  4478. #endif // NAPI_HAS_THREADS
  4479. #if (NAPI_VERSION > 3 && NAPI_HAS_THREADS)
  4480. ////////////////////////////////////////////////////////////////////////////////
  4481. // TypedThreadSafeFunction<ContextType,DataType,CallJs> class
  4482. ////////////////////////////////////////////////////////////////////////////////
  4483. // Starting with NAPI 5, the JavaScript function `func` parameter of
  4484. // `napi_create_threadsafe_function` is optional.
  4485. #if NAPI_VERSION > 4
  4486. // static, with Callback [missing] Resource [missing] Finalizer [missing]
  4487. template <typename ContextType,
  4488. typename DataType,
  4489. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4490. template <typename ResourceString>
  4491. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4492. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4493. napi_env env,
  4494. ResourceString resourceName,
  4495. size_t maxQueueSize,
  4496. size_t initialThreadCount,
  4497. ContextType* context) {
  4498. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4499. napi_status status =
  4500. napi_create_threadsafe_function(env,
  4501. nullptr,
  4502. nullptr,
  4503. String::From(env, resourceName),
  4504. maxQueueSize,
  4505. initialThreadCount,
  4506. nullptr,
  4507. nullptr,
  4508. context,
  4509. CallJsInternal,
  4510. &tsfn._tsfn);
  4511. if (status != napi_ok) {
  4512. NAPI_THROW_IF_FAILED(
  4513. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4514. }
  4515. return tsfn;
  4516. }
  4517. // static, with Callback [missing] Resource [passed] Finalizer [missing]
  4518. template <typename ContextType,
  4519. typename DataType,
  4520. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4521. template <typename ResourceString>
  4522. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4523. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4524. napi_env env,
  4525. const Object& resource,
  4526. ResourceString resourceName,
  4527. size_t maxQueueSize,
  4528. size_t initialThreadCount,
  4529. ContextType* context) {
  4530. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4531. napi_status status =
  4532. napi_create_threadsafe_function(env,
  4533. nullptr,
  4534. resource,
  4535. String::From(env, resourceName),
  4536. maxQueueSize,
  4537. initialThreadCount,
  4538. nullptr,
  4539. nullptr,
  4540. context,
  4541. CallJsInternal,
  4542. &tsfn._tsfn);
  4543. if (status != napi_ok) {
  4544. NAPI_THROW_IF_FAILED(
  4545. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4546. }
  4547. return tsfn;
  4548. }
  4549. // static, with Callback [missing] Resource [missing] Finalizer [passed]
  4550. template <typename ContextType,
  4551. typename DataType,
  4552. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4553. template <typename ResourceString,
  4554. typename Finalizer,
  4555. typename FinalizerDataType>
  4556. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4557. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4558. napi_env env,
  4559. ResourceString resourceName,
  4560. size_t maxQueueSize,
  4561. size_t initialThreadCount,
  4562. ContextType* context,
  4563. Finalizer finalizeCallback,
  4564. FinalizerDataType* data) {
  4565. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4566. auto* finalizeData = new details::
  4567. ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
  4568. {data, finalizeCallback});
  4569. napi_status status = napi_create_threadsafe_function(
  4570. env,
  4571. nullptr,
  4572. nullptr,
  4573. String::From(env, resourceName),
  4574. maxQueueSize,
  4575. initialThreadCount,
  4576. finalizeData,
  4577. details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
  4578. FinalizeFinalizeWrapperWithDataAndContext,
  4579. context,
  4580. CallJsInternal,
  4581. &tsfn._tsfn);
  4582. if (status != napi_ok) {
  4583. delete finalizeData;
  4584. NAPI_THROW_IF_FAILED(
  4585. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4586. }
  4587. return tsfn;
  4588. }
  4589. // static, with Callback [missing] Resource [passed] Finalizer [passed]
  4590. template <typename ContextType,
  4591. typename DataType,
  4592. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4593. template <typename ResourceString,
  4594. typename Finalizer,
  4595. typename FinalizerDataType>
  4596. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4597. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4598. napi_env env,
  4599. const Object& resource,
  4600. ResourceString resourceName,
  4601. size_t maxQueueSize,
  4602. size_t initialThreadCount,
  4603. ContextType* context,
  4604. Finalizer finalizeCallback,
  4605. FinalizerDataType* data) {
  4606. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4607. auto* finalizeData = new details::
  4608. ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
  4609. {data, finalizeCallback});
  4610. napi_status status = napi_create_threadsafe_function(
  4611. env,
  4612. nullptr,
  4613. resource,
  4614. String::From(env, resourceName),
  4615. maxQueueSize,
  4616. initialThreadCount,
  4617. finalizeData,
  4618. details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
  4619. FinalizeFinalizeWrapperWithDataAndContext,
  4620. context,
  4621. CallJsInternal,
  4622. &tsfn._tsfn);
  4623. if (status != napi_ok) {
  4624. delete finalizeData;
  4625. NAPI_THROW_IF_FAILED(
  4626. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4627. }
  4628. return tsfn;
  4629. }
  4630. #endif
  4631. // static, with Callback [passed] Resource [missing] Finalizer [missing]
  4632. template <typename ContextType,
  4633. typename DataType,
  4634. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4635. template <typename ResourceString>
  4636. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4637. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4638. napi_env env,
  4639. const Function& callback,
  4640. ResourceString resourceName,
  4641. size_t maxQueueSize,
  4642. size_t initialThreadCount,
  4643. ContextType* context) {
  4644. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4645. napi_status status =
  4646. napi_create_threadsafe_function(env,
  4647. callback,
  4648. nullptr,
  4649. String::From(env, resourceName),
  4650. maxQueueSize,
  4651. initialThreadCount,
  4652. nullptr,
  4653. nullptr,
  4654. context,
  4655. CallJsInternal,
  4656. &tsfn._tsfn);
  4657. if (status != napi_ok) {
  4658. NAPI_THROW_IF_FAILED(
  4659. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4660. }
  4661. return tsfn;
  4662. }
  4663. // static, with Callback [passed] Resource [passed] Finalizer [missing]
  4664. template <typename ContextType,
  4665. typename DataType,
  4666. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4667. template <typename ResourceString>
  4668. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4669. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4670. napi_env env,
  4671. const Function& callback,
  4672. const Object& resource,
  4673. ResourceString resourceName,
  4674. size_t maxQueueSize,
  4675. size_t initialThreadCount,
  4676. ContextType* context) {
  4677. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4678. napi_status status =
  4679. napi_create_threadsafe_function(env,
  4680. callback,
  4681. resource,
  4682. String::From(env, resourceName),
  4683. maxQueueSize,
  4684. initialThreadCount,
  4685. nullptr,
  4686. nullptr,
  4687. context,
  4688. CallJsInternal,
  4689. &tsfn._tsfn);
  4690. if (status != napi_ok) {
  4691. NAPI_THROW_IF_FAILED(
  4692. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4693. }
  4694. return tsfn;
  4695. }
  4696. // static, with Callback [passed] Resource [missing] Finalizer [passed]
  4697. template <typename ContextType,
  4698. typename DataType,
  4699. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4700. template <typename ResourceString,
  4701. typename Finalizer,
  4702. typename FinalizerDataType>
  4703. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4704. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4705. napi_env env,
  4706. const Function& callback,
  4707. ResourceString resourceName,
  4708. size_t maxQueueSize,
  4709. size_t initialThreadCount,
  4710. ContextType* context,
  4711. Finalizer finalizeCallback,
  4712. FinalizerDataType* data) {
  4713. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4714. auto* finalizeData = new details::
  4715. ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
  4716. {data, finalizeCallback});
  4717. napi_status status = napi_create_threadsafe_function(
  4718. env,
  4719. callback,
  4720. nullptr,
  4721. String::From(env, resourceName),
  4722. maxQueueSize,
  4723. initialThreadCount,
  4724. finalizeData,
  4725. details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
  4726. FinalizeFinalizeWrapperWithDataAndContext,
  4727. context,
  4728. CallJsInternal,
  4729. &tsfn._tsfn);
  4730. if (status != napi_ok) {
  4731. delete finalizeData;
  4732. NAPI_THROW_IF_FAILED(
  4733. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4734. }
  4735. return tsfn;
  4736. }
  4737. // static, with: Callback [passed] Resource [passed] Finalizer [passed]
  4738. template <typename ContextType,
  4739. typename DataType,
  4740. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4741. template <typename CallbackType,
  4742. typename ResourceString,
  4743. typename Finalizer,
  4744. typename FinalizerDataType>
  4745. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
  4746. TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
  4747. napi_env env,
  4748. CallbackType callback,
  4749. const Object& resource,
  4750. ResourceString resourceName,
  4751. size_t maxQueueSize,
  4752. size_t initialThreadCount,
  4753. ContextType* context,
  4754. Finalizer finalizeCallback,
  4755. FinalizerDataType* data) {
  4756. TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
  4757. auto* finalizeData = new details::
  4758. ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
  4759. {data, finalizeCallback});
  4760. napi_status status = napi_create_threadsafe_function(
  4761. env,
  4762. details::DefaultCallbackWrapper<
  4763. CallbackType,
  4764. TypedThreadSafeFunction<ContextType, DataType, CallJs>>(env,
  4765. callback),
  4766. resource,
  4767. String::From(env, resourceName),
  4768. maxQueueSize,
  4769. initialThreadCount,
  4770. finalizeData,
  4771. details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
  4772. FinalizeFinalizeWrapperWithDataAndContext,
  4773. context,
  4774. CallJsInternal,
  4775. &tsfn._tsfn);
  4776. if (status != napi_ok) {
  4777. delete finalizeData;
  4778. NAPI_THROW_IF_FAILED(
  4779. env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
  4780. }
  4781. return tsfn;
  4782. }
  4783. template <typename ContextType,
  4784. typename DataType,
  4785. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4786. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>::
  4787. TypedThreadSafeFunction()
  4788. : _tsfn() {}
  4789. template <typename ContextType,
  4790. typename DataType,
  4791. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4792. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>::
  4793. TypedThreadSafeFunction(napi_threadsafe_function tsfn)
  4794. : _tsfn(tsfn) {}
  4795. template <typename ContextType,
  4796. typename DataType,
  4797. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4798. inline TypedThreadSafeFunction<ContextType, DataType, CallJs>::
  4799. operator napi_threadsafe_function() const {
  4800. return _tsfn;
  4801. }
  4802. template <typename ContextType,
  4803. typename DataType,
  4804. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4805. inline napi_status
  4806. TypedThreadSafeFunction<ContextType, DataType, CallJs>::BlockingCall(
  4807. DataType* data) const {
  4808. return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
  4809. }
  4810. template <typename ContextType,
  4811. typename DataType,
  4812. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4813. inline napi_status
  4814. TypedThreadSafeFunction<ContextType, DataType, CallJs>::NonBlockingCall(
  4815. DataType* data) const {
  4816. return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
  4817. }
  4818. template <typename ContextType,
  4819. typename DataType,
  4820. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4821. inline void TypedThreadSafeFunction<ContextType, DataType, CallJs>::Ref(
  4822. napi_env env) const {
  4823. if (_tsfn != nullptr) {
  4824. napi_status status = napi_ref_threadsafe_function(env, _tsfn);
  4825. NAPI_THROW_IF_FAILED_VOID(env, status);
  4826. }
  4827. }
  4828. template <typename ContextType,
  4829. typename DataType,
  4830. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4831. inline void TypedThreadSafeFunction<ContextType, DataType, CallJs>::Unref(
  4832. napi_env env) const {
  4833. if (_tsfn != nullptr) {
  4834. napi_status status = napi_unref_threadsafe_function(env, _tsfn);
  4835. NAPI_THROW_IF_FAILED_VOID(env, status);
  4836. }
  4837. }
  4838. template <typename ContextType,
  4839. typename DataType,
  4840. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4841. inline napi_status
  4842. TypedThreadSafeFunction<ContextType, DataType, CallJs>::Acquire() const {
  4843. return napi_acquire_threadsafe_function(_tsfn);
  4844. }
  4845. template <typename ContextType,
  4846. typename DataType,
  4847. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4848. inline napi_status
  4849. TypedThreadSafeFunction<ContextType, DataType, CallJs>::Release() const {
  4850. return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
  4851. }
  4852. template <typename ContextType,
  4853. typename DataType,
  4854. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4855. inline napi_status
  4856. TypedThreadSafeFunction<ContextType, DataType, CallJs>::Abort() const {
  4857. return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
  4858. }
  4859. template <typename ContextType,
  4860. typename DataType,
  4861. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4862. inline ContextType*
  4863. TypedThreadSafeFunction<ContextType, DataType, CallJs>::GetContext() const {
  4864. void* context;
  4865. napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
  4866. NAPI_FATAL_IF_FAILED(status,
  4867. "TypedThreadSafeFunction::GetContext",
  4868. "napi_get_threadsafe_function_context");
  4869. return static_cast<ContextType*>(context);
  4870. }
  4871. // static
  4872. template <typename ContextType,
  4873. typename DataType,
  4874. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4875. void TypedThreadSafeFunction<ContextType, DataType, CallJs>::CallJsInternal(
  4876. napi_env env, napi_value jsCallback, void* context, void* data) {
  4877. details::CallJsWrapper<ContextType, DataType, decltype(CallJs), CallJs>(
  4878. env, jsCallback, context, data);
  4879. }
  4880. #if NAPI_VERSION == 4
  4881. // static
  4882. template <typename ContextType,
  4883. typename DataType,
  4884. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4885. Napi::Function
  4886. TypedThreadSafeFunction<ContextType, DataType, CallJs>::EmptyFunctionFactory(
  4887. Napi::Env env) {
  4888. return Napi::Function::New(env, [](const CallbackInfo& cb) {});
  4889. }
  4890. // static
  4891. template <typename ContextType,
  4892. typename DataType,
  4893. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4894. Napi::Function
  4895. TypedThreadSafeFunction<ContextType, DataType, CallJs>::FunctionOrEmpty(
  4896. Napi::Env env, Napi::Function& callback) {
  4897. if (callback.IsEmpty()) {
  4898. return EmptyFunctionFactory(env);
  4899. }
  4900. return callback;
  4901. }
  4902. #else
  4903. // static
  4904. template <typename ContextType,
  4905. typename DataType,
  4906. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4907. std::nullptr_t
  4908. TypedThreadSafeFunction<ContextType, DataType, CallJs>::EmptyFunctionFactory(
  4909. Napi::Env /*env*/) {
  4910. return nullptr;
  4911. }
  4912. // static
  4913. template <typename ContextType,
  4914. typename DataType,
  4915. void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
  4916. Napi::Function
  4917. TypedThreadSafeFunction<ContextType, DataType, CallJs>::FunctionOrEmpty(
  4918. Napi::Env /*env*/, Napi::Function& callback) {
  4919. return callback;
  4920. }
  4921. #endif
  4922. ////////////////////////////////////////////////////////////////////////////////
  4923. // ThreadSafeFunction class
  4924. ////////////////////////////////////////////////////////////////////////////////
  4925. // static
  4926. template <typename ResourceString>
  4927. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  4928. const Function& callback,
  4929. ResourceString resourceName,
  4930. size_t maxQueueSize,
  4931. size_t initialThreadCount) {
  4932. return New(
  4933. env, callback, Object(), resourceName, maxQueueSize, initialThreadCount);
  4934. }
  4935. // static
  4936. template <typename ResourceString, typename ContextType>
  4937. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  4938. const Function& callback,
  4939. ResourceString resourceName,
  4940. size_t maxQueueSize,
  4941. size_t initialThreadCount,
  4942. ContextType* context) {
  4943. return New(env,
  4944. callback,
  4945. Object(),
  4946. resourceName,
  4947. maxQueueSize,
  4948. initialThreadCount,
  4949. context);
  4950. }
  4951. // static
  4952. template <typename ResourceString, typename Finalizer>
  4953. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  4954. const Function& callback,
  4955. ResourceString resourceName,
  4956. size_t maxQueueSize,
  4957. size_t initialThreadCount,
  4958. Finalizer finalizeCallback) {
  4959. return New(env,
  4960. callback,
  4961. Object(),
  4962. resourceName,
  4963. maxQueueSize,
  4964. initialThreadCount,
  4965. finalizeCallback);
  4966. }
  4967. // static
  4968. template <typename ResourceString,
  4969. typename Finalizer,
  4970. typename FinalizerDataType>
  4971. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  4972. const Function& callback,
  4973. ResourceString resourceName,
  4974. size_t maxQueueSize,
  4975. size_t initialThreadCount,
  4976. Finalizer finalizeCallback,
  4977. FinalizerDataType* data) {
  4978. return New(env,
  4979. callback,
  4980. Object(),
  4981. resourceName,
  4982. maxQueueSize,
  4983. initialThreadCount,
  4984. finalizeCallback,
  4985. data);
  4986. }
  4987. // static
  4988. template <typename ResourceString, typename ContextType, typename Finalizer>
  4989. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  4990. const Function& callback,
  4991. ResourceString resourceName,
  4992. size_t maxQueueSize,
  4993. size_t initialThreadCount,
  4994. ContextType* context,
  4995. Finalizer finalizeCallback) {
  4996. return New(env,
  4997. callback,
  4998. Object(),
  4999. resourceName,
  5000. maxQueueSize,
  5001. initialThreadCount,
  5002. context,
  5003. finalizeCallback);
  5004. }
  5005. // static
  5006. template <typename ResourceString,
  5007. typename ContextType,
  5008. typename Finalizer,
  5009. typename FinalizerDataType>
  5010. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5011. const Function& callback,
  5012. ResourceString resourceName,
  5013. size_t maxQueueSize,
  5014. size_t initialThreadCount,
  5015. ContextType* context,
  5016. Finalizer finalizeCallback,
  5017. FinalizerDataType* data) {
  5018. return New(env,
  5019. callback,
  5020. Object(),
  5021. resourceName,
  5022. maxQueueSize,
  5023. initialThreadCount,
  5024. context,
  5025. finalizeCallback,
  5026. data);
  5027. }
  5028. // static
  5029. template <typename ResourceString>
  5030. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5031. const Function& callback,
  5032. const Object& resource,
  5033. ResourceString resourceName,
  5034. size_t maxQueueSize,
  5035. size_t initialThreadCount) {
  5036. return New(env,
  5037. callback,
  5038. resource,
  5039. resourceName,
  5040. maxQueueSize,
  5041. initialThreadCount,
  5042. static_cast<void*>(nullptr) /* context */);
  5043. }
  5044. // static
  5045. template <typename ResourceString, typename ContextType>
  5046. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5047. const Function& callback,
  5048. const Object& resource,
  5049. ResourceString resourceName,
  5050. size_t maxQueueSize,
  5051. size_t initialThreadCount,
  5052. ContextType* context) {
  5053. return New(env,
  5054. callback,
  5055. resource,
  5056. resourceName,
  5057. maxQueueSize,
  5058. initialThreadCount,
  5059. context,
  5060. [](Env, ContextType*) {} /* empty finalizer */);
  5061. }
  5062. // static
  5063. template <typename ResourceString, typename Finalizer>
  5064. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5065. const Function& callback,
  5066. const Object& resource,
  5067. ResourceString resourceName,
  5068. size_t maxQueueSize,
  5069. size_t initialThreadCount,
  5070. Finalizer finalizeCallback) {
  5071. return New(env,
  5072. callback,
  5073. resource,
  5074. resourceName,
  5075. maxQueueSize,
  5076. initialThreadCount,
  5077. static_cast<void*>(nullptr) /* context */,
  5078. finalizeCallback,
  5079. static_cast<void*>(nullptr) /* data */,
  5080. details::ThreadSafeFinalize<void, Finalizer>::Wrapper);
  5081. }
  5082. // static
  5083. template <typename ResourceString,
  5084. typename Finalizer,
  5085. typename FinalizerDataType>
  5086. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5087. const Function& callback,
  5088. const Object& resource,
  5089. ResourceString resourceName,
  5090. size_t maxQueueSize,
  5091. size_t initialThreadCount,
  5092. Finalizer finalizeCallback,
  5093. FinalizerDataType* data) {
  5094. return New(env,
  5095. callback,
  5096. resource,
  5097. resourceName,
  5098. maxQueueSize,
  5099. initialThreadCount,
  5100. static_cast<void*>(nullptr) /* context */,
  5101. finalizeCallback,
  5102. data,
  5103. details::ThreadSafeFinalize<void, Finalizer, FinalizerDataType>::
  5104. FinalizeWrapperWithData);
  5105. }
  5106. // static
  5107. template <typename ResourceString, typename ContextType, typename Finalizer>
  5108. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5109. const Function& callback,
  5110. const Object& resource,
  5111. ResourceString resourceName,
  5112. size_t maxQueueSize,
  5113. size_t initialThreadCount,
  5114. ContextType* context,
  5115. Finalizer finalizeCallback) {
  5116. return New(
  5117. env,
  5118. callback,
  5119. resource,
  5120. resourceName,
  5121. maxQueueSize,
  5122. initialThreadCount,
  5123. context,
  5124. finalizeCallback,
  5125. static_cast<void*>(nullptr) /* data */,
  5126. details::ThreadSafeFinalize<ContextType,
  5127. Finalizer>::FinalizeWrapperWithContext);
  5128. }
  5129. // static
  5130. template <typename ResourceString,
  5131. typename ContextType,
  5132. typename Finalizer,
  5133. typename FinalizerDataType>
  5134. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5135. const Function& callback,
  5136. const Object& resource,
  5137. ResourceString resourceName,
  5138. size_t maxQueueSize,
  5139. size_t initialThreadCount,
  5140. ContextType* context,
  5141. Finalizer finalizeCallback,
  5142. FinalizerDataType* data) {
  5143. return New(
  5144. env,
  5145. callback,
  5146. resource,
  5147. resourceName,
  5148. maxQueueSize,
  5149. initialThreadCount,
  5150. context,
  5151. finalizeCallback,
  5152. data,
  5153. details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
  5154. FinalizeFinalizeWrapperWithDataAndContext);
  5155. }
  5156. inline ThreadSafeFunction::ThreadSafeFunction() : _tsfn() {}
  5157. inline ThreadSafeFunction::ThreadSafeFunction(napi_threadsafe_function tsfn)
  5158. : _tsfn(tsfn) {}
  5159. inline ThreadSafeFunction::operator napi_threadsafe_function() const {
  5160. return _tsfn;
  5161. }
  5162. inline napi_status ThreadSafeFunction::BlockingCall() const {
  5163. return CallInternal(nullptr, napi_tsfn_blocking);
  5164. }
  5165. template <>
  5166. inline napi_status ThreadSafeFunction::BlockingCall(void* data) const {
  5167. return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
  5168. }
  5169. template <typename Callback>
  5170. inline napi_status ThreadSafeFunction::BlockingCall(Callback callback) const {
  5171. return CallInternal(new CallbackWrapper(callback), napi_tsfn_blocking);
  5172. }
  5173. template <typename DataType, typename Callback>
  5174. inline napi_status ThreadSafeFunction::BlockingCall(DataType* data,
  5175. Callback callback) const {
  5176. auto wrapper = [data, callback](Env env, Function jsCallback) {
  5177. callback(env, jsCallback, data);
  5178. };
  5179. return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_blocking);
  5180. }
  5181. inline napi_status ThreadSafeFunction::NonBlockingCall() const {
  5182. return CallInternal(nullptr, napi_tsfn_nonblocking);
  5183. }
  5184. template <>
  5185. inline napi_status ThreadSafeFunction::NonBlockingCall(void* data) const {
  5186. return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
  5187. }
  5188. template <typename Callback>
  5189. inline napi_status ThreadSafeFunction::NonBlockingCall(
  5190. Callback callback) const {
  5191. return CallInternal(new CallbackWrapper(callback), napi_tsfn_nonblocking);
  5192. }
  5193. template <typename DataType, typename Callback>
  5194. inline napi_status ThreadSafeFunction::NonBlockingCall(
  5195. DataType* data, Callback callback) const {
  5196. auto wrapper = [data, callback](Env env, Function jsCallback) {
  5197. callback(env, jsCallback, data);
  5198. };
  5199. return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
  5200. }
  5201. inline void ThreadSafeFunction::Ref(napi_env env) const {
  5202. if (_tsfn != nullptr) {
  5203. napi_status status = napi_ref_threadsafe_function(env, _tsfn);
  5204. NAPI_THROW_IF_FAILED_VOID(env, status);
  5205. }
  5206. }
  5207. inline void ThreadSafeFunction::Unref(napi_env env) const {
  5208. if (_tsfn != nullptr) {
  5209. napi_status status = napi_unref_threadsafe_function(env, _tsfn);
  5210. NAPI_THROW_IF_FAILED_VOID(env, status);
  5211. }
  5212. }
  5213. inline napi_status ThreadSafeFunction::Acquire() const {
  5214. return napi_acquire_threadsafe_function(_tsfn);
  5215. }
  5216. inline napi_status ThreadSafeFunction::Release() const {
  5217. return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
  5218. }
  5219. inline napi_status ThreadSafeFunction::Abort() const {
  5220. return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
  5221. }
  5222. inline ThreadSafeFunction::ConvertibleContext ThreadSafeFunction::GetContext()
  5223. const {
  5224. void* context;
  5225. napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
  5226. NAPI_FATAL_IF_FAILED(status,
  5227. "ThreadSafeFunction::GetContext",
  5228. "napi_get_threadsafe_function_context");
  5229. return ConvertibleContext({context});
  5230. }
  5231. // static
  5232. template <typename ResourceString,
  5233. typename ContextType,
  5234. typename Finalizer,
  5235. typename FinalizerDataType>
  5236. inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
  5237. const Function& callback,
  5238. const Object& resource,
  5239. ResourceString resourceName,
  5240. size_t maxQueueSize,
  5241. size_t initialThreadCount,
  5242. ContextType* context,
  5243. Finalizer finalizeCallback,
  5244. FinalizerDataType* data,
  5245. napi_finalize wrapper) {
  5246. static_assert(details::can_make_string<ResourceString>::value ||
  5247. std::is_convertible<ResourceString, napi_value>::value,
  5248. "Resource name should be convertible to the string type");
  5249. ThreadSafeFunction tsfn;
  5250. auto* finalizeData = new details::
  5251. ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
  5252. {data, finalizeCallback});
  5253. napi_status status =
  5254. napi_create_threadsafe_function(env,
  5255. callback,
  5256. resource,
  5257. Value::From(env, resourceName),
  5258. maxQueueSize,
  5259. initialThreadCount,
  5260. finalizeData,
  5261. wrapper,
  5262. context,
  5263. CallJS,
  5264. &tsfn._tsfn);
  5265. if (status != napi_ok) {
  5266. delete finalizeData;
  5267. NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
  5268. }
  5269. return tsfn;
  5270. }
  5271. inline napi_status ThreadSafeFunction::CallInternal(
  5272. CallbackWrapper* callbackWrapper,
  5273. napi_threadsafe_function_call_mode mode) const {
  5274. napi_status status =
  5275. napi_call_threadsafe_function(_tsfn, callbackWrapper, mode);
  5276. if (status != napi_ok && callbackWrapper != nullptr) {
  5277. delete callbackWrapper;
  5278. }
  5279. return status;
  5280. }
  5281. // static
  5282. inline void ThreadSafeFunction::CallJS(napi_env env,
  5283. napi_value jsCallback,
  5284. void* /* context */,
  5285. void* data) {
  5286. if (env == nullptr && jsCallback == nullptr) {
  5287. return;
  5288. }
  5289. details::WrapVoidCallback([&]() {
  5290. if (data != nullptr) {
  5291. auto* callbackWrapper = static_cast<CallbackWrapper*>(data);
  5292. (*callbackWrapper)(env, Function(env, jsCallback));
  5293. delete callbackWrapper;
  5294. } else if (jsCallback != nullptr) {
  5295. Function(env, jsCallback).Call({});
  5296. }
  5297. });
  5298. }
  5299. ////////////////////////////////////////////////////////////////////////////////
  5300. // Async Progress Worker Base class
  5301. ////////////////////////////////////////////////////////////////////////////////
  5302. template <typename DataType>
  5303. inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(
  5304. const Object& receiver,
  5305. const Function& callback,
  5306. const char* resource_name,
  5307. const Object& resource,
  5308. size_t queue_size)
  5309. : AsyncWorker(receiver, callback, resource_name, resource) {
  5310. // Fill all possible arguments to work around ambiguous
  5311. // ThreadSafeFunction::New signatures.
  5312. _tsfn = ThreadSafeFunction::New(callback.Env(),
  5313. callback,
  5314. resource,
  5315. resource_name,
  5316. queue_size,
  5317. /** initialThreadCount */ 1,
  5318. /** context */ this,
  5319. OnThreadSafeFunctionFinalize,
  5320. /** finalizeData */ this);
  5321. }
  5322. #if NAPI_VERSION > 4
  5323. template <typename DataType>
  5324. inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(
  5325. Napi::Env env,
  5326. const char* resource_name,
  5327. const Object& resource,
  5328. size_t queue_size)
  5329. : AsyncWorker(env, resource_name, resource) {
  5330. // TODO: Once the changes to make the callback optional for threadsafe
  5331. // functions are available on all versions we can remove the dummy Function
  5332. // here.
  5333. Function callback;
  5334. // Fill all possible arguments to work around ambiguous
  5335. // ThreadSafeFunction::New signatures.
  5336. _tsfn = ThreadSafeFunction::New(env,
  5337. callback,
  5338. resource,
  5339. resource_name,
  5340. queue_size,
  5341. /** initialThreadCount */ 1,
  5342. /** context */ this,
  5343. OnThreadSafeFunctionFinalize,
  5344. /** finalizeData */ this);
  5345. }
  5346. #endif
  5347. template <typename DataType>
  5348. inline AsyncProgressWorkerBase<DataType>::~AsyncProgressWorkerBase() {
  5349. // Abort pending tsfn call.
  5350. // Don't send progress events after we've already completed.
  5351. // It's ok to call ThreadSafeFunction::Abort and ThreadSafeFunction::Release
  5352. // duplicated.
  5353. _tsfn.Abort();
  5354. }
  5355. template <typename DataType>
  5356. inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(
  5357. Napi::Env /* env */, Napi::Function /* jsCallback */, void* data) {
  5358. ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
  5359. tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
  5360. delete tsd;
  5361. }
  5362. template <typename DataType>
  5363. inline napi_status AsyncProgressWorkerBase<DataType>::NonBlockingCall(
  5364. DataType* data) {
  5365. auto tsd = new AsyncProgressWorkerBase::ThreadSafeData(this, data);
  5366. auto ret = _tsfn.NonBlockingCall(tsd, OnAsyncWorkProgress);
  5367. if (ret != napi_ok) {
  5368. delete tsd;
  5369. }
  5370. return ret;
  5371. }
  5372. template <typename DataType>
  5373. inline void AsyncProgressWorkerBase<DataType>::OnWorkComplete(
  5374. Napi::Env /* env */, napi_status status) {
  5375. _work_completed = true;
  5376. _complete_status = status;
  5377. _tsfn.Release();
  5378. }
  5379. template <typename DataType>
  5380. inline void AsyncProgressWorkerBase<DataType>::OnThreadSafeFunctionFinalize(
  5381. Napi::Env env, void* /* data */, AsyncProgressWorkerBase* context) {
  5382. if (context->_work_completed) {
  5383. context->AsyncWorker::OnWorkComplete(env, context->_complete_status);
  5384. }
  5385. }
  5386. ////////////////////////////////////////////////////////////////////////////////
  5387. // Async Progress Worker class
  5388. ////////////////////////////////////////////////////////////////////////////////
  5389. template <class T>
  5390. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback)
  5391. : AsyncProgressWorker(callback, "generic") {}
  5392. template <class T>
  5393. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
  5394. const char* resource_name)
  5395. : AsyncProgressWorker(
  5396. callback, resource_name, Object::New(callback.Env())) {}
  5397. template <class T>
  5398. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
  5399. const char* resource_name,
  5400. const Object& resource)
  5401. : AsyncProgressWorker(
  5402. Object::New(callback.Env()), callback, resource_name, resource) {}
  5403. template <class T>
  5404. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
  5405. const Function& callback)
  5406. : AsyncProgressWorker(receiver, callback, "generic") {}
  5407. template <class T>
  5408. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
  5409. const Function& callback,
  5410. const char* resource_name)
  5411. : AsyncProgressWorker(
  5412. receiver, callback, resource_name, Object::New(callback.Env())) {}
  5413. template <class T>
  5414. inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
  5415. const Function& callback,
  5416. const char* resource_name,
  5417. const Object& resource)
  5418. : AsyncProgressWorkerBase(receiver, callback, resource_name, resource),
  5419. _asyncdata(nullptr),
  5420. _asyncsize(0),
  5421. _signaled(false) {}
  5422. #if NAPI_VERSION > 4
  5423. template <class T>
  5424. inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
  5425. : AsyncProgressWorker(env, "generic") {}
  5426. template <class T>
  5427. inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
  5428. const char* resource_name)
  5429. : AsyncProgressWorker(env, resource_name, Object::New(env)) {}
  5430. template <class T>
  5431. inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
  5432. const char* resource_name,
  5433. const Object& resource)
  5434. : AsyncProgressWorkerBase(env, resource_name, resource),
  5435. _asyncdata(nullptr),
  5436. _asyncsize(0) {}
  5437. #endif
  5438. template <class T>
  5439. inline AsyncProgressWorker<T>::~AsyncProgressWorker() {
  5440. {
  5441. std::lock_guard<std::mutex> lock(this->_mutex);
  5442. _asyncdata = nullptr;
  5443. _asyncsize = 0;
  5444. }
  5445. }
  5446. template <class T>
  5447. inline void AsyncProgressWorker<T>::Execute() {
  5448. ExecutionProgress progress(this);
  5449. Execute(progress);
  5450. }
  5451. template <class T>
  5452. inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
  5453. T* data;
  5454. size_t size;
  5455. bool signaled;
  5456. {
  5457. std::lock_guard<std::mutex> lock(this->_mutex);
  5458. data = this->_asyncdata;
  5459. size = this->_asyncsize;
  5460. signaled = this->_signaled;
  5461. this->_asyncdata = nullptr;
  5462. this->_asyncsize = 0;
  5463. this->_signaled = false;
  5464. }
  5465. /**
  5466. * The callback of ThreadSafeFunction is not been invoked immediately on the
  5467. * callback of uv_async_t (uv io poll), rather the callback of TSFN is
  5468. * invoked on the right next uv idle callback. There are chances that during
  5469. * the deferring the signal of uv_async_t is been sent again, i.e. potential
  5470. * not coalesced two calls of the TSFN callback.
  5471. */
  5472. if (data == nullptr && !signaled) {
  5473. return;
  5474. }
  5475. this->OnProgress(data, size);
  5476. delete[] data;
  5477. }
  5478. template <class T>
  5479. inline void AsyncProgressWorker<T>::SendProgress_(const T* data, size_t count) {
  5480. T* new_data = new T[count];
  5481. std::copy(data, data + count, new_data);
  5482. T* old_data;
  5483. {
  5484. std::lock_guard<std::mutex> lock(this->_mutex);
  5485. old_data = _asyncdata;
  5486. _asyncdata = new_data;
  5487. _asyncsize = count;
  5488. _signaled = false;
  5489. }
  5490. this->NonBlockingCall(nullptr);
  5491. delete[] old_data;
  5492. }
  5493. template <class T>
  5494. inline void AsyncProgressWorker<T>::Signal() {
  5495. {
  5496. std::lock_guard<std::mutex> lock(this->_mutex);
  5497. _signaled = true;
  5498. }
  5499. this->NonBlockingCall(static_cast<T*>(nullptr));
  5500. }
  5501. template <class T>
  5502. inline void AsyncProgressWorker<T>::ExecutionProgress::Signal() const {
  5503. this->_worker->Signal();
  5504. }
  5505. template <class T>
  5506. inline void AsyncProgressWorker<T>::ExecutionProgress::Send(
  5507. const T* data, size_t count) const {
  5508. _worker->SendProgress_(data, count);
  5509. }
  5510. ////////////////////////////////////////////////////////////////////////////////
  5511. // Async Progress Queue Worker class
  5512. ////////////////////////////////////////////////////////////////////////////////
  5513. template <class T>
  5514. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5515. const Function& callback)
  5516. : AsyncProgressQueueWorker(callback, "generic") {}
  5517. template <class T>
  5518. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5519. const Function& callback, const char* resource_name)
  5520. : AsyncProgressQueueWorker(
  5521. callback, resource_name, Object::New(callback.Env())) {}
  5522. template <class T>
  5523. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5524. const Function& callback, const char* resource_name, const Object& resource)
  5525. : AsyncProgressQueueWorker(
  5526. Object::New(callback.Env()), callback, resource_name, resource) {}
  5527. template <class T>
  5528. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5529. const Object& receiver, const Function& callback)
  5530. : AsyncProgressQueueWorker(receiver, callback, "generic") {}
  5531. template <class T>
  5532. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5533. const Object& receiver, const Function& callback, const char* resource_name)
  5534. : AsyncProgressQueueWorker(
  5535. receiver, callback, resource_name, Object::New(callback.Env())) {}
  5536. template <class T>
  5537. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5538. const Object& receiver,
  5539. const Function& callback,
  5540. const char* resource_name,
  5541. const Object& resource)
  5542. : AsyncProgressWorkerBase<std::pair<T*, size_t>>(
  5543. receiver,
  5544. callback,
  5545. resource_name,
  5546. resource,
  5547. /** unlimited queue size */ 0) {}
  5548. #if NAPI_VERSION > 4
  5549. template <class T>
  5550. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env)
  5551. : AsyncProgressQueueWorker(env, "generic") {}
  5552. template <class T>
  5553. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5554. Napi::Env env, const char* resource_name)
  5555. : AsyncProgressQueueWorker(env, resource_name, Object::New(env)) {}
  5556. template <class T>
  5557. inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(
  5558. Napi::Env env, const char* resource_name, const Object& resource)
  5559. : AsyncProgressWorkerBase<std::pair<T*, size_t>>(
  5560. env, resource_name, resource, /** unlimited queue size */ 0) {}
  5561. #endif
  5562. template <class T>
  5563. inline void AsyncProgressQueueWorker<T>::Execute() {
  5564. ExecutionProgress progress(this);
  5565. Execute(progress);
  5566. }
  5567. template <class T>
  5568. inline void AsyncProgressQueueWorker<T>::OnWorkProgress(
  5569. std::pair<T*, size_t>* datapair) {
  5570. if (datapair == nullptr) {
  5571. return;
  5572. }
  5573. T* data = datapair->first;
  5574. size_t size = datapair->second;
  5575. this->OnProgress(data, size);
  5576. delete datapair;
  5577. delete[] data;
  5578. }
  5579. template <class T>
  5580. inline void AsyncProgressQueueWorker<T>::SendProgress_(const T* data,
  5581. size_t count) {
  5582. T* new_data = new T[count];
  5583. std::copy(data, data + count, new_data);
  5584. auto pair = new std::pair<T*, size_t>(new_data, count);
  5585. this->NonBlockingCall(pair);
  5586. }
  5587. template <class T>
  5588. inline void AsyncProgressQueueWorker<T>::Signal() const {
  5589. this->SendProgress_(static_cast<T*>(nullptr), 0);
  5590. }
  5591. template <class T>
  5592. inline void AsyncProgressQueueWorker<T>::OnWorkComplete(Napi::Env env,
  5593. napi_status status) {
  5594. // Draining queued items in TSFN.
  5595. AsyncProgressWorkerBase<std::pair<T*, size_t>>::OnWorkComplete(env, status);
  5596. }
  5597. template <class T>
  5598. inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Signal() const {
  5599. _worker->SendProgress_(static_cast<T*>(nullptr), 0);
  5600. }
  5601. template <class T>
  5602. inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(
  5603. const T* data, size_t count) const {
  5604. _worker->SendProgress_(data, count);
  5605. }
  5606. #endif // NAPI_VERSION > 3 && NAPI_HAS_THREADS
  5607. ////////////////////////////////////////////////////////////////////////////////
  5608. // Memory Management class
  5609. ////////////////////////////////////////////////////////////////////////////////
  5610. inline int64_t MemoryManagement::AdjustExternalMemory(Env env,
  5611. int64_t change_in_bytes) {
  5612. int64_t result;
  5613. napi_status status =
  5614. napi_adjust_external_memory(env, change_in_bytes, &result);
  5615. NAPI_THROW_IF_FAILED(env, status, 0);
  5616. return result;
  5617. }
  5618. ////////////////////////////////////////////////////////////////////////////////
  5619. // Version Management class
  5620. ////////////////////////////////////////////////////////////////////////////////
  5621. inline uint32_t VersionManagement::GetNapiVersion(Env env) {
  5622. uint32_t result;
  5623. napi_status status = napi_get_version(env, &result);
  5624. NAPI_THROW_IF_FAILED(env, status, 0);
  5625. return result;
  5626. }
  5627. inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
  5628. const napi_node_version* result;
  5629. napi_status status = napi_get_node_version(env, &result);
  5630. NAPI_THROW_IF_FAILED(env, status, 0);
  5631. return result;
  5632. }
  5633. #if NAPI_VERSION > 5
  5634. ////////////////////////////////////////////////////////////////////////////////
  5635. // Addon<T> class
  5636. ////////////////////////////////////////////////////////////////////////////////
  5637. template <typename T>
  5638. inline Object Addon<T>::Init(Env env, Object exports) {
  5639. T* addon = new T(env, exports);
  5640. env.SetInstanceData(addon);
  5641. return addon->entry_point_;
  5642. }
  5643. template <typename T>
  5644. inline T* Addon<T>::Unwrap(Object wrapper) {
  5645. return wrapper.Env().GetInstanceData<T>();
  5646. }
  5647. template <typename T>
  5648. inline void Addon<T>::DefineAddon(
  5649. Object exports, const std::initializer_list<AddonProp>& props) {
  5650. DefineProperties(exports, props);
  5651. entry_point_ = exports;
  5652. }
  5653. template <typename T>
  5654. inline Napi::Object Addon<T>::DefineProperties(
  5655. Object object, const std::initializer_list<AddonProp>& props) {
  5656. const napi_property_descriptor* properties =
  5657. reinterpret_cast<const napi_property_descriptor*>(props.begin());
  5658. size_t size = props.size();
  5659. napi_status status =
  5660. napi_define_properties(object.Env(), object, size, properties);
  5661. NAPI_THROW_IF_FAILED(object.Env(), status, object);
  5662. for (size_t idx = 0; idx < size; idx++)
  5663. T::AttachPropData(object.Env(), object, &properties[idx]);
  5664. return object;
  5665. }
  5666. #endif // NAPI_VERSION > 5
  5667. #if NAPI_VERSION > 2
  5668. template <typename Hook, typename Arg>
  5669. Env::CleanupHook<Hook, Arg> Env::AddCleanupHook(Hook hook, Arg* arg) {
  5670. return CleanupHook<Hook, Arg>(*this, hook, arg);
  5671. }
  5672. template <typename Hook>
  5673. Env::CleanupHook<Hook> Env::AddCleanupHook(Hook hook) {
  5674. return CleanupHook<Hook>(*this, hook);
  5675. }
  5676. template <typename Hook, typename Arg>
  5677. Env::CleanupHook<Hook, Arg>::CleanupHook() {
  5678. data = nullptr;
  5679. }
  5680. template <typename Hook, typename Arg>
  5681. Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::Env env, Hook hook)
  5682. : wrapper(Env::CleanupHook<Hook, Arg>::Wrapper) {
  5683. data = new CleanupData{std::move(hook), nullptr};
  5684. napi_status status = napi_add_env_cleanup_hook(env, wrapper, data);
  5685. if (status != napi_ok) {
  5686. delete data;
  5687. data = nullptr;
  5688. }
  5689. }
  5690. template <typename Hook, typename Arg>
  5691. Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::Env env, Hook hook, Arg* arg)
  5692. : wrapper(Env::CleanupHook<Hook, Arg>::WrapperWithArg) {
  5693. data = new CleanupData{std::move(hook), arg};
  5694. napi_status status = napi_add_env_cleanup_hook(env, wrapper, data);
  5695. if (status != napi_ok) {
  5696. delete data;
  5697. data = nullptr;
  5698. }
  5699. }
  5700. template <class Hook, class Arg>
  5701. bool Env::CleanupHook<Hook, Arg>::Remove(Env env) {
  5702. napi_status status = napi_remove_env_cleanup_hook(env, wrapper, data);
  5703. delete data;
  5704. data = nullptr;
  5705. return status == napi_ok;
  5706. }
  5707. template <class Hook, class Arg>
  5708. bool Env::CleanupHook<Hook, Arg>::IsEmpty() const {
  5709. return data == nullptr;
  5710. }
  5711. #endif // NAPI_VERSION > 2
  5712. #ifdef NAPI_CPP_CUSTOM_NAMESPACE
  5713. } // namespace NAPI_CPP_CUSTOM_NAMESPACE
  5714. #endif
  5715. } // namespace Napi
  5716. #endif // SRC_NAPI_INL_H_