Skip to content

Commit

Permalink
src: add SyntaxError (#1326)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinEady authored Jun 16, 2023
1 parent 717a619 commit d9828c6
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ The following is the documentation for node-addon-api.
- [Error](doc/error.md)
- [TypeError](doc/type_error.md)
- [RangeError](doc/range_error.md)
- [SyntaxError](doc/syntax_error.md)
- [Object Lifetime Management](doc/object_lifetime_management.md)
- [HandleScope](doc/handle_scope.md)
- [EscapableHandleScope](doc/escapable_handle_scope.md)
Expand Down
2 changes: 2 additions & 0 deletions doc/hierarchy.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
| [`Napi::Reference`] | |
| [`Napi::String`][] | [`Napi::Name`][] |
| [`Napi::Symbol`][] | [`Napi::Name`][] |
| [`Napi::SyntaxError`][] | [`Napi::Error`][] |
| [`Napi::ThreadSafeFunction`][] | |
| [`Napi::TypeTaggable`][] | [`Napi::Value][] |
| [`Napi::TypeError`][] | [`Napi::Error`][] |
Expand Down Expand Up @@ -82,6 +83,7 @@
[`Napi::Reference<Napi::Object>`]: ./reference.md
[`Napi::String`]: ./string.md
[`Napi::Symbol`]: ./symbol.md
[`Napi::SyntaxError`]: ./syntax_error.md
[`Napi::ThreadSafeFunction`]: ./threadsafe_function.md
[`Napi::TypeError`]: ./type_error.md
[`Napi::TypeTaggable`]: ./type_taggable.md
Expand Down
66 changes: 66 additions & 0 deletions doc/syntax_error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# SyntaxError

The `Napi::SyntaxError` class is a representation of the JavaScript
`SyntaxError` that is thrown when the engine encounters tokens or token order
that does not conform to the syntax of the language when parsing code.

The `Napi::SyntaxError` class inherits its behaviors from the `Napi::Error`
class (for more info see: [`Napi::Error`](error.md)).

For more details about error handling refer to the section titled [Error
handling](error_handling.md).

## Methods

### New

Creates a new instance of a `Napi::SyntaxError` object.

```cpp
Napi::SyntaxError::New(Napi::Env env, const char* message);
```
- `[in] Env`: The environment in which to construct the `Napi::SyntaxError`
object.
- `[in] message`: Null-terminated string to be used as the message for the
`Napi::SyntaxError`.
Returns an instance of a `Napi::SyntaxError` object.
### New
Creates a new instance of a `Napi::SyntaxError` object.
```cpp
Napi::SyntaxError::New(Napi::Env env, const std::string& message);
```

- `[in] Env`: The environment in which to construct the `Napi::SyntaxError`
object.
- `[in] message`: Reference string to be used as the message for the
`Napi::SyntaxError`.

Returns an instance of a `Napi::SyntaxError` object.

### Constructor

Creates a new empty instance of a `Napi::SyntaxError`.

```cpp
Napi::SyntaxError::SyntaxError();
```

### Constructor

Initializes a `Napi::SyntaxError` instance from an existing Javascript error
object.

```cpp
Napi::SyntaxError::SyntaxError(napi_env env, napi_value value);
```
- `[in] Env`: The environment in which to construct the `Napi::SyntaxError`
object.
- `[in] value`: The `Napi::Error` reference to wrap.
Returns an instance of a `Napi::SyntaxError` object.
17 changes: 17 additions & 0 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3157,6 +3157,23 @@ inline RangeError::RangeError() : Error() {}
inline RangeError::RangeError(napi_env env, napi_value value)
: Error(env, value) {}

#if NAPI_VERSION > 8
inline SyntaxError SyntaxError::New(napi_env env, const char* message) {
return Error::New<SyntaxError>(
env, message, std::strlen(message), node_api_create_syntax_error);
}

inline SyntaxError SyntaxError::New(napi_env env, const std::string& message) {
return Error::New<SyntaxError>(
env, message.c_str(), message.size(), node_api_create_syntax_error);
}

inline SyntaxError::SyntaxError() : Error() {}

inline SyntaxError::SyntaxError(napi_env env, napi_value value)
: Error(env, value) {}
#endif // NAPI_VERSION > 8

////////////////////////////////////////////////////////////////////////////////
// Reference<T> class
////////////////////////////////////////////////////////////////////////////////
Expand Down
11 changes: 11 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1853,6 +1853,17 @@ class RangeError : public Error {
RangeError(napi_env env, napi_value value);
};

#if NAPI_VERSION > 8
class SyntaxError : public Error {
public:
static SyntaxError New(napi_env env, const char* message);
static SyntaxError New(napi_env env, const std::string& message);

SyntaxError();
SyntaxError(napi_env env, napi_value value);
};
#endif // NAPI_VERSION > 8

class CallbackInfo {
public:
CallbackInfo(napi_env env, napi_callback_info info);
Expand Down
47 changes: 47 additions & 0 deletions test/error.cc
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,27 @@ void ThrowRangeError(const CallbackInfo& info) {
throw RangeError::New(info.Env(), message);
}

#if NAPI_VERSION > 8
void ThrowSyntaxErrorCStr(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();
ReleaseAndWaitForChildProcess(info, 1);
throw SyntaxError::New(info.Env(), message.c_str());
}

void ThrowSyntaxErrorCtor(const CallbackInfo& info) {
Napi::Value js_range_err = info[0];
ReleaseAndWaitForChildProcess(info, 1);
throw Napi::SyntaxError(info.Env(), js_range_err);
}

void ThrowSyntaxError(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();

ReleaseAndWaitForChildProcess(info, 1);
throw SyntaxError::New(info.Env(), message);
}
#endif // NAPI_VERSION > 8

Value CatchError(const CallbackInfo& info) {
Function thrower = info[0].As<Function>();
try {
Expand Down Expand Up @@ -255,6 +276,27 @@ void ThrowEmptyRangeError(const CallbackInfo& info) {
RangeError().ThrowAsJavaScriptException();
}

#if NAPI_VERSION > 8
void ThrowSyntaxError(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();

ReleaseAndWaitForChildProcess(info, 1);
SyntaxError::New(info.Env(), message).ThrowAsJavaScriptException();
}

void ThrowSyntaxErrorCtor(const CallbackInfo& info) {
Napi::Value js_range_err = info[0];
ReleaseAndWaitForChildProcess(info, 1);
SyntaxError(info.Env(), js_range_err).ThrowAsJavaScriptException();
}

void ThrowSyntaxErrorCStr(const CallbackInfo& info) {
std::string message = info[0].As<String>().Utf8Value();
ReleaseAndWaitForChildProcess(info, 1);
SyntaxError::New(info.Env(), message.c_str()).ThrowAsJavaScriptException();
}
#endif // NAPI_VERSION > 8

Value CatchError(const CallbackInfo& info) {
Function thrower = info[0].As<Function>();
thrower({});
Expand Down Expand Up @@ -372,6 +414,11 @@ Object InitError(Env env) {
exports["throwRangeErrorCtor"] = Function::New(env, ThrowRangeErrorCtor);
exports["throwRangeErrorCStr"] = Function::New(env, ThrowRangeErrorCStr);
exports["throwEmptyRangeError"] = Function::New(env, ThrowEmptyRangeError);
#if NAPI_VERSION > 8
exports["throwSyntaxError"] = Function::New(env, ThrowSyntaxError);
exports["throwSyntaxErrorCtor"] = Function::New(env, ThrowSyntaxErrorCtor);
exports["throwSyntaxErrorCStr"] = Function::New(env, ThrowSyntaxErrorCStr);
#endif // NAPI_VERSION > 8
exports["catchError"] = Function::New(env, CatchError);
exports["catchErrorMessage"] = Function::New(env, CatchErrorMessage);
exports["doNotCatch"] = Function::New(env, DoNotCatch);
Expand Down
16 changes: 16 additions & 0 deletions test/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ if (process.argv[2] === 'fatal') {

module.exports = require('./common').runTestWithBindingPath(test);

const napiVersion = Number(process.env.NAPI_VERSION ?? process.versions.napi);

function test (bindingPath) {
const binding = require(bindingPath);
binding.error.testErrorCopySemantics();
Expand Down Expand Up @@ -46,6 +48,20 @@ function test (bindingPath) {
return err instanceof RangeError && err.message === 'rangeTypeError';
});

if (napiVersion > 8) {
assert.throws(() => binding.error.throwSyntaxErrorCStr('test'), function (err) {
return err instanceof SyntaxError && err.message === 'test';
});

assert.throws(() => binding.error.throwSyntaxError('test'), function (err) {
return err instanceof SyntaxError && err.message === 'test';
});

assert.throws(() => binding.error.throwSyntaxErrorCtor(new SyntaxError('syntaxTypeError')), function (err) {
return err instanceof SyntaxError && err.message === 'syntaxTypeError';
});
}

assert.throws(
() => binding.error.doNotCatch(
() => {
Expand Down

0 comments on commit d9828c6

Please sign in to comment.