Skip to content

Commit 88b57bc

Browse files
Idan Attiastargos
Idan Attias
authored andcommitted
src,doc: add SyntaxError napi support
Add `napi_create_syntax_error` and `napi_throw_syntax_error`. Fixes: nodejs/node-addon-api#1099 PR-URL: #40736 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent fa37428 commit 88b57bc

File tree

5 files changed

+157
-4
lines changed

5 files changed

+157
-4
lines changed

doc/api/n-api.md

+48-4
Original file line numberDiff line numberDiff line change
@@ -1065,12 +1065,11 @@ JavaScript value to be thrown.
10651065
The following utility functions are also available in case native code
10661066
needs to throw an exception or determine if a `napi_value` is an instance
10671067
of a JavaScript `Error` object: [`napi_throw_error`][],
1068-
[`napi_throw_type_error`][], [`napi_throw_range_error`][] and
1069-
[`napi_is_error`][].
1068+
[`napi_throw_type_error`][], [`napi_throw_range_error`][], [`node_api_throw_syntax_error`][] and [`napi_is_error`][].
10701069
10711070
The following utility functions are also available in case native
10721071
code needs to create an `Error` object: [`napi_create_error`][],
1073-
[`napi_create_type_error`][], and [`napi_create_range_error`][],
1072+
[`napi_create_type_error`][], [`napi_create_range_error`][] and [`node_api_create_syntax_error`][],
10741073
where result is the `napi_value` that refers to the newly created
10751074
JavaScript `Error` object.
10761075
@@ -1180,6 +1179,25 @@ Returns `napi_ok` if the API succeeded.
11801179

11811180
This API throws a JavaScript `RangeError` with the text provided.
11821181

1182+
#### `node_api_throw_syntax_error`
1183+
1184+
<!-- YAML
1185+
added: REPLACEME
1186+
-->
1187+
1188+
````c
1189+
NAPI_EXTERN napi_status node_api_throw_syntax_error(napi_env env,
1190+
const char* code,
1191+
const char* msg);
1192+
1193+
* `[in] env`: The environment that the API is invoked under.
1194+
* `[in] code`: Optional error code to be set on the error.
1195+
* `[in] msg`: C string representing the text to be associated with the error.
1196+
1197+
Returns `napi_ok` if the API succeeded.
1198+
1199+
This API throws a JavaScript `SyntaxError` with the text provided.
1200+
11831201
#### `napi_is_error`
11841202

