• Home
Name
Date
Size
#Lines
LOC

..--

api/07-Sep-2024-2,3101,785

crypto/07-Sep-2024-20,13415,604

dataqueue/07-Sep-2024-29560

inspector/07-Sep-2024-1,7661,450

large_pages/07-Sep-2024-509347

permission/07-Sep-2024-605454

quic/07-Sep-2024-2,8052,075

res/07-Sep-2024-272249

tracing/07-Sep-2024-3,2172,250

README.mdD07-Sep-202443.4 KiB1,123848

acorn_version.hD07-Sep-2024210 74

aliased_buffer-inl.hD07-Sep-20247.4 KiB233180

aliased_buffer.hD07-Sep-20246.1 KiB198100

aliased_struct-inl.hD07-Sep-20241.3 KiB5540

aliased_struct.hD07-Sep-20241.4 KiB6433

async_wrap-inl.hD07-Sep-20242.7 KiB8849

async_wrap.ccD07-Sep-202426.1 KiB715518

async_wrap.hD07-Sep-202411.3 KiB249185

base64-inl.hD07-Sep-20245.8 KiB194155

base64.hD07-Sep-20241.4 KiB5436

base64_version.hD07-Sep-2024227 74

base_object-inl.hD07-Sep-20249 KiB303226

base_object.ccD07-Sep-20245.1 KiB165131

base_object.hD07-Sep-202413.3 KiB315148

base_object_types.hD07-Sep-20243.3 KiB7241

blob_serializer_deserializer-inl.hD07-Sep-202410.5 KiB360281

blob_serializer_deserializer.hD07-Sep-20243.6 KiB12971

callback_queue-inl.hD07-Sep-20242.6 KiB9879

callback_queue.hD07-Sep-20242 KiB7950

cares_wrap.ccD07-Sep-202460.6 KiB1,9861,544

cares_wrap.hD07-Sep-202414.2 KiB525425

cjs_module_lexer_version.hD07-Sep-2024277 74

cleanup_queue-inl.hD07-Sep-20241.6 KiB6347

cleanup_queue.ccD07-Sep-20241.7 KiB5335

cleanup_queue.hD07-Sep-20242.2 KiB8657

connect_wrap.ccD07-Sep-2024305 1711

connect_wrap.hD07-Sep-2024584 2718

connection_wrap.ccD07-Sep-20244.4 KiB143102

connection_wrap.hD07-Sep-2024686 3120

debug_utils-inl.hD07-Sep-20247.4 KiB227192

debug_utils.ccD07-Sep-202415.4 KiB519390

debug_utils.hD07-Sep-20246.8 KiB187127

diagnosticfilename-inl.hD07-Sep-2024768 3424

env-inl.hD07-Sep-202425.3 KiB865667

env.ccD07-Sep-202469.1 KiB1,8701,433

env.hD07-Sep-202438.5 KiB1,109778

env_properties.hD07-Sep-202433.5 KiB442415

fs_event_wrap.ccD07-Sep-20247.9 KiB244167

handle_wrap.ccD07-Sep-20245.5 KiB186122

handle_wrap.hD07-Sep-20244.2 KiB12255

heap_utils.ccD07-Sep-202414 KiB469404

histogram-inl.hD07-Sep-20242.4 KiB10889

histogram.ccD07-Sep-202421.7 KiB636559

histogram.hD07-Sep-20247.9 KiB240189

inspector_agent.ccD07-Sep-202431.8 KiB1,017828

inspector_agent.hD07-Sep-20244.7 KiB14590

inspector_io.ccD07-Sep-202411.5 KiB385326

inspector_io.hD07-Sep-20242.2 KiB7945

inspector_js_api.ccD07-Sep-202414.1 KiB407333

inspector_profiler.ccD07-Sep-202416.3 KiB531464

inspector_profiler.hD07-Sep-20244.5 KiB150101

inspector_socket.ccD07-Sep-202425.7 KiB820647

inspector_socket.hD07-Sep-20241.5 KiB6142

inspector_socket_server.ccD07-Sep-202417.7 KiB563494

inspector_socket_server.hD07-Sep-20243.5 KiB11183

js_native_api.hD07-Sep-202428.1 KiB562449

js_native_api_types.hD07-Sep-20244.4 KiB164125

js_native_api_v8.ccD07-Sep-2024163.6 KiB4,7223,639

js_native_api_v8.hD07-Sep-202420.6 KiB549424

js_native_api_v8_inspector.ccD07-Sep-202442.2 KiB1,4441,159

js_native_api_v8_inspector.hD07-Sep-20243.9 KiB13376

js_native_api_v8_internals.hD07-Sep-20241.6 KiB4622

js_stream.ccD07-Sep-20246 KiB220168

js_stream.hD07-Sep-20241.4 KiB5337

js_udp_wrap.ccD07-Sep-20246.9 KiB221178

json_utils.ccD07-Sep-20241.9 KiB7057

json_utils.hD07-Sep-20243.8 KiB173148

jsvm.hD07-Sep-2024109.6 KiB2,488570

jsvm_node_api.hD07-Sep-20249.8 KiB261197

jsvm_node_api_types.hD07-Sep-20241.6 KiB5342

jsvm_types.hD07-Sep-202418.6 KiB618218

memory_tracker-inl.hD07-Sep-202412 KiB357286

memory_tracker.hD07-Sep-202411.5 KiB290157

module_wrap.ccD07-Sep-202426.8 KiB828678

module_wrap.hD07-Sep-20243.7 KiB11893

node.ccD07-Sep-202442.3 KiB1,295924

node.dD07-Sep-202412 KiB316197

node.hD07-Sep-202456.4 KiB1,340849

node.stpD07-Sep-20243.4 KiB147126

node_api.ccD07-Sep-202445.5 KiB1,4161,105

node_api.hD07-Sep-202411.4 KiB276217

node_api_internals.hD07-Sep-20241.2 KiB4332

node_api_types.hD07-Sep-20241.6 KiB5142

node_binding.ccD07-Sep-202426 KiB736576

node_binding.hD07-Sep-20244.2 KiB12285

node_blob.ccD07-Sep-202415.5 KiB501417

node_blob.hD07-Sep-20245 KiB189141

node_bob-inl.hD07-Sep-2024657 3827

node_bob.hD07-Sep-20242.8 KiB11254

node_buffer.ccD07-Sep-202447 KiB1,4781,118

node_buffer.hD07-Sep-20243.6 KiB9343

node_builtins.ccD07-Sep-202426.2 KiB747624

node_builtins.hD07-Sep-20245.6 KiB156109

node_config.ccD07-Sep-20242.4 KiB9062

node_constants.ccD07-Sep-202430.7 KiB1,4241,069

node_constants.hD07-Sep-20243.7 KiB8550

node_context_data.hD07-Sep-20242.9 KiB10071

node_contextify.ccD07-Sep-202447.9 KiB1,4411,089

node_contextify.hD07-Sep-20247.1 KiB197160

node_credentials.ccD07-Sep-202413.4 KiB488369

node_crypto.ccD07-Sep-20244.2 KiB9865

node_crypto.hD07-Sep-20242.3 KiB5727

node_dir.ccD07-Sep-202414 KiB431340

node_dir.hD07-Sep-20241.3 KiB5333

node_dtrace.ccD07-Sep-202413.5 KiB322237

node_dtrace.hD07-Sep-20242.9 KiB8732

node_env_var.ccD07-Sep-202416.1 KiB491411

node_errors.ccD07-Sep-202434.5 KiB1,209926

node_errors.hD07-Sep-202416.9 KiB289245

node_external_reference.ccD07-Sep-2024710 2820

node_external_reference.hD07-Sep-20247.9 KiB154129

node_file-inl.hD07-Sep-202412.4 KiB357300

node_file.ccD07-Sep-202496.4 KiB2,8602,272

