jsshell.h (7693B)
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 #ifndef jsshell_js_h 8 #define jsshell_js_h 9 10 #include "mozilla/Atomics.h" 11 #include "mozilla/Maybe.h" 12 #include "mozilla/TimeStamp.h" 13 14 #include "builtin/MapObject.h" 15 #include "js/CompileOptions.h" 16 #include "js/GCVector.h" 17 #include "shell/ModuleLoader.h" 18 #include "threading/ConditionVariable.h" 19 #include "threading/LockGuard.h" 20 #include "threading/Mutex.h" 21 #include "threading/Thread.h" 22 #include "vm/GeckoProfiler.h" 23 #include "vm/Monitor.h" 24 25 // Some platform hooks must be implemented for single-step profiling. 26 #if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64) || \ 27 defined(JS_SIMULATOR_ARM64) || defined(JS_SIMULATOR_LOONG64) 28 # define SINGLESTEP_PROFILING 29 #endif 30 31 namespace js { 32 namespace shell { 33 34 // Define use of application-specific slots on the shell's global object. 35 enum GlobalAppSlot { GlobalAppSlotModuleRegistry, GlobalAppSlotCount }; 36 static_assert(GlobalAppSlotCount <= JSCLASS_GLOBAL_APPLICATION_SLOTS, 37 "Too many applications slots defined for shell global"); 38 39 enum JSShellErrNum { 40 #define MSG_DEF(name, count, exception, format) name, 41 #include "jsshell.msg" 42 #undef MSG_DEF 43 JSShellErr_Limit 44 }; 45 46 const JSErrorFormatString* my_GetErrorMessage(void* userRef, 47 const unsigned errorNumber); 48 49 void WarningReporter(JSContext* cx, JSErrorReport* report); 50 51 class MOZ_STACK_CLASS AutoReportException { 52 JSContext* cx; 53 54 public: 55 explicit AutoReportException(JSContext* cx) : cx(cx) {} 56 ~AutoReportException(); 57 }; 58 59 bool GenerateInterfaceHelp(JSContext* cx, JS::HandleObject obj, 60 const char* name); 61 62 JSString* FileAsString(JSContext* cx, JS::HandleString pathnameStr); 63 64 class AutoCloseFile { 65 private: 66 FILE* f_; 67 68 public: 69 explicit AutoCloseFile(FILE* f) : f_(f) {} 70 ~AutoCloseFile() { (void)release(); } 71 bool release() { 72 bool success = true; 73 if (f_ && f_ != stdin && f_ != stdout && f_ != stderr) { 74 success = !fclose(f_); 75 } 76 f_ = nullptr; 77 return success; 78 } 79 }; 80 81 // Reference counted file. 82 struct RCFile { 83 FILE* fp; 84 uint32_t numRefs; 85 86 RCFile() : fp(nullptr), numRefs(0) {} 87 explicit RCFile(FILE* fp) : fp(fp), numRefs(0) {} 88 89 void acquire() { numRefs++; } 90 91 // Starts out with a ref count of zero. 92 static RCFile* create(JSContext* cx, const char* filename, const char* mode); 93 94 void close(); 95 bool isOpen() const { return fp; } 96 bool release(); 97 }; 98 99 // Shell command-line arguments and count. 100 extern int sArgc; 101 extern char** sArgv; 102 103 // Shell state set once at startup. 104 extern const char* selfHostedXDRPath; 105 extern bool encodeSelfHostedCode; 106 extern bool enableCodeCoverage; 107 extern bool enableDisassemblyDumps; 108 extern bool offthreadBaselineCompilation; 109 extern bool offthreadIonCompilation; 110 extern JS::DelazificationOption defaultDelazificationMode; 111 extern bool enableAsmJS; 112 extern bool enableWasm; 113 extern bool enableSharedMemory; 114 extern bool enableWasmBaseline; 115 extern bool enableWasmOptimizing; 116 extern bool enableTestWasmAwaitTier2; 117 extern bool enableSourcePragmas; 118 extern bool enableAsyncStacks; 119 extern bool enableAsyncStackCaptureDebuggeeOnly; 120 extern bool enableWeakRefs; 121 extern bool enableToSource; 122 extern bool enablePropertyErrorMessageFix; 123 extern bool enableIteratorHelpers; 124 extern bool enableShadowRealms; 125 extern bool enableArrayGrouping; 126 extern bool enableWellFormedUnicodeStrings; 127 extern bool enableArrayBufferTransfer; 128 extern bool enableArrayBufferResizable; 129 extern bool enableSymbolsAsWeakMapKeys; 130 extern bool enableNewSetMethods; 131 extern bool enableDestructuringFuse; 132 #ifdef JS_GC_ZEAL 133 extern uint32_t gZealBits; 134 extern uint32_t gZealFrequency; 135 #endif 136 extern bool printTiming; 137 extern RCFile* gErrFile; 138 extern RCFile* gOutFile; 139 extern bool reportWarnings; 140 extern bool compileOnly; 141 extern bool disableOOMFunctions; 142 extern bool defaultToSameCompartment; 143 144 #ifdef DEBUG 145 extern bool dumpEntrainedVariables; 146 extern bool OOM_printAllocationCount; 147 #endif 148 149 extern bool useFdlibmForSinCosTan; 150 151 extern UniqueChars processWideModuleLoadPath; 152 153 // Alias the global dstName to namespaceObj.srcName. For example, if dstName is 154 // "snarf", namespaceObj represents "os.file", and srcName is "readFile", then 155 // this is equivalent to the JS code: 156 // 157 // snarf = os.file.readFile; 158 // 159 // This provides a mechanism for namespacing the various JS shell helper 160 // functions without breaking backwards compatibility with things that use the 161 // global names. 162 bool CreateAlias(JSContext* cx, const char* dstName, 163 JS::HandleObject namespaceObj, const char* srcName); 164 165 class NonShrinkingValueVector 166 : public GCVector<HeapPtr<Value>, 0, SystemAllocPolicy> { 167 using Base = GCVector<HeapPtr<Value>, 0, SystemAllocPolicy>; 168 169 public: 170 bool traceWeak(JSTracer* trc) { 171 for (HeapPtr<Value>& value : *this) { 172 if (value.isGCThing()) { 173 Zone* zone = value.toGCThing()->zoneFromAnyThread(); 174 if (zone->isGCSweeping() || zone->isGCCompacting()) { 175 TraceWeakEdge(trc, &value, "NonShrinkingValueVector element"); 176 } 177 } 178 } 179 return true; 180 } 181 }; 182 183 using MarkBitObservers = JS::WeakCache<NonShrinkingValueVector>; 184 185 #ifdef SINGLESTEP_PROFILING 186 using StackChars = Vector<char16_t, 0, SystemAllocPolicy>; 187 #endif 188 189 class OffThreadJob; 190 191 // Per-context shell state. 192 struct ShellContext { 193 enum IsWorkerEnum { Worker = true, MainThread = false }; 194 195 explicit ShellContext(JSContext* cx, IsWorkerEnum isWorker_); 196 bool registerWithCx(JSContext* cx); 197 ~ShellContext(); 198 199 JSContext* cx_; 200 201 const IsWorkerEnum isWorker; 202 bool lastWarningEnabled; 203 204 // Track promise rejections and report unhandled rejections. 205 bool trackUnhandledRejections; 206 207 double timeoutInterval; 208 double startTime; 209 mozilla::Atomic<bool> serviceInterrupt; 210 mozilla::Atomic<bool> haveInterruptFunc; 211 JS::PersistentRootedValue interruptFunc; 212 JS::PersistentRootedValue lastWarning; 213 JS::PersistentRootedValue promiseRejectionTrackerCallback; 214 215 // Rejected promises that are not yet handled. Added when rejection 216 // happens, and removed when rejection is handled. This uses SetObject to 217 // report unhandled rejections in the rejected order. 218 JS::PersistentRooted<SetObject*> unhandledRejectedPromises; 219 220 #ifdef SINGLESTEP_PROFILING 221 Vector<StackChars, 0, SystemAllocPolicy> stacks; 222 #endif 223 224 /* 225 * Watchdog thread state. 226 */ 227 js::Mutex watchdogLock MOZ_UNANNOTATED; 228 js::ConditionVariable watchdogWakeup; 229 mozilla::Maybe<js::Thread> watchdogThread; 230 mozilla::Maybe<mozilla::TimeStamp> watchdogTimeout; 231 232 js::ConditionVariable sleepWakeup; 233 234 int exitCode; 235 bool quitting; 236 237 JS::UniqueChars readLineBuf; 238 size_t readLineBufPos; 239 240 js::shell::RCFile** errFilePtr; 241 js::shell::RCFile** outFilePtr; 242 243 UniquePtr<ProfilingStack> geckoProfilingStack; 244 245 UniquePtr<ModuleLoader> moduleLoader; 246 247 UniquePtr<MarkBitObservers> markObservers; 248 249 // Off-thread parse state. 250 js::Monitor offThreadMonitor MOZ_UNANNOTATED; 251 Vector<OffThreadJob*, 0, SystemAllocPolicy> offThreadJobs; 252 253 // Queued task callbacks that run after the microtask queue. 254 255 using ObjectVector = GCVector<JSObject*, 0, SystemAllocPolicy>; 256 JS::PersistentRooted<ObjectVector> taskCallbacks; 257 }; 258 259 extern ShellContext* GetShellContext(JSContext* cx); 260 261 [[nodiscard]] extern bool PrintStackTrace(JSContext* cx, 262 JS::Handle<JSObject*> stackObj); 263 264 } /* namespace shell */ 265 } /* namespace js */ 266 267 #endif