11851203
<!-- YAML
@@ -1191,7 +1209,7 @@ napiVersion: 1
11911209
NAPI_EXTERN napi_status napi_is_error(napi_env env,
11921210
napi_value value,
11931211
bool* result);
1194-
```
1212+
````
11951213
11961214
* `[in] env`: The environment that the API is invoked under.
11971215
* `[in] value`: The `napi_value` to be checked.
@@ -1277,6 +1295,30 @@ Returns `napi_ok` if the API succeeded.
12771295
12781296
This API returns a JavaScript `RangeError` with the text provided.
12791297
1298+
#### `node_api_create_syntax_error`
1299+
1300+
<!-- YAML
1301+
added: REPLACEME
1302+
-->
1303+
1304+
```c
1305+
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
1306+
napi_value code,
1307+
napi_value msg,
1308+
napi_value* result);
1309+
```
1310+
1311+
* `[in] env`: The environment that the API is invoked under.
1312+
* `[in] code`: Optional `napi_value` with the string for the error code to be
1313+
associated with the error.
1314+
* `[in] msg`: `napi_value` that references a JavaScript `string` to be used as
1315+
the message for the `Error`.
1316+
* `[out] result`: `napi_value` representing the error created.
1317+
1318+
Returns `napi_ok` if the API succeeded.
1319+
1320+
This API returns a JavaScript `SyntaxError` with the text provided.
1321+
12801322
#### `napi_get_and_clear_last_exception`
12811323
12821324
<!-- YAML
@@ -6296,6 +6338,8 @@ the add-on's file name during loading.
62966338
[`napi_wrap`]: #napi_wrap
62976339
[`node-addon-api`]: https://github.com/nodejs/node-addon-api
62986340
[`node_api.h`]: https://github.com/nodejs/node/blob/HEAD/src/node_api.h
6341+
[`node_api_create_syntax_error`]: #node_api_create_syntax_error
6342+
[`node_api_throw_syntax_error`]: #node_api_throw_syntax_error
62996343
[`process.release`]: process.md#processrelease
63006344
[`uv_ref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_ref
63016345
[`uv_unref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_unref

src/js_native_api.h

+11
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
111111
napi_value code,
112112
napi_value msg,
113113
napi_value* result);
114+
#ifdef NAPI_EXPERIMENTAL
115+
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
116+
napi_value code,
117+
napi_value msg,
118+
napi_value* result);
119+
#endif // NAPI_EXPERIMENTAL
114120

115121
// Methods to get the native napi_value from Primitive type
116122
NAPI_EXTERN napi_status napi_typeof(napi_env env,
@@ -370,6 +376,11 @@ NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
370376
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
371377
const char* code,
372378
const char* msg);
379+
#ifdef NAPI_EXPERIMENTAL
380+
NAPI_EXTERN napi_status node_api_throw_syntax_error(napi_env env,
381+
const char* code,
382+
const char* msg);
383+
#endif // NAPI_EXPERIMENTAL
373384
NAPI_EXTERN napi_status napi_is_error(napi_env env,
374385
napi_value value,
375386
bool* result);

src/js_native_api_v8.cc

+38
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,26 @@ napi_status napi_create_range_error(napi_env env,
17471747
return napi_clear_last_error(env);
17481748
}
17491749

1750+
napi_status node_api_create_syntax_error(napi_env env,
1751+
napi_value code,
1752+
napi_value msg,
1753+
napi_value* result) {
1754+
CHECK_ENV(env);
1755+
CHECK_ARG(env, msg);
1756+
CHECK_ARG(env, result);
1757+
1758+
v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
1759+
RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
1760+
1761+
v8::Local<v8::Value> error_obj =
1762+
v8::Exception::SyntaxError(message_value.As<v8::String>());
1763+
STATUS_CALL(set_error_code(env, error_obj, code, nullptr));
1764+
1765+
*result = v8impl::JsValueFromV8LocalValue(error_obj);
1766+
1767+
return napi_clear_last_error(env);
1768+
}
1769+
17501770
napi_status napi_typeof(napi_env env,
17511771
napi_value value,
17521772
napi_valuetype* result) {
@@ -1964,6 +1984,24 @@ napi_status napi_throw_range_error(napi_env env,
19641984
return napi_clear_last_error(env);
19651985
}
19661986

1987+
napi_status node_api_throw_syntax_error(napi_env env,
1988+
const char* code,
1989+
const char* msg) {
1990+
NAPI_PREAMBLE(env);
1991+
1992+
v8::Isolate* isolate = env->isolate;
1993+
v8::Local<v8::String> str;
1994+
CHECK_NEW_FROM_UTF8(env, str, msg);
1995+
1996+
v8::Local<v8::Value> error_obj = v8::Exception::SyntaxError(str);
1997+
STATUS_CALL(set_error_code(env, error_obj, nullptr, code));
1998+
1999+
isolate->ThrowException(error_obj);
2000+
// any VM calls after this point and before returning
2001+
// to the javascript invoker will fail
2002+
return napi_clear_last_error(env);
2003+
}
2004+
19672005
napi_status napi_is_error(napi_env env, napi_value value, bool* result) {
19682006
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot
19692007
// throw JS exceptions.

test/js-native-api/test_error/test.js

+23
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ assert.throws(() => {
6060
test_error.throwTypeError();
6161
}, /^TypeError: type error$/);
6262

63+
assert.throws(() => {
64+
test_error.throwSyntaxError();
65+
}, /^SyntaxError: syntax error$/);
66+
6367
[42, {}, [], Symbol('xyzzy'), true, 'ball', undefined, null, NaN]
6468
.forEach((value) => assert.throws(
6569
() => test_error.throwArbitrary(value),
@@ -90,6 +94,13 @@ assert.throws(
9094
message: 'TypeError [type error]'
9195
});
9296

97+
assert.throws(
98+
() => test_error.throwSyntaxErrorCode(),
99+
{
100+
code: 'ERR_TEST_CODE',
101+
message: 'SyntaxError [syntax error]'
102+
});
103+
93104
let error = test_error.createError();
94105
assert.ok(error instanceof Error, 'expected error to be an instance of Error');
95106
assert.strictEqual(error.message, 'error');
@@ -104,6 +115,11 @@ assert.ok(error instanceof TypeError,
104115
'expected error to be an instance of TypeError');
105116
assert.strictEqual(error.message, 'type error');
106117

118+
error = test_error.createSyntaxError();
119+
assert.ok(error instanceof SyntaxError,
120+
'expected error to be an instance of SyntaxError');
121+
assert.strictEqual(error.message, 'syntax error');
122+
107123
error = test_error.createErrorCode();
108124
assert.ok(error instanceof Error, 'expected error to be an instance of Error');
109125
assert.strictEqual(error.code, 'ERR_TEST_CODE');
@@ -123,3 +139,10 @@ assert.ok(error instanceof TypeError,
123139
assert.strictEqual(error.message, 'TypeError [type error]');
124140
assert.strictEqual(error.code, 'ERR_TEST_CODE');
125141
assert.strictEqual(error.name, 'TypeError');
142+
143+
error = test_error.createSyntaxErrorCode();
144+
assert.ok(error instanceof SyntaxError,
145+
'expected error to be an instance of SyntaxError');
146+
assert.strictEqual(error.message, 'SyntaxError [syntax error]');
147+
assert.strictEqual(error.code, 'ERR_TEST_CODE');
148+
assert.strictEqual(error.name, 'SyntaxError');

test/js-native-api/test_error/test_error.c

+37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#define NAPI_EXPERIMENTAL
12
#include <js_native_api.h>
23
#include "../common.h"
34

@@ -40,6 +41,11 @@ static napi_value throwTypeError(napi_env env, napi_callback_info info) {
4041
return NULL;
4142
}
4243

44+
static napi_value throwSyntaxError(napi_env env, napi_callback_info info) {
45+
NODE_API_CALL(env, node_api_throw_syntax_error(env, NULL, "syntax error"));
46+
return NULL;
47+
}
48+
4349
static napi_value throwErrorCode(napi_env env, napi_callback_info info) {
4450
NODE_API_CALL(env, napi_throw_error(env, "ERR_TEST_CODE", "Error [error]"));
4551
return NULL;
@@ -57,6 +63,11 @@ static napi_value throwTypeErrorCode(napi_env env, napi_callback_info info) {
5763
return NULL;
5864
}
5965

66+
static napi_value throwSyntaxErrorCode(napi_env env, napi_callback_info info) {
67+
NODE_API_CALL(env,
68+
node_api_throw_syntax_error(env, "ERR_TEST_CODE", "SyntaxError [syntax error]"));
69+
return NULL;
70+
}
6071

6172
static napi_value createError(napi_env env, napi_callback_info info) {
6273
napi_value result;
@@ -85,6 +96,15 @@ static napi_value createTypeError(napi_env env, napi_callback_info info) {
8596
return result;
8697
}
8798

99+
static napi_value createSyntaxError(napi_env env, napi_callback_info info) {
100+
napi_value result;
101+
napi_value message;
102+
NODE_API_CALL(env, napi_create_string_utf8(
103+
env, "syntax error", NAPI_AUTO_LENGTH, &message));
104+
NODE_API_CALL(env, node_api_create_syntax_error(env, NULL, message, &result));
105+
return result;
106+
}
107+
88108
static napi_value createErrorCode(napi_env env, napi_callback_info info) {
89109
napi_value result;
90110
napi_value message;
@@ -123,6 +143,19 @@ static napi_value createTypeErrorCode(napi_env env, napi_callback_info info) {
123143
return result;
124144
}
125145

146+
static napi_value createSyntaxErrorCode(napi_env env, napi_callback_info info) {
147+
napi_value result;
148+
napi_value message;
149+
napi_value code;
150+
NODE_API_CALL(env,
151+
napi_create_string_utf8(
152+
env, "SyntaxError [syntax error]", NAPI_AUTO_LENGTH, &message));
153+
NODE_API_CALL(env, napi_create_string_utf8(
154+
env, "ERR_TEST_CODE", NAPI_AUTO_LENGTH, &code));
155+
NODE_API_CALL(env, node_api_create_syntax_error(env, code, message, &result));
156+
return result;
157+
}
158+
126159
static napi_value throwArbitrary(napi_env env, napi_callback_info info) {
127160
napi_value arbitrary;
128161
size_t argc = 1;
@@ -139,16 +172,20 @@ napi_value Init(napi_env env, napi_value exports) {
139172
DECLARE_NODE_API_PROPERTY("throwError", throwError),
140173
DECLARE_NODE_API_PROPERTY("throwRangeError", throwRangeError),
141174
DECLARE_NODE_API_PROPERTY("throwTypeError", throwTypeError),
175+
DECLARE_NODE_API_PROPERTY("throwSyntaxError", throwSyntaxError),
142176
DECLARE_NODE_API_PROPERTY("throwErrorCode", throwErrorCode),
143177
DECLARE_NODE_API_PROPERTY("throwRangeErrorCode", throwRangeErrorCode),
144178
DECLARE_NODE_API_PROPERTY("throwTypeErrorCode", throwTypeErrorCode),
179+
DECLARE_NODE_API_PROPERTY("throwSyntaxErrorCode", throwSyntaxErrorCode),
145180
DECLARE_NODE_API_PROPERTY("throwArbitrary", throwArbitrary),
146181
DECLARE_NODE_API_PROPERTY("createError", createError),
147182
DECLARE_NODE_API_PROPERTY("createRangeError", createRangeError),
148183
DECLARE_NODE_API_PROPERTY("createTypeError", createTypeError),
184+
DECLARE_NODE_API_PROPERTY("createSyntaxError", createSyntaxError),
149185
DECLARE_NODE_API_PROPERTY("createErrorCode", createErrorCode),
150186
DECLARE_NODE_API_PROPERTY("createRangeErrorCode", createRangeErrorCode),
151187
DECLARE_NODE_API_PROPERTY("createTypeErrorCode", createTypeErrorCode),
188+
DECLARE_NODE_API_PROPERTY("createSyntaxErrorCode", createSyntaxErrorCode),
152189
};
153190

154191
NODE_API_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)