mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
doc: suggest not to throw JS errors from C++
Also provide an example on how to use internal/errors to handle errors in C++. PR-URL: https://github.com/nodejs/node/pull/18149 Refs: https://github.com/nodejs/node/issues/18106 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Jon Moss <me@jonathanmoss.me> Reviewed-By: Weijia Wang <starkwang@126.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
This commit is contained in:
parent
80973ec6c3
commit
afc528920b
|
|
@ -20,7 +20,8 @@
|
||||||
* [Others](#others)
|
* [Others](#others)
|
||||||
* [Type casting](#type-casting)
|
* [Type casting](#type-casting)
|
||||||
* [Do not include `*.h` if `*-inl.h` has already been included](#do-not-include-h-if--inlh-has-already-been-included)
|
* [Do not include `*.h` if `*-inl.h` has already been included](#do-not-include-h-if--inlh-has-already-been-included)
|
||||||
* [Avoid throwing JavaScript errors in nested C++ methods](#avoid-throwing-javascript-errors-in-nested-c-methods)
|
* [Avoid throwing JavaScript errors in C++ methods](#avoid-throwing-javascript-errors-in-c)
|
||||||
|
* [Avoid throwing JavaScript errors in nested C++ methods](#avoid-throwing-javascript-errors-in-nested-c-methods)
|
||||||
|
|
||||||
Unfortunately, the C++ linter (based on
|
Unfortunately, the C++ linter (based on
|
||||||
[Google’s `cpplint`](https://github.com/google/styleguide)), which can be run
|
[Google’s `cpplint`](https://github.com/google/styleguide)), which can be run
|
||||||
|
|
@ -213,12 +214,65 @@ instead of
|
||||||
#include "util-inl.h"
|
#include "util-inl.h"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Avoid throwing JavaScript errors in nested C++ methods
|
## Avoid throwing JavaScript errors in C++
|
||||||
|
|
||||||
If you need to throw JavaScript errors from a C++ binding method, try to do it
|
When there is a need to throw errors from a C++ binding method, try to
|
||||||
at the top level and not inside of nested calls.
|
return the data necessary for constructing the errors to JavaScript,
|
||||||
|
then construct and throw the errors [using `lib/internal/errors.js`][errors].
|
||||||
|
|
||||||
A lot of code inside Node.js is written so that typechecking etc. is performed
|
Note that in general, type-checks on arguments should be done in JavaScript
|
||||||
in JavaScript.
|
before the arguments are passed into C++. Then in the C++ binding, simply using
|
||||||
|
`CHECK` assertions to guard against invalid arguments should be enough.
|
||||||
|
|
||||||
|
If the return value of the binding cannot be used to signal failures or return
|
||||||
|
the necessary data for constructing errors in JavaScript, pass a context object
|
||||||
|
to the binding and put the necessary data inside in C++. For example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void Foo(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
// Let the JavaScript handle the actual type-checking,
|
||||||
|
// only assertions are placed in C++
|
||||||
|
CHECK_EQ(args.Length(), 2);
|
||||||
|
CHECK(args[0]->IsString());
|
||||||
|
CHECK(args[1]->IsObject());
|
||||||
|
|
||||||
|
int err = DoSomethingWith(args[0].As<String>());
|
||||||
|
if (err) {
|
||||||
|
// Put the data inside the error context
|
||||||
|
Local<Object> ctx = args[1].As<Object>();
|
||||||
|
Local<String> key = FIXED_ONE_BYTE_STRING(env->isolate(), "code");
|
||||||
|
ctx->Set(env->context(), key, err).FromJust();
|
||||||
|
} else {
|
||||||
|
args.GetReturnValue().Set(something_to_return);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the initialize function
|
||||||
|
env->SetMethod(target, "foo", Foo);
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
exports.foo = function(str) {
|
||||||
|
// Prefer doing the type-checks in JavaScript
|
||||||
|
if (typeof str !== 'string') {
|
||||||
|
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'str', 'string');
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = {};
|
||||||
|
const result = binding.foo(str, ctx);
|
||||||
|
if (ctx.code !== undefined) {
|
||||||
|
throw new errors.Error('ERR_ERROR_NAME', ctx.code);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Avoid throwing JavaScript errors in nested C++ methods
|
||||||
|
|
||||||
|
When you have to throw the errors from C++, try to do it at the top level and
|
||||||
|
not inside of nested calls.
|
||||||
|
|
||||||
Using C++ `throw` is not allowed.
|
Using C++ `throw` is not allowed.
|
||||||
|
|
||||||
|
[errors]: https://github.com/nodejs/node/blob/master/doc/guides/using-internal-errors.md
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user