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(¶ms, 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(¶ms, 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