11cb0ef41Sopenharmony_ci#include "node.h"
21cb0ef41Sopenharmony_ci#include "node_builtins.h"
31cb0ef41Sopenharmony_ci#include "node_context_data.h"
41cb0ef41Sopenharmony_ci#include "node_errors.h"
51cb0ef41Sopenharmony_ci#include "node_internals.h"
61cb0ef41Sopenharmony_ci#include "node_options-inl.h"
71cb0ef41Sopenharmony_ci#include "node_platform.h"
81cb0ef41Sopenharmony_ci#include "node_realm-inl.h"
91cb0ef41Sopenharmony_ci#include "node_shadow_realm.h"
101cb0ef41Sopenharmony_ci#include "node_v8_platform-inl.h"
111cb0ef41Sopenharmony_ci#include "node_wasm_web_api.h"
121cb0ef41Sopenharmony_ci#include "uv.h"
131cb0ef41Sopenharmony_ci#ifdef NODE_ENABLE_VTUNE_PROFILING
141cb0ef41Sopenharmony_ci#include "../deps/v8/src/third_party/vtune/v8-vtune.h"
151cb0ef41Sopenharmony_ci#endif
161cb0ef41Sopenharmony_ci#if HAVE_INSPECTOR
171cb0ef41Sopenharmony_ci#include "inspector/worker_inspector.h"  // ParentInspectorHandle
181cb0ef41Sopenharmony_ci#endif
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cinamespace node {
211cb0ef41Sopenharmony_ciusing errors::TryCatchScope;
221cb0ef41Sopenharmony_ciusing v8::Array;
231cb0ef41Sopenharmony_ciusing v8::Boolean;
241cb0ef41Sopenharmony_ciusing v8::Context;
251cb0ef41Sopenharmony_ciusing v8::EscapableHandleScope;
261cb0ef41Sopenharmony_ciusing v8::Function;
271cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
281cb0ef41Sopenharmony_ciusing v8::HandleScope;
291cb0ef41Sopenharmony_ciusing v8::Isolate;
301cb0ef41Sopenharmony_ciusing v8::Just;
311cb0ef41Sopenharmony_ciusing v8::Local;
321cb0ef41Sopenharmony_ciusing v8::Maybe;
331cb0ef41Sopenharmony_ciusing v8::MaybeLocal;
341cb0ef41Sopenharmony_ciusing v8::Nothing;
351cb0ef41Sopenharmony_ciusing v8::Null;
361cb0ef41Sopenharmony_ciusing v8::Object;
371cb0ef41Sopenharmony_ciusing v8::ObjectTemplate;
381cb0ef41Sopenharmony_ciusing v8::Private;
391cb0ef41Sopenharmony_ciusing v8::PropertyDescriptor;
401cb0ef41Sopenharmony_ciusing v8::SealHandleScope;
411cb0ef41Sopenharmony_ciusing v8::String;
421cb0ef41Sopenharmony_ciusing v8::Value;
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cibool AllowWasmCodeGenerationCallback(Local<Context> context,
451cb0ef41Sopenharmony_ci                                     Local<String>) {
461cb0ef41Sopenharmony_ci  Local<Value> wasm_code_gen =
471cb0ef41Sopenharmony_ci      context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration);
481cb0ef41Sopenharmony_ci  return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue();
491cb0ef41Sopenharmony_ci}
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_cibool ShouldAbortOnUncaughtException(Isolate* isolate) {
521cb0ef41Sopenharmony_ci  DebugSealHandleScope scope(isolate);
531cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(isolate);
541cb0ef41Sopenharmony_ci  return env != nullptr &&
551cb0ef41Sopenharmony_ci         (env->is_main_thread() || !env->is_stopping()) &&
561cb0ef41Sopenharmony_ci         env->abort_on_uncaught_exception() &&
571cb0ef41Sopenharmony_ci         env->should_abort_on_uncaught_toggle()[0] &&
581cb0ef41Sopenharmony_ci         !env->inside_should_not_abort_on_uncaught_scope();
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciMaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
621cb0ef41Sopenharmony_ci                                            Local<Value> exception,
631cb0ef41Sopenharmony_ci                                            Local<Array> trace) {
641cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(context);
651cb0ef41Sopenharmony_ci  if (env == nullptr) {
661cb0ef41Sopenharmony_ci    return exception->ToString(context).FromMaybe(Local<Value>());
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci  Realm* realm = Realm::GetCurrent(context);
691cb0ef41Sopenharmony_ci  Local<Function> prepare;
701cb0ef41Sopenharmony_ci  if (realm != nullptr) {
711cb0ef41Sopenharmony_ci    // If we are in a Realm, call the realm specific prepareStackTrace callback
721cb0ef41Sopenharmony_ci    // to avoid passing the JS objects (the exception and trace) across the
731cb0ef41Sopenharmony_ci    // realm boundary with the `Error.prepareStackTrace` override.
741cb0ef41Sopenharmony_ci    prepare = realm->prepare_stack_trace_callback();
751cb0ef41Sopenharmony_ci  } else {
761cb0ef41Sopenharmony_ci    // The context is created with ContextifyContext, call the principal
771cb0ef41Sopenharmony_ci    // realm's prepareStackTrace callback.
781cb0ef41Sopenharmony_ci    prepare = env->principal_realm()->prepare_stack_trace_callback();
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci  if (prepare.IsEmpty()) {
811cb0ef41Sopenharmony_ci    return exception->ToString(context).FromMaybe(Local<Value>());
821cb0ef41Sopenharmony_ci  }
831cb0ef41Sopenharmony_ci  Local<Value> args[] = {
841cb0ef41Sopenharmony_ci      context->Global(),
851cb0ef41Sopenharmony_ci      exception,
861cb0ef41Sopenharmony_ci      trace,
871cb0ef41Sopenharmony_ci  };
881cb0ef41Sopenharmony_ci  // This TryCatch + Rethrow is required by V8 due to details around exception
891cb0ef41Sopenharmony_ci  // handling there. For C++ callbacks, V8 expects a scheduled exception (which
901cb0ef41Sopenharmony_ci  // is what ReThrow gives us). Just returning the empty MaybeLocal would leave
911cb0ef41Sopenharmony_ci  // us with a pending exception.
921cb0ef41Sopenharmony_ci  TryCatchScope try_catch(env);
931cb0ef41Sopenharmony_ci  MaybeLocal<Value> result = prepare->Call(
941cb0ef41Sopenharmony_ci      context, Undefined(env->isolate()), arraysize(args), args);
951cb0ef41Sopenharmony_ci  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
961cb0ef41Sopenharmony_ci    try_catch.ReThrow();
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci  return result;
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_civoid* NodeArrayBufferAllocator::Allocate(size_t size) {
1021cb0ef41Sopenharmony_ci  void* ret;
1031cb0ef41Sopenharmony_ci  if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
1041cb0ef41Sopenharmony_ci    ret = allocator_->Allocate(size);
1051cb0ef41Sopenharmony_ci  else
1061cb0ef41Sopenharmony_ci    ret = allocator_->AllocateUninitialized(size);
1071cb0ef41Sopenharmony_ci  if (LIKELY(ret != nullptr))
1081cb0ef41Sopenharmony_ci    total_mem_usage_.fetch_add(size, std::memory_order_relaxed);
1091cb0ef41Sopenharmony_ci  return ret;
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_civoid* NodeArrayBufferAllocator::AllocateUninitialized(size_t size) {
1131cb0ef41Sopenharmony_ci  void* ret = allocator_->AllocateUninitialized(size);
1141cb0ef41Sopenharmony_ci  if (LIKELY(ret != nullptr))
1151cb0ef41Sopenharmony_ci    total_mem_usage_.fetch_add(size, std::memory_order_relaxed);
1161cb0ef41Sopenharmony_ci  return ret;
1171cb0ef41Sopenharmony_ci}
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_civoid* NodeArrayBufferAllocator::Reallocate(
1201cb0ef41Sopenharmony_ci    void* data, size_t old_size, size_t size) {
1211cb0ef41Sopenharmony_ci  void* ret = allocator_->Reallocate(data, old_size, size);
1221cb0ef41Sopenharmony_ci  if (LIKELY(ret != nullptr) || UNLIKELY(size == 0))
1231cb0ef41Sopenharmony_ci    total_mem_usage_.fetch_add(size - old_size, std::memory_order_relaxed);
1241cb0ef41Sopenharmony_ci  return ret;
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_civoid NodeArrayBufferAllocator::Free(void* data, size_t size) {
1281cb0ef41Sopenharmony_ci  total_mem_usage_.fetch_sub(size, std::memory_order_relaxed);
1291cb0ef41Sopenharmony_ci  allocator_->Free(data, size);
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ciDebuggingArrayBufferAllocator::~DebuggingArrayBufferAllocator() {
1331cb0ef41Sopenharmony_ci  CHECK(allocations_.empty());
1341cb0ef41Sopenharmony_ci}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_civoid* DebuggingArrayBufferAllocator::Allocate(size_t size) {
1371cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
1381cb0ef41Sopenharmony_ci  void* data = NodeArrayBufferAllocator::Allocate(size);
1391cb0ef41Sopenharmony_ci  RegisterPointerInternal(data, size);
1401cb0ef41Sopenharmony_ci  return data;
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_civoid* DebuggingArrayBufferAllocator::AllocateUninitialized(size_t size) {
1441cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
1451cb0ef41Sopenharmony_ci  void* data = NodeArrayBufferAllocator::AllocateUninitialized(size);
1461cb0ef41Sopenharmony_ci  RegisterPointerInternal(data, size);
1471cb0ef41Sopenharmony_ci  return data;
1481cb0ef41Sopenharmony_ci}
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_civoid DebuggingArrayBufferAllocator::Free(void* data, size_t size) {
1511cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
1521cb0ef41Sopenharmony_ci  UnregisterPointerInternal(data, size);
1531cb0ef41Sopenharmony_ci  NodeArrayBufferAllocator::Free(data, size);
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_civoid* DebuggingArrayBufferAllocator::Reallocate(void* data,
1571cb0ef41Sopenharmony_ci                                                size_t old_size,
1581cb0ef41Sopenharmony_ci                                                size_t size) {
1591cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
1601cb0ef41Sopenharmony_ci  void* ret = NodeArrayBufferAllocator::Reallocate(data, old_size, size);
1611cb0ef41Sopenharmony_ci  if (ret == nullptr) {
1621cb0ef41Sopenharmony_ci    if (size == 0) {  // i.e. equivalent to free().
1631cb0ef41Sopenharmony_ci      // suppress coverity warning as data is used as key versus as pointer
1641cb0ef41Sopenharmony_ci      // in UnregisterPointerInternal
1651cb0ef41Sopenharmony_ci      // coverity[pass_freed_arg]
1661cb0ef41Sopenharmony_ci      UnregisterPointerInternal(data, old_size);
1671cb0ef41Sopenharmony_ci    }
1681cb0ef41Sopenharmony_ci    return nullptr;
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  if (data != nullptr) {
1721cb0ef41Sopenharmony_ci    auto it = allocations_.find(data);
1731cb0ef41Sopenharmony_ci    CHECK_NE(it, allocations_.end());
1741cb0ef41Sopenharmony_ci    allocations_.erase(it);
1751cb0ef41Sopenharmony_ci  }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  RegisterPointerInternal(ret, size);
1781cb0ef41Sopenharmony_ci  return ret;
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_civoid DebuggingArrayBufferAllocator::RegisterPointer(void* data, size_t size) {
1821cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
1831cb0ef41Sopenharmony_ci  NodeArrayBufferAllocator::RegisterPointer(data, size);
1841cb0ef41Sopenharmony_ci  RegisterPointerInternal(data, size);
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_civoid DebuggingArrayBufferAllocator::UnregisterPointer(void* data, size_t size) {
1881cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
1891cb0ef41Sopenharmony_ci  NodeArrayBufferAllocator::UnregisterPointer(data, size);
1901cb0ef41Sopenharmony_ci  UnregisterPointerInternal(data, size);
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_civoid DebuggingArrayBufferAllocator::UnregisterPointerInternal(void* data,
1941cb0ef41Sopenharmony_ci                                                              size_t size) {
1951cb0ef41Sopenharmony_ci  if (data == nullptr) return;
1961cb0ef41Sopenharmony_ci  auto it = allocations_.find(data);
1971cb0ef41Sopenharmony_ci  CHECK_NE(it, allocations_.end());
1981cb0ef41Sopenharmony_ci  if (size > 0) {
1991cb0ef41Sopenharmony_ci    // We allow allocations with size 1 for 0-length buffers to avoid having
2001cb0ef41Sopenharmony_ci    // to deal with nullptr values.
2011cb0ef41Sopenharmony_ci    CHECK_EQ(it->second, size);
2021cb0ef41Sopenharmony_ci  }
2031cb0ef41Sopenharmony_ci  allocations_.erase(it);
2041cb0ef41Sopenharmony_ci}
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_civoid DebuggingArrayBufferAllocator::RegisterPointerInternal(void* data,
2071cb0ef41Sopenharmony_ci                                                            size_t size) {
2081cb0ef41Sopenharmony_ci  if (data == nullptr) return;
2091cb0ef41Sopenharmony_ci  CHECK_EQ(allocations_.count(data), 0);
2101cb0ef41Sopenharmony_ci  allocations_[data] = size;
2111cb0ef41Sopenharmony_ci}
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_cistd::unique_ptr<ArrayBufferAllocator> ArrayBufferAllocator::Create(bool debug) {
2141cb0ef41Sopenharmony_ci  if (debug || per_process::cli_options->debug_arraybuffer_allocations)
2151cb0ef41Sopenharmony_ci    return std::make_unique<DebuggingArrayBufferAllocator>();
2161cb0ef41Sopenharmony_ci  else
2171cb0ef41Sopenharmony_ci    return std::make_unique<NodeArrayBufferAllocator>();
2181cb0ef41Sopenharmony_ci}
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ciArrayBufferAllocator* CreateArrayBufferAllocator() {
2211cb0ef41Sopenharmony_ci  return ArrayBufferAllocator::Create().release();
2221cb0ef41Sopenharmony_ci}
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_civoid FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) {
2251cb0ef41Sopenharmony_ci  delete allocator;
2261cb0ef41Sopenharmony_ci}
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_civoid SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
2291cb0ef41Sopenharmony_ci  const uint64_t constrained_memory = uv_get_constrained_memory();
2301cb0ef41Sopenharmony_ci  const uint64_t total_memory = constrained_memory > 0 ?
2311cb0ef41Sopenharmony_ci      std::min(uv_get_total_memory(), constrained_memory) :
2321cb0ef41Sopenharmony_ci      uv_get_total_memory();
2331cb0ef41Sopenharmony_ci  if (total_memory > 0 &&
2341cb0ef41Sopenharmony_ci      params->constraints.max_old_generation_size_in_bytes() == 0) {
2351cb0ef41Sopenharmony_ci    // V8 defaults to 700MB or 1.4GB on 32 and 64 bit platforms respectively.
2361cb0ef41Sopenharmony_ci    // This default is based on browser use-cases. Tell V8 to configure the
2371cb0ef41Sopenharmony_ci    // heap based on the actual physical memory.
2381cb0ef41Sopenharmony_ci    params->constraints.ConfigureDefaults(total_memory, 0);
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci  params->embedder_wrapper_object_index = BaseObject::InternalFields::kSlot;
2411cb0ef41Sopenharmony_ci  params->embedder_wrapper_type_index = std::numeric_limits<int>::max();
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci#ifdef NODE_ENABLE_VTUNE_PROFILING
2441cb0ef41Sopenharmony_ci  params->code_event_handler = vTune::GetVtuneCodeEventHandler();
2451cb0ef41Sopenharmony_ci#endif
2461cb0ef41Sopenharmony_ci}
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_civoid SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
2491cb0ef41Sopenharmony_ci  if (s.flags & MESSAGE_LISTENER_WITH_ERROR_LEVEL)
2501cb0ef41Sopenharmony_ci    isolate->AddMessageListenerWithErrorLevel(
2511cb0ef41Sopenharmony_ci            errors::PerIsolateMessageListener,
2521cb0ef41Sopenharmony_ci            Isolate::MessageErrorLevel::kMessageError |
2531cb0ef41Sopenharmony_ci                Isolate::MessageErrorLevel::kMessageWarning);
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  auto* abort_callback = s.should_abort_on_uncaught_exception_callback ?
2561cb0ef41Sopenharmony_ci      s.should_abort_on_uncaught_exception_callback :
2571cb0ef41Sopenharmony_ci      ShouldAbortOnUncaughtException;
2581cb0ef41Sopenharmony_ci  isolate->SetAbortOnUncaughtExceptionCallback(abort_callback);
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  auto* fatal_error_cb = s.fatal_error_callback ?
2611cb0ef41Sopenharmony_ci      s.fatal_error_callback : OnFatalError;
2621cb0ef41Sopenharmony_ci  isolate->SetFatalErrorHandler(fatal_error_cb);
2631cb0ef41Sopenharmony_ci  isolate->SetOOMErrorHandler(OOMErrorHandler);
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci  if ((s.flags & SHOULD_NOT_SET_PREPARE_STACK_TRACE_CALLBACK) == 0) {
2661cb0ef41Sopenharmony_ci    auto* prepare_stack_trace_cb = s.prepare_stack_trace_callback ?
2671cb0ef41Sopenharmony_ci        s.prepare_stack_trace_callback : PrepareStackTraceCallback;
2681cb0ef41Sopenharmony_ci    isolate->SetPrepareStackTraceCallback(prepare_stack_trace_cb);
2691cb0ef41Sopenharmony_ci  }
2701cb0ef41Sopenharmony_ci}
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_civoid SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
2731cb0ef41Sopenharmony_ci  isolate->SetMicrotasksPolicy(s.policy);
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  auto* allow_wasm_codegen_cb = s.allow_wasm_code_generation_callback ?
2761cb0ef41Sopenharmony_ci    s.allow_wasm_code_generation_callback : AllowWasmCodeGenerationCallback;
2771cb0ef41Sopenharmony_ci  isolate->SetAllowWasmCodeGenerationCallback(allow_wasm_codegen_cb);
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  auto* modify_code_generation_from_strings_callback =
2801cb0ef41Sopenharmony_ci      ModifyCodeGenerationFromStrings;
2811cb0ef41Sopenharmony_ci  if (s.flags & ALLOW_MODIFY_CODE_GENERATION_FROM_STRINGS_CALLBACK &&
2821cb0ef41Sopenharmony_ci      s.modify_code_generation_from_strings_callback) {
2831cb0ef41Sopenharmony_ci    modify_code_generation_from_strings_callback =
2841cb0ef41Sopenharmony_ci        s.modify_code_generation_from_strings_callback;
2851cb0ef41Sopenharmony_ci  }
2861cb0ef41Sopenharmony_ci  isolate->SetModifyCodeGenerationFromStringsCallback(
2871cb0ef41Sopenharmony_ci      modify_code_generation_from_strings_callback);
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
2901cb0ef41Sopenharmony_ci  if (per_process::cli_options->get_per_isolate_options()
2911cb0ef41Sopenharmony_ci          ->get_per_env_options()
2921cb0ef41Sopenharmony_ci          ->experimental_fetch) {
2931cb0ef41Sopenharmony_ci    isolate->SetWasmStreamingCallback(wasm_web_api::StartStreamingCompilation);
2941cb0ef41Sopenharmony_ci  }
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  if (per_process::cli_options->get_per_isolate_options()
2971cb0ef41Sopenharmony_ci          ->experimental_shadow_realm) {
2981cb0ef41Sopenharmony_ci    isolate->SetHostCreateShadowRealmContextCallback(
2991cb0ef41Sopenharmony_ci        shadow_realm::HostCreateShadowRealmContextCallback);
3001cb0ef41Sopenharmony_ci  }
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  if ((s.flags & SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK) == 0) {
3031cb0ef41Sopenharmony_ci    auto* promise_reject_cb = s.promise_reject_callback ?
3041cb0ef41Sopenharmony_ci      s.promise_reject_callback : PromiseRejectCallback;
3051cb0ef41Sopenharmony_ci    isolate->SetPromiseRejectCallback(promise_reject_cb);
3061cb0ef41Sopenharmony_ci  }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  if (s.flags & DETAILED_SOURCE_POSITIONS_FOR_PROFILING)
3091cb0ef41Sopenharmony_ci    v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate);
3101cb0ef41Sopenharmony_ci}
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_civoid SetIsolateUpForNode(v8::Isolate* isolate,
3131cb0ef41Sopenharmony_ci                         const IsolateSettings& settings) {
3141cb0ef41Sopenharmony_ci  SetIsolateErrorHandlers(isolate, settings);
3151cb0ef41Sopenharmony_ci  SetIsolateMiscHandlers(isolate, settings);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_civoid SetIsolateUpForNode(v8::Isolate* isolate) {
3191cb0ef41Sopenharmony_ci  IsolateSettings settings;
3201cb0ef41Sopenharmony_ci  SetIsolateUpForNode(isolate, settings);
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci// TODO(joyeecheung): we may want to expose this, but then we need to be
3241cb0ef41Sopenharmony_ci// careful about what we override in the params.
3251cb0ef41Sopenharmony_ciIsolate* NewIsolate(Isolate::CreateParams* params,
3261cb0ef41Sopenharmony_ci                    uv_loop_t* event_loop,
3271cb0ef41Sopenharmony_ci                    MultiIsolatePlatform* platform,
3281cb0ef41Sopenharmony_ci                    bool has_snapshot_data) {
3291cb0ef41Sopenharmony_ci  Isolate* isolate = Isolate::Allocate();
3301cb0ef41Sopenharmony_ci  if (isolate == nullptr) return nullptr;
3311cb0ef41Sopenharmony_ci#ifdef NODE_V8_SHARED_RO_HEAP
3321cb0ef41Sopenharmony_ci  {
3331cb0ef41Sopenharmony_ci    // In shared-readonly-heap mode, V8 requires all snapshots used for
3341cb0ef41Sopenharmony_ci    // creating Isolates to be identical. This isn't really memory-safe
3351cb0ef41Sopenharmony_ci    // but also otherwise just doesn't work, and the only real alternative
3361cb0ef41Sopenharmony_ci    // is disabling shared-readonly-heap mode altogether.
3371cb0ef41Sopenharmony_ci    static Isolate::CreateParams first_params = *params;
3381cb0ef41Sopenharmony_ci    params->snapshot_blob = first_params.snapshot_blob;
3391cb0ef41Sopenharmony_ci    params->external_references = first_params.external_references;
3401cb0ef41Sopenharmony_ci  }
3411cb0ef41Sopenharmony_ci#endif
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  // Register the isolate on the platform before the isolate gets initialized,
3441cb0ef41Sopenharmony_ci  // so that the isolate can access the platform during initialization.
3451cb0ef41Sopenharmony_ci  platform->RegisterIsolate(isolate, event_loop);
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci  SetIsolateCreateParamsForNode(params);
3481cb0ef41Sopenharmony_ci  Isolate::Initialize(isolate, *params);
3491cb0ef41Sopenharmony_ci  if (!has_snapshot_data) {
3501cb0ef41Sopenharmony_ci    // If in deserialize mode, delay until after the deserialization is
3511cb0ef41Sopenharmony_ci    // complete.
3521cb0ef41Sopenharmony_ci    SetIsolateUpForNode(isolate);
3531cb0ef41Sopenharmony_ci  } else {
3541cb0ef41Sopenharmony_ci    SetIsolateMiscHandlers(isolate, {});
3551cb0ef41Sopenharmony_ci  }
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci  return isolate;
3581cb0ef41Sopenharmony_ci}
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ciIsolate* NewIsolate(ArrayBufferAllocator* allocator,
3611cb0ef41Sopenharmony_ci                    uv_loop_t* event_loop,
3621cb0ef41Sopenharmony_ci                    MultiIsolatePlatform* platform) {
3631cb0ef41Sopenharmony_ci  Isolate::CreateParams params;
3641cb0ef41Sopenharmony_ci  if (allocator != nullptr) params.array_buffer_allocator = allocator;
3651cb0ef41Sopenharmony_ci  return NewIsolate(&params, event_loop, platform);
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ciIsolate* NewIsolate(std::shared_ptr<ArrayBufferAllocator> allocator,
3691cb0ef41Sopenharmony_ci                    uv_loop_t* event_loop,
3701cb0ef41Sopenharmony_ci                    MultiIsolatePlatform* platform) {
3711cb0ef41Sopenharmony_ci  Isolate::CreateParams params;
3721cb0ef41Sopenharmony_ci  if (allocator) params.array_buffer_allocator_shared = allocator;
3731cb0ef41Sopenharmony_ci  return NewIsolate(&params, event_loop, platform);
3741cb0ef41Sopenharmony_ci}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ciIsolateData* CreateIsolateData(Isolate* isolate,
3771cb0ef41Sopenharmony_ci                               uv_loop_t* loop,
3781cb0ef41Sopenharmony_ci                               MultiIsolatePlatform* platform,
3791cb0ef41Sopenharmony_ci                               ArrayBufferAllocator* allocator) {
3801cb0ef41Sopenharmony_ci  return new IsolateData(isolate, loop, platform, allocator);
3811cb0ef41Sopenharmony_ci}
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_civoid FreeIsolateData(IsolateData* isolate_data) {
3841cb0ef41Sopenharmony_ci  delete isolate_data;
3851cb0ef41Sopenharmony_ci}
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ciInspectorParentHandle::~InspectorParentHandle() {}
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci// Hide the internal handle class from the public API.
3901cb0ef41Sopenharmony_ci#if HAVE_INSPECTOR
3911cb0ef41Sopenharmony_cistruct InspectorParentHandleImpl : public InspectorParentHandle {
3921cb0ef41Sopenharmony_ci  std::unique_ptr<inspector::ParentInspectorHandle> impl;
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci  explicit InspectorParentHandleImpl(
3951cb0ef41Sopenharmony_ci      std::unique_ptr<inspector::ParentInspectorHandle>&& impl)
3961cb0ef41Sopenharmony_ci    : impl(std::move(impl)) {}
3971cb0ef41Sopenharmony_ci};
3981cb0ef41Sopenharmony_ci#endif
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ciEnvironment* CreateEnvironment(
4011cb0ef41Sopenharmony_ci    IsolateData* isolate_data,
4021cb0ef41Sopenharmony_ci    Local<Context> context,
4031cb0ef41Sopenharmony_ci    const std::vector<std::string>& args,
4041cb0ef41Sopenharmony_ci    const std::vector<std::string>& exec_args,
4051cb0ef41Sopenharmony_ci    EnvironmentFlags::Flags flags,
4061cb0ef41Sopenharmony_ci    ThreadId thread_id,
4071cb0ef41Sopenharmony_ci    std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
4081cb0ef41Sopenharmony_ci  Isolate* isolate = context->GetIsolate();
4091cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
4101cb0ef41Sopenharmony_ci  Context::Scope context_scope(context);
4111cb0ef41Sopenharmony_ci  // TODO(addaleax): This is a much better place for parsing per-Environment
4121cb0ef41Sopenharmony_ci  // options than the global parse call.
4131cb0ef41Sopenharmony_ci  Environment* env = new Environment(
4141cb0ef41Sopenharmony_ci      isolate_data, context, args, exec_args, nullptr, flags, thread_id);
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci#if HAVE_INSPECTOR
4171cb0ef41Sopenharmony_ci  if (env->should_create_inspector()) {
4181cb0ef41Sopenharmony_ci    if (inspector_parent_handle) {
4191cb0ef41Sopenharmony_ci      env->InitializeInspector(std::move(
4201cb0ef41Sopenharmony_ci          static_cast<InspectorParentHandleImpl*>(inspector_parent_handle.get())
4211cb0ef41Sopenharmony_ci              ->impl));
4221cb0ef41Sopenharmony_ci    } else {
4231cb0ef41Sopenharmony_ci      env->InitializeInspector({});
4241cb0ef41Sopenharmony_ci    }
4251cb0ef41Sopenharmony_ci  }
4261cb0ef41Sopenharmony_ci#endif
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci  if (env->principal_realm()->RunBootstrapping().IsEmpty()) {
4291cb0ef41Sopenharmony_ci    FreeEnvironment(env);
4301cb0ef41Sopenharmony_ci    return nullptr;
4311cb0ef41Sopenharmony_ci  }
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci  return env;
4341cb0ef41Sopenharmony_ci}
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_civoid FreeEnvironment(Environment* env) {
4371cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
4381cb0ef41Sopenharmony_ci  Isolate::DisallowJavascriptExecutionScope disallow_js(isolate,
4391cb0ef41Sopenharmony_ci      Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
4401cb0ef41Sopenharmony_ci  {
4411cb0ef41Sopenharmony_ci    HandleScope handle_scope(isolate);  // For env->context().
4421cb0ef41Sopenharmony_ci    Context::Scope context_scope(env->context());
4431cb0ef41Sopenharmony_ci    SealHandleScope seal_handle_scope(isolate);
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci    // Set the flag in accordance with the DisallowJavascriptExecutionScope
4461cb0ef41Sopenharmony_ci    // above.
4471cb0ef41Sopenharmony_ci    env->set_can_call_into_js(false);
4481cb0ef41Sopenharmony_ci    env->set_stopping(true);
4491cb0ef41Sopenharmony_ci    env->stop_sub_worker_contexts();
4501cb0ef41Sopenharmony_ci    env->RunCleanup();
4511cb0ef41Sopenharmony_ci    RunAtExit(env);
4521cb0ef41Sopenharmony_ci  }
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci  // This call needs to be made while the `Environment` is still alive
4551cb0ef41Sopenharmony_ci  // because we assume that it is available for async tracking in the
4561cb0ef41Sopenharmony_ci  // NodePlatform implementation.
4571cb0ef41Sopenharmony_ci  MultiIsolatePlatform* platform = env->isolate_data()->platform();
4581cb0ef41Sopenharmony_ci  if (platform != nullptr)
4591cb0ef41Sopenharmony_ci    platform->DrainTasks(isolate);
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  delete env;
4621cb0ef41Sopenharmony_ci}
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ciNODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
4651cb0ef41Sopenharmony_ci    Environment* env,
4661cb0ef41Sopenharmony_ci    ThreadId thread_id,
4671cb0ef41Sopenharmony_ci    const char* url) {
4681cb0ef41Sopenharmony_ci  return GetInspectorParentHandle(env, thread_id, url, "");
4691cb0ef41Sopenharmony_ci}
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ciNODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
4721cb0ef41Sopenharmony_ci    Environment* env, ThreadId thread_id, const char* url, const char* name) {
4731cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(env);
4741cb0ef41Sopenharmony_ci  if (name == nullptr) name = "";
4751cb0ef41Sopenharmony_ci  CHECK_NE(thread_id.id, static_cast<uint64_t>(-1));
4761cb0ef41Sopenharmony_ci  if (!env->should_create_inspector()) {
4771cb0ef41Sopenharmony_ci    return nullptr;
4781cb0ef41Sopenharmony_ci  }
4791cb0ef41Sopenharmony_ci#if HAVE_INSPECTOR
4801cb0ef41Sopenharmony_ci  return std::make_unique<InspectorParentHandleImpl>(
4811cb0ef41Sopenharmony_ci      env->inspector_agent()->GetParentHandle(thread_id.id, url, name));
4821cb0ef41Sopenharmony_ci#else
4831cb0ef41Sopenharmony_ci  return {};
4841cb0ef41Sopenharmony_ci#endif
4851cb0ef41Sopenharmony_ci}
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ciMaybeLocal<Value> LoadEnvironment(
4881cb0ef41Sopenharmony_ci    Environment* env,
4891cb0ef41Sopenharmony_ci    StartExecutionCallback cb) {
4901cb0ef41Sopenharmony_ci  env->InitializeLibuv();
4911cb0ef41Sopenharmony_ci  env->InitializeDiagnostics();
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  return StartExecution(env, cb);
4941cb0ef41Sopenharmony_ci}
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ciMaybeLocal<Value> LoadEnvironment(
4971cb0ef41Sopenharmony_ci    Environment* env,
4981cb0ef41Sopenharmony_ci    const char* main_script_source_utf8) {
4991cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(main_script_source_utf8);
5001cb0ef41Sopenharmony_ci  return LoadEnvironment(
5011cb0ef41Sopenharmony_ci      env, [&](const StartExecutionCallbackInfo& info) -> MaybeLocal<Value> {
5021cb0ef41Sopenharmony_ci        std::string name = "embedder_main_" + std::to_string(env->thread_id());
5031cb0ef41Sopenharmony_ci        env->builtin_loader()->Add(name.c_str(), main_script_source_utf8);
5041cb0ef41Sopenharmony_ci        Realm* realm = env->principal_realm();
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci        return realm->ExecuteBootstrapper(name.c_str());
5071cb0ef41Sopenharmony_ci      });
5081cb0ef41Sopenharmony_ci}
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ciEnvironment* GetCurrentEnvironment(Local<Context> context) {
5111cb0ef41Sopenharmony_ci  return Environment::GetCurrent(context);
5121cb0ef41Sopenharmony_ci}
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ciIsolateData* GetEnvironmentIsolateData(Environment* env) {
5151cb0ef41Sopenharmony_ci  return env->isolate_data();
5161cb0ef41Sopenharmony_ci}
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ciArrayBufferAllocator* GetArrayBufferAllocator(IsolateData* isolate_data) {
5191cb0ef41Sopenharmony_ci  return isolate_data->node_allocator();
5201cb0ef41Sopenharmony_ci}
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ciMultiIsolatePlatform* GetMultiIsolatePlatform(Environment* env) {
5231cb0ef41Sopenharmony_ci  return GetMultiIsolatePlatform(env->isolate_data());
5241cb0ef41Sopenharmony_ci}
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ciMultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env) {
5271cb0ef41Sopenharmony_ci  return env->platform();
5281cb0ef41Sopenharmony_ci}
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_ciMultiIsolatePlatform* CreatePlatform(
5311cb0ef41Sopenharmony_ci    int thread_pool_size,
5321cb0ef41Sopenharmony_ci    node::tracing::TracingController* tracing_controller) {
5331cb0ef41Sopenharmony_ci  return CreatePlatform(
5341cb0ef41Sopenharmony_ci      thread_pool_size,
5351cb0ef41Sopenharmony_ci      static_cast<v8::TracingController*>(tracing_controller));
5361cb0ef41Sopenharmony_ci}
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ciMultiIsolatePlatform* CreatePlatform(
5391cb0ef41Sopenharmony_ci    int thread_pool_size,
5401cb0ef41Sopenharmony_ci    v8::TracingController* tracing_controller) {
5411cb0ef41Sopenharmony_ci  return MultiIsolatePlatform::Create(thread_pool_size,
5421cb0ef41Sopenharmony_ci                                      tracing_controller)
5431cb0ef41Sopenharmony_ci      .release();
5441cb0ef41Sopenharmony_ci}
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_civoid FreePlatform(MultiIsolatePlatform* platform) {
5471cb0ef41Sopenharmony_ci  delete platform;
5481cb0ef41Sopenharmony_ci}
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_cistd::unique_ptr<MultiIsolatePlatform> MultiIsolatePlatform::Create(
5511cb0ef41Sopenharmony_ci    int thread_pool_size,
5521cb0ef41Sopenharmony_ci    v8::TracingController* tracing_controller,
5531cb0ef41Sopenharmony_ci    v8::PageAllocator* page_allocator) {
5541cb0ef41Sopenharmony_ci  return std::make_unique<NodePlatform>(thread_pool_size,
5551cb0ef41Sopenharmony_ci                                        tracing_controller,
5561cb0ef41Sopenharmony_ci                                        page_allocator);
5571cb0ef41Sopenharmony_ci}
5581cb0ef41Sopenharmony_ci
5591cb0ef41Sopenharmony_ciMaybeLocal<Object> GetPerContextExports(Local<Context> context) {
5601cb0ef41Sopenharmony_ci  Isolate* isolate = context->GetIsolate();
5611cb0ef41Sopenharmony_ci  EscapableHandleScope handle_scope(isolate);
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci  Local<Object> global = context->Global();
5641cb0ef41Sopenharmony_ci  Local<Private> key = Private::ForApi(isolate,
5651cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(isolate, "node:per_context_binding_exports"));
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci  Local<Value> existing_value;
5681cb0ef41Sopenharmony_ci  if (!global->GetPrivate(context, key).ToLocal(&existing_value))
5691cb0ef41Sopenharmony_ci    return MaybeLocal<Object>();
5701cb0ef41Sopenharmony_ci  if (existing_value->IsObject())
5711cb0ef41Sopenharmony_ci    return handle_scope.Escape(existing_value.As<Object>());
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ci  Local<Object> exports = Object::New(isolate);
5741cb0ef41Sopenharmony_ci  if (context->Global()->SetPrivate(context, key, exports).IsNothing() ||
5751cb0ef41Sopenharmony_ci      InitializePrimordials(context).IsNothing())
5761cb0ef41Sopenharmony_ci    return MaybeLocal<Object>();
5771cb0ef41Sopenharmony_ci  return handle_scope.Escape(exports);
5781cb0ef41Sopenharmony_ci}
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci// Any initialization logic should be performed in
5811cb0ef41Sopenharmony_ci// InitializeContext, because embedders don't necessarily
5821cb0ef41Sopenharmony_ci// call NewContext and so they will experience breakages.
5831cb0ef41Sopenharmony_ciLocal<Context> NewContext(Isolate* isolate,
5841cb0ef41Sopenharmony_ci                          Local<ObjectTemplate> object_template) {
5851cb0ef41Sopenharmony_ci  auto context = Context::New(isolate, nullptr, object_template);
5861cb0ef41Sopenharmony_ci  if (context.IsEmpty()) return context;
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci  if (InitializeContext(context).IsNothing()) {
5891cb0ef41Sopenharmony_ci    return Local<Context>();
5901cb0ef41Sopenharmony_ci  }
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci  return context;
5931cb0ef41Sopenharmony_ci}
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_civoid ProtoThrower(const FunctionCallbackInfo<Value>& info) {
5961cb0ef41Sopenharmony_ci  THROW_ERR_PROTO_ACCESS(info.GetIsolate());
5971cb0ef41Sopenharmony_ci}
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci// This runs at runtime, regardless of whether the context
6001cb0ef41Sopenharmony_ci// is created from a snapshot.
6011cb0ef41Sopenharmony_ciMaybe<bool> InitializeContextRuntime(Local<Context> context) {
6021cb0ef41Sopenharmony_ci  Isolate* isolate = context->GetIsolate();
6031cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  // When `IsCodeGenerationFromStringsAllowed` is true, V8 takes the fast path
6061cb0ef41Sopenharmony_ci  // and ignores the ModifyCodeGenerationFromStrings callback. Set it to false
6071cb0ef41Sopenharmony_ci  // to delegate the code generation validation to
6081cb0ef41Sopenharmony_ci  // node::ModifyCodeGenerationFromStrings.
6091cb0ef41Sopenharmony_ci  // The `IsCodeGenerationFromStringsAllowed` can be refreshed by V8 according
6101cb0ef41Sopenharmony_ci  // to the runtime flags, propagate the value to the embedder data.
6111cb0ef41Sopenharmony_ci  bool is_code_generation_from_strings_allowed =
6121cb0ef41Sopenharmony_ci      context->IsCodeGenerationFromStringsAllowed();
6131cb0ef41Sopenharmony_ci  context->AllowCodeGenerationFromStrings(false);
6141cb0ef41Sopenharmony_ci  context->SetEmbedderData(
6151cb0ef41Sopenharmony_ci      ContextEmbedderIndex::kAllowCodeGenerationFromStrings,
6161cb0ef41Sopenharmony_ci      Boolean::New(isolate, is_code_generation_from_strings_allowed));
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci  if (per_process::cli_options->disable_proto == "") {
6191cb0ef41Sopenharmony_ci    return Just(true);
6201cb0ef41Sopenharmony_ci  }
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  // Remove __proto__
6231cb0ef41Sopenharmony_ci  // https://github.com/nodejs/node/issues/31951
6241cb0ef41Sopenharmony_ci  Local<Object> prototype;
6251cb0ef41Sopenharmony_ci  {
6261cb0ef41Sopenharmony_ci    Local<String> object_string =
6271cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(isolate, "Object");
6281cb0ef41Sopenharmony_ci    Local<String> prototype_string =
6291cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(isolate, "prototype");
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ci    Local<Value> object_v;
6321cb0ef41Sopenharmony_ci    if (!context->Global()
6331cb0ef41Sopenharmony_ci        ->Get(context, object_string)
6341cb0ef41Sopenharmony_ci        .ToLocal(&object_v)) {
6351cb0ef41Sopenharmony_ci      return Nothing<bool>();
6361cb0ef41Sopenharmony_ci    }
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci    Local<Value> prototype_v;
6391cb0ef41Sopenharmony_ci    if (!object_v.As<Object>()
6401cb0ef41Sopenharmony_ci        ->Get(context, prototype_string)
6411cb0ef41Sopenharmony_ci        .ToLocal(&prototype_v)) {
6421cb0ef41Sopenharmony_ci      return Nothing<bool>();
6431cb0ef41Sopenharmony_ci    }
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci    prototype = prototype_v.As<Object>();
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci  Local<String> proto_string =
6491cb0ef41Sopenharmony_ci    FIXED_ONE_BYTE_STRING(isolate, "__proto__");
6501cb0ef41Sopenharmony_ci
6511cb0ef41Sopenharmony_ci  if (per_process::cli_options->disable_proto == "delete") {
6521cb0ef41Sopenharmony_ci    if (prototype
6531cb0ef41Sopenharmony_ci        ->Delete(context, proto_string)
6541cb0ef41Sopenharmony_ci        .IsNothing()) {
6551cb0ef41Sopenharmony_ci      return Nothing<bool>();
6561cb0ef41Sopenharmony_ci    }
6571cb0ef41Sopenharmony_ci  } else if (per_process::cli_options->disable_proto == "throw") {
6581cb0ef41Sopenharmony_ci    Local<Value> thrower;
6591cb0ef41Sopenharmony_ci    if (!Function::New(context, ProtoThrower)
6601cb0ef41Sopenharmony_ci        .ToLocal(&thrower)) {
6611cb0ef41Sopenharmony_ci      return Nothing<bool>();
6621cb0ef41Sopenharmony_ci    }
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_ci    PropertyDescriptor descriptor(thrower, thrower);
6651cb0ef41Sopenharmony_ci    descriptor.set_enumerable(false);
6661cb0ef41Sopenharmony_ci    descriptor.set_configurable(true);
6671cb0ef41Sopenharmony_ci    if (prototype
6681cb0ef41Sopenharmony_ci        ->DefineProperty(context, proto_string, descriptor)
6691cb0ef41Sopenharmony_ci        .IsNothing()) {
6701cb0ef41Sopenharmony_ci      return Nothing<bool>();
6711cb0ef41Sopenharmony_ci    }
6721cb0ef41Sopenharmony_ci  } else if (per_process::cli_options->disable_proto != "") {
6731cb0ef41Sopenharmony_ci    // Validated in ProcessGlobalArgs
6741cb0ef41Sopenharmony_ci    OnFatalError("InitializeContextRuntime()", "invalid --disable-proto mode");
6751cb0ef41Sopenharmony_ci  }
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ci  return Just(true);
6781cb0ef41Sopenharmony_ci}
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ciMaybe<bool> InitializeBaseContextForSnapshot(Local<Context> context) {
6811cb0ef41Sopenharmony_ci  Isolate* isolate = context->GetIsolate();
6821cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
6831cb0ef41Sopenharmony_ci
6841cb0ef41Sopenharmony_ci  // Delete `Intl.v8BreakIterator`
6851cb0ef41Sopenharmony_ci  // https://github.com/nodejs/node/issues/14909
6861cb0ef41Sopenharmony_ci  {
6871cb0ef41Sopenharmony_ci    Context::Scope context_scope(context);
6881cb0ef41Sopenharmony_ci    Local<String> intl_string = FIXED_ONE_BYTE_STRING(isolate, "Intl");
6891cb0ef41Sopenharmony_ci    Local<String> break_iter_string =
6901cb0ef41Sopenharmony_ci        FIXED_ONE_BYTE_STRING(isolate, "v8BreakIterator");
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci    Local<Value> intl_v;
6931cb0ef41Sopenharmony_ci    if (!context->Global()->Get(context, intl_string).ToLocal(&intl_v)) {
6941cb0ef41Sopenharmony_ci      return Nothing<bool>();
6951cb0ef41Sopenharmony_ci    }
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_ci    if (intl_v->IsObject() &&
6981cb0ef41Sopenharmony_ci        intl_v.As<Object>()->Delete(context, break_iter_string).IsNothing()) {
6991cb0ef41Sopenharmony_ci      return Nothing<bool>();
7001cb0ef41Sopenharmony_ci    }
7011cb0ef41Sopenharmony_ci  }
7021cb0ef41Sopenharmony_ci  return Just(true);
7031cb0ef41Sopenharmony_ci}
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ciMaybe<bool> InitializeMainContextForSnapshot(Local<Context> context) {
7061cb0ef41Sopenharmony_ci  Isolate* isolate = context->GetIsolate();
7071cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci  // Initialize the default values.
7101cb0ef41Sopenharmony_ci  context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration,
7111cb0ef41Sopenharmony_ci                           True(isolate));
7121cb0ef41Sopenharmony_ci  context->SetEmbedderData(
7131cb0ef41Sopenharmony_ci      ContextEmbedderIndex::kAllowCodeGenerationFromStrings, True(isolate));
7141cb0ef41Sopenharmony_ci
7151cb0ef41Sopenharmony_ci  if (InitializeBaseContextForSnapshot(context).IsNothing()) {
7161cb0ef41Sopenharmony_ci    return Nothing<bool>();
7171cb0ef41Sopenharmony_ci  }
7181cb0ef41Sopenharmony_ci  return InitializePrimordials(context);
7191cb0ef41Sopenharmony_ci}
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ciMaybe<bool> InitializePrimordials(Local<Context> context) {
7221cb0ef41Sopenharmony_ci  // Run per-context JS files.
7231cb0ef41Sopenharmony_ci  Isolate* isolate = context->GetIsolate();
7241cb0ef41Sopenharmony_ci  Context::Scope context_scope(context);
7251cb0ef41Sopenharmony_ci  Local<Object> exports;
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_ci  Local<String> primordials_string =
7281cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(isolate, "primordials");
7291cb0ef41Sopenharmony_ci
7301cb0ef41Sopenharmony_ci  // Create primordials first and make it available to per-context scripts.
7311cb0ef41Sopenharmony_ci  Local<Object> primordials = Object::New(isolate);
7321cb0ef41Sopenharmony_ci  if (primordials->SetPrototype(context, Null(isolate)).IsNothing() ||
7331cb0ef41Sopenharmony_ci      !GetPerContextExports(context).ToLocal(&exports) ||
7341cb0ef41Sopenharmony_ci      exports->Set(context, primordials_string, primordials).IsNothing()) {
7351cb0ef41Sopenharmony_ci    return Nothing<bool>();
7361cb0ef41Sopenharmony_ci  }
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci  static const char* context_files[] = {"internal/per_context/primordials",
7391cb0ef41Sopenharmony_ci                                        "internal/per_context/domexception",
7401cb0ef41Sopenharmony_ci                                        "internal/per_context/messageport",
7411cb0ef41Sopenharmony_ci                                        nullptr};
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ci  // We do not have access to a per-Environment BuiltinLoader instance
7441cb0ef41Sopenharmony_ci  // at this point, because this code runs before an Environment exists
7451cb0ef41Sopenharmony_ci  // in the first place. However, creating BuiltinLoader instances is
7461cb0ef41Sopenharmony_ci  // relatively cheap and all the scripts that we may want to run at
7471cb0ef41Sopenharmony_ci  // startup are always present in it.
7481cb0ef41Sopenharmony_ci  thread_local builtins::BuiltinLoader builtin_loader;
7491cb0ef41Sopenharmony_ci  for (const char** module = context_files; *module != nullptr; module++) {
7501cb0ef41Sopenharmony_ci    Local<Value> arguments[] = {exports, primordials};
7511cb0ef41Sopenharmony_ci    if (builtin_loader
7521cb0ef41Sopenharmony_ci            .CompileAndCall(
7531cb0ef41Sopenharmony_ci                context, *module, arraysize(arguments), arguments, nullptr)
7541cb0ef41Sopenharmony_ci            .IsEmpty()) {
7551cb0ef41Sopenharmony_ci      // Execution failed during context creation.
7561cb0ef41Sopenharmony_ci      return Nothing<bool>();
7571cb0ef41Sopenharmony_ci    }
7581cb0ef41Sopenharmony_ci  }
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci  return Just(true);
7611cb0ef41Sopenharmony_ci}
7621cb0ef41Sopenharmony_ci
7631cb0ef41Sopenharmony_ci// This initializes the main context (i.e. vm contexts are not included).
7641cb0ef41Sopenharmony_ciMaybe<bool> InitializeContext(Local<Context> context) {
7651cb0ef41Sopenharmony_ci  if (InitializeMainContextForSnapshot(context).IsNothing()) {
7661cb0ef41Sopenharmony_ci    return Nothing<bool>();
7671cb0ef41Sopenharmony_ci  }
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci  return InitializeContextRuntime(context);
7701cb0ef41Sopenharmony_ci}
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ciuv_loop_t* GetCurrentEventLoop(Isolate* isolate) {
7731cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
7741cb0ef41Sopenharmony_ci  Local<Context> context = isolate->GetCurrentContext();
7751cb0ef41Sopenharmony_ci  if (context.IsEmpty()) return nullptr;
7761cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(context);
7771cb0ef41Sopenharmony_ci  if (env == nullptr) return nullptr;
7781cb0ef41Sopenharmony_ci  return env->event_loop();
7791cb0ef41Sopenharmony_ci}
7801cb0ef41Sopenharmony_ci
7811cb0ef41Sopenharmony_civoid AddLinkedBinding(Environment* env, const node_module& mod) {
7821cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(env);
7831cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(env->extra_linked_bindings_mutex());
7841cb0ef41Sopenharmony_ci
7851cb0ef41Sopenharmony_ci  node_module* prev_tail = env->extra_linked_bindings_tail();
7861cb0ef41Sopenharmony_ci  env->extra_linked_bindings()->push_back(mod);
7871cb0ef41Sopenharmony_ci  if (prev_tail != nullptr)
7881cb0ef41Sopenharmony_ci    prev_tail->nm_link = &env->extra_linked_bindings()->back();
7891cb0ef41Sopenharmony_ci}
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_civoid AddLinkedBinding(Environment* env, const jsvm_module& mod) {
7921cb0ef41Sopenharmony_ci  node_module node_mod = jsvm_module_to_node_module(&mod);
7931cb0ef41Sopenharmony_ci  node_mod.nm_flags = NM_F_LINKED;
7941cb0ef41Sopenharmony_ci  AddLinkedBinding(env, node_mod);
7951cb0ef41Sopenharmony_ci}
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_civoid AddLinkedBinding(Environment* env,
7981cb0ef41Sopenharmony_ci                      const char* name,
7991cb0ef41Sopenharmony_ci                      addon_context_register_func fn,
8001cb0ef41Sopenharmony_ci                      void* priv) {
8011cb0ef41Sopenharmony_ci  node_module mod = {
8021cb0ef41Sopenharmony_ci    NODE_MODULE_VERSION,
8031cb0ef41Sopenharmony_ci    NM_F_LINKED,
8041cb0ef41Sopenharmony_ci    nullptr,  // nm_dso_handle
8051cb0ef41Sopenharmony_ci    nullptr,  // nm_filename
8061cb0ef41Sopenharmony_ci    nullptr,  // nm_register_func
8071cb0ef41Sopenharmony_ci    fn,
8081cb0ef41Sopenharmony_ci    name,
8091cb0ef41Sopenharmony_ci    priv,
8101cb0ef41Sopenharmony_ci    nullptr   // nm_link
8111cb0ef41Sopenharmony_ci  };
8121cb0ef41Sopenharmony_ci  AddLinkedBinding(env, mod);
8131cb0ef41Sopenharmony_ci}
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_civoid AddLinkedBinding(Environment* env,
8161cb0ef41Sopenharmony_ci                      const char* name,
8171cb0ef41Sopenharmony_ci                      jsvm_addon_register_func fn,
8181cb0ef41Sopenharmony_ci                      int32_t module_api_version) {
8191cb0ef41Sopenharmony_ci  node_module mod = {
8201cb0ef41Sopenharmony_ci      -1,           // nm_version for Node-API
8211cb0ef41Sopenharmony_ci      NM_F_LINKED,  // nm_flags
8221cb0ef41Sopenharmony_ci      nullptr,      // nm_dso_handle
8231cb0ef41Sopenharmony_ci      nullptr,      // nm_filename
8241cb0ef41Sopenharmony_ci      nullptr,      // nm_register_func
8251cb0ef41Sopenharmony_ci      get_node_api_context_register_func(env, name, module_api_version),
8261cb0ef41Sopenharmony_ci      name,                         // nm_modname
8271cb0ef41Sopenharmony_ci      reinterpret_cast<void*>(fn),  // nm_priv
8281cb0ef41Sopenharmony_ci      nullptr                       // nm_link
8291cb0ef41Sopenharmony_ci  };
8301cb0ef41Sopenharmony_ci  AddLinkedBinding(env, mod);
8311cb0ef41Sopenharmony_ci}
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_cistatic std::atomic<uint64_t> next_thread_id{0};
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ciThreadId AllocateEnvironmentThreadId() {
8361cb0ef41Sopenharmony_ci  return ThreadId { next_thread_id++ };
8371cb0ef41Sopenharmony_ci}
8381cb0ef41Sopenharmony_ci
8391cb0ef41Sopenharmony_civoid DefaultProcessExitHandler(Environment* env, int exit_code) {
8401cb0ef41Sopenharmony_ci  env->set_stopping(true);
8411cb0ef41Sopenharmony_ci  env->set_can_call_into_js(false);
8421cb0ef41Sopenharmony_ci  env->stop_sub_worker_contexts();
8431cb0ef41Sopenharmony_ci  env->isolate()->DumpAndResetStats();
8441cb0ef41Sopenharmony_ci  // The tracing agent could be in the process of writing data using the
8451cb0ef41Sopenharmony_ci  // threadpool. Stop it before shutting down libuv. The rest of the tracing
8461cb0ef41Sopenharmony_ci  // agent disposal will be performed in DisposePlatform().
8471cb0ef41Sopenharmony_ci  per_process::v8_platform.StopTracingAgent();
8481cb0ef41Sopenharmony_ci  // When the process exits, the tasks in the thread pool may also need to
8491cb0ef41Sopenharmony_ci  // access the data of V8Platform, such as trace agent, or a field
8501cb0ef41Sopenharmony_ci  // added in the future. So make sure the thread pool exits first.
8511cb0ef41Sopenharmony_ci  // And make sure V8Platform don not call into Libuv threadpool, see Dispose
8521cb0ef41Sopenharmony_ci  // in node_v8_platform-inl.h
8531cb0ef41Sopenharmony_ci  uv_library_shutdown();
8541cb0ef41Sopenharmony_ci  DisposePlatform();
8551cb0ef41Sopenharmony_ci  exit(exit_code);
8561cb0ef41Sopenharmony_ci}
8571cb0ef41Sopenharmony_ci
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_civoid SetProcessExitHandler(Environment* env,
8601cb0ef41Sopenharmony_ci                           std::function<void(Environment*, int)>&& handler) {
8611cb0ef41Sopenharmony_ci  env->set_process_exit_handler(std::move(handler));
8621cb0ef41Sopenharmony_ci}
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci}  // namespace node
865