doc: improve documentation on argument validation
PR-URL: https://github.com/nodejs/node/pull/56954 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
This commit is contained in:
parent
e4f2c25527
commit
f208027c3b
@ -589,6 +589,68 @@ void InitializeHttpParser(Local<Object> target,
|
||||
}
|
||||
```
|
||||
|
||||
### Argument validation in public APIs vs. internal code
|
||||
|
||||
#### Public API argument sanitization
|
||||
|
||||
When arguments come directly from user code, Node.js will typically validate them at the
|
||||
JavaScript layer and throws user-friendly
|
||||
[errors](https://github.com/nodejs/node/blob/main/doc/contributing/using-internal-errors.md)
|
||||
(e.g., `ERR_INVALID_*`), if they are invalid. This helps end users
|
||||
quickly understand and fix mistakes in their own code.
|
||||
|
||||
This approach ensures that the error message pinpoints which argument is wrong
|
||||
and how it should be fixed. Additionally, problems in user code do not cause
|
||||
mysterious crashes or hard-to-diagnose failures deeper in the engine.
|
||||
|
||||
Example from `zlib.js`:
|
||||
|
||||
```js
|
||||
function crc32(data, value = 0) {
|
||||
if (typeof data !== 'string' && !isArrayBufferView(data)) {
|
||||
throw new ERR_INVALID_ARG_TYPE('data', ['Buffer', 'TypedArray', 'DataView','string'], data);
|
||||
}
|
||||
validateUint32(value, 'value');
|
||||
return crc32Native(data, value);
|
||||
}
|
||||
```
|
||||
|
||||
The corresponding C++ assertion code for the above example from it's binding `node_zlib.cc`:
|
||||
|
||||
```cpp
|
||||
CHECK(args[0]->IsArrayBufferView() || args[0]->IsString());
|
||||
CHECK(args[1]->IsUint32());
|
||||
```
|
||||
|
||||
#### Internal code and C++ binding checks
|
||||
|
||||
Inside Node.js’s internal layers, especially the C++ [binding function][]s
|
||||
typically assume their arguments have already been checked and sanitized
|
||||
by the upper-level (JavaScript) callers. As a result, internal C++ code
|
||||
often just uses `CHECK()` or similar assertions to confirm that the
|
||||
types/values passed in are correct. If that assertion fails, Node.js will
|
||||
crash or abort with an internal diagnostic message. This is to avoid
|
||||
re-validating every internal function argument repeatedly which can slow
|
||||
down the system.
|
||||
|
||||
However, in a less common case where the API is implemented completely in
|
||||
C++, the arguments would be validated directly in C++, with the errors
|
||||
thrown using `THROW_ERR_INVALID_*` macros from `src/node_errors.h`.
|
||||
|
||||
For example in `worker_threads.moveMessagePortToContext`:
|
||||
|
||||
```cpp
|
||||
void MessagePort::MoveToContext(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
if (!args[0]->IsObject() ||
|
||||
!env->message_port_constructor_template()->HasInstance(args[0])) {
|
||||
return THROW_ERR_INVALID_ARG_TYPE(env,
|
||||
"The \"port\" argument must be a MessagePort instance");
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
<a id="exception-handling"></a>
|
||||
|
||||
### Exception handling
|
||||
|
Loading…
x
Reference in New Issue
Block a user