Name |
Date |
Size |
#Lines |
LOC |
||
---|---|---|---|---|---|---|
.. | - | - | ||||
api/ | 07-Sep-2024 | - | 2,310 | 1,785 | ||
crypto/ | 07-Sep-2024 | - | 20,134 | 15,604 | ||
dataqueue/ | 07-Sep-2024 | - | 295 | 60 | ||
inspector/ | 07-Sep-2024 | - | 1,766 | 1,450 | ||
large_pages/ | 07-Sep-2024 | - | 509 | 347 | ||
permission/ | 07-Sep-2024 | - | 605 | 454 | ||
quic/ | 07-Sep-2024 | - | 2,805 | 2,075 | ||
res/ | 07-Sep-2024 | - | 272 | 249 | ||
tracing/ | 07-Sep-2024 | - | 3,217 | 2,250 | ||
README.md | D | 07-Sep-2024 | 43.4 KiB | 1,123 | 848 | |
acorn_version.h | D | 07-Sep-2024 | 210 | 7 | 4 | |
aliased_buffer-inl.h | D | 07-Sep-2024 | 7.4 KiB | 233 | 180 | |
aliased_buffer.h | D | 07-Sep-2024 | 6.1 KiB | 198 | 100 | |
aliased_struct-inl.h | D | 07-Sep-2024 | 1.3 KiB | 55 | 40 | |
aliased_struct.h | D | 07-Sep-2024 | 1.4 KiB | 64 | 33 | |
async_wrap-inl.h | D | 07-Sep-2024 | 2.7 KiB | 88 | 49 | |
async_wrap.cc | D | 07-Sep-2024 | 26.1 KiB | 715 | 518 | |
async_wrap.h | D | 07-Sep-2024 | 11.3 KiB | 249 | 185 | |
base64-inl.h | D | 07-Sep-2024 | 5.8 KiB | 194 | 155 | |
base64.h | D | 07-Sep-2024 | 1.4 KiB | 54 | 36 | |
base64_version.h | D | 07-Sep-2024 | 227 | 7 | 4 | |
base_object-inl.h | D | 07-Sep-2024 | 9 KiB | 303 | 226 | |
base_object.cc | D | 07-Sep-2024 | 5.1 KiB | 165 | 131 | |
base_object.h | D | 07-Sep-2024 | 13.3 KiB | 315 | 148 | |
base_object_types.h | D | 07-Sep-2024 | 3.3 KiB | 72 | 41 | |
blob_serializer_deserializer-inl.h | D | 07-Sep-2024 | 10.5 KiB | 360 | 281 | |
blob_serializer_deserializer.h | D | 07-Sep-2024 | 3.6 KiB | 129 | 71 | |
callback_queue-inl.h | D | 07-Sep-2024 | 2.6 KiB | 98 | 79 | |
callback_queue.h | D | 07-Sep-2024 | 2 KiB | 79 | 50 | |
cares_wrap.cc | D | 07-Sep-2024 | 60.6 KiB | 1,986 | 1,544 | |
cares_wrap.h | D | 07-Sep-2024 | 14.2 KiB | 525 | 425 | |
cjs_module_lexer_version.h | D | 07-Sep-2024 | 277 | 7 | 4 | |
cleanup_queue-inl.h | D | 07-Sep-2024 | 1.6 KiB | 63 | 47 | |
cleanup_queue.cc | D | 07-Sep-2024 | 1.7 KiB | 53 | 35 | |
cleanup_queue.h | D | 07-Sep-2024 | 2.2 KiB | 86 | 57 | |
connect_wrap.cc | D | 07-Sep-2024 | 305 | 17 | 11 | |
connect_wrap.h | D | 07-Sep-2024 | 584 | 27 | 18 | |
connection_wrap.cc | D | 07-Sep-2024 | 4.4 KiB | 143 | 102 | |
connection_wrap.h | D | 07-Sep-2024 | 686 | 31 | 20 | |
debug_utils-inl.h | D | 07-Sep-2024 | 7.4 KiB | 227 | 192 | |
debug_utils.cc | D | 07-Sep-2024 | 15.4 KiB | 519 | 390 | |
debug_utils.h | D | 07-Sep-2024 | 6.8 KiB | 187 | 127 | |
diagnosticfilename-inl.h | D | 07-Sep-2024 | 768 | 34 | 24 | |
env-inl.h | D | 07-Sep-2024 | 25.3 KiB | 865 | 667 | |
env.cc | D | 07-Sep-2024 | 69.1 KiB | 1,870 | 1,433 | |
env.h | D | 07-Sep-2024 | 38.5 KiB | 1,109 | 778 | |
env_properties.h | D | 07-Sep-2024 | 33.5 KiB | 442 | 415 | |
fs_event_wrap.cc | D | 07-Sep-2024 | 7.9 KiB | 244 | 167 | |
handle_wrap.cc | D | 07-Sep-2024 | 5.5 KiB | 186 | 122 | |
handle_wrap.h | D | 07-Sep-2024 | 4.2 KiB | 122 | 55 | |
heap_utils.cc | D | 07-Sep-2024 | 14 KiB | 469 | 404 | |
histogram-inl.h | D | 07-Sep-2024 | 2.4 KiB | 108 | 89 | |
histogram.cc | D | 07-Sep-2024 | 21.7 KiB | 636 | 559 | |
histogram.h | D | 07-Sep-2024 | 7.9 KiB | 240 | 189 | |
inspector_agent.cc | D | 07-Sep-2024 | 31.8 KiB | 1,017 | 828 | |
inspector_agent.h | D | 07-Sep-2024 | 4.7 KiB | 145 | 90 | |
inspector_io.cc | D | 07-Sep-2024 | 11.5 KiB | 385 | 326 | |
inspector_io.h | D | 07-Sep-2024 | 2.2 KiB | 79 | 45 | |
inspector_js_api.cc | D | 07-Sep-2024 | 14.1 KiB | 407 | 333 | |
inspector_profiler.cc | D | 07-Sep-2024 | 16.3 KiB | 531 | 464 | |
inspector_profiler.h | D | 07-Sep-2024 | 4.5 KiB | 150 | 101 | |
inspector_socket.cc | D | 07-Sep-2024 | 25.7 KiB | 820 | 647 | |
inspector_socket.h | D | 07-Sep-2024 | 1.5 KiB | 61 | 42 | |
inspector_socket_server.cc | D | 07-Sep-2024 | 17.7 KiB | 563 | 494 | |
inspector_socket_server.h | D | 07-Sep-2024 | 3.5 KiB | 111 | 83 | |
js_native_api.h | D | 07-Sep-2024 | 28.1 KiB | 562 | 449 | |
js_native_api_types.h | D | 07-Sep-2024 | 4.4 KiB | 164 | 125 | |
js_native_api_v8.cc | D | 07-Sep-2024 | 163.6 KiB | 4,722 | 3,639 | |
js_native_api_v8.h | D | 07-Sep-2024 | 20.6 KiB | 549 | 424 | |
js_native_api_v8_inspector.cc | D | 07-Sep-2024 | 42.2 KiB | 1,444 | 1,159 | |
js_native_api_v8_inspector.h | D | 07-Sep-2024 | 3.9 KiB | 133 | 76 | |
js_native_api_v8_internals.h | D | 07-Sep-2024 | 1.6 KiB | 46 | 22 | |
js_stream.cc | D | 07-Sep-2024 | 6 KiB | 220 | 168 | |
js_stream.h | D | 07-Sep-2024 | 1.4 KiB | 53 | 37 | |
js_udp_wrap.cc | D | 07-Sep-2024 | 6.9 KiB | 221 | 178 | |
json_utils.cc | D | 07-Sep-2024 | 1.9 KiB | 70 | 57 | |
json_utils.h | D | 07-Sep-2024 | 3.8 KiB | 173 | 148 | |
jsvm.h | D | 07-Sep-2024 | 109.6 KiB | 2,488 | 570 | |
jsvm_node_api.h | D | 07-Sep-2024 | 9.8 KiB | 261 | 197 | |
jsvm_node_api_types.h | D | 07-Sep-2024 | 1.6 KiB | 53 | 42 | |
jsvm_types.h | D | 07-Sep-2024 | 18.6 KiB | 618 | 218 | |
memory_tracker-inl.h | D | 07-Sep-2024 | 12 KiB | 357 | 286 | |
memory_tracker.h | D | 07-Sep-2024 | 11.5 KiB | 290 | 157 | |
module_wrap.cc | D | 07-Sep-2024 | 26.8 KiB | 828 | 678 | |
module_wrap.h | D | 07-Sep-2024 | 3.7 KiB | 118 | 93 | |
node.cc | D | 07-Sep-2024 | 42.3 KiB | 1,295 | 924 | |
node.d | D | 07-Sep-2024 | 12 KiB | 316 | 197 | |
node.h | D | 07-Sep-2024 | 56.4 KiB | 1,340 | 849 | |
node.stp | D | 07-Sep-2024 | 3.4 KiB | 147 | 126 | |
node_api.cc | D | 07-Sep-2024 | 45.5 KiB | 1,416 | 1,105 | |
node_api.h | D | 07-Sep-2024 | 11.4 KiB | 276 | 217 | |
node_api_internals.h | D | 07-Sep-2024 | 1.2 KiB | 43 | 32 | |
node_api_types.h | D | 07-Sep-2024 | 1.6 KiB | 51 | 42 | |
node_binding.cc | D | 07-Sep-2024 | 26 KiB | 736 | 576 | |
node_binding.h | D | 07-Sep-2024 | 4.2 KiB | 122 | 85 | |
node_blob.cc | D | 07-Sep-2024 | 15.5 KiB | 501 | 417 | |
node_blob.h | D | 07-Sep-2024 | 5 KiB | 189 | 141 | |
node_bob-inl.h | D | 07-Sep-2024 | 657 | 38 | 27 | |
node_bob.h | D | 07-Sep-2024 | 2.8 KiB | 112 | 54 | |
node_buffer.cc | D | 07-Sep-2024 | 47 KiB | 1,478 | 1,118 | |
node_buffer.h | D | 07-Sep-2024 | 3.6 KiB | 93 | 43 | |
node_builtins.cc | D | 07-Sep-2024 | 26.2 KiB | 747 | 624 | |
node_builtins.h | D | 07-Sep-2024 | 5.6 KiB | 156 | 109 | |
node_config.cc | D | 07-Sep-2024 | 2.4 KiB | 90 | 62 | |
node_constants.cc | D | 07-Sep-2024 | 30.7 KiB | 1,424 | 1,069 | |
node_constants.h | D | 07-Sep-2024 | 3.7 KiB | 85 | 50 | |
node_context_data.h | D | 07-Sep-2024 | 2.9 KiB | 100 | 71 | |
node_contextify.cc | D | 07-Sep-2024 | 47.9 KiB | 1,441 | 1,089 | |
node_contextify.h | D | 07-Sep-2024 | 7.1 KiB | 197 | 160 | |
node_credentials.cc | D | 07-Sep-2024 | 13.4 KiB | 488 | 369 | |
node_crypto.cc | D | 07-Sep-2024 | 4.2 KiB | 98 | 65 | |
node_crypto.h | D | 07-Sep-2024 | 2.3 KiB | 57 | 27 | |
node_dir.cc | D | 07-Sep-2024 | 14 KiB | 431 | 340 | |
node_dir.h | D | 07-Sep-2024 | 1.3 KiB | 53 | 33 | |
node_dtrace.cc | D | 07-Sep-2024 | 13.5 KiB | 322 | 237 | |
node_dtrace.h | D | 07-Sep-2024 | 2.9 KiB | 87 | 32 | |
node_env_var.cc | D | 07-Sep-2024 | 16.1 KiB | 491 | 411 | |
node_errors.cc | D | 07-Sep-2024 | 34.5 KiB | 1,209 | 926 | |
node_errors.h | D | 07-Sep-2024 | 16.9 KiB | 289 | 245 | |
node_external_reference.cc | D | 07-Sep-2024 | 710 | 28 | 20 | |
node_external_reference.h | D | 07-Sep-2024 | 7.9 KiB | 154 | 129 | |
node_file-inl.h | D | 07-Sep-2024 | 12.4 KiB | 357 | 300 | |
node_file.cc | D | 07-Sep-2024 | 96.4 KiB | 2,860 | 2,272 | |
node_file.h | D | 07-Sep-2024 | 14.7 KiB | 485 | 354 | |
node_http2.cc | D | 07-Sep-2024 | 118 KiB | 3,350 | 2,406 | |
node_http2.h | D | 07-Sep-2024 | 38.6 KiB | 1,147 | 812 | |
node_http2_state.h | D | 07-Sep-2024 | 4.8 KiB | 148 | 128 | |
node_http_common-inl.h | D | 07-Sep-2024 | 5.5 KiB | 202 | 166 | |
node_http_common.h | D | 07-Sep-2024 | 24.6 KiB | 533 | 432 | |
node_http_parser.cc | D | 07-Sep-2024 | 36.7 KiB | 1,280 | 906 | |
node_i18n.cc | D | 07-Sep-2024 | 30.3 KiB | 910 | 674 | |
node_i18n.h | D | 07-Sep-2024 | 4.3 KiB | 146 | 86 | |
node_internals.h | D | 07-Sep-2024 | 15 KiB | 434 | 317 | |
node_main.cc | D | 07-Sep-2024 | 3.6 KiB | 96 | 60 | |
node_main_instance.cc | D | 07-Sep-2024 | 6 KiB | 196 | 159 | |
node_main_instance.h | D | 07-Sep-2024 | 3 KiB | 94 | 55 | |
node_mem-inl.h | D | 07-Sep-2024 | 3.6 KiB | 113 | 84 | |
node_mem.h | D | 07-Sep-2024 | 1.3 KiB | 46 | 24 | |
node_messaging.cc | D | 07-Sep-2024 | 52.1 KiB | 1,557 | 1,221 | |
node_messaging.h | D | 07-Sep-2024 | 14.3 KiB | 374 | 212 | |
node_metadata.cc | D | 07-Sep-2024 | 3.7 KiB | 149 | 123 | |
node_metadata.h | D | 07-Sep-2024 | 4.4 KiB | 139 | 110 | |
node_mutex.h | D | 07-Sep-2024 | 7.8 KiB | 324 | 247 | |
node_object_wrap.h | D | 07-Sep-2024 | 3.8 KiB | 133 | 69 | |
node_options-inl.h | D | 07-Sep-2024 | 15.9 KiB | 479 | 377 | |
node_options.cc | D | 07-Sep-2024 | 51 KiB | 1,352 | 1,205 | |
node_options.h | D | 07-Sep-2024 | 17.6 KiB | 534 | 387 | |
node_os.cc | D | 07-Sep-2024 | 14.7 KiB | 435 | 329 | |
node_perf.cc | D | 07-Sep-2024 | 13.4 KiB | 379 | 317 | |
node_perf.h | D | 07-Sep-2024 | 4.8 KiB | 169 | 139 | |
node_perf_common.h | D | 07-Sep-2024 | 2.9 KiB | 93 | 69 | |
node_platform.cc | D | 07-Sep-2024 | 19.9 KiB | 642 | 516 | |
node_platform.h | D | 07-Sep-2024 | 6.2 KiB | 196 | 146 | |
node_postmortem_metadata.cc | D | 07-Sep-2024 | 3.2 KiB | 73 | 55 | |
node_process-inl.h | D | 07-Sep-2024 | 737 | 27 | 17 | |
node_process.h | D | 07-Sep-2024 | 3.4 KiB | 99 | 67 | |
node_process_events.cc | D | 07-Sep-2024 | 3.3 KiB | 107 | 83 | |
node_process_methods.cc | D | 07-Sep-2024 | 21 KiB | 642 | 500 | |
node_process_object.cc | D | 07-Sep-2024 | 8.7 KiB | 259 | 206 | |
node_provider.d | D | 07-Sep-2024 | 3.3 KiB | 81 | 41 | |
node_realm-inl.h | D | 07-Sep-2024 | 4.6 KiB | 149 | 116 | |
node_realm.cc | D | 07-Sep-2024 | 12.2 KiB | 329 | 230 | |
node_realm.h | D | 07-Sep-2024 | 5.4 KiB | 157 | 100 | |
node_report.cc | D | 07-Sep-2024 | 33.2 KiB | 990 | 808 | |
node_report.h | D | 07-Sep-2024 | 994 | 43 | 29 | |
node_report_module.cc | D | 07-Sep-2024 | 7.9 KiB | 223 | 190 | |
node_report_utils.cc | D | 07-Sep-2024 | 8.4 KiB | 273 | 239 | |
node_revert.h | D | 07-Sep-2024 | 2.1 KiB | 83 | 57 | |
node_root_certs.h | D | 07-Sep-2024 | 233.2 KiB | 3,575 | 3,280 | |
node_sea.cc | D | 07-Sep-2024 | 3.6 KiB | 125 | 92 | |
node_sea.h | D | 07-Sep-2024 | 517 | 25 | 15 | |
node_serdes.cc | D | 07-Sep-2024 | 18.6 KiB | 546 | 431 | |
node_shadow_realm.cc | D | 07-Sep-2024 | 350 | 17 | 12 | |
node_shadow_realm.h | D | 07-Sep-2024 | 449 | 20 | 12 | |
node_snapshot_builder.h | D | 07-Sep-2024 | 1.2 KiB | 43 | 27 | |
node_snapshot_stub.cc | D | 07-Sep-2024 | 327 | 14 | 7 | |
node_snapshotable.cc | D | 07-Sep-2024 | 51.9 KiB | 1,539 | 1,187 | |
node_snapshotable.h | D | 07-Sep-2024 | 4.8 KiB | 129 | 82 | |
node_sockaddr-inl.h | D | 07-Sep-2024 | 7.3 KiB | 267 | 207 | |
node_sockaddr.cc | D | 07-Sep-2024 | 26.6 KiB | 891 | 747 | |
node_sockaddr.h | D | 07-Sep-2024 | 12.9 KiB | 406 | 278 | |
node_stat_watcher.cc | D | 07-Sep-2024 | 4.3 KiB | 127 | 81 | |
node_stat_watcher.h | D | 07-Sep-2024 | 2.4 KiB | 73 | 38 | |
node_symbols.cc | D | 07-Sep-2024 | 991 | 33 | 26 | |
node_task_queue.cc | D | 07-Sep-2024 | 8.1 KiB | 232 | 183 | |
node_threadsafe_cow-inl.h | D | 07-Sep-2024 | 1.3 KiB | 55 | 41 | |
node_threadsafe_cow.h | D | 07-Sep-2024 | 2.8 KiB | 106 | 74 | |
node_trace_events.cc | D | 07-Sep-2024 | 5.9 KiB | 175 | 146 | |
node_types.cc | D | 07-Sep-2024 | 3.7 KiB | 90 | 75 | |
node_union_bytes.h | D | 07-Sep-2024 | 1.7 KiB | 58 | 40 | |
node_url.cc | D | 07-Sep-2024 | 12.4 KiB | 387 | 315 | |
node_url.h | D | 07-Sep-2024 | 2.1 KiB | 80 | 58 | |
node_util.cc | D | 07-Sep-2024 | 15.8 KiB | 493 | 396 | |
node_util.h | D | 07-Sep-2024 | 1.4 KiB | 53 | 39 | |
node_v8.cc | D | 07-Sep-2024 | 18.8 KiB | 484 | 400 | |
node_v8.h | D | 07-Sep-2024 | 1.7 KiB | 70 | 51 | |
node_v8_platform-inl.h | D | 07-Sep-2024 | 6.6 KiB | 206 | 156 | |
node_version.h | D | 07-Sep-2024 | 3.8 KiB | 103 | 44 | |
node_wasi.cc | D | 07-Sep-2024 | 63.6 KiB | 1,769 | 1,586 | |
node_wasi.h | D | 07-Sep-2024 | 5.2 KiB | 110 | 94 | |
node_wasm_web_api.cc | D | 07-Sep-2024 | 7.2 KiB | 215 | 154 | |
node_wasm_web_api.h | D | 07-Sep-2024 | 1.8 KiB | 56 | 36 | |
node_watchdog.cc | D | 07-Sep-2024 | 12.4 KiB | 438 | 301 | |
node_watchdog.h | D | 07-Sep-2024 | 4.3 KiB | 155 | 105 | |
node_win32_etw_provider-inl.h | D | 07-Sep-2024 | 11.5 KiB | 289 | 216 | |
node_win32_etw_provider.cc | D | 07-Sep-2024 | 6.3 KiB | 214 | 135 | |
node_win32_etw_provider.h | D | 07-Sep-2024 | 3.7 KiB | 100 | 65 | |
node_worker.cc | D | 07-Sep-2024 | 31.9 KiB | 967 | 749 | |
node_worker.h | D | 07-Sep-2024 | 4.9 KiB | 151 | 99 | |
node_zlib.cc | D | 07-Sep-2024 | 44.3 KiB | 1,436 | 1,119 | |
pipe_wrap.cc | D | 07-Sep-2024 | 8.2 KiB | 260 | 186 | |
pipe_wrap.h | D | 07-Sep-2024 | 2.8 KiB | 81 | 45 | |
process_wrap.cc | D | 07-Sep-2024 | 10.9 KiB | 325 | 235 | |
req_wrap-inl.h | D | 07-Sep-2024 | 5.4 KiB | 172 | 114 | |
req_wrap.h | D | 07-Sep-2024 | 2.2 KiB | 78 | 45 | |
signal_wrap.cc | D | 07-Sep-2024 | 5.8 KiB | 180 | 130 | |
sourcemap.def | D | 07-Sep-2024 | 12.5 KiB | 395 | 363 | |
spawn_sync.cc | D | 07-Sep-2024 | 29.9 KiB | 1,108 | 761 | |
spawn_sync.h | D | 07-Sep-2024 | 6.9 KiB | 243 | 157 | |
stream_base-inl.h | D | 07-Sep-2024 | 4.9 KiB | 174 | 138 | |
stream_base.cc | D | 07-Sep-2024 | 25.9 KiB | 837 | 653 | |
stream_base.h | D | 07-Sep-2024 | 17.4 KiB | 468 | 241 | |
stream_pipe.cc | D | 07-Sep-2024 | 10.8 KiB | 336 | 271 | |
stream_pipe.h | D | 07-Sep-2024 | 2.4 KiB | 77 | 54 | |
stream_wrap.cc | D | 07-Sep-2024 | 12.8 KiB | 422 | 307 | |
stream_wrap.h | D | 07-Sep-2024 | 4.1 KiB | 132 | 74 | |
string_bytes.cc | D | 07-Sep-2024 | 23.1 KiB | 725 | 555 | |
string_bytes.h | D | 07-Sep-2024 | 4.7 KiB | 121 | 64 | |
string_decoder-inl.h | D | 07-Sep-2024 | 858 | 38 | 25 | |
string_decoder.cc | D | 07-Sep-2024 | 11.9 KiB | 349 | 258 | |
string_decoder.h | D | 07-Sep-2024 | 1.5 KiB | 51 | 31 | |
string_search.h | D | 07-Sep-2024 | 20.9 KiB | 639 | 455 | |
tcp_wrap.cc | D | 07-Sep-2024 | 14.9 KiB | 456 | 357 | |
tcp_wrap.h | D | 07-Sep-2024 | 3.9 KiB | 106 | 68 | |
threadpoolwork-inl.h | D | 07-Sep-2024 | 2.6 KiB | 71 | 41 | |
timer_wrap-inl.h | D | 07-Sep-2024 | 755 | 33 | 22 | |
timer_wrap.cc | D | 07-Sep-2024 | 1.8 KiB | 84 | 66 | |
timer_wrap.h | D | 07-Sep-2024 | 1.8 KiB | 86 | 53 | |
timers.cc | D | 07-Sep-2024 | 2.5 KiB | 82 | 66 | |
tty_wrap.cc | D | 07-Sep-2024 | 5.1 KiB | 162 | 108 | |
tty_wrap.h | D | 07-Sep-2024 | 2.3 KiB | 66 | 32 | |
udp_wrap.cc | D | 07-Sep-2024 | 24.2 KiB | 810 | 628 | |
udp_wrap.h | D | 07-Sep-2024 | 8.5 KiB | 228 | 141 | |
undici_version.h | D | 07-Sep-2024 | 215 | 7 | 4 | |
util-inl.h | D | 07-Sep-2024 | 19.6 KiB | 624 | 488 | |
util.cc | D | 07-Sep-2024 | 19.5 KiB | 581 | 470 | |
util.h | D | 07-Sep-2024 | 31.5 KiB | 927 | 662 | |
uv.cc | D | 07-Sep-2024 | 4.8 KiB | 142 | 99 | |
v8abbr.h | D | 07-Sep-2024 | 5 KiB | 124 | 73 | |
v8ustack.d | D | 07-Sep-2024 | 21 KiB | 696 | 459 |
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