jsfriendapi.h 101 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=8 sts=4 et sw=4 tw=99:
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #ifndef jsfriendapi_h
  7. #define jsfriendapi_h
  8. #include "mozilla/Atomics.h"
  9. #include "mozilla/Casting.h"
  10. #include "mozilla/Maybe.h"
  11. #include "mozilla/MemoryReporting.h"
  12. #include "mozilla/UniquePtr.h"
  13. #include "jsapi.h" // For JSAutoByteString. See bug 1033916.
  14. #include "jsbytecode.h"
  15. #include "jspubtd.h"
  16. #include "js/CallArgs.h"
  17. #include "js/CallNonGenericMethod.h"
  18. #include "js/Class.h"
  19. #include "js/Utility.h"
  20. #if JS_STACK_GROWTH_DIRECTION > 0
  21. # define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) < (limit)))
  22. #else
  23. # define JS_CHECK_STACK_SIZE(limit, sp) (MOZ_LIKELY((uintptr_t)(sp) > (limit)))
  24. #endif
  25. class JSAtom;
  26. struct JSErrorFormatString;
  27. class JSLinearString;
  28. struct JSJitInfo;
  29. class JSErrorReport;
  30. namespace JS {
  31. template <class T>
  32. class Heap;
  33. } /* namespace JS */
  34. namespace js {
  35. class JS_FRIEND_API(BaseProxyHandler);
  36. class InterpreterFrame;
  37. } /* namespace js */
  38. extern JS_FRIEND_API(void)
  39. JS_SetGrayGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
  40. extern JS_FRIEND_API(JSObject*)
  41. JS_FindCompilationScope(JSContext* cx, JS::HandleObject obj);
  42. extern JS_FRIEND_API(JSFunction*)
  43. JS_GetObjectFunction(JSObject* obj);
  44. extern JS_FRIEND_API(bool)
  45. JS_SplicePrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
  46. extern JS_FRIEND_API(JSObject*)
  47. JS_NewObjectWithUniqueType(JSContext* cx, const JSClass* clasp, JS::HandleObject proto);
  48. /**
  49. * Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
  50. * without invoking the metadata callback on it. This allows creation of
  51. * internal bookkeeping objects that are guaranteed to not have metadata
  52. * attached to them.
  53. */
  54. extern JS_FRIEND_API(JSObject*)
  55. JS_NewObjectWithoutMetadata(JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
  56. extern JS_FRIEND_API(uint32_t)
  57. JS_ObjectCountDynamicSlots(JS::HandleObject obj);
  58. extern JS_FRIEND_API(size_t)
  59. JS_SetProtoCalled(JSContext* cx);
  60. extern JS_FRIEND_API(size_t)
  61. JS_GetCustomIteratorCount(JSContext* cx);
  62. extern JS_FRIEND_API(bool)
  63. JS_NondeterministicGetWeakMapKeys(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
  64. extern JS_FRIEND_API(bool)
  65. JS_NondeterministicGetWeakSetKeys(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
  66. // Raw JSScript* because this needs to be callable from a signal handler.
  67. extern JS_FRIEND_API(unsigned)
  68. JS_PCToLineNumber(JSScript* script, jsbytecode* pc, unsigned* columnp = nullptr);
  69. /**
  70. * Determine whether the given object is backed by a DeadObjectProxy.
  71. *
  72. * Such objects hold no other objects (they have no outgoing reference edges)
  73. * and will throw if you touch them (e.g. by reading/writing a property).
  74. */
  75. extern JS_FRIEND_API(bool)
  76. JS_IsDeadWrapper(JSObject* obj);
  77. /*
  78. * Used by the cycle collector to trace through a shape or object group and
  79. * all cycle-participating data it reaches, using bounded stack space.
  80. */
  81. extern JS_FRIEND_API(void)
  82. JS_TraceShapeCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr shape);
  83. extern JS_FRIEND_API(void)
  84. JS_TraceObjectGroupCycleCollectorChildren(JS::CallbackTracer* trc, JS::GCCellPtr group);
  85. enum {
  86. JS_TELEMETRY_GC_REASON,
  87. JS_TELEMETRY_GC_IS_ZONE_GC,
  88. JS_TELEMETRY_GC_MS,
  89. JS_TELEMETRY_GC_BUDGET_MS,
  90. JS_TELEMETRY_GC_ANIMATION_MS,
  91. JS_TELEMETRY_GC_MAX_PAUSE_MS,
  92. JS_TELEMETRY_GC_MARK_MS,
  93. JS_TELEMETRY_GC_SWEEP_MS,
  94. JS_TELEMETRY_GC_COMPACT_MS,
  95. JS_TELEMETRY_GC_MARK_ROOTS_MS,
  96. JS_TELEMETRY_GC_MARK_GRAY_MS,
  97. JS_TELEMETRY_GC_SLICE_MS,
  98. JS_TELEMETRY_GC_SLOW_PHASE,
  99. JS_TELEMETRY_GC_MMU_50,
  100. JS_TELEMETRY_GC_RESET,
  101. JS_TELEMETRY_GC_RESET_REASON,
  102. JS_TELEMETRY_GC_INCREMENTAL_DISABLED,
  103. JS_TELEMETRY_GC_NON_INCREMENTAL,
  104. JS_TELEMETRY_GC_NON_INCREMENTAL_REASON,
  105. JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
  106. JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
  107. JS_TELEMETRY_GC_MINOR_REASON,
  108. JS_TELEMETRY_GC_MINOR_REASON_LONG,
  109. JS_TELEMETRY_GC_MINOR_US,
  110. JS_TELEMETRY_GC_NURSERY_BYTES,
  111. JS_TELEMETRY_GC_PRETENURE_COUNT,
  112. JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
  113. JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS,
  114. JS_TELEMETRY_ADDON_EXCEPTIONS,
  115. JS_TELEMETRY_AOT_USAGE,
  116. JS_TELEMETRY_END
  117. };
  118. typedef void
  119. (*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
  120. extern JS_FRIEND_API(void)
  121. JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
  122. extern JS_FRIEND_API(bool)
  123. JS_GetIsSecureContext(JSCompartment* compartment);
  124. extern JS_FRIEND_API(JSPrincipals*)
  125. JS_GetCompartmentPrincipals(JSCompartment* compartment);
  126. extern JS_FRIEND_API(void)
  127. JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals);
  128. extern JS_FRIEND_API(JSPrincipals*)
  129. JS_GetScriptPrincipals(JSScript* script);
  130. extern JS_FRIEND_API(bool)
  131. JS_ScriptHasMutedErrors(JSScript* script);
  132. extern JS_FRIEND_API(JSObject*)
  133. JS_CloneObject(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto);
  134. /**
  135. * Copy the own properties of src to dst in a fast way. src and dst must both
  136. * be native and must be in the compartment of cx. They must have the same
  137. * class, the same parent, and the same prototype. Class reserved slots will
  138. * NOT be copied.
  139. *
  140. * dst must not have any properties on it before this function is called.
  141. *
  142. * src must have been allocated via JS_NewObjectWithoutMetadata so that we can
  143. * be sure it has no metadata that needs copying to dst. This also means that
  144. * dst needs to have the compartment global as its parent. This function will
  145. * preserve the existing metadata on dst, if any.
  146. */
  147. extern JS_FRIEND_API(bool)
  148. JS_InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
  149. JS::HandleObject dst,
  150. JS::HandleObject src);
  151. extern JS_FRIEND_API(JSString*)
  152. JS_BasicObjectToString(JSContext* cx, JS::HandleObject obj);
  153. namespace js {
  154. JS_FRIEND_API(bool)
  155. GetBuiltinClass(JSContext* cx, JS::HandleObject obj, ESClass* cls);
  156. JS_FRIEND_API(const char*)
  157. ObjectClassName(JSContext* cx, JS::HandleObject obj);
  158. JS_FRIEND_API(void)
  159. ReportOverRecursed(JSContext* maybecx);
  160. JS_FRIEND_API(bool)
  161. AddRawValueRoot(JSContext* cx, JS::Value* vp, const char* name);
  162. JS_FRIEND_API(void)
  163. RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
  164. JS_FRIEND_API(JSAtom*)
  165. GetPropertyNameFromPC(JSScript* script, jsbytecode* pc);
  166. #ifdef JS_DEBUG
  167. /*
  168. * Routines to print out values during debugging. These are FRIEND_API to help
  169. * the debugger find them and to support temporarily hacking js::Dump* calls
  170. * into other code. Note that there are overloads that do not require the FILE*
  171. * parameter, which will default to stderr.
  172. */
  173. extern JS_FRIEND_API(void)
  174. DumpString(JSString* str, FILE* fp);
  175. extern JS_FRIEND_API(void)
  176. DumpAtom(JSAtom* atom, FILE* fp);
  177. extern JS_FRIEND_API(void)
  178. DumpObject(JSObject* obj, FILE* fp);
  179. extern JS_FRIEND_API(void)
  180. DumpChars(const char16_t* s, size_t n, FILE* fp);
  181. extern JS_FRIEND_API(void)
  182. DumpValue(const JS::Value& val, FILE* fp);
  183. extern JS_FRIEND_API(void)
  184. DumpId(jsid id, FILE* fp);
  185. extern JS_FRIEND_API(void)
  186. DumpInterpreterFrame(JSContext* cx, FILE* fp, InterpreterFrame* start = nullptr);
  187. extern JS_FRIEND_API(bool)
  188. DumpPC(JSContext* cx, FILE* fp);
  189. extern JS_FRIEND_API(bool)
  190. DumpScript(JSContext* cx, JSScript* scriptArg, FILE* fp);
  191. // Versions for use directly in a debugger (default parameters are not handled
  192. // well in gdb; built-in handles like stderr are not handled well in lldb.)
  193. extern JS_FRIEND_API(void) DumpString(JSString* str);
  194. extern JS_FRIEND_API(void) DumpAtom(JSAtom* atom);
  195. extern JS_FRIEND_API(void) DumpObject(JSObject* obj);
  196. extern JS_FRIEND_API(void) DumpChars(const char16_t* s, size_t n);
  197. extern JS_FRIEND_API(void) DumpValue(const JS::Value& val);
  198. extern JS_FRIEND_API(void) DumpId(jsid id);
  199. extern JS_FRIEND_API(void) DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start = nullptr);
  200. extern JS_FRIEND_API(bool) DumpPC(JSContext* cx);
  201. extern JS_FRIEND_API(bool) DumpScript(JSContext* cx, JSScript* scriptArg);
  202. #endif
  203. extern JS_FRIEND_API(void)
  204. DumpBacktrace(JSContext* cx, FILE* fp);
  205. extern JS_FRIEND_API(void)
  206. DumpBacktrace(JSContext* cx);
  207. } // namespace js
  208. namespace JS {
  209. /** Exposed for DumpJSStack */
  210. extern JS_FRIEND_API(char*)
  211. FormatStackDump(JSContext* cx, char* buf, bool showArgs, bool showLocals, bool showThisProps);
  212. /**
  213. * Set all of the uninitialized lexicals on an object to undefined. Return
  214. * true if any lexicals were initialized and false otherwise.
  215. * */
  216. extern JS_FRIEND_API(bool)
  217. ForceLexicalInitialization(JSContext *cx, HandleObject obj);
  218. } // namespace JS
  219. /**
  220. * Copies all own properties from |obj| to |target|. |obj| must be a "native"
  221. * object (that is to say, normal-ish - not an Array or a Proxy).
  222. *
  223. * This function immediately enters a compartment, and does not impose any
  224. * restrictions on the compartment of |cx|.
  225. */
  226. extern JS_FRIEND_API(bool)
  227. JS_CopyPropertiesFrom(JSContext* cx, JS::HandleObject target, JS::HandleObject obj);
  228. /*
  229. * Single-property version of the above. This function asserts that an |own|
  230. * property of the given name exists on |obj|.
  231. *
  232. * On entry, |cx| must be same-compartment with |obj|.
  233. *
  234. * The copyBehavior argument controls what happens with
  235. * non-configurable properties.
  236. */
  237. typedef enum {
  238. MakeNonConfigurableIntoConfigurable,
  239. CopyNonConfigurableAsIs
  240. } PropertyCopyBehavior;
  241. extern JS_FRIEND_API(bool)
  242. JS_CopyPropertyFrom(JSContext* cx, JS::HandleId id, JS::HandleObject target,
  243. JS::HandleObject obj,
  244. PropertyCopyBehavior copyBehavior = CopyNonConfigurableAsIs);
  245. extern JS_FRIEND_API(bool)
  246. JS_WrapPropertyDescriptor(JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
  247. struct JSFunctionSpecWithHelp {
  248. const char* name;
  249. JSNative call;
  250. uint16_t nargs;
  251. uint16_t flags;
  252. const JSJitInfo* jitInfo;
  253. const char* usage;
  254. const char* help;
  255. };
  256. #define JS_FN_HELP(name,call,nargs,flags,usage,help) \
  257. {name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, nullptr, usage, help}
  258. #define JS_INLINABLE_FN_HELP(name,call,nargs,flags,native,usage,help) \
  259. {name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, &js::jit::JitInfo_##native,\
  260. usage, help}
  261. #define JS_FS_HELP_END \
  262. {nullptr, nullptr, 0, 0, nullptr, nullptr}
  263. extern JS_FRIEND_API(bool)
  264. JS_DefineFunctionsWithHelp(JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs);
  265. namespace js {
  266. extern JS_FRIEND_DATA(const js::ClassOps) ProxyClassOps;
  267. extern JS_FRIEND_DATA(const js::ClassExtension) ProxyClassExtension;
  268. extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
  269. /*
  270. * Helper Macros for creating JSClasses that function as proxies.
  271. *
  272. * NB: The macro invocation must be surrounded by braces, so as to
  273. * allow for potential JSClass extensions.
  274. */
  275. #define PROXY_MAKE_EXT(objectMoved) \
  276. { \
  277. js::proxy_WeakmapKeyDelegate, \
  278. objectMoved \
  279. }
  280. #define PROXY_CLASS_WITH_EXT(name, flags, extPtr) \
  281. { \
  282. name, \
  283. js::Class::NON_NATIVE | \
  284. JSCLASS_IS_PROXY | \
  285. JSCLASS_DELAY_METADATA_BUILDER | \
  286. flags, \
  287. &js::ProxyClassOps, \
  288. JS_NULL_CLASS_SPEC, \
  289. extPtr, \
  290. &js::ProxyObjectOps \
  291. }
  292. #define PROXY_CLASS_DEF(name, flags) \
  293. PROXY_CLASS_WITH_EXT(name, flags, &js::ProxyClassExtension)
  294. /*
  295. * Proxy stubs, similar to JS_*Stub, for embedder proxy class definitions.
  296. *
  297. * NB: Should not be called directly.
  298. */
  299. extern JS_FRIEND_API(bool)
  300. proxy_LookupProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp,
  301. JS::MutableHandle<Shape*> propp);
  302. extern JS_FRIEND_API(bool)
  303. proxy_DefineProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
  304. JS::Handle<JS::PropertyDescriptor> desc,
  305. JS::ObjectOpResult& result);
  306. extern JS_FRIEND_API(bool)
  307. proxy_HasProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
  308. extern JS_FRIEND_API(bool)
  309. proxy_GetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleValue receiver, JS::HandleId id,
  310. JS::MutableHandleValue vp);
  311. extern JS_FRIEND_API(bool)
  312. proxy_SetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue bp,
  313. JS::HandleValue receiver, JS::ObjectOpResult& result);
  314. extern JS_FRIEND_API(bool)
  315. proxy_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
  316. JS::MutableHandle<JS::PropertyDescriptor> desc);
  317. extern JS_FRIEND_API(bool)
  318. proxy_DeleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
  319. JS::ObjectOpResult& result);
  320. extern JS_FRIEND_API(void)
  321. proxy_Trace(JSTracer* trc, JSObject* obj);
  322. extern JS_FRIEND_API(JSObject*)
  323. proxy_WeakmapKeyDelegate(JSObject* obj);
  324. extern JS_FRIEND_API(bool)
  325. proxy_Convert(JSContext* cx, JS::HandleObject proxy, JSType hint, JS::MutableHandleValue vp);
  326. extern JS_FRIEND_API(void)
  327. proxy_Finalize(FreeOp* fop, JSObject* obj);
  328. extern JS_FRIEND_API(void)
  329. proxy_ObjectMoved(JSObject* obj, const JSObject* old);
  330. extern JS_FRIEND_API(bool)
  331. proxy_HasInstance(JSContext* cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool* bp);
  332. extern JS_FRIEND_API(bool)
  333. proxy_Call(JSContext* cx, unsigned argc, JS::Value* vp);
  334. extern JS_FRIEND_API(bool)
  335. proxy_Construct(JSContext* cx, unsigned argc, JS::Value* vp);
  336. extern JS_FRIEND_API(JSObject*)
  337. proxy_innerObject(JSObject* obj);
  338. extern JS_FRIEND_API(bool)
  339. proxy_Watch(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
  340. extern JS_FRIEND_API(bool)
  341. proxy_Unwatch(JSContext* cx, JS::HandleObject obj, JS::HandleId id);
  342. extern JS_FRIEND_API(bool)
  343. proxy_GetElements(JSContext* cx, JS::HandleObject proxy, uint32_t begin, uint32_t end,
  344. ElementAdder* adder);
  345. extern JS_FRIEND_API(JSString*)
  346. proxy_FunToString(JSContext* cx, JS::HandleObject proxy, unsigned indent);
  347. /**
  348. * A class of objects that return source code on demand.
  349. *
  350. * When code is compiled with setSourceIsLazy(true), SpiderMonkey doesn't
  351. * retain the source code (and doesn't do lazy bytecode generation). If we ever
  352. * need the source code, say, in response to a call to Function.prototype.
  353. * toSource or Debugger.Source.prototype.text, then we call the 'load' member
  354. * function of the instance of this class that has hopefully been registered
  355. * with the runtime, passing the code's URL, and hope that it will be able to
  356. * find the source.
  357. */
  358. class SourceHook {
  359. public:
  360. virtual ~SourceHook() { }
  361. /**
  362. * Set |*src| and |*length| to refer to the source code for |filename|.
  363. * On success, the caller owns the buffer to which |*src| points, and
  364. * should use JS_free to free it.
  365. */
  366. virtual bool load(JSContext* cx, const char* filename, char16_t** src, size_t* length) = 0;
  367. };
  368. /**
  369. * Have |cx| use |hook| to retrieve lazily-retrieved source code. See the
  370. * comments for SourceHook. The context takes ownership of the hook, and
  371. * will delete it when the context itself is deleted, or when a new hook is
  372. * set.
  373. */
  374. extern JS_FRIEND_API(void)
  375. SetSourceHook(JSContext* cx, mozilla::UniquePtr<SourceHook> hook);
  376. /** Remove |cx|'s source hook, and return it. The caller now owns the hook. */
  377. extern JS_FRIEND_API(mozilla::UniquePtr<SourceHook>)
  378. ForgetSourceHook(JSContext* cx);
  379. extern JS_FRIEND_API(JS::Zone*)
  380. GetCompartmentZone(JSCompartment* comp);
  381. typedef bool
  382. (* PreserveWrapperCallback)(JSContext* cx, JSObject* obj);
  383. typedef enum {
  384. CollectNurseryBeforeDump,
  385. IgnoreNurseryObjects
  386. } DumpHeapNurseryBehaviour;
  387. /**
  388. * Dump the complete object graph of heap-allocated things.
  389. * fp is the file for the dump output.
  390. */
  391. extern JS_FRIEND_API(void)
  392. DumpHeap(JSContext* cx, FILE* fp, DumpHeapNurseryBehaviour nurseryBehaviour);
  393. #ifdef JS_OLD_GETTER_SETTER_METHODS
  394. JS_FRIEND_API(bool) obj_defineGetter(JSContext* cx, unsigned argc, JS::Value* vp);
  395. JS_FRIEND_API(bool) obj_defineSetter(JSContext* cx, unsigned argc, JS::Value* vp);
  396. #endif
  397. extern JS_FRIEND_API(bool)
  398. IsSystemCompartment(JSCompartment* comp);
  399. extern JS_FRIEND_API(bool)
  400. IsSystemZone(JS::Zone* zone);
  401. extern JS_FRIEND_API(bool)
  402. IsAtomsCompartment(JSCompartment* comp);
  403. extern JS_FRIEND_API(bool)
  404. IsAtomsZone(JS::Zone* zone);
  405. struct WeakMapTracer
  406. {
  407. JSContext* context;
  408. explicit WeakMapTracer(JSContext* cx) : context(cx) {}
  409. // Weak map tracer callback, called once for every binding of every
  410. // weak map that was live at the time of the last garbage collection.
  411. //
  412. // m will be nullptr if the weak map is not contained in a JS Object.
  413. //
  414. // The callback should not GC (and will assert in a debug build if it does so.)
  415. virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0;
  416. };
  417. extern JS_FRIEND_API(void)
  418. TraceWeakMaps(WeakMapTracer* trc);
  419. extern JS_FRIEND_API(bool)
  420. AreGCGrayBitsValid(JSContext* cx);
  421. extern JS_FRIEND_API(bool)
  422. ZoneGlobalsAreAllGray(JS::Zone* zone);
  423. typedef void
  424. (*GCThingCallback)(void* closure, JS::GCCellPtr thing);
  425. extern JS_FRIEND_API(void)
  426. VisitGrayWrapperTargets(JS::Zone* zone, GCThingCallback callback, void* closure);
  427. extern JS_FRIEND_API(JSObject*)
  428. GetWeakmapKeyDelegate(JSObject* key);
  429. /**
  430. * Invoke cellCallback on every gray JSObject in the given zone.
  431. */
  432. extern JS_FRIEND_API(void)
  433. IterateGrayObjects(JS::Zone* zone, GCThingCallback cellCallback, void* data);
  434. /**
  435. * Invoke cellCallback on every gray JSObject in the given zone while cycle
  436. * collection is in progress.
  437. */
  438. extern JS_FRIEND_API(void)
  439. IterateGrayObjectsUnderCC(JS::Zone* zone, GCThingCallback cellCallback, void* data);
  440. #ifdef JS_HAS_CTYPES
  441. extern JS_FRIEND_API(size_t)
  442. SizeOfDataIfCDataObject(mozilla::MallocSizeOf mallocSizeOf, JSObject* obj);
  443. #endif
  444. extern JS_FRIEND_API(JSCompartment*)
  445. GetAnyCompartmentInZone(JS::Zone* zone);
  446. /*
  447. * Shadow declarations of JS internal structures, for access by inline access
  448. * functions below. Do not use these structures in any other way. When adding
  449. * new fields for access by inline methods, make sure to add static asserts to
  450. * the original header file to ensure that offsets are consistent.
  451. */
  452. namespace shadow {
  453. struct ObjectGroup {
  454. const Class* clasp;
  455. JSObject* proto;
  456. JSCompartment* compartment;
  457. };
  458. struct BaseShape {
  459. const js::Class* clasp_;
  460. JSObject* parent;
  461. };
  462. class Shape {
  463. public:
  464. shadow::BaseShape* base;
  465. jsid _1;
  466. uint32_t slotInfo;
  467. static const uint32_t FIXED_SLOTS_SHIFT = 27;
  468. };
  469. /**
  470. * This layout is shared by all native objects. For non-native objects, the
  471. * group may always be accessed safely, and other members may be as well,
  472. * depending on the object's specific layout.
  473. */
  474. struct Object {
  475. shadow::ObjectGroup* group;
  476. shadow::Shape* shape;
  477. JS::Value* slots;
  478. void* _1;
  479. size_t numFixedSlots() const { return shape->slotInfo >> Shape::FIXED_SLOTS_SHIFT; }
  480. JS::Value* fixedSlots() const {
  481. return (JS::Value*)(uintptr_t(this) + sizeof(shadow::Object));
  482. }
  483. JS::Value& slotRef(size_t slot) const {
  484. size_t nfixed = numFixedSlots();
  485. if (slot < nfixed)
  486. return fixedSlots()[slot];
  487. return slots[slot - nfixed];
  488. }
  489. };
  490. struct Function {
  491. Object base;
  492. uint16_t nargs;
  493. uint16_t flags;
  494. /* Used only for natives */
  495. JSNative native;
  496. const JSJitInfo* jitinfo;
  497. void* _1;
  498. };
  499. struct String
  500. {
  501. static const uint32_t INLINE_CHARS_BIT = JS_BIT(2);
  502. static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
  503. static const uint32_t ROPE_FLAGS = 0;
  504. static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1;
  505. uint32_t flags;
  506. uint32_t length;
  507. union {
  508. const JS::Latin1Char* nonInlineCharsLatin1;
  509. const char16_t* nonInlineCharsTwoByte;
  510. JS::Latin1Char inlineStorageLatin1[1];
  511. char16_t inlineStorageTwoByte[1];
  512. };
  513. };
  514. } /* namespace shadow */
  515. // This is equal to |&JSObject::class_|. Use it in places where you don't want
  516. // to #include jsobj.h.
  517. extern JS_FRIEND_DATA(const js::Class* const) ObjectClassPtr;
  518. inline const js::Class*
  519. GetObjectClass(const JSObject* obj)
  520. {
  521. return reinterpret_cast<const shadow::Object*>(obj)->group->clasp;
  522. }
  523. inline const JSClass*
  524. GetObjectJSClass(JSObject* obj)
  525. {
  526. return js::Jsvalify(GetObjectClass(obj));
  527. }
  528. JS_FRIEND_API(const Class*)
  529. ProtoKeyToClass(JSProtoKey key);
  530. // Returns the key for the class inherited by a given standard class (that
  531. // is to say, the prototype of this standard class's prototype).
  532. //
  533. // You must be sure that this corresponds to a standard class with a cached
  534. // JSProtoKey before calling this function. In general |key| will match the
  535. // cached proto key, except in cases where multiple JSProtoKeys share a
  536. // JSClass.
  537. inline JSProtoKey
  538. InheritanceProtoKeyForStandardClass(JSProtoKey key)
  539. {
  540. // [Object] has nothing to inherit from.
  541. if (key == JSProto_Object)
  542. return JSProto_Null;
  543. // If we're ClassSpec defined return the proto key from that
  544. if (ProtoKeyToClass(key)->specDefined())
  545. return ProtoKeyToClass(key)->specInheritanceProtoKey();
  546. // Otherwise, we inherit [Object].
  547. return JSProto_Object;
  548. }
  549. JS_FRIEND_API(bool)
  550. IsFunctionObject(JSObject* obj);
  551. static MOZ_ALWAYS_INLINE JSCompartment*
  552. GetObjectCompartment(JSObject* obj)
  553. {
  554. return reinterpret_cast<shadow::Object*>(obj)->group->compartment;
  555. }
  556. JS_FRIEND_API(JSObject*)
  557. GetGlobalForObjectCrossCompartment(JSObject* obj);
  558. JS_FRIEND_API(JSObject*)
  559. GetPrototypeNoProxy(JSObject* obj);
  560. JS_FRIEND_API(void)
  561. AssertSameCompartment(JSContext* cx, JSObject* obj);
  562. #ifdef JS_DEBUG
  563. JS_FRIEND_API(void)
  564. AssertSameCompartment(JSObject* objA, JSObject* objB);
  565. #else
  566. inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
  567. #endif
  568. JS_FRIEND_API(void)
  569. NotifyAnimationActivity(JSObject* obj);
  570. /**
  571. * Return the outermost enclosing function (script) of the scripted caller.
  572. * This function returns nullptr in several cases:
  573. * - no script is running on the context
  574. * - the caller is in global or eval code
  575. * In particular, this function will "stop" its outermost search at eval() and
  576. * thus it will really return the outermost enclosing function *since the
  577. * innermost eval*.
  578. */
  579. JS_FRIEND_API(JSFunction*)
  580. GetOutermostEnclosingFunctionOfScriptedCaller(JSContext* cx);
  581. JS_FRIEND_API(JSFunction*)
  582. DefineFunctionWithReserved(JSContext* cx, JSObject* obj, const char* name, JSNative call,
  583. unsigned nargs, unsigned attrs);
  584. JS_FRIEND_API(JSFunction*)
  585. NewFunctionWithReserved(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
  586. const char* name);
  587. JS_FRIEND_API(JSFunction*)
  588. NewFunctionByIdWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
  589. jsid id);
  590. JS_FRIEND_API(const JS::Value&)
  591. GetFunctionNativeReserved(JSObject* fun, size_t which);
  592. JS_FRIEND_API(void)
  593. SetFunctionNativeReserved(JSObject* fun, size_t which, const JS::Value& val);
  594. JS_FRIEND_API(bool)
  595. FunctionHasNativeReserved(JSObject* fun);
  596. JS_FRIEND_API(bool)
  597. GetObjectProto(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject proto);
  598. extern JS_FRIEND_API(JSObject*)
  599. GetStaticPrototype(JSObject* obj);
  600. JS_FRIEND_API(bool)
  601. GetOriginalEval(JSContext* cx, JS::HandleObject scope,
  602. JS::MutableHandleObject eval);
  603. inline void*
  604. GetObjectPrivate(JSObject* obj)
  605. {
  606. MOZ_ASSERT(GetObjectClass(obj)->flags & JSCLASS_HAS_PRIVATE);
  607. const shadow::Object* nobj = reinterpret_cast<const shadow::Object*>(obj);
  608. void** addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
  609. return *addr;
  610. }
  611. inline const JS::Value&
  612. GetReservedSlot(JSObject* obj, size_t slot)
  613. {
  614. MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
  615. return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
  616. }
  617. JS_FRIEND_API(void)
  618. SetReservedOrProxyPrivateSlotWithBarrier(JSObject* obj, size_t slot, const JS::Value& value);
  619. inline void
  620. SetReservedSlot(JSObject* obj, size_t slot, const JS::Value& value)
  621. {
  622. MOZ_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
  623. shadow::Object* sobj = reinterpret_cast<shadow::Object*>(obj);
  624. if (sobj->slotRef(slot).isMarkable() || value.isMarkable())
  625. SetReservedOrProxyPrivateSlotWithBarrier(obj, slot, value);
  626. else
  627. sobj->slotRef(slot) = value;
  628. }
  629. JS_FRIEND_API(uint32_t)
  630. GetObjectSlotSpan(JSObject* obj);
  631. inline const JS::Value&
  632. GetObjectSlot(JSObject* obj, size_t slot)
  633. {
  634. MOZ_ASSERT(slot < GetObjectSlotSpan(obj));
  635. return reinterpret_cast<const shadow::Object*>(obj)->slotRef(slot);
  636. }
  637. MOZ_ALWAYS_INLINE size_t
  638. GetAtomLength(JSAtom* atom)
  639. {
  640. return reinterpret_cast<shadow::String*>(atom)->length;
  641. }
  642. static const uint32_t MaxStringLength = (1 << 28) - 1;
  643. MOZ_ALWAYS_INLINE size_t
  644. GetStringLength(JSString* s)
  645. {
  646. return reinterpret_cast<shadow::String*>(s)->length;
  647. }
  648. MOZ_ALWAYS_INLINE size_t
  649. GetFlatStringLength(JSFlatString* s)
  650. {
  651. return reinterpret_cast<shadow::String*>(s)->length;
  652. }
  653. MOZ_ALWAYS_INLINE size_t
  654. GetLinearStringLength(JSLinearString* s)
  655. {
  656. return reinterpret_cast<shadow::String*>(s)->length;
  657. }
  658. MOZ_ALWAYS_INLINE bool
  659. LinearStringHasLatin1Chars(JSLinearString* s)
  660. {
  661. return reinterpret_cast<shadow::String*>(s)->flags & shadow::String::LATIN1_CHARS_BIT;
  662. }
  663. MOZ_ALWAYS_INLINE bool
  664. AtomHasLatin1Chars(JSAtom* atom)
  665. {
  666. return reinterpret_cast<shadow::String*>(atom)->flags & shadow::String::LATIN1_CHARS_BIT;
  667. }
  668. MOZ_ALWAYS_INLINE bool
  669. StringHasLatin1Chars(JSString* s)
  670. {
  671. return reinterpret_cast<shadow::String*>(s)->flags & shadow::String::LATIN1_CHARS_BIT;
  672. }
  673. MOZ_ALWAYS_INLINE const JS::Latin1Char*
  674. GetLatin1LinearStringChars(const JS::AutoCheckCannotGC& nogc, JSLinearString* linear)
  675. {
  676. MOZ_ASSERT(LinearStringHasLatin1Chars(linear));
  677. using shadow::String;
  678. String* s = reinterpret_cast<String*>(linear);
  679. if (s->flags & String::INLINE_CHARS_BIT)
  680. return s->inlineStorageLatin1;
  681. return s->nonInlineCharsLatin1;
  682. }
  683. MOZ_ALWAYS_INLINE const char16_t*
  684. GetTwoByteLinearStringChars(const JS::AutoCheckCannotGC& nogc, JSLinearString* linear)
  685. {
  686. MOZ_ASSERT(!LinearStringHasLatin1Chars(linear));
  687. using shadow::String;
  688. String* s = reinterpret_cast<String*>(linear);
  689. if (s->flags & String::INLINE_CHARS_BIT)
  690. return s->inlineStorageTwoByte;
  691. return s->nonInlineCharsTwoByte;
  692. }
  693. MOZ_ALWAYS_INLINE JSLinearString*
  694. AtomToLinearString(JSAtom* atom)
  695. {
  696. return reinterpret_cast<JSLinearString*>(atom);
  697. }
  698. MOZ_ALWAYS_INLINE JSFlatString*
  699. AtomToFlatString(JSAtom* atom)
  700. {
  701. return reinterpret_cast<JSFlatString*>(atom);
  702. }
  703. MOZ_ALWAYS_INLINE JSLinearString*
  704. FlatStringToLinearString(JSFlatString* s)
  705. {
  706. return reinterpret_cast<JSLinearString*>(s);
  707. }
  708. MOZ_ALWAYS_INLINE const JS::Latin1Char*
  709. GetLatin1AtomChars(const JS::AutoCheckCannotGC& nogc, JSAtom* atom)
  710. {
  711. return GetLatin1LinearStringChars(nogc, AtomToLinearString(atom));
  712. }
  713. MOZ_ALWAYS_INLINE const char16_t*
  714. GetTwoByteAtomChars(const JS::AutoCheckCannotGC& nogc, JSAtom* atom)
  715. {
  716. return GetTwoByteLinearStringChars(nogc, AtomToLinearString(atom));
  717. }
  718. JS_FRIEND_API(JSLinearString*)
  719. StringToLinearStringSlow(JSContext* cx, JSString* str);
  720. MOZ_ALWAYS_INLINE JSLinearString*
  721. StringToLinearString(JSContext* cx, JSString* str)
  722. {
  723. using shadow::String;
  724. String* s = reinterpret_cast<String*>(str);
  725. if (MOZ_UNLIKELY((s->flags & String::TYPE_FLAGS_MASK) == String::ROPE_FLAGS))
  726. return StringToLinearStringSlow(cx, str);
  727. return reinterpret_cast<JSLinearString*>(str);
  728. }
  729. template<typename CharType>
  730. MOZ_ALWAYS_INLINE void
  731. CopyLinearStringChars(CharType* dest, JSLinearString* s, size_t len, size_t start = 0);
  732. MOZ_ALWAYS_INLINE void
  733. CopyLinearStringChars(char16_t* dest, JSLinearString* s, size_t len, size_t start = 0)
  734. {
  735. MOZ_ASSERT(start + len <= GetLinearStringLength(s));
  736. JS::AutoCheckCannotGC nogc;
  737. if (LinearStringHasLatin1Chars(s)) {
  738. const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
  739. for (size_t i = 0; i < len; i++)
  740. dest[i] = src[start + i];
  741. } else {
  742. const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
  743. mozilla::PodCopy(dest, src + start, len);
  744. }
  745. }
  746. MOZ_ALWAYS_INLINE void
  747. CopyLinearStringChars(char* dest, JSLinearString* s, size_t len, size_t start = 0)
  748. {
  749. MOZ_ASSERT(start + len <= GetLinearStringLength(s));
  750. JS::AutoCheckCannotGC nogc;
  751. if (LinearStringHasLatin1Chars(s)) {
  752. const JS::Latin1Char* src = GetLatin1LinearStringChars(nogc, s);
  753. for (size_t i = 0; i < len; i++)
  754. dest[i] = char(src[start + i]);
  755. } else {
  756. const char16_t* src = GetTwoByteLinearStringChars(nogc, s);
  757. for (size_t i = 0; i < len; i++)
  758. dest[i] = char(src[start + i]);
  759. }
  760. }
  761. template<typename CharType>
  762. inline bool
  763. CopyStringChars(JSContext* cx, CharType* dest, JSString* s, size_t len, size_t start = 0)
  764. {
  765. JSLinearString* linear = StringToLinearString(cx, s);
  766. if (!linear)
  767. return false;
  768. CopyLinearStringChars(dest, linear, len, start);
  769. return true;
  770. }
  771. inline void
  772. CopyFlatStringChars(char16_t* dest, JSFlatString* s, size_t len)
  773. {
  774. CopyLinearStringChars(dest, FlatStringToLinearString(s), len);
  775. }
  776. /**
  777. * Add some or all property keys of obj to the id vector *props.
  778. *
  779. * The flags parameter controls which property keys are added. Pass a
  780. * combination of the following bits:
  781. *
  782. * JSITER_OWNONLY - Don't also search the prototype chain; only consider
  783. * obj's own properties.
  784. *
  785. * JSITER_HIDDEN - Include nonenumerable properties.
  786. *
  787. * JSITER_SYMBOLS - Include property keys that are symbols. The default
  788. * behavior is to filter out symbols.
  789. *
  790. * JSITER_SYMBOLSONLY - Exclude non-symbol property keys.
  791. *
  792. * This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or
  793. * equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass
  794. * `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get
  795. * results that match the output of Reflect.ownKeys.
  796. */
  797. JS_FRIEND_API(bool)
  798. GetPropertyKeys(JSContext* cx, JS::HandleObject obj, unsigned flags, JS::AutoIdVector* props);
  799. JS_FRIEND_API(bool)
  800. AppendUnique(JSContext* cx, JS::AutoIdVector& base, JS::AutoIdVector& others);
  801. JS_FRIEND_API(bool)
  802. StringIsArrayIndex(JSLinearString* str, uint32_t* indexp);
  803. JS_FRIEND_API(void)
  804. SetPreserveWrapperCallback(JSContext* cx, PreserveWrapperCallback callback);
  805. JS_FRIEND_API(bool)
  806. IsObjectInContextCompartment(JSObject* obj, const JSContext* cx);
  807. /*
  808. * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
  809. * The first three are omitted because they shouldn't be used in new code.
  810. */
  811. #define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
  812. #define JSITER_FOREACH 0x2 /* get obj[key] for each property */
  813. #define JSITER_KEYVALUE 0x4 /* obsolete destructuring for-in wants [key, value] */
  814. #define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
  815. #define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
  816. #define JSITER_SYMBOLS 0x20 /* also include symbol property keys */
  817. #define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
  818. JS_FRIEND_API(bool)
  819. RunningWithTrustedPrincipals(JSContext* cx);
  820. inline uintptr_t
  821. GetNativeStackLimit(JSContext* cx, StackKind kind, int extraAllowance = 0)
  822. {
  823. uintptr_t limit = ContextFriendFields::get(cx)->nativeStackLimit[kind];
  824. #if JS_STACK_GROWTH_DIRECTION > 0
  825. limit += extraAllowance;
  826. #else
  827. limit -= extraAllowance;
  828. #endif
  829. return limit;
  830. }
  831. inline uintptr_t
  832. GetNativeStackLimit(JSContext* cx, int extraAllowance = 0)
  833. {
  834. StackKind kind = RunningWithTrustedPrincipals(cx) ? StackForTrustedScript
  835. : StackForUntrustedScript;
  836. return GetNativeStackLimit(cx, kind, extraAllowance);
  837. }
  838. /*
  839. * These macros report a stack overflow and run |onerror| if we are close to
  840. * using up the C stack. The JS_CHECK_CHROME_RECURSION variant gives us a
  841. * little extra space so that we can ensure that crucial code is able to run.
  842. * JS_CHECK_RECURSION_CONSERVATIVE allows less space than any other check,
  843. * including a safety buffer (as in, it uses the untrusted limit and subtracts
  844. * a little more from it).
  845. */
  846. #define JS_CHECK_RECURSION_LIMIT(cx, limit, onerror) \
  847. JS_BEGIN_MACRO \
  848. int stackDummy_; \
  849. if (!JS_CHECK_STACK_SIZE(limit, &stackDummy_)) { \
  850. js::ReportOverRecursed(cx); \
  851. onerror; \
  852. } \
  853. JS_END_MACRO
  854. #define JS_CHECK_RECURSION(cx, onerror) \
  855. JS_CHECK_RECURSION_LIMIT(cx, js::GetNativeStackLimit(cx), onerror)
  856. #define JS_CHECK_RECURSION_LIMIT_DONT_REPORT(cx, limit, onerror) \
  857. JS_BEGIN_MACRO \
  858. int stackDummy_; \
  859. if (!JS_CHECK_STACK_SIZE(limit, &stackDummy_)) { \
  860. onerror; \
  861. } \
  862. JS_END_MACRO
  863. #define JS_CHECK_RECURSION_DONT_REPORT(cx, onerror) \
  864. JS_CHECK_RECURSION_LIMIT_DONT_REPORT(cx, js::GetNativeStackLimit(cx), onerror)
  865. #define JS_CHECK_RECURSION_WITH_SP_DONT_REPORT(cx, sp, onerror) \
  866. JS_BEGIN_MACRO \
  867. if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), sp)) { \
  868. onerror; \
  869. } \
  870. JS_END_MACRO
  871. #define JS_CHECK_RECURSION_WITH_SP(cx, sp, onerror) \
  872. JS_BEGIN_MACRO \
  873. if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(cx), sp)) { \
  874. js::ReportOverRecursed(cx); \
  875. onerror; \
  876. } \
  877. JS_END_MACRO
  878. #define JS_CHECK_SYSTEM_RECURSION(cx, onerror) \
  879. JS_CHECK_RECURSION_LIMIT(cx, js::GetNativeStackLimit(cx, js::StackForSystemCode), onerror)
  880. #define JS_CHECK_RECURSION_CONSERVATIVE(cx, onerror) \
  881. JS_CHECK_RECURSION_LIMIT(cx, \
  882. js::GetNativeStackLimit(cx, js::StackForUntrustedScript, -1024 * int(sizeof(size_t))), \
  883. onerror)
  884. #define JS_CHECK_RECURSION_CONSERVATIVE_DONT_REPORT(cx, onerror) \
  885. JS_CHECK_RECURSION_LIMIT_DONT_REPORT(cx, \
  886. js::GetNativeStackLimit(cx, js::StackForUntrustedScript, -1024 * int(sizeof(size_t))), \
  887. onerror)
  888. JS_FRIEND_API(void)
  889. StartPCCountProfiling(JSContext* cx);
  890. JS_FRIEND_API(void)
  891. StopPCCountProfiling(JSContext* cx);
  892. JS_FRIEND_API(void)
  893. PurgePCCounts(JSContext* cx);
  894. JS_FRIEND_API(size_t)
  895. GetPCCountScriptCount(JSContext* cx);
  896. JS_FRIEND_API(JSString*)
  897. GetPCCountScriptSummary(JSContext* cx, size_t script);
  898. JS_FRIEND_API(JSString*)
  899. GetPCCountScriptContents(JSContext* cx, size_t script);
  900. /**
  901. * Generate lcov trace file content for the current compartment, and allocate a
  902. * new buffer and return the content in it, the size of the newly allocated
  903. * content within the buffer would be set to the length out-param.
  904. *
  905. * In case of out-of-memory, this function returns nullptr and does not set any
  906. * value to the length out-param.
  907. */
  908. JS_FRIEND_API(char*)
  909. GetCodeCoverageSummary(JSContext* cx, size_t* length);
  910. typedef void
  911. (* ActivityCallback)(void* arg, bool active);
  912. /**
  913. * Sets a callback that is run whenever the runtime goes idle - the
  914. * last active request ceases - and begins activity - when it was
  915. * idle and a request begins.
  916. */
  917. JS_FRIEND_API(void)
  918. SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg);
  919. typedef bool
  920. (* DOMInstanceClassHasProtoAtDepth)(const Class* instanceClass,
  921. uint32_t protoID, uint32_t depth);
  922. struct JSDOMCallbacks {
  923. DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto;
  924. };
  925. typedef struct JSDOMCallbacks DOMCallbacks;
  926. extern JS_FRIEND_API(void)
  927. SetDOMCallbacks(JSContext* cx, const DOMCallbacks* callbacks);
  928. extern JS_FRIEND_API(const DOMCallbacks*)
  929. GetDOMCallbacks(JSContext* cx);
  930. extern JS_FRIEND_API(JSObject*)
  931. GetTestingFunctions(JSContext* cx);
  932. /**
  933. * Helper to convert FreeOp to JSFreeOp when the definition of FreeOp is not
  934. * available and the compiler does not know that FreeOp inherits from
  935. * JSFreeOp.
  936. */
  937. inline JSFreeOp*
  938. CastToJSFreeOp(FreeOp* fop)
  939. {
  940. return reinterpret_cast<JSFreeOp*>(fop);
  941. }
  942. /* Implemented in jsexn.cpp. */
  943. /**
  944. * Get an error type name from a JSExnType constant.
  945. * Returns nullptr for invalid arguments and JSEXN_INTERNALERR
  946. */
  947. extern JS_FRIEND_API(JSFlatString*)
  948. GetErrorTypeName(JSContext* cx, int16_t exnType);
  949. #ifdef JS_DEBUG
  950. extern JS_FRIEND_API(unsigned)
  951. GetEnterCompartmentDepth(JSContext* cx);
  952. #endif
  953. class RegExpGuard;
  954. extern JS_FRIEND_API(bool)
  955. RegExpToSharedNonInline(JSContext* cx, JS::HandleObject regexp, RegExpGuard* shared);
  956. /* Implemented in jswrapper.cpp. */
  957. typedef enum NukeReferencesToWindow {
  958. NukeWindowReferences,
  959. DontNukeWindowReferences
  960. } NukeReferencesToWindow;
  961. /*
  962. * These filters are designed to be ephemeral stack classes, and thus don't
  963. * do any rooting or holding of their members.
  964. */
  965. struct CompartmentFilter {
  966. virtual bool match(JSCompartment* c) const = 0;
  967. };
  968. struct AllCompartments : public CompartmentFilter {
  969. virtual bool match(JSCompartment* c) const override { return true; }
  970. };
  971. struct ContentCompartmentsOnly : public CompartmentFilter {
  972. virtual bool match(JSCompartment* c) const override {
  973. return !IsSystemCompartment(c);
  974. }
  975. };
  976. struct ChromeCompartmentsOnly : public CompartmentFilter {
  977. virtual bool match(JSCompartment* c) const override {
  978. return IsSystemCompartment(c);
  979. }
  980. };
  981. struct SingleCompartment : public CompartmentFilter {
  982. JSCompartment* ours;
  983. explicit SingleCompartment(JSCompartment* c) : ours(c) {}
  984. virtual bool match(JSCompartment* c) const override { return c == ours; }
  985. };
  986. struct CompartmentsWithPrincipals : public CompartmentFilter {
  987. JSPrincipals* principals;
  988. explicit CompartmentsWithPrincipals(JSPrincipals* p) : principals(p) {}
  989. virtual bool match(JSCompartment* c) const override {
  990. return JS_GetCompartmentPrincipals(c) == principals;
  991. }
  992. };
  993. extern JS_FRIEND_API(bool)
  994. NukeCrossCompartmentWrappers(JSContext* cx,
  995. const CompartmentFilter& sourceFilter,
  996. const CompartmentFilter& targetFilter,
  997. NukeReferencesToWindow nukeReferencesToWindow);
  998. /* Specify information about DOMProxy proxies in the DOM, for use by ICs. */
  999. /*
  1000. * The DOMProxyShadowsCheck function will be called to check if the property for
  1001. * id should be gotten from the prototype, or if there is an own property that
  1002. * shadows it.
  1003. * * If ShadowsViaDirectExpando is returned, then the slot at
  1004. * listBaseExpandoSlot contains an expando object which has the property in
  1005. * question.
  1006. * * If ShadowsViaIndirectExpando is returned, then the slot at
  1007. * listBaseExpandoSlot contains a private pointer to an ExpandoAndGeneration
  1008. * and the expando object in the ExpandoAndGeneration has the property in
  1009. * question.
  1010. * * If DoesntShadow is returned then the slot at listBaseExpandoSlot should
  1011. * either be undefined or point to an expando object that would contain the
  1012. * own property.
  1013. * * If DoesntShadowUnique is returned then the slot at listBaseExpandoSlot
  1014. * should contain a private pointer to a ExpandoAndGeneration, which contains
  1015. * a JS::Value that should either be undefined or point to an expando object,
  1016. * and a uint64 value. If that value changes then the IC for getting a
  1017. * property will be invalidated.
  1018. * * If Shadows is returned, that means the property is an own property of the
  1019. * proxy but doesn't live on the expando object.
  1020. */
  1021. struct ExpandoAndGeneration {
  1022. ExpandoAndGeneration()
  1023. : expando(JS::UndefinedValue()),
  1024. generation(0)
  1025. {}
  1026. void OwnerUnlinked()
  1027. {
  1028. ++generation;
  1029. }
  1030. static size_t offsetOfExpando()
  1031. {
  1032. return offsetof(ExpandoAndGeneration, expando);
  1033. }
  1034. static size_t offsetOfGeneration()
  1035. {
  1036. return offsetof(ExpandoAndGeneration, generation);
  1037. }
  1038. JS::Heap<JS::Value> expando;
  1039. uint64_t generation;
  1040. };
  1041. typedef enum DOMProxyShadowsResult {
  1042. ShadowCheckFailed,
  1043. Shadows,
  1044. DoesntShadow,
  1045. DoesntShadowUnique,
  1046. ShadowsViaDirectExpando,
  1047. ShadowsViaIndirectExpando
  1048. } DOMProxyShadowsResult;
  1049. typedef DOMProxyShadowsResult
  1050. (* DOMProxyShadowsCheck)(JSContext* cx, JS::HandleObject object, JS::HandleId id);
  1051. JS_FRIEND_API(void)
  1052. SetDOMProxyInformation(const void* domProxyHandlerFamily, uint32_t domProxyExpandoSlot,
  1053. DOMProxyShadowsCheck domProxyShadowsCheck);
  1054. const void* GetDOMProxyHandlerFamily();
  1055. uint32_t GetDOMProxyExpandoSlot();
  1056. DOMProxyShadowsCheck GetDOMProxyShadowsCheck();
  1057. inline bool DOMProxyIsShadowing(DOMProxyShadowsResult result) {
  1058. return result == Shadows ||
  1059. result == ShadowsViaDirectExpando ||
  1060. result == ShadowsViaIndirectExpando;
  1061. }
  1062. /* Implemented in jsdate.cpp. */
  1063. /** Detect whether the internal date value is NaN. */
  1064. extern JS_FRIEND_API(bool)
  1065. DateIsValid(JSContext* cx, JS::HandleObject obj, bool* isValid);
  1066. extern JS_FRIEND_API(bool)
  1067. DateGetMsecSinceEpoch(JSContext* cx, JS::HandleObject obj, double* msecSinceEpoch);
  1068. } /* namespace js */
  1069. /* Implemented in jscntxt.cpp. */
  1070. /**
  1071. * Report an exception, which is currently realized as a printf-style format
  1072. * string and its arguments.
  1073. */
  1074. typedef enum JSErrNum {
  1075. #define MSG_DEF(name, count, exception, format) \
  1076. name,
  1077. #include "js.msg"
  1078. #undef MSG_DEF
  1079. JSErr_Limit
  1080. } JSErrNum;
  1081. namespace js {
  1082. extern JS_FRIEND_API(const JSErrorFormatString*)
  1083. GetErrorMessage(void* userRef, const unsigned errorNumber);
  1084. // AutoStableStringChars is here so we can use it in ErrorReport. It
  1085. // should get moved out of here if we can manage it. See bug 1040316.
  1086. /**
  1087. * This class provides safe access to a string's chars across a GC. Once
  1088. * we allocate strings and chars in the nursery (bug 903519), this class
  1089. * will have to make a copy of the string's chars if they are allocated
  1090. * in the nursery, so it's best to avoid using this class unless you really
  1091. * need it. It's usually more efficient to use the latin1Chars/twoByteChars
  1092. * JSString methods and often the code can be rewritten so that only indexes
  1093. * instead of char pointers are used in parts of the code that can GC.
  1094. */
  1095. class MOZ_STACK_CLASS AutoStableStringChars
  1096. {
  1097. /*
  1098. * When copying string char, use this many bytes of inline storage. This is
  1099. * chosen to allow the inline string types to be copied without allocating.
  1100. * This is asserted in AutoStableStringChars::allocOwnChars.
  1101. */
  1102. static const size_t InlineCapacity = 24;
  1103. /* Ensure the string is kept alive while we're using its chars. */
  1104. JS::RootedString s_;
  1105. union {
  1106. const char16_t* twoByteChars_;
  1107. const JS::Latin1Char* latin1Chars_;
  1108. };
  1109. mozilla::Maybe<Vector<uint8_t, InlineCapacity>> ownChars_;
  1110. enum State { Uninitialized, Latin1, TwoByte };
  1111. State state_;
  1112. public:
  1113. explicit AutoStableStringChars(JSContext* cx)
  1114. : s_(cx), state_(Uninitialized)
  1115. {}
  1116. MOZ_MUST_USE
  1117. bool init(JSContext* cx, JSString* s);
  1118. /* Like init(), but Latin1 chars are inflated to TwoByte. */
  1119. MOZ_MUST_USE
  1120. bool initTwoByte(JSContext* cx, JSString* s);
  1121. bool isLatin1() const { return state_ == Latin1; }
  1122. bool isTwoByte() const { return state_ == TwoByte; }
  1123. const char16_t* twoByteChars() const {
  1124. MOZ_ASSERT(state_ == TwoByte);
  1125. return twoByteChars_;
  1126. }
  1127. mozilla::Range<const JS::Latin1Char> latin1Range() const {
  1128. MOZ_ASSERT(state_ == Latin1);
  1129. return mozilla::Range<const JS::Latin1Char>(latin1Chars_,
  1130. GetStringLength(s_));
  1131. }
  1132. mozilla::Range<const char16_t> twoByteRange() const {
  1133. MOZ_ASSERT(state_ == TwoByte);
  1134. return mozilla::Range<const char16_t>(twoByteChars_,
  1135. GetStringLength(s_));
  1136. }
  1137. /* If we own the chars, transfer ownership to the caller. */
  1138. bool maybeGiveOwnershipToCaller() {
  1139. MOZ_ASSERT(state_ != Uninitialized);
  1140. if (!ownChars_.isSome() || !ownChars_->extractRawBuffer())
  1141. return false;
  1142. state_ = Uninitialized;
  1143. ownChars_.reset();
  1144. return true;
  1145. }
  1146. private:
  1147. AutoStableStringChars(const AutoStableStringChars& other) = delete;
  1148. void operator=(const AutoStableStringChars& other) = delete;
  1149. bool baseIsInline(JS::Handle<JSLinearString*> linearString);
  1150. template <typename T> T* allocOwnChars(JSContext* cx, size_t count);
  1151. bool copyLatin1Chars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
  1152. bool copyTwoByteChars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
  1153. bool copyAndInflateLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
  1154. };
  1155. struct MOZ_STACK_CLASS JS_FRIEND_API(ErrorReport)
  1156. {
  1157. explicit ErrorReport(JSContext* cx);
  1158. ~ErrorReport();
  1159. enum SniffingBehavior {
  1160. WithSideEffects,
  1161. NoSideEffects
  1162. };
  1163. /**
  1164. * Generate a JSErrorReport from the provided thrown value.
  1165. *
  1166. * If the value is a (possibly wrapped) Error object, the JSErrorReport will
  1167. * be exactly initialized from the Error object's information, without
  1168. * observable side effects. (The Error object's JSErrorReport is reused, if
  1169. * it has one.)
  1170. *
  1171. * Otherwise various attempts are made to derive JSErrorReport information
  1172. * from |exn| and from the current execution state. This process is
  1173. * *definitely* inconsistent with any standard, and particulars of the
  1174. * behavior implemented here generally shouldn't be relied upon.
  1175. *
  1176. * If the value of |sniffingBehavior| is |WithSideEffects|, some of these
  1177. * attempts *may* invoke user-configurable behavior when |exn| is an object:
  1178. * converting |exn| to a string, detecting and getting properties on |exn|,
  1179. * accessing |exn|'s prototype chain, and others are possible. Users *must*
  1180. * tolerate |ErrorReport::init| potentially having arbitrary effects. Any
  1181. * exceptions thrown by these operations will be caught and silently
  1182. * ignored, and "default" values will be substituted into the JSErrorReport.
  1183. *
  1184. * But if the value of |sniffingBehavior| is |NoSideEffects|, these attempts
  1185. * *will not* invoke any observable side effects. The JSErrorReport will
  1186. * simply contain fewer, less precise details.
  1187. *
  1188. * Unlike some functions involved in error handling, this function adheres
  1189. * to the usual JSAPI return value error behavior.
  1190. */
  1191. bool init(JSContext* cx, JS::HandleValue exn,
  1192. SniffingBehavior sniffingBehavior);
  1193. JSErrorReport* report()
  1194. {
  1195. return reportp;
  1196. }
  1197. const JS::ConstUTF8CharsZ toStringResult()
  1198. {
  1199. return toStringResult_;
  1200. }
  1201. private:
  1202. // More or less an equivalent of JS_ReportErrorNumber/js::ReportErrorNumberVA
  1203. // but fills in an ErrorReport instead of reporting it. Uses varargs to
  1204. // make it simpler to call js::ExpandErrorArgumentsVA.
  1205. //
  1206. // Returns false if we fail to actually populate the ErrorReport
  1207. // for some reason (probably out of memory).
  1208. bool populateUncaughtExceptionReportUTF8(JSContext* cx, ...);
  1209. bool populateUncaughtExceptionReportUTF8VA(JSContext* cx, va_list ap);
  1210. // Reports exceptions from add-on scopes to telementry.
  1211. void ReportAddonExceptionToTelementry(JSContext* cx);
  1212. // We may have a provided JSErrorReport, so need a way to represent that.
  1213. JSErrorReport* reportp;
  1214. // Or we may need to synthesize a JSErrorReport one of our own.
  1215. JSErrorReport ownedReport;
  1216. // And we have a string to maybe keep alive that has pointers into
  1217. // it from ownedReport.
  1218. JS::RootedString str;
  1219. // And keep its chars alive too.
  1220. AutoStableStringChars strChars;
  1221. // And we need to root our exception value.
  1222. JS::RootedObject exnObject;
  1223. // And for our filename.
  1224. JSAutoByteString filename;
  1225. // We may have a result of error.toString().
  1226. // FIXME: We should not call error.toString(), since it could have side
  1227. // effect (see bug 633623).
  1228. JS::ConstUTF8CharsZ toStringResult_;
  1229. JSAutoByteString toStringResultBytesStorage;
  1230. };
  1231. /* Implemented in vm/StructuredClone.cpp. */
  1232. extern JS_FRIEND_API(uint64_t)
  1233. GetSCOffset(JSStructuredCloneWriter* writer);
  1234. namespace Scalar {
  1235. /**
  1236. * Scalar types that can appear in typed arrays and typed objects. The enum
  1237. * values must to be kept in sync with the JS_SCALARTYPEREPR_ constants, as
  1238. * well as the TypedArrayObject::classes and TypedArrayObject::protoClasses
  1239. * definitions.
  1240. */
  1241. enum Type {
  1242. Int8 = 0,
  1243. Uint8,
  1244. Int16,
  1245. Uint16,
  1246. Int32,
  1247. Uint32,
  1248. Float32,
  1249. Float64,
  1250. /**
  1251. * Special type that is a uint8_t, but assignments are clamped to [0, 256).
  1252. * Treat the raw data type as a uint8_t.
  1253. */
  1254. Uint8Clamped,
  1255. /**
  1256. * Types that don't have their own TypedArray equivalent, for now.
  1257. */
  1258. MaxTypedArrayViewType,
  1259. Int64,
  1260. Float32x4,
  1261. Int8x16,
  1262. Int16x8,
  1263. Int32x4
  1264. };
  1265. static inline size_t
  1266. byteSize(Type atype)
  1267. {
  1268. switch (atype) {
  1269. case Int8:
  1270. case Uint8:
  1271. case Uint8Clamped:
  1272. return 1;
  1273. case Int16:
  1274. case Uint16:
  1275. return 2;
  1276. case Int32:
  1277. case Uint32:
  1278. case Float32:
  1279. return 4;
  1280. case Int64:
  1281. case Float64:
  1282. return 8;
  1283. case Int8x16:
  1284. case Int16x8:
  1285. case Int32x4:
  1286. case Float32x4:
  1287. return 16;
  1288. default:
  1289. MOZ_CRASH("invalid scalar type");
  1290. }
  1291. }
  1292. static inline bool
  1293. isSignedIntType(Type atype) {
  1294. switch (atype) {
  1295. case Int8:
  1296. case Int16:
  1297. case Int32:
  1298. case Int64:
  1299. case Int8x16:
  1300. case Int16x8:
  1301. case Int32x4:
  1302. return true;
  1303. case Uint8:
  1304. case Uint8Clamped:
  1305. case Uint16:
  1306. case Uint32:
  1307. case Float32:
  1308. case Float64:
  1309. case Float32x4:
  1310. return false;
  1311. default:
  1312. MOZ_CRASH("invalid scalar type");
  1313. }
  1314. }
  1315. static inline bool
  1316. isSimdType(Type atype) {
  1317. switch (atype) {
  1318. case Int8:
  1319. case Uint8:
  1320. case Uint8Clamped:
  1321. case Int16:
  1322. case Uint16:
  1323. case Int32:
  1324. case Uint32:
  1325. case Int64:
  1326. case Float32:
  1327. case Float64:
  1328. return false;
  1329. case Int8x16:
  1330. case Int16x8:
  1331. case Int32x4:
  1332. case Float32x4:
  1333. return true;
  1334. case MaxTypedArrayViewType:
  1335. break;
  1336. }
  1337. MOZ_CRASH("invalid scalar type");
  1338. }
  1339. static inline size_t
  1340. scalarByteSize(Type atype) {
  1341. switch (atype) {
  1342. case Int8x16:
  1343. return 1;
  1344. case Int16x8:
  1345. return 2;
  1346. case Int32x4:
  1347. case Float32x4:
  1348. return 4;
  1349. case Int8:
  1350. case Uint8:
  1351. case Uint8Clamped:
  1352. case Int16:
  1353. case Uint16:
  1354. case Int32:
  1355. case Uint32:
  1356. case Int64:
  1357. case Float32:
  1358. case Float64:
  1359. case MaxTypedArrayViewType:
  1360. break;
  1361. }
  1362. MOZ_CRASH("invalid simd type");
  1363. }
  1364. } /* namespace Scalar */
  1365. } /* namespace js */
  1366. /*
  1367. * Create a new typed array with nelements elements.
  1368. *
  1369. * These functions (except the WithBuffer variants) fill in the array with zeros.
  1370. */
  1371. extern JS_FRIEND_API(JSObject*)
  1372. JS_NewInt8Array(JSContext* cx, uint32_t nelements);
  1373. extern JS_FRIEND_API(JSObject*)
  1374. JS_NewUint8Array(JSContext* cx, uint32_t nelements);
  1375. extern JS_FRIEND_API(JSObject*)
  1376. JS_NewUint8ClampedArray(JSContext* cx, uint32_t nelements);
  1377. extern JS_FRIEND_API(JSObject*)
  1378. JS_NewInt16Array(JSContext* cx, uint32_t nelements);
  1379. extern JS_FRIEND_API(JSObject*)
  1380. JS_NewUint16Array(JSContext* cx, uint32_t nelements);
  1381. extern JS_FRIEND_API(JSObject*)
  1382. JS_NewInt32Array(JSContext* cx, uint32_t nelements);
  1383. extern JS_FRIEND_API(JSObject*)
  1384. JS_NewUint32Array(JSContext* cx, uint32_t nelements);
  1385. extern JS_FRIEND_API(JSObject*)
  1386. JS_NewFloat32Array(JSContext* cx, uint32_t nelements);
  1387. extern JS_FRIEND_API(JSObject*)
  1388. JS_NewFloat64Array(JSContext* cx, uint32_t nelements);
  1389. /*
  1390. * Create a new typed array and copy in values from the given object. The
  1391. * object is used as if it were an array; that is, the new array (if
  1392. * successfully created) will have length given by array.length, and its
  1393. * elements will be those specified by array[0], array[1], and so on, after
  1394. * conversion to the typed array element type.
  1395. */
  1396. extern JS_FRIEND_API(JSObject*)
  1397. JS_NewInt8ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1398. extern JS_FRIEND_API(JSObject*)
  1399. JS_NewUint8ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1400. extern JS_FRIEND_API(JSObject*)
  1401. JS_NewUint8ClampedArrayFromArray(JSContext* cx, JS::HandleObject array);
  1402. extern JS_FRIEND_API(JSObject*)
  1403. JS_NewInt16ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1404. extern JS_FRIEND_API(JSObject*)
  1405. JS_NewUint16ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1406. extern JS_FRIEND_API(JSObject*)
  1407. JS_NewInt32ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1408. extern JS_FRIEND_API(JSObject*)
  1409. JS_NewUint32ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1410. extern JS_FRIEND_API(JSObject*)
  1411. JS_NewFloat32ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1412. extern JS_FRIEND_API(JSObject*)
  1413. JS_NewFloat64ArrayFromArray(JSContext* cx, JS::HandleObject array);
  1414. /*
  1415. * Create a new typed array using the given ArrayBuffer or
  1416. * SharedArrayBuffer for storage. The length value is optional; if -1
  1417. * is passed, enough elements to use up the remainder of the byte
  1418. * array is used as the default value.
  1419. */
  1420. extern JS_FRIEND_API(JSObject*)
  1421. JS_NewInt8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1422. uint32_t byteOffset, int32_t length);
  1423. extern JS_FRIEND_API(JSObject*)
  1424. JS_NewUint8ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1425. uint32_t byteOffset, int32_t length);
  1426. extern JS_FRIEND_API(JSObject*)
  1427. JS_NewUint8ClampedArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1428. uint32_t byteOffset, int32_t length);
  1429. extern JS_FRIEND_API(JSObject*)
  1430. JS_NewInt16ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1431. uint32_t byteOffset, int32_t length);
  1432. extern JS_FRIEND_API(JSObject*)
  1433. JS_NewUint16ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1434. uint32_t byteOffset, int32_t length);
  1435. extern JS_FRIEND_API(JSObject*)
  1436. JS_NewInt32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1437. uint32_t byteOffset, int32_t length);
  1438. extern JS_FRIEND_API(JSObject*)
  1439. JS_NewUint32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1440. uint32_t byteOffset, int32_t length);
  1441. extern JS_FRIEND_API(JSObject*)
  1442. JS_NewFloat32ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1443. uint32_t byteOffset, int32_t length);
  1444. extern JS_FRIEND_API(JSObject*)
  1445. JS_NewFloat64ArrayWithBuffer(JSContext* cx, JS::HandleObject arrayBuffer,
  1446. uint32_t byteOffset, int32_t length);
  1447. /**
  1448. * Create a new SharedArrayBuffer with the given byte length. This
  1449. * may only be called if
  1450. * JS::CompartmentCreationOptionsRef(cx).getSharedMemoryAndAtomicsEnabled() is
  1451. * true.
  1452. */
  1453. extern JS_FRIEND_API(JSObject*)
  1454. JS_NewSharedArrayBuffer(JSContext* cx, uint32_t nbytes);
  1455. /**
  1456. * Create a new ArrayBuffer with the given byte length.
  1457. */
  1458. extern JS_FRIEND_API(JSObject*)
  1459. JS_NewArrayBuffer(JSContext* cx, uint32_t nbytes);
  1460. /**
  1461. * Check whether obj supports JS_GetTypedArray* APIs. Note that this may return
  1462. * false if a security wrapper is encountered that denies the unwrapping. If
  1463. * this test or one of the JS_Is*Array tests succeeds, then it is safe to call
  1464. * the various accessor JSAPI calls defined below.
  1465. */
  1466. extern JS_FRIEND_API(bool)
  1467. JS_IsTypedArrayObject(JSObject* obj);
  1468. /**
  1469. * Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
  1470. * return false if a security wrapper is encountered that denies the
  1471. * unwrapping. If this test or one of the more specific tests succeeds, then it
  1472. * is safe to call the various ArrayBufferView accessor JSAPI calls defined
  1473. * below.
  1474. */
  1475. extern JS_FRIEND_API(bool)
  1476. JS_IsArrayBufferViewObject(JSObject* obj);
  1477. /*
  1478. * Test for specific typed array types (ArrayBufferView subtypes)
  1479. */
  1480. extern JS_FRIEND_API(bool)
  1481. JS_IsInt8Array(JSObject* obj);
  1482. extern JS_FRIEND_API(bool)
  1483. JS_IsUint8Array(JSObject* obj);
  1484. extern JS_FRIEND_API(bool)
  1485. JS_IsUint8ClampedArray(JSObject* obj);
  1486. extern JS_FRIEND_API(bool)
  1487. JS_IsInt16Array(JSObject* obj);
  1488. extern JS_FRIEND_API(bool)
  1489. JS_IsUint16Array(JSObject* obj);
  1490. extern JS_FRIEND_API(bool)
  1491. JS_IsInt32Array(JSObject* obj);
  1492. extern JS_FRIEND_API(bool)
  1493. JS_IsUint32Array(JSObject* obj);
  1494. extern JS_FRIEND_API(bool)
  1495. JS_IsFloat32Array(JSObject* obj);
  1496. extern JS_FRIEND_API(bool)
  1497. JS_IsFloat64Array(JSObject* obj);
  1498. /**
  1499. * Return the isShared flag of a typed array, which denotes whether
  1500. * the underlying buffer is a SharedArrayBuffer.
  1501. *
  1502. * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  1503. * be known that it would pass such a test: it is a typed array or a wrapper of
  1504. * a typed array, and the unwrapping will succeed.
  1505. */
  1506. extern JS_FRIEND_API(bool)
  1507. JS_GetTypedArraySharedness(JSObject* obj);
  1508. /*
  1509. * Test for specific typed array types (ArrayBufferView subtypes) and return
  1510. * the unwrapped object if so, else nullptr. Never throws.
  1511. */
  1512. namespace js {
  1513. extern JS_FRIEND_API(JSObject*)
  1514. UnwrapInt8Array(JSObject* obj);
  1515. extern JS_FRIEND_API(JSObject*)
  1516. UnwrapUint8Array(JSObject* obj);
  1517. extern JS_FRIEND_API(JSObject*)
  1518. UnwrapUint8ClampedArray(JSObject* obj);
  1519. extern JS_FRIEND_API(JSObject*)
  1520. UnwrapInt16Array(JSObject* obj);
  1521. extern JS_FRIEND_API(JSObject*)
  1522. UnwrapUint16Array(JSObject* obj);
  1523. extern JS_FRIEND_API(JSObject*)
  1524. UnwrapInt32Array(JSObject* obj);
  1525. extern JS_FRIEND_API(JSObject*)
  1526. UnwrapUint32Array(JSObject* obj);
  1527. extern JS_FRIEND_API(JSObject*)
  1528. UnwrapFloat32Array(JSObject* obj);
  1529. extern JS_FRIEND_API(JSObject*)
  1530. UnwrapFloat64Array(JSObject* obj);
  1531. extern JS_FRIEND_API(JSObject*)
  1532. UnwrapArrayBuffer(JSObject* obj);
  1533. extern JS_FRIEND_API(JSObject*)
  1534. UnwrapArrayBufferView(JSObject* obj);
  1535. extern JS_FRIEND_API(JSObject*)
  1536. UnwrapSharedArrayBuffer(JSObject* obj);
  1537. namespace detail {
  1538. extern JS_FRIEND_DATA(const Class* const) Int8ArrayClassPtr;
  1539. extern JS_FRIEND_DATA(const Class* const) Uint8ArrayClassPtr;
  1540. extern JS_FRIEND_DATA(const Class* const) Uint8ClampedArrayClassPtr;
  1541. extern JS_FRIEND_DATA(const Class* const) Int16ArrayClassPtr;
  1542. extern JS_FRIEND_DATA(const Class* const) Uint16ArrayClassPtr;
  1543. extern JS_FRIEND_DATA(const Class* const) Int32ArrayClassPtr;
  1544. extern JS_FRIEND_DATA(const Class* const) Uint32ArrayClassPtr;
  1545. extern JS_FRIEND_DATA(const Class* const) Float32ArrayClassPtr;
  1546. extern JS_FRIEND_DATA(const Class* const) Float64ArrayClassPtr;
  1547. const size_t TypedArrayLengthSlot = 1;
  1548. } // namespace detail
  1549. #define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
  1550. inline void \
  1551. Get ## Type ## ArrayLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, type** data) \
  1552. { \
  1553. MOZ_ASSERT(GetObjectClass(obj) == detail::Type ## ArrayClassPtr); \
  1554. const JS::Value& lenSlot = GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
  1555. *length = mozilla::AssertedCast<uint32_t>(lenSlot.toInt32()); \
  1556. *isSharedMemory = JS_GetTypedArraySharedness(obj); \
  1557. *data = static_cast<type*>(GetObjectPrivate(obj)); \
  1558. }
  1559. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
  1560. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
  1561. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
  1562. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
  1563. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
  1564. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
  1565. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
  1566. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
  1567. JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
  1568. #undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
  1569. // This one isn't inlined because it's rather tricky (by dint of having to deal
  1570. // with a dozen-plus classes and varying slot layouts.
  1571. extern JS_FRIEND_API(void)
  1572. GetArrayBufferViewLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
  1573. // This one isn't inlined because there are a bunch of different ArrayBuffer
  1574. // classes that would have to be individually handled here.
  1575. //
  1576. // There is an isShared out argument for API consistency (eases use from DOM).
  1577. // It will always be set to false.
  1578. extern JS_FRIEND_API(void)
  1579. GetArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
  1580. // Ditto for SharedArrayBuffer.
  1581. //
  1582. // There is an isShared out argument for API consistency (eases use from DOM).
  1583. // It will always be set to true.
  1584. extern JS_FRIEND_API(void)
  1585. GetSharedArrayBufferLengthAndData(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
  1586. } // namespace js
  1587. JS_FRIEND_API(uint8_t*)
  1588. JS_GetSharedArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1589. /*
  1590. * Unwrap Typed arrays all at once. Return nullptr without throwing if the
  1591. * object cannot be viewed as the correct typed array, or the typed array
  1592. * object on success, filling both outparameters.
  1593. */
  1594. extern JS_FRIEND_API(JSObject*)
  1595. JS_GetObjectAsInt8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int8_t** data);
  1596. extern JS_FRIEND_API(JSObject*)
  1597. JS_GetObjectAsUint8Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
  1598. extern JS_FRIEND_API(JSObject*)
  1599. JS_GetObjectAsUint8ClampedArray(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
  1600. extern JS_FRIEND_API(JSObject*)
  1601. JS_GetObjectAsInt16Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int16_t** data);
  1602. extern JS_FRIEND_API(JSObject*)
  1603. JS_GetObjectAsUint16Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint16_t** data);
  1604. extern JS_FRIEND_API(JSObject*)
  1605. JS_GetObjectAsInt32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, int32_t** data);
  1606. extern JS_FRIEND_API(JSObject*)
  1607. JS_GetObjectAsUint32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint32_t** data);
  1608. extern JS_FRIEND_API(JSObject*)
  1609. JS_GetObjectAsFloat32Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, float** data);
  1610. extern JS_FRIEND_API(JSObject*)
  1611. JS_GetObjectAsFloat64Array(JSObject* obj, uint32_t* length, bool* isSharedMemory, double** data);
  1612. extern JS_FRIEND_API(JSObject*)
  1613. JS_GetObjectAsArrayBufferView(JSObject* obj, uint32_t* length, bool* isSharedMemory, uint8_t** data);
  1614. /*
  1615. * Unwrap an ArrayBuffer, return nullptr if it's a different type.
  1616. */
  1617. extern JS_FRIEND_API(JSObject*)
  1618. JS_GetObjectAsArrayBuffer(JSObject* obj, uint32_t* length, uint8_t** data);
  1619. /*
  1620. * Get the type of elements in a typed array, or MaxTypedArrayViewType if a DataView.
  1621. *
  1622. * |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
  1623. * be known that it would pass such a test: it is an ArrayBufferView or a
  1624. * wrapper of an ArrayBufferView, and the unwrapping will succeed.
  1625. */
  1626. extern JS_FRIEND_API(js::Scalar::Type)
  1627. JS_GetArrayBufferViewType(JSObject* obj);
  1628. extern JS_FRIEND_API(js::Scalar::Type)
  1629. JS_GetSharedArrayBufferViewType(JSObject* obj);
  1630. /*
  1631. * Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
  1632. * return false if a security wrapper is encountered that denies the
  1633. * unwrapping. If this test succeeds, then it is safe to call the various
  1634. * accessor JSAPI calls defined below.
  1635. */
  1636. extern JS_FRIEND_API(bool)
  1637. JS_IsArrayBufferObject(JSObject* obj);
  1638. extern JS_FRIEND_API(bool)
  1639. JS_IsSharedArrayBufferObject(JSObject* obj);
  1640. /**
  1641. * Return the available byte length of an array buffer.
  1642. *
  1643. * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
  1644. * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
  1645. * ArrayBuffer, and the unwrapping will succeed.
  1646. */
  1647. extern JS_FRIEND_API(uint32_t)
  1648. JS_GetArrayBufferByteLength(JSObject* obj);
  1649. extern JS_FRIEND_API(uint32_t)
  1650. JS_GetSharedArrayBufferByteLength(JSObject* obj);
  1651. /**
  1652. * Return true if the arrayBuffer contains any data. This will return false for
  1653. * ArrayBuffer.prototype and detached ArrayBuffers.
  1654. *
  1655. * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
  1656. * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
  1657. * ArrayBuffer, and the unwrapping will succeed.
  1658. */
  1659. extern JS_FRIEND_API(bool)
  1660. JS_ArrayBufferHasData(JSObject* obj);
  1661. /**
  1662. * Return a pointer to the start of the data referenced by a typed array. The
  1663. * data is still owned by the typed array, and should not be modified on
  1664. * another thread. Furthermore, the pointer can become invalid on GC (if the
  1665. * data is small and fits inside the array's GC header), so callers must take
  1666. * care not to hold on across anything that could GC.
  1667. *
  1668. * |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
  1669. * that it would pass such a test: it is an ArrayBuffer or a wrapper of an
  1670. * ArrayBuffer, and the unwrapping will succeed.
  1671. *
  1672. * *isSharedMemory will be set to false, the argument is present to simplify
  1673. * its use from code that also interacts with SharedArrayBuffer.
  1674. */
  1675. extern JS_FRIEND_API(uint8_t*)
  1676. JS_GetArrayBufferData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1677. /**
  1678. * Check whether the obj is ArrayBufferObject and memory mapped. Note that this
  1679. * may return false if a security wrapper is encountered that denies the
  1680. * unwrapping.
  1681. */
  1682. extern JS_FRIEND_API(bool)
  1683. JS_IsMappedArrayBufferObject(JSObject* obj);
  1684. /**
  1685. * Return the number of elements in a typed array.
  1686. *
  1687. * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  1688. * be known that it would pass such a test: it is a typed array or a wrapper of
  1689. * a typed array, and the unwrapping will succeed.
  1690. */
  1691. extern JS_FRIEND_API(uint32_t)
  1692. JS_GetTypedArrayLength(JSObject* obj);
  1693. /**
  1694. * Return the byte offset from the start of an array buffer to the start of a
  1695. * typed array view.
  1696. *
  1697. * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  1698. * be known that it would pass such a test: it is a typed array or a wrapper of
  1699. * a typed array, and the unwrapping will succeed.
  1700. */
  1701. extern JS_FRIEND_API(uint32_t)
  1702. JS_GetTypedArrayByteOffset(JSObject* obj);
  1703. /**
  1704. * Return the byte length of a typed array.
  1705. *
  1706. * |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
  1707. * be known that it would pass such a test: it is a typed array or a wrapper of
  1708. * a typed array, and the unwrapping will succeed.
  1709. */
  1710. extern JS_FRIEND_API(uint32_t)
  1711. JS_GetTypedArrayByteLength(JSObject* obj);
  1712. /**
  1713. * Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
  1714. * return false if a security wrapper is encountered that denies the
  1715. * unwrapping.
  1716. */
  1717. extern JS_FRIEND_API(bool)
  1718. JS_IsArrayBufferViewObject(JSObject* obj);
  1719. /**
  1720. * More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
  1721. */
  1722. extern JS_FRIEND_API(uint32_t)
  1723. JS_GetArrayBufferViewByteLength(JSObject* obj);
  1724. /*
  1725. * Return a pointer to the start of the data referenced by a typed array. The
  1726. * data is still owned by the typed array, and should not be modified on
  1727. * another thread. Furthermore, the pointer can become invalid on GC (if the
  1728. * data is small and fits inside the array's GC header), so callers must take
  1729. * care not to hold on across anything that could GC.
  1730. *
  1731. * |obj| must have passed a JS_Is*Array test, or somehow be known that it would
  1732. * pass such a test: it is a typed array or a wrapper of a typed array, and the
  1733. * unwrapping will succeed.
  1734. *
  1735. * *isSharedMemory will be set to true if the typed array maps a
  1736. * SharedArrayBuffer, otherwise to false.
  1737. */
  1738. extern JS_FRIEND_API(int8_t*)
  1739. JS_GetInt8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1740. extern JS_FRIEND_API(uint8_t*)
  1741. JS_GetUint8ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1742. extern JS_FRIEND_API(uint8_t*)
  1743. JS_GetUint8ClampedArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1744. extern JS_FRIEND_API(int16_t*)
  1745. JS_GetInt16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1746. extern JS_FRIEND_API(uint16_t*)
  1747. JS_GetUint16ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1748. extern JS_FRIEND_API(int32_t*)
  1749. JS_GetInt32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1750. extern JS_FRIEND_API(uint32_t*)
  1751. JS_GetUint32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1752. extern JS_FRIEND_API(float*)
  1753. JS_GetFloat32ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1754. extern JS_FRIEND_API(double*)
  1755. JS_GetFloat64ArrayData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1756. /**
  1757. * Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
  1758. * versions when possible.
  1759. */
  1760. extern JS_FRIEND_API(void*)
  1761. JS_GetArrayBufferViewData(JSObject* obj, bool* isSharedMemory, const JS::AutoCheckCannotGC&);
  1762. /**
  1763. * Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
  1764. * This may return a detached buffer. |obj| must be an object that would
  1765. * return true for JS_IsArrayBufferViewObject().
  1766. */
  1767. extern JS_FRIEND_API(JSObject*)
  1768. JS_GetArrayBufferViewBuffer(JSContext* cx, JS::HandleObject obj, bool* isSharedMemory);
  1769. /**
  1770. * Detach an ArrayBuffer, causing all associated views to no longer refer to
  1771. * the ArrayBuffer's original attached memory.
  1772. *
  1773. * The |changeData| argument is obsolete and ignored.
  1774. */
  1775. extern JS_FRIEND_API(bool)
  1776. JS_DetachArrayBuffer(JSContext* cx, JS::HandleObject obj);
  1777. /**
  1778. * Check whether the obj is a detached ArrayBufferObject. Note that this may
  1779. * return false if a security wrapper is encountered that denies the
  1780. * unwrapping.
  1781. */
  1782. extern JS_FRIEND_API(bool)
  1783. JS_IsDetachedArrayBufferObject(JSObject* obj);
  1784. /**
  1785. * Check whether obj supports JS_GetDataView* APIs.
  1786. */
  1787. JS_FRIEND_API(bool)
  1788. JS_IsDataViewObject(JSObject* obj);
  1789. /**
  1790. * Create a new DataView using the given ArrayBuffer for storage. The given
  1791. * buffer must be an ArrayBuffer (or a cross-compartment wrapper of an
  1792. * ArrayBuffer), and the offset and length must fit within the bounds of the
  1793. * arrayBuffer. Currently, nullptr will be returned and an exception will be
  1794. * thrown if these conditions do not hold, but do not depend on that behavior.
  1795. */
  1796. JS_FRIEND_API(JSObject*)
  1797. JS_NewDataView(JSContext* cx, JS::HandleObject arrayBuffer, uint32_t byteOffset, int32_t byteLength);
  1798. /**
  1799. * Return the byte offset of a data view into its array buffer. |obj| must be a
  1800. * DataView.
  1801. *
  1802. * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
  1803. * it would pass such a test: it is a data view or a wrapper of a data view,
  1804. * and the unwrapping will succeed.
  1805. */
  1806. JS_FRIEND_API(uint32_t)
  1807. JS_GetDataViewByteOffset(JSObject* obj);
  1808. /**
  1809. * Return the byte length of a data view.
  1810. *
  1811. * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
  1812. * it would pass such a test: it is a data view or a wrapper of a data view,
  1813. * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
  1814. * unable to assert when unwrapping should be disallowed.
  1815. */
  1816. JS_FRIEND_API(uint32_t)
  1817. JS_GetDataViewByteLength(JSObject* obj);
  1818. /**
  1819. * Return a pointer to the beginning of the data referenced by a DataView.
  1820. *
  1821. * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
  1822. * it would pass such a test: it is a data view or a wrapper of a data view,
  1823. * and the unwrapping will succeed. If cx is nullptr, then DEBUG builds may be
  1824. * unable to assert when unwrapping should be disallowed.
  1825. */
  1826. JS_FRIEND_API(void*)
  1827. JS_GetDataViewData(JSObject* obj, const JS::AutoCheckCannotGC&);
  1828. namespace js {
  1829. /**
  1830. * Add a watchpoint -- in the Object.prototype.watch sense -- to |obj| for the
  1831. * property |id|, using the callable object |callable| as the function to be
  1832. * called for notifications.
  1833. *
  1834. * This is an internal function exposed -- temporarily -- only so that DOM
  1835. * proxies can be watchable. Don't use it! We'll soon kill off the
  1836. * Object.prototype.{,un}watch functions, at which point this will go too.
  1837. */
  1838. extern JS_FRIEND_API(bool)
  1839. WatchGuts(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
  1840. /**
  1841. * Remove a watchpoint -- in the Object.prototype.watch sense -- from |obj| for
  1842. * the property |id|.
  1843. *
  1844. * This is an internal function exposed -- temporarily -- only so that DOM
  1845. * proxies can be watchable. Don't use it! We'll soon kill off the
  1846. * Object.prototype.{,un}watch functions, at which point this will go too.
  1847. */
  1848. extern JS_FRIEND_API(bool)
  1849. UnwatchGuts(JSContext* cx, JS::HandleObject obj, JS::HandleId id);
  1850. namespace jit {
  1851. enum class InlinableNative : uint16_t;
  1852. } // namespace jit
  1853. } // namespace js
  1854. /**
  1855. * A class, expected to be passed by value, which represents the CallArgs for a
  1856. * JSJitGetterOp.
  1857. */
  1858. class JSJitGetterCallArgs : protected JS::MutableHandleValue
  1859. {
  1860. public:
  1861. explicit JSJitGetterCallArgs(const JS::CallArgs& args)
  1862. : JS::MutableHandleValue(args.rval())
  1863. {}
  1864. explicit JSJitGetterCallArgs(JS::RootedValue* rooted)
  1865. : JS::MutableHandleValue(rooted)
  1866. {}
  1867. JS::MutableHandleValue rval() {
  1868. return *this;
  1869. }
  1870. };
  1871. /**
  1872. * A class, expected to be passed by value, which represents the CallArgs for a
  1873. * JSJitSetterOp.
  1874. */
  1875. class JSJitSetterCallArgs : protected JS::MutableHandleValue
  1876. {
  1877. public:
  1878. explicit JSJitSetterCallArgs(const JS::CallArgs& args)
  1879. : JS::MutableHandleValue(args[0])
  1880. {}
  1881. JS::MutableHandleValue operator[](unsigned i) {
  1882. MOZ_ASSERT(i == 0);
  1883. return *this;
  1884. }
  1885. unsigned length() const { return 1; }
  1886. // Add get() or maybe hasDefined() as needed
  1887. };
  1888. struct JSJitMethodCallArgsTraits;
  1889. /**
  1890. * A class, expected to be passed by reference, which represents the CallArgs
  1891. * for a JSJitMethodOp.
  1892. */
  1893. class JSJitMethodCallArgs : protected JS::detail::CallArgsBase<JS::detail::NoUsedRval>
  1894. {
  1895. private:
  1896. typedef JS::detail::CallArgsBase<JS::detail::NoUsedRval> Base;
  1897. friend struct JSJitMethodCallArgsTraits;
  1898. public:
  1899. explicit JSJitMethodCallArgs(const JS::CallArgs& args) {
  1900. argv_ = args.array();
  1901. argc_ = args.length();
  1902. }
  1903. JS::MutableHandleValue rval() const {
  1904. return Base::rval();
  1905. }
  1906. unsigned length() const { return Base::length(); }
  1907. JS::MutableHandleValue operator[](unsigned i) const {
  1908. return Base::operator[](i);
  1909. }
  1910. bool hasDefined(unsigned i) const {
  1911. return Base::hasDefined(i);
  1912. }
  1913. JSObject& callee() const {
  1914. // We can't use Base::callee() because that will try to poke at
  1915. // this->usedRval_, which we don't have.
  1916. return argv_[-2].toObject();
  1917. }
  1918. JS::HandleValue get(unsigned i) const {
  1919. return Base::get(i);
  1920. }
  1921. };
  1922. struct JSJitMethodCallArgsTraits
  1923. {
  1924. static const size_t offsetOfArgv = offsetof(JSJitMethodCallArgs, argv_);
  1925. static const size_t offsetOfArgc = offsetof(JSJitMethodCallArgs, argc_);
  1926. };
  1927. typedef bool
  1928. (* JSJitGetterOp)(JSContext* cx, JS::HandleObject thisObj,
  1929. void* specializedThis, JSJitGetterCallArgs args);
  1930. typedef bool
  1931. (* JSJitSetterOp)(JSContext* cx, JS::HandleObject thisObj,
  1932. void* specializedThis, JSJitSetterCallArgs args);
  1933. typedef bool
  1934. (* JSJitMethodOp)(JSContext* cx, JS::HandleObject thisObj,
  1935. void* specializedThis, const JSJitMethodCallArgs& args);
  1936. /**
  1937. * This struct contains metadata passed from the DOM to the JS Engine for JIT
  1938. * optimizations on DOM property accessors. Eventually, this should be made
  1939. * available to general JSAPI users, but we are not currently ready to do so.
  1940. */
  1941. struct JSJitInfo {
  1942. enum OpType {
  1943. Getter,
  1944. Setter,
  1945. Method,
  1946. StaticMethod,
  1947. InlinableNative,
  1948. // Must be last
  1949. OpTypeCount
  1950. };
  1951. enum ArgType {
  1952. // Basic types
  1953. String = (1 << 0),
  1954. Integer = (1 << 1), // Only 32-bit or less
  1955. Double = (1 << 2), // Maybe we want to add Float sometime too
  1956. Boolean = (1 << 3),
  1957. Object = (1 << 4),
  1958. Null = (1 << 5),
  1959. // And derived types
  1960. Numeric = Integer | Double,
  1961. // Should "Primitive" use the WebIDL definition, which
  1962. // excludes string and null, or the typical JS one that includes them?
  1963. Primitive = Numeric | Boolean | Null | String,
  1964. ObjectOrNull = Object | Null,
  1965. Any = ObjectOrNull | Primitive,
  1966. // Our sentinel value.
  1967. ArgTypeListEnd = (1 << 31)
  1968. };
  1969. static_assert(Any & String, "Any must include String.");
  1970. static_assert(Any & Integer, "Any must include Integer.");
  1971. static_assert(Any & Double, "Any must include Double.");
  1972. static_assert(Any & Boolean, "Any must include Boolean.");
  1973. static_assert(Any & Object, "Any must include Object.");
  1974. static_assert(Any & Null, "Any must include Null.");
  1975. /**
  1976. * An enum that describes what this getter/setter/method aliases. This
  1977. * determines what things can be hoisted past this call, and if this
  1978. * call is movable what it can be hoisted past.
  1979. */
  1980. enum AliasSet {
  1981. /**
  1982. * Alias nothing: a constant value, getting it can't affect any other
  1983. * values, nothing can affect it.
  1984. */
  1985. AliasNone,
  1986. /**
  1987. * Alias things that can modify the DOM but nothing else. Doing the
  1988. * call can't affect the behavior of any other function.
  1989. */
  1990. AliasDOMSets,
  1991. /**
  1992. * Alias the world. Calling this can change arbitrary values anywhere
  1993. * in the system. Most things fall in this bucket.
  1994. */
  1995. AliasEverything,
  1996. /** Must be last. */
  1997. AliasSetCount
  1998. };
  1999. bool needsOuterizedThisObject() const
  2000. {
  2001. return type() != Getter && type() != Setter;
  2002. }
  2003. bool isTypedMethodJitInfo() const
  2004. {
  2005. return isTypedMethod;
  2006. }
  2007. OpType type() const
  2008. {
  2009. return OpType(type_);
  2010. }
  2011. AliasSet aliasSet() const
  2012. {
  2013. return AliasSet(aliasSet_);
  2014. }
  2015. JSValueType returnType() const
  2016. {
  2017. return JSValueType(returnType_);
  2018. }
  2019. union {
  2020. JSJitGetterOp getter;
  2021. JSJitSetterOp setter;
  2022. JSJitMethodOp method;
  2023. /** A DOM static method, used for Promise wrappers */
  2024. JSNative staticMethod;
  2025. };
  2026. union {
  2027. uint16_t protoID;
  2028. js::jit::InlinableNative inlinableNative;
  2029. };
  2030. union {
  2031. uint16_t depth;
  2032. // Additional opcode for some InlinableNative functions.
  2033. uint16_t nativeOp;
  2034. };
  2035. // These fields are carefully packed to take up 4 bytes. If you need more
  2036. // bits for whatever reason, please see if you can steal bits from existing
  2037. // fields before adding more members to this structure.
  2038. #define JITINFO_OP_TYPE_BITS 4
  2039. #define JITINFO_ALIAS_SET_BITS 4
  2040. #define JITINFO_RETURN_TYPE_BITS 8
  2041. #define JITINFO_SLOT_INDEX_BITS 10
  2042. /** The OpType that says what sort of function we are. */
  2043. uint32_t type_ : JITINFO_OP_TYPE_BITS;
  2044. /**
  2045. * The alias set for this op. This is a _minimal_ alias set; in
  2046. * particular for a method it does not include whatever argument
  2047. * conversions might do. That's covered by argTypes and runtime
  2048. * analysis of the actual argument types being passed in.
  2049. */
  2050. uint32_t aliasSet_ : JITINFO_ALIAS_SET_BITS;
  2051. /** The return type tag. Might be JSVAL_TYPE_UNKNOWN. */
  2052. uint32_t returnType_ : JITINFO_RETURN_TYPE_BITS;
  2053. static_assert(OpTypeCount <= (1 << JITINFO_OP_TYPE_BITS),
  2054. "Not enough space for OpType");
  2055. static_assert(AliasSetCount <= (1 << JITINFO_ALIAS_SET_BITS),
  2056. "Not enough space for AliasSet");
  2057. static_assert((sizeof(JSValueType) * 8) <= JITINFO_RETURN_TYPE_BITS,
  2058. "Not enough space for JSValueType");
  2059. #undef JITINFO_RETURN_TYPE_BITS
  2060. #undef JITINFO_ALIAS_SET_BITS
  2061. #undef JITINFO_OP_TYPE_BITS
  2062. /** Is op fallible? False in setters. */
  2063. uint32_t isInfallible : 1;
  2064. /**
  2065. * Is op movable? To be movable the op must
  2066. * not AliasEverything, but even that might
  2067. * not be enough (e.g. in cases when it can
  2068. * throw or is explicitly not movable).
  2069. */
  2070. uint32_t isMovable : 1;
  2071. /**
  2072. * Can op be dead-code eliminated? Again, this
  2073. * depends on whether the op can throw, in
  2074. * addition to the alias set.
  2075. */
  2076. uint32_t isEliminatable : 1;
  2077. // XXXbz should we have a JSValueType for the type of the member?
  2078. /**
  2079. * True if this is a getter that can always
  2080. * get the value from a slot of the "this" object.
  2081. */
  2082. uint32_t isAlwaysInSlot : 1;
  2083. /**
  2084. * True if this is a getter that can sometimes (if the slot doesn't contain
  2085. * UndefinedValue()) get the value from a slot of the "this" object.
  2086. */
  2087. uint32_t isLazilyCachedInSlot : 1;
  2088. /** True if this is an instance of JSTypedMethodJitInfo. */
  2089. uint32_t isTypedMethod : 1;
  2090. /**
  2091. * If isAlwaysInSlot or isSometimesInSlot is true,
  2092. * the index of the slot to get the value from.
  2093. * Otherwise 0.
  2094. */
  2095. uint32_t slotIndex : JITINFO_SLOT_INDEX_BITS;
  2096. static const size_t maxSlotIndex = (1 << JITINFO_SLOT_INDEX_BITS) - 1;
  2097. #undef JITINFO_SLOT_INDEX_BITS
  2098. };
  2099. static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),
  2100. "There are several thousand instances of JSJitInfo stored in "
  2101. "a binary. Please don't increase its space requirements without "
  2102. "verifying that there is no other way forward (better packing, "
  2103. "smaller datatypes for fields, subclassing, etc.).");
  2104. struct JSTypedMethodJitInfo
  2105. {
  2106. // We use C-style inheritance here, rather than C++ style inheritance
  2107. // because not all compilers support brace-initialization for non-aggregate
  2108. // classes. Using C++ style inheritance and constructors instead of
  2109. // brace-initialization would also force the creation of static
  2110. // constructors (on some compilers) when JSJitInfo and JSTypedMethodJitInfo
  2111. // structures are declared. Since there can be several thousand of these
  2112. // structures present and we want to have roughly equivalent performance
  2113. // across a range of compilers, we do things manually.
  2114. JSJitInfo base;
  2115. const JSJitInfo::ArgType* const argTypes; /* For a method, a list of sets of
  2116. types that the function
  2117. expects. This can be used,
  2118. for example, to figure out
  2119. when argument coercions can
  2120. have side-effects. */
  2121. };
  2122. namespace js {
  2123. static MOZ_ALWAYS_INLINE shadow::Function*
  2124. FunctionObjectToShadowFunction(JSObject* fun)
  2125. {
  2126. MOZ_ASSERT(GetObjectClass(fun) == FunctionClassPtr);
  2127. return reinterpret_cast<shadow::Function*>(fun);
  2128. }
  2129. /* Statically asserted in jsfun.h. */
  2130. static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x0201;
  2131. // Return whether the given function object is native.
  2132. static MOZ_ALWAYS_INLINE bool
  2133. FunctionObjectIsNative(JSObject* fun)
  2134. {
  2135. return !(FunctionObjectToShadowFunction(fun)->flags & JS_FUNCTION_INTERPRETED_BITS);
  2136. }
  2137. static MOZ_ALWAYS_INLINE JSNative
  2138. GetFunctionObjectNative(JSObject* fun)
  2139. {
  2140. MOZ_ASSERT(FunctionObjectIsNative(fun));
  2141. return FunctionObjectToShadowFunction(fun)->native;
  2142. }
  2143. } // namespace js
  2144. static MOZ_ALWAYS_INLINE const JSJitInfo*
  2145. FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
  2146. {
  2147. MOZ_ASSERT(js::FunctionObjectIsNative(&v.toObject()));
  2148. return js::FunctionObjectToShadowFunction(&v.toObject())->jitinfo;
  2149. }
  2150. static MOZ_ALWAYS_INLINE void
  2151. SET_JITINFO(JSFunction * func, const JSJitInfo* info)
  2152. {
  2153. js::shadow::Function* fun = reinterpret_cast<js::shadow::Function*>(func);
  2154. MOZ_ASSERT(!(fun->flags & js::JS_FUNCTION_INTERPRETED_BITS));
  2155. fun->jitinfo = info;
  2156. }
  2157. /*
  2158. * Engine-internal extensions of jsid. This code is here only until we
  2159. * eliminate Gecko's dependencies on it!
  2160. */
  2161. static MOZ_ALWAYS_INLINE jsid
  2162. JSID_FROM_BITS(size_t bits)
  2163. {
  2164. jsid id;
  2165. JSID_BITS(id) = bits;
  2166. return id;
  2167. }
  2168. namespace js {
  2169. namespace detail {
  2170. bool IdMatchesAtom(jsid id, JSAtom* atom);
  2171. } // namespace detail
  2172. } // namespace js
  2173. /**
  2174. * Must not be used on atoms that are representable as integer jsids.
  2175. * Prefer NameToId or AtomToId over this function:
  2176. *
  2177. * A PropertyName is an atom that does not contain an integer in the range
  2178. * [0, UINT32_MAX]. However, jsid can only hold an integer in the range
  2179. * [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of
  2180. * integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be
  2181. * the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most
  2182. * cases when creating a jsid, code does not have to care about this corner
  2183. * case because:
  2184. *
  2185. * - When given an arbitrary JSAtom*, AtomToId must be used, which checks for
  2186. * integer atoms representable as integer jsids, and does this conversion.
  2187. *
  2188. * - When given a PropertyName*, NameToId can be used which which does not need
  2189. * to do any dynamic checks.
  2190. *
  2191. * Thus, it is only the rare third case which needs this function, which
  2192. * handles any JSAtom* that is known not to be representable with an int jsid.
  2193. */
  2194. static MOZ_ALWAYS_INLINE jsid
  2195. NON_INTEGER_ATOM_TO_JSID(JSAtom* atom)
  2196. {
  2197. MOZ_ASSERT(((size_t)atom & 0x7) == 0);
  2198. jsid id = JSID_FROM_BITS((size_t)atom);
  2199. MOZ_ASSERT(js::detail::IdMatchesAtom(id, atom));
  2200. return id;
  2201. }
  2202. /* All strings stored in jsids are atomized, but are not necessarily property names. */
  2203. static MOZ_ALWAYS_INLINE bool
  2204. JSID_IS_ATOM(jsid id)
  2205. {
  2206. return JSID_IS_STRING(id);
  2207. }
  2208. static MOZ_ALWAYS_INLINE bool
  2209. JSID_IS_ATOM(jsid id, JSAtom* atom)
  2210. {
  2211. return id == JSID_FROM_BITS((size_t)atom);
  2212. }
  2213. static MOZ_ALWAYS_INLINE JSAtom*
  2214. JSID_TO_ATOM(jsid id)
  2215. {
  2216. return (JSAtom*)JSID_TO_STRING(id);
  2217. }
  2218. JS_STATIC_ASSERT(sizeof(jsid) == sizeof(void*));
  2219. namespace js {
  2220. static MOZ_ALWAYS_INLINE JS::Value
  2221. IdToValue(jsid id)
  2222. {
  2223. if (JSID_IS_STRING(id))
  2224. return JS::StringValue(JSID_TO_STRING(id));
  2225. if (JSID_IS_INT(id))
  2226. return JS::Int32Value(JSID_TO_INT(id));
  2227. if (JSID_IS_SYMBOL(id))
  2228. return JS::SymbolValue(JSID_TO_SYMBOL(id));
  2229. MOZ_ASSERT(JSID_IS_VOID(id));
  2230. return JS::UndefinedValue();
  2231. }
  2232. /**
  2233. * If the embedder has registered a ScriptEnvironmentPreparer,
  2234. * PrepareScriptEnvironmentAndInvoke will call the preparer's 'invoke' method
  2235. * with the given |closure|, with the assumption that the preparer will set up
  2236. * any state necessary to run script in |scope|, invoke |closure| with a valid
  2237. * JSContext*, report any exceptions thrown from the closure, and return.
  2238. *
  2239. * If no preparer is registered, PrepareScriptEnvironmentAndInvoke will assert
  2240. * that |rt| has exactly one JSContext associated with it, enter the compartment
  2241. * of |scope| on that context, and invoke |closure|.
  2242. *
  2243. * In both cases, PrepareScriptEnvironmentAndInvoke will report any exceptions
  2244. * that are thrown by the closure. Consumers who want to propagate back
  2245. * whether the closure succeeded should do so via members of the closure
  2246. * itself.
  2247. */
  2248. struct ScriptEnvironmentPreparer {
  2249. struct Closure {
  2250. virtual bool operator()(JSContext* cx) = 0;
  2251. };
  2252. virtual void invoke(JS::HandleObject scope, Closure& closure) = 0;
  2253. };
  2254. extern JS_FRIEND_API(void)
  2255. PrepareScriptEnvironmentAndInvoke(JSContext* cx, JS::HandleObject scope,
  2256. ScriptEnvironmentPreparer::Closure& closure);
  2257. JS_FRIEND_API(void)
  2258. SetScriptEnvironmentPreparer(JSContext* cx, ScriptEnvironmentPreparer* preparer);
  2259. enum CTypesActivityType {
  2260. CTYPES_CALL_BEGIN,
  2261. CTYPES_CALL_END,
  2262. CTYPES_CALLBACK_BEGIN,
  2263. CTYPES_CALLBACK_END
  2264. };
  2265. typedef void
  2266. (* CTypesActivityCallback)(JSContext* cx, CTypesActivityType type);
  2267. /**
  2268. * Sets a callback that is run whenever js-ctypes is about to be used when
  2269. * calling into C.
  2270. */
  2271. JS_FRIEND_API(void)
  2272. SetCTypesActivityCallback(JSContext* cx, CTypesActivityCallback cb);
  2273. class MOZ_RAII JS_FRIEND_API(AutoCTypesActivityCallback) {
  2274. private:
  2275. JSContext* cx;
  2276. CTypesActivityCallback callback;
  2277. CTypesActivityType endType;
  2278. MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  2279. public:
  2280. AutoCTypesActivityCallback(JSContext* cx, CTypesActivityType beginType,
  2281. CTypesActivityType endType
  2282. MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
  2283. ~AutoCTypesActivityCallback() {
  2284. DoEndCallback();
  2285. }
  2286. void DoEndCallback() {
  2287. if (callback) {
  2288. callback(cx, endType);
  2289. callback = nullptr;
  2290. }
  2291. }
  2292. };
  2293. // Abstract base class for objects that build allocation metadata for JavaScript
  2294. // values.
  2295. struct AllocationMetadataBuilder {
  2296. AllocationMetadataBuilder() { }
  2297. // Return a metadata object for the newly constructed object |obj|, or
  2298. // nullptr if there's no metadata to attach.
  2299. //
  2300. // Implementations should treat all errors as fatal; there is no way to
  2301. // report errors from this callback. In particular, the caller provides an
  2302. // oomUnsafe for overriding implementations to use.
  2303. virtual JSObject* build(JSContext* cx, JS::HandleObject obj,
  2304. AutoEnterOOMUnsafeRegion& oomUnsafe) const
  2305. {
  2306. return nullptr;
  2307. }
  2308. };
  2309. /**
  2310. * Specify a callback to invoke when creating each JS object in the current
  2311. * compartment, which may return a metadata object to associate with the
  2312. * object.
  2313. */
  2314. JS_FRIEND_API(void)
  2315. SetAllocationMetadataBuilder(JSContext* cx, const AllocationMetadataBuilder *callback);
  2316. /** Get the metadata associated with an object. */
  2317. JS_FRIEND_API(JSObject*)
  2318. GetAllocationMetadata(JSObject* obj);
  2319. JS_FRIEND_API(bool)
  2320. GetElementsWithAdder(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver,
  2321. uint32_t begin, uint32_t end, js::ElementAdder* adder);
  2322. JS_FRIEND_API(bool)
  2323. ForwardToNative(JSContext* cx, JSNative native, const JS::CallArgs& args);
  2324. /**
  2325. * Helper function for HTMLDocument and HTMLFormElement.
  2326. *
  2327. * These are the only two interfaces that have [OverrideBuiltins], a named
  2328. * getter, and no named setter. They're implemented as proxies with a custom
  2329. * getOwnPropertyDescriptor() method. Unfortunately, overriding
  2330. * getOwnPropertyDescriptor() automatically affects the behavior of set(),
  2331. * which normally is just common sense but is *not* desired for these two
  2332. * interfaces.
  2333. *
  2334. * The fix is for these two interfaces to override set() to ignore the
  2335. * getOwnPropertyDescriptor() override.
  2336. *
  2337. * SetPropertyIgnoringNamedGetter is exposed to make it easier to override
  2338. * set() in this way. It carries out all the steps of BaseProxyHandler::set()
  2339. * except the initial getOwnPropertyDescriptor() call. The caller must supply
  2340. * that descriptor as the 'ownDesc' parameter.
  2341. *
  2342. * Implemented in proxy/BaseProxyHandler.cpp.
  2343. */
  2344. JS_FRIEND_API(bool)
  2345. SetPropertyIgnoringNamedGetter(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
  2346. JS::HandleValue v, JS::HandleValue receiver,
  2347. JS::Handle<JS::PropertyDescriptor> ownDesc,
  2348. JS::ObjectOpResult& result);
  2349. JS_FRIEND_API(void)
  2350. ReportASCIIErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
  2351. // This function is for one specific use case, please don't use this for anything else!
  2352. extern JS_FRIEND_API(bool)
  2353. ExecuteInGlobalAndReturnScope(JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
  2354. JS::MutableHandleObject scope);
  2355. #if defined(XP_WIN) && defined(_WIN64)
  2356. // Parameters use void* types to avoid #including windows.h. The return value of
  2357. // this function is returned from the exception handler.
  2358. typedef long
  2359. (*JitExceptionHandler)(void* exceptionRecord, // PEXECTION_RECORD
  2360. void* context); // PCONTEXT
  2361. /**
  2362. * Windows uses "structured exception handling" to handle faults. When a fault
  2363. * occurs, the stack is searched for a handler (similar to C++ exception
  2364. * handling). If the search does not find a handler, the "unhandled exception
  2365. * filter" is called. Breakpad uses the unhandled exception filter to do crash
  2366. * reporting. Unfortunately, on Win64, JIT code on the stack completely throws
  2367. * off this unwinding process and prevents the unhandled exception filter from
  2368. * being called. The reason is that Win64 requires unwind information be
  2369. * registered for all code regions and JIT code has none. While it is possible
  2370. * to register full unwind information for JIT code, this is a lot of work (one
  2371. * has to be able to recover the frame pointer at any PC) so instead we register
  2372. * a handler for all JIT code that simply calls breakpad's unhandled exception
  2373. * filter (which will perform crash reporting and then terminate the process).
  2374. * This would be wrong if there was an outer __try block that expected to handle
  2375. * the fault, but this is not generally allowed.
  2376. *
  2377. * Gecko must call SetJitExceptionFilter before any JIT code is compiled and
  2378. * only once per process.
  2379. */
  2380. extern JS_FRIEND_API(void)
  2381. SetJitExceptionHandler(JitExceptionHandler handler);
  2382. #endif
  2383. /**
  2384. * Get the nearest enclosing with environment object for a given function. If
  2385. * the function is not scripted or is not enclosed by a with scope, returns
  2386. * the global.
  2387. */
  2388. extern JS_FRIEND_API(JSObject*)
  2389. GetNearestEnclosingWithEnvironmentObjectForFunction(JSFunction* fun);
  2390. /**
  2391. * Get the first SavedFrame object in this SavedFrame stack whose principals are
  2392. * subsumed by the cx's principals. If there is no such frame, return nullptr.
  2393. *
  2394. * Do NOT pass a non-SavedFrame object here.
  2395. *
  2396. * The savedFrame and cx do not need to be in the same compartment.
  2397. */
  2398. extern JS_FRIEND_API(JSObject*)
  2399. GetFirstSubsumedSavedFrame(JSContext* cx, JS::HandleObject savedFrame, JS::SavedFrameSelfHosted selfHosted);
  2400. extern JS_FRIEND_API(bool)
  2401. ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
  2402. extern JS_FRIEND_API(JSObject*)
  2403. ConvertArgsToArray(JSContext* cx, const JS::CallArgs& args);
  2404. /**
  2405. * Window and WindowProxy
  2406. *
  2407. * The functions below have to do with Windows and WindowProxies. There's an
  2408. * invariant that actual Window objects (the global objects of web pages) are
  2409. * never directly exposed to script. Instead we often substitute a WindowProxy.
  2410. *
  2411. * The environment chain, on the other hand, contains the Window and never its
  2412. * WindowProxy.
  2413. *
  2414. * As a result, we have calls to these "substitute-this-object-for-that-object"
  2415. * functions sprinkled at apparently arbitrary (but actually *very* carefully
  2416. * and nervously selected) places throughout the engine and indeed the
  2417. * universe.
  2418. */
  2419. /**
  2420. * Tell the JS engine which Class is used for WindowProxy objects. Used by the
  2421. * functions below.
  2422. */
  2423. extern JS_FRIEND_API(void)
  2424. SetWindowProxyClass(JSContext* cx, const Class* clasp);
  2425. /**
  2426. * Associates a WindowProxy with a Window (global object). `windowProxy` must
  2427. * have the Class set by SetWindowProxyClass.
  2428. */
  2429. extern JS_FRIEND_API(void)
  2430. SetWindowProxy(JSContext* cx, JS::HandleObject global, JS::HandleObject windowProxy);
  2431. namespace detail {
  2432. JS_FRIEND_API(bool)
  2433. IsWindowSlow(JSObject* obj);
  2434. } // namespace detail
  2435. /**
  2436. * Returns true iff `obj` is a global object with an associated WindowProxy,
  2437. * see SetWindowProxy.
  2438. */
  2439. inline bool
  2440. IsWindow(JSObject* obj)
  2441. {
  2442. if (GetObjectClass(obj)->flags & JSCLASS_IS_GLOBAL)
  2443. return detail::IsWindowSlow(obj);
  2444. return false;
  2445. }
  2446. /**
  2447. * Returns true iff `obj` has the WindowProxy Class (see SetWindowProxyClass).
  2448. */
  2449. JS_FRIEND_API(bool)
  2450. IsWindowProxy(JSObject* obj);
  2451. /**
  2452. * If `obj` is a Window, get its associated WindowProxy (or a CCW or dead
  2453. * wrapper if the page was navigated away from), else return `obj`. This
  2454. * function is infallible and never returns nullptr.
  2455. */
  2456. extern JS_FRIEND_API(JSObject*)
  2457. ToWindowProxyIfWindow(JSObject* obj);
  2458. /**
  2459. * If `obj` is a WindowProxy, get its associated Window (the compartment's
  2460. * global), else return `obj`. This function is infallible and never returns
  2461. * nullptr.
  2462. */
  2463. extern JS_FRIEND_API(JSObject*)
  2464. ToWindowIfWindowProxy(JSObject* obj);
  2465. } /* namespace js */
  2466. class NativeProfiler
  2467. {
  2468. public:
  2469. virtual ~NativeProfiler() {};
  2470. virtual void sampleNative(void* addr, uint32_t size) = 0;
  2471. virtual void removeNative(void* addr) = 0;
  2472. virtual void reset() = 0;
  2473. };
  2474. class GCHeapProfiler
  2475. {
  2476. public:
  2477. virtual ~GCHeapProfiler() {};
  2478. virtual void sampleTenured(void* addr, uint32_t size) = 0;
  2479. virtual void sampleNursery(void* addr, uint32_t size) = 0;
  2480. virtual void markTenuredStart() = 0;
  2481. virtual void markTenured(void* addr) = 0;
  2482. virtual void sweepTenured() = 0;
  2483. virtual void sweepNursery() = 0;
  2484. virtual void moveNurseryToTenured(void* addrOld, void* addrNew) = 0;
  2485. virtual void reset() = 0;
  2486. };
  2487. class MemProfiler
  2488. {
  2489. static mozilla::Atomic<uint32_t, mozilla::Relaxed> sActiveProfilerCount;
  2490. static NativeProfiler* sNativeProfiler;
  2491. static GCHeapProfiler* GetGCHeapProfiler(void* addr);
  2492. static GCHeapProfiler* GetGCHeapProfiler(JSRuntime* runtime);
  2493. static NativeProfiler* GetNativeProfiler() {
  2494. return sNativeProfiler;
  2495. }
  2496. GCHeapProfiler* mGCHeapProfiler;
  2497. JSRuntime* mRuntime;
  2498. public:
  2499. explicit MemProfiler(JSRuntime* aRuntime) : mGCHeapProfiler(nullptr), mRuntime(aRuntime) {}
  2500. void start(GCHeapProfiler* aGCHeapProfiler);
  2501. void stop();
  2502. GCHeapProfiler* getGCHeapProfiler() const {
  2503. return mGCHeapProfiler;
  2504. }
  2505. static MOZ_ALWAYS_INLINE bool enabled() {
  2506. return sActiveProfilerCount > 0;
  2507. }
  2508. static MemProfiler* GetMemProfiler(JSContext* context);
  2509. static void SetNativeProfiler(NativeProfiler* aProfiler) {
  2510. sNativeProfiler = aProfiler;
  2511. }
  2512. static MOZ_ALWAYS_INLINE void SampleNative(void* addr, uint32_t size) {
  2513. JS::AutoSuppressGCAnalysis nogc;
  2514. if (MOZ_LIKELY(!enabled()))
  2515. return;
  2516. NativeProfiler* profiler = GetNativeProfiler();
  2517. if (profiler)
  2518. profiler->sampleNative(addr, size);
  2519. }
  2520. static MOZ_ALWAYS_INLINE void SampleTenured(void* addr, uint32_t size) {
  2521. JS::AutoSuppressGCAnalysis nogc;
  2522. if (MOZ_LIKELY(!enabled()))
  2523. return;
  2524. GCHeapProfiler* profiler = GetGCHeapProfiler(addr);
  2525. if (profiler)
  2526. profiler->sampleTenured(addr, size);
  2527. }
  2528. static MOZ_ALWAYS_INLINE void SampleNursery(void* addr, uint32_t size) {
  2529. JS::AutoSuppressGCAnalysis nogc;
  2530. if (MOZ_LIKELY(!enabled()))
  2531. return;
  2532. GCHeapProfiler* profiler = GetGCHeapProfiler(addr);
  2533. if (profiler)
  2534. profiler->sampleNursery(addr, size);
  2535. }
  2536. static MOZ_ALWAYS_INLINE void RemoveNative(void* addr) {
  2537. JS::AutoSuppressGCAnalysis nogc;
  2538. if (MOZ_LIKELY(!enabled()))
  2539. return;
  2540. NativeProfiler* profiler = GetNativeProfiler();
  2541. if (profiler)
  2542. profiler->removeNative(addr);
  2543. }
  2544. static MOZ_ALWAYS_INLINE void MarkTenuredStart(JSRuntime* runtime) {
  2545. JS::AutoSuppressGCAnalysis nogc;
  2546. if (MOZ_LIKELY(!enabled()))
  2547. return;
  2548. GCHeapProfiler* profiler = GetGCHeapProfiler(runtime);
  2549. if (profiler)
  2550. profiler->markTenuredStart();
  2551. }
  2552. static MOZ_ALWAYS_INLINE void MarkTenured(void* addr) {
  2553. JS::AutoSuppressGCAnalysis nogc;
  2554. if (MOZ_LIKELY(!enabled()))
  2555. return;
  2556. GCHeapProfiler* profiler = GetGCHeapProfiler(addr);
  2557. if (profiler)
  2558. profiler->markTenured(addr);
  2559. }
  2560. static MOZ_ALWAYS_INLINE void SweepTenured(JSRuntime* runtime) {
  2561. JS::AutoSuppressGCAnalysis nogc;
  2562. if (MOZ_LIKELY(!enabled()))
  2563. return;
  2564. GCHeapProfiler* profiler = GetGCHeapProfiler(runtime);
  2565. if (profiler)
  2566. profiler->sweepTenured();
  2567. }
  2568. static MOZ_ALWAYS_INLINE void SweepNursery(JSRuntime* runtime) {
  2569. JS::AutoSuppressGCAnalysis nogc;
  2570. if (MOZ_LIKELY(!enabled()))
  2571. return;
  2572. GCHeapProfiler* profiler = GetGCHeapProfiler(runtime);
  2573. if (profiler)
  2574. profiler->sweepNursery();
  2575. }
  2576. static MOZ_ALWAYS_INLINE void MoveNurseryToTenured(void* addrOld, void* addrNew) {
  2577. JS::AutoSuppressGCAnalysis nogc;
  2578. if (MOZ_LIKELY(!enabled()))
  2579. return;
  2580. GCHeapProfiler* profiler = GetGCHeapProfiler(addrOld);
  2581. if (profiler)
  2582. profiler->moveNurseryToTenured(addrOld, addrNew);
  2583. }
  2584. };
  2585. #endif /* jsfriendapi_h */