• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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