GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/js_native_api_v8.h Lines: 61 62 98.4 %
Date: 2019-09-17 22:33:17 Branches: 31 48 64.6 %

Line Branch Exec Source
1
#ifndef SRC_JS_NATIVE_API_V8_H_
2
#define SRC_JS_NATIVE_API_V8_H_
3
4
// This file needs to be compatible with C compilers.
5
#include <string.h>  // NOLINT(modernize-deprecated-headers)
6
#include "js_native_api_types.h"
7
#include "js_native_api_v8_internals.h"
8
9
static napi_status napi_clear_last_error(napi_env env);
10
11
struct napi_env__ {
12
72
  explicit napi_env__(v8::Local<v8::Context> context)
13
72
      : isolate(context->GetIsolate()),
14
288
        context_persistent(isolate, context) {
15
144
    CHECK_EQ(isolate, context->GetIsolate());
16
72
  }
17
213
  virtual ~napi_env__() {
18
71
    if (instance_data.finalize_cb != nullptr) {
19
4
      CallIntoModuleThrow([&](napi_env env) {
20
4
        instance_data.finalize_cb(env, instance_data.data, instance_data.hint);
21
8
      });
22
    }
23
71
  }
24
  v8::Isolate* const isolate;  // Shortcut for context()->GetIsolate()
25
  v8impl::Persistent<v8::Context> context_persistent;
26
27
10972
  inline v8::Local<v8::Context> context() const {
28
10972
    return v8impl::PersistentToLocal::Strong(context_persistent);
29
  }
30
31
17
  inline void Ref() { refs++; }
32

88
  inline void Unref() { if ( --refs == 0) delete this; }
33
34
  virtual bool can_call_into_js() const { return true; }
35
36
  template <typename T, typename U>
37
6277
  void CallIntoModule(T&& call, U&& handle_exception) {
38
6277
    int open_handle_scopes_before = open_handle_scopes;
39
6277
    int open_callback_scopes_before = open_callback_scopes;
40
6277
    napi_clear_last_error(this);
41
6277
    call(this);
42



6277
    CHECK_EQ(open_handle_scopes, open_handle_scopes_before);
43



6277
    CHECK_EQ(open_callback_scopes, open_callback_scopes_before);
44



12554
    if (!last_exception.IsEmpty()) {
45
2468
      handle_exception(this, last_exception.Get(this->isolate));
46
1233
      last_exception.Reset();
47
    }
48
6276
  }
49
50
  template <typename T>
51
5765
  void CallIntoModuleThrow(T&& call) {
52
6997
    CallIntoModule(call, [&](napi_env env, v8::Local<v8::Value> value) {
53
1232
      env->isolate->ThrowException(value);
54
1232
    });
55
5765
  }
56
57
  v8impl::Persistent<v8::Value> last_exception;
58
  napi_extended_error_info last_error;
59
  int open_handle_scopes = 0;
60
  int open_callback_scopes = 0;
61
  int refs = 1;
62
72
  struct {
63
    void* data = nullptr;
64
    void* hint = nullptr;
65
    napi_finalize finalize_cb = nullptr;
66
  } instance_data;
67
};
68
69
28156
static inline napi_status napi_clear_last_error(napi_env env) {
70
28156
  env->last_error.error_code = napi_ok;
71
72
  // TODO(boingoing): Should this be a callback?
73
28156
  env->last_error.engine_error_code = 0;
74
28156
  env->last_error.engine_reserved = nullptr;
75
28156
  return napi_ok;
76
}
77
78
static inline
79
1255
napi_status napi_set_last_error(napi_env env, napi_status error_code,
80
                                uint32_t engine_error_code = 0,
81
                                void* engine_reserved = nullptr) {
82
1255
  env->last_error.error_code = error_code;
83
1255
  env->last_error.engine_error_code = engine_error_code;
84
1255
  env->last_error.engine_reserved = engine_reserved;
85
1255
  return error_code;
86
}
87
88
#define RETURN_STATUS_IF_FALSE(env, condition, status)                  \
89
  do {                                                                  \
90
    if (!(condition)) {                                                 \
91
      return napi_set_last_error((env), (status));                      \
92
    }                                                                   \
93
  } while (0)
94
95
#define CHECK_ENV(env)          \
96
  do {                          \
97
    if ((env) == nullptr) {     \
98
      return napi_invalid_arg;  \
99
    }                           \
100
  } while (0)
101
102
#define CHECK_ARG(env, arg) \
103
  RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg)
104
105
#define CHECK_MAYBE_EMPTY(env, maybe, status) \
106
  RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status))
