/
node_bindings.h
184 lines (140 loc) · 5.34 KB
/
node_bindings.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_COMMON_NODE_BINDINGS_H_
#define ELECTRON_SHELL_COMMON_NODE_BINDINGS_H_
#include <string>
#include <type_traits>
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "uv.h" // NOLINT(build/include_directory)
#include "v8/include/v8.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace node {
class Environment;
class MultiIsolatePlatform;
class IsolateData;
} // namespace node
namespace electron {
// A helper class to manage uv_handle_t types, e.g. uv_async_t.
//
// As per the uv docs: "uv_close() MUST be called on each handle before
// memory is released. Moreover, the memory can only be released in
// close_cb or after it has returned." This class encapsulates the work
// needed to follow those requirements.
template <typename T,
typename std::enable_if<
// these are the C-style 'subclasses' of uv_handle_t
std::is_same<T, uv_async_t>::value ||
std::is_same<T, uv_check_t>::value ||
std::is_same<T, uv_fs_event_t>::value ||
std::is_same<T, uv_fs_poll_t>::value ||
std::is_same<T, uv_idle_t>::value ||
std::is_same<T, uv_pipe_t>::value ||
std::is_same<T, uv_poll_t>::value ||
std::is_same<T, uv_prepare_t>::value ||
std::is_same<T, uv_process_t>::value ||
std::is_same<T, uv_signal_t>::value ||
std::is_same<T, uv_stream_t>::value ||
std::is_same<T, uv_tcp_t>::value ||
std::is_same<T, uv_timer_t>::value ||
std::is_same<T, uv_tty_t>::value ||
std::is_same<T, uv_udp_t>::value>::type* = nullptr>
class UvHandle {
public:
UvHandle() : t_(new T) {}
~UvHandle() { reset(); }
T* get() { return t_; }
uv_handle_t* handle() { return reinterpret_cast<uv_handle_t*>(t_); }
void reset() {
auto* h = handle();
if (h != nullptr) {
DCHECK_EQ(0, uv_is_closing(h));
uv_close(h, OnClosed);
t_ = nullptr;
}
}
private:
static void OnClosed(uv_handle_t* handle) {
delete reinterpret_cast<T*>(handle);
}
T* t_ = {};
};
class NodeBindings {
public:
enum class BrowserEnvironment { kBrowser, kRenderer, kUtility, kWorker };
static NodeBindings* Create(BrowserEnvironment browser_env);
static void RegisterBuiltinModules();
static bool IsInitialized();
virtual ~NodeBindings();
// Setup V8, libuv.
void Initialize();
void SetNodeCliFlags();
// Create the environment and load node.js.
node::Environment* CreateEnvironment(v8::Handle<v8::Context> context,
node::MultiIsolatePlatform* platform,
std::vector<std::string> args,
std::vector<std::string> exec_args);
node::Environment* CreateEnvironment(v8::Handle<v8::Context> context,
node::MultiIsolatePlatform* platform);
// Load node.js in the environment.
void LoadEnvironment(node::Environment* env);
// Prepare embed thread for message loop integration.
void PrepareEmbedThread();
// Notify embed thread to start polling after environment is loaded.
void StartPolling();
// Gets/sets the per isolate data.
void set_isolate_data(node::IsolateData* isolate_data) {
isolate_data_ = isolate_data;
}
node::IsolateData* isolate_data() const { return isolate_data_; }
// Gets/sets the environment to wrap uv loop.
void set_uv_env(node::Environment* env) { uv_env_ = env; }
node::Environment* uv_env() const { return uv_env_; }
uv_loop_t* uv_loop() const { return uv_loop_; }
bool in_worker_loop() const { return uv_loop_ == &worker_loop_; }
// disable copy
NodeBindings(const NodeBindings&) = delete;
NodeBindings& operator=(const NodeBindings&) = delete;
protected:
explicit NodeBindings(BrowserEnvironment browser_env);
// Called to poll events in new thread.
virtual void PollEvents() = 0;
// Run the libuv loop for once.
void UvRunOnce();
// Make the main thread run libuv loop.
void WakeupMainThread();
// Interrupt the PollEvents.
void WakeupEmbedThread();
// Which environment we are running.
const BrowserEnvironment browser_env_;
// Current thread's MessageLoop.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Current thread's libuv loop.
uv_loop_t* uv_loop_;
private:
// Thread to poll uv events.
static void EmbedThreadRunner(void* arg);
// Indicates whether polling thread has been created.
bool initialized_ = false;
// Whether the libuv loop has ended.
bool embed_closed_ = false;
// Loop used when constructed in WORKER mode
uv_loop_t worker_loop_;
// Dummy handle to make uv's loop not quit.
UvHandle<uv_async_t> dummy_uv_handle_;
// Thread for polling events.
uv_thread_t embed_thread_;
// Semaphore to wait for main loop in the embed thread.
uv_sem_t embed_sem_;
// Environment that to wrap the uv loop.
node::Environment* uv_env_ = nullptr;
// Isolate data used in creating the environment
node::IsolateData* isolate_data_ = nullptr;
base::WeakPtrFactory<NodeBindings> weak_factory_{this};
};
} // namespace electron
#endif // ELECTRON_SHELL_COMMON_NODE_BINDINGS_H_