1 |
|
|
// Copyright Joyent, Inc. and other Node contributors. |
2 |
|
|
// |
3 |
|
|
// Permission is hereby granted, free of charge, to any person obtaining a |
4 |
|
|
// copy of this software and associated documentation files (the |
5 |
|
|
// "Software"), to deal in the Software without restriction, including |
6 |
|
|
// without limitation the rights to use, copy, modify, merge, publish, |
7 |
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit |
8 |
|
|
// persons to whom the Software is furnished to do so, subject to the |
9 |
|
|
// following conditions: |
10 |
|
|
// |
11 |
|
|
// The above copyright notice and this permission notice shall be included |
12 |
|
|
// in all copies or substantial portions of the Software. |
13 |
|
|
// |
14 |
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
15 |
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
16 |
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
17 |
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
18 |
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
19 |
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
20 |
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE. |
21 |
|
|
|
22 |
|
|
#ifndef SRC_NODE_H_ |
23 |
|
|
#define SRC_NODE_H_ |
24 |
|
|
|
25 |
|
|
#ifdef _WIN32 |
26 |
|
|
# ifndef BUILDING_NODE_EXTENSION |
27 |
|
|
# define NODE_EXTERN __declspec(dllexport) |
28 |
|
|
# else |
29 |
|
|
# define NODE_EXTERN __declspec(dllimport) |
30 |
|
|
# endif |
31 |
|
|
#else |
32 |
|
|
# define NODE_EXTERN __attribute__((visibility("default"))) |
33 |
|
|
#endif |
34 |
|
|
|
35 |
|
|
// Declarations annotated with NODE_EXTERN_PRIVATE do not form part of |
36 |
|
|
// the public API. They are implementation details that can and will |
37 |
|
|
// change between releases, even in semver patch releases. Do not use |
38 |
|
|
// any such symbol in external code. |
39 |
|
|
#ifdef NODE_SHARED_MODE |
40 |
|
|
#define NODE_EXTERN_PRIVATE NODE_EXTERN |
41 |
|
|
#else |
42 |
|
|
#define NODE_EXTERN_PRIVATE |
43 |
|
|
#endif |
44 |
|
|
|
45 |
|
|
#ifdef BUILDING_NODE_EXTENSION |
46 |
|
|
# undef BUILDING_V8_SHARED |
47 |
|
|
# undef BUILDING_UV_SHARED |
48 |
|
|
# define USING_V8_SHARED 1 |
49 |
|
|
# define USING_UV_SHARED 1 |
50 |
|
|
#endif |
51 |
|
|
|
52 |
|
|
// This should be defined in make system. |
53 |
|
|
// See issue https://github.com/nodejs/node-v0.x-archive/issues/1236 |
54 |
|
|
#if defined(__MINGW32__) || defined(_MSC_VER) |
55 |
|
|
#ifndef _WIN32_WINNT |
56 |
|
|
# define _WIN32_WINNT 0x0600 // Windows Server 2008 |
57 |
|
|
#endif |
58 |
|
|
|
59 |
|
|
#ifndef NOMINMAX |
60 |
|
|
# define NOMINMAX |
61 |
|
|
#endif |
62 |
|
|
|
63 |
|
|
#endif |
64 |
|
|
|
65 |
|
|
#if defined(_MSC_VER) |
66 |
|
|
#define PATH_MAX MAX_PATH |
67 |
|
|
#endif |
68 |
|
|
|
69 |
|
|
#ifdef _WIN32 |
70 |
|
|
# define SIGKILL 9 |
71 |
|
|
#endif |
72 |
|
|
|
73 |
|
|
#include "v8.h" // NOLINT(build/include_order) |
74 |
|
|
|
75 |
|
|
#include "v8-platform.h" // NOLINT(build/include_order) |
76 |
|
|
#include "node_version.h" // NODE_MODULE_VERSION |
77 |
|
|
|
78 |
|
|
#include <memory> |
79 |
|
|
#include <functional> |
80 |
|
|
|
81 |
|
|
// We cannot use __POSIX__ in this header because that's only defined when |
82 |
|
|
// building Node.js. |
83 |
|
|
#ifndef _WIN32 |
84 |
|
|
#include <signal.h> |
85 |
|
|
#endif // _WIN32 |
86 |
|
|
|
87 |
|
|
#define NODE_MAKE_VERSION(major, minor, patch) \ |
88 |
|
|
((major) * 0x1000 + (minor) * 0x100 + (patch)) |
89 |
|
|
|
90 |
|
|
#ifdef __clang__ |
91 |
|
|
# define NODE_CLANG_AT_LEAST(major, minor, patch) \ |
92 |
|
|
(NODE_MAKE_VERSION(major, minor, patch) <= \ |
93 |
|
|
NODE_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)) |
94 |
|
|
#else |
95 |
|
|
# define NODE_CLANG_AT_LEAST(major, minor, patch) (0) |
96 |
|
|
#endif |
97 |
|
|
|
98 |
|
|
#ifdef __GNUC__ |
99 |
|
|
# define NODE_GNUC_AT_LEAST(major, minor, patch) \ |
100 |
|
|
(NODE_MAKE_VERSION(major, minor, patch) <= \ |
101 |
|
|
NODE_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)) |
102 |
|
|
#else |
103 |
|
|
# define NODE_GNUC_AT_LEAST(major, minor, patch) (0) |
104 |
|
|
#endif |
105 |
|
|
|
106 |
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
107 |
|
|
# define NODE_DEPRECATED(message, declarator) declarator |
108 |
|
|
#else // NODE_WANT_INTERNALS |
109 |
|
|
# if NODE_CLANG_AT_LEAST(2, 9, 0) || NODE_GNUC_AT_LEAST(4, 5, 0) |
110 |
|
|
# define NODE_DEPRECATED(message, declarator) \ |
111 |
|
|
__attribute__((deprecated(message))) declarator |
112 |
|
|
# elif defined(_MSC_VER) |
113 |
|
|
# define NODE_DEPRECATED(message, declarator) \ |
114 |
|
|
__declspec(deprecated) declarator |
115 |
|
|
# else |
116 |
|
|
# define NODE_DEPRECATED(message, declarator) declarator |
117 |
|
|
# endif |
118 |
|
|
#endif |
119 |
|
|
|
120 |
|
|
// Forward-declare libuv loop |
121 |
|
|
struct uv_loop_s; |
122 |
|
|
|
123 |
|
|
struct napi_module; |
124 |
|
|
|
125 |
|
|
// Forward-declare these functions now to stop MSVS from becoming |
126 |
|
|
// terminally confused when it's done in node_internals.h |
127 |
|
|
namespace node { |
128 |
|
|
|
129 |
|
|
namespace tracing { |
130 |
|
|
|
131 |
|
|
class TracingController; |
132 |
|
|
|
133 |
|
|
} |
134 |
|
|
|
135 |
|
|
NODE_EXTERN v8::Local<v8::Value> ErrnoException(v8::Isolate* isolate, |
136 |
|
|
int errorno, |
137 |
|
|
const char* syscall = nullptr, |
138 |
|
|
const char* message = nullptr, |
139 |
|
|
const char* path = nullptr); |
140 |
|
|
NODE_EXTERN v8::Local<v8::Value> UVException(v8::Isolate* isolate, |
141 |
|
|
int errorno, |
142 |
|
|
const char* syscall = nullptr, |
143 |
|
|
const char* message = nullptr, |
144 |
|
|
const char* path = nullptr, |
145 |
|
|
const char* dest = nullptr); |
146 |
|
|
|
147 |
|
|
NODE_DEPRECATED("Use ErrnoException(isolate, ...)", |
148 |
|
|
inline v8::Local<v8::Value> ErrnoException( |
149 |
|
|
int errorno, |
150 |
|
|
const char* syscall = nullptr, |
151 |
|
|
const char* message = nullptr, |
152 |
|
|
const char* path = nullptr) { |
153 |
|
|
return ErrnoException(v8::Isolate::GetCurrent(), |
154 |
|
|
errorno, |
155 |
|
|
syscall, |
156 |
|
|
message, |
157 |
|
|
path); |
158 |
|
|
}) |
159 |
|
|
|
160 |
|
|
NODE_DEPRECATED("Use UVException(isolate, ...)", |
161 |
|
|
inline v8::Local<v8::Value> UVException(int errorno, |
162 |
|
|
const char* syscall = nullptr, |
163 |
|
|
const char* message = nullptr, |
164 |
|
|
const char* path = nullptr) { |
165 |
|
|
return UVException(v8::Isolate::GetCurrent(), |
166 |
|
|
errorno, |
167 |
|
|
syscall, |
168 |
|
|
message, |
169 |
|
|
path); |
170 |
|
|
}) |
171 |
|
|
|
172 |
|
|
/* |
173 |
|
|
* These methods need to be called in a HandleScope. |
174 |
|
|
* |
175 |
|
|
* It is preferred that you use the `MakeCallback` overloads taking |
176 |
|
|
* `async_context` arguments. |
177 |
|
|
*/ |
178 |
|
|
|
179 |
|
|
NODE_DEPRECATED("Use MakeCallback(..., async_context)", |
180 |
|
|
NODE_EXTERN v8::Local<v8::Value> MakeCallback( |
181 |
|
|
v8::Isolate* isolate, |
182 |
|
|
v8::Local<v8::Object> recv, |
183 |
|
|
const char* method, |
184 |
|
|
int argc, |
185 |
|
|
v8::Local<v8::Value>* argv)); |
186 |
|
|
NODE_DEPRECATED("Use MakeCallback(..., async_context)", |
187 |
|
|
NODE_EXTERN v8::Local<v8::Value> MakeCallback( |
188 |
|
|
v8::Isolate* isolate, |
189 |
|
|
v8::Local<v8::Object> recv, |
190 |
|
|
v8::Local<v8::String> symbol, |
191 |
|
|
int argc, |
192 |
|
|
v8::Local<v8::Value>* argv)); |
193 |
|
|
NODE_DEPRECATED("Use MakeCallback(..., async_context)", |
194 |
|
|
NODE_EXTERN v8::Local<v8::Value> MakeCallback( |
195 |
|
|
v8::Isolate* isolate, |
196 |
|
|
v8::Local<v8::Object> recv, |
197 |
|
|
v8::Local<v8::Function> callback, |
198 |
|
|
int argc, |
199 |
|
|
v8::Local<v8::Value>* argv)); |
200 |
|
|
|
201 |
|
|
} // namespace node |
202 |
|
|
|
203 |
|
|
#include <cassert> |
204 |
|
|
#include <cstdint> |
205 |
|
|
|
206 |
|
|
#ifndef NODE_STRINGIFY |
207 |
|
|
# define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) |
208 |
|
|
# define NODE_STRINGIFY_HELPER(n) #n |
209 |
|
|
#endif |
210 |
|
|
|
211 |
|
|
#ifdef _WIN32 |
212 |
|
|
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) |
213 |
|
|
typedef intptr_t ssize_t; |
214 |
|
|
# define _SSIZE_T_ |
215 |
|
|
# define _SSIZE_T_DEFINED |
216 |
|
|
#endif |
217 |
|
|
#else // !_WIN32 |
218 |
|
|
# include <sys/types.h> // size_t, ssize_t |
219 |
|
|
#endif // _WIN32 |
220 |
|
|
|
221 |
|
|
|
222 |
|
|
namespace node { |
223 |
|
|
|
224 |
|
|
class IsolateData; |
225 |
|
|
class Environment; |
226 |
|
|
|
227 |
|
|
namespace ProcessFlags { |
228 |
|
|
enum Flags : uint64_t { |
229 |
|
|
kNoFlags = 0, |
230 |
|
|
// Enable stdio inheritance, which is disabled by default. |
231 |
|
|
kEnableStdioInheritance = 1 << 0, |
232 |
|
|
// Disable reading the NODE_OPTIONS environment variable. |
233 |
|
|
kDisableNodeOptionsEnv = 1 << 1, |
234 |
|
|
// Do not parse CLI options. |
235 |
|
|
kDisableCLIOptions = 1 << 2, |
236 |
|
|
// Do not initialize ICU. |
237 |
|
|
kNoICU = 1 << 3, |
238 |
|
|
}; |
239 |
|
|
} // namespace ProcessFlags |
240 |
|
|
|
241 |
|
|
// TODO(addaleax): Officially deprecate this and replace it with something |
242 |
|
|
// better suited for a public embedder API. |
243 |
|
|
NODE_EXTERN int Start(int argc, char* argv[]); |
244 |
|
|
|
245 |
|
|
// Tear down Node.js while it is running (there are active handles |
246 |
|
|
// in the loop and / or actively executing JavaScript code). |
247 |
|
|
NODE_EXTERN int Stop(Environment* env); |
248 |
|
|
|
249 |
|
|
// Set up per-process state needed to run Node.js. This will consume arguments |
250 |
|
|
// from argv, fill exec_argv, and possibly add errors resulting from parsing |
251 |
|
|
// the arguments to `errors`. The return value is a suggested exit code for the |
252 |
|
|
// program; If it is 0, then initializing Node.js succeeded. |
253 |
|
|
NODE_EXTERN int InitializeNodeWithArgs( |
254 |
|
|
std::vector<std::string>* argv, |
255 |
|
|
std::vector<std::string>* exec_argv, |
256 |
|
|
std::vector<std::string>* errors); |
257 |
|
|
// TODO(zcbenz): Turn above overloaded version into below's default argument. |
258 |
|
|
NODE_EXTERN int InitializeNodeWithArgs( |
259 |
|
|
std::vector<std::string>* argv, |
260 |
|
|
std::vector<std::string>* exec_argv, |
261 |
|
|
std::vector<std::string>* errors, |
262 |
|
|
ProcessFlags::Flags flags); |
263 |
|
|
|
264 |
|
|
enum OptionEnvvarSettings { |
265 |
|
|
kAllowedInEnvironment, |
266 |
|
|
kDisallowedInEnvironment |
267 |
|
|
}; |
268 |
|
|
|
269 |
|
|
NODE_EXTERN int ProcessGlobalArgs(std::vector<std::string>* args, |
270 |
|
|
std::vector<std::string>* exec_args, |
271 |
|
|
std::vector<std::string>* errors, |
272 |
|
|
OptionEnvvarSettings settings); |
273 |
|
|
|
274 |
|
|
class NodeArrayBufferAllocator; |
275 |
|
|
|
276 |
|
|
// An ArrayBuffer::Allocator class with some Node.js-specific tweaks. If you do |
277 |
|
|
// not have to use another allocator, using this class is recommended: |
278 |
|
|
// - It supports Buffer.allocUnsafe() and Buffer.allocUnsafeSlow() with |
279 |
|
|
// uninitialized memory. |
280 |
|
|
// - It supports transferring, rather than copying, ArrayBuffers when using |
281 |
|
|
// MessagePorts. |
282 |
|
|
class NODE_EXTERN ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { |
283 |
|
|
public: |
284 |
|
|
// If `always_debug` is true, create an ArrayBuffer::Allocator instance |
285 |
|
|
// that performs additional integrity checks (e.g. make sure that only memory |
286 |
|
|
// that was allocated by the it is also freed by it). |
287 |
|
|
// This can also be set using the --debug-arraybuffer-allocations flag. |
288 |
|
|
static std::unique_ptr<ArrayBufferAllocator> Create( |
289 |
|
|
bool always_debug = false); |
290 |
|
|
|
291 |
|
|
private: |
292 |
|
|
virtual NodeArrayBufferAllocator* GetImpl() = 0; |
293 |
|
|
|
294 |
|
|
friend class IsolateData; |
295 |
|
|
}; |
296 |
|
|
|
297 |
|
|
// Legacy equivalents for ArrayBufferAllocator::Create(). |
298 |
|
|
NODE_EXTERN ArrayBufferAllocator* CreateArrayBufferAllocator(); |
299 |
|
|
NODE_EXTERN void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator); |
300 |
|
|
|
301 |
|
|
class NODE_EXTERN IsolatePlatformDelegate { |
302 |
|
|
public: |
303 |
|
|
virtual std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner() = 0; |
304 |
|
|
virtual bool IdleTasksEnabled() = 0; |
305 |
|
|
}; |
306 |
|
|
|
307 |
|
|
class NODE_EXTERN MultiIsolatePlatform : public v8::Platform { |
308 |
|
|
public: |
309 |
|
10374 |
~MultiIsolatePlatform() override = default; |
310 |
|
|
// Returns true if work was dispatched or executed. New tasks that are |
311 |
|
|
// posted during flushing of the queue are postponed until the next |
312 |
|
|
// flushing. |
313 |
|
|
virtual bool FlushForegroundTasks(v8::Isolate* isolate) = 0; |
314 |
|
|
virtual void DrainTasks(v8::Isolate* isolate) = 0; |
315 |
|
|
|
316 |
|
|
// This needs to be called between the calls to `Isolate::Allocate()` and |
317 |
|
|
// `Isolate::Initialize()`, so that initialization can already start |
318 |
|
|
// using the platform. |
319 |
|
|
// When using `NewIsolate()`, this is taken care of by that function. |
320 |
|
|
// This function may only be called once per `Isolate`. |
321 |
|
|
virtual void RegisterIsolate(v8::Isolate* isolate, |
322 |
|
|
struct uv_loop_s* loop) = 0; |
323 |
|
|
// This method can be used when an application handles task scheduling on its |
324 |
|
|
// own through `IsolatePlatformDelegate`. Upon registering an isolate with |
325 |
|
|
// this overload any other method in this class with the exception of |
326 |
|
|
// `UnregisterIsolate` *must not* be used on that isolate. |
327 |
|
|
virtual void RegisterIsolate(v8::Isolate* isolate, |
328 |
|
|
IsolatePlatformDelegate* delegate) = 0; |
329 |
|
|
|
330 |
|
|
// This function may only be called once per `Isolate`, and discard any |
331 |
|
|
// pending delayed tasks scheduled for that isolate. |
332 |
|
|
// This needs to be called right before calling `Isolate::Dispose()`. |
333 |
|
|
virtual void UnregisterIsolate(v8::Isolate* isolate) = 0; |
334 |
|
|
|
335 |
|
|
// The platform should call the passed function once all state associated |
336 |
|
|
// with the given isolate has been cleaned up. This can, but does not have to, |
337 |
|
|
// happen asynchronously. |
338 |
|
|
virtual void AddIsolateFinishedCallback(v8::Isolate* isolate, |
339 |
|
|
void (*callback)(void*), |
340 |
|
|
void* data) = 0; |
341 |
|
|
|
342 |
|
|
static std::unique_ptr<MultiIsolatePlatform> Create( |
343 |
|
|
int thread_pool_size, |
344 |
|
|
v8::TracingController* tracing_controller = nullptr, |
345 |
|
|
v8::PageAllocator* page_allocator = nullptr); |
346 |
|
|
}; |
347 |
|
|
|
348 |
|
|
enum IsolateSettingsFlags { |
349 |
|
|
MESSAGE_LISTENER_WITH_ERROR_LEVEL = 1 << 0, |
350 |
|
|
DETAILED_SOURCE_POSITIONS_FOR_PROFILING = 1 << 1, |
351 |
|
|
SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK = 1 << 2, |
352 |
|
|
SHOULD_NOT_SET_PREPARE_STACK_TRACE_CALLBACK = 1 << 3 |
353 |
|
|
}; |
354 |
|
|
|
355 |
|
|
struct IsolateSettings { |
356 |
|
|
uint64_t flags = MESSAGE_LISTENER_WITH_ERROR_LEVEL | |
357 |
|
|
DETAILED_SOURCE_POSITIONS_FOR_PROFILING; |
358 |
|
|
v8::MicrotasksPolicy policy = v8::MicrotasksPolicy::kExplicit; |
359 |
|
|
|
360 |
|
|
// Error handling callbacks |
361 |
|
|
v8::Isolate::AbortOnUncaughtExceptionCallback |
362 |
|
|
should_abort_on_uncaught_exception_callback = nullptr; |
363 |
|
|
v8::FatalErrorCallback fatal_error_callback = nullptr; |
364 |
|
|
v8::PrepareStackTraceCallback prepare_stack_trace_callback = nullptr; |
365 |
|
|
|
366 |
|
|
// Miscellaneous callbacks |
367 |
|
|
v8::PromiseRejectCallback promise_reject_callback = nullptr; |
368 |
|
|
v8::AllowWasmCodeGenerationCallback |
369 |
|
|
allow_wasm_code_generation_callback = nullptr; |
370 |
|
|
}; |
371 |
|
|
|
372 |
|
|
// Overriding IsolateSettings may produce unexpected behavior |
373 |
|
|
// in Node.js core functionality, so proceed at your own risk. |
374 |
|
|
NODE_EXTERN void SetIsolateUpForNode(v8::Isolate* isolate, |
375 |
|
|
const IsolateSettings& settings); |
376 |
|
|
|
377 |
|
|
// Set a number of callbacks for the `isolate`, in particular the Node.js |
378 |
|
|
// uncaught exception listener. |
379 |
|
|
NODE_EXTERN void SetIsolateUpForNode(v8::Isolate* isolate); |
380 |
|
|
|
381 |
|
|
// Creates a new isolate with Node.js-specific settings. |
382 |
|
|
// This is a convenience method equivalent to using SetIsolateCreateParams(), |
383 |
|
|
// Isolate::Allocate(), MultiIsolatePlatform::RegisterIsolate(), |
384 |
|
|
// Isolate::Initialize(), and SetIsolateUpForNode(). |
385 |
|
|
NODE_EXTERN v8::Isolate* NewIsolate(ArrayBufferAllocator* allocator, |
386 |
|
|
struct uv_loop_s* event_loop, |
387 |
|
|
MultiIsolatePlatform* platform = nullptr); |
388 |
|
|
NODE_EXTERN v8::Isolate* NewIsolate( |
389 |
|
|
std::shared_ptr<ArrayBufferAllocator> allocator, |
390 |
|
|
struct uv_loop_s* event_loop, |
391 |
|
|
MultiIsolatePlatform* platform); |
392 |
|
|
|
393 |
|
|
// Creates a new context with Node.js-specific tweaks. |
394 |
|
|
NODE_EXTERN v8::Local<v8::Context> NewContext( |
395 |
|
|
v8::Isolate* isolate, |
396 |
|
|
v8::Local<v8::ObjectTemplate> object_template = |
397 |
|
|
v8::Local<v8::ObjectTemplate>()); |
398 |
|
|
|
399 |
|
|
// Runs Node.js-specific tweaks on an already constructed context |
400 |
|
|
// Return value indicates success of operation |
401 |
|
|
NODE_EXTERN v8::Maybe<bool> InitializeContext(v8::Local<v8::Context> context); |
402 |
|
|
|
403 |
|
|
// If `platform` is passed, it will be used to register new Worker instances. |
404 |
|
|
// It can be `nullptr`, in which case creating new Workers inside of |
405 |
|
|
// Environments that use this `IsolateData` will not work. |
406 |
|
|
NODE_EXTERN IsolateData* CreateIsolateData( |
407 |
|
|
v8::Isolate* isolate, |
408 |
|
|
struct uv_loop_s* loop, |
409 |
|
|
MultiIsolatePlatform* platform = nullptr, |
410 |
|
|
ArrayBufferAllocator* allocator = nullptr); |
411 |
|
|
NODE_EXTERN void FreeIsolateData(IsolateData* isolate_data); |
412 |
|
|
|
413 |
|
|
struct ThreadId { |
414 |
|
|
uint64_t id = static_cast<uint64_t>(-1); |
415 |
|
|
}; |
416 |
|
|
NODE_EXTERN ThreadId AllocateEnvironmentThreadId(); |
417 |
|
|
|
418 |
|
|
namespace EnvironmentFlags { |
419 |
|
|
enum Flags : uint64_t { |
420 |
|
|
kNoFlags = 0, |
421 |
|
|
// Use the default behaviour for Node.js instances. |
422 |
|
|
kDefaultFlags = 1 << 0, |
423 |
|
|
// Controls whether this Environment is allowed to affect per-process state |
424 |
|
|
// (e.g. cwd, process title, uid, etc.). |
425 |
|
|
// This is set when using kDefaultFlags. |
426 |
|
|
kOwnsProcessState = 1 << 1, |
427 |
|
|
// Set if this Environment instance is associated with the global inspector |
428 |
|
|
// handling code (i.e. listening on SIGUSR1). |
429 |
|
|
// This is set when using kDefaultFlags. |
430 |
|
|
kOwnsInspector = 1 << 2, |
431 |
|
|
// Set if Node.js should not run its own esm loader. This is needed by some |
432 |
|
|
// embedders, because it's possible for the Node.js esm loader to conflict |
433 |
|
|
// with another one in an embedder environment, e.g. Blink's in Chromium. |
434 |
|
|
kNoRegisterESMLoader = 1 << 3, |
435 |
|
|
// Set this flag to make Node.js track "raw" file descriptors, i.e. managed |
436 |
|
|
// by fs.open() and fs.close(), and close them during FreeEnvironment(). |
437 |
|
|
kTrackUnmanagedFds = 1 << 4, |
438 |
|
|
// Set this flag to force hiding console windows when spawning child |
439 |
|
|
// processes. This is usually used when embedding Node.js in GUI programs on |
440 |
|
|
// Windows. |
441 |
|
|
kHideConsoleWindows = 1 << 5, |
442 |
|
|
// Set this flag to disable loading native addons via `process.dlopen`. |
443 |
|
|
// This environment flag is especially important for worker threads |
444 |
|
|
// so that a worker thread can't load a native addon even if `execArgv` |
445 |
|
|
// is overwritten and `--no-addons` is not specified but was specified |
446 |
|
|
// for this Environment instance. |
447 |
|
|
kNoNativeAddons = 1 << 6, |
448 |
|
|
// Set this flag to disable searching modules from global paths like |
449 |
|
|
// $HOME/.node_modules and $NODE_PATH. This is used by standalone apps that |
450 |
|
|
// do not expect to have their behaviors changed because of globally |
451 |
|
|
// installed modules. |
452 |
|
|
kNoGlobalSearchPaths = 1 << 7, |
453 |
|
|
// Do not export browser globals like setTimeout, console, etc. |
454 |
|
|
kNoBrowserGlobals = 1 << 8, |
455 |
|
|
// Controls whether or not the Environment should call V8Inspector::create(). |
456 |
|
|
// This control is needed by embedders who may not want to initialize the V8 |
457 |
|
|
// inspector in situations where one has already been created, |
458 |
|
|
// e.g. Blink's in Chromium. |
459 |
|
|
kNoCreateInspector = 1 << 9 |
460 |
|
|
}; |
461 |
|
|
} // namespace EnvironmentFlags |
462 |
|
|
|
463 |
|
|
struct InspectorParentHandle { |
464 |
|
|
virtual ~InspectorParentHandle(); |
465 |
|
|
}; |
466 |
|
|
|
467 |
|
|
// TODO(addaleax): Maybe move per-Environment options parsing here. |
468 |
|
|
// Returns nullptr when the Environment cannot be created e.g. there are |
469 |
|
|
// pending JavaScript exceptions. |
470 |
|
|
NODE_EXTERN Environment* CreateEnvironment( |
471 |
|
|
IsolateData* isolate_data, |
472 |
|
|
v8::Local<v8::Context> context, |
473 |
|
|
const std::vector<std::string>& args, |
474 |
|
|
const std::vector<std::string>& exec_args, |
475 |
|
|
EnvironmentFlags::Flags flags = EnvironmentFlags::kDefaultFlags, |
476 |
|
|
ThreadId thread_id = {} /* allocates a thread id automatically */, |
477 |
|
|
std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {}); |
478 |
|
|
|
479 |
|
|
// Returns a handle that can be passed to `LoadEnvironment()`, making the |
480 |
|
|
// child Environment accessible to the inspector as if it were a Node.js Worker. |
481 |
|
|
// `child_thread_id` can be created using `AllocateEnvironmentThreadId()` |
482 |
|
|
// and then later passed on to `CreateEnvironment()` to create the child |
483 |
|
|
// Environment, together with the inspector handle. |
484 |
|
|
// This method should not be called while the parent Environment is active |
485 |
|
|
// on another thread. |
486 |
|
|
NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle( |
487 |
|
|
Environment* parent_env, |
488 |
|
|
ThreadId child_thread_id, |
489 |
|
|
const char* child_url); |
490 |
|
|
|
491 |
|
|
struct StartExecutionCallbackInfo { |
492 |
|
|
v8::Local<v8::Object> process_object; |
493 |
|
|
v8::Local<v8::Function> native_require; |
494 |
|
|
}; |
495 |
|
|
|
496 |
|
|
using StartExecutionCallback = |
497 |
|
|
std::function<v8::MaybeLocal<v8::Value>(const StartExecutionCallbackInfo&)>; |
498 |
|
|
|
499 |
|
|
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment( |
500 |
|
|
Environment* env, |
501 |
|
|
StartExecutionCallback cb); |
502 |
|
|
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment( |
503 |
|
|
Environment* env, |
504 |
|
|
const char* main_script_source_utf8); |
505 |
|
|
NODE_EXTERN void FreeEnvironment(Environment* env); |
506 |
|
|
|
507 |
|
|
// Set a callback that is called when process.exit() is called from JS, |
508 |
|
|
// overriding the default handler. |
509 |
|
|
// It receives the Environment* instance and the exit code as arguments. |
510 |
|
|
// This could e.g. call Stop(env); in order to terminate execution and stop |
511 |
|
|
// the event loop. |
512 |
|
|
// The default handler disposes of the global V8 platform instance, if one is |
513 |
|
|
// being used, and calls exit(). |
514 |
|
|
NODE_EXTERN void SetProcessExitHandler( |
515 |
|
|
Environment* env, |
516 |
|
|
std::function<void(Environment*, int)>&& handler); |
517 |
|
|
NODE_EXTERN void DefaultProcessExitHandler(Environment* env, int exit_code); |
518 |
|
|
|
519 |
|
|
// This may return nullptr if context is not associated with a Node instance. |
520 |
|
|
NODE_EXTERN Environment* GetCurrentEnvironment(v8::Local<v8::Context> context); |
521 |
|
|
NODE_EXTERN IsolateData* GetEnvironmentIsolateData(Environment* env); |
522 |
|
|
NODE_EXTERN ArrayBufferAllocator* GetArrayBufferAllocator(IsolateData* data); |
523 |
|
|
|
524 |
|
|
NODE_EXTERN void OnFatalError(const char* location, const char* message); |
525 |
|
|
NODE_EXTERN void PromiseRejectCallback(v8::PromiseRejectMessage message); |
526 |
|
|
NODE_EXTERN bool AllowWasmCodeGenerationCallback(v8::Local<v8::Context> context, |
527 |
|
|
v8::Local<v8::String>); |
528 |
|
|
NODE_EXTERN bool ShouldAbortOnUncaughtException(v8::Isolate* isolate); |
529 |
|
|
NODE_EXTERN v8::MaybeLocal<v8::Value> PrepareStackTraceCallback( |
530 |
|
|
v8::Local<v8::Context> context, |
531 |
|
|
v8::Local<v8::Value> exception, |
532 |
|
|
v8::Local<v8::Array> trace); |
533 |
|
|
|
534 |
|
|
// This returns the MultiIsolatePlatform used for an Environment or IsolateData |
535 |
|
|
// instance, if one exists. |
536 |
|
|
NODE_EXTERN MultiIsolatePlatform* GetMultiIsolatePlatform(Environment* env); |
537 |
|
|
NODE_EXTERN MultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env); |
538 |
|
|
|
539 |
|
|
NODE_DEPRECATED("Use MultiIsolatePlatform::Create() instead", |
540 |
|
|
NODE_EXTERN MultiIsolatePlatform* CreatePlatform( |
541 |
|
|
int thread_pool_size, |
542 |
|
|
v8::TracingController* tracing_controller)); |
543 |
|
|
NODE_DEPRECATED("Use MultiIsolatePlatform::Create() instead", |
544 |
|
|
NODE_EXTERN void FreePlatform(MultiIsolatePlatform* platform)); |
545 |
|
|
|
546 |
|
|
// Get/set the currently active tracing controller. Using CreatePlatform() |
547 |
|
|
// will implicitly set this by default. This is global and should be initialized |
548 |
|
|
// along with the v8::Platform instance that is being used. `controller` |
549 |
|
|
// is allowed to be `nullptr`. |
550 |
|
|
// This is used for tracing events from Node.js itself. V8 uses the tracing |
551 |
|
|
// controller returned from the active `v8::Platform` instance. |
552 |
|
|
NODE_EXTERN v8::TracingController* GetTracingController(); |
553 |
|
|
NODE_EXTERN void SetTracingController(v8::TracingController* controller); |
554 |
|
|
|
555 |
|
|
// Run `process.emit('beforeExit')` as it would usually happen when Node.js is |
556 |
|
|
// run in standalone mode. |
557 |
|
|
NODE_EXTERN v8::Maybe<bool> EmitProcessBeforeExit(Environment* env); |
558 |
|
|
NODE_DEPRECATED("Use Maybe version (EmitProcessBeforeExit) instead", |
559 |
|
|
NODE_EXTERN void EmitBeforeExit(Environment* env)); |
560 |
|
|
// Run `process.emit('exit')` as it would usually happen when Node.js is run |
561 |
|
|
// in standalone mode. The return value corresponds to the exit code. |
562 |
|
|
NODE_EXTERN v8::Maybe<int> EmitProcessExit(Environment* env); |
563 |
|
|
NODE_DEPRECATED("Use Maybe version (EmitProcessExit) instead", |
564 |
|
|
NODE_EXTERN int EmitExit(Environment* env)); |
565 |
|
|
|
566 |
|
|
// Runs hooks added through `AtExit()`. This is part of `FreeEnvironment()`, |
567 |
|
|
// so calling it manually is typically not necessary. |
568 |
|
|
NODE_EXTERN void RunAtExit(Environment* env); |
569 |
|
|
|
570 |
|
|
// This may return nullptr if the current v8::Context is not associated |
571 |
|
|
// with a Node instance. |
572 |
|
|
NODE_EXTERN struct uv_loop_s* GetCurrentEventLoop(v8::Isolate* isolate); |
573 |
|
|
|
574 |
|
|
// Runs the main loop for a given Environment. This roughly performs the |
575 |
|
|
// following steps: |
576 |
|
|
// 1. Call uv_run() on the event loop until it is drained. |
577 |
|
|
// 2. Call platform->DrainTasks() on the associated platform/isolate. |
578 |
|
|
// 3. If the event loop is alive again, go to Step 1. |
579 |
|
|
// 4. Call EmitProcessBeforeExit(). |
580 |
|
|
// 5. If the event loop is alive again, go to Step 1. |
581 |
|
|
// 6. Call EmitProcessExit() and forward the return value. |
582 |
|
|
// If at any point node::Stop() is called, the function will attempt to return |
583 |
|
|
// as soon as possible, returning an empty `Maybe`. |
584 |
|
|
// This function only works if `env` has an associated `MultiIsolatePlatform`. |
585 |
|
|
NODE_EXTERN v8::Maybe<int> SpinEventLoop(Environment* env); |
586 |
|
|
|
587 |
|
|
class NODE_EXTERN CommonEnvironmentSetup { |
588 |
|
|
public: |
589 |
|
|
~CommonEnvironmentSetup(); |
590 |
|
|
|
591 |
|
|
// Create a new CommonEnvironmentSetup, that is, a group of objects that |
592 |
|
|
// together form the typical setup for a single Node.js Environment instance. |
593 |
|
|
// If any error occurs, `*errors` will be populated and the returned pointer |
594 |
|
|
// will be empty. |
595 |
|
|
// env_args will be passed through as arguments to CreateEnvironment(), after |
596 |
|
|
// `isolate_data` and `context`. |
597 |
|
|
template <typename... EnvironmentArgs> |
598 |
|
|
static std::unique_ptr<CommonEnvironmentSetup> Create( |
599 |
|
|
MultiIsolatePlatform* platform, |
600 |
|
|
std::vector<std::string>* errors, |
601 |
|
|
EnvironmentArgs&&... env_args); |
602 |
|
|
|
603 |
|
|
struct uv_loop_s* event_loop() const; |
604 |
|
|
std::shared_ptr<ArrayBufferAllocator> array_buffer_allocator() const; |
605 |
|
|
v8::Isolate* isolate() const; |
606 |
|
|
IsolateData* isolate_data() const; |
607 |
|
|
Environment* env() const; |
608 |
|
|
v8::Local<v8::Context> context() const; |
609 |
|
|
|
610 |
|
|
CommonEnvironmentSetup(const CommonEnvironmentSetup&) = delete; |
611 |
|
|
CommonEnvironmentSetup& operator=(const CommonEnvironmentSetup&) = delete; |
612 |
|
|
CommonEnvironmentSetup(CommonEnvironmentSetup&&) = delete; |
613 |
|
|
CommonEnvironmentSetup& operator=(CommonEnvironmentSetup&&) = delete; |
614 |
|
|
|
615 |
|
|
private: |
616 |
|
|
struct Impl; |
617 |
|
|
Impl* impl_; |
618 |
|
|
CommonEnvironmentSetup( |
619 |
|
|
MultiIsolatePlatform*, |
620 |
|
|
std::vector<std::string>*, |
621 |
|
|
std::function<Environment*(const CommonEnvironmentSetup*)>); |
622 |
|
|
}; |
623 |
|
|
|
624 |
|
|
// Implementation for CommonEnvironmentSetup::Create |
625 |
|
|
template <typename... EnvironmentArgs> |
626 |
|
7 |
std::unique_ptr<CommonEnvironmentSetup> CommonEnvironmentSetup::Create( |
627 |
|
|
MultiIsolatePlatform* platform, |
628 |
|
|
std::vector<std::string>* errors, |
629 |
|
|
EnvironmentArgs&&... env_args) { |
630 |
|
7 |
auto ret = std::unique_ptr<CommonEnvironmentSetup>(new CommonEnvironmentSetup( |
631 |
|
|
platform, errors, |
632 |
|
7 |
[&](const CommonEnvironmentSetup* setup) -> Environment* { |
633 |
|
21 |
return CreateEnvironment( |
634 |
|
|
setup->isolate_data(), setup->context(), |
635 |
|
14 |
std::forward<EnvironmentArgs>(env_args)...); |
636 |
|
|
})); |
637 |
✗✓ |
7 |
if (!errors->empty()) ret.reset(); |
638 |
|
7 |
return ret; |
639 |
|
|
} |
640 |
|
|
|
641 |
|
|
/* Converts a unixtime to V8 Date */ |
642 |
|
|
NODE_DEPRECATED("Use v8::Date::New() directly", |
643 |
|
|
inline v8::Local<v8::Value> NODE_UNIXTIME_V8(double time) { |
644 |
|
|
return v8::Date::New( |
645 |
|
|
v8::Isolate::GetCurrent()->GetCurrentContext(), |
646 |
|
|
1000 * time) |
647 |
|
|
.ToLocalChecked(); |
648 |
|
|
}) |
649 |
|
|
#define NODE_UNIXTIME_V8 node::NODE_UNIXTIME_V8 |
650 |
|
|
NODE_DEPRECATED("Use v8::Date::ValueOf() directly", |
651 |
|
|
inline double NODE_V8_UNIXTIME(v8::Local<v8::Date> date) { |
652 |
|
|
return date->ValueOf() / 1000; |
653 |
|
|
}) |
654 |
|
|
#define NODE_V8_UNIXTIME node::NODE_V8_UNIXTIME |
655 |
|
|
|
656 |
|
|
#define NODE_DEFINE_CONSTANT(target, constant) \ |
657 |
|
|
do { \ |
658 |
|
|
v8::Isolate* isolate = target->GetIsolate(); \ |
659 |
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext(); \ |
660 |
|
|
v8::Local<v8::String> constant_name = \ |
661 |
|
|
v8::String::NewFromUtf8(isolate, #constant, \ |
662 |
|
|
v8::NewStringType::kInternalized).ToLocalChecked(); \ |
663 |
|
|
v8::Local<v8::Number> constant_value = \ |
664 |
|
|
v8::Number::New(isolate, static_cast<double>(constant)); \ |
665 |
|
|
v8::PropertyAttribute constant_attributes = \ |
666 |
|
|
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); \ |
667 |
|
|
(target)->DefineOwnProperty(context, \ |
668 |
|
|
constant_name, \ |
669 |
|
|
constant_value, \ |
670 |
|
|
constant_attributes).Check(); \ |
671 |
|
|
} \ |
672 |
|
|
while (0) |
673 |
|
|
|
674 |
|
|
#define NODE_DEFINE_HIDDEN_CONSTANT(target, constant) \ |
675 |
|
|
do { \ |
676 |
|
|
v8::Isolate* isolate = target->GetIsolate(); \ |
677 |
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext(); \ |
678 |
|
|
v8::Local<v8::String> constant_name = \ |
679 |
|
|
v8::String::NewFromUtf8(isolate, #constant, \ |
680 |
|
|
v8::NewStringType::kInternalized) \ |
681 |
|
|
.ToLocalChecked(); \ |
682 |
|
|
v8::Local<v8::Number> constant_value = \ |
683 |
|
|
v8::Number::New(isolate, static_cast<double>(constant)); \ |
684 |
|
|
v8::PropertyAttribute constant_attributes = \ |
685 |
|
|
static_cast<v8::PropertyAttribute>(v8::ReadOnly | \ |
686 |
|
|
v8::DontDelete | \ |
687 |
|
|
v8::DontEnum); \ |
688 |
|
|
(target)->DefineOwnProperty(context, \ |
689 |
|
|
constant_name, \ |
690 |
|
|
constant_value, \ |
691 |
|
|
constant_attributes).Check(); \ |
692 |
|
|
} \ |
693 |
|
|
while (0) |
694 |
|
|
|
695 |
|
|
// Used to be a macro, hence the uppercase name. |
696 |
|
|
inline void NODE_SET_METHOD(v8::Local<v8::Template> recv, |
697 |
|
|
const char* name, |
698 |
|
|
v8::FunctionCallback callback) { |
699 |
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
700 |
|
|
v8::HandleScope handle_scope(isolate); |
701 |
|
|
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate, |
702 |
|
|
callback); |
703 |
|
|
v8::Local<v8::String> fn_name = v8::String::NewFromUtf8(isolate, name, |
704 |
|
|
v8::NewStringType::kInternalized).ToLocalChecked(); |
705 |
|
|
t->SetClassName(fn_name); |
706 |
|
|
recv->Set(fn_name, t); |
707 |
|
|
} |
708 |
|
|
|
709 |
|
|
// Used to be a macro, hence the uppercase name. |
710 |
|
|
inline void NODE_SET_METHOD(v8::Local<v8::Object> recv, |
711 |
|
|
const char* name, |
712 |
|
|
v8::FunctionCallback callback) { |
713 |
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
714 |
|
|
v8::HandleScope handle_scope(isolate); |
715 |
|
|
v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
716 |
|
|
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate, |
717 |
|
|
callback); |
718 |
|
|
v8::Local<v8::Function> fn = t->GetFunction(context).ToLocalChecked(); |
719 |
|
|
v8::Local<v8::String> fn_name = v8::String::NewFromUtf8(isolate, name, |
720 |
|
|
v8::NewStringType::kInternalized).ToLocalChecked(); |
721 |
|
|
fn->SetName(fn_name); |
722 |
|
|
recv->Set(context, fn_name, fn).Check(); |
723 |
|
|
} |
724 |
|
|
#define NODE_SET_METHOD node::NODE_SET_METHOD |
725 |
|
|
|
726 |
|
|
// Used to be a macro, hence the uppercase name. |
727 |
|
|
// Not a template because it only makes sense for FunctionTemplates. |
728 |
|
|
inline void NODE_SET_PROTOTYPE_METHOD(v8::Local<v8::FunctionTemplate> recv, |
729 |
|
|
const char* name, |
730 |
|
|
v8::FunctionCallback callback) { |
731 |
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
732 |
|
|
v8::HandleScope handle_scope(isolate); |
733 |
|
|
v8::Local<v8::Signature> s = v8::Signature::New(isolate, recv); |
734 |
|
|
v8::Local<v8::FunctionTemplate> t = |
735 |
|
|
v8::FunctionTemplate::New(isolate, callback, v8::Local<v8::Value>(), s); |
736 |
|
|
v8::Local<v8::String> fn_name = v8::String::NewFromUtf8(isolate, name, |
737 |
|
|
v8::NewStringType::kInternalized).ToLocalChecked(); |
738 |
|
|
t->SetClassName(fn_name); |
739 |
|
|
recv->PrototypeTemplate()->Set(fn_name, t); |
740 |
|
|
} |
741 |
|
|
#define NODE_SET_PROTOTYPE_METHOD node::NODE_SET_PROTOTYPE_METHOD |
742 |
|
|
|
743 |
|
|
// BINARY is a deprecated alias of LATIN1. |
744 |
|
|
// BASE64URL is not currently exposed to the JavaScript side. |
745 |
|
|
enum encoding { |
746 |
|
|
ASCII, |
747 |
|
|
UTF8, |
748 |
|
|
BASE64, |
749 |
|
|
UCS2, |
750 |
|
|
BINARY, |
751 |
|
|
HEX, |
752 |
|
|
BUFFER, |
753 |
|
|
BASE64URL, |
754 |
|
|
LATIN1 = BINARY |
755 |
|
|
}; |
756 |
|
|
|
757 |
|
|
NODE_EXTERN enum encoding ParseEncoding( |
758 |
|
|
v8::Isolate* isolate, |
759 |
|
|
v8::Local<v8::Value> encoding_v, |
760 |
|
|
enum encoding default_encoding = LATIN1); |
761 |
|
|
|
762 |
|
|
NODE_EXTERN void FatalException(v8::Isolate* isolate, |
763 |
|
|
const v8::TryCatch& try_catch); |
764 |
|
|
|
765 |
|
|
NODE_EXTERN v8::Local<v8::Value> Encode(v8::Isolate* isolate, |
766 |
|
|
const char* buf, |
767 |
|
|
size_t len, |
768 |
|
|
enum encoding encoding = LATIN1); |
769 |
|
|
|
770 |
|
|
// Warning: This reverses endianness on Big Endian platforms, even though the |
771 |
|
|
// signature using uint16_t implies that it should not. |
772 |
|
|
NODE_EXTERN v8::Local<v8::Value> Encode(v8::Isolate* isolate, |
773 |
|
|
const uint16_t* buf, |
774 |
|
|
size_t len); |
775 |
|
|
|
776 |
|
|
// Returns -1 if the handle was not valid for decoding |
777 |
|
|
NODE_EXTERN ssize_t DecodeBytes(v8::Isolate* isolate, |
778 |
|
|
v8::Local<v8::Value>, |
779 |
|
|
enum encoding encoding = LATIN1); |
780 |
|
|
// returns bytes written. |
781 |
|
|
NODE_EXTERN ssize_t DecodeWrite(v8::Isolate* isolate, |
782 |
|
|
char* buf, |
783 |
|
|
size_t buflen, |
784 |
|
|
v8::Local<v8::Value>, |
785 |
|
|
enum encoding encoding = LATIN1); |
786 |
|
|
#ifdef _WIN32 |
787 |
|
|
NODE_EXTERN v8::Local<v8::Value> WinapiErrnoException( |
788 |
|
|
v8::Isolate* isolate, |
789 |
|
|
int errorno, |
790 |
|
|
const char* syscall = nullptr, |
791 |
|
|
const char* msg = "", |
792 |
|
|
const char* path = nullptr); |
793 |
|
|
#endif |
794 |
|
|
|
795 |
|
|
const char* signo_string(int errorno); |
796 |
|
|
|
797 |
|
|
|
798 |
|
|
typedef void (*addon_register_func)( |
799 |
|
|
v8::Local<v8::Object> exports, |
800 |
|
|
v8::Local<v8::Value> module, |
801 |
|
|
void* priv); |
802 |
|
|
|
803 |
|
|
typedef void (*addon_context_register_func)( |
804 |
|
|
v8::Local<v8::Object> exports, |
805 |
|
|
v8::Local<v8::Value> module, |
806 |
|
|
v8::Local<v8::Context> context, |
807 |
|
|
void* priv); |
808 |
|
|
|
809 |
|
|
enum ModuleFlags { |
810 |
|
|
kLinked = 0x02 |
811 |
|
|
}; |
812 |
|
|
|
813 |
|
|
struct node_module { |
814 |
|
|
int nm_version; |
815 |
|
|
unsigned int nm_flags; |
816 |
|
|
void* nm_dso_handle; |
817 |
|
|
const char* nm_filename; |
818 |
|
|
node::addon_register_func nm_register_func; |
819 |
|
|
node::addon_context_register_func nm_context_register_func; |
820 |
|
|
const char* nm_modname; |
821 |
|
|
void* nm_priv; |
822 |
|
|
struct node_module* nm_link; |
823 |
|
|
}; |
824 |
|
|
|
825 |
|
|
extern "C" NODE_EXTERN void node_module_register(void* mod); |
826 |
|
|
|
827 |
|
|
#ifdef _WIN32 |
828 |
|
|
# define NODE_MODULE_EXPORT __declspec(dllexport) |
829 |
|
|
#else |
830 |
|
|
# define NODE_MODULE_EXPORT __attribute__((visibility("default"))) |
831 |
|
|
#endif |
832 |
|
|
|
833 |
|
|
#ifdef NODE_SHARED_MODE |
834 |
|
|
# define NODE_CTOR_PREFIX |
835 |
|
|
#else |
836 |
|
|
# define NODE_CTOR_PREFIX static |
837 |
|
|
#endif |
838 |
|
|
|
839 |
|
|
#if defined(_MSC_VER) |
840 |
|
|
#define NODE_C_CTOR(fn) \ |
841 |
|
|
NODE_CTOR_PREFIX void __cdecl fn(void); \ |
842 |
|
|
namespace { \ |
843 |
|
|
struct fn##_ { \ |
844 |
|
|
fn##_() { fn(); }; \ |
845 |
|
|
} fn##_v_; \ |
846 |
|
|
} \ |
847 |
|
|
NODE_CTOR_PREFIX void __cdecl fn(void) |
848 |
|
|
#else |
849 |
|
|
#define NODE_C_CTOR(fn) \ |
850 |
|
|
NODE_CTOR_PREFIX void fn(void) __attribute__((constructor)); \ |
851 |
|
|
NODE_CTOR_PREFIX void fn(void) |
852 |
|
|
#endif |
853 |
|
|
|
854 |
|
|
#define NODE_MODULE_X(modname, regfunc, priv, flags) \ |
855 |
|
|
extern "C" { \ |
856 |
|
|
static node::node_module _module = \ |
857 |
|
|
{ \ |
858 |
|
|
NODE_MODULE_VERSION, \ |
859 |
|
|
flags, \ |
860 |
|
|
NULL, /* NOLINT (readability/null_usage) */ \ |
861 |
|
|
__FILE__, \ |
862 |
|
|
(node::addon_register_func) (regfunc), \ |
863 |
|
|
NULL, /* NOLINT (readability/null_usage) */ \ |
864 |
|
|
NODE_STRINGIFY(modname), \ |
865 |
|
|
priv, \ |
866 |
|
|
NULL /* NOLINT (readability/null_usage) */ \ |
867 |
|
|
}; \ |
868 |
|
|
NODE_C_CTOR(_register_ ## modname) { \ |
869 |
|
|
node_module_register(&_module); \ |
870 |
|
|
} \ |
871 |
|
|
} |
872 |
|
|
|
873 |
|
|
#define NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, priv, flags) \ |
874 |
|
|
extern "C" { \ |
875 |
|
|
static node::node_module _module = \ |
876 |
|
|
{ \ |
877 |
|
|
NODE_MODULE_VERSION, \ |
878 |
|
|
flags, \ |
879 |
|
|
NULL, /* NOLINT (readability/null_usage) */ \ |
880 |
|
|
__FILE__, \ |
881 |
|
|
NULL, /* NOLINT (readability/null_usage) */ \ |
882 |
|
|
(node::addon_context_register_func) (regfunc), \ |
883 |
|
|
NODE_STRINGIFY(modname), \ |
884 |
|
|
priv, \ |
885 |
|
|
NULL /* NOLINT (readability/null_usage) */ \ |
886 |
|
|
}; \ |
887 |
|
|
NODE_C_CTOR(_register_ ## modname) { \ |
888 |
|
|
node_module_register(&_module); \ |
889 |
|
|
} \ |
890 |
|
|
} |
891 |
|
|
|
892 |
|
|
// Usage: `NODE_MODULE(NODE_GYP_MODULE_NAME, InitializerFunction)` |
893 |
|
|
// If no NODE_MODULE is declared, Node.js looks for the well-known |
894 |
|
|
// symbol `node_register_module_v${NODE_MODULE_VERSION}`. |
895 |
|
|
#define NODE_MODULE(modname, regfunc) \ |
896 |
|
|
NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage) |
897 |
|
|
|
898 |
|
|
#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \ |
899 |
|
|
/* NOLINTNEXTLINE (readability/null_usage) */ \ |
900 |
|
|
NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0) |
901 |
|
|
|
902 |
|
|
// Embedders can use this type of binding for statically linked native bindings. |
903 |
|
|
// It is used the same way addon bindings are used, except that linked bindings |
904 |
|
|
// can be accessed through `process._linkedBinding(modname)`. |
905 |
|
|
#define NODE_MODULE_LINKED(modname, regfunc) \ |
906 |
|
|
/* NOLINTNEXTLINE (readability/null_usage) */ \ |
907 |
|
|
NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, \ |
908 |
|
|
node::ModuleFlags::kLinked) |
909 |
|
|
|
910 |
|
|
/* |
911 |
|
|
* For backward compatibility in add-on modules. |
912 |
|
|
*/ |
913 |
|
|
#define NODE_MODULE_DECL /* nothing */ |
914 |
|
|
|
915 |
|
|
#define NODE_MODULE_INITIALIZER_BASE node_register_module_v |
916 |
|
|
|
917 |
|
|
#define NODE_MODULE_INITIALIZER_X(base, version) \ |
918 |
|
|
NODE_MODULE_INITIALIZER_X_HELPER(base, version) |
919 |
|
|
|
920 |
|
|
#define NODE_MODULE_INITIALIZER_X_HELPER(base, version) base##version |
921 |
|
|
|
922 |
|
|
#define NODE_MODULE_INITIALIZER \ |
923 |
|
|
NODE_MODULE_INITIALIZER_X(NODE_MODULE_INITIALIZER_BASE, \ |
924 |
|
|
NODE_MODULE_VERSION) |
925 |
|
|
|
926 |
|
|
#define NODE_MODULE_INIT() \ |
927 |
|
|
extern "C" NODE_MODULE_EXPORT void \ |
928 |
|
|
NODE_MODULE_INITIALIZER(v8::Local<v8::Object> exports, \ |
929 |
|
|
v8::Local<v8::Value> module, \ |
930 |
|
|
v8::Local<v8::Context> context); \ |
931 |
|
|
NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, \ |
932 |
|
|
NODE_MODULE_INITIALIZER) \ |
933 |
|
|
void NODE_MODULE_INITIALIZER(v8::Local<v8::Object> exports, \ |
934 |
|
|
v8::Local<v8::Value> module, \ |
935 |
|
|
v8::Local<v8::Context> context) |
936 |
|
|
|
937 |
|
|
// Allows embedders to add a binding to the current Environment* that can be |
938 |
|
|
// accessed through process._linkedBinding() in the target Environment and all |
939 |
|
|
// Worker threads that it creates. |
940 |
|
|
// In each variant, the registration function needs to be usable at least for |
941 |
|
|
// the time during which the Environment exists. |
942 |
|
|
NODE_EXTERN void AddLinkedBinding(Environment* env, const node_module& mod); |
943 |
|
|
NODE_EXTERN void AddLinkedBinding(Environment* env, |
944 |
|
|
const struct napi_module& mod); |
945 |
|
|
NODE_EXTERN void AddLinkedBinding(Environment* env, |
946 |
|
|
const char* name, |
947 |
|
|
addon_context_register_func fn, |
948 |
|
|
void* priv); |
949 |
|
|
|
950 |
|
|
/* Registers a callback with the passed-in Environment instance. The callback |
951 |
|
|
* is called after the event loop exits, but before the VM is disposed. |
952 |
|
|
* Callbacks are run in reverse order of registration, i.e. newest first. |
953 |
|
|
*/ |
954 |
|
|
NODE_EXTERN void AtExit(Environment* env, |
955 |
|
|
void (*cb)(void* arg), |
956 |
|
|
void* arg); |
957 |
|
|
|
958 |
|
|
typedef double async_id; |
959 |
|
|
struct async_context { |
960 |
|
|
::node::async_id async_id; |
961 |
|
|
::node::async_id trigger_async_id; |
962 |
|
|
}; |
963 |
|
|
|
964 |
|
|
/* This is a lot like node::AtExit, except that the hooks added via this |
965 |
|
|
* function are run before the AtExit ones and will always be registered |
966 |
|
|
* for the current Environment instance. |
967 |
|
|
* These functions are safe to use in an addon supporting multiple |
968 |
|
|
* threads/isolates. */ |
969 |
|
|
NODE_EXTERN void AddEnvironmentCleanupHook(v8::Isolate* isolate, |
970 |
|
|
void (*fun)(void* arg), |
971 |
|
|
void* arg); |
972 |
|
|
|
973 |
|
|
NODE_EXTERN void RemoveEnvironmentCleanupHook(v8::Isolate* isolate, |
974 |
|
|
void (*fun)(void* arg), |
975 |
|
|
void* arg); |
976 |
|
|
|
977 |
|
|
/* These are async equivalents of the above. After the cleanup hook is invoked, |
978 |
|
|
* `cb(cbarg)` *must* be called, and attempting to remove the cleanup hook will |
979 |
|
|
* have no effect. */ |
980 |
|
|
struct ACHHandle; |
981 |
|
|
struct NODE_EXTERN DeleteACHHandle { void operator()(ACHHandle*) const; }; |
982 |
|
|
typedef std::unique_ptr<ACHHandle, DeleteACHHandle> AsyncCleanupHookHandle; |
983 |
|
|
|
984 |
|
|
/* This function is not intended to be used externally, it exists to aid in |
985 |
|
|
* keeping ABI compatibility between Node and Electron. */ |
986 |
|
|
NODE_EXTERN ACHHandle* AddEnvironmentCleanupHookInternal( |
987 |
|
|
v8::Isolate* isolate, |
988 |
|
|
void (*fun)(void* arg, void (*cb)(void*), void* cbarg), |
989 |
|
|
void* arg); |
990 |
|
6 |
inline AsyncCleanupHookHandle AddEnvironmentCleanupHook( |
991 |
|
|
v8::Isolate* isolate, |
992 |
|
|
void (*fun)(void* arg, void (*cb)(void*), void* cbarg), |
993 |
|
|
void* arg) { |
994 |
|
|
return AsyncCleanupHookHandle(AddEnvironmentCleanupHookInternal(isolate, fun, |
995 |
|
6 |
arg)); |
996 |
|
|
} |
997 |
|
|
|
998 |
|
|
/* This function is not intended to be used externally, it exists to aid in |
999 |
|
|
* keeping ABI compatibility between Node and Electron. */ |
1000 |
|
|
NODE_EXTERN void RemoveEnvironmentCleanupHookInternal(ACHHandle* holder); |
1001 |
|
6 |
inline void RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle holder) { |
1002 |
|
6 |
RemoveEnvironmentCleanupHookInternal(holder.get()); |
1003 |
|
6 |
} |
1004 |
|
|
|
1005 |
|
|
/* Returns the id of the current execution context. If the return value is |
1006 |
|
|
* zero then no execution has been set. This will happen if the user handles |
1007 |
|
|
* I/O from native code. */ |
1008 |
|
|
NODE_EXTERN async_id AsyncHooksGetExecutionAsyncId(v8::Isolate* isolate); |
1009 |
|
|
|
1010 |
|
|
/* Return same value as async_hooks.triggerAsyncId(); */ |
1011 |
|
|
NODE_EXTERN async_id AsyncHooksGetTriggerAsyncId(v8::Isolate* isolate); |
1012 |
|
|
|
1013 |
|
|
/* If the native API doesn't inherit from the helper class then the callbacks |
1014 |
|
|
* must be triggered manually. This triggers the init() callback. The return |
1015 |
|
|
* value is the async id assigned to the resource. |
1016 |
|
|
* |
1017 |
|
|
* The `trigger_async_id` parameter should correspond to the resource which is |
1018 |
|
|
* creating the new resource, which will usually be the return value of |
1019 |
|
|
* `AsyncHooksGetTriggerAsyncId()`. */ |
1020 |
|
|
NODE_EXTERN async_context EmitAsyncInit(v8::Isolate* isolate, |
1021 |
|
|
v8::Local<v8::Object> resource, |
1022 |
|
|
const char* name, |
1023 |
|
|
async_id trigger_async_id = -1); |
1024 |
|
|
|
1025 |
|
|
NODE_EXTERN async_context EmitAsyncInit(v8::Isolate* isolate, |
1026 |
|
|
v8::Local<v8::Object> resource, |
1027 |
|
|
v8::Local<v8::String> name, |
1028 |
|
|
async_id trigger_async_id = -1); |
1029 |
|
|
|
1030 |
|
|
/* Emit the destroy() callback. The overload taking an `Environment*` argument |
1031 |
|
|
* should be used when the Isolate’s current Context is not associated with |
1032 |
|
|
* a Node.js Environment, or when there is no current Context, for example |
1033 |
|
|
* when calling this function during garbage collection. In that case, the |
1034 |
|
|
* `Environment*` value should have been acquired previously, e.g. through |
1035 |
|
|
* `GetCurrentEnvironment()`. */ |
1036 |
|
|
NODE_EXTERN void EmitAsyncDestroy(v8::Isolate* isolate, |
1037 |
|
|
async_context asyncContext); |
1038 |
|
|
NODE_EXTERN void EmitAsyncDestroy(Environment* env, |
1039 |
|
|
async_context asyncContext); |
1040 |
|
|
|
1041 |
|
|
class InternalCallbackScope; |
1042 |
|
|
|
1043 |
|
|
/* This class works like `MakeCallback()` in that it sets up a specific |
1044 |
|
|
* asyncContext as the current one and informs the async_hooks and domains |
1045 |
|
|
* modules that this context is currently active. |
1046 |
|
|
* |
1047 |
|
|
* `MakeCallback()` is a wrapper around this class as well as |
1048 |
|
|
* `Function::Call()`. Either one of these mechanisms needs to be used for |
1049 |
|
|
* top-level calls into JavaScript (i.e. without any existing JS stack). |
1050 |
|
|
* |
1051 |
|
|
* This object should be stack-allocated to ensure that it is contained in a |
1052 |
|
|
* valid HandleScope. |
1053 |
|
|
* |
1054 |
|
|
* Exceptions happening within this scope will be treated like uncaught |
1055 |
|
|
* exceptions. If this behaviour is undesirable, a new `v8::TryCatch` scope |
1056 |
|
|
* needs to be created inside of this scope. |
1057 |
|
|
*/ |
1058 |
|
|
class NODE_EXTERN CallbackScope { |
1059 |
|
|
public: |
1060 |
|
|
CallbackScope(v8::Isolate* isolate, |
1061 |
|
|
v8::Local<v8::Object> resource, |
1062 |
|
|
async_context asyncContext); |
1063 |
|
|
CallbackScope(Environment* env, |
1064 |
|
|
v8::Local<v8::Object> resource, |
1065 |
|
|
async_context asyncContext); |
1066 |
|
|
~CallbackScope(); |
1067 |
|
|
|
1068 |
|
|
void operator=(const CallbackScope&) = delete; |
1069 |
|
|
void operator=(CallbackScope&&) = delete; |
1070 |
|
|
CallbackScope(const CallbackScope&) = delete; |
1071 |
|
|
CallbackScope(CallbackScope&&) = delete; |
1072 |
|
|
|
1073 |
|
|
private: |
1074 |
|
|
InternalCallbackScope* private_; |
1075 |
|
|
v8::TryCatch try_catch_; |
1076 |
|
|
}; |
1077 |
|
|
|
1078 |
|
|
/* An API specific to emit before/after callbacks is unnecessary because |
1079 |
|
|
* MakeCallback will automatically call them for you. |
1080 |
|
|
* |
1081 |
|
|
* These methods may create handles on their own, so run them inside a |
1082 |
|
|
* HandleScope. |
1083 |
|
|
* |
1084 |
|
|
* `asyncId` and `triggerAsyncId` should correspond to the values returned by |
1085 |
|
|
* `EmitAsyncInit()` and `AsyncHooksGetTriggerAsyncId()`, respectively, when the |
1086 |
|
|
* invoking resource was created. If these values are unknown, 0 can be passed. |
1087 |
|
|
* */ |
1088 |
|
|
NODE_EXTERN |
1089 |
|
|
v8::MaybeLocal<v8::Value> MakeCallback(v8::Isolate* isolate, |
1090 |
|
|
v8::Local<v8::Object> recv, |
1091 |
|
|
v8::Local<v8::Function> callback, |
1092 |
|
|
int argc, |
1093 |
|
|
v8::Local<v8::Value>* argv, |
1094 |
|
|
async_context asyncContext); |
1095 |
|
|
NODE_EXTERN |
1096 |
|
|
v8::MaybeLocal<v8::Value> MakeCallback(v8::Isolate* isolate, |
1097 |
|
|
v8::Local<v8::Object> recv, |
1098 |
|
|
const char* method, |
1099 |
|
|
int argc, |
1100 |
|
|
v8::Local<v8::Value>* argv, |
1101 |
|
|
async_context asyncContext); |
1102 |
|
|
NODE_EXTERN |
1103 |
|
|
v8::MaybeLocal<v8::Value> MakeCallback(v8::Isolate* isolate, |
1104 |
|
|
v8::Local<v8::Object> recv, |
1105 |
|
|
v8::Local<v8::String> symbol, |
1106 |
|
|
int argc, |
1107 |
|
|
v8::Local<v8::Value>* argv, |
1108 |
|
|
async_context asyncContext); |
1109 |
|
|
|
1110 |
|
|
/* Helper class users can optionally inherit from. If |
1111 |
|
|
* `AsyncResource::MakeCallback()` is used, then all four callbacks will be |
1112 |
|
|
* called automatically. */ |
1113 |
|
|
class NODE_EXTERN AsyncResource { |
1114 |
|
|
public: |
1115 |
|
|
AsyncResource(v8::Isolate* isolate, |
1116 |
|
|
v8::Local<v8::Object> resource, |
1117 |
|
|
const char* name, |
1118 |
|
|
async_id trigger_async_id = -1); |
1119 |
|
|
|
1120 |
|
|
virtual ~AsyncResource(); |
1121 |
|
|
|
1122 |
|
|
AsyncResource(const AsyncResource&) = delete; |
1123 |
|
|
void operator=(const AsyncResource&) = delete; |
1124 |
|
|
|
1125 |
|
|
v8::MaybeLocal<v8::Value> MakeCallback( |
1126 |
|
|
v8::Local<v8::Function> callback, |
1127 |
|
|
int argc, |
1128 |
|
|
v8::Local<v8::Value>* argv); |
1129 |
|
|
|
1130 |
|
|
v8::MaybeLocal<v8::Value> MakeCallback( |
1131 |
|
|
const char* method, |
1132 |
|
|
int argc, |
1133 |
|
|
v8::Local<v8::Value>* argv); |
1134 |
|
|
|
1135 |
|
|
v8::MaybeLocal<v8::Value> MakeCallback( |
1136 |
|
|
v8::Local<v8::String> symbol, |
1137 |
|
|
int argc, |
1138 |
|
|
v8::Local<v8::Value>* argv); |
1139 |
|
|
|
1140 |
|
|
v8::Local<v8::Object> get_resource(); |
1141 |
|
|
async_id get_async_id() const; |
1142 |
|
|
async_id get_trigger_async_id() const; |
1143 |
|
|
|
1144 |
|
|
protected: |
1145 |
|
|
class NODE_EXTERN CallbackScope : public node::CallbackScope { |
1146 |
|
|
public: |
1147 |
|
|
explicit CallbackScope(AsyncResource* res); |
1148 |
|
|
}; |
1149 |
|
|
|
1150 |
|
|
private: |
1151 |
|
|
Environment* env_; |
1152 |
|
|
v8::Global<v8::Object> resource_; |
1153 |
|
|
async_context async_context_; |
1154 |
|
|
}; |
1155 |
|
|
|
1156 |
|
|
#ifndef _WIN32 |
1157 |
|
|
// Register a signal handler without interrupting any handlers that node |
1158 |
|
|
// itself needs. This does override handlers registered through |
1159 |
|
|
// process.on('SIG...', function() { ... }). The `reset_handler` flag indicates |
1160 |
|
|
// whether the signal handler for the given signal should be reset to its |
1161 |
|
|
// default value before executing the handler (i.e. it works like SA_RESETHAND). |
1162 |
|
|
// The `reset_handler` flag is invalid when `signal` is SIGSEGV. |
1163 |
|
|
NODE_EXTERN |
1164 |
|
|
void RegisterSignalHandler(int signal, |
1165 |
|
|
void (*handler)(int signal, |
1166 |
|
|
siginfo_t* info, |
1167 |
|
|
void* ucontext), |
1168 |
|
|
bool reset_handler = false); |
1169 |
|
|
#endif // _WIN32 |
1170 |
|
|
|
1171 |
|
|
} // namespace node |
1172 |
|
|
|
1173 |
|
|
#endif // SRC_NODE_H_ |