• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef JS_NATIVE_API_COMMON_H_
2 #define JS_NATIVE_API_COMMON_H_
3 
4 #include <js_native_api.h>
5 #include <stdlib.h>  // abort()
6 
7 // Empty value so that macros here are able to return NULL or void
8 #define NODE_API_RETVAL_NOTHING  // Intentionally blank #define
9 
10 #define GET_AND_THROW_LAST_ERROR(env)                                    \
11   do {                                                                   \
12     const napi_extended_error_info *error_info;                          \
13     napi_get_last_error_info((env), &error_info);                        \
14     bool is_pending;                                                     \
15     const char* err_message = error_info->error_message;                  \
16     napi_is_exception_pending((env), &is_pending);                       \
17     /* If an exception is already pending, don't rethrow it */           \
18     if (!is_pending) {                                                   \
19       const char* error_message = err_message != NULL ?                  \
20                        err_message :                                     \
21                       "empty error message";                             \
22       napi_throw_error((env), NULL, error_message);                      \
23     }                                                                    \
24   } while (0)
25 
26 // The nogc version of GET_AND_THROW_LAST_ERROR. We cannot access any
27 // exceptions and we cannot fail by way of JS exception, so we abort.
28 #define FATALLY_FAIL_WITH_LAST_ERROR(env)                                      \
29   do {                                                                         \
30     const napi_extended_error_info* error_info;                                \
31     napi_get_last_error_info((env), &error_info);                              \
32     const char* err_message = error_info->error_message;                       \
33     const char* error_message =                                                \
34         err_message != NULL ? err_message : "empty error message";             \
35     fprintf(stderr, "%s\n", error_message);                                    \
36     abort();                                                                   \
37   } while (0)
38 
39 #define NODE_API_ASSERT_BASE(env, assertion, message, ret_val)           \
40   do {                                                                   \
41     if (!(assertion)) {                                                  \
42       napi_throw_error(                                                  \
43           (env),                                                         \
44         NULL,                                                            \
45           "assertion (" #assertion ") failed: " message);                \
46       return ret_val;                                                    \
47     }                                                                    \
48   } while (0)
49 
50 #define NODE_API_NOGC_ASSERT_BASE(assertion, message, ret_val)                 \
51   do {                                                                         \
52     if (!(assertion)) {                                                        \
53       fprintf(stderr, "assertion (" #assertion ") failed: " message);          \
54       abort();                                                                 \
55       return ret_val;                                                          \
56     }                                                                          \
57   } while (0)
58 
59 // Returns NULL on failed assertion.
60 // This is meant to be used inside napi_callback methods.
61 #define NODE_API_ASSERT(env, assertion, message)                         \
62   NODE_API_ASSERT_BASE(env, assertion, message, NULL)
63 
64 // Returns empty on failed assertion.
65 // This is meant to be used inside functions with void return type.
66 #define NODE_API_ASSERT_RETURN_VOID(env, assertion, message)             \
67   NODE_API_ASSERT_BASE(env, assertion, message, NODE_API_RETVAL_NOTHING)
68 
69 #define NODE_API_NOGC_ASSERT_RETURN_VOID(assertion, message)                   \
70   NODE_API_NOGC_ASSERT_BASE(assertion, message, NODE_API_RETVAL_NOTHING)
71 
72 #define NODE_API_CALL_BASE(env, the_call, ret_val)                       \
73   do {                                                                   \
74     if ((the_call) != napi_ok) {                                         \
75       GET_AND_THROW_LAST_ERROR((env));                                   \
76       return ret_val;                                                    \
77     }                                                                    \
78   } while (0)
79 
80 #define NODE_API_NOGC_CALL_BASE(env, the_call, ret_val)                        \
81   do {                                                                         \
82     if ((the_call) != napi_ok) {                                               \
83       FATALLY_FAIL_WITH_LAST_ERROR((env));                                     \
84       return ret_val;                                                          \
85     }                                                                          \
86   } while (0)
87 
88 // Returns NULL if the_call doesn't return napi_ok.
89 #define NODE_API_CALL(env, the_call)                                     \
90   NODE_API_CALL_BASE(env, the_call, NULL)
91 
92 // Returns empty if the_call doesn't return napi_ok.
93 #define NODE_API_CALL_RETURN_VOID(env, the_call)                         \
94   NODE_API_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING)
95 
96 #define NODE_API_NOGC_CALL_RETURN_VOID(env, the_call)                          \
97   NODE_API_NOGC_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING)
98 
99 #define NODE_API_CHECK_STATUS(the_call)                                   \
100   do {                                                                         \
101     napi_status status = (the_call);                                           \
102     if (status != napi_ok) {                                                   \
103       return status;                                                           \
104     }                                                                          \
105   } while (0)
106 
107 #define NODE_API_ASSERT_STATUS(env, assertion, message)                        \
108   NODE_API_ASSERT_BASE(env, assertion, message, napi_generic_failure)
109 
110 #define DECLARE_NODE_API_PROPERTY(name, func)                            \
111   { (name), NULL, (func), NULL, NULL, NULL, napi_default, NULL }
112 
113 #define DECLARE_NODE_API_GETTER(name, func)                              \
114   { (name), NULL, NULL, (func), NULL, NULL, napi_default, NULL }
115 
116 #define DECLARE_NODE_API_PROPERTY_VALUE(name, value)                     \
117   { (name), NULL, NULL, NULL, NULL, (value), napi_default, NULL }
118 
119 static inline void add_returned_status(napi_env env,
120                                        const char* key,
121                                        napi_value object,
122                                        char* expected_message,
123                                        napi_status expected_status,
124                                        napi_status actual_status);
125 
126 static inline void add_last_status(napi_env env,
127                                    const char* key,
128                                    napi_value return_value);
129 
130 #include "common-inl.h"
131 
132 #endif  // JS_NATIVE_API_COMMON_H_
133