• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_D8_D8_H_
6 #define V8_D8_D8_H_
7 
8 #include <iterator>
9 #include <map>
10 #include <memory>
11 #include <queue>
12 #include <string>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <vector>
16 
17 #include "include/v8-array-buffer.h"
18 #include "include/v8-isolate.h"
19 #include "include/v8-script.h"
20 #include "src/base/once.h"
21 #include "src/base/platform/time.h"
22 #include "src/base/platform/wrappers.h"
23 #include "src/d8/async-hooks-wrapper.h"
24 #include "src/strings/string-hasher.h"
25 #include "src/utils/allocation.h"
26 #include "src/utils/utils.h"
27 
28 namespace v8 {
29 
30 class BackingStore;
31 class CompiledWasmModule;
32 class D8Console;
33 class Message;
34 class TryCatch;
35 
36 enum class ModuleType { kJavaScript, kJSON, kInvalid };
37 
38 namespace internal {
39 class CancelableTaskManager;
40 }  // namespace internal
41 
42 struct DynamicImportData;
43 
44 // A single counter in a counter collection.
45 class Counter {
46  public:
47   static const int kMaxNameSize = 64;
48   void Bind(const char* name, bool histogram);
49   // TODO(12482): Return pointer to an atomic.
ptr()50   int* ptr() {
51     STATIC_ASSERT(sizeof(int) == sizeof(count_));
52     return reinterpret_cast<int*>(&count_);
53   }
count()54   int count() const { return count_.load(std::memory_order_relaxed); }
sample_total()55   int sample_total() const {
56     return sample_total_.load(std::memory_order_relaxed);
57   }
is_histogram()58   bool is_histogram() const { return is_histogram_; }
59   void AddSample(int32_t sample);
60 
61  private:
62   std::atomic<int> count_;
63   std::atomic<int> sample_total_;
64   bool is_histogram_;
65   char name_[kMaxNameSize];
66 };
67 
68 // A set of counters and associated information.  An instance of this
69 // class is stored directly in the memory-mapped counters file if
70 // the --map-counters options is used
71 class CounterCollection {
72  public:
73   CounterCollection();
74   Counter* GetNextCounter();
75 
76  private:
77   static const unsigned kMaxCounters = 512;
78   uint32_t magic_number_;
79   uint32_t max_counters_;
80   uint32_t max_name_size_;
81   uint32_t counters_in_use_;
82   Counter counters_[kMaxCounters];
83 };
84 
85 using CounterMap = std::unordered_map<std::string, Counter*>;
86 
87 class SourceGroup {
88  public:
SourceGroup()89   SourceGroup()
90       : next_semaphore_(0),
91         done_semaphore_(0),
92         thread_(nullptr),
93         argv_(nullptr),
94         begin_offset_(0),
95         end_offset_(0) {}
96 
97   ~SourceGroup();
98 
Begin(char ** argv,int offset)99   void Begin(char** argv, int offset) {
100     argv_ = const_cast<const char**>(argv);
101     begin_offset_ = offset;
102   }
103 
End(int offset)104   void End(int offset) { end_offset_ = offset; }
105 
106   // Returns true on success, false if an uncaught exception was thrown.
107   bool Execute(Isolate* isolate);
108 
109   void StartExecuteInThread();
110   void WaitForThread();
111   void JoinThread();
112 
113  private:
114   class IsolateThread : public base::Thread {
115    public:
116     explicit IsolateThread(SourceGroup* group);
117 
Run()118     void Run() override { group_->ExecuteInThread(); }
119 
120    private:
121     SourceGroup* group_;
122   };
123 
124   void ExecuteInThread();
125 
126   base::Semaphore next_semaphore_;
127   base::Semaphore done_semaphore_;
128   base::Thread* thread_;
129 
130   void ExitShell(int exit_code);
131 
132   const char** argv_;
133   int begin_offset_;
134   int end_offset_;
135 };
136 
137 class SerializationData {
138  public:
139   SerializationData() = default;
140   SerializationData(const SerializationData&) = delete;
141   SerializationData& operator=(const SerializationData&) = delete;
142 
data()143   uint8_t* data() { return data_.get(); }
size()144   size_t size() { return size_; }
backing_stores()145   const std::vector<std::shared_ptr<v8::BackingStore>>& backing_stores() {
146     return backing_stores_;
147   }
sab_backing_stores()148   const std::vector<std::shared_ptr<v8::BackingStore>>& sab_backing_stores() {
149     return sab_backing_stores_;
150   }
compiled_wasm_modules()151   const std::vector<CompiledWasmModule>& compiled_wasm_modules() {
152     return compiled_wasm_modules_;
153   }
shared_values()154   const std::vector<v8::Global<v8::Value>>& shared_values() {
155     return shared_values_;
156   }
157 
158   void ClearSharedValuesUnderLockIfNeeded();
159 
160  private:
161   struct DataDeleter {
operatorDataDeleter162     void operator()(uint8_t* p) const { base::Free(p); }
163   };
164 
165   std::unique_ptr<uint8_t, DataDeleter> data_;
166   size_t size_ = 0;
167   std::vector<std::shared_ptr<v8::BackingStore>> backing_stores_;
168   std::vector<std::shared_ptr<v8::BackingStore>> sab_backing_stores_;
169   std::vector<CompiledWasmModule> compiled_wasm_modules_;
170   std::vector<v8::Global<v8::Value>> shared_values_;
171 
172  private:
173   friend class Serializer;
174 };
175 
176 class SerializationDataQueue {
177  public:
178   void Enqueue(std::unique_ptr<SerializationData> data);
179   bool Dequeue(std::unique_ptr<SerializationData>* data);
180   bool IsEmpty();
181   void Clear();
182 
183  private:
184   base::Mutex mutex_;
185   std::vector<std::unique_ptr<SerializationData>> data_;
186 };
187 
188 class Worker : public std::enable_shared_from_this<Worker> {
189  public:
190   explicit Worker(const char* script);
191   ~Worker();
192 
193   // Post a message to the worker. The worker will take ownership of the
194   // SerializationData. This function should only be called by the thread that
195   // created the Worker.
196   void PostMessage(std::unique_ptr<SerializationData> data);
197   // Synchronously retrieve messages from the worker's outgoing message queue.
198   // If there is no message in the queue, block until a message is available.
199   // If there are no messages in the queue and the worker is no longer running,
200   // return nullptr.
201   // This function should only be called by the thread that created the Worker.
202   std::unique_ptr<SerializationData> GetMessage();
203   // Terminate the worker's event loop. Messages from the worker that have been
204   // queued can still be read via GetMessage().
205   // This function can be called by any thread.
206   void Terminate();
207   // Terminate and join the thread.
208   // This function can be called by any thread.
209   void TerminateAndWaitForThread();
210 
211   // Start running the given worker in another thread.
212   static bool StartWorkerThread(std::shared_ptr<Worker> worker);
213 
214  private:
215   friend class ProcessMessageTask;
216   friend class TerminateTask;
217 
218   enum class State {
219     kReady,
220     kPrepareRunning,
221     kRunning,
222     kTerminating,
223     kTerminated,
224   };
225   bool is_running() const;
226 
227   void ProcessMessage(std::unique_ptr<SerializationData> data);
228   void ProcessMessages();
229 
230   class WorkerThread : public base::Thread {
231    public:
WorkerThread(std::shared_ptr<Worker> worker)232     explicit WorkerThread(std::shared_ptr<Worker> worker)
233         : base::Thread(base::Thread::Options("WorkerThread")),
234           worker_(std::move(worker)) {}
235 
236     void Run() override;
237 
238    private:
239     std::shared_ptr<Worker> worker_;
240   };
241 
242   void ExecuteInThread();
243   static void PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& args);
244 
245   base::Semaphore out_semaphore_{0};
246   SerializationDataQueue out_queue_;
247   base::Thread* thread_ = nullptr;
248   char* script_;
249   std::atomic<State> state_;
250   bool is_joined_ = false;
251   // For signalling that the worker has started.
252   base::Semaphore started_semaphore_{0};
253 
254   // For posting tasks to the worker
255   std::shared_ptr<TaskRunner> task_runner_;
256   i::CancelableTaskManager* task_manager_;
257 
258   // Protects reading / writing task_runner_. (The TaskRunner itself doesn't
259   // need locking, but accessing the Worker's data member does.)
260   base::Mutex worker_mutex_;
261 
262   // The isolate should only be accessed by the worker itself, or when holding
263   // the worker_mutex_ and after checking the worker state.
264   Isolate* isolate_ = nullptr;
265 
266   // Only accessed by the worker thread.
267   v8::Persistent<v8::Context> context_;
268 };
269 
270 class PerIsolateData {
271  public:
272   explicit PerIsolateData(Isolate* isolate);
273 
274   ~PerIsolateData();
275 
Get(Isolate * isolate)276   inline static PerIsolateData* Get(Isolate* isolate) {
277     return reinterpret_cast<PerIsolateData*>(isolate->GetData(0));
278   }
279 
280   class V8_NODISCARD RealmScope {
281    public:
282     explicit RealmScope(PerIsolateData* data);
283     ~RealmScope();
284 
285    private:
286     PerIsolateData* data_;
287   };
288 
289   // Contrary to RealmScope (which creates a new Realm), ExplicitRealmScope
290   // allows for entering an existing Realm, as specified by its index.
291   class V8_NODISCARD ExplicitRealmScope {
292    public:
293     explicit ExplicitRealmScope(PerIsolateData* data, int index);
294     ~ExplicitRealmScope();
295 
296     Local<Context> context() const;
297 
298    private:
299     PerIsolateData* data_;
300     Local<Context> realm_;
301     int index_;
302     int previous_index_;
303   };
304 
305   inline void SetTimeout(Local<Function> callback, Local<Context> context);
306   inline MaybeLocal<Function> GetTimeoutCallback();
307   inline MaybeLocal<Context> GetTimeoutContext();
308 
GetAsyncHooks()309   AsyncHooks* GetAsyncHooks() { return async_hooks_wrapper_; }
310 
311   void RemoveUnhandledPromise(Local<Promise> promise);
312   void AddUnhandledPromise(Local<Promise> promise, Local<Message> message,
313                            Local<Value> exception);
314   int HandleUnhandledPromiseRejections();
315 
316   // Keep track of DynamicImportData so we can properly free it on shutdown
317   // when LEAK_SANITIZER is active.
318   void AddDynamicImportData(DynamicImportData*);
319   void DeleteDynamicImportData(DynamicImportData*);
320 
321   Local<FunctionTemplate> GetTestApiObjectCtor() const;
322   void SetTestApiObjectCtor(Local<FunctionTemplate> ctor);
323 
324   Local<FunctionTemplate> GetSnapshotObjectCtor() const;
325   void SetSnapshotObjectCtor(Local<FunctionTemplate> ctor);
326 
327  private:
328   friend class Shell;
329   friend class RealmScope;
330   Isolate* isolate_;
331   int realm_count_;
332   int realm_current_;
333   int realm_switch_;
334   Global<Context>* realms_;
335   Global<Value> realm_shared_;
336   std::queue<Global<Function>> set_timeout_callbacks_;
337   std::queue<Global<Context>> set_timeout_contexts_;
338   bool ignore_unhandled_promises_;
339   std::vector<std::tuple<Global<Promise>, Global<Message>, Global<Value>>>
340       unhandled_promises_;
341   AsyncHooks* async_hooks_wrapper_;
342 #if defined(LEAK_SANITIZER)
343   std::unordered_set<DynamicImportData*> import_data_;
344 #endif
345   Global<FunctionTemplate> test_api_object_ctor_;
346   Global<FunctionTemplate> snapshot_object_ctor_;
347 
348   int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
349                         int arg_offset);
350   int RealmFind(Local<Context> context);
351 };
352 
353 extern bool check_d8_flag_contradictions;
354 
355 class ShellOptions {
356  public:
357   enum CodeCacheOptions {
358     kNoProduceCache,
359     kProduceCache,
360     kProduceCacheAfterExecute
361   };
362 
~ShellOptions()363   ~ShellOptions() { delete[] isolate_sources; }
364 
365   // In analogy to Flag::CheckFlagChange() in src/flags/flag.cc, only allow
366   // repeated flags for identical boolean values. We allow exceptions for flags
367   // with enum-like arguments since their conflicts can also be specified
368   // completely.
369   template <class T,
370             bool kAllowIdenticalAssignment = std::is_same<T, bool>::value>
371   class DisallowReassignment {
372    public:
DisallowReassignment(const char * name,T value)373     DisallowReassignment(const char* name, T value)
374         : name_(name), value_(value) {}
375 
T()376     operator T() const { return value_; }
get()377     T get() const { return value_; }
378     DisallowReassignment& operator=(T value) {
379       if (check_d8_flag_contradictions) {
380         if (kAllowIdenticalAssignment) {
381           if (specified_ && value_ != value) {
382             FATAL("Contradictory values for d8 flag --%s", name_);
383           }
384         } else {
385           if (specified_) {
386             FATAL("Repeated specification of d8 flag --%s", name_);
387           }
388         }
389       }
390       value_ = value;
391       specified_ = true;
392       return *this;
393     }
Overwrite(T value)394     void Overwrite(T value) { value_ = value; }
395 
396    private:
397     const char* name_;
398     T value_;
399     bool specified_ = false;
400   };
401 
402   DisallowReassignment<const char*> d8_path = {"d8-path", ""};
403   DisallowReassignment<bool> fuzzilli_coverage_statistics = {
404       "fuzzilli-coverage-statistics", false};
405   DisallowReassignment<bool> fuzzilli_enable_builtins_coverage = {
406       "fuzzilli-enable-builtins-coverage", true};
407   DisallowReassignment<bool> send_idle_notification = {"send-idle-notification",
408                                                        false};
409   DisallowReassignment<bool> invoke_weak_callbacks = {"invoke-weak-callbacks",
410                                                       false};
411   DisallowReassignment<bool> omit_quit = {"omit-quit", false};
412   DisallowReassignment<bool> wait_for_background_tasks = {
413       "wait-for-background-tasks", true};
414   DisallowReassignment<bool> simulate_errors = {"simulate-errors", false};
415   DisallowReassignment<bool> stress_opt = {"stress-opt", false};
416   DisallowReassignment<int> stress_runs = {"stress-runs", 1};
417   DisallowReassignment<bool> interactive_shell = {"shell", false};
418   bool test_shell = false;
419   DisallowReassignment<bool> expected_to_throw = {"throws", false};
420   DisallowReassignment<bool> no_fail = {"no-fail", false};
421   DisallowReassignment<bool> dump_counters = {"dump-counters", false};
422   DisallowReassignment<bool> dump_counters_nvp = {"dump-counters-nvp", false};
423   DisallowReassignment<bool> ignore_unhandled_promises = {
424       "ignore-unhandled-promises", false};
425   DisallowReassignment<bool> mock_arraybuffer_allocator = {
426       "mock-arraybuffer-allocator", false};
427   DisallowReassignment<size_t> mock_arraybuffer_allocator_limit = {
428       "mock-arraybuffer-allocator-limit", 0};
429 #if MULTI_MAPPED_ALLOCATOR_AVAILABLE
430   DisallowReassignment<bool> multi_mapped_mock_allocator = {
431       "multi-mapped-mock-allocator", false};
432 #endif
433   DisallowReassignment<bool> enable_inspector = {"enable-inspector", false};
434   int num_isolates = 1;
435   DisallowReassignment<v8::ScriptCompiler::CompileOptions, true>
436       compile_options = {"cache", v8::ScriptCompiler::kNoCompileOptions};
437   DisallowReassignment<CodeCacheOptions, true> code_cache_options = {
438       "cache", CodeCacheOptions::kNoProduceCache};
439   DisallowReassignment<bool> streaming_compile = {"streaming-compile", false};
440   DisallowReassignment<SourceGroup*> isolate_sources = {"isolate-sources",
441                                                         nullptr};
442   DisallowReassignment<const char*> icu_data_file = {"icu-data-file", nullptr};
443   DisallowReassignment<const char*> icu_locale = {"icu-locale", nullptr};
444   DisallowReassignment<const char*> snapshot_blob = {"snapshot_blob", nullptr};
445   DisallowReassignment<bool> trace_enabled = {"trace-enabled", false};
446   DisallowReassignment<const char*> trace_path = {"trace-path", nullptr};
447   DisallowReassignment<const char*> trace_config = {"trace-config", nullptr};
448   DisallowReassignment<const char*> lcov_file = {"lcov", nullptr};
449   DisallowReassignment<bool> disable_in_process_stack_traces = {
450       "disable-in-process-stack-traces", false};
451   DisallowReassignment<int> read_from_tcp_port = {"read-from-tcp-port", -1};
452   DisallowReassignment<bool> enable_os_system = {"enable-os-system", false};
453   DisallowReassignment<bool> quiet_load = {"quiet-load", false};
454   DisallowReassignment<int> thread_pool_size = {"thread-pool-size", 0};
455   DisallowReassignment<bool> stress_delay_tasks = {"stress-delay-tasks", false};
456   std::vector<const char*> arguments;
457   DisallowReassignment<bool> include_arguments = {"arguments", true};
458   DisallowReassignment<bool> cpu_profiler = {"cpu-profiler", false};
459   DisallowReassignment<bool> cpu_profiler_print = {"cpu-profiler-print", false};
460   DisallowReassignment<bool> fuzzy_module_file_extensions = {
461       "fuzzy-module-file-extensions", true};
462   DisallowReassignment<bool> enable_system_instrumentation = {
463       "enable-system-instrumentation", false};
464   DisallowReassignment<const char*> web_snapshot_config = {
465       "web-snapshot-config", nullptr};
466   DisallowReassignment<const char*> web_snapshot_output = {
467       "web-snapshot-output", nullptr};
468   DisallowReassignment<bool> d8_web_snapshot_api = {
469       "experimental-d8-web-snapshot-api", false};
470   // Applies to web snapshot and JSON deserialization.
471   DisallowReassignment<bool> stress_deserialize = {"stress-deserialize", false};
472   DisallowReassignment<bool> compile_only = {"compile-only", false};
473   DisallowReassignment<int> repeat_compile = {"repeat-compile", 1};
474 #if V8_ENABLE_WEBASSEMBLY
475   DisallowReassignment<bool> wasm_trap_handler = {"wasm-trap-handler", true};
476 #endif  // V8_ENABLE_WEBASSEMBLY
477   DisallowReassignment<bool> expose_fast_api = {"expose-fast-api", false};
478 };
479 
480 class Shell : public i::AllStatic {
481  public:
482   enum PrintResult : bool { kPrintResult = true, kNoPrintResult = false };
483   enum ReportExceptions : bool {
484     kReportExceptions = true,
485     kNoReportExceptions = false
486   };
487   enum ProcessMessageQueue : bool {
488     kProcessMessageQueue = true,
489     kNoProcessMessageQueue = false
490   };
491   enum class CodeType { kFileName, kString, kFunction, kInvalid, kNone };
492 
493   static bool ExecuteString(Isolate* isolate, Local<String> source,
494                             Local<String> name, PrintResult print_result,
495                             ReportExceptions report_exceptions,
496                             ProcessMessageQueue process_message_queue);
497   static bool ExecuteModule(Isolate* isolate, const char* file_name);
498   static bool ExecuteWebSnapshot(Isolate* isolate, const char* file_name);
499   static bool LoadJSON(Isolate* isolate, const char* file_name);
500   static void ReportException(Isolate* isolate, Local<Message> message,
501                               Local<Value> exception);
502   static void ReportException(Isolate* isolate, TryCatch* try_catch);
503   static MaybeLocal<String> ReadFile(Isolate* isolate, const char* name,
504                                      bool should_throw = true);
505   static Local<String> WasmLoadSourceMapCallback(Isolate* isolate,
506                                                  const char* name);
507   static Local<Context> CreateEvaluationContext(Isolate* isolate);
508   static int RunMain(Isolate* isolate, bool last_run);
509   static int Main(int argc, char* argv[]);
510   static void Exit(int exit_code);
511   static void OnExit(Isolate* isolate, bool dispose);
512   static void CollectGarbage(Isolate* isolate);
513   static bool EmptyMessageQueues(Isolate* isolate);
514   static bool CompleteMessageLoop(Isolate* isolate);
515 
516   static bool HandleUnhandledPromiseRejections(Isolate* isolate);
517 
518   static void PostForegroundTask(Isolate* isolate, std::unique_ptr<Task> task);
519   static void PostBlockingBackgroundTask(std::unique_ptr<Task> task);
520 
521   static std::unique_ptr<SerializationData> SerializeValue(
522       Isolate* isolate, Local<Value> value, Local<Value> transfer);
523   static MaybeLocal<Value> DeserializeValue(
524       Isolate* isolate, std::unique_ptr<SerializationData> data);
525   static int* LookupCounter(const char* name);
526   static void* CreateHistogram(const char* name, int min, int max,
527                                size_t buckets);
528   static void AddHistogramSample(void* histogram, int sample);
529   static void MapCounters(v8::Isolate* isolate, const char* name);
530 
531   static void PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args);
532   static void PerformanceMeasureMemory(
533       const v8::FunctionCallbackInfo<v8::Value>& args);
534 
535   static void RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& args);
536   static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
537   static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
538   static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
539   static void RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args);
540   static void RealmCreateAllowCrossRealmAccess(
541       const v8::FunctionCallbackInfo<v8::Value>& args);
542   static void RealmDetachGlobal(
543       const v8::FunctionCallbackInfo<v8::Value>& args);
544   static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
545   static void RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args);
546   static void RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args);
547   static void RealmSharedGet(Local<String> property,
548                              const PropertyCallbackInfo<Value>& info);
549   static void RealmSharedSet(Local<String> property, Local<Value> value,
550                              const PropertyCallbackInfo<void>& info);
551   static void RealmTakeWebSnapshot(
552       const v8::FunctionCallbackInfo<v8::Value>& args);
553   static void RealmUseWebSnapshot(
554       const v8::FunctionCallbackInfo<v8::Value>& args);
555 
556   static void LogGetAndStop(const v8::FunctionCallbackInfo<v8::Value>& args);
557   static void TestVerifySourcePositions(
558       const v8::FunctionCallbackInfo<v8::Value>& args);
559 
560   static void InstallConditionalFeatures(
561       const v8::FunctionCallbackInfo<v8::Value>& args);
562 
563   static void AsyncHooksCreateHook(
564       const v8::FunctionCallbackInfo<v8::Value>& args);
565   static void AsyncHooksExecutionAsyncId(
566       const v8::FunctionCallbackInfo<v8::Value>& args);
567   static void AsyncHooksTriggerAsyncId(
568       const v8::FunctionCallbackInfo<v8::Value>& args);
569 
570   static void SetPromiseHooks(const v8::FunctionCallbackInfo<v8::Value>& args);
571 
572   static void EnableDebugger(const v8::FunctionCallbackInfo<v8::Value>& args);
573   static void DisableDebugger(const v8::FunctionCallbackInfo<v8::Value>& args);
574 
575   static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
576   static void PrintErr(const v8::FunctionCallbackInfo<v8::Value>& args);
577   static void WriteStdout(const v8::FunctionCallbackInfo<v8::Value>& args);
578   static void WaitUntilDone(const v8::FunctionCallbackInfo<v8::Value>& args);
579   static void NotifyDone(const v8::FunctionCallbackInfo<v8::Value>& args);
580   static void QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args);
581   static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args);
582   static void Version(const v8::FunctionCallbackInfo<v8::Value>& args);
583   static void ReadFile(const v8::FunctionCallbackInfo<v8::Value>& args);
584   static char* ReadChars(const char* name, int* size_out);
585   static MaybeLocal<PrimitiveArray> ReadLines(Isolate* isolate,
586                                               const char* name);
587   static void ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
588   static Local<String> ReadFromStdin(Isolate* isolate);
ReadLine(const v8::FunctionCallbackInfo<v8::Value> & args)589   static void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
590     args.GetReturnValue().Set(ReadFromStdin(args.GetIsolate()));
591   }
592   static void WriteChars(const char* name, uint8_t* buffer, size_t buffer_size);
593   static void ExecuteFile(const v8::FunctionCallbackInfo<v8::Value>& args);
594   static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args);
595   static void ReadCodeTypeAndArguments(
596       const v8::FunctionCallbackInfo<v8::Value>& args, int index,
597       CodeType* code_type, Local<Value>* arguments = nullptr);
598   static bool FunctionAndArgumentsToString(Local<Function> function,
599                                            Local<Value> arguments,
600                                            Local<String>* source,
601                                            Isolate* isolate);
602   static MaybeLocal<String> ReadSource(
603       const v8::FunctionCallbackInfo<v8::Value>& args, int index,
604       CodeType default_type);
605   static void WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args);
606   static void WorkerPostMessage(
607       const v8::FunctionCallbackInfo<v8::Value>& args);
608   static void WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args);
609   static void WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args);
610   static void WorkerTerminateAndWait(
611       const v8::FunctionCallbackInfo<v8::Value>& args);
612   // The OS object on the global object contains methods for performing
613   // operating system calls:
614   //
615   // os.system("program_name", ["arg1", "arg2", ...], timeout1, timeout2) will
616   // run the command, passing the arguments to the program.  The standard output
617   // of the program will be picked up and returned as a multiline string.  If
618   // timeout1 is present then it should be a number.  -1 indicates no timeout
619   // and a positive number is used as a timeout in milliseconds that limits the
620   // time spent waiting between receiving output characters from the program.
621   // timeout2, if present, should be a number indicating the limit in
622   // milliseconds on the total running time of the program.  Exceptions are
623   // thrown on timeouts or other errors or if the exit status of the program
624   // indicates an error.
625   static void System(const v8::FunctionCallbackInfo<v8::Value>& args);
626 
627   // os.chdir(dir) changes directory to the given directory.  Throws an
628   // exception/ on error.
629   static void ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
630 
631   // os.setenv(variable, value) sets an environment variable.  Repeated calls to
632   // this method leak memory due to the API of setenv in the standard C library.
633   static void SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
634   static void UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args);
635 
636   // os.umask(alue) calls the umask system call and returns the old umask.
637   static void SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args);
638 
639   // os.mkdirp(name, mask) creates a directory.  The mask (if present) is anded
640   // with the current umask.  Intermediate directories are created if necessary.
641   // An exception is not thrown if the directory already exists.  Analogous to
642   // the "mkdir -p" command.
643   static void MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
644   static void RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args);
645   static MaybeLocal<Promise> HostImportModuleDynamically(
646       Local<Context> context, Local<Data> host_defined_options,
647       Local<Value> resource_name, Local<String> specifier,
648       Local<FixedArray> import_assertions);
649 
650   static void ModuleResolutionSuccessCallback(
651       const v8::FunctionCallbackInfo<v8::Value>& info);
652   static void ModuleResolutionFailureCallback(
653       const v8::FunctionCallbackInfo<v8::Value>& info);
654   static void HostInitializeImportMetaObject(Local<Context> context,
655                                              Local<Module> module,
656                                              Local<Object> meta);
657   static MaybeLocal<Context> HostCreateShadowRealmContext(
658       Local<Context> initiator_context);
659 
660 #ifdef V8_FUZZILLI
661   static void Fuzzilli(const v8::FunctionCallbackInfo<v8::Value>& args);
662 #endif  // V8_FUZZILLI
663 
664   // Data is of type DynamicImportData*. We use void* here to be able
665   // to conform with MicrotaskCallback interface and enqueue this
666   // function in the microtask queue.
667   static void DoHostImportModuleDynamically(void* data);
668   static void AddOSMethods(v8::Isolate* isolate,
669                            Local<ObjectTemplate> os_template);
670 
671   static const char* kPrompt;
672   static ShellOptions options;
673   static ArrayBuffer::Allocator* array_buffer_allocator;
674   static Isolate* shared_isolate;
675 
676   static void SetWaitUntilDone(Isolate* isolate, bool value);
677   static void NotifyStartStreamingTask(Isolate* isolate);
678   static void NotifyFinishStreamingTask(Isolate* isolate);
679 
680   static char* ReadCharsFromTcpPort(const char* name, int* size_out);
681 
set_script_executed()682   static void set_script_executed() { script_executed_.store(true); }
use_interactive_shell()683   static bool use_interactive_shell() {
684     return (options.interactive_shell || !script_executed_.load()) &&
685            !options.test_shell;
686   }
687 
update_script_size(int size)688   static void update_script_size(int size) {
689     if (size > 0) valid_fuzz_script_.store(true);
690   }
is_valid_fuzz_script()691   static bool is_valid_fuzz_script() { return valid_fuzz_script_.load(); }
692 
693   static void WaitForRunningWorkers();
694   static void AddRunningWorker(std::shared_ptr<Worker> worker);
695   static void RemoveRunningWorker(const std::shared_ptr<Worker>& worker);
696 
697   static void Initialize(Isolate* isolate, D8Console* console,
698                          bool isOnMainThread = true);
699 
700   static void PromiseRejectCallback(v8::PromiseRejectMessage reject_message);
701 
702   static Local<FunctionTemplate> CreateSnapshotTemplate(Isolate* isolate);
703 
704  private:
DeserializationRunCount()705   static inline int DeserializationRunCount() {
706     return options.stress_deserialize ? 1000 : 1;
707   }
708 
709   static Global<Context> evaluation_context_;
710   static base::OnceType quit_once_;
711   static Global<Function> stringify_function_;
712   static const char* stringify_source_;
713   static CounterMap* counter_map_;
714   static base::SharedMutex counter_mutex_;
715   // We statically allocate a set of local counters to be used if we
716   // don't want to store the stats in a memory-mapped file
717   static CounterCollection local_counters_;
718   static CounterCollection* counters_;
719   static base::OS::MemoryMappedFile* counters_file_;
720   static base::LazyMutex context_mutex_;
721   static const base::TimeTicks kInitialTicks;
722 
723   static base::LazyMutex workers_mutex_;  // Guards the following members.
724   static bool allow_new_workers_;
725   static std::unordered_set<std::shared_ptr<Worker>> running_workers_;
726 
727   // Multiple isolates may update these flags concurrently.
728   static std::atomic<bool> script_executed_;
729   static std::atomic<bool> valid_fuzz_script_;
730 
731   static void WriteIgnitionDispatchCountersFile(v8::Isolate* isolate);
732   // Append LCOV coverage data to file.
733   static void WriteLcovData(v8::Isolate* isolate, const char* file);
734   static Counter* GetCounter(const char* name, bool is_histogram);
735   static Local<String> Stringify(Isolate* isolate, Local<Value> value);
736   static void RunShell(Isolate* isolate);
737   static bool SetOptions(int argc, char* argv[]);
738 
739   static void NodeTypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
740 
741   static Local<FunctionTemplate> CreateNodeTemplates(Isolate* isolate);
742   static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
743   static Local<ObjectTemplate> CreateOSTemplate(Isolate* isolate);
744   static Local<FunctionTemplate> CreateWorkerTemplate(Isolate* isolate);
745   static Local<ObjectTemplate> CreateAsyncHookTemplate(Isolate* isolate);
746   static Local<ObjectTemplate> CreateTestRunnerTemplate(Isolate* isolate);
747   static Local<ObjectTemplate> CreatePerformanceTemplate(Isolate* isolate);
748   static Local<ObjectTemplate> CreateRealmTemplate(Isolate* isolate);
749   static Local<ObjectTemplate> CreateD8Template(Isolate* isolate);
750   static Local<FunctionTemplate> CreateTestFastCApiTemplate(Isolate* isolate);
751   static Local<FunctionTemplate> CreateLeafInterfaceTypeTemplate(
752       Isolate* isolate);
753 
754   static MaybeLocal<Context> CreateRealm(
755       const v8::FunctionCallbackInfo<v8::Value>& args, int index,
756       v8::MaybeLocal<Value> global_object);
757   static void DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
758                            int index);
759   static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Module> origin_module,
760                                             v8::Local<v8::Context> context,
761                                             const std::string& file_name,
762                                             ModuleType module_type);
763 
764   static MaybeLocal<Value> JSONModuleEvaluationSteps(Local<Context> context,
765                                                      Local<Module> module);
766 
767   template <class T>
768   static MaybeLocal<T> CompileString(Isolate* isolate, Local<Context> context,
769                                      Local<String> source,
770                                      const ScriptOrigin& origin);
771 
772   static ScriptCompiler::CachedData* LookupCodeCache(Isolate* isolate,
773                                                      Local<Value> name);
774   static void StoreInCodeCache(Isolate* isolate, Local<Value> name,
775                                const ScriptCompiler::CachedData* data);
776   // We may have multiple isolates running concurrently, so the access to
777   // the isolate_status_ needs to be concurrency-safe.
778   static base::LazyMutex isolate_status_lock_;
779   static std::map<Isolate*, bool> isolate_status_;
780   static std::map<Isolate*, int> isolate_running_streaming_tasks_;
781 
782   static base::LazyMutex cached_code_mutex_;
783   static std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
784       cached_code_map_;
785   static std::atomic<int> unhandled_promise_rejections_;
786 };
787 
788 class FuzzerMonitor : public i::AllStatic {
789  public:
790   static void SimulateErrors();
791 
792  private:
793   static void ControlFlowViolation();
794   static void DCheck();
795   static void Fatal();
796   static void ObservableDifference();
797   static void UndefinedBehavior();
798   static void UseAfterFree();
799   static void UseOfUninitializedValue();
800 };
801 
802 }  // namespace v8
803 
804 #endif  // V8_D8_D8_H_
805