Repository navigation
Question: Embedding NodeJS to run many scripts #1031
Copy link
Copy link
Closed
Description
- Node.js Version: various versions compiled from source code of "v8.x" and "master" branches
- OS: MS Windows 7
- Scope: Embedding
I want to embed NodeJS into an application. My idea is following:
- make fork of node with my additional files
- build modified library
- use it in my application
but I want to run any script at any time. For access to node I wrote following code:
#include <node_version.h>
#include <v8.h>
#include <uv.h>
#include <env.h>
#include <env-inl.h>
#include <node_internals.h>
#include <node_platform.h>
#include <libplatform\libplatform.h>
namespace embed {
const int DEFAULT_THREAD_POOL_SIZE = 4;
bool initialized = false;
node::NodePlatform* v8_platform;
class Finalizer {
public:
~Finalizer() {
Fini();
}
}finalizer;
//initialization v8 - once per process
void Init() {
if (!initialized) {
#if NODE_MAJOR_VERSION == 8
v8_platform = new node::NodePlatform(DEFAULT_THREAD_POOL_SIZE, uv_default_loop(), nullptr);
#elif NODE_MAJOR_VERSION > 8
v8_platform = new node::NodePlatform(DEFAULT_THREAD_POOL_SIZE, nullptr);
#endif
#if NODE_MAJOR_VERSION > 8
node::tracing::TraceEventHelper::SetTracingController(
new v8::TracingController());
#endif
v8::V8::InitializePlatform(v8_platform);
v8::V8::Initialize();
initialized = true;
}
}
//finalization v8 - once per process
void Fini()
{
if (initialized) {
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
//v8_platform->Shutdown();
delete v8_platform;
v8_platform = nullptr;
initialized = false;
}
}
//running script
void Run(int argc, const char * argv[])
{
node::ArrayBufferAllocator allocator;
v8::Isolate::CreateParams params;
params.array_buffer_allocator = &allocator;
auto isolate = v8::Isolate::New(params);
{
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope h_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
node::IsolateData * isolate_data;
#if NODE_MAJOR_VERSION == 8
isolate_data = node::CreateIsolateData(isolate, uv_default_loop());
#elif NODE_MAJOR_VERSION > 8
isolate_data = node::CreateIsolateData(iso, uv_default_loop(), v8_platform);
#endif
int exec_argc;
const char ** exec_argv;
node::Init(&argc, argv, &exec_argc, &exec_argv);
auto env = node::CreateEnvironment(isolate_data,
context,
argc,
argv,
exec_argc,
exec_argv);
node::LoadEnvironment(env);
node::FreeEnvironment(env);
node::FreeIsolateData(isolate_data);
}
isolate->Dispose();
}
}All works fine (without errors) and I can call Run function many times when i want (of course, after calling Init function). But i don't like, that I must create v8::Isolate and node::Environment for every script. I tried to make one isolate for all scripts, but when I create second environment with the same isolate I get an error. I think, that one isolate and one environment for all scripts will be better way than code above. Is there a way to "reload" node::Environment with new argv? If no, is it possible to make this feature?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]Embedding NodeJS to run many scripts[/-][+]Question: Embedding NodeJS to run many scripts[/+]bnoordhuis commentedon Dec 19, 2017
What error?
smeshch commentedon Dec 19, 2017
related to this line. I think environment tries to add existing callback
bnoordhuis commentedon Jan 10, 2018
Sorry, been a while. I suspect it's caused by the built-in performance counters or ETW support. I filed nodejs/node#18074, help welcome.
smeshch commentedon Jan 11, 2018
It's not exactly what I wanted. The best way for me is create one isolate and one environment and just "reload" environment with new arguments for every script. But I think it's hard to realize my thoughts, isn't it?
bnoordhuis commentedon Jan 11, 2018
Correct.
smeshch commentedon Jan 12, 2018
I found one more bug realted to this theme.
As i described above, I use
Runfunction for every script. But on node, builded from branchesv9.xandmasterit runs one time. Second run doesn't work. In this line it loops andnameparameter have value"natives". It caused by more than one call ofnode::Initfunction. On code fromv8.xbranch it works fine.Simplest way to reproduce is:
v9.xormasterbranchInitfunction call (link to line)smeshch commentedon Jan 12, 2018
If it can help:
OS: MS Windows 7 x64 (nodejs also x64)
My thoughts: when I call
Initsecond time, it register modules again and make circular structure, where last node module's propertynm_linklinks to first node module (or to another node module but not to nullptr). And nodejs try to findnativesin infinite loop.gireeshpunathil commentedon Apr 5, 2018
@Let0s - is this still outstanding?
smeshch commentedon Apr 6, 2018
@gireeshpunathil Yes, I think second part (with many calls
Initfunction) is still important for embedders, because I think, thatnode::Initcall is the only external way to pass arguments to nodejs (e.g path to script or its code).If there is (or will be) another way, then this problem is not so important.
gireeshpunathil commentedon Apr 6, 2018
linking with nodejs/node#19377 in expectation that it is the most relevant one.
I guess the key question that is outstanding is:
/cc @addaleax who has been leading the embedder's use cases.
smeshch commentedon Apr 6, 2018
Yes, this is the key question.
gireeshpunathil commentedon May 29, 2018
@Let0s - multi-thread based execution environment is being proposed through nodejs/node#20876 . You can find source that was refactored, as well as few APIs added in that PR - specifically in
that helps in re-entrance through a new
Environment.smeshch commentedon May 29, 2018
@gireeshpunathil Thank you for information.
gireeshpunathil commentedon May 21, 2019
closing this as answered.