node_file.hD07-Sep-202414.7 KiB485354

node_http2.ccD07-Sep-2024118 KiB3,3502,406

node_http2.hD07-Sep-202438.6 KiB1,147812

node_http2_state.hD07-Sep-20244.8 KiB148128

node_http_common-inl.hD07-Sep-20245.5 KiB202166

node_http_common.hD07-Sep-202424.6 KiB533432

node_http_parser.ccD07-Sep-202436.7 KiB1,280906

node_i18n.ccD07-Sep-202430.3 KiB910674

node_i18n.hD07-Sep-20244.3 KiB14686

node_internals.hD07-Sep-202415 KiB434317

node_main.ccD07-Sep-20243.6 KiB9660

node_main_instance.ccD07-Sep-20246 KiB196159

node_main_instance.hD07-Sep-20243 KiB9455

node_mem-inl.hD07-Sep-20243.6 KiB11384

node_mem.hD07-Sep-20241.3 KiB4624

node_messaging.ccD07-Sep-202452.1 KiB1,5571,221

node_messaging.hD07-Sep-202414.3 KiB374212

node_metadata.ccD07-Sep-20243.7 KiB149123

node_metadata.hD07-Sep-20244.4 KiB139110

node_mutex.hD07-Sep-20247.8 KiB324247

node_object_wrap.hD07-Sep-20243.8 KiB13369

node_options-inl.hD07-Sep-202415.9 KiB479377

node_options.ccD07-Sep-202451 KiB1,3521,205

node_options.hD07-Sep-202417.6 KiB534387

node_os.ccD07-Sep-202414.7 KiB435329

node_perf.ccD07-Sep-202413.4 KiB379317

node_perf.hD07-Sep-20244.8 KiB169139

node_perf_common.hD07-Sep-20242.9 KiB9369

node_platform.ccD07-Sep-202419.9 KiB642516

node_platform.hD07-Sep-20246.2 KiB196146

node_postmortem_metadata.ccD07-Sep-20243.2 KiB7355

node_process-inl.hD07-Sep-2024737 2717

node_process.hD07-Sep-20243.4 KiB9967

node_process_events.ccD07-Sep-20243.3 KiB10783

node_process_methods.ccD07-Sep-202421 KiB642500

node_process_object.ccD07-Sep-20248.7 KiB259206

node_provider.dD07-Sep-20243.3 KiB8141

node_realm-inl.hD07-Sep-20244.6 KiB149116

node_realm.ccD07-Sep-202412.2 KiB329230

node_realm.hD07-Sep-20245.4 KiB157100

node_report.ccD07-Sep-202433.2 KiB990808

node_report.hD07-Sep-2024994 4329

node_report_module.ccD07-Sep-20247.9 KiB223190

node_report_utils.ccD07-Sep-20248.4 KiB273239

node_revert.hD07-Sep-20242.1 KiB8357

node_root_certs.hD07-Sep-2024233.2 KiB3,5753,280

node_sea.ccD07-Sep-20243.6 KiB12592

node_sea.hD07-Sep-2024517 2515

node_serdes.ccD07-Sep-202418.6 KiB546431

node_shadow_realm.ccD07-Sep-2024350 1712

node_shadow_realm.hD07-Sep-2024449 2012

node_snapshot_builder.hD07-Sep-20241.2 KiB4327

node_snapshot_stub.ccD07-Sep-2024327 147

node_snapshotable.ccD07-Sep-202451.9 KiB1,5391,187

node_snapshotable.hD07-Sep-20244.8 KiB12982

node_sockaddr-inl.hD07-Sep-20247.3 KiB267207

node_sockaddr.ccD07-Sep-202426.6 KiB891747

node_sockaddr.hD07-Sep-202412.9 KiB406278

node_stat_watcher.ccD07-Sep-20244.3 KiB12781

node_stat_watcher.hD07-Sep-20242.4 KiB7338

node_symbols.ccD07-Sep-2024991 3326

node_task_queue.ccD07-Sep-20248.1 KiB232183

node_threadsafe_cow-inl.hD07-Sep-20241.3 KiB5541

node_threadsafe_cow.hD07-Sep-20242.8 KiB10674

node_trace_events.ccD07-Sep-20245.9 KiB175146

node_types.ccD07-Sep-20243.7 KiB9075

node_union_bytes.hD07-Sep-20241.7 KiB5840

node_url.ccD07-Sep-202412.4 KiB387315

node_url.hD07-Sep-20242.1 KiB8058

node_util.ccD07-Sep-202415.8 KiB493396

node_util.hD07-Sep-20241.4 KiB5339

node_v8.ccD07-Sep-202418.8 KiB484400

node_v8.hD07-Sep-20241.7 KiB7051

node_v8_platform-inl.hD07-Sep-20246.6 KiB206156

node_version.hD07-Sep-20243.8 KiB10344

node_wasi.ccD07-Sep-202463.6 KiB1,7691,586

node_wasi.hD07-Sep-20245.2 KiB11094

node_wasm_web_api.ccD07-Sep-20247.2 KiB215154

node_wasm_web_api.hD07-Sep-20241.8 KiB5636

node_watchdog.ccD07-Sep-202412.4 KiB438301

node_watchdog.hD07-Sep-20244.3 KiB155105

node_win32_etw_provider-inl.hD07-Sep-202411.5 KiB289216

node_win32_etw_provider.ccD07-Sep-20246.3 KiB214135

node_win32_etw_provider.hD07-Sep-20243.7 KiB10065

node_worker.ccD07-Sep-202431.9 KiB967749

node_worker.hD07-Sep-20244.9 KiB15199

node_zlib.ccD07-Sep-202444.3 KiB1,4361,119

pipe_wrap.ccD07-Sep-20248.2 KiB260186

pipe_wrap.hD07-Sep-20242.8 KiB8145

process_wrap.ccD07-Sep-202410.9 KiB325235

req_wrap-inl.hD07-Sep-20245.4 KiB172114

req_wrap.hD07-Sep-20242.2 KiB7845

signal_wrap.ccD07-Sep-20245.8 KiB180130

sourcemap.defD07-Sep-202412.5 KiB395363

spawn_sync.ccD07-Sep-202429.9 KiB1,108761

spawn_sync.hD07-Sep-20246.9 KiB243157

stream_base-inl.hD07-Sep-20244.9 KiB174138

stream_base.ccD07-Sep-202425.9 KiB837653

stream_base.hD07-Sep-202417.4 KiB468241

stream_pipe.ccD07-Sep-202410.8 KiB336271

stream_pipe.hD07-Sep-20242.4 KiB7754

stream_wrap.ccD07-Sep-202412.8 KiB422307

stream_wrap.hD07-Sep-20244.1 KiB13274

string_bytes.ccD07-Sep-202423.1 KiB725555

string_bytes.hD07-Sep-20244.7 KiB12164

string_decoder-inl.hD07-Sep-2024858 3825

string_decoder.ccD07-Sep-202411.9 KiB349258

string_decoder.hD07-Sep-20241.5 KiB5131

string_search.hD07-Sep-202420.9 KiB639455

tcp_wrap.ccD07-Sep-202414.9 KiB456357

tcp_wrap.hD07-Sep-20243.9 KiB10668

threadpoolwork-inl.hD07-Sep-20242.6 KiB7141

timer_wrap-inl.hD07-Sep-2024755 3322

timer_wrap.ccD07-Sep-20241.8 KiB8466

timer_wrap.hD07-Sep-20241.8 KiB8653

timers.ccD07-Sep-20242.5 KiB8266

tty_wrap.ccD07-Sep-20245.1 KiB162108

tty_wrap.hD07-Sep-20242.3 KiB6632

udp_wrap.ccD07-Sep-202424.2 KiB810628

udp_wrap.hD07-Sep-20248.5 KiB228141

