LCOV - code coverage report
Current view: top level - js/src - jsfriendapi.h (source / functions) Hit Total Coverage
Test: output.info Lines: 252 385 65.5 %
Date: 2017-07-14 16:53:18 Functions: 85 130 65.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13