// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_D8_D8_H_ #define V8_D8_D8_H_ #include #include #include #include #include #include #include #include #include "include/v8-array-buffer.h" #include "include/v8-isolate.h" #include "include/v8-script.h" #include "src/base/once.h" #include "src/base/platform/time.h" #include "src/base/platform/wrappers.h" #include "src/d8/async-hooks-wrapper.h" #include "src/heap/parked-scope.h" namespace v8 { class BackingStore; class CompiledWasmModule; class D8Console; class Message; class TryCatch; enum class ModuleType { kJavaScript, kJSON, kInvalid }; namespace internal { class CancelableTaskManager; } // namespace internal struct DynamicImportData; // A single counter in a counter collection. class Counter { public: static const int kMaxNameSize = 64; void Bind(const char* name, bool histogram); // TODO(12482): Return pointer to an atomic. int* ptr() { static_assert(sizeof(int) == sizeof(count_)); return reinterpret_cast(&count_); } int count() const { return count_.load(std::memory_order_relaxed); } int sample_total() const { return sample_total_.load(std::memory_order_relaxed); } bool is_histogram() const { return is_histogram_; } void AddSample(int32_t sample); private: std::atomic count_; std::atomic sample_total_; bool is_histogram_; char name_[kMaxNameSize]; }; // A set of counters and associated information. An instance of this // class is stored directly in the memory-mapped counters file if // the --map-counters options is used class CounterCollection { public: CounterCollection(); Counter* GetNextCounter(); private: static const unsigned kMaxCounters = 512; uint32_t magic_number_; uint32_t max_counters_; uint32_t max_name_size_; uint32_t counters_in_use_; Counter counters_[kMaxCounters]; }; using CounterMap = std::unordered_map; class SourceGroup { public: SourceGroup() : next_semaphore_(0), done_semaphore_(0), thread_(nullptr), argv_(nullptr), begin_offset_(0), end_offset_(0) {} ~SourceGroup(); void Begin(char** argv, int offset) { argv_ = const_cast(argv); begin_offset_ = offset; } void End(int offset) { end_offset_ = offset; } // Returns true on success, false if an uncaught exception was thrown. bool Execute(Isolate* isolate); void StartExecuteInThread(); void WaitForThread(const i::ParkedScope& parked); void JoinThread(const i::ParkedScope& parked); private: class IsolateThread : public base::Thread { public: explicit IsolateThread(SourceGroup* group); void Run() override { group_->ExecuteInThread(); } private: SourceGroup* group_; }; void ExecuteInThread(); i::ParkingSemaphore next_semaphore_; i::ParkingSemaphore done_semaphore_; base::Thread* thread_; void ExitShell(int exit_code); const char** argv_; int begin_offset_; int end_offset_; }; class SerializationData { public: SerializationData() = default; SerializationData(const SerializationData&) = delete; SerializationData& operator=(const SerializationData&) = delete; uint8_t* data() { return data_.get(); } size_t size() { return size_; } const std::vector>& backing_stores() { return backing_stores_; } const std::vector>& sab_backing_stores() { return sab_backing_stores_; } const std::vector& compiled_wasm_modules() { return compiled_wasm_modules_; } const std::vector>& shared_values() { return shared_values_; } void ClearSharedValuesUnderLockIfNeeded(); private: struct DataDeleter { void operator()(uint8_t* p) const { base::Free(p); } }; std::unique_ptr data_; size_t size_ = 0; std::vector> backing_stores_; std::vector> sab_backing_stores_; std::vector compiled_wasm_modules_; std::vector> shared_values_; private: friend class Serializer; }; class SerializationDataQueue { public: void Enqueue(std::unique_ptr data); bool Dequeue(std::unique_ptr* data); bool IsEmpty(); void Clear(); private: base::Mutex mutex_; std::vector> data_; }; class Worker : public std::enable_shared_from_this { public: explicit Worker(const char* script); ~Worker(); // Post a message to the worker. The worker will take ownership of the // SerializationData. This function should only be called by the thread that // created the Worker. void PostMessage(std::unique_ptr data); // Synchronously retrieve messages from the worker's outgoing message queue. // If there is no message in the queue, block until a message is available. // If there are no messages in the queue and the worker is no longer running, // return nullptr. // This function should only be called by the thread that created the Worker. std::unique_ptr GetMessage(Isolate* requester); // Terminate the worker's event loop. Messages from the worker that have been // queued can still be read via GetMessage(). // This function can be called by any thread. void Terminate(); // Terminate and join the thread. // This function can be called by any thread. void TerminateAndWaitForThread(const i::ParkedScope& parked); // Start running the given worker in another thread. static bool StartWorkerThread(Isolate* requester, std::shared_ptr worker); private: friend class ProcessMessageTask; friend class TerminateTask; enum class State { kReady, kPrepareRunning, kRunning, kTerminating, kTerminated, }; bool is_running() const; void ProcessMessage(std::unique_ptr data); void ProcessMessages(); class WorkerThread : public base::Thread { public: explicit WorkerThread(std::shared_ptr worker) : base::Thread(base::Thread::Options("WorkerThread")), worker_(std::move(worker)) {} void Run() override; private: std::shared_ptr worker_; }; void ExecuteInThread(); static void PostMessageOut(const v8::FunctionCallbackInfo& args); i::ParkingSemaphore out_semaphore_{0}; SerializationDataQueue out_queue_; base::Thread* thread_ = nullptr; char* script_; std::atomic state_; bool is_joined_ = false; // For signalling that the worker has started. i::ParkingSemaphore started_semaphore_{0}; // For posting tasks to the worker std::shared_ptr task_runner_; i::CancelableTaskManager* task_manager_; // Protects reading / writing task_runner_. (The TaskRunner itself doesn't // need locking, but accessing the Worker's data member does.) base::Mutex worker_mutex_; // The isolate should only be accessed by the worker itself, or when holding // the worker_mutex_ and after checking the worker state. Isolate* isolate_ = nullptr; // Only accessed by the worker thread. v8::Persistent context_; }; class PerIsolateData { public: explicit PerIsolateData(Isolate* isolate); ~PerIsolateData(); inline static PerIsolateData* Get(Isolate* isolate) { return reinterpret_cast(isolate->GetData(0)); } class V8_NODISCARD RealmScope { public: explicit RealmScope(PerIsolateData* data); ~RealmScope(); private: PerIsolateData* data_; }; // Contrary to RealmScope (which creates a new Realm), ExplicitRealmScope // allows for entering an existing Realm, as specified by its index. class V8_NODISCARD ExplicitRealmScope { public: explicit ExplicitRealmScope(PerIsolateData* data, int index); ~ExplicitRealmScope(); Local context() const; private: PerIsolateData* data_; Local realm_; int index_; int previous_index_; }; inline void SetTimeout(Local callback, Local context); inline MaybeLocal GetTimeoutCallback(); inline MaybeLocal GetTimeoutContext(); AsyncHooks* GetAsyncHooks() { return async_hooks_wrapper_; } void RemoveUnhandledPromise(Local promise); void AddUnhandledPromise(Local promise, Local message, Local exception); int HandleUnhandledPromiseRejections(); // Keep track of DynamicImportData so we can properly free it on shutdown // when LEAK_SANITIZER is active. void AddDynamicImportData(DynamicImportData*); void DeleteDynamicImportData(DynamicImportData*); Local GetTestApiObjectCtor() const; void SetTestApiObjectCtor(Local ctor); Local GetSnapshotObjectCtor() const; void SetSnapshotObjectCtor(Local ctor); Local GetDomNodeCtor() const; void SetDomNodeCtor(Local ctor); private: friend class Shell; friend class RealmScope; Isolate* isolate_; int realm_count_; int realm_current_; int realm_switch_; Global* realms_; Global realm_shared_; std::queue> set_timeout_callbacks_; std::queue> set_timeout_contexts_; bool ignore_unhandled_promises_; std::vector, Global, Global>> unhandled_promises_; AsyncHooks* async_hooks_wrapper_; #if defined(LEAK_SANITIZER) std::unordered_set import_data_; #endif Global test_api_object_ctor_; Global snapshot_object_ctor_; Global dom_node_ctor_; int RealmIndexOrThrow(const v8::FunctionCallbackInfo& args, int arg_offset); int RealmFind(Local context); }; extern bool check_d8_flag_contradictions; class ShellOptions { public: enum CodeCacheOptions { kNoProduceCache, kProduceCache, kProduceCacheAfterExecute }; ~ShellOptions() { delete[] isolate_sources; } // In analogy to Flag::CheckFlagChange() in src/flags/flag.cc, only allow // repeated flags for identical boolean values. We allow exceptions for flags // with enum-like arguments since their conflicts can also be specified // completely. template ::value> class DisallowReassignment { public: DisallowReassignment(const char* name, T value) : name_(name), value_(value) {} operator T() const { return value_; } T get() const { return value_; } DisallowReassignment& operator=(T value) { if (check_d8_flag_contradictions) { if (kAllowIdenticalAssignment) { if (specified_ && value_ != value) { FATAL("Contradictory values for d8 flag --%s", name_); } } else { if (specified_) { FATAL("Repeated specification of d8 flag --%s", name_); } } } value_ = value; specified_ = true; return *this; } void Overwrite(T value) { value_ = value; } private: const char* name_; T value_; bool specified_ = false; }; DisallowReassignment d8_path = {"d8-path", ""}; DisallowReassignment fuzzilli_coverage_statistics = { "fuzzilli-coverage-statistics", false}; DisallowReassignment fuzzilli_enable_builtins_coverage = { "fuzzilli-enable-builtins-coverage", true}; DisallowReassignment send_idle_notification = {"send-idle-notification", false}; DisallowReassignment invoke_weak_callbacks = {"invoke-weak-callbacks", false}; DisallowReassignment omit_quit = {"omit-quit", false}; DisallowReassignment wait_for_background_tasks = { "wait-for-background-tasks", true}; DisallowReassignment simulate_errors = {"simulate-errors", false}; DisallowReassignment stress_opt = {"stress-opt", false}; DisallowReassignment stress_runs = {"stress-runs", 1}; DisallowReassignment interactive_shell = {"shell", false}; bool test_shell = false; DisallowReassignment expected_to_throw = {"throws", false}; DisallowReassignment no_fail = {"no-fail", false}; DisallowReassignment dump_counters = {"dump-counters", false}; DisallowReassignment dump_counters_nvp = {"dump-counters-nvp", false}; DisallowReassignment ignore_unhandled_promises = { "ignore-unhandled-promises", false}; DisallowReassignment mock_arraybuffer_allocator = { "mock-arraybuffer-allocator", false}; DisallowReassignment mock_arraybuffer_allocator_limit = { "mock-arraybuffer-allocator-limit", 0}; #if MULTI_MAPPED_ALLOCATOR_AVAILABLE DisallowReassignment multi_mapped_mock_allocator = { "multi-mapped-mock-allocator", false}; #endif DisallowReassignment enable_inspector = {"enable-inspector", false}; int num_isolates = 1; DisallowReassignment compile_options = {"cache", v8::ScriptCompiler::kNoCompileOptions}; DisallowReassignment code_cache_options = { "cache", CodeCacheOptions::kNoProduceCache}; DisallowReassignment streaming_compile = {"streaming-compile", false}; DisallowReassignment isolate_sources = {"isolate-sources", nullptr}; DisallowReassignment icu_data_file = {"icu-data-file", nullptr}; DisallowReassignment icu_locale = {"icu-locale", nullptr}; DisallowReassignment snapshot_blob = {"snapshot_blob", nullptr}; DisallowReassignment trace_enabled = {"trace-enabled", false}; DisallowReassignment trace_path = {"trace-path", nullptr}; DisallowReassignment trace_config = {"trace-config", nullptr}; DisallowReassignment lcov_file = {"lcov", nullptr}; DisallowReassignment disable_in_process_stack_traces = { "disable-in-process-stack-traces", false}; DisallowReassignment read_from_tcp_port = {"read-from-tcp-port", -1}; DisallowReassignment enable_os_system = {"enable-os-system", false}; DisallowReassignment quiet_load = {"quiet-load", false}; DisallowReassignment thread_pool_size = {"thread-pool-size", 0}; DisallowReassignment stress_delay_tasks = {"stress-delay-tasks", false}; std::vector arguments; DisallowReassignment include_arguments = {"arguments", true}; DisallowReassignment cpu_profiler = {"cpu-profiler", false}; DisallowReassignment cpu_profiler_print = {"cpu-profiler-print", false}; DisallowReassignment fuzzy_module_file_extensions = { "fuzzy-module-file-extensions", true}; DisallowReassignment enable_system_instrumentation = { "enable-system-instrumentation", false}; DisallowReassignment enable_etw_stack_walking = { "enable-etw-stack-walking", false}; DisallowReassignment web_snapshot_config = { "web-snapshot-config", nullptr}; DisallowReassignment web_snapshot_output = { "web-snapshot-output", nullptr}; DisallowReassignment d8_web_snapshot_api = { "experimental-d8-web-snapshot-api", false}; // Applies to web snapshot and JSON deserialization. DisallowReassignment stress_deserialize = {"stress-deserialize", false}; DisallowReassignment compile_only = {"compile-only", false}; DisallowReassignment repeat_compile = {"repeat-compile", 1}; #if V8_ENABLE_WEBASSEMBLY DisallowReassignment wasm_trap_handler = {"wasm-trap-handler", true}; #endif // V8_ENABLE_WEBASSEMBLY DisallowReassignment expose_fast_api = {"expose-fast-api", false}; #if V8_ENABLE_SANDBOX DisallowReassignment enable_sandbox_crash_filter = { "enable-sandbox-crash-filter", false}; #endif // V8_ENABLE_SANDBOX DisallowReassignment throw_on_failed_access_check = { "throw-on-failed-access-check", false}; DisallowReassignment noop_on_failed_access_check = { "noop-on-failed-access-check", false}; }; class Shell : public i::AllStatic { public: enum PrintResult : bool { kPrintResult = true, kNoPrintResult = false }; enum ReportExceptions : bool { kReportExceptions = true, kNoReportExceptions = false }; enum ProcessMessageQueue : bool { kProcessMessageQueue = true, kNoProcessMessageQueue = false }; enum class CodeType { kFileName, kString, kFunction, kInvalid, kNone }; static bool ExecuteString(Isolate* isolate, Local source, Local name, PrintResult print_result, ReportExceptions report_exceptions, ProcessMessageQueue process_message_queue); static bool ExecuteModule(Isolate* isolate, const char* file_name); static bool TakeWebSnapshot(Isolate* isolate); static bool ExecuteWebSnapshot(Isolate* isolate, const char* file_name); static bool LoadJSON(Isolate* isolate, const char* file_name); static void ReportException(Isolate* isolate, Local message, Local exception); static void ReportException(Isolate* isolate, TryCatch* try_catch); static MaybeLocal ReadFile(Isolate* isolate, const char* name, bool should_throw = true); static Local WasmLoadSourceMapCallback(Isolate* isolate, const char* name); static Local CreateEvaluationContext(Isolate* isolate); static int RunMain(Isolate* isolate, bool last_run); static int Main(int argc, char* argv[]); static void Exit(int exit_code); static void OnExit(Isolate* isolate, bool dispose); static void CollectGarbage(Isolate* isolate); static bool EmptyMessageQueues(Isolate* isolate); static bool CompleteMessageLoop(Isolate* isolate); static bool HandleUnhandledPromiseRejections(Isolate* isolate); static void PostForegroundTask(Isolate* isolate, std::unique_ptr task); static void PostBlockingBackgroundTask(std::unique_ptr task); static std::unique_ptr SerializeValue( Isolate* isolate, Local value, Local transfer); static MaybeLocal DeserializeValue( Isolate* isolate, std::unique_ptr data); static int* LookupCounter(const char* name); static void* CreateHistogram(const char* name, int min, int max, size_t buckets); static void AddHistogramSample(void* histogram, int sample); static void MapCounters(v8::Isolate* isolate, const char* name); static void PerformanceNow(const v8::FunctionCallbackInfo& args); static void PerformanceMeasureMemory( const v8::FunctionCallbackInfo& args); static void RealmCurrent(const v8::FunctionCallbackInfo& args); static void RealmOwner(const v8::FunctionCallbackInfo& args); static void RealmGlobal(const v8::FunctionCallbackInfo& args); static void RealmCreate(const v8::FunctionCallbackInfo& args); static void RealmNavigate(const v8::FunctionCallbackInfo& args); static void RealmCreateAllowCrossRealmAccess( const v8::FunctionCallbackInfo& args); static void RealmDetachGlobal( const v8::FunctionCallbackInfo& args); static void RealmDispose(const v8::FunctionCallbackInfo& args); static void RealmSwitch(const v8::FunctionCallbackInfo& args); static void RealmEval(const v8::FunctionCallbackInfo& args); static void RealmSharedGet(Local property, const PropertyCallbackInfo& info); static void RealmSharedSet(Local property, Local value, const PropertyCallbackInfo& info); static void RealmTakeWebSnapshot( const v8::FunctionCallbackInfo& args); static void RealmUseWebSnapshot( const v8::FunctionCallbackInfo& args); static void LogGetAndStop(const v8::FunctionCallbackInfo& args); static void TestVerifySourcePositions( const v8::FunctionCallbackInfo& args); static void InstallConditionalFeatures( const v8::FunctionCallbackInfo& args); static void AsyncHooksCreateHook( const v8::FunctionCallbackInfo& args); static void AsyncHooksExecutionAsyncId( const v8::FunctionCallbackInfo& args); static void AsyncHooksTriggerAsyncId( const v8::FunctionCallbackInfo& args); static void SetPromiseHooks(const v8::FunctionCallbackInfo& args); static void SerializerSerialize( const v8::FunctionCallbackInfo& args); static void SerializerDeserialize( const v8::FunctionCallbackInfo& args); static void Print(const v8::FunctionCallbackInfo& args); static void PrintErr(const v8::FunctionCallbackInfo& args); static void WriteStdout(const v8::FunctionCallbackInfo& args); static void WaitUntilDone(const v8::FunctionCallbackInfo& args); static void NotifyDone(const v8::FunctionCallbackInfo& args); static void QuitOnce(v8::FunctionCallbackInfo* args); static void Quit(const v8::FunctionCallbackInfo& args); static void Version(const v8::FunctionCallbackInfo& args); static void ReadFile(const v8::FunctionCallbackInfo& args); static char* ReadChars(const char* name, int* size_out); static MaybeLocal ReadLines(Isolate* isolate, const char* name); static void ReadBuffer(const v8::FunctionCallbackInfo& args); static Local ReadFromStdin(Isolate* isolate); static void ReadLine(const v8::FunctionCallbackInfo& args) { args.GetReturnValue().Set(ReadFromStdin(args.GetIsolate())); } static void WriteChars(const char* name, uint8_t* buffer, size_t buffer_size); static void ExecuteFile(const v8::FunctionCallbackInfo& args); static void SetTimeout(const v8::FunctionCallbackInfo& args); static void ReadCodeTypeAndArguments( const v8::FunctionCallbackInfo& args, int index, CodeType* code_type, Local* arguments = nullptr); static bool FunctionAndArgumentsToString(Local function, Local arguments, Local* source, Isolate* isolate); static MaybeLocal ReadSource( const v8::FunctionCallbackInfo& args, int index, CodeType default_type); static void WorkerNew(const v8::FunctionCallbackInfo& args); static void WorkerPostMessage( const v8::FunctionCallbackInfo& args); static void WorkerGetMessage(const v8::FunctionCallbackInfo& args); static void WorkerTerminate(const v8::FunctionCallbackInfo& args); static void WorkerTerminateAndWait( const v8::FunctionCallbackInfo& args); // The OS object on the global object contains methods for performing // operating system calls: // // os.system("program_name", ["arg1", "arg2", ...], timeout1, timeout2) will // run the command, passing the arguments to the program. The standard output // of the program will be picked up and returned as a multiline string. If // timeout1 is present then it should be a number. -1 indicates no timeout // and a positive number is used as a timeout in milliseconds that limits the // time spent waiting between receiving output characters from the program. // timeout2, if present, should be a number indicating the limit in // milliseconds on the total running time of the program. Exceptions are // thrown on timeouts or other errors or if the exit status of the program // indicates an error. static void System(const v8::FunctionCallbackInfo& args); // os.chdir(dir) changes directory to the given directory. Throws an // exception/ on error. static void ChangeDirectory(const v8::FunctionCallbackInfo& args); // os.setenv(variable, value) sets an environment variable. Repeated calls to // this method leak memory due to the API of setenv in the standard C library. static void SetEnvironment(const v8::FunctionCallbackInfo& args); static void UnsetEnvironment(const v8::FunctionCallbackInfo& args); // os.umask(alue) calls the umask system call and returns the old umask. static void SetUMask(const v8::FunctionCallbackInfo& args); // os.mkdirp(name, mask) creates a directory. The mask (if present) is anded // with the current umask. Intermediate directories are created if necessary. // An exception is not thrown if the directory already exists. Analogous to // the "mkdir -p" command. static void MakeDirectory(const v8::FunctionCallbackInfo& args); static void RemoveDirectory(const v8::FunctionCallbackInfo& args); static MaybeLocal HostImportModuleDynamically( Local context, Local host_defined_options, Local resource_name, Local specifier, Local import_assertions); static void ModuleResolutionSuccessCallback( const v8::FunctionCallbackInfo& info); static void ModuleResolutionFailureCallback( const v8::FunctionCallbackInfo& info); static void HostInitializeImportMetaObject(Local context, Local module, Local meta); static MaybeLocal HostCreateShadowRealmContext( Local initiator_context); #ifdef V8_FUZZILLI static void Fuzzilli(const v8::FunctionCallbackInfo& args); #endif // V8_FUZZILLI // Data is of type DynamicImportData*. We use void* here to be able // to conform with MicrotaskCallback interface and enqueue this // function in the microtask queue. static void DoHostImportModuleDynamically(void* data); static void AddOSMethods(v8::Isolate* isolate, Local os_template); static const char* kPrompt; static ShellOptions options; static ArrayBuffer::Allocator* array_buffer_allocator; static Isolate* shared_isolate; static void SetWaitUntilDone(Isolate* isolate, bool value); static void NotifyStartStreamingTask(Isolate* isolate); static void NotifyFinishStreamingTask(Isolate* isolate); static char* ReadCharsFromTcpPort(const char* name, int* size_out); static void set_script_executed() { script_executed_.store(true); } static bool use_interactive_shell() { return (options.interactive_shell || !script_executed_.load()) && !options.test_shell; } static void update_script_size(int size) { if (size > 0) valid_fuzz_script_.store(true); } static bool is_valid_fuzz_script() { return valid_fuzz_script_.load(); } static void WaitForRunningWorkers(const i::ParkedScope& parked); static void AddRunningWorker(std::shared_ptr worker); static void RemoveRunningWorker(const std::shared_ptr& worker); static void Initialize(Isolate* isolate, D8Console* console, bool isOnMainThread = true); static void PromiseRejectCallback(v8::PromiseRejectMessage reject_message); static Local CreateSnapshotTemplate(Isolate* isolate); private: static inline int DeserializationRunCount() { return options.stress_deserialize ? 1000 : 1; } static Global evaluation_context_; static base::OnceType quit_once_; static Global stringify_function_; static const char* stringify_source_; static CounterMap* counter_map_; static base::SharedMutex counter_mutex_; // We statically allocate a set of local counters to be used if we // don't want to store the stats in a memory-mapped file static CounterCollection local_counters_; static CounterCollection* counters_; static base::OS::MemoryMappedFile* counters_file_; static base::LazyMutex context_mutex_; static const base::TimeTicks kInitialTicks; static base::LazyMutex workers_mutex_; // Guards the following members. static bool allow_new_workers_; static std::unordered_set> running_workers_; // Multiple isolates may update these flags concurrently. static std::atomic script_executed_; static std::atomic valid_fuzz_script_; static void WriteIgnitionDispatchCountersFile(v8::Isolate* isolate); // Append LCOV coverage data to file. static void WriteLcovData(v8::Isolate* isolate, const char* file); static Counter* GetCounter(const char* name, bool is_histogram); static Local Stringify(Isolate* isolate, Local value); static void RunShell(Isolate* isolate); static bool SetOptions(int argc, char* argv[]); static void NodeTypeCallback(const v8::FunctionCallbackInfo& args); static Local CreateEventTargetTemplate(Isolate* isolate); static Local CreateNodeTemplates( Isolate* isolate, Local event_target); static Local CreateGlobalTemplate(Isolate* isolate); static Local CreateOSTemplate(Isolate* isolate); static Local CreateWorkerTemplate(Isolate* isolate); static Local CreateAsyncHookTemplate(Isolate* isolate); static Local CreateTestRunnerTemplate(Isolate* isolate); static Local CreatePerformanceTemplate(Isolate* isolate); static Local CreateRealmTemplate(Isolate* isolate); static Local CreateD8Template(Isolate* isolate); static Local CreateTestFastCApiTemplate(Isolate* isolate); static Local CreateLeafInterfaceTypeTemplate( Isolate* isolate); static MaybeLocal CreateRealm( const v8::FunctionCallbackInfo& args, int index, v8::MaybeLocal global_object); static void DisposeRealm(const v8::FunctionCallbackInfo& args, int index); static MaybeLocal FetchModuleTree(v8::Local origin_module, v8::Local context, const std::string& file_name, ModuleType module_type); static MaybeLocal JSONModuleEvaluationSteps(Local context, Local module); template static MaybeLocal CompileString(Isolate* isolate, Local context, Local source, const ScriptOrigin& origin); static ScriptCompiler::CachedData* LookupCodeCache(Isolate* isolate, Local name); static void StoreInCodeCache(Isolate* isolate, Local name, const ScriptCompiler::CachedData* data); // We may have multiple isolates running concurrently, so the access to // the isolate_status_ needs to be concurrency-safe. static base::LazyMutex isolate_status_lock_; static std::map isolate_status_; static std::map isolate_running_streaming_tasks_; static base::LazyMutex cached_code_mutex_; static std::map> cached_code_map_; static std::atomic unhandled_promise_rejections_; }; class FuzzerMonitor : public i::AllStatic { public: static void SimulateErrors(); private: static void ControlFlowViolation(); static void DCheck(); static void Fatal(); static void ObservableDifference(); static void UndefinedBehavior(); static void UseAfterFree(); static void UseOfUninitializedValue(); }; } // namespace v8 #endif // V8_D8_D8_H_