@@ -589,6 +589,68 @@ void InitializeHttpParser(Local<Object> target,
589
589
}
590
590
```
591
591
592
+ ### Argument validation in public APIs vs. internal code
593
+
594
+ #### Public API argument sanitization
595
+
596
+ When arguments come directly from user code, Node.js will typically validate them at the
597
+ JavaScript layer and throws user-friendly
598
+ [errors](https://github.com/nodejs/node/blob/main/doc/contributing/using-internal-errors.md)
599
+ (e.g., `ERR_INVALID_*`), if they are invalid. This helps end users
600
+ quickly understand and fix mistakes in their own code.
601
+
602
+ This approach ensures that the error message pinpoints which argument is wrong
603
+ and how it should be fixed. Additionally, problems in user code do not cause
604
+ mysterious crashes or hard-to-diagnose failures deeper in the engine.
605
+
606
+ Example from `zlib.js`:
607
+
608
+ ```js
609
+ function crc32(data, value = 0) {
610
+ if (typeof data !== 'string' && !isArrayBufferView(data)) {
611
+ throw new ERR_INVALID_ARG_TYPE('data', ['Buffer', 'TypedArray', 'DataView','string'], data);
612
+ }
613
+ validateUint32(value, 'value');
614
+ return crc32Native(data, value);
615
+ }
616
+ ```
617
+
618
+ The corresponding C++ assertion code for the above example from it's binding ` node_zlib.cc ` :
619
+
620
+ ``` cpp
621
+ CHECK (args[ 0] ->IsArrayBufferView() || args[ 0] ->IsString());
622
+ CHECK(args[ 1] ->IsUint32());
623
+ ```
624
+
625
+ #### Internal code and C++ binding checks
626
+
627
+ Inside Node.js’s internal layers, especially the C++ [binding function][]s
628
+ typically assume their arguments have already been checked and sanitized
629
+ by the upper-level (JavaScript) callers. As a result, internal C++ code
630
+ often just uses `CHECK()` or similar assertions to confirm that the
631
+ types/values passed in are correct. If that assertion fails, Node.js will
632
+ crash or abort with an internal diagnostic message. This is to avoid
633
+ re-validating every internal function argument repeatedly which can slow
634
+ down the system.
635
+
636
+ However, in a less common case where the API is implemented completely in
637
+ C++, the arguments would be validated directly in C++, with the errors
638
+ thrown using `THROW_ERR_INVALID_*` macros from `src/node_errors.h`.
639
+
640
+ For example in `worker_threads.moveMessagePortToContext`:
641
+
642
+ ```cpp
643
+ void MessagePort::MoveToContext(const FunctionCallbackInfo<Value>& args) {
644
+ Environment* env = Environment::GetCurrent(args);
645
+ if (!args[0]->IsObject() ||
646
+ !env->message_port_constructor_template()->HasInstance(args[0])) {
647
+ return THROW_ERR_INVALID_ARG_TYPE(env,
648
+ "The \"port\" argument must be a MessagePort instance");
649
+ }
650
+ // ...
651
+ }
652
+ ```
653
+
592
654
<a id =" exception-handling " ></a >
593
655
594
656
### Exception handling
0 commit comments