1 #include "node.h"
2 #include "uv.h"
3 #include <assert.h>
4
5 // Note: This file is being referred to from doc/api/embedding.md, and excerpts
6 // from it are included in the documentation. Try to keep these in sync.
7
8 using node::ArrayBufferAllocator;
9 using node::Environment;
10 using node::IsolateData;
11 using node::MultiIsolatePlatform;
12 using v8::Context;
13 using v8::HandleScope;
14 using v8::Isolate;
15 using v8::Local;
16 using v8::Locker;
17 using v8::MaybeLocal;
18 using v8::SealHandleScope;
19 using v8::V8;
20 using v8::Value;
21
22 static int RunNodeInstance(MultiIsolatePlatform* platform,
23 const std::vector<std::string>& args,
24 const std::vector<std::string>& exec_args);
25
main(int argc,char ** argv)26 int main(int argc, char** argv) {
27 argv = uv_setup_args(argc, argv);
28 std::vector<std::string> args(argv, argv + argc);
29 std::vector<std::string> exec_args;
30 std::vector<std::string> errors;
31 int exit_code = node::InitializeNodeWithArgs(&args, &exec_args, &errors);
32 for (const std::string& error : errors)
33 fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str());
34 if (exit_code != 0) {
35 return exit_code;
36 }
37
38 std::unique_ptr<MultiIsolatePlatform> platform =
39 MultiIsolatePlatform::Create(4);
40 V8::InitializePlatform(platform.get());
41 V8::Initialize();
42
43 int ret = RunNodeInstance(platform.get(), args, exec_args);
44
45 V8::Dispose();
46 V8::ShutdownPlatform();
47 return ret;
48 }
49
RunNodeInstance(MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args)50 int RunNodeInstance(MultiIsolatePlatform* platform,
51 const std::vector<std::string>& args,
52 const std::vector<std::string>& exec_args) {
53 int exit_code = 0;
54 uv_loop_t loop;
55 int ret = uv_loop_init(&loop);
56 if (ret != 0) {
57 fprintf(stderr, "%s: Failed to initialize loop: %s\n",
58 args[0].c_str(),
59 uv_err_name(ret));
60 return 1;
61 }
62
63 std::shared_ptr<ArrayBufferAllocator> allocator =
64 ArrayBufferAllocator::Create();
65
66 Isolate* isolate = NewIsolate(allocator, &loop, platform);
67 if (isolate == nullptr) {
68 fprintf(stderr, "%s: Failed to initialize V8 Isolate\n", args[0].c_str());
69 return 1;
70 }
71
72 {
73 Locker locker(isolate);
74 Isolate::Scope isolate_scope(isolate);
75
76 std::unique_ptr<IsolateData, decltype(&node::FreeIsolateData)> isolate_data(
77 node::CreateIsolateData(isolate, &loop, platform, allocator.get()),
78 node::FreeIsolateData);
79
80 HandleScope handle_scope(isolate);
81 Local<Context> context = node::NewContext(isolate);
82 if (context.IsEmpty()) {
83 fprintf(stderr, "%s: Failed to initialize V8 Context\n", args[0].c_str());
84 return 1;
85 }
86
87 Context::Scope context_scope(context);
88 std::unique_ptr<Environment, decltype(&node::FreeEnvironment)> env(
89 node::CreateEnvironment(isolate_data.get(), context, args, exec_args),
90 node::FreeEnvironment);
91
92 MaybeLocal<Value> loadenv_ret = node::LoadEnvironment(
93 env.get(),
94 "const publicRequire ="
95 " require('module').createRequire(process.cwd() + '/');"
96 "globalThis.require = publicRequire;"
97 "globalThis.embedVars = { nön_ascıı: '️' };"
98 "require('vm').runInThisContext(process.argv[1]);");
99
100 if (loadenv_ret.IsEmpty()) // There has been a JS exception.
101 return 1;
102
103 {
104 SealHandleScope seal(isolate);
105 bool more;
106 do {
107 uv_run(&loop, UV_RUN_DEFAULT);
108
109 platform->DrainTasks(isolate);
110 more = uv_loop_alive(&loop);
111 if (more) continue;
112
113 if (node::EmitProcessBeforeExit(env.get()).IsNothing())
114 break;
115
116 more = uv_loop_alive(&loop);
117 } while (more == true);
118 }
119
120 exit_code = node::EmitProcessExit(env.get()).FromMaybe(1);
121
122 node::Stop(env.get());
123 }
124
125 bool platform_finished = false;
126 platform->AddIsolateFinishedCallback(isolate, [](void* data) {
127 *static_cast<bool*>(data) = true;
128 }, &platform_finished);
129 platform->UnregisterIsolate(isolate);
130 isolate->Dispose();
131
132 // Wait until the platform has cleaned up all relevant resources.
133 while (!platform_finished)
134 uv_run(&loop, UV_RUN_ONCE);
135 int err = uv_loop_close(&loop);
136 assert(err == 0);
137
138 return exit_code;
139 }
140