tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

JSContext.h (44848B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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 /* JS execution context. */
      8 
      9 #ifndef vm_JSContext_h
     10 #define vm_JSContext_h
     11 
     12 #include "mozilla/Attributes.h"
     13 #include "mozilla/BaseProfilerUtils.h"  // BaseProfilerThreadId
     14 #include "mozilla/Maybe.h"
     15 #include "mozilla/MemoryReporting.h"
     16 
     17 #include "jstypes.h"  // JS_PUBLIC_API
     18 
     19 #include "builtin/AtomicsObject.h"
     20 #include "ds/TraceableFifo.h"
     21 #include "frontend/NameCollections.h"
     22 #include "gc/Allocator.h"
     23 #include "gc/GCEnum.h"
     24 #include "gc/Memory.h"
     25 #include "irregexp/RegExpTypes.h"
     26 #include "js/ContextOptions.h"  // JS::ContextOptions
     27 #include "js/Debug.h"           // JS::CustomObjectSummaryCallback
     28 #include "js/Exception.h"
     29 #include "js/friend/MicroTask.h"
     30 #include "js/GCVector.h"
     31 #include "js/Interrupt.h"
     32 #include "js/Promise.h"
     33 #include "js/Result.h"
     34 #include "js/RootingAPI.h"
     35 #include "js/Stack.h"  // JS::NativeStackBase, JS::NativeStackLimit
     36 #include "js/Utility.h"
     37 #include "js/Vector.h"
     38 #include "threading/ProtectedData.h"
     39 #include "util/StructuredSpewer.h"
     40 #include "vm/Activation.h"  // js::Activation
     41 #include "vm/MallocProvider.h"
     42 #include "vm/Runtime.h"
     43 #include "wasm/WasmContext.h"
     44 
     45 struct JS_PUBLIC_API JSContext;
     46 
     47 struct DtoaState;
     48 
     49 namespace js {
     50 
     51 class AutoAllocInAtomsZone;
     52 class AutoMaybeLeaveAtomsZone;
     53 class AutoRealm;
     54 struct PortableBaselineStack;
     55 
     56 #ifdef MOZ_EXECUTION_TRACING
     57 class ExecutionTracer;
     58 #endif
     59 
     60 namespace jit {
     61 class JitActivation;
     62 class JitContext;
     63 class DebugModeOSRVolatileJitFrameIter;
     64 }  // namespace jit
     65 
     66 /* Detects cycles when traversing an object graph. */
     67 class MOZ_RAII AutoCycleDetector {
     68 public:
     69  using Vector = GCVector<JSObject*, 8>;
     70 
     71  AutoCycleDetector(JSContext* cx, HandleObject objArg)
     72      : cx(cx), obj(cx, objArg), cyclic(true) {}
     73 
     74  ~AutoCycleDetector();
     75 
     76  bool init();
     77 
     78  bool foundCycle() { return cyclic; }
     79 
     80 private:
     81  JSContext* cx;
     82  RootedObject obj;
     83  bool cyclic;
     84 };
     85 
     86 struct AutoResolving;
     87 
     88 class InternalJobQueue : public JS::JobQueue {
     89 public:
     90  explicit InternalJobQueue(JSContext* cx)
     91      : queue(cx, SystemAllocPolicy()), draining_(false), interrupted_(false) {}
     92  ~InternalJobQueue() = default;
     93 
     94  // JS::JobQueue methods.
     95  bool getHostDefinedData(JSContext* cx,
     96                          JS::MutableHandle<JSObject*> data) const override;
     97 
     98  bool getHostDefinedGlobal(JSContext*,
     99                            JS::MutableHandle<JSObject*>) const override;
    100 
    101  bool enqueuePromiseJob(JSContext* cx, JS::HandleObject promise,
    102                         JS::HandleObject job, JS::HandleObject allocationSite,
    103                         JS::HandleObject hostDefinedData) override;
    104  void runJobs(JSContext* cx) override;
    105  bool empty() const override;
    106  bool isDrainingStopped() const override { return interrupted_; }
    107 
    108  // If we are currently in a call to runJobs(), make that call stop processing
    109  // jobs once the current one finishes, and return. If we are not currently in
    110  // a call to runJobs, make all future calls return immediately.
    111  void interrupt() { interrupted_ = true; }
    112 
    113  void uninterrupt() { interrupted_ = false; }
    114 
    115  // Return the front element of the queue, or nullptr if the queue is empty.
    116  // This is only used by shell testing functions.
    117  JSObject* maybeFront() const;
    118 
    119 #ifdef DEBUG
    120  JSObject* copyJobs(JSContext* cx);
    121 #endif
    122 
    123 private:
    124  using Queue = js::TraceableFifo<JSObject*, 0, SystemAllocPolicy>;
    125 
    126  JS::PersistentRooted<Queue> queue;
    127 
    128  // True if we are in the midst of draining jobs from this queue. We use this
    129  // to avoid re-entry (nested calls simply return immediately).
    130  bool draining_;
    131 
    132  // True if we've been asked to interrupt draining jobs. Set by interrupt().
    133  bool interrupted_;
    134 
    135  class SavedQueue;
    136  js::UniquePtr<JobQueue::SavedJobQueue> saveJobQueue(JSContext*) override;
    137 };
    138 
    139 class AutoLockScriptData;
    140 
    141 /* Thread Local Storage slot for storing the context for a thread. */
    142 extern MOZ_THREAD_LOCAL(JSContext*) TlsContext;
    143 
    144 #ifdef DEBUG
    145 JSContext* MaybeGetJSContext();
    146 #endif
    147 
    148 enum class InterruptReason : uint32_t {
    149  MinorGC = 1 << 0,
    150  MajorGC = 1 << 1,
    151  AttachOffThreadCompilations = 1 << 2,
    152  CallbackUrgent = 1 << 3,
    153  CallbackCanWait = 1 << 4,
    154  OOMStackTrace = 1 << 5,
    155 };
    156 
    157 enum class ShouldCaptureStack { Maybe, Always };
    158 
    159 // A wrapper type to allow customization of tracing of
    160 // MicroTaskElements.
    161 struct MicroTaskQueueElement {
    162  MOZ_IMPLICIT
    163  MicroTaskQueueElement(const JS::Value& val) : value(val) {}
    164 
    165  operator JS::Value() const { return value; }
    166 
    167  void trace(JSTracer* trc);
    168 
    169 private:
    170  JS::Value value;
    171 };
    172 
    173 // Use TempAllocPolicy to report OOM
    174 // MG:XXX: It would be nice to explore the typical depth of the queue
    175 //         to see if we can get it all inline in the common case.
    176 // MG:XXX: This appears to be broken for non-zero values of inline!
    177 using MicroTaskQueue =
    178    js::TraceableFifo<MicroTaskQueueElement, 0, TempAllocPolicy>;
    179 
    180 // A pair of microtask queues; one debug and one 'regular' (non-debug).
    181 struct MicroTaskQueueSet {
    182  explicit MicroTaskQueueSet(JSContext* cx)
    183      : microTaskQueue(cx), debugMicroTaskQueue(cx) {}
    184 
    185  // We want to swap so we need move constructors
    186  MicroTaskQueueSet(MicroTaskQueueSet&&) = default;
    187  MicroTaskQueueSet& operator=(MicroTaskQueueSet&&) = default;
    188 
    189  // Don't copy.
    190  MicroTaskQueueSet(const MicroTaskQueueSet&) = delete;
    191  MicroTaskQueueSet& operator=(const MicroTaskQueueSet&) = delete;
    192 
    193  bool enqueueRegularMicroTask(JSContext* cx, const JS::GenericMicroTask&);
    194  bool enqueueDebugMicroTask(JSContext* cx, const JS::GenericMicroTask&);
    195  bool prependRegularMicroTask(JSContext* cx, const JS::GenericMicroTask&);
    196 
    197  JS::GenericMicroTask popFront();
    198  JS::GenericMicroTask popDebugFront();
    199 
    200  bool empty() { return microTaskQueue.empty() && debugMicroTaskQueue.empty(); }
    201 
    202  void trace(JSTracer* trc) {
    203    microTaskQueue.trace(trc);
    204    debugMicroTaskQueue.trace(trc);
    205  }
    206 
    207  void clear() {
    208    microTaskQueue.clear();
    209    debugMicroTaskQueue.clear();
    210  }
    211 
    212  MicroTaskQueue microTaskQueue;
    213  MicroTaskQueue debugMicroTaskQueue;
    214 };
    215 
    216 } /* namespace js */
    217 
    218 /*
    219 * A JSContext encapsulates the thread local state used when using the JS
    220 * runtime.
    221 */
    222 struct JS_PUBLIC_API JSContext : public JS::RootingContext,
    223                                 public js::MallocProvider<JSContext> {
    224  JSContext(JSRuntime* runtime, const JS::ContextOptions& options);
    225  ~JSContext();
    226 
    227  bool init();
    228 
    229  static JSContext* from(JS::RootingContext* rcx) {
    230    return static_cast<JSContext*>(rcx);
    231  }
    232 
    233 private:
    234  js::UnprotectedData<JSRuntime*> runtime_;
    235 #ifdef DEBUG
    236  js::WriteOnceData<bool> initialized_;
    237 #endif
    238 
    239  js::ContextData<JS::ContextOptions> options_;
    240 
    241  // Are we currently timing execution? This flag ensures that we do not
    242  // double-count execution time in reentrant situations.
    243  js::ContextData<bool> measuringExecutionTimeEnabled_;
    244 
    245  // This variable is used by the HelperThread scheduling to update the priority
    246  // of task based on whether JavaScript is being executed on the main thread.
    247  mozilla::Atomic<bool, mozilla::ReleaseAcquire> isExecuting_;
    248 
    249 public:
    250  // This is used by helper threads to change the runtime their context is
    251  // currently operating on.
    252  void setRuntime(JSRuntime* rt);
    253 
    254  bool measuringExecutionTimeEnabled() const {
    255    return measuringExecutionTimeEnabled_;
    256  }
    257  void setMeasuringExecutionTimeEnabled(bool value) {
    258    measuringExecutionTimeEnabled_ = value;
    259  }
    260 
    261  // While JSContexts are meant to be used on a single thread, this reference is
    262  // meant to be shared to helper thread tasks. This is used by helper threads
    263  // to change the priority of tasks based on whether JavaScript is executed on
    264  // the main thread.
    265  const mozilla::Atomic<bool, mozilla::ReleaseAcquire>& isExecutingRef() const {
    266    return isExecuting_;
    267  }
    268  void setIsExecuting(bool value) { isExecuting_ = value; }
    269 
    270 #ifdef DEBUG
    271  bool isInitialized() const { return initialized_; }
    272 #endif
    273 
    274  template <typename T>
    275  bool isInsideCurrentZone(T thing) const {
    276    return thing->zoneFromAnyThread() == zone_;
    277  }
    278 
    279  template <typename T>
    280  inline bool isInsideCurrentCompartment(T thing) const {
    281    return thing->compartment() == compartment();
    282  }
    283 
    284  void onOutOfMemory();
    285  void* onOutOfMemory(js::AllocFunction allocFunc, arena_id_t arena,
    286                      size_t nbytes, void* reallocPtr = nullptr) {
    287    return runtime_->onOutOfMemory(allocFunc, arena, nbytes, reallocPtr, this);
    288  }
    289 
    290  void onOverRecursed();
    291 
    292  // Allocate a GC thing.
    293  template <typename T, js::AllowGC allowGC = js::CanGC, typename... Args>
    294  T* newCell(Args&&... args);
    295 
    296  /* Clear the pending exception (if any) due to OOM. */
    297  void recoverFromOutOfMemory();
    298 
    299  void reportAllocationOverflow();
    300 
    301  // Accessors for immutable runtime data.
    302  JSAtomState& names() { return *runtime_->commonNames; }
    303  js::StaticStrings& staticStrings() { return *runtime_->staticStrings; }
    304  bool permanentAtomsPopulated() { return runtime_->permanentAtomsPopulated(); }
    305  const js::FrozenAtomSet& permanentAtoms() {
    306    return *runtime_->permanentAtoms();
    307  }
    308  js::WellKnownSymbols& wellKnownSymbols() {
    309    return *runtime_->wellKnownSymbols;
    310  }
    311  js::PropertyName* emptyString() { return runtime_->emptyString; }
    312  JS::GCContext* gcContext() { return runtime_->gcContext(); }
    313  JS::StackKind stackKindForCurrentPrincipal();
    314  JS::NativeStackLimit stackLimitForCurrentPrincipal();
    315  JS::NativeStackLimit stackLimit(JS::StackKind kind) {
    316    return nativeStackLimit[kind];
    317  }
    318  JS::NativeStackLimit stackLimitForJitCode(JS::StackKind kind);
    319  size_t gcSystemPageSize() { return js::gc::SystemPageSize(); }
    320 
    321  /*
    322   * "Entering" a realm changes cx->realm (which changes cx->global). Note
    323   * that this does not push an Activation so it's possible for the caller's
    324   * realm to be != cx->realm(). This is not a problem since, in general, most
    325   * places in the VM cannot know that they were called from script (e.g.,
    326   * they may have been called through the JSAPI via JS_CallFunction) and thus
    327   * cannot expect there is a scripted caller.
    328   *
    329   * Realms should be entered/left in a LIFO fasion. To enter a realm, code
    330   * should prefer using AutoRealm over JS::EnterRealm/JS::LeaveRealm.
    331   *
    332   * Also note that the JIT can enter (same-compartment) realms without going
    333   * through these methods - it will update cx->realm_ directly.
    334   */
    335 private:
    336  inline void setRealm(JS::Realm* realm);
    337  inline void enterRealm(JS::Realm* realm);
    338 
    339  inline void enterAtomsZone();
    340  inline void leaveAtomsZone(JS::Realm* oldRealm);
    341  inline void setZone(js::Zone* zone);
    342 
    343  friend class js::AutoAllocInAtomsZone;
    344  friend class js::AutoMaybeLeaveAtomsZone;
    345  friend class js::AutoRealm;
    346 
    347 public:
    348  inline void enterRealmOf(JSObject* target);
    349  inline void enterRealmOf(JSScript* target);
    350  inline void enterRealmOf(js::Shape* target);
    351  inline void enterNullRealm();
    352 
    353  inline void setRealmForJitExceptionHandler(JS::Realm* realm);
    354 
    355  inline void leaveRealm(JS::Realm* oldRealm);
    356 
    357  // Threads may freely access any data in their realm, compartment and zone.
    358  JS::Compartment* compartment() const {
    359    return realm_ ? JS::GetCompartmentForRealm(realm_) : nullptr;
    360  }
    361 
    362  JS::Realm* realm() const { return realm_; }
    363 
    364 #ifdef DEBUG
    365  bool inAtomsZone() const;
    366 #endif
    367 
    368  JS::Zone* zone() const {
    369    MOZ_ASSERT_IF(!realm() && zone_, inAtomsZone());
    370    MOZ_ASSERT_IF(realm(), js::GetRealmZone(realm()) == zone_);
    371    return zone_;
    372  }
    373 
    374  // For JIT use.
    375  static size_t offsetOfZone() { return offsetof(JSContext, zone_); }
    376 
    377  // Current global. This is only safe to use within the scope of the
    378  // AutoRealm from which it's called.
    379  inline js::Handle<js::GlobalObject*> global() const;
    380 
    381  js::AtomsTable& atoms() { return runtime_->atoms(); }
    382 
    383  js::SymbolRegistry& symbolRegistry() { return runtime_->symbolRegistry(); }
    384 
    385  // Methods to access other runtime data that checks locking internally.
    386  js::gc::AtomMarkingRuntime& atomMarking() { return runtime_->gc.atomMarking; }
    387  void markAtom(JSAtom* atom) { atomMarking().markAtom(this, atom); }
    388  void markAtom(JS::Symbol* symbol) { atomMarking().markAtom(this, symbol); }
    389  void markId(jsid id) { atomMarking().markId(this, id); }
    390  void markAtomValue(const js::Value& value) {
    391    atomMarking().markAtomValue(this, value);
    392  }
    393 
    394  // Interface for recording telemetry metrics.
    395  js::Metrics metrics() { return js::Metrics(runtime_); }
    396 
    397  JSRuntime* runtime() { return runtime_; }
    398  const JSRuntime* runtime() const { return runtime_; }
    399 
    400  static size_t offsetOfRuntime() {
    401    return offsetof(JSContext, runtime_) +
    402           js::UnprotectedData<JSRuntime*>::offsetOfValue();
    403  }
    404  static size_t offsetOfRealm() { return offsetof(JSContext, realm_); }
    405 
    406  friend class JS::AutoSaveExceptionState;
    407  friend class js::jit::DebugModeOSRVolatileJitFrameIter;
    408  friend void js::ReportOutOfMemory(JSContext*);
    409  friend void js::ReportOverRecursed(JSContext*);
    410  friend void js::ReportOversizedAllocation(JSContext*, const unsigned);
    411 
    412 public:
    413  /**
    414   * Intentionally awkward signpost method that is stationed on the
    415   * boundary between Result-using and non-Result-using code.
    416   */
    417  template <typename V, typename E>
    418  bool resultToBool(const JS::Result<V, E>& result) {
    419    return result.isOk();
    420  }
    421 
    422  template <typename V, typename E>
    423  V* resultToPtr(JS::Result<V*, E>& result) {
    424    return result.isOk() ? result.unwrap() : nullptr;
    425  }
    426 
    427  mozilla::GenericErrorResult<JS::OOM> alreadyReportedOOM();
    428  mozilla::GenericErrorResult<JS::Error> alreadyReportedError();
    429 
    430  /*
    431   * Points to the most recent JitActivation pushed on the thread.
    432   * See JitActivation constructor in vm/Stack.cpp
    433   */
    434  js::ContextData<js::jit::JitActivation*> jitActivation;
    435 
    436  // Shim for V8 interfaces used by irregexp code
    437  js::ContextData<js::irregexp::Isolate*> isolate;
    438 
    439  /*
    440   * Points to the most recent activation running on the thread.
    441   * See Activation comment in vm/Stack.h.
    442   */
    443  js::ContextData<js::Activation*> activation_;
    444 
    445  /*
    446   * Points to the most recent profiling activation running on the
    447   * thread.
    448   */
    449  js::Activation* volatile profilingActivation_;
    450 
    451 public:
    452  js::Activation* activation() const { return activation_; }
    453  static size_t offsetOfActivation() {
    454    return offsetof(JSContext, activation_);
    455  }
    456 
    457  js::Activation* profilingActivation() const { return profilingActivation_; }
    458  static size_t offsetOfProfilingActivation() {
    459    return offsetof(JSContext, profilingActivation_);
    460  }
    461 
    462  static size_t offsetOfJitActivation() {
    463    return offsetof(JSContext, jitActivation);
    464  }
    465 
    466 #ifdef JS_CHECK_UNSAFE_CALL_WITH_ABI
    467  static size_t offsetOfInUnsafeCallWithABI() {
    468    return offsetof(JSContext, inUnsafeCallWithABI);
    469  }
    470 #endif
    471 
    472 public:
    473  js::InterpreterStack& interpreterStack() {
    474    return runtime()->interpreterStack();
    475  }
    476 #ifdef ENABLE_PORTABLE_BASELINE_INTERP
    477  js::PortableBaselineStack& portableBaselineStack() {
    478    return runtime()->portableBaselineStack();
    479  }
    480 #endif
    481 
    482 private:
    483  // Base address of the native stack for the current thread.
    484  mozilla::Maybe<JS::NativeStackBase> nativeStackBase_;
    485 
    486 public:
    487  JS::NativeStackBase nativeStackBase() const { return *nativeStackBase_; }
    488 
    489 public:
    490  // In brittle mode, any failure will produce a diagnostic assertion rather
    491  // than propagating an error or throwing an exception. This is used for
    492  // intermittent crash diagnostics: if an operation is failing for unknown
    493  // reasons, turn on brittle mode and annotate the operations within
    494  // SpiderMonkey that the failing operation uses with:
    495  //
    496  //   MOZ_DIAGNOSTIC_ASSERT(!cx->brittleMode, "specific failure");
    497  //
    498  bool brittleMode = false;
    499 
    500  /*
    501   * Stack of debuggers that currently disallow debuggee execution.
    502   *
    503   * When we check for NX we are inside the debuggee compartment, and thus a
    504   * stack of Debuggers that have prevented execution need to be tracked to
    505   * enter the correct Debugger compartment to report the error.
    506   */
    507  js::ContextData<js::EnterDebuggeeNoExecute*> noExecuteDebuggerTop;
    508 
    509 #ifdef JS_CHECK_UNSAFE_CALL_WITH_ABI
    510  js::ContextData<uint32_t> inUnsafeCallWithABI;
    511  js::ContextData<bool> hasAutoUnsafeCallWithABI;
    512 #endif
    513 
    514 #ifdef DEBUG
    515  js::ContextData<uint32_t> liveArraySortDataInstances;
    516 #endif
    517 
    518 #ifdef JS_SIMULATOR
    519 private:
    520  js::ContextData<js::jit::Simulator*> simulator_;
    521 
    522 public:
    523  js::jit::Simulator* simulator() const;
    524  JS::NativeStackLimit* addressOfSimulatorStackLimit();
    525 #endif
    526 
    527 public:
    528  // State used by util/DoubleToString.cpp.
    529  js::ContextData<DtoaState*> dtoaState;
    530 
    531  /*
    532   * When this flag is non-zero, any attempt to GC will be skipped. See the
    533   * AutoSuppressGC class for for details.
    534   */
    535  js::ContextData<int32_t> suppressGC;
    536 
    537 #ifdef FUZZING_JS_FUZZILLI
    538  uint32_t executionHash;
    539  uint32_t executionHashInputs;
    540 #endif
    541 
    542 #ifdef DEBUG
    543  js::ContextData<size_t> noNurseryAllocationCheck;
    544 
    545  /*
    546   * If this is 0, all cross-compartment proxies must be registered in the
    547   * wrapper map. This checking must be disabled temporarily while creating
    548   * new wrappers. When non-zero, this records the recursion depth of wrapper
    549   * creation.
    550   */
    551  js::ContextData<uintptr_t> disableStrictProxyCheckingCount;
    552 
    553  bool isNurseryAllocAllowed() { return noNurseryAllocationCheck == 0; }
    554  void disallowNurseryAlloc() { ++noNurseryAllocationCheck; }
    555  void allowNurseryAlloc() {
    556    MOZ_ASSERT(!isNurseryAllocAllowed());
    557    --noNurseryAllocationCheck;
    558  }
    559 
    560  bool isStrictProxyCheckingEnabled() {
    561    return disableStrictProxyCheckingCount == 0;
    562  }
    563  void disableStrictProxyChecking() { ++disableStrictProxyCheckingCount; }
    564  void enableStrictProxyChecking() {
    565    MOZ_ASSERT(disableStrictProxyCheckingCount > 0);
    566    --disableStrictProxyCheckingCount;
    567  }
    568 #endif
    569 
    570 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
    571  // We are currently running a simulated OOM test.
    572  js::ContextData<bool> runningOOMTest;
    573 #endif
    574 
    575  /*
    576   * Some regions of code are hard for the static rooting hazard analysis to
    577   * understand. In those cases, we trade the static analysis for a dynamic
    578   * analysis. When this is non-zero, we should assert if we trigger, or
    579   * might trigger, a GC.
    580   */
    581  js::ContextData<int> inUnsafeRegion;
    582 
    583  // Count of AutoDisableGenerationalGC instances on the thread's stack.
    584  js::ContextData<unsigned> generationalDisabled;
    585 
    586  // Some code cannot tolerate compacting GC so it can be disabled temporarily
    587  // with AutoDisableCompactingGC which uses this counter.
    588  js::ContextData<unsigned> compactingDisabledCount;
    589 
    590  // Match limit result for the most recent call to RegExpSearcher.
    591  js::ContextData<uint32_t> regExpSearcherLastLimit;
    592 
    593  static constexpr size_t offsetOfRegExpSearcherLastLimit() {
    594    return offsetof(JSContext, regExpSearcherLastLimit);
    595  }
    596 
    597  // Whether we are currently executing the top level of a module.
    598  js::ContextData<uint32_t> isEvaluatingModule;
    599 
    600 private:
    601  // Pools used for recycling name maps and vectors when parsing and
    602  // emitting bytecode. Purged on GC when there are no active script
    603  // compilations.
    604  js::ContextData<js::frontend::NameCollectionPool> frontendCollectionPool_;
    605 
    606 public:
    607  js::frontend::NameCollectionPool& frontendCollectionPool() {
    608    return frontendCollectionPool_.ref();
    609  }
    610 
    611  void verifyIsSafeToGC() {
    612    MOZ_DIAGNOSTIC_ASSERT(!inUnsafeRegion,
    613                          "[AutoAssertNoGC] possible GC in GC-unsafe region");
    614  }
    615 
    616  bool isInUnsafeRegion() const { return bool(inUnsafeRegion); }
    617 
    618  // For JIT use.
    619  MOZ_NEVER_INLINE void resetInUnsafeRegion() {
    620    MOZ_ASSERT(inUnsafeRegion >= 0);
    621    inUnsafeRegion = 0;
    622  }
    623 
    624  static constexpr size_t offsetOfInUnsafeRegion() {
    625    return offsetof(JSContext, inUnsafeRegion);
    626  }
    627 
    628  /* Whether sampling should be enabled or not. */
    629 private:
    630  mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
    631      suppressProfilerSampling;
    632 
    633 public:
    634  bool isProfilerSamplingEnabled() const { return !suppressProfilerSampling; }
    635  void disableProfilerSampling() { suppressProfilerSampling = true; }
    636  void enableProfilerSampling() { suppressProfilerSampling = false; }
    637 
    638 private:
    639  js::wasm::Context wasm_;
    640 
    641 public:
    642  js::wasm::Context& wasm() { return wasm_; }
    643  static constexpr size_t offsetOfWasm() { return offsetof(JSContext, wasm_); }
    644 
    645  /* Temporary arena pool used while compiling and decompiling. */
    646  static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
    647 
    648 private:
    649  js::ContextData<js::LifoAlloc> tempLifoAlloc_;
    650 
    651 public:
    652  js::LifoAlloc& tempLifoAlloc() { return tempLifoAlloc_.ref(); }
    653  const js::LifoAlloc& tempLifoAlloc() const { return tempLifoAlloc_.ref(); }
    654 
    655  js::ContextData<uint32_t> debuggerMutations;
    656 
    657 private:
    658  // Indicates if an exception is pending and the reason for it.
    659  js::ContextData<JS::ExceptionStatus> status;
    660  js::ContextData<JS::PersistentRooted<JS::Value>>
    661      unwrappedException_; /* most-recently-thrown exception */
    662  js::ContextData<JS::PersistentRooted<js::SavedFrame*>>
    663      unwrappedExceptionStack_; /* stack when the exception was thrown */
    664 
    665  JS::Value& unwrappedException() {
    666    if (!unwrappedException_.ref().initialized()) {
    667      unwrappedException_.ref().init(this);
    668    }
    669    return unwrappedException_.ref().get();
    670  }
    671 
    672  js::SavedFrame*& unwrappedExceptionStack() {
    673    if (!unwrappedExceptionStack_.ref().initialized()) {
    674      unwrappedExceptionStack_.ref().init(this);
    675    }
    676    return unwrappedExceptionStack_.ref().get();
    677  }
    678 
    679 #ifdef DEBUG
    680  // True if this context has ever thrown an exception because of an exceeded
    681  // limit: stack space (ReportOverRecursed), memory (ReportOutOfMemory), or
    682  // some other self-imposed limit (eg ReportOversizedAllocation). Used when
    683  // detecting bailout loops in WarpOracle: bailout loops involving resource
    684  // exhaustion are generally not interesting.
    685  js::ContextData<bool> hadResourceExhaustion_;
    686 
    687  // True if this context has ever thrown an uncatchable exception to terminate
    688  // execution from the interrupt callback.
    689  js::ContextData<bool> hadUncatchableException_;
    690 
    691 public:
    692  bool hadResourceExhaustion() const {
    693    return hadResourceExhaustion_ || js::oom::simulator.isThreadSimulatingAny();
    694  }
    695  bool hadUncatchableException() const { return hadUncatchableException_; }
    696 #endif
    697 
    698 public:
    699  void reportResourceExhaustion() {
    700 #ifdef DEBUG
    701    hadResourceExhaustion_ = true;
    702 #endif
    703  }
    704  void reportUncatchableException() {
    705    // Make sure the context has no pending exception. See also the comment for
    706    // JS::ReportUncatchableException.
    707    clearPendingException();
    708 #ifdef DEBUG
    709    hadUncatchableException_ = true;
    710 #endif
    711  }
    712 
    713  // OOM stack trace buffer management
    714  void unsetOOMStackTrace();
    715  const char* getOOMStackTrace() const;
    716  bool hasOOMStackTrace() const;
    717  void captureOOMStackTrace();
    718 
    719  js::ContextData<int32_t> reportGranularity; /* see vm/Probes.h */
    720 
    721  js::ContextData<js::AutoResolving*> resolvingList;
    722 
    723 #ifdef DEBUG
    724  js::ContextData<js::AutoEnterPolicy*> enteredPolicy;
    725 #endif
    726 
    727  /* True if generating an error, to prevent runaway recursion. */
    728  js::ContextData<bool> generatingError;
    729 
    730 private:
    731  /* State for object and array toSource conversion. */
    732  js::ContextData<js::AutoCycleDetector::Vector> cycleDetectorVector_;
    733 
    734 public:
    735  js::AutoCycleDetector::Vector& cycleDetectorVector() {
    736    return cycleDetectorVector_.ref();
    737  }
    738  const js::AutoCycleDetector::Vector& cycleDetectorVector() const {
    739    return cycleDetectorVector_.ref();
    740  }
    741 
    742  /* Client opaque pointer. */
    743  js::UnprotectedData<void*> data;
    744 
    745  void initJitStackLimit();
    746  void resetJitStackLimit();
    747 
    748 public:
    749  JS::ContextOptions& options() { return options_.ref(); }
    750 
    751  bool runtimeMatches(JSRuntime* rt) const { return runtime_ == rt; }
    752 
    753 private:
    754  /*
    755   * Youngest frame of a saved stack that will be picked up as an async stack
    756   * by any new Activation, and is nullptr when no async stack should be used.
    757   *
    758   * The JS::AutoSetAsyncStackForNewCalls class can be used to set this.
    759   *
    760   * New activations will reset this to nullptr on construction after getting
    761   * the current value, and will restore the previous value on destruction.
    762   */
    763  js::ContextData<JS::PersistentRooted<js::SavedFrame*>>
    764      asyncStackForNewActivations_;
    765 
    766 public:
    767  js::SavedFrame*& asyncStackForNewActivations() {
    768    if (!asyncStackForNewActivations_.ref().initialized()) {
    769      asyncStackForNewActivations_.ref().init(this);
    770    }
    771    return asyncStackForNewActivations_.ref().get();
    772  }
    773 
    774  /*
    775   * Value of asyncCause to be attached to asyncStackForNewActivations.
    776   */
    777  js::ContextData<const char*> asyncCauseForNewActivations;
    778 
    779  /*
    780   * True if the async call was explicitly requested, e.g. via
    781   * callFunctionWithAsyncStack.
    782   */
    783  js::ContextData<bool> asyncCallIsExplicit;
    784 
    785  bool currentlyRunningInInterpreter() const {
    786    return activation()->isInterpreter();
    787  }
    788  bool currentlyRunningInJit() const { return activation()->isJit(); }
    789  js::InterpreterFrame* interpreterFrame() const {
    790    return activation()->asInterpreter()->current();
    791  }
    792  js::InterpreterRegs& interpreterRegs() const {
    793    return activation()->asInterpreter()->regs();
    794  }
    795 
    796  /*
    797   * Get the topmost script and optional pc on the stack. By default, this
    798   * function only returns a JSScript in the current realm, returning nullptr
    799   * if the current script is in a different realm. This behavior can be
    800   * overridden by passing AllowCrossRealm::Allow.
    801   */
    802  enum class AllowCrossRealm { DontAllow = false, Allow = true };
    803  JSScript* currentScript(
    804      jsbytecode** ppc = nullptr,
    805      AllowCrossRealm allowCrossRealm = AllowCrossRealm::DontAllow);
    806 
    807  inline void minorGC(JS::GCReason reason);
    808 
    809 public:
    810  bool isExceptionPending() const {
    811    return JS::IsCatchableExceptionStatus(status);
    812  }
    813 
    814  /**
    815   * Return the pending exception and wrap it into the current compartment.
    816   */
    817  [[nodiscard]] bool getPendingException(JS::MutableHandleValue rval);
    818 
    819  /**
    820   * Return the pending exception stack and wrap it into the current
    821   * compartment. Return |JS::NullValue| when the pending exception has no stack
    822   * attached.
    823   */
    824  [[nodiscard]] bool getPendingExceptionStack(JS::MutableHandleValue rval);
    825 
    826  /**
    827   * Return the pending exception stack, but does not wrap it into the current
    828   * compartment. Return |nullptr| when the pending exception has no stack
    829   * attached.
    830   */
    831  js::SavedFrame* getPendingExceptionStack();
    832 
    833 #ifdef DEBUG
    834  /**
    835   * Return the pending exception (without wrapping).
    836   */
    837  const JS::Value& getPendingExceptionUnwrapped();
    838 #endif
    839 
    840  bool isThrowingDebuggeeWouldRun();
    841  bool isClosingGenerator();
    842 
    843  void setPendingException(JS::HandleValue v,
    844                           JS::Handle<js::SavedFrame*> stack);
    845  void setPendingException(JS::HandleValue v,
    846                           js::ShouldCaptureStack captureStack);
    847 
    848  void clearPendingException() {
    849    status = JS::ExceptionStatus::None;
    850    unwrappedException().setUndefined();
    851    unwrappedExceptionStack() = nullptr;
    852  }
    853 
    854  bool isThrowingOutOfMemory() const {
    855    return status == JS::ExceptionStatus::OutOfMemory;
    856  }
    857  bool isThrowingOverRecursed() const {
    858    return status == JS::ExceptionStatus::OverRecursed;
    859  }
    860  bool isPropagatingForcedReturn() const {
    861    return status == JS::ExceptionStatus::ForcedReturn;
    862  }
    863  void setPropagatingForcedReturn() {
    864    MOZ_ASSERT(status == JS::ExceptionStatus::None);
    865    status = JS::ExceptionStatus::ForcedReturn;
    866  }
    867  void clearPropagatingForcedReturn() {
    868    MOZ_ASSERT(status == JS::ExceptionStatus::ForcedReturn);
    869    status = JS::ExceptionStatus::None;
    870  }
    871 
    872  /*
    873   * See JS_SetTrustedPrincipals in jsapi.h.
    874   * Note: !cx->realm() is treated as trusted.
    875   */
    876  inline bool runningWithTrustedPrincipals();
    877 
    878  // Checks if the page's Content-Security-Policy (CSP) allows
    879  // runtime code generation "unsafe-eval", or "wasm-unsafe-eval" for Wasm.
    880  bool isRuntimeCodeGenEnabled(
    881      JS::RuntimeCode kind, JS::Handle<JSString*> codeString,
    882      JS::CompilationType compilationType,
    883      JS::Handle<JS::StackGCVector<JSString*>> parameterStrings,
    884      JS::Handle<JSString*> bodyString,
    885      JS::Handle<JS::StackGCVector<JS::Value>> parameterArgs,
    886      JS::Handle<JS::Value> bodyArg, bool* outCanCompileStrings);
    887 
    888  // Get code to be used by eval for Object argument.
    889  bool getCodeForEval(JS::HandleObject code,
    890                      JS::MutableHandle<JSString*> outCode);
    891 
    892  size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    893  size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
    894 
    895  void trace(JSTracer* trc);
    896 
    897  inline js::RuntimeCaches& caches();
    898 
    899 public:
    900  using InterruptCallbackVector =
    901      js::Vector<JSInterruptCallback, 2, js::SystemAllocPolicy>;
    902 
    903 private:
    904  js::ContextData<InterruptCallbackVector> interruptCallbacks_;
    905 
    906 public:
    907  InterruptCallbackVector& interruptCallbacks() {
    908    return interruptCallbacks_.ref();
    909  }
    910 
    911  js::ContextData<bool> interruptCallbackDisabled;
    912 
    913  // Bitfield storing InterruptReason values.
    914  mozilla::Atomic<uint32_t, mozilla::Relaxed> interruptBits_;
    915 
    916  // Any thread can call requestInterrupt() to request that this thread
    917  // stop running. To stop this thread, requestInterrupt sets two fields:
    918  // interruptBits_ (a bitset of InterruptReasons) and jitStackLimit (set to
    919  // JS::NativeStackLimitMin). The JS engine must continually poll one of these
    920  // fields and call handleInterrupt if either field has the interrupt value.
    921  //
    922  // The point of setting jitStackLimit to JS::NativeStackLimitMin is that JIT
    923  // code already needs to guard on jitStackLimit in every function prologue to
    924  // avoid stack overflow, so we avoid a second branch on interruptBits_ by
    925  // setting jitStackLimit to a value that is guaranteed to fail the guard.)
    926  //
    927  // Note that the writes to interruptBits_ and jitStackLimit use a Relaxed
    928  // Atomic so, while the writes are guaranteed to eventually be visible to
    929  // this thread, it can happen in any order. handleInterrupt calls the
    930  // interrupt callback if either is set, so it really doesn't matter as long
    931  // as the JS engine is continually polling at least one field. In corner
    932  // cases, this relaxed ordering could lead to an interrupt handler being
    933  // called twice in succession after a single requestInterrupt call, but
    934  // that's fine.
    935  void requestInterrupt(js::InterruptReason reason);
    936  bool handleInterrupt();
    937  bool handleInterruptNoCallbacks();
    938 
    939  MOZ_ALWAYS_INLINE bool hasAnyPendingInterrupt() const {
    940    static_assert(sizeof(interruptBits_) == sizeof(uint32_t),
    941                  "Assumed by JIT callers");
    942    return interruptBits_ != 0;
    943  }
    944  bool hasPendingInterrupt(js::InterruptReason reason) const {
    945    return interruptBits_ & uint32_t(reason);
    946  }
    947  void clearPendingInterrupt(js::InterruptReason reason);
    948 
    949 public:
    950  void* addressOfInterruptBits() { return &interruptBits_; }
    951  void* addressOfJitStackLimit() { return &jitStackLimit; }
    952  void* addressOfJitStackLimitNoInterrupt() {
    953    return &jitStackLimitNoInterrupt;
    954  }
    955  void* addressOfZone() { return &zone_; }
    956 
    957  const void* addressOfRealm() const { return &realm_; }
    958 
    959  const void* addressOfJitActivation() const { return &jitActivation; }
    960 
    961  // Futex state, used by Atomics.wait() and Atomics.wake() on the Atomics
    962  // object.
    963  js::FutexThread fx;
    964 
    965  mozilla::Atomic<JS::NativeStackLimit, mozilla::Relaxed> jitStackLimit;
    966 
    967  // Like jitStackLimit, but not reset to trigger interrupts.
    968  js::ContextData<JS::NativeStackLimit> jitStackLimitNoInterrupt;
    969 
    970  // Queue of pending jobs as described in ES2016 section 8.4.
    971  //
    972  // This is a non-owning pointer to either:
    973  // - a JobQueue implementation the embedding provided by calling
    974  //   JS::SetJobQueue, owned by the embedding, or
    975  // - our internal JobQueue implementation, established by calling
    976  //   js::UseInternalJobQueues, owned by JSContext::internalJobQueue below.
    977  js::ContextData<JS::JobQueue*> jobQueue;
    978 
    979  // If the embedding has called js::UseInternalJobQueues, this is the owning
    980  // pointer to our internal JobQueue implementation, which JSContext::jobQueue
    981  // borrows.
    982  js::ContextData<js::UniquePtr<js::InternalJobQueue>> internalJobQueue;
    983 
    984  // True if jobQueue is empty, or we are running the last job in the queue.
    985  // Such conditions permit optimizations around `await` expressions.
    986  js::ContextData<bool> canSkipEnqueuingJobs;
    987 
    988  js::ContextData<JS::PromiseRejectionTrackerCallback>
    989      promiseRejectionTrackerCallback;
    990  js::ContextData<void*> promiseRejectionTrackerCallbackData;
    991 
    992  // Pre-allocated buffer for storing out-of-memory stack traces.
    993  // This buffer is allocated during context initialization to avoid
    994  // allocation during OOM conditions. The buffer stores a formatted
    995  // stack trace string that can be retrieved by privileged JavaScript.
    996  static constexpr size_t OOMStackTraceBufferSize = 4096;
    997  js::ContextData<char*> oomStackTraceBuffer_;
    998  js::ContextData<bool> oomStackTraceBufferValid_;
    999 
   1000  JSObject* getIncumbentGlobal(JSContext* cx);
   1001  bool enqueuePromiseJob(JSContext* cx, js::HandleFunction job,
   1002                         js::HandleObject promise,
   1003                         js::HandleObject incumbentGlobal);
   1004  void addUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
   1005  void removeUnhandledRejectedPromise(JSContext* cx, js::HandleObject promise);
   1006 
   1007 private:
   1008  template <class... Args>
   1009  inline void checkImpl(const Args&... args);
   1010 
   1011  bool contextChecksEnabled() const {
   1012    // Don't perform these checks when called from a finalizer. The checking
   1013    // depends on other objects not having been swept yet.
   1014    return !RuntimeHeapIsCollecting(runtime()->heapState());
   1015  }
   1016 
   1017 public:
   1018  // Assert the arguments are in this context's realm (for scripts),
   1019  // compartment (for objects) or zone (for strings, symbols).
   1020  template <class... Args>
   1021  inline void check(const Args&... args);
   1022  template <class... Args>
   1023  inline void releaseCheck(const Args&... args);
   1024  template <class... Args>
   1025  MOZ_ALWAYS_INLINE void debugOnlyCheck(const Args&... args);
   1026 
   1027 #ifdef JS_STRUCTURED_SPEW
   1028 private:
   1029  // Spewer for this thread
   1030  js::UnprotectedData<js::StructuredSpewer> structuredSpewer_;
   1031 
   1032 public:
   1033  js::StructuredSpewer& spewer() { return structuredSpewer_.ref(); }
   1034 #endif
   1035 
   1036  // This flag indicates whether we should bypass CSP restrictions for
   1037  // eval() and Function() calls or not. This flag can be set when
   1038  // evaluating the code for Debugger.Frame.prototype.eval.
   1039  js::ContextData<bool> bypassCSPForDebugger;
   1040 
   1041  // Debugger having set `exclusiveDebuggerOnEval` property to true
   1042  // want their evaluations and calls to be ignore by all other Debuggers
   1043  // except themself. This flag indicates whether we are in such debugger
   1044  // evaluation, and which debugger initiated the evaluation. This debugger
   1045  // has other references on the stack and does not need to be traced.
   1046  js::ContextData<js::Debugger*> insideExclusiveDebuggerOnEval;
   1047 
   1048 #ifdef MOZ_EXECUTION_TRACING
   1049 private:
   1050  CustomObjectSummaryCallback customObjectSummaryCallback_ = nullptr;
   1051 
   1052  // This holds onto the JS execution tracer, a system which when turned on
   1053  // records function calls and other information about the JS which has been
   1054  // run under this context.
   1055  js::UniquePtr<js::ExecutionTracer> executionTracer_;
   1056 
   1057  // See suspendExecutionTracing
   1058  bool executionTracerSuspended_ = false;
   1059 
   1060  // Cleans up caches and realm flags associated with execution tracing, while
   1061  // leaving the underlying tracing buffers intact to be read from later.
   1062  void cleanUpExecutionTracingState();
   1063 
   1064 public:
   1065  js::ExecutionTracer& getExecutionTracer() {
   1066    MOZ_ASSERT(hasExecutionTracer());
   1067    return *executionTracer_;
   1068  }
   1069 
   1070  CustomObjectSummaryCallback getCustomObjectSummaryCallback() {
   1071    MOZ_ASSERT(hasExecutionTracer());
   1072    return customObjectSummaryCallback_;
   1073  }
   1074 
   1075  void setCustomObjectSummaryCallback(CustomObjectSummaryCallback cb) {
   1076    customObjectSummaryCallback_ = cb;
   1077  }
   1078 
   1079  // See the latter clause of the comment over executionTracer_
   1080  [[nodiscard]] bool enableExecutionTracing();
   1081  void disableExecutionTracing();
   1082 
   1083  // suspendExecutionTracing will turn off tracing, and clean up the relevant
   1084  // flags on this context's realms, but still leave the trace around to be
   1085  // collected. This currently is only called when an error occurs during
   1086  // tracing.
   1087  void suspendExecutionTracing();
   1088 
   1089  // Returns true if there is currently an ExecutionTracer tracing this
   1090  // context's execution.
   1091  bool hasExecutionTracer() {
   1092    return !!executionTracer_ && !executionTracerSuspended_;
   1093  }
   1094 #else
   1095  bool hasExecutionTracer() { return false; }
   1096 #endif
   1097 
   1098  JS::PersistentRooted<js::UniquePtr<js::MicroTaskQueueSet>> microTaskQueues;
   1099 }; /* struct JSContext */
   1100 
   1101 inline JSContext* JSRuntime::mainContextFromOwnThread() {
   1102  MOZ_ASSERT(mainContextFromAnyThread() == js::TlsContext.get());
   1103  return mainContextFromAnyThread();
   1104 }
   1105 
   1106 namespace js {
   1107 
   1108 struct MOZ_RAII AutoResolving {
   1109 public:
   1110  AutoResolving(JSContext* cx, HandleObject obj, HandleId id)
   1111      : context(cx), object(obj), id(id), link(cx->resolvingList) {
   1112    MOZ_ASSERT(obj);
   1113    cx->resolvingList = this;
   1114  }
   1115 
   1116  ~AutoResolving() {
   1117    MOZ_ASSERT(context->resolvingList == this);
   1118    context->resolvingList = link;
   1119  }
   1120 
   1121  bool alreadyStarted() const { return link && alreadyStartedSlow(); }
   1122 
   1123 private:
   1124  bool alreadyStartedSlow() const;
   1125 
   1126  JSContext* const context;
   1127  HandleObject object;
   1128  HandleId id;
   1129  AutoResolving* const link;
   1130 };
   1131 
   1132 /*
   1133 * Create and destroy functions for JSContext, which is manually allocated
   1134 * and exclusively owned.
   1135 */
   1136 extern JSContext* NewContext(uint32_t maxBytes, JSRuntime* parentRuntime);
   1137 
   1138 extern void DestroyContext(JSContext* cx);
   1139 
   1140 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
   1141 extern void ReportUsageErrorASCII(JSContext* cx, HandleObject callee,
   1142                                  const char* msg);
   1143 
   1144 extern void ReportIsNotDefined(JSContext* cx, Handle<PropertyName*> name);
   1145 
   1146 extern void ReportIsNotDefined(JSContext* cx, HandleId id);
   1147 
   1148 /*
   1149 * Report an attempt to access the property of a null or undefined value (v).
   1150 */
   1151 extern void ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx,
   1152                                                     HandleValue v, int vIndex);
   1153 extern void ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx,
   1154                                                     HandleValue v, int vIndex,
   1155                                                     HandleId key);
   1156 
   1157 /*
   1158 * Report error using js::DecompileValueGenerator(cx, spindex, v, fallback) as
   1159 * the first argument for the error message.
   1160 */
   1161 extern bool ReportValueError(JSContext* cx, const unsigned errorNumber,
   1162                             int spindex, HandleValue v, HandleString fallback,
   1163                             const char* arg1 = nullptr,
   1164                             const char* arg2 = nullptr);
   1165 
   1166 JSObject* CreateErrorNotesArray(JSContext* cx, JSErrorReport* report);
   1167 
   1168 /************************************************************************/
   1169 
   1170 /*
   1171 * Encapsulates an external array of values and adds a trace method, for use in
   1172 * Rooted.
   1173 */
   1174 class MOZ_STACK_CLASS ExternalValueArray {
   1175 public:
   1176  ExternalValueArray(size_t len, Value* vec) : array_(vec), length_(len) {}
   1177 
   1178  Value* begin() { return array_; }
   1179  size_t length() { return length_; }
   1180 
   1181  void trace(JSTracer* trc);
   1182 
   1183 private:
   1184  Value* array_;
   1185  size_t length_;
   1186 };
   1187 
   1188 /* RootedExternalValueArray roots an external array of Values. */
   1189 class MOZ_RAII RootedExternalValueArray
   1190    : public JS::Rooted<ExternalValueArray> {
   1191 public:
   1192  RootedExternalValueArray(JSContext* cx, size_t len, Value* vec)
   1193      : JS::Rooted<ExternalValueArray>(cx, ExternalValueArray(len, vec)) {}
   1194 
   1195 private:
   1196 };
   1197 
   1198 class AutoAssertNoPendingException {
   1199 #ifdef DEBUG
   1200  JSContext* cx_;
   1201 
   1202 public:
   1203  explicit AutoAssertNoPendingException(JSContext* cxArg) : cx_(cxArg) {
   1204    MOZ_ASSERT(!JS_IsExceptionPending(cx_));
   1205  }
   1206 
   1207  ~AutoAssertNoPendingException() { MOZ_ASSERT(!JS_IsExceptionPending(cx_)); }
   1208 #else
   1209 public:
   1210  explicit AutoAssertNoPendingException(JSContext* cxArg) {}
   1211 #endif
   1212 };
   1213 
   1214 class MOZ_RAII AutoNoteExclusiveDebuggerOnEval {
   1215  JSContext* cx;
   1216  Debugger* oldValue;
   1217 
   1218 public:
   1219  AutoNoteExclusiveDebuggerOnEval(JSContext* cx, Debugger* dbg)
   1220      : cx(cx), oldValue(cx->insideExclusiveDebuggerOnEval) {
   1221    cx->insideExclusiveDebuggerOnEval = dbg;
   1222  }
   1223 
   1224  ~AutoNoteExclusiveDebuggerOnEval() {
   1225    cx->insideExclusiveDebuggerOnEval = oldValue;
   1226  }
   1227 };
   1228 
   1229 class MOZ_RAII AutoSetBypassCSPForDebugger {
   1230  JSContext* cx;
   1231  bool oldValue;
   1232 
   1233 public:
   1234  AutoSetBypassCSPForDebugger(JSContext* cx, bool value)
   1235      : cx(cx), oldValue(cx->bypassCSPForDebugger) {
   1236    cx->bypassCSPForDebugger = value;
   1237  }
   1238 
   1239  ~AutoSetBypassCSPForDebugger() { cx->bypassCSPForDebugger = oldValue; }
   1240 };
   1241 
   1242 enum UnsafeABIStrictness { NoExceptions, AllowPendingExceptions };
   1243 
   1244 // Should be used in functions called directly from JIT code (with
   1245 // masm.callWithABI). This assert invariants in debug builds. Resets
   1246 // JSContext::inUnsafeCallWithABI on destruction.
   1247 //
   1248 // In debug mode, masm.callWithABI inserts code to verify that the callee
   1249 // function uses AutoUnsafeCallWithABI.
   1250 //
   1251 // While this object is live:
   1252 //   1. cx->hasAutoUnsafeCallWithABI must be true.
   1253 //   2. We can't GC.
   1254 //   3. Exceptions should not be pending/thrown.
   1255 //
   1256 // Note that #3 is a precaution, not a requirement. By default, we assert that
   1257 // the function is not called with a pending exception, and that it does not
   1258 // throw an exception itself.
   1259 class MOZ_RAII AutoUnsafeCallWithABI {
   1260 #ifdef JS_CHECK_UNSAFE_CALL_WITH_ABI
   1261  JSContext* cx_;
   1262  bool nested_;
   1263  bool checkForPendingException_;
   1264 #endif
   1265  JS::AutoCheckCannotGC nogc;
   1266 
   1267 public:
   1268 #ifdef JS_CHECK_UNSAFE_CALL_WITH_ABI
   1269  explicit AutoUnsafeCallWithABI(
   1270      UnsafeABIStrictness strictness = UnsafeABIStrictness::NoExceptions);
   1271  ~AutoUnsafeCallWithABI();
   1272 #else
   1273  explicit AutoUnsafeCallWithABI(
   1274      UnsafeABIStrictness unused_ = UnsafeABIStrictness::NoExceptions) {}
   1275 #endif
   1276 };
   1277 
   1278 template <typename T>
   1279 inline BufferHolder<T>::BufferHolder(JSContext* cx, T* buffer)
   1280    : BufferHolder(cx->zone(), buffer) {}
   1281 
   1282 } /* namespace js */
   1283 
   1284 #define CHECK_THREAD(cx) \
   1285  MOZ_ASSERT_IF(cx, js::CurrentThreadCanAccessRuntime(cx->runtime()))
   1286 
   1287 /**
   1288 * [SMDOC] JS::Result transitional macros
   1289 *
   1290 * ## Checking Results when your return type is not Result
   1291 *
   1292 * This header defines alternatives to MOZ_TRY for when you
   1293 * need to call a `Result` function from a function that uses false or nullptr
   1294 * to indicate errors:
   1295 *
   1296 *     JS_TRY_OR_RETURN_FALSE(cx, DefenestrateObject(cx, obj));
   1297 *     JS_TRY_VAR_OR_RETURN_FALSE(cx, v, GetObjectThrug(cx, obj));
   1298 *
   1299 *     JS_TRY_VAR_OR_RETURN_NULL(cx, v, GetObjectThrug(cx, obj));
   1300 *
   1301 * When TRY is not what you want, because you need to do some cleanup or
   1302 * recovery on error, use this idiom:
   1303 *
   1304 *     if (!cx->resultToBool(expr_that_is_a_Result)) {
   1305 *         ... your recovery code here ...
   1306 *     }
   1307 *
   1308 * In place of a tail call, you can use one of these methods:
   1309 *
   1310 *     return cx->resultToBool(expr);  // false on error
   1311 *     return cx->resultToPtr(expr);  // null on error
   1312 *
   1313 * Once we are using `Result` everywhere, including in public APIs, all of
   1314 * these will go away.
   1315 */
   1316 
   1317 /**
   1318 * JS_TRY_OR_RETURN_FALSE(cx, expr) runs expr to compute a Result value.
   1319 * On success, nothing happens; on error, it returns false immediately.
   1320 *
   1321 * Implementation note: this involves cx because this may eventually
   1322 * do the work of setting a pending exception or reporting OOM.
   1323 */
   1324 #define JS_TRY_OR_RETURN_FALSE(cx, expr)                           \
   1325  do {                                                             \
   1326    auto tmpResult_ = (expr);                                      \
   1327    if (tmpResult_.isErr()) return (cx)->resultToBool(tmpResult_); \
   1328  } while (0)
   1329 
   1330 #define JS_TRY_VAR_OR_RETURN_FALSE(cx, target, expr)               \
   1331  do {                                                             \
   1332    auto tmpResult_ = (expr);                                      \
   1333    if (tmpResult_.isErr()) return (cx)->resultToBool(tmpResult_); \
   1334    (target) = tmpResult_.unwrap();                                \
   1335  } while (0)
   1336 
   1337 #define JS_TRY_VAR_OR_RETURN_NULL(cx, target, expr)     \
   1338  do {                                                  \
   1339    auto tmpResult_ = (expr);                           \
   1340    if (tmpResult_.isErr()) {                           \
   1341      MOZ_ALWAYS_FALSE((cx)->resultToBool(tmpResult_)); \
   1342      return nullptr;                                   \
   1343    }                                                   \
   1344    (target) = tmpResult_.unwrap();                     \
   1345  } while (0)
   1346 
   1347 #endif /* vm_JSContext_h */