chromium/v8/src/d8/d8.cc

// 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.

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iterator>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>

#ifdef ENABLE_VTUNE_JIT_INTERFACE
#include "src/third_party/vtune/v8-vtune.h"
#endif

#include "include/libplatform/libplatform.h"
#include "include/libplatform/v8-tracing.h"
#include "include/v8-function.h"
#include "include/v8-initialization.h"
#include "include/v8-inspector.h"
#include "include/v8-isolate.h"
#include "include/v8-json.h"
#include "include/v8-locker.h"
#include "include/v8-profiler.h"
#include "include/v8-wasm.h"
#include "src/api/api-inl.h"
#include "src/base/cpu.h"
#include "src/base/logging.h"
#include "src/base/platform/memory.h"
#include "src/base/platform/platform.h"
#include "src/base/platform/time.h"
#include "src/base/platform/wrappers.h"
#include "src/base/sanitizer/msan.h"
#include "src/base/sys-info.h"
#include "src/base/utils/random-number-generator.h"
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
#include "src/d8/d8-console.h"
#include "src/d8/d8-platforms.h"
#include "src/d8/d8.h"
#include "src/debug/debug-interface.h"
#include "src/deoptimizer/deoptimizer.h"
#include "src/diagnostics/basic-block-profiler.h"
#include "src/execution/microtask-queue.h"
#include "src/execution/v8threads.h"
#include "src/execution/vm-state-inl.h"
#include "src/flags/flags.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/parked-scope-inl.h"
#include "src/init/v8.h"
#include "src/interpreter/interpreter.h"
#include "src/logging/counters.h"
#include "src/logging/log-file.h"
#include "src/objects/managed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parsing.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/profiler/profile-generator.h"
#include "src/snapshot/snapshot.h"
#include "src/tasks/cancelable-task.h"
#include "src/utils/ostreams.h"
#include "src/utils/utils.h"

#ifdef V8_OS_DARWIN
#include <mach/mach.h>
#include <mach/task_policy.h>
#endif

#ifdef V8_ENABLE_MAGLEV
#include "src/maglev/maglev-concurrent-dispatcher.h"
#endif  // V8_ENABLE_MAGLEV

#if V8_OS_POSIX
#include <signal.h>
#endif  // V8_OS_POSIX

#ifdef V8_FUZZILLI
#include "src/fuzzilli/cov.h"
#include "src/fuzzilli/fuzzilli.h"
#endif  // V8_FUZZILLI

#ifdef V8_USE_PERFETTO
#include "perfetto/tracing/track_event.h"
#include "perfetto/tracing/track_event_legacy.h"
#endif  // V8_USE_PERFETTO

#ifdef V8_INTL_SUPPORT
#include "unicode/locid.h"
#endif  // V8_INTL_SUPPORT

#ifdef V8_OS_LINUX
#include <sys/mman.h>  // For MultiMappedAllocator.
#endif

#if defined(V8_OS_WIN)
#include <windows.h>
#else
#include <unistd.h>
#endif  // defined(V8_OS_WIN)

#if V8_ENABLE_WEBASSEMBLY
#include "src/trap-handler/trap-handler.h"
#endif  // V8_ENABLE_WEBASSEMBLY

#ifndef DCHECK
#define DCHECK
#endif

#ifndef CHECK
#define CHECK
#endif

