• 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::Value;
20 using v8::V8;
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.get(), &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         node::EmitBeforeExit(env.get());
114         more = uv_loop_alive(&loop);
115       } while (more == true);
116     }
117 
118     exit_code = node::EmitExit(env.get());
119 
120     node::Stop(env.get());
121   }
122 
123   bool platform_finished = false;
124   platform->AddIsolateFinishedCallback(isolate, [](void* data) {
125     *static_cast<bool*>(data) = true;
126   }, &platform_finished);
127   platform->UnregisterIsolate(isolate);
128   isolate->Dispose();
129 
130   // Wait until the platform has cleaned up all relevant resources.
131   while (!platform_finished)
132     uv_run(&loop, UV_RUN_ONCE);
133   int err = uv_loop_close(&loop);
134   assert(err == 0);
135 
136   return exit_code;
137 }
138