Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/nodejs/src/js_native_api_v8.h
$ cat -n /usr/include/nodejs/src/js_native_api_v8.h 1 #ifndef SRC_JS_NATIVE_API_V8_H_ 2 #define SRC_JS_NATIVE_API_V8_H_ 3 4 #include "js_native_api_types.h" 5 #include "js_native_api_v8_internals.h" 6 7 inline napi_status napi_clear_last_error(napi_env env); 8 9 namespace v8impl { 10 11 class RefTracker { 12 public: 13 RefTracker() {} 14 virtual ~RefTracker() {} 15 virtual void Finalize() {} 16 17 typedef RefTracker RefList; 18 19 inline void Link(RefList* list) { 20 prev_ = list; 21 next_ = list->next_; 22 if (next_ != nullptr) { 23 next_->prev_ = this; 24 } 25 list->next_ = this; 26 } 27 28 inline void Unlink() { 29 if (prev_ != nullptr) { 30 prev_->next_ = next_; 31 } 32 if (next_ != nullptr) { 33 next_->prev_ = prev_; 34 } 35 prev_ = nullptr; 36 next_ = nullptr; 37 } 38 39 static void FinalizeAll(RefList* list) { 40 while (list->next_ != nullptr) { 41 list->next_->Finalize(); 42 } 43 } 44 45 private: 46 RefList* next_ = nullptr; 47 RefList* prev_ = nullptr; 48 }; 49 50 class Finalizer; 51 } // end of namespace v8impl 52 53 struct napi_env__ { 54 explicit napi_env__(v8::Local
context, 55 int32_t module_api_version) 56 : isolate(context->GetIsolate()), 57 context_persistent(isolate, context), 58 module_api_version(module_api_version) { 59 napi_clear_last_error(this); 60 } 61 62 inline v8::Local
context() const { 63 return v8impl::PersistentToLocal::Strong(context_persistent); 64 } 65 66 inline void Ref() { refs++; } 67 inline void Unref() { 68 if (--refs == 0) DeleteMe(); 69 } 70 71 virtual bool can_call_into_js() const { return true; } 72 73 static inline void HandleThrow(napi_env env, v8::Local
value) { 74 if (env->terminatedOrTerminating()) { 75 return; 76 } 77 env->isolate->ThrowException(value); 78 } 79 80 // i.e. whether v8 exited or is about to exit 81 inline bool terminatedOrTerminating() { 82 return this->isolate->IsExecutionTerminating() || !can_call_into_js(); 83 } 84 85 // v8 uses a special exception to indicate termination, the 86 // `handle_exception` callback should identify such case using 87 // terminatedOrTerminating() before actually handle the exception 88 template
89 inline void CallIntoModule(T&& call, U&& handle_exception = HandleThrow) { 90 int open_handle_scopes_before = open_handle_scopes; 91 int open_callback_scopes_before = open_callback_scopes; 92 napi_clear_last_error(this); 93 call(this); 94 CHECK_EQ(open_handle_scopes, open_handle_scopes_before); 95 CHECK_EQ(open_callback_scopes, open_callback_scopes_before); 96 if (!last_exception.IsEmpty()) { 97 handle_exception(this, last_exception.Get(this->isolate)); 98 last_exception.Reset(); 99 } 100 } 101 102 // Call finalizer immediately. 103 virtual void CallFinalizer(napi_finalize cb, void* data, void* hint) { 104 v8::HandleScope handle_scope(isolate); 105 CallIntoModule([&](napi_env env) { cb(env, data, hint); }); 106 } 107 108 // Invoke finalizer from V8 garbage collector. 109 void InvokeFinalizerFromGC(v8impl::RefTracker* finalizer); 110 111 // Enqueue the finalizer to the napi_env's own queue of the second pass 112 // weak callback. 113 // Implementation should drain the queue at the time it is safe to call 114 // into JavaScript. 115 virtual void EnqueueFinalizer(v8impl::RefTracker* finalizer) { 116 pending_finalizers.emplace(finalizer); 117 } 118 119 // Remove the finalizer from the scheduled second pass weak callback queue. 120 // The finalizer can be deleted after this call. 121 virtual void DequeueFinalizer(v8impl::RefTracker* finalizer) { 122 pending_finalizers.erase(finalizer); 123 } 124 125 virtual void DeleteMe() { 126 // First we must finalize those references that have `napi_finalizer` 127 // callbacks. The reason is that addons might store other references which 128 // they delete during their `napi_finalizer` callbacks. If we deleted such 129 // references here first, they would be doubly deleted when the 130 // `napi_finalizer` deleted them subsequently. 131 v8impl::RefTracker::FinalizeAll(&finalizing_reflist); 132 v8impl::RefTracker::FinalizeAll(&reflist); 133 delete this; 134 } 135 136 void CheckGCAccess() { 137 if (module_api_version == NAPI_VERSION_EXPERIMENTAL && in_gc_finalizer) { 138 v8impl::OnFatalError( 139 nullptr, 140 "Finalizer is calling a function that may affect GC state.\n" 141 "The finalizers are run directly from GC and must not affect GC " 142 "state.\n" 143 "Use `node_api_post_finalizer` from inside of the finalizer to work " 144 "around this issue.\n" 145 "It schedules the call as a new task in the event loop."); 146 } 147 } 148 149 v8::Isolate* const isolate; // Shortcut for context()->GetIsolate() 150 v8impl::Persistent
context_persistent; 151 152 v8impl::Persistent
last_exception; 153 154 // We store references in two different lists, depending on whether they have 155 // `napi_finalizer` callbacks, because we must first finalize the ones that 156 // have such a callback. See `~napi_env__()` above for details. 157 v8impl::RefTracker::RefList reflist; 158 v8impl::RefTracker::RefList finalizing_reflist; 159 // The invocation order of the finalizers is not determined. 160 std::unordered_set
pending_finalizers; 161 napi_extended_error_info last_error; 162 int open_handle_scopes = 0; 163 int open_callback_scopes = 0; 164 int refs = 1; 165 void* instance_data = nullptr; 166 int32_t module_api_version = NODE_API_DEFAULT_MODULE_API_VERSION; 167 bool in_gc_finalizer = false; 168 169 protected: 170 // Should not be deleted directly. Delete with `napi_env__::DeleteMe()` 171 // instead. 172 virtual ~napi_env__() = default; 173 }; 174 175 inline napi_status napi_clear_last_error(napi_env env) { 176 env->last_error.error_code = napi_ok; 177 env->last_error.engine_error_code = 0; 178 env->last_error.engine_reserved = nullptr; 179 env->last_error.error_message = nullptr; 180 return napi_ok; 181 } 182 183 inline napi_status napi_set_last_error(napi_env env, 184 napi_status error_code, 185 uint32_t engine_error_code = 0, 186 void* engine_reserved = nullptr) { 187 env->last_error.error_code = error_code; 188 env->last_error.engine_error_code = engine_error_code; 189 env->last_error.engine_reserved = engine_reserved; 190 return error_code; 191 } 192 193 #define RETURN_STATUS_IF_FALSE(env, condition, status) \ 194 do { \ 195 if (!(condition)) { \ 196 return napi_set_last_error((env), (status)); \ 197 } \ 198 } while (0) 199 200 #define RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env, condition, status) \ 201 do { \ 202 if (!(condition)) { \ 203 return napi_set_last_error( \ 204 (env), try_catch.HasCaught() ? napi_pending_exception : (status)); \ 205 } \ 206 } while (0) 207 208 #define CHECK_ENV(env) \ 209 do { \ 210 if ((env) == nullptr) { \ 211 return napi_invalid_arg; \ 212 } \ 213 } while (0) 214 215 #define CHECK_ARG(env, arg) \ 216 RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg) 217 218 #define CHECK_ARG_WITH_PREAMBLE(env, arg) \ 219 RETURN_STATUS_IF_FALSE_WITH_PREAMBLE( \ 220 (env), ((arg) != nullptr), napi_invalid_arg) 221 222 #define CHECK_MAYBE_EMPTY(env, maybe, status) \ 223 RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status)) 224 225 #define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \ 226 RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status)) 227 228 // NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope 229 #define NAPI_PREAMBLE(env) \ 230 CHECK_ENV((env)); \ 231 (env)->CheckGCAccess(); \ 232 RETURN_STATUS_IF_FALSE( \ 233 (env), (env)->last_exception.IsEmpty(), napi_pending_exception); \ 234 RETURN_STATUS_IF_FALSE((env), \ 235 (env)->can_call_into_js(), \ 236 (env->module_api_version == NAPI_VERSION_EXPERIMENTAL \ 237 ? napi_cannot_run_js \ 238 : napi_pending_exception)); \ 239 napi_clear_last_error((env)); \ 240 v8impl::TryCatch try_catch((env)) 241 242 #define CHECK_TO_TYPE(env, type, context, result, src, status) \ 243 do { \ 244 CHECK_ARG((env), (src)); \ 245 auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \ 246 CHECK_MAYBE_EMPTY((env), maybe, (status)); \ 247 (result) = maybe.ToLocalChecked(); \ 248 } while (0) 249 250 #define CHECK_TO_TYPE_WITH_PREAMBLE(env, type, context, result, src, status) \ 251 do { \ 252 CHECK_ARG_WITH_PREAMBLE((env), (src)); \ 253 auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \ 254 CHECK_MAYBE_EMPTY_WITH_PREAMBLE((env), maybe, (status)); \ 255 (result) = maybe.ToLocalChecked(); \ 256 } while (0) 257 258 #define CHECK_TO_FUNCTION(env, result, src) \ 259 do { \ 260 CHECK_ARG((env), (src)); \ 261 v8::Local
v8value = v8impl::V8LocalValueFromJsValue((src)); \ 262 RETURN_STATUS_IF_FALSE((env), v8value->IsFunction(), napi_invalid_arg); \ 263 (result) = v8value.As
(); \ 264 } while (0) 265 266 #define CHECK_TO_OBJECT(env, context, result, src) \ 267 CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected) 268 269 #define CHECK_TO_OBJECT_WITH_PREAMBLE(env, context, result, src) \ 270 CHECK_TO_TYPE_WITH_PREAMBLE( \ 271 (env), Object, (context), (result), (src), napi_object_expected) 272 273 #define CHECK_TO_STRING(env, context, result, src) \ 274 CHECK_TO_TYPE((env), String, (context), (result), (src), napi_string_expected) 275 276 #define GET_RETURN_STATUS(env) \ 277 (!try_catch.HasCaught() \ 278 ? napi_ok \ 279 : napi_set_last_error((env), napi_pending_exception)) 280 281 #define THROW_RANGE_ERROR_IF_FALSE(env, condition, error, message) \ 282 do { \ 283 if (!(condition)) { \ 284 napi_throw_range_error((env), (error), (message)); \ 285 return napi_set_last_error((env), napi_generic_failure); \ 286 } \ 287 } while (0) 288 289 #define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \ 290 RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status)) 291 292 #define STATUS_CALL(call) \ 293 do { \ 294 napi_status status = (call); \ 295 if (status != napi_ok) return status; \ 296 } while (0) 297 298 namespace v8impl { 299 300 //=== Conversion between V8 Handles and napi_value ======================== 301 302 // This asserts v8::Local<> will always be implemented with a single 303 // pointer field so that we can pass it around as a void*. 304 static_assert(sizeof(v8::Local
) == sizeof(napi_value), 305 "Cannot convert between v8::Local
and napi_value"); 306 307 inline napi_value JsValueFromV8LocalValue(v8::Local
local) { 308 return reinterpret_cast
(*local); 309 } 310 311 inline v8::Local
V8LocalValueFromJsValue(napi_value v) { 312 v8::Local
local; 313 memcpy(static_cast
(&local), &v, sizeof(v)); 314 return local; 315 } 316 317 // Adapter for napi_finalize callbacks. 318 class Finalizer { 319 protected: 320 Finalizer(napi_env env, 321 napi_finalize finalize_callback, 322 void* finalize_data, 323 void* finalize_hint) 324 : env_(env), 325 finalize_callback_(finalize_callback), 326 finalize_data_(finalize_data), 327 finalize_hint_(finalize_hint) {} 328 329 virtual ~Finalizer() = default; 330 331 public: 332 static Finalizer* New(napi_env env, 333 napi_finalize finalize_callback = nullptr, 334 void* finalize_data = nullptr, 335 void* finalize_hint = nullptr) { 336 return new Finalizer(env, finalize_callback, finalize_data, finalize_hint); 337 } 338 339 napi_finalize callback() { return finalize_callback_; } 340 void* data() { return finalize_data_; } 341 void* hint() { return finalize_hint_; } 342 343 void ResetFinalizer(); 344 345 protected: 346 napi_env env_; 347 napi_finalize finalize_callback_; 348 void* finalize_data_; 349 void* finalize_hint_; 350 }; 351 352 class TryCatch : public v8::TryCatch { 353 public: 354 explicit TryCatch(napi_env env) : v8::TryCatch(env->isolate), _env(env) {} 355 356 ~TryCatch() { 357 if (HasCaught()) { 358 _env->last_exception.Reset(_env->isolate, Exception()); 359 } 360 } 361 362 private: 363 napi_env _env; 364 }; 365 366 // Ownership of a reference. 367 enum class Ownership { 368 // The reference is owned by the runtime. No userland call is needed to 369 // destruct the reference. 370 kRuntime, 371 // The reference is owned by the userland. User code is responsible to delete 372 // the reference with appropriate node-api calls. 373 kUserland, 374 }; 375 376 // Wrapper around Finalizer that can be tracked. 377 class TrackedFinalizer : public Finalizer, public RefTracker { 378 protected: 379 TrackedFinalizer(napi_env env, 380 napi_finalize finalize_callback, 381 void* finalize_data, 382 void* finalize_hint); 383 384 public: 385 static TrackedFinalizer* New(napi_env env, 386 napi_finalize finalize_callback, 387 void* finalize_data, 388 void* finalize_hint); 389 ~TrackedFinalizer() override; 390 391 protected: 392 void Finalize() override; 393 void FinalizeCore(bool deleteMe); 394 }; 395 396 // Wrapper around TrackedFinalizer that implements reference counting. 397 class RefBase : public TrackedFinalizer { 398 protected: 399 RefBase(napi_env env, 400 uint32_t initial_refcount, 401 Ownership ownership, 402 napi_finalize finalize_callback, 403 void* finalize_data, 404 void* finalize_hint); 405 406 public: 407 static RefBase* New(napi_env env, 408 uint32_t initial_refcount, 409 Ownership ownership, 410 napi_finalize finalize_callback, 411 void* finalize_data, 412 void* finalize_hint); 413 414 void* Data(); 415 uint32_t Ref(); 416 uint32_t Unref(); 417 uint32_t RefCount(); 418 419 Ownership ownership() { return ownership_; } 420 421 protected: 422 void Finalize() override; 423 424 private: 425 uint32_t refcount_; 426 Ownership ownership_; 427 }; 428 429 // Wrapper around v8impl::Persistent. 430 class Reference : public RefBase { 431 protected: 432 template
433 Reference(napi_env env, v8::Local
value, Args&&... args); 434 435 public: 436 static Reference* New(napi_env env, 437 v8::Local
value, 438 uint32_t initial_refcount, 439 Ownership ownership, 440 napi_finalize finalize_callback = nullptr, 441 void* finalize_data = nullptr, 442 void* finalize_hint = nullptr); 443 444 virtual ~Reference(); 445 uint32_t Ref(); 446 uint32_t Unref(); 447 v8::Local
Get(); 448 449 protected: 450 void Finalize() override; 451 452 private: 453 static void WeakCallback(const v8::WeakCallbackInfo
& data); 454 455 void SetWeak(); 456 457 v8impl::Persistent
persistent_; 458 bool can_be_weak_; 459 }; 460 461 } // end of namespace v8impl 462 463 #endif // SRC_JS_NATIVE_API_V8_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™