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

Generated by: LCOV version 1.13-14-ga5dd952