undici_version.hD07-Sep-2024215 74

util-inl.hD07-Sep-202419.6 KiB624488

util.ccD07-Sep-202419.5 KiB581470

util.hD07-Sep-202431.5 KiB927662

uv.ccD07-Sep-20244.8 KiB14299

v8abbr.hD07-Sep-20245 KiB12473

v8ustack.dD07-Sep-202421 KiB696459

README.md

1# Node.js C++ codebase
2
3Hi! �� You've found the C++ code backing Node.js. This README aims to help you
4get started working on it and document some idioms you may encounter while
5doing so.
6
7## Coding style
8
9Node.js has a document detailing its [C++ coding style][]
10that can be helpful as a reference for stylistic issues.
11
12## V8 API documentation
13
14A lot of the Node.js codebase is around what the underlying JavaScript engine,
15V8, provides through its API for embedders. Knowledge of this API can also be
16useful when working with native addons for Node.js written in C++, although for
17new projects [N-API][] is typically the better alternative.
18
19V8 does not provide much public API documentation beyond what is
20available in its C++ header files, most importantly `v8.h`, which can be
21accessed online in the following locations:
22
23* On GitHub: [`v8.h` in Node.js][]
24* On GitHub: [`v8.h` in V8][]
25* On the Chromium project's Code Search application: [`v8.h` in Code Search][]
26
27V8 also provides an [introduction for V8 embedders][],
28which can be useful for understanding some of the concepts it uses in its
29embedder API.
30
31Important concepts when using V8 are the ones of [`Isolate`][]s and
32[JavaScript value handles][].
33
34V8 supports [fast API calls][], which can be useful for improving the
35performance in certain cases.
36
37## libuv API documentation
38
39The other major dependency of Node.js is [libuv][], providing
40the [event loop][] and other operating system abstractions to Node.js.
41
42There is a [reference documentation for the libuv API][].
43
44## File structure
45
46The Node.js C++ files follow this structure:
47
48The `.h` header files contain declarations, and sometimes definitions that don't
49require including other headers (e.g. getters, setters, etc.). They should only
50include other `.h` header files and nothing else.
51
52The `-inl.h` header files contain definitions of inline functions from the
53corresponding `.h` header file (e.g. functions marked `inline` in the
54declaration or `template` functions).  They always include the corresponding
55`.h` header file, and can include other `.h` and `-inl.h` header files as
56needed.  It is not mandatory to split out the definitions from the `.h` file
57into an `-inl.h` file, but it becomes necessary when there are multiple
58definitions and contents of other `-inl.h` files start being used. Therefore, it
59is recommended to split a `-inl.h` file when inline functions become longer than
60a few lines to keep the corresponding `.h` file readable and clean. All visible
61definitions from the `-inl.h` file should be declared in the corresponding `.h`
62header file.
63
64The `.cc` files contain definitions of non-inline functions from the
65corresponding `.h` header file. They always include the corresponding `.h`
66header file, and can include other `.h` and `-inl.h` header files as needed.
67
68## Helpful concepts
69
70A number of concepts are involved in putting together Node.js on top of V8 and
71libuv. This section aims to explain some of them and how they work together.
72
73<a id="isolate"></a>
74
75### `Isolate`
76
77The `v8::Isolate` class represents a single JavaScript engine instance, in
78particular a set of JavaScript objects that can refer to each other
79(the “heap”).
80
81The `v8::Isolate` is often passed to other V8 API functions, and provides some
82APIs for managing the behaviour of the JavaScript engine or querying about its
83current state or statistics such as memory usage.
84
85V8 APIs are not thread-safe unless explicitly specified. In a typical Node.js
86application, the main thread and any `Worker` threads each have one `Isolate`,
87and JavaScript objects from one `Isolate` cannot refer to objects from
88another `Isolate`.
89
90Garbage collection, as well as other operations that affect the entire heap,
91happen on a per-`Isolate` basis.
92
93Typical ways of accessing the current `Isolate` in the Node.js code are:
94
95* Given a `FunctionCallbackInfo` for a [binding function][],
96  using `args.GetIsolate()`.
97* Given a [`Context`][], using `context->GetIsolate()`.
98* Given a [`Environment`][], using `env->isolate()`.
99* Given a [`Realm`][], using `realm->isolate()`.
100
101### V8 JavaScript values
102
103V8 provides classes that mostly correspond to JavaScript types; for example,
104`v8::Value` is a class representing any kind of JavaScript type, with
105subclasses such as `v8::Number` (which in turn has subclasses like `v8::Int32`),
106`v8::Boolean` or `v8::Object`. Most types are represented by subclasses
107of `v8::Object`, e.g. `v8::Uint8Array` or `v8::Date`.
108
109<a id="internal-fields"></a>
110
111### Internal fields
112
113V8 provides the ability to store data in so-called “internal fields” inside
114`v8::Object`s that were created as instances of C++-backed classes. The number
115of fields needs to be defined when creating that class.
116
117Both JavaScript values and `void*` pointers may be stored in such fields.
118In most native Node.js objects, the first internal field is used to store a
119pointer to a [`BaseObject`][] subclass, which then contains all relevant
120information associated with the JavaScript object.
121
122Typical ways of working with internal fields are:
123
124* `obj->InternalFieldCount()` to look up the number of internal fields for an
125  object (`0` for regular JavaScript objects).
126* `obj->GetInternalField(i)` to get a JavaScript value from an internal field.
127* `obj->SetInternalField(i, v)` to store a JavaScript value in an
128  internal field.
129* `obj->GetAlignedPointerFromInternalField(i)` to get a `void*` pointer from an
130  internal field.
131* `obj->SetAlignedPointerInInternalField(i, p)` to store a `void*` pointer in an
132  internal field.
133
134[`Context`][]s provide the same feature under the name “embedder data”.
135
136<a id="js-handles"></a>
137
138### JavaScript value handles
139
140All JavaScript values are accessed through the V8 API through so-called handles,
141of which there are two types: [`Local`][]s and [`Global`][]s.
142
143<a id="local-handles"></a>
144
145#### `Local` handles
146
147A `v8::Local` handle is a temporary pointer to a JavaScript object, where
148“temporary” usually means that is no longer needed after the current function
149is done executing. `Local` handles can only be allocated on the C++ stack.
150
151Most of the V8 API uses `Local` handles to work with JavaScript values or return
152them from functions.
153
154Whenever a `Local` handle is created, a `v8::HandleScope` or
155`v8::EscapableHandleScope` object must exist on the stack. The `Local` is then
156added to that scope and deleted along with it.
157
158When inside a [binding function][], a `HandleScope` already exists outside of
159it, so there is no need to explicitly create one.
160
161`EscapableHandleScope`s can be used to allow a single `Local` handle to be
162passed to the outer scope. This is useful when a function returns a `Local`.
163
164The following JavaScript and C++ functions are mostly equivalent:
165
166```js
167function getFoo(obj) {
168  return obj.foo;
169}
170```
171
172```cpp
173v8::Local<v8::Value> GetFoo(v8::Local<v8::Context> context,
174                            v8::Local<v8::Object> obj) {
175  v8::Isolate* isolate = context->GetIsolate();
176  v8::EscapableHandleScope handle_scope(isolate);
177
178  // The 'foo_string' handle cannot be returned from this function because
179  // it is not “escaped” with `.Escape()`.
180  v8::Local<v8::String> foo_string =
181      v8::String::NewFromUtf8(isolate, "foo").ToLocalChecked();
182
183  v8::Local<v8::Value> return_value;
184  if (obj->Get(context, foo_string).ToLocal(&return_value)) {
185    return handle_scope.Escape(return_value);
186  } else {
187    // There was a JS exception! Handle it somehow.
188    return v8::Local<v8::Value>();
189  }
190}
191```
192
193See [exception handling][] for more information about the usage of `.To()`,
194`.ToLocalChecked()`, `v8::Maybe` and `v8::MaybeLocal` usage.
195
196##### Casting local handles
197
198If it is known that a `Local<Value>` refers to a more specific type, it can
199be cast to that type using `.As<...>()`:
200
201```cpp
202v8::Local<v8::Value> some_value;
203// CHECK() is a Node.js utilitity that works similar to assert().
204CHECK(some_value->IsUint8Array());
205v8::Local<v8::Uint8Array> as_uint8 = some_value.As<v8::Uint8Array>();
206```
207
208Generally, using `val.As<v8::X>()` is only valid if `val->IsX()` is true, and
209failing to follow that rule may lead to crashes.
210
211##### Detecting handle leaks
212
213If it is expected that no `Local` handles should be created within a given
214scope unless explicitly within a `HandleScope`, a `SealHandleScope` can be used.
215
216For example, there is a `SealHandleScope` around the event loop, forcing
217any functions that are called from the event loop and want to run or access
218JavaScript code to create `HandleScope`s.
219
220<a id="global-handles"></a>
221
222#### `Global` handles
223
224A `v8::Global` handle (sometimes also referred to by the name of its parent
225class `Persistent`, although use of that is discouraged in Node.js) is a
226reference to a JavaScript object that can remain active as long as the engine
227instance is active.
228
229Global handles can be either strong or weak. Strong global handles are so-called
230“GC roots”, meaning that they will keep the JavaScript object they refer to
231alive even if no other objects refer to them. Weak global handles do not do
232that, and instead optionally call a callback when the object they refer to
233is garbage-collected.
234
235```cpp
236v8::Global<v8::Object> reference;
237
238void StoreReference(v8::Isolate* isolate, v8::Local<v8::Object> obj) {
239  // Create a strong reference to `obj`.
240  reference.Reset(isolate, obj);
241}
242
243// Must be called with a HandleScope around it.
244v8::Local<v8::Object> LoadReference(v8::Isolate* isolate) {
245  return reference.Get(isolate);
246}
247```
248
249##### `Eternal` handles
250
251`v8::Eternal` handles are a special kind of handles similar to `v8::Global`
252handles, with the exception that the values they point to are never
253garbage-collected while the JavaScript Engine instance is alive, even if
254the `v8::Eternal` itself is destroyed at some point. This type of handle
255is rarely used.
256
257<a id="context"></a>
258
259### `Context`
260
261JavaScript allows multiple global objects and sets of built-in JavaScript
262objects (like the `Object` or `Array` functions) to coexist inside the same
263heap. Node.js exposes this ability through the [`vm` module][].
264
265V8 refers to each of these global objects and their associated builtins as a
266`Context`.
267
268Currently, in Node.js there is one main `Context` associated with the
269principal [`Realm`][] of an [`Environment`][] instance, and a number of
270subsidiary `Context`s that are created with `vm.Context` or associated with
271[`ShadowRealm`][].
272
273Most Node.js features will only work inside a context associated with a
274`Realm`. The only exception at the time of writing are [`MessagePort`][]
275objects. This restriction is not inherent to the design of Node.js, and a
276sufficiently committed person could restructure Node.js to provide built-in
277modules inside of `vm.Context`s.
278
279Often, the `Context` is passed around for [exception handling][].
280Typical ways of accessing the current `Context` in the Node.js code are:
281
282* Given an [`Isolate`][], using `isolate->GetCurrentContext()`.
283* Given an [`Environment`][], using `env->context()` to get the `Environment`'s
284  principal [`Realm`][]'s context.
285* Given a [`Realm`][], using `realm->context()` to get the `Realm`'s
286  context.
287
288<a id="event-loop"></a>
289
290### Event loop
291
292The main abstraction for an event loop inside Node.js is the `uv_loop_t` struct.
293Typically, there is one event loop per thread. This includes not only the main
294thread and Workers, but also helper threads that may occasionally be spawned
295in the course of running a Node.js program.
296
297The current event loop can be accessed using `env->event_loop()` given an
298[`Environment`][] instance. The restriction of using a single event loop
299is not inherent to the design of Node.js, and a sufficiently committed person
300could restructure Node.js to provide e.g. the ability to run parts of Node.js
301inside an event loop separate from the active thread's event loop.
302
303<a id="environment"></a>
304
305### `Environment`
306
307Node.js instances are represented by the `Environment` class.
308
309Currently, every `Environment` class is associated with:
310
311* One [event loop][]
312* One [`Isolate`][]
313* One principal [`Realm`][]
314
315The `Environment` class contains a large number of different fields for
316different built-in modules that can be shared across different `Realm`
317instances, for example, the inspector agent, async hooks info.
318
319Typical ways of accessing the current `Environment` in the Node.js code are:
320
321* Given a `FunctionCallbackInfo` for a [binding function][],
322  using `Environment::GetCurrent(args)`.
323* Given a [`BaseObject`][], using `env()` or `self->env()`.
324* Given a [`Context`][], using `Environment::GetCurrent(context)`.
325  This requires that `context` has been associated with the `Environment`
326  instance, e.g. is the main `Context` for the `Environment` or one of its
327  `vm.Context`s.
328* Given an [`Isolate`][], using `Environment::GetCurrent(isolate)`. This looks
329  up the current [`Context`][] and then uses that.
330
331<a id="realm"></a>
332
333### `Realm`
334
335The `Realm` class is a container for a set of JavaScript objects and functions
336that are associated with a particular [ECMAScript realm][].
337
338Each ECMAScript realm comes with a global object and a set of intrinsic
339objects. An ECMAScript realm has a `[[HostDefined]]` field, which represents
340the Node.js [`Realm`][] object.
341
342Every `Realm` instance is created for a particular [`Context`][]. A `Realm`
343can be a principal realm or a synthetic realm. A principal realm is created
344for each `Environment`'s main [`Context`][]. A synthetic realm is created
345for the [`Context`][] of each [`ShadowRealm`][] constructed from the JS API. No
346`Realm` is created for the [`Context`][] of a `vm.Context`.
347
348Native bindings and built-in modules can be evaluated in either a principal
349realm or a synthetic realm.
350
351The `Realm` class contains a large number of different fields for
352different built-in modules, for example the memory for a `Uint32Array` that
353the `url` module uses for storing data returned from a
354`urlBinding.update()` call.
355
356It also provides [cleanup hooks][] and maintains a list of [`BaseObject`][]
357instances.
358
359Typical ways of accessing the current `Realm` in the Node.js code are:
360
361* Given a `FunctionCallbackInfo` for a [binding function][],
362  using `Realm::GetCurrent(args)`.
363* Given a [`BaseObject`][], using `realm()` or `self->realm()`.
364* Given a [`Context`][], using `Realm::GetCurrent(context)`.
365  This requires that `context` has been associated with the `Realm`
366  instance, e.g. is the principal `Realm` for the `Environment`.
367* Given an [`Isolate`][], using `Realm::GetCurrent(isolate)`. This looks
368  up the current [`Context`][] and then uses its `Realm`.
369
370<a id="isolate-data"></a>
371
372### `IsolateData`
373
374Every Node.js instance ([`Environment`][]) is associated with one `IsolateData`
375instance that contains information about or associated with a given
376[`Isolate`][].
377
378#### String table
379
380`IsolateData` contains a list of strings that can be quickly accessed
381inside Node.js code, e.g. given an `Environment` instance `env` the JavaScript
382string “name” can be accessed through `env->name_string()` without actually
383creating a new JavaScript string.
384
385### Platform
386
387Every process that uses V8 has a `v8::Platform` instance that provides some
388functionalities to V8, most importantly the ability to schedule work on
389background threads.
390
391Node.js provides a `NodePlatform` class that implements the `v8::Platform`
392interface and uses libuv for providing background threading abilities.
393
394The platform can be accessed through `isolate_data->platform()` given an
395[`IsolateData`][] instance, although that only works when:
396
397* The current Node.js instance was not started by an embedder; or
398* The current Node.js instance was started by an embedder whose `v8::Platform`
399  implementation also implement's the `node::MultiIsolatePlatform` interface
400  and who passed this to Node.js.
401
402<a id="binding-functions"></a>
403
404### Binding functions
405
406C++ functions exposed to JS follow a specific signature. The following example
407is from `node_util.cc`:
408
409```cpp
410void ArrayBufferViewHasBuffer(const FunctionCallbackInfo<Value>& args) {
411  CHECK(args[0]->IsArrayBufferView());
412  args.GetReturnValue().Set(args[0].As<ArrayBufferView>()->HasBuffer());
413}
414```
415
416(Namespaces are usually omitted through the use of `using` statements in the
417Node.js source code.)
418
419`args[n]` is a `Local<Value>` that represents the n-th argument passed to the
420function. `args.This()` is the `this` value inside this function call.
421`args.Holder()` is equivalent to `args.This()` in all use cases inside of
422Node.js.
423
424`args.GetReturnValue()` is a placeholder for the return value of the function,
425and provides a `.Set()` method that can be called with a boolean, integer,
426floating-point number or a `Local<Value>` to set the return value.
427
428Node.js provides various helpers for building JS classes in C++ and/or attaching
429C++ functions to the exports of a built-in module:
430
431```cpp
432void Initialize(Local<Object> target,
433                Local<Value> unused,
434                Local<Context> context,
435                void* priv) {
436  Environment* env = Environment::GetCurrent(context);
437
438  SetMethod(context, target, "getaddrinfo", GetAddrInfo);
439  SetMethod(context, target, "getnameinfo", GetNameInfo);
440
441  // 'SetMethodNoSideEffect' means that debuggers can safely execute this
442  // function for e.g. previews.
443  SetMethodNoSideEffect(context, target, "canonicalizeIP", CanonicalizeIP);
444
445  // ... more code ...
446
447  Isolate* isolate = env->isolate();
448  // Building the `ChannelWrap` class for JS:
449  Local<FunctionTemplate> channel_wrap =
450      NewFunctionTemplate(isolate, ChannelWrap::New);
451  // Allow for 1 internal field, see `BaseObject` for details on this:
452  channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
453  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
454
455  // Set various methods on the class (i.e. on the prototype):
456  SetProtoMethod(isolate, channel_wrap, "queryAny", Query<QueryAnyWrap>);
457  SetProtoMethod(isolate, channel_wrap, "queryA", Query<QueryAWrap>);
458  // ...
459  SetProtoMethod(isolate, channel_wrap, "querySoa", Query<QuerySoaWrap>);
460  SetProtoMethod(isolate, channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
461
462  SetProtoMethodNoSideEffect(isolate, channel_wrap, "getServers", GetServers);
463
464  SetConstructorFunction(context, target, "ChannelWrap", channel_wrap);
465}
466
467// Run the `Initialize` function when loading this binding through
468// `internalBinding('cares_wrap')` in Node.js's built-in JavaScript code:
469NODE_BINDING_CONTEXT_AWARE_INTERNAL(cares_wrap, Initialize)
470```
471
472If the C++ binding is loaded during bootstrap, it needs to be registered
473with the utilities in `node_external_reference.h`, like this:
474
475```cpp
476namespace node {
477namespace util {
478void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
479  registry->Register(GetHiddenValue);
480  registry->Register(SetHiddenValue);
481  // ... register all C++ functions used to create FunctionTemplates.
482}
483}  // namespace util
484}  // namespace node
485
486// The first argument passed to `NODE_BINDING_EXTERNAL_REFERENCE`,
487// which is `util` here, needs to be added to the
488// `EXTERNAL_REFERENCE_BINDING_LIST_BASE` list in node_external_reference.h
489NODE_BINDING_EXTERNAL_REFERENCE(util, node::util::RegisterExternalReferences)
490```
491
492Otherwise, you might see an error message like this when building the
493executables:
494
495```console
496FAILED: gen/node_snapshot.cc
497cd ../../; out/Release/node_mksnapshot out/Release/gen/node_snapshot.cc
498Unknown external reference 0x107769200.
499<unresolved>
500/bin/sh: line 1:  6963 Illegal instruction: 4  out/Release/node_mksnapshot out/Release/gen/node_snapshot.cc
501```
502
503You can try using a debugger to symbolicate the external reference. For example,
504with lldb's `image lookup --address` command (with gdb it's `info symbol`):
505
506```console
507$ lldb -- out/Release/node_mksnapshot out/Release/gen/node_snapshot.cc
508(lldb) run
509Process 7012 launched: '/Users/joyee/projects/node/out/Release/node_mksnapshot' (x86_64)
510Unknown external reference 0x1004c8200.
511<unresolved>
512Process 7012 stopped
513(lldb) image lookup --address 0x1004c8200
514      Address: node_mksnapshot[0x00000001004c8200] (node_mksnapshot.__TEXT.__text + 5009920)
515      Summary: node_mksnapshot`node::util::GetHiddenValue(v8::FunctionCallbackInfo<v8::Value> const&) at node_util.cc:159
516```
517
518Which explains that the unregistered external reference is
519`node::util::GetHiddenValue` defined in `node_util.cc`.
520
521<a id="per-binding-state"></a>
522
523#### Per-binding state
524
525Some internal bindings, such as the HTTP parser, maintain internal state that
526only affects that particular binding. In that case, one common way to store
527that state is through the use of `Realm::AddBindingData`, which gives
528binding functions access to an object for storing such state.
529That object is always a [`BaseObject`][].
530
531In the binding, call `SET_BINDING_ID()` with an identifier for the binding
532type. For example, for `http_parser::BindingData`, the identifier can be
533`http_parser_binding_data`.
534
535If the binding should be supported in a snapshot, the id and the
536fully-specified class name should be added to the `SERIALIZABLE_BINDING_TYPES`
537list in `base_object_types.h`, and the class should implement the serialization
538and deserialization methods. See the comments of `SnapshotableObject` on how to
539implement them. Otherwise, add the id and the class name to the
540`UNSERIALIZABLE_BINDING_TYPES` list instead.
541
542```cpp
543// In base_object_types.h, add the binding to either
544// UNSERIALIZABLE_BINDING_TYPES or SERIALIZABLE_BINDING_TYPES.
545// The second parameter is a descriptive name of the class, which is
546// usually the fully-specified class name.
547
548#define UNSERIALIZABLE_BINDING_TYPES(V)                                         \
549  V(http_parser_binding_data, http_parser::BindingData)
550
551// In the HTTP parser source code file:
552class BindingData : public BaseObject {
553 public:
554  BindingData(Realm* realm, Local<Object> obj) : BaseObject(realm, obj) {}
555
556  SET_BINDING_ID(http_parser_binding_data)
557
558  std::vector<char> parser_buffer;
559  bool parser_buffer_in_use = false;
560
561  // ...
562};
563
564// Available for binding functions, e.g. the HTTP Parser constructor:
565static void New(const FunctionCallbackInfo<Value>& args) {
566  BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
567  new Parser(binding_data, args.This());
568}
569
570// ... because the initialization function told the Realm to store the
571// BindingData object:
572void InitializeHttpParser(Local<Object> target,
573                          Local<Value> unused,
574                          Local<Context> context,
575                          void* priv) {
576  Realm* realm = Realm::GetCurrent(context);
577  BindingData* const binding_data =
578      realm->AddBindingData<BindingData>(context, target);
579  if (binding_data == nullptr) return;
580
581  Local<FunctionTemplate> t = NewFunctionTemplate(realm->isolate(), Parser::New);
582  ...
583}
584```
585
586<a id="exception-handling"></a>
587
588### Exception handling
589
590The V8 engine provides multiple features to work with JavaScript exceptions,
591as C++ exceptions are disabled inside of Node.js:
592
593#### Maybe types
594
595V8 provides the `v8::Maybe<T>` and `v8::MaybeLocal<T>` types, typically used
596as return values from API functions that can run JavaScript code and therefore
597can throw exceptions.
598
599Conceptually, the idea is that every `v8::Maybe<T>` is either empty (checked
600through `.IsNothing()`) or holds a value of type `T` (checked through
601`.IsJust()`). If the `Maybe` is empty, then a JavaScript exception is pending.
602A typical way of accessing the value is using the `.To()` function, which
603returns a boolean indicating success of the operation (i.e. the `Maybe` not
604being empty) and taking a pointer to a `T` to store the value if there is one.
605
606##### Checked conversion
607
608`maybe.Check()` can be used to assert that the maybe is not empty, i.e. crash
609the process otherwise. `maybe.FromJust()` (aka `maybe.ToChecked()`) can be used
610to access the value and crash the process if it is not set.
611
612This should only be performed if it is actually sure that the operation has
613not failed. A lot of the Node.js source code does **not** follow this rule, and
614can be brought to crash through this.
615
616In particular, it is often not safe to assume that an operation does not throw
617an exception, even if it seems like it would not do that.
618The most common reasons for this are:
619
620* Calls to functions like `object->Get(...)` or `object->Set(...)` may fail on
621  most objects, if the `Object.prototype` object has been modified from userland
622  code that added getters or setters.
623* Calls that invoke _any_ JavaScript code, including JavaScript code that is
624  provided from Node.js internals or V8 internals, will fail when JavaScript
625  execution is being terminated. This typically happens inside Workers when
626  `worker.terminate()` is called, but it can also affect the main thread when
627  e.g. Node.js is used as an embedded library. These exceptions can happen at
628  any point.
629  It is not always obvious whether a V8 call will enter JavaScript. In addition
630  to unexpected getters and setters, accessing some types of built-in objects
631  like `Map`s and `Set`s can also run V8-internal JavaScript code.
632
633##### MaybeLocal
634
635`v8::MaybeLocal<T>` is a variant of `v8::Maybe<T>` that is either empty or
636holds a value of type `Local<T>`. It has methods that perform the same
637operations as the methods of `v8::Maybe`, but with different names:
638
639| `Maybe`              | `MaybeLocal`                   |
640| -------------------- | ------------------------------ |
641| `maybe.IsNothing()`  | `maybe_local.IsEmpty()`        |
642| `maybe.IsJust()`     | `!maybe_local.IsEmpty()`       |
643| `maybe.To(&value)`   | `maybe_local.ToLocal(&local)`  |
644| `maybe.ToChecked()`  | `maybe_local.ToLocalChecked()` |
645| `maybe.FromJust()`   | `maybe_local.ToLocalChecked()` |
646| `maybe.Check()`      | –                              |
647| `v8::Nothing<T>()`   | `v8::MaybeLocal<T>()`          |
648| `v8::Just<T>(value)` | `v8::MaybeLocal<T>(value)`     |
649
650##### Handling empty `Maybe`s
651
652Usually, the best approach to encountering an empty `Maybe` is to just return
653from the current function as soon as possible, and let execution in JavaScript
654land resume. If the empty `Maybe` is encountered inside a nested function,
655is may be a good idea to use a `Maybe` or `MaybeLocal` for the return type
656of that function and pass information about pending JavaScript exceptions along
657that way.
658
659Generally, when an empty `Maybe` is encountered, it is not valid to attempt
660to perform further calls to APIs that return `Maybe`s.
661
662A typical pattern for dealing with APIs that return `Maybe` and `MaybeLocal` is
663using `.ToLocal()` and `.To()` and returning early in case there is an error:
664
665```cpp
666// This could also return a v8::MaybeLocal<v8::Number>, for example.
667v8::Maybe<double> SumNumbers(v8::Local<v8::Context> context,
668                             v8::Local<v8::Array> array_of_integers) {
669  v8::Isolate* isolate = context->GetIsolate();
670  v8::HandleScope handle_scope(isolate);
671
672  double sum = 0;
673
674  for (uint32_t i = 0; i < array_of_integers->Length(); i++) {
675    v8::Local<v8::Value> entry;
676    if (!array_of_integers->Get(context, i).ToLocal(&entry)) {
677      // Oops, we might have hit a getter that throws an exception!
678      // It's better to not continue return an empty (“nothing”) Maybe.
679      return v8::Nothing<double>();
680    }
681
682    if (!entry->IsNumber()) {
683      // Let's just skip any non-numbers. It would also be reasonable to throw
684      // an exception here, e.g. using the error system in src/node_errors.h,
685      // and then to return an empty Maybe again.
686      continue;
687    }
688
689    // This cast is valid, because we've made sure it's really a number.
690    v8::Local<v8::Number> entry_as_number = entry.As<v8::Number>();
691
692    sum += entry_as_number->Value();
693  }
694
695  return v8::Just(sum);
696}
697
698// Function that is exposed to JS:
699void SumNumbers(const v8::FunctionCallbackInfo<v8::Value>& args) {
700  // This will crash if the first argument is not an array. Let's assume we
701  // have performed type checking in a JavaScript wrapper function.
702  CHECK(args[0]->IsArray());
703
704  double sum;
705  if (!SumNumbers(args.GetIsolate()->GetCurrentContext(),
706                  args[0].As<v8::Array>()).To(&sum)) {
707    // Nothing to do, we can just return directly to JavaScript.
708    return;
709  }
710
711  args.GetReturnValue().Set(sum);
712}
713```
714
715#### TryCatch
716
717If there is a need to catch JavaScript exceptions in C++, V8 provides the
718`v8::TryCatch` type for doing so, which we wrap into our own
719`node::errors::TryCatchScope` in Node.js. The latter has the additional feature
720of providing the ability to shut down the program in the typical Node.js way
721(printing the exception + stack trace) if an exception is caught.
722
723A `TryCatch` will catch regular JavaScript exceptions, as well as termination
724exceptions such as the ones thrown by `worker.terminate()` calls.
725In the latter case, the `try_catch.HasTerminated()` function will return `true`,
726and the exception object will not be a meaningful JavaScript value.
727`try_catch.ReThrow()` should not be used in this case.
728
729<a id="libuv-handles-and-requests"></a>
730
731### libuv handles and requests
732
733Two central concepts when working with libuv are handles and requests.
734
735Handles are subclasses of the `uv_handle_t` “class”, and generally refer to
736long-lived objects that can emit events multiple times, such as network sockets
737or file system watchers.
738
739In Node.js, handles are often managed through a [`HandleWrap`][] subclass.
740
741Requests are one-time asynchronous function calls on the event loop, such as
742file system requests or network write operations, that either succeed or fail.
743
744In Node.js, requests are often managed through a [`ReqWrap`][] subclass.
745
746### Environment cleanup
747
748When a Node.js [`Environment`][] is destroyed, it generally needs to clean up
749any resources owned by it, e.g. memory or libuv requests/handles.
750
751<a id="cleanup-hooks"></a>
752
753#### Cleanup hooks
754
755Cleanup hooks are provided that run before the [`Environment`][] or the
756[`Realm`][] is destroyed. They can be added and removed by using
757`env->AddCleanupHook(callback, hint);` and
758`env->RemoveCleanupHook(callback, hint);`, or
759`realm->AddCleanupHook(callback, hint);` and
760`realm->RemoveCleanupHook(callback, hint);` respectively, where callback takes
761a `void* hint` argument.
762
763Inside these cleanup hooks, new asynchronous operations _may_ be started on the
764event loop, although ideally that is avoided as much as possible.
765
766Every [`BaseObject`][] has its own cleanup hook that deletes it. For
767[`ReqWrap`][] and [`HandleWrap`][] instances, cleanup of the associated libuv
768objects is performed automatically, i.e. handles are closed and requests
769are cancelled if possible.
770
771#### Closing libuv handles
772
773If a libuv handle is not managed through a [`HandleWrap`][] instance,
774it needs to be closed explicitly. Do not use `uv_close()` for that, but rather
775`env->CloseHandle()`, which works the same way but keeps track of the number
776of handles that are still closing.
777
778#### Closing libuv requests
779
780There is no way to abort libuv requests in general. If a libuv request is not
781managed through a [`ReqWrap`][] instance, the
782`env->IncreaseWaitingRequestCounter()` and
783`env->DecreaseWaitingRequestCounter()` functions need to be used to keep track
784of the number of active libuv requests.
785
786#### Calling into JavaScript
787
788Calling into JavaScript is not allowed during cleanup. Worker threads explicitly
789forbid this during their shutdown sequence, but the main thread does not for
790backwards compatibility reasons.
791
792When calling into JavaScript without using [`MakeCallback()`][], check the
793`env->can_call_into_js()` flag and do not proceed if it is set to `false`.
794
795## Classes associated with JavaScript objects
796
797### `MemoryRetainer`
798
799A large number of classes in the Node.js C++ codebase refer to other objects.
800The `MemoryRetainer` class is a helper for annotating C++ classes with
801information that can be used by the heap snapshot builder in V8, so that
802memory retained by C++ can be tracked in V8 heap snapshots captured in
803Node.js applications.
804
805Inheriting from the `MemoryRetainer` class enables objects (both from JavaScript
806and C++) to refer to instances of that class, and in turn enables that class
807to point to other objects as well, including native C++ types
808such as `std::string` and track their memory usage.
809
810This can be useful for debugging memory leaks.
811
812The [`memory_tracker.h`][] header file explains how to use this class.
813
814<a id="baseobject"></a>
815
816### `BaseObject`
817
818A frequently recurring situation is that a JavaScript object and a C++ object
819need to be tied together. `BaseObject` is the main abstraction for that in
820Node.js, and most classes that are associated with JavaScript objects are
821subclasses of it. It is defined in [`base_object.h`][].
822
823Every `BaseObject` is associated with one [`Realm`][] and one
824`v8::Object`. The `v8::Object` needs to have at least one [internal field][]
825that is used for storing the pointer to the C++ object. In order to ensure this,
826the V8 `SetInternalFieldCount()` function is usually used when setting up the
827class from C++.
828
829The JavaScript object can be accessed as a `v8::Local<v8::Object>` by using
830`self->object()`, given a `BaseObject` named `self`.
831
832Accessing a `BaseObject` from a `v8::Local<v8::Object>` (frequently that is
833`args.This()` or `args.Holder()` in a [binding function][]) can be done using
834the `Unwrap<T>(obj)` function, where `T` is a subclass of `BaseObject`.
835A helper for this is the `ASSIGN_OR_RETURN_UNWRAP` macro that returns from the
836current function if unwrapping fails (typically that means that the `BaseObject`
837has been deleted earlier).
838
839```cpp
840void Http2Session::Request(const FunctionCallbackInfo<Value>& args) {
841  Http2Session* session;
842  ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
843  Environment* env = session->env();
844  Local<Context> context = env->context();
845  Isolate* isolate = env->isolate();
846
847  // ...
848  // The actual function body, which can now use the `session` object.
849  // ...
850}
851```
852
853#### Lifetime management
854
855The `BaseObject` class comes with a set of features that allow managing the
856lifetime of its instances, either associating it with the lifetime of the
857corresponding JavaScript object or untying the two.
858
859The `BaseObject::MakeWeak()` method turns the underlying [`Global`][] handle
860into a weak one, and makes it so that the `BaseObject::OnGCCollect()` virtual
861method is called when the JavaScript object is garbage collected. By default,
862that methods deletes the `BaseObject` instance.
863
864`BaseObject::ClearWeak()` undoes this effect.
865
866It generally makes sense to call `MakeWeak()` in the constructor of a
867`BaseObject` subclass, unless that subclass is referred to by e.g. the event
868loop, as is the case for the [`HandleWrap`][] and [`ReqWrap`][] classes.
869
870In addition, there are two kinds of smart pointers that can be used to refer
871to `BaseObject`s.
872
873`BaseObjectWeakPtr<T>` is similar to `std::weak_ptr<T>`, but holds on to
874an object of a `BaseObject` subclass `T` and integrates with the lifetime
875management of the former. When the `BaseObject` no longer exists, e.g. when
876it was garbage collected, accessing it through `weak_ptr.get()` will return
877`nullptr`.
878
879`BaseObjectPtr<T>` is similar to `std::shared_ptr<T>`, but also holds on to
880objects of a `BaseObject` subclass `T`. While there are `BaseObjectPtr`s
881pointing to a given object, the `BaseObject` will always maintain a strong
882reference to its associated JavaScript object. This can be useful when one
883`BaseObject` refers to another `BaseObject` and wants to make sure it stays
884alive during the lifetime of that reference.
885
886A `BaseObject` can be “detached” through the `BaseObject::Detach()` method.
887In this case, it will be deleted once the last `BaseObjectPtr` referring to
888it is destroyed. There must be at least one such pointer when `Detach()` is
889called. This can be useful when one `BaseObject` fully owns another
890`BaseObject`.
891
892<a id="asyncwrap"></a>
893
894### `AsyncWrap`
895
896`AsyncWrap` is a subclass of `BaseObject` that additionally provides tracking
897functions for asynchronous calls. It is commonly used for classes whose methods
898make calls into JavaScript without any JavaScript stack below, i.e. more or less
899directly from the event loop. It is defined in [`async_wrap.h`][].
900
901Every `AsyncWrap` subclass has a “provider type”. A list of provider types is
902maintained in `src/async_wrap.h`.
903
904Every `AsyncWrap` instance is associated with two numbers, the “async id”
905and the “async trigger id”. The “async id” is generally unique per `AsyncWrap`
906instance, and only changes when the object is re-used in some way.
907
908See the [`async_hooks` module][] documentation for more information about how
909this information is provided to async tracking tools.
910
911<a id="makecallback"></a>
912
913#### `MakeCallback`
914
915The `AsyncWrap` class has a set of methods called `MakeCallback()`, with the
916intention of the naming being that it is used to “make calls back into
917JavaScript” from the event loop, rather than making callbacks in some way.
918(As the naming has made its way into the Node.js public API, it's not worth
919the breakage of fixing it).
920
921`MakeCallback()` generally calls a method on the JavaScript object associated
922with the current `AsyncWrap`, and informs async tracking code about these calls
923as well as takes care of running the `process.nextTick()` and `Promise` task
924queues once it returns.
925
926Before calling `MakeCallback()`, it is typically necessary to enter both a
927`HandleScope` and a `Context::Scope`.
928
929```cpp
930void StatWatcher::Callback(uv_fs_poll_t* handle,
931                           int status,
932                           const uv_stat_t* prev,
933                           const uv_stat_t* curr) {
934  // Get the StatWatcher instance associated with this call from libuv,
935  // StatWatcher is a subclass of AsyncWrap.
936  StatWatcher* wrap = ContainerOf(&StatWatcher::watcher_, handle);
937  Environment* env = wrap->env();
938  HandleScope handle_scope(env->isolate());
939  Context::Scope context_scope(env->context());
940
941  // Transform 'prev' and 'curr' into an array:
942  Local<Value> arr = ...;
943
944  Local<Value> argv[] = { Integer::New(env->isolate(), status), arr };
945  wrap->MakeCallback(env->onchange_string(), arraysize(argv), argv);
946}
947```
948
949See [Callback scopes][] for more information.
950
951<a id="handlewrap"></a>
952
953### `HandleWrap`
954
955`HandleWrap` is a subclass of `AsyncWrap` specifically designed to make working
956with [libuv handles][] easier. It provides the `.ref()`, `.unref()` and
957`.hasRef()` methods as well as `.close()` to enable easier lifetime management
958from JavaScript. It is defined in [`handle_wrap.h`][].
959
960`HandleWrap` instances are [cleaned up][cleanup hooks] automatically when the
961current Node.js [`Environment`][] is destroyed, e.g. when a Worker thread stops.
962
963`HandleWrap` also provides facilities for diagnostic tooling to get an
964overview over libuv handles managed by Node.js.
965
966<a id="reqwrap"></a>
967
968### `ReqWrap`
969
970`ReqWrap` is a subclass of `AsyncWrap` specifically designed to make working
971with [libuv requests][] easier. It is defined in [`req_wrap.h`][].
972
973In particular, its `Dispatch()` method is designed to avoid the need to keep
974track of the current count of active libuv requests.
975
976`ReqWrap` also provides facilities for diagnostic tooling to get an
977overview over libuv handles managed by Node.js.
978
979<a id="callback-scopes"></a>
980
981### Callback scopes
982
983The public `CallbackScope` and the internally used `InternalCallbackScope`
984classes provide the same facilities as [`MakeCallback()`][], namely:
985
986* Emitting the `'before'` event for async tracking when entering the scope
987* Setting the current async IDs to the ones passed to the constructor
988* Emitting the `'after'` event for async tracking when leaving the scope
989* Running the `process.nextTick()` queue
990* Running microtasks, in particular `Promise` callbacks and async/await
991  functions
992
993Usually, using `AsyncWrap::MakeCallback()` or using the constructor taking
994an `AsyncWrap*` argument (i.e. used as
995`InternalCallbackScope callback_scope(this);`) suffices inside of the Node.js
996C++ codebase.
997
998## C++ utilities
999
1000Node.js uses a few custom C++ utilities, mostly defined in [`util.h`][].
1001
1002### Memory allocation
1003
1004Node.js provides `Malloc()`, `Realloc()` and `Calloc()` functions that work
1005like their C stdlib counterparts, but crash if memory cannot be allocated.
1006(As V8 does not handle out-of-memory situations gracefully, it does not make
1007sense for Node.js to attempt to do so in all cases.)
1008
1009The `UncheckedMalloc()`, `UncheckedRealloc()` and `UncheckedCalloc()` functions
1010return `nullptr` in these cases (or when `size == 0`).
1011
1012#### Optional stack-based memory allocation
1013
1014The `MaybeStackBuffer` class provides a way to allocate memory on the stack
1015if it is smaller than a given limit, and falls back to allocating it on the
1016heap if it is larger. This can be useful for performantly allocating temporary
1017data if it is typically expected to be small (e.g. file paths).
1018
1019The `Utf8Value`, `TwoByteValue` (i.e. UTF-16 value) and `BufferValue`
1020(`Utf8Value` but copy data from a `Buffer` if one is passed) helpers
1021inherit from this class and allow accessing the characters in a JavaScript
1022string this way.
1023
1024```cpp
1025static void Chdir(const FunctionCallbackInfo<Value>& args) {
1026  Environment* env = Environment::GetCurrent(args);
1027  // ...
1028  CHECK(args[0]->IsString());
1029  Utf8Value path(env->isolate(), args[0]);
1030  int err = uv_chdir(*path);
1031  if (err) {
1032    // ... error handling ...
1033  }
1034}
1035```
1036
1037### Assertions
1038
1039Node.js provides a few macros that behave similar to `assert()`:
1040
1041* `CHECK(expression)` aborts the process with a stack trace
1042  if `expression` is false.
1043* `CHECK_EQ(a, b)` checks for `a == b`
1044* `CHECK_GE(a, b)` checks for `a >= b`
1045* `CHECK_GT(a, b)` checks for `a > b`
1046* `CHECK_LE(a, b)` checks for `a <= b`
1047* `CHECK_LT(a, b)` checks for `a < b`
1048* `CHECK_NE(a, b)` checks for `a != b`
1049* `CHECK_NULL(val)` checks for `a == nullptr`
1050* `CHECK_NOT_NULL(val)` checks for `a != nullptr`
1051* `CHECK_IMPLIES(a, b)` checks that `b` is true if `a` is true.
1052* `UNREACHABLE([message])` aborts the process if it is reached.
1053
1054`CHECK`s are always enabled. For checks that should only run in debug mode, use
1055`DCHECK()`, `DCHECK_EQ()`, etc.
1056
1057### Scope-based cleanup
1058
1059The `OnScopeLeave()` function can be used to run a piece of code when leaving
1060the current C++ scope.
1061
1062```cpp
1063static void GetUserInfo(const FunctionCallbackInfo<Value>& args) {
1064  Environment* env = Environment::GetCurrent(args);
1065  uv_passwd_t pwd;
1066  // ...
1067
1068  const int err = uv_os_get_passwd(&pwd);
1069
1070  if (err) {
1071    // ... error handling, return early ...
1072  }
1073
1074  auto free_passwd = OnScopeLeave([&]() { uv_os_free_passwd(&pwd); });
1075
1076  // ...
1077  // Turn `pwd` into a JavaScript object now; whenever we return from this
1078  // function, `uv_os_free_passwd()` will be called.
1079  // ...
1080}
1081```
1082
1083[C++ coding style]: ../doc/contributing/cpp-style-guide.md
1084[Callback scopes]: #callback-scopes
1085[ECMAScript realm]: https://tc39.es/ecma262/#sec-code-realms
1086[JavaScript value handles]: #js-handles
1087[N-API]: https://nodejs.org/api/n-api.html
1088[`BaseObject`]: #baseobject
1089[`Context`]: #context
1090[`Environment`]: #environment
1091[`Global`]: #global-handles
1092[`HandleWrap`]: #handlewrap
1093[`IsolateData`]: #isolate-data
1094[`Isolate`]: #isolate
1095[`Local`]: #local-handles
1096[`MakeCallback()`]: #makecallback
1097[`MessagePort`]: https://nodejs.org/api/worker_threads.html#worker_threads_class_messageport
1098[`Realm`]: #realm
1099[`ReqWrap`]: #reqwrap
1100[`ShadowRealm`]: https://github.com/tc39/proposal-shadowrealm
1101[`async_hooks` module]: https://nodejs.org/api/async_hooks.html
1102[`async_wrap.h`]: async_wrap.h
1103[`base_object.h`]: base_object.h
1104[`handle_wrap.h`]: handle_wrap.h
1105[`memory_tracker.h`]: memory_tracker.h
1106[`req_wrap.h`]: req_wrap.h
1107[`util.h`]: util.h
1108[`v8.h` in Code Search]: https://cs.chromium.org/chromium/src/v8/include/v8.h
1109[`v8.h` in Node.js]: https://github.com/nodejs/node/blob/HEAD/deps/v8/include/v8.h
1110[`v8.h` in V8]: https://github.com/v8/v8/blob/HEAD/include/v8.h
1111[`vm` module]: https://nodejs.org/api/vm.html
1112[binding function]: #binding-functions
1113[cleanup hooks]: #cleanup-hooks
1114[event loop]: #event-loop
1115[exception handling]: #exception-handling
1116[fast API calls]: ../doc/contributing/adding-v8-fast-api.md
1117[internal field]: #internal-fields
1118[introduction for V8 embedders]: https://v8.dev/docs/embed
1119[libuv]: https://libuv.org/
1120[libuv handles]: #libuv-handles-and-requests
1121[libuv requests]: #libuv-handles-and-requests
1122[reference documentation for the libuv API]: http://docs.libuv.org/en/v1.x/
1123