namespace v8 {

namespace {

// Set on worker threads to the current Worker instance.
thread_local Worker* current_worker_ =;

#ifdef V8_FUZZILLI
bool fuzzilli_reprl = true;
#else
bool fuzzilli_reprl =;
#endif  // V8_FUZZILLI

// Base class for shell ArrayBuffer allocators. It forwards all operations to
// the default v8 allocator.
class ArrayBufferAllocatorBase : public v8::ArrayBuffer::Allocator {};

// ArrayBuffer allocator that can use virtual memory to improve performance.
class ShellArrayBufferAllocator : public ArrayBufferAllocatorBase {};

// ArrayBuffer allocator that never allocates over 10MB.
class MockArrayBufferAllocator : public ArrayBufferAllocatorBase {};

// ArrayBuffer allocator that can be equipped with a limit to simulate system
// OOM.
class MockArrayBufferAllocatiorWithLimit : public MockArrayBufferAllocator {};

#ifdef V8_OS_LINUX

// This is a mock allocator variant that provides a huge virtual allocation
// backed by a small real allocation that is repeatedly mapped. If you create an
// array on memory allocated by this allocator, you will observe that elements
// will alias each other as if their indices were modulo-divided by the real
// allocation length.
// The purpose is to allow stability-testing of huge (typed) arrays without
// actually consuming huge amounts of physical memory.
// This is currently only available on Linux because it relies on {mremap}.
class MultiMappedAllocator : public ArrayBufferAllocatorBase {};

#endif  // V8_OS_LINUX

v8::Platform* g_default_platform;
std::unique_ptr<v8::Platform> g_platform;

template <int N>
bool ThrowError(Isolate* isolate, const char (&message)[N]) {}

bool ThrowError(Isolate* isolate, Local<String> message) {}

static MaybeLocal<Value> TryGetValue(v8::Isolate* isolate,
                                     Local<Context> context,
                                     Local<v8::Object> object,
                                     const char* property) {}

static Local<Value> GetValue(v8::Isolate* isolate, Local<Context> context,
                             Local<v8::Object> object, const char* property) {}

std::shared_ptr<Worker> GetWorkerFromInternalField(Isolate* isolate,
                                                   Local<Object> object) {}

base::Thread::Options GetThreadOptions(const char* name) {}

}  // namespace

namespace tracing {

namespace {

static constexpr char kIncludedCategoriesParam[] =;
static constexpr char kTraceConfigParam[] =;

class TraceConfigParser {};

}  // namespace

static platform::tracing::TraceConfig* CreateTraceConfigFromJSON(
    v8::Isolate* isolate, const char* json_str) {}

}  // namespace tracing

class ExternalOwningOneByteStringResource
    : public String::ExternalOneByteStringResource {};

// static variables:
CounterMap* Shell::counter_map_;
base::SharedMutex Shell::counter_mutex_;
base::OS::MemoryMappedFile* Shell::counters_file_ =;
CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ =;
base::LazyMutex Shell::context_mutex_;
const base::TimeTicks Shell::kInitialTicks =;
Global<Function> Shell::stringify_function_;
base::Mutex Shell::profiler_end_callback_lock_;
std::map<Isolate*, std::pair<Global<Function>, Global<Context>>>
    Shell::profiler_end_callback_;
base::LazyMutex Shell::workers_mutex_;
bool Shell::allow_new_workers_ =;

std::unordered_set<std::shared_ptr<Worker>> Shell::running_workers_;
std::atomic<bool> Shell::script_executed_{};
std::atomic<bool> Shell::valid_fuzz_script_{};
base::LazyMutex Shell::cached_code_mutex_;
std::map<std::string, std::unique_ptr<ScriptCompiler::CachedData>>
    Shell::cached_code_map_;
std::atomic<int> Shell::unhandled_promise_rejections_{};

Global<Context> Shell::evaluation_context_;
ArrayBuffer::Allocator* Shell::array_buffer_allocator;
bool check_d8_flag_contradictions =;
ShellOptions Shell::options;
base::OnceType Shell::quit_once_ =;

ScriptCompiler::CachedData* Shell::LookupCodeCache(Isolate* isolate,
                                                   Local<Value> source) {}

void Shell::StoreInCodeCache(Isolate* isolate, Local<Value> source,
                             const ScriptCompiler::CachedData* cache_data) {}

// Dummy external source stream which returns the whole source in one go.
// TODO(leszeks): Also test chunking the data.
class DummySourceStream : public v8::ScriptCompiler::ExternalSourceStream {};

// Run a ScriptStreamingTask in a separate thread.
class StreamerThread : public v8::base::Thread {};

namespace {
template <class T>
MaybeLocal<T> CompileStreamed(Local<Context> context,
                              ScriptCompiler::StreamedSource* v8_source,
                              Local<String> full_source_string,
                              const ScriptOrigin& origin) {}

template <>
MaybeLocal<Script> CompileStreamed(Local<Context> context,
                                   ScriptCompiler::StreamedSource* v8_source,
                                   Local<String> full_source_string,
                                   const ScriptOrigin& origin) {}

template <>
MaybeLocal<Module> CompileStreamed(Local<Context> context,
                                   ScriptCompiler::StreamedSource* v8_source,
                                   Local<String> full_source_string,
                                   const ScriptOrigin& origin) {}

template <class T>
MaybeLocal<T> Compile(Local<Context> context, ScriptCompiler::Source* source,
                      ScriptCompiler::CompileOptions options) {}
template <>
MaybeLocal<Script> Compile(Local<Context> context,
                           ScriptCompiler::Source* source,
                           ScriptCompiler::CompileOptions options) {}

template <>
MaybeLocal<Module> Compile(Local<Context> context,
                           ScriptCompiler::Source* source,
                           ScriptCompiler::CompileOptions options) {}

}  // namespace

template <class T>
MaybeLocal<T> Shell::CompileString(Isolate* isolate, Local<Context> context,
                                   Local<String> source,
                                   const ScriptOrigin& origin) {}

namespace {
// For testing.
const int kHostDefinedOptionsLength =;
const uint32_t kHostDefinedOptionsMagicConstant =;

const char kDataURLPrefix[] =;

std::string ToSTLString(Isolate* isolate, Local<String> v8_str) {}

// Per-context Module data, allowing sharing of module maps
// across top-level module loads.
class ModuleEmbedderData {};

enum {};

std::shared_ptr<ModuleEmbedderData> InitializeModuleEmbedderData(
    Local<Context> context) {}

std::shared_ptr<ModuleEmbedderData> GetModuleDataFromContext(
    Local<Context> context) {}

ScriptOrigin CreateScriptOrigin(Isolate* isolate, Local<String> resource_name,
                                v8::ScriptType type) {}

bool IsValidHostDefinedOptions(Local<Context> context, Local<Data> options,
                               Local<Value> resource_name) {}

class D8WasmAsyncResolvePromiseTask : public v8::Task {};

void D8WasmAsyncResolvePromiseCallback(
    v8::Isolate* isolate, v8::Local<v8::Context> context,
    v8::Local<v8::Promise::Resolver> resolver, v8::Local<v8::Value> result,
    WasmAsyncSuccess success) {}

}  // namespace

// Executes a string within the current v8 context.
bool Shell::ExecuteString(Isolate* isolate, Local<String> source,
                          Local<String> name,
                          ReportExceptions report_exceptions,
                          Global<Value>* out_result) {}

namespace {

bool IsAbsolutePath(const std::string& path) {}

std::string GetWorkingDirectory() {}

// Returns the directory part of path, without the trailing '/'.
std::string DirName(const std::string& path) {}

// Resolves path to an absolute path if necessary, and does some
// normalization (eliding references to the current directory
// and replacing backslashes with slashes).
std::string NormalizePath(const std::string& path,
                          const std::string& dir_name) {}

// Resolves specifier to an absolute path if necessary, and does some
// normalization (eliding references to the current directory
// and replacing backslashes with slashes).
//
// If specifier is a data url, returns it unchanged.
std::string NormalizeModuleSpecifier(const std::string& specifier,
                                     const std::string& dir_name) {}

MaybeLocal<Module> ResolveModuleCallback(Local<Context> context,
                                         Local<String> specifier,
                                         Local<FixedArray> import_attributes,
                                         Local<Module> referrer) {}

}  // anonymous namespace

// file_name must be either an absolute path to the filesystem or a data URL.
MaybeLocal<Module> Shell::FetchModuleTree(Local<Module> referrer,
                                          Local<Context> context,
                                          const std::string& module_specifier,
                                          ModuleType module_type) {}

MaybeLocal<Value> Shell::JSONModuleEvaluationSteps(Local<Context> context,
                                                   Local<Module> module) {}

struct DynamicImportData {};

namespace {

enum ModuleResolutionDataIndex : uint32_t {};

}  // namespace

void Shell::ModuleResolutionSuccessCallback(
    const FunctionCallbackInfo<Value>& info) {}

void Shell::ModuleResolutionFailureCallback(
    const FunctionCallbackInfo<Value>& info) {}

MaybeLocal<Promise> Shell::HostImportModuleDynamically(
    Local<Context> context, Local<Data> host_defined_options,
    Local<Value> resource_name, Local<String> specifier,
    Local<FixedArray> import_attributes) {}

void Shell::HostInitializeImportMetaObject(Local<Context> context,
                                           Local<Module> module,
                                           Local<Object> meta) {}

MaybeLocal<Context> Shell::HostCreateShadowRealmContext(
    Local<Context> initiator_context) {}

void Shell::DoHostImportModuleDynamically(void* import_data) {}

bool Shell::ExecuteModule(Isolate* isolate, const char* file_name) {}

// Treat every line as a JSON value and parse it.
bool Shell::LoadJSON(Isolate* isolate, const char* file_name) {}

PerIsolateData::PerIsolateData(Isolate* isolate)
    :{}

PerIsolateData::~PerIsolateData() {}

void PerIsolateData::RemoveUnhandledPromise(Local<Promise> promise) {}

void PerIsolateData::AddUnhandledPromise(Local<Promise> promise,
                                         Local<Message> message,
                                         Local<Value> exception) {}

int PerIsolateData::HandleUnhandledPromiseRejections() {}

void PerIsolateData::AddDynamicImportData(DynamicImportData* data) {}
void PerIsolateData::DeleteDynamicImportData(DynamicImportData* data) {}

Local<FunctionTemplate> PerIsolateData::GetTestApiObjectCtor() const {}

void PerIsolateData::SetTestApiObjectCtor(Local<FunctionTemplate> ctor) {}

Local<FunctionTemplate> PerIsolateData::GetDomNodeCtor() const {}

void PerIsolateData::SetDomNodeCtor(Local<FunctionTemplate> ctor) {}

bool PerIsolateData::HasRunningSubscribedWorkers() {}

void PerIsolateData::RegisterWorker(std::shared_ptr<Worker> worker) {}

void PerIsolateData::SubscribeWorkerOnMessage(
    const std::shared_ptr<Worker>& worker, Local<Context> context,
    Local<Function> callback) {}

std::pair<Local<Context>, Local<Function>> PerIsolateData::GetWorkerOnMessage(
    const std::shared_ptr<Worker>& worker) const {}

void PerIsolateData::UnregisterWorker(const std::shared_ptr<Worker>& worker) {}

PerIsolateData::RealmScope::RealmScope(Isolate* isolate,
                                       const Global<Context>& context)
    :{}

PerIsolateData::RealmScope::~RealmScope() {}

PerIsolateData::ExplicitRealmScope::ExplicitRealmScope(PerIsolateData* data,
                                                       int index)
    :{}

PerIsolateData::ExplicitRealmScope::~ExplicitRealmScope() {}

Local<Context> PerIsolateData::ExplicitRealmScope::context() const {}

int PerIsolateData::RealmFind(Local<Context> context) {}

int PerIsolateData::RealmIndexOrThrow(
    const v8::FunctionCallbackInfo<v8::Value>& info, int arg_offset) {}

// GetTimestamp() returns a time stamp as double, measured in milliseconds.
// When v8_flags.verify_predictable mode is enabled it returns result of
// v8::Platform::MonotonicallyIncreasingTime().
double Shell::GetTimestamp() {}
uint64_t Shell::GetTracingTimestampFromPerformanceTimestamp(
    double performance_timestamp) {}

#ifdef V8_OS_LINUX
void SendPerfControlCommand(const char* command) {}
#endif

// performance.now() returns GetTimestamp().
void Shell::PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// performance.mark() records and returns a PerformanceEntry with the current
// timestamp.
void Shell::PerformanceMark(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// performance.measure() records and returns a PerformanceEntry with a duration
// since a given mark, or since zero.
void Shell::PerformanceMeasure(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

// performance.measureMemory() implements JavaScript Memory API proposal.
// See https://github.com/ulan/javascript-agent-memory/blob/master/explainer.md.
void Shell::PerformanceMeasureMemory(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.current() returns the index of the currently active realm.
void Shell::RealmCurrent(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.owner(o) returns the index of the realm that created o.
void Shell::RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.global(i) returns the global object of realm i.
// (Note that properties of global objects cannot be read/written cross-realm.)
void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& info) {}

MaybeLocal<Context> Shell::CreateRealm(
    const v8::FunctionCallbackInfo<v8::Value>& info, int index,
    v8::MaybeLocal<Value> global_object) {}

void Shell::DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& info,
                         int index) {}

// Realm.create() creates a new realm with a distinct security token
// and returns its index.
void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.createAllowCrossRealmAccess() creates a new realm with the same
// security token as the current realm.
void Shell::RealmCreateAllowCrossRealmAccess(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.navigate(i) creates a new realm with a distinct security token
// in place of realm i.
void Shell::RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.detachGlobal(i) detaches the global objects of realm i from realm i.
void Shell::RealmDetachGlobal(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.dispose(i) disposes the reference to the realm i.
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.switch(i) switches to the realm i for consecutive interactive inputs.
void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.eval(i, s) evaluates s in realm i and returns the result.
void Shell::RealmEval(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Realm.shared is an accessor for a single shared value across realms.
void Shell::RealmSharedGet(Local<Name> property,
                           const PropertyCallbackInfo<Value>& info) {}

void Shell::RealmSharedSet(Local<Name> property, Local<Value> value,
                           const PropertyCallbackInfo<void>& info) {}

void Shell::LogGetAndStop(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::TestVerifySourcePositions(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::InstallConditionalFeatures(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::EnableJSPI(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// async_hooks.createHook() registers functions to be called for different
// lifetime events of each async operation.
void Shell::AsyncHooksCreateHook(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

// async_hooks.executionAsyncId() returns the asyncId of the current execution
// context.
void Shell::AsyncHooksExecutionAsyncId(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::AsyncHooksTriggerAsyncId(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

static v8::debug::DebugDelegate dummy_delegate;

void Shell::EnableDebugger(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::DisableDebugger(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::SetPromiseHooks(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::SerializerSerialize(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::SerializerDeserialize(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::ProfilerSetOnProfileEndListener(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

bool Shell::HasOnProfileEndListener(Isolate* isolate) {}

void Shell::ResetOnProfileEndListener(Isolate* isolate) {}

void Shell::ProfilerTriggerSample(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::TriggerOnProfileEndListener(Isolate* isolate, std::string profile) {}

void WriteToFile(FILE* file, const v8::FunctionCallbackInfo<v8::Value>& info,
                 int first_arg_index = 0) {}

void WriteAndFlush(FILE* file,
                   const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::Print(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::PrintErr(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::WriteStdout(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// There are two overloads of writeFile().
//
// The first parameter is always the filename.
//
// If there are exactly 2 arguments, and the second argument is an ArrayBuffer
// or an ArrayBufferView, write the binary contents into the file.
//
// Otherwise, convert arguments to UTF-8 strings, and write them to the file,
// separated by space.
void Shell::WriteFile(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::ReadFile(const v8::FunctionCallbackInfo<v8::Value>& info) {}

Local<String> Shell::ReadFromStdin(Isolate* isolate) {}

void Shell::ExecuteFile(const v8::FunctionCallbackInfo<v8::Value>& info) {}

class SetTimeoutTask : public v8::Task {};

void Shell::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& info) {}

#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
void Shell::GetContinuationPreservedEmbedderData(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}
#endif  // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA

void Shell::GetExtrasBindingObject(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::ReadCodeTypeAndArguments(
    const v8::FunctionCallbackInfo<v8::Value>& info, int index,
    CodeType* code_type, Local<Value>* arguments) {}

bool Shell::FunctionAndArgumentsToString(Local<Function> function,
                                         Local<Value> arguments,
                                         Local<String>* source,
                                         Isolate* isolate) {}

// ReadSource() supports reading source code through `info[index]` as specified
// by the `default_type` or an optional options bag provided in `info[index+1]`
// (e.g. `options={type: 'code_type', arguments:[...]}`).
MaybeLocal<String> Shell::ReadSource(
    const v8::FunctionCallbackInfo<v8::Value>& info, int index,
    CodeType default_type) {}

void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Task processing one onmessage event received from a Worker.
class OnMessageFromWorkerTask : public v8::Task {};

// Check, on the main thread, whether a worker has any enqueued any message
// events. Workers post this task when posting a message, instead of posting
// OnMessageFromWorkerTask directly, to avoid races between message posting
// and onmessage subscription.
class CheckMessageFromWorkerTask : public v8::Task {};

// Unregister the given isolate from message events from the given worker.
// This must be done before the isolate or worker are destroyed, so that the
// global handles for context and callback are cleaned up correctly -- thus the
// event loop blocks until all workers are unregistered.
class CleanUpWorkerTask : public v8::Task {};

void Shell::WorkerOnMessageGetter(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::WorkerOnMessageSetter(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::WorkerTerminateAndWait(
    const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* info) {}

void Shell::Terminate(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::Quit(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::Version(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::ReportException(Isolate* isolate, Local<v8::Message> message,
                            Local<v8::Value> exception_obj) {}

void Shell::ReportException(v8::Isolate* isolate,
                            const v8::TryCatch& try_catch) {}

void Counter::Bind(const char* name, bool is_histogram) {}

void Counter::AddSample(int sample) {}

CounterCollection::CounterCollection() {}

Counter* CounterCollection::GetNextCounter() {}

void Shell::MapCounters(v8::Isolate* isolate, const char* name) {}

Counter* Shell::GetCounter(const char* name, bool is_histogram) {}

int* Shell::LookupCounter(const char* name) {}

void* Shell::CreateHistogram(const char* name, int min, int max,
                             size_t buckets) {}

void Shell::AddHistogramSample(void* histogram, int sample) {}

// Turn a value into a human-readable string.
Local<String> Shell::Stringify(Isolate* isolate, Local<Value> value) {}

void Shell::NodeTypeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {}

enum class JSApiInstanceType : uint16_t {};

Local<FunctionTemplate> NewDOMFunctionTemplate(
    Isolate* isolate, JSApiInstanceType instance_type) {}

Local<FunctionTemplate> Shell::CreateEventTargetTemplate(Isolate* isolate) {}

Local<FunctionTemplate> Shell::CreateNodeTemplates(
    Isolate* isolate, Local<FunctionTemplate> event_target) {}

Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {}

Local<ObjectTemplate> Shell::CreateOSTemplate(Isolate* isolate) {}

Local<FunctionTemplate> Shell::CreateWorkerTemplate(Isolate* isolate) {}

Local<ObjectTemplate> Shell::CreateAsyncHookTemplate(Isolate* isolate) {}

Local<ObjectTemplate> Shell::CreateTestRunnerTemplate(Isolate* isolate) {}

Local<ObjectTemplate> Shell::CreatePerformanceTemplate(Isolate* isolate) {}

Local<ObjectTemplate> Shell::CreateRealmTemplate(Isolate* isolate) {}

Local<ObjectTemplate> Shell::CreateD8Template(Isolate* isolate) {}

static void PrintMessageCallback(Local<Message> message, Local<Value> error) {}

void Shell::PromiseRejectCallback(v8::PromiseRejectMessage data) {}

void Shell::Initialize(Isolate* isolate, D8Console* console,
                       bool isOnMainThread) {}

Local<String> Shell::WasmLoadSourceMapCallback(Isolate* isolate,
                                               const char* path) {}

MaybeLocal<Context> Shell::CreateEvaluationContext(Isolate* isolate) {}

void Shell::WriteIgnitionDispatchCountersFile(v8::Isolate* isolate) {}

namespace {
int LineFromOffset(Local<debug::Script> script, int offset) {}

void WriteLcovDataForRange(std::vector<uint32_t>* lines, int start_line,
                           int end_line, uint32_t count) {}

void WriteLcovDataForNamedRange(std::ostream& sink,
                                std::vector<uint32_t>* lines,
                                const std::string& name, int start_line,
                                int end_line, uint32_t count) {}
}  // namespace

// Write coverage data in LCOV format. See man page for geninfo(1).
void Shell::WriteLcovData(v8::Isolate* isolate, const char* file) {}

void Shell::OnExit(v8::Isolate* isolate, bool dispose) {}

void Dummy(char* arg) {}

V8_NOINLINE void FuzzerMonitor::SimulateErrors() {}

V8_NOINLINE void FuzzerMonitor::ControlFlowViolation() {}

V8_NOINLINE void FuzzerMonitor::DCheck() {}

V8_NOINLINE void FuzzerMonitor::Fatal() {}

V8_NOINLINE void FuzzerMonitor::ObservableDifference() {}

V8_NOINLINE void FuzzerMonitor::UndefinedBehavior() {}

V8_NOINLINE void FuzzerMonitor::UseAfterFree() {}

V8_NOINLINE void FuzzerMonitor::UseOfUninitializedValue() {}

char* Shell::ReadChars(const char* name, int* size_out) {}

MaybeLocal<PrimitiveArray> Shell::ReadLines(Isolate* isolate,
                                            const char* name) {}

void Shell::ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Shell::ReadLine(const v8::FunctionCallbackInfo<v8::Value>& info) {}

// Reads a file into a v8 string.
MaybeLocal<String> Shell::ReadFile(Isolate* isolate, const char* name,
                                   bool should_throw) {}

void Shell::WriteChars(const char* name, uint8_t* buffer, size_t buffer_size) {}

void Shell::RunShell(Isolate* isolate) {}

class InspectorFrontend final : public v8_inspector::V8Inspector::Channel {};

class InspectorClient : public v8_inspector::V8InspectorClient {};

SourceGroup::~SourceGroup() {}

bool ends_with(const char* input, const char* suffix) {}

bool SourceGroup::Execute(Isolate* isolate) {}

SourceGroup::IsolateThread::IsolateThread(SourceGroup* group)
    :{}

void SourceGroup::ExecuteInThread() {}

void SourceGroup::StartExecuteInThread() {}

void SourceGroup::WaitForThread(const i::ParkedScope& parked) {}

void SourceGroup::JoinThread(const i::ParkedScope& parked) {}

void SerializationDataQueue::Enqueue(std::unique_ptr<SerializationData> data) {}

bool SerializationDataQueue::Dequeue(
    std::unique_ptr<SerializationData>* out_data) {}

bool SerializationDataQueue::IsEmpty() {}

void SerializationDataQueue::Clear() {}

Worker::Worker(Isolate* parent_isolate, const char* script)
    :{}

Worker::~Worker() {}

bool Worker::is_running() const {}

bool Worker::StartWorkerThread(Isolate* requester,
                               std::shared_ptr<Worker> worker,
                               base::Thread::Priority priority) {}

void Worker::WorkerThread::Run() {}

class ProcessMessageTask : public i::CancelableTask {};

void Worker::PostMessage(std::unique_ptr<SerializationData> data) {}

class TerminateTask : public i::CancelableTask {};

std::unique_ptr<SerializationData> Worker::GetMessage(Isolate* requester) {}

std::unique_ptr<SerializationData> Worker::TryGetMessage() {}

void Worker::TerminateAndWaitForThread(const i::ParkedScope& parked) {}

void Worker::Terminate() {}

void Worker::EnterTerminatedState() {}

void Worker::ProcessMessage(std::unique_ptr<SerializationData> data) {}

void Worker::ProcessMessages() {}

// static
void Worker::SetCurrentWorker(Worker* worker) {}

// static
Worker* Worker::GetCurrentWorker() {}

void Worker::ExecuteInThread() {}

void Worker::PostMessageOut(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Worker::ImportScripts(const v8::FunctionCallbackInfo<v8::Value>& info) {}

void Worker::Close(const v8::FunctionCallbackInfo<v8::Value>& info) {}

#ifdef V8_TARGET_OS_WIN
// Enable support for unicode filename path on windows.
// We first convert ansi encoded argv[i] to utf16 encoded, and then
// convert utf16 encoded to utf8 encoded with setting the argv[i]
// to the utf8 encoded arg. We allocate memory for the utf8 encoded
// arg, and we will free it and reset it to nullptr after using
// the filename path arg. And because Execute may be called multiple
// times, we need to free the allocated unicode filename when exit.

// Save the allocated utf8 filenames, and we will free them when exit.
std::vector<char*> utf8_filenames;
#include <shellapi.h>
// Convert utf-16 encoded string to utf-8 encoded.
char* ConvertUtf16StringToUtf8(const wchar_t* str) {
  // On Windows wchar_t must be a 16-bit value.
  static_assert(sizeof(wchar_t) == 2, "wrong wchar_t size");
  int len =
      WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, FALSE);
  DCHECK_LT(0, len);
  char* utf8_str = new char[len];
  utf8_filenames.push_back(utf8_str);
  WideCharToMultiByte(CP_UTF8, 0, str, -1, utf8_str, len, nullptr, FALSE);
  return utf8_str;
}

// Convert ansi encoded argv[i] to utf8 encoded.
void PreProcessUnicodeFilenameArg(char* argv[], int i) {
  int argc;
  wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
  argv[i] = ConvertUtf16StringToUtf8(wargv[i]);
  LocalFree(wargv);
}

#endif

namespace {

bool FlagMatches(const char* flag, char** arg, bool keep_flag = false) {}

template <size_t N>
bool FlagWithArgMatches(const char (&flag)[N], char** flag_value, int argc,
                        char* argv[], int* i) {}

}  // namespace

bool Shell::SetOptions(int argc, char* argv[]) {}

int Shell::RunMain(v8::Isolate* isolate, bool last_run) {}

bool Shell::RunMainIsolate(v8::Isolate* isolate, bool keep_context_alive) {}

void Shell::CollectGarbage(Isolate* isolate) {}

namespace {
bool ProcessMessages(
    Isolate* isolate,
    const std::function<platform::MessageLoopBehavior()>& behavior) {}
}  // anonymous namespace

bool Shell::CompleteMessageLoop(Isolate* isolate) {}

bool Shell::FinishExecuting(Isolate* isolate, const Global<Context>& context) {}

bool Shell::EmptyMessageQueues(Isolate* isolate) {}

bool Shell::HandleUnhandledPromiseRejections(Isolate* isolate) {}

class Serializer : public ValueSerializer::Delegate {};

class Deserializer : public ValueDeserializer::Delegate {};

class D8Testing {};

std::unique_ptr<SerializationData> Shell::SerializeValue(
    Isolate* isolate, Local<Value> value, Local<Value> transfer) {}

MaybeLocal<Value> Shell::DeserializeValue(
    Isolate* isolate, std::unique_ptr<SerializationData> data) {}

void Shell::AddRunningWorker(std::shared_ptr<Worker> worker) {}

void Shell::RemoveRunningWorker(const std::shared_ptr<Worker>& worker) {}

void Shell::WaitForRunningWorkers(const i::ParkedScope& parked) {}

namespace {

#ifdef V8_OS_POSIX
void d8_sigterm_handler(int signal, siginfo_t* info, void* context) {}
#endif  // V8_OS_POSIX

void d8_install_sigterm_handler() {}

}  // namespace

int Shell::Main(int argc, char* argv[]) {}

}  // namespace v8

int main(int argc, char* argv[]) {}

#undef CHECK
#undef DCHECK