From 07f69078788410934d788480ab342dda6392e47a Mon Sep 17 00:00:00 2001 From: Vadim Zubkov Date: Sun, 29 Oct 2023 00:29:43 +0300 Subject: [PATCH] Own isolate for each resource to allow proper inspector initialization --- server/src/CNodeResourceImpl.cpp | 74 ++++++++++++++++--------------- server/src/CNodeScriptRuntime.cpp | 39 ++++++++++------ server/src/CNodeScriptRuntime.h | 13 ++++++ 3 files changed, 77 insertions(+), 49 deletions(-) diff --git a/server/src/CNodeResourceImpl.cpp b/server/src/CNodeResourceImpl.cpp index 3255d029..5ac41f7d 100644 --- a/server/src/CNodeResourceImpl.cpp +++ b/server/src/CNodeResourceImpl.cpp @@ -26,21 +26,14 @@ static const char bootstrap_code[] = #include "bootstrap.js.gen" ; -CNodeResourceImpl::CNodeResourceImpl(CNodeScriptRuntime* _runtime, v8::Isolate* isolate, alt::IResource* resource) : V8ResourceImpl(isolate, resource), runtime(_runtime) +CNodeResourceImpl::CNodeResourceImpl(CNodeScriptRuntime* _runtime, v8::Isolate* _isolate, alt::IResource* resource) : V8ResourceImpl(nullptr, resource), runtime(_runtime) { - v8::Locker locker(isolate); - v8::Isolate::Scope isolateScope(isolate); - v8::HandleScope handleScope(isolate); - - v8::Local global = v8::ObjectTemplate::New(isolate); - - v8::Local resourceName = V8Helpers::JSValue(resource->GetName()); - - v8::Local _context = node::NewContext(isolate, global); - v8::Context::Scope scope(_context); + uvLoop = new uv_loop_t; + uv_loop_init(uvLoop); - _context->SetAlignedPointerInEmbedderData(1, resource); - context.Reset(isolate, _context); + auto allocator = node::CreateArrayBufferAllocator(); + isolate = node::NewIsolate(allocator, uvLoop, runtime->GetPlatform()); + nodeData = node::CreateIsolateData(isolate, uvLoop, runtime->GetPlatform(), allocator); } bool CNodeResourceImpl::Start() @@ -48,40 +41,45 @@ bool CNodeResourceImpl::Start() v8::Locker locker(isolate); v8::Isolate::Scope isolateScope(isolate); v8::HandleScope handleScope(isolate); - v8::Local _context = GetContext(); - v8::Context::Scope scope(_context); - _context->Global()->Set(_context, V8Helpers::JSValue("__resourceLoaded"), v8::Function::New(_context, &ResourceLoaded).ToLocalChecked()); - _context->Global()->Set(_context, V8Helpers::JSValue("__internal_bindings_code"), V8Helpers::JSValue(JSBindings::GetBindingsCode())); + v8::Local _context = node::NewContext(isolate); + _context->SetAlignedPointerInEmbedderData(1, resource); + context.Reset(isolate, _context); + + { + v8::Context::Scope scope(_context); - V8ResourceImpl::Start(); - V8ResourceImpl::SetupScriptGlobals(); + _context->Global()->Set(_context, V8Helpers::JSValue("__resourceLoaded"), v8::Function::New(_context, &ResourceLoaded).ToLocalChecked()); + _context->Global()->Set(_context, V8Helpers::JSValue("__internal_bindings_code"), V8Helpers::JSValue(JSBindings::GetBindingsCode())); - node::EnvironmentFlags::Flags flags = (node::EnvironmentFlags::Flags)(node::EnvironmentFlags::kOwnsProcessState & node::EnvironmentFlags::kNoCreateInspector); + V8Class::LoadAll(isolate); + V8ResourceImpl::Start(); + V8ResourceImpl::SetupScriptGlobals(); - uvLoop = new uv_loop_t; - uv_loop_init(uvLoop); + node::ThreadId threadId = node::AllocateEnvironmentThreadId(); + auto flags = static_cast(node::EnvironmentFlags::kNoFlags); + auto inspector = node::GetInspectorParentHandle(runtime->GetParentEnv(), threadId, resource->GetName().c_str()); - nodeData = node::CreateIsolateData(isolate, uvLoop, runtime->GetPlatform()); - std::vector argv = { "altv-resource" }; - env = node::CreateEnvironment(nodeData, _context, argv, argv, flags); + std::vector args{ resource->GetName() }; + std::vector execArgs{ "--inspect=127.0.0.1:9229" }; - node::IsolateSettings is; - node::SetIsolateUpForNode(isolate, is); + env = node::CreateEnvironment(nodeData, _context, args, execArgs, flags, threadId, std::move(inspector)); + node::LoadEnvironment(env, bootstrap_code); - node::LoadEnvironment(env, bootstrap_code); + // Not sure it's needed anymore + asyncResource.Reset(isolate, v8::Object::New(isolate)); + asyncContext = node::EmitAsyncInit(isolate, asyncResource.Get(isolate), "CNodeResourceImpl"); - asyncResource.Reset(isolate, v8::Object::New(isolate)); - asyncContext = node::EmitAsyncInit(isolate, asyncResource.Get(isolate), "CNodeResourceImpl"); + while(!envStarted && !startError) + { + runtime->OnTick(); + OnTick(); + } - while(!envStarted && !startError) - { - runtime->OnTick(); - OnTick(); + Log::Debug << "Started" << Log::Endl; + DispatchStartEvent(startError); } - DispatchStartEvent(startError); - return !startError; } @@ -91,6 +89,8 @@ bool CNodeResourceImpl::Stop() v8::Isolate::Scope isolateScope(isolate); v8::HandleScope handleScope(isolate); + Log::Debug << "Before stop" << Log::Endl; + { v8::Context::Scope scope(GetContext()); DispatchStopEvent(); @@ -99,6 +99,8 @@ bool CNodeResourceImpl::Stop() asyncResource.Reset(); } + Log::Debug << "After stop" << Log::Endl; + node::EmitProcessBeforeExit(env); node::EmitProcessExit(env); diff --git a/server/src/CNodeScriptRuntime.cpp b/server/src/CNodeScriptRuntime.cpp index 4b0bb8dd..57e80076 100644 --- a/server/src/CNodeScriptRuntime.cpp +++ b/server/src/CNodeScriptRuntime.cpp @@ -6,34 +6,45 @@ bool CNodeScriptRuntime::Init() { ProcessConfigOptions(); - std::vector argv = GetNodeArgs(); - std::vector execArgv; - std::vector errors; - node::InitializeNodeWithArgs(&argv, &execArgv, &errors); - if(errors.size() > 0) + auto result = node::InitializeOncePerProcess(GetNodeArgs()); + + if (result->early_return()) { - for(std::string& error : errors) + for (auto& error : result->errors()) { Log::Error << "Error while initializing node: " << error << Log::Endl; } + return false; } - platform = node::MultiIsolatePlatform::Create(4); - v8::V8::InitializePlatform(platform.get()); - v8::V8::Initialize(); + platform.reset(result->platform()); + + auto allocator = node::CreateArrayBufferAllocator(); + isolate = node::NewIsolate(allocator, uv_default_loop(), platform.get()); + node::IsolateData* nodeData = node::CreateIsolateData(isolate, uv_default_loop(), platform.get(), allocator); - isolate = node::NewIsolate(node::CreateArrayBufferAllocator(), uv_default_loop(), platform.get()); + // node::IsolateSettings is; + // node::SetIsolateUpForNode(isolate, is); // IsWorker data slot - isolate->SetData(v8::Isolate::GetNumberOfDataSlots() - 1, new bool(false)); + // isolate->SetData(v8::Isolate::GetNumberOfDataSlots() - 1, new bool(false)); { v8::Locker locker(isolate); v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); - V8Class::LoadAll(isolate); + context.Reset(isolate, node::NewContext(isolate)); + v8::Context::Scope scope(context.Get(isolate)); + + parentEnv = node::CreateEnvironment(nodeData, context.Get(isolate), result->args(), result->exec_args()); + + /* + Load here only needs for debugging as this environment only used as a parent for real environments + */ + + // node::LoadEnvironment(parentEnv, "console.log('PARENT INIT'); setInterval(() => {}, 1000);"); } IRuntimeEventHandler::Start(); @@ -54,8 +65,10 @@ void CNodeScriptRuntime::OnTick() { v8::Locker locker(isolate); v8::Isolate::Scope isolateScope(isolate); - v8::SealHandleScope seal(isolate); + v8::HandleScope seal(isolate); + v8::Context::Scope scope(context.Get(isolate)); + uv_run(uv_default_loop(), UV_RUN_NOWAIT); platform->DrainTasks(isolate); UpdateMetrics(); diff --git a/server/src/CNodeScriptRuntime.h b/server/src/CNodeScriptRuntime.h index 8406109c..9c596bb4 100644 --- a/server/src/CNodeScriptRuntime.h +++ b/server/src/CNodeScriptRuntime.h @@ -10,6 +10,9 @@ class CNodeScriptRuntime : public alt::IScriptRuntime, public IRuntimeEventHandler { v8::Isolate* isolate; + V8Helpers::CPersistent context; + node::Environment* parentEnv; + std::unique_ptr platform; std::unordered_set resources; @@ -39,6 +42,16 @@ class CNodeScriptRuntime : public alt::IScriptRuntime, public IRuntimeEventHandl return isolate; } + node::Environment* GetParentEnv() const + { + return parentEnv; + } + + v8::Local GetContext() + { + return context.Get(isolate); + } + alt::IResource::Impl* CreateImpl(alt::IResource* resource) override; void DestroyImpl(alt::IResource::Impl* impl) override