Skip to content

Commit

Permalink
Own isolate for each resource to allow proper inspector initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
vadzz-dev committed Oct 28, 2023
1 parent 5ddb005 commit 07f6907
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 49 deletions.
74 changes: 38 additions & 36 deletions server/src/CNodeResourceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,62 +26,60 @@ 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<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);

v8::Local<v8::String> resourceName = V8Helpers::JSValue(resource->GetName());

v8::Local<v8::Context> _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()
{
v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> _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<v8::Context> _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::Flags>(node::EnvironmentFlags::kNoFlags);
auto inspector = node::GetInspectorParentHandle(runtime->GetParentEnv(), threadId, resource->GetName().c_str());

nodeData = node::CreateIsolateData(isolate, uvLoop, runtime->GetPlatform());
std::vector<std::string> argv = { "altv-resource" };
env = node::CreateEnvironment(nodeData, _context, argv, argv, flags);
std::vector<std::string> args{ resource->GetName() };
std::vector<std::string> 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;
}

Expand All @@ -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();
Expand All @@ -99,6 +99,8 @@ bool CNodeResourceImpl::Stop()
asyncResource.Reset();
}

Log::Debug << "After stop" << Log::Endl;

node::EmitProcessBeforeExit(env);
node::EmitProcessExit(env);

Expand Down
39 changes: 26 additions & 13 deletions server/src/CNodeScriptRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,45 @@
bool CNodeScriptRuntime::Init()
{
ProcessConfigOptions();
std::vector<std::string> argv = GetNodeArgs();
std::vector<std::string> execArgv;
std::vector<std::string> 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();
Expand All @@ -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();
Expand Down
13 changes: 13 additions & 0 deletions server/src/CNodeScriptRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
class CNodeScriptRuntime : public alt::IScriptRuntime, public IRuntimeEventHandler
{
v8::Isolate* isolate;
V8Helpers::CPersistent<v8::Context> context;
node::Environment* parentEnv;

std::unique_ptr<node::MultiIsolatePlatform> platform;
std::unordered_set<CNodeResourceImpl*> resources;

Expand Down Expand Up @@ -39,6 +42,16 @@ class CNodeScriptRuntime : public alt::IScriptRuntime, public IRuntimeEventHandl
return isolate;
}

node::Environment* GetParentEnv() const
{
return parentEnv;
}

v8::Local<v8::Context> GetContext()
{
return context.Get(isolate);
}

alt::IResource::Impl* CreateImpl(alt::IResource* resource) override;

void DestroyImpl(alt::IResource::Impl* impl) override
Expand Down

0 comments on commit 07f6907

Please sign in to comment.