107
108
// NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
109
#define NAPI_PREAMBLE(env)                                          \
110
  CHECK_ENV((env));                                                 \
111
  RETURN_STATUS_IF_FALSE((env),                                     \
112
      (env)->last_exception.IsEmpty() && (env)->can_call_into_js(), \
113
      napi_pending_exception);                                      \
114
  napi_clear_last_error((env));                                     \
115
  v8impl::TryCatch try_catch((env))
116
117
#define CHECK_TO_TYPE(env, type, context, result, src, status)                \
118
  do {                                                                        \
119
    CHECK_ARG((env), (src));                                                  \
120
    auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \
121
    CHECK_MAYBE_EMPTY((env), maybe, (status));                                \
122
    (result) = maybe.ToLocalChecked();                                        \
123
  } while (0)
124
125
#define CHECK_TO_FUNCTION(env, result, src)                                 \
126
  do {                                                                      \
127
    CHECK_ARG((env), (src));                                                \
128
    v8::Local<v8::Value> v8value = v8impl::V8LocalValueFromJsValue((src));  \
129
    RETURN_STATUS_IF_FALSE((env), v8value->IsFunction(), napi_invalid_arg); \
130
    (result) = v8value.As<v8::Function>();                                  \
131
  } while (0)
132
133
#define CHECK_TO_OBJECT(env, context, result, src) \
134
  CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected)
135
136
#define CHECK_TO_STRING(env, context, result, src) \
137
  CHECK_TO_TYPE((env), String, (context), (result), (src), napi_string_expected)
138
139
#define GET_RETURN_STATUS(env)      \
140
  (!try_catch.HasCaught() ? napi_ok \
141
                         : napi_set_last_error((env), napi_pending_exception))
142
143
#define THROW_RANGE_ERROR_IF_FALSE(env, condition, error, message) \
144
  do {                                                             \
145
    if (!(condition)) {                                            \
146
      napi_throw_range_error((env), (error), (message));           \
147
      return napi_set_last_error((env), napi_generic_failure);     \
148
    }                                                              \
149
  } while (0)
150
151
namespace v8impl {
152
153
//=== Conversion between V8 Handles and napi_value ========================
154
155
// This asserts v8::Local<> will always be implemented with a single
156
// pointer field so that we can pass it around as a void*.
157
static_assert(sizeof(v8::Local<v8::Value>) == sizeof(napi_value),
158
  "Cannot convert between v8::Local<v8::Value> and napi_value");
159
160
16513
inline napi_value JsValueFromV8LocalValue(v8::Local<v8::Value> local) {
161
16513
  return reinterpret_cast<napi_value>(*local);
162
}
163
164
13477
inline v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {
165
  v8::Local<v8::Value> local;
166
13477
  memcpy(static_cast<void*>(&local), &v, sizeof(v));
167
13477
  return local;
168
}
169
170
// Adapter for napi_finalize callbacks.
171
class Finalizer {
172
 protected:
173
2950
  Finalizer(napi_env env,
174
            napi_finalize finalize_callback,
175
            void* finalize_data,
176
            void* finalize_hint)
177
    : _env(env),
178
      _finalize_callback(finalize_callback),
179
      _finalize_data(finalize_data),
180
2950
      _finalize_hint(finalize_hint) {
181
2950
  }
182
183
  ~Finalizer() = default;
184
185
 public:
186
5
  static Finalizer* New(napi_env env,
187
                        napi_finalize finalize_callback = nullptr,
188
                        void* finalize_data = nullptr,
189
                        void* finalize_hint = nullptr) {
190
    return new Finalizer(
191
5
      env, finalize_callback, finalize_data, finalize_hint);
192
  }
193
194
5
  static void Delete(Finalizer* finalizer) {
195
5
    delete finalizer;
196
5
  }
197
198
 protected:
199
  napi_env _env;
200
  napi_finalize _finalize_callback;
201
  void* _finalize_data;
202
  void* _finalize_hint;
203
  bool _finalize_ran = false;
204
};
205
206
class TryCatch : public v8::TryCatch {
207
 public:
208
4697
  explicit TryCatch(napi_env env)
209
4697
      : v8::TryCatch(env->isolate), _env(env) {}
210
211
9394
  ~TryCatch() {
212
4697
    if (HasCaught()) {
213
2470
      _env->last_exception.Reset(_env->isolate, Exception());
214
    }
215
4697
  }
216
217
 private:
218
  napi_env _env;
219
};
220
221
}  // end of namespace v8impl
222
223
#endif  // SRC_JS_NATIVE_API_V8_H_