| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 84b7070 commit 8d222d4
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3686,6 +3686,23 @@ NAPI_EXTERN napi_status napi_run_script(napi_env env, | |||
| 3686 | 3686 | - `[in] script`: A JavaScript string containing the script to execute. | |
| 3687 | 3687 | - `[out] result`: The value resulting from having executed the script. | |
| 3688 | 3688 | ||
| 3689 | + ## libuv event loop | ||
| 3690 | + | ||
| 3691 | + N-API provides a function for getting the current event loop associated with | ||
| 3692 | + a specific `napi_env`. | ||
| 3693 | + | ||
| 3694 | + ### napi_get_uv_event_loop | ||
| 3695 | + <!-- YAML | ||
| 3696 | + added: REPLACEME | ||
| 3697 | + --> | ||
| 3698 | + ```C | ||
| 3699 | + NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, | ||
| 3700 | + uv_loop_t** loop); | ||
| 3701 | + ``` | ||
| 3702 | + | ||
| 3703 | + - `[in] env`: The environment that the API is invoked under. | ||
| 3704 | + - `[out] loop`: The current libuv loop instance. | ||
| 3705 | + | ||
| 3689 | 3706 | [Promises]: #n_api_promises | |
| 3690 | 3707 | [Simple Asynchronous Operations]: #n_api_simple_asynchronous_operations | |
| 3691 | 3708 | [Custom Asynchronous Operations]: #n_api_custom_asynchronous_operations | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,7 +18,7 @@ | |||
| 18 | 18 | #include "node_api.h" | |
| 19 | 19 | #include "node_internals.h" | |
| 20 | 20 | ||
| 21 | - #define NAPI_VERSION 1 | ||
| 21 | + #define NAPI_VERSION 2 | ||
| 22 | 22 | ||
| 23 | 23 | static | |
| 24 | 24 | napi_status napi_set_last_error(napi_env env, napi_status error_code, | |
@@ -28,8 +28,10 @@ static | |||
| 28 | 28 | napi_status napi_clear_last_error(napi_env env); | |
| 29 | 29 | ||
| 30 | 30 | struct napi_env__ { | |
| 31 | - explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), | ||
| 32 | - last_error() {} | ||
| 31 | + explicit napi_env__(v8::Isolate* _isolate, uv_loop_t* _loop) | ||
| 32 | + : isolate(_isolate), | ||
| 33 | + last_error(), | ||
| 34 | + loop(_loop) {} | ||
| 33 | 35 | ~napi_env__() { | |
| 34 | 36 | last_exception.Reset(); | |
| 35 | 37 | wrap_template.Reset(); | |
@@ -43,6 +45,7 @@ struct napi_env__ { | |||
| 43 | 45 | v8::Persistent<v8::ObjectTemplate> accessor_data_template; | |
| 44 | 46 | napi_extended_error_info last_error; | |
| 45 | 47 | int open_handle_scopes = 0; | |
| 48 | + uv_loop_t* loop = nullptr; | ||
| 46 | 49 | }; | |
| 47 | 50 | ||
| 48 | 51 | #define ENV_OBJECT_TEMPLATE(env, prefix, destination, field_count) \ | |
@@ -771,7 +774,7 @@ napi_env GetEnv(v8::Local<v8::Context> context) { | |||
| 771 | 774 | if (value->IsExternal()) { | |
| 772 | 775 | result = static_cast<napi_env>(value.As<v8::External>()->Value()); | |
| 773 | 776 | } else { | |
| 774 | - result = new napi_env__(isolate); | ||
| 777 | + result = new napi_env__(isolate, node::GetCurrentEventLoop(isolate)); | ||
| 775 | 778 | auto external = v8::External::New(isolate, result); | |
| 776 | 779 | ||
| 777 | 780 | // We must also stop hard if the result of assigning the env to the global | |
@@ -3401,15 +3404,22 @@ napi_status napi_delete_async_work(napi_env env, napi_async_work work) { | |||
| 3401 | 3404 | return napi_clear_last_error(env); | |
| 3402 | 3405 | } | |
| 3403 | 3406 | ||
| 3407 | + napi_status napi_get_uv_event_loop(napi_env env, uv_loop_t** loop) { | ||
| 3408 | + CHECK_ENV(env); | ||
| 3409 | + CHECK_ARG(env, loop); | ||
| 3410 | + *loop = env->loop; | ||
| 3411 | + return napi_clear_last_error(env); | ||
| 3412 | + } | ||
| 3413 | + | ||
| 3404 | 3414 | napi_status napi_queue_async_work(napi_env env, napi_async_work work) { | |
| 3405 | 3415 | CHECK_ENV(env); | |
| 3406 | 3416 | CHECK_ARG(env, work); | |
| 3407 | 3417 | ||
| 3408 | - // Consider: Encapsulate the uv_loop_t into an opaque pointer parameter. | ||
| 3409 | - // Currently the environment event loop is the same as the UV default loop. | ||
| 3410 | - // Someday (if node ever supports multiple isolates), it may be better to get | ||
| 3411 | - // the loop from node::Environment::GetCurrent(env->isolate)->event_loop(); | ||
| 3412 | - uv_loop_t* event_loop = uv_default_loop(); | ||
| 3418 | + napi_status status; | ||
| 3419 | + uv_loop_t* event_loop = nullptr; | ||
| 3420 | + status = napi_get_uv_event_loop(env, &event_loop); | ||
| 3421 | + if (status != napi_ok) | ||
| 3422 | + return napi_set_last_error(env, status); | ||
| 3413 | 3423 | ||
| 3414 | 3424 | uvimpl::Work* w = reinterpret_cast<uvimpl::Work*>(work); | |
| 3415 | 3425 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,6 +14,8 @@ | |||
| 14 | 14 | #include <stdbool.h> | |
| 15 | 15 | #include "node_api_types.h" | |
| 16 | 16 | ||
| 17 | + struct uv_loop_s; // Forward declaration. | ||
| 18 | + | ||
| 17 | 19 | #ifdef _WIN32 | |
| 18 | 20 | #ifdef BUILDING_NODE_EXTENSION | |
| 19 | 21 | #ifdef EXTERNAL_NAPI | |
@@ -581,6 +583,10 @@ NAPI_EXTERN napi_status napi_run_script(napi_env env, | |||
| 581 | 583 | napi_value script, | |
| 582 | 584 | napi_value* result); | |
| 583 | 585 | ||
| 586 | + // Return the current libuv event loop for a given environment | ||
| 587 | + NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, | ||
| 588 | + struct uv_loop_s** loop); | ||
| 589 | + | ||
| 584 | 590 | EXTERN_C_END | |
| 585 | 591 | ||
| 586 | 592 | #endif // SRC_NODE_API_H_ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,7 +34,7 @@ assert.ok(test_general.testGetPrototype(baseObject) !== | |||
| 34 | 34 | ||
| 35 | 35 | // test version management functions | |
| 36 | 36 | // expected version is currently 1 | |
| 37 | - assert.strictEqual(test_general.testGetVersion(), 1); | ||
| 37 | + assert.strictEqual(test_general.testGetVersion(), 2); | ||
| 38 | 38 | ||
| 39 | 39 | const [ major, minor, patch, release ] = test_general.testGetNodeVersion(); | |
| 40 | 40 | assert.strictEqual(process.version.split('-')[0], | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,8 @@ | |||
| 1 | + { | ||
| 2 | + "targets": [ | ||
| 3 | + { | ||
| 4 | + "target_name": "test_uv_loop", | ||
| 5 | + "sources": [ "test_uv_loop.cc" ] | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../../common'); | ||
| 3 | + const { SetImmediate } = require(`./build/${common.buildType}/test_uv_loop`); | ||
| 4 | + | ||
| 5 | + SetImmediate(common.mustCall()); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,78 @@ | |||
| 1 | + #include <node_api.h> | ||
| 2 | + #include <uv.h> | ||
| 3 | + #include <utility> | ||
| 4 | + #include <memory> | ||
| 5 | + #include <assert.h> | ||
| 6 | + #include "../common.h" | ||
| 7 | + | ||
| 8 | + template <typename T> | ||
| 9 | + void* SetImmediate(napi_env env, T&& cb) { | ||
| 10 | + T* ptr = new T(std::move(cb)); | ||
| 11 | + uv_loop_t* loop = nullptr; | ||
| 12 | + uv_check_t* check = new uv_check_t; | ||
| 13 | + check->data = ptr; | ||
| 14 | + NAPI_ASSERT(env, | ||
| 15 | + napi_get_uv_event_loop(env, &loop) == napi_ok, | ||
| 16 | + "can get event loop"); | ||
| 17 | + uv_check_init(loop, check); | ||
| 18 | + uv_check_start(check, [](uv_check_t* check) { | ||
| 19 | + std::unique_ptr<T> ptr {static_cast<T*>(check->data)}; | ||
| 20 | + T cb = std::move(*ptr); | ||
| 21 | + uv_close(reinterpret_cast<uv_handle_t*>(check), [](uv_handle_t* handle) { | ||
| 22 | + delete reinterpret_cast<uv_check_t*>(handle); | ||
| 23 | + }); | ||
| 24 | + | ||
| 25 | + assert(cb() != nullptr); | ||
| 26 | + }); | ||
| 27 | + return nullptr; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + static char dummy; | ||
| 31 | + | ||
| 32 | + napi_value SetImmediateBinding(napi_env env, napi_callback_info info) { | ||
| 33 | + size_t argc = 1; | ||
| 34 | + napi_value argv[1]; | ||
| 35 | + napi_value _this; | ||
| 36 | + void* data; | ||
| 37 | + NAPI_CALL(env, | ||
| 38 | + napi_get_cb_info(env, info, &argc, argv, &_this, &data)); | ||
| 39 | + NAPI_ASSERT(env, argc >= 1, "Not enough arguments, expected 1."); | ||
| 40 | + | ||
| 41 | + napi_valuetype t; | ||
| 42 | + NAPI_CALL(env, napi_typeof(env, argv[0], &t)); | ||
| 43 | + NAPI_ASSERT(env, t == napi_function, | ||
| 44 | + "Wrong first argument, function expected."); | ||
| 45 | + | ||
| 46 | + napi_ref cbref; | ||
| 47 | + NAPI_CALL(env, | ||
| 48 | + napi_create_reference(env, argv[0], 1, &cbref)); | ||
| 49 | + | ||
| 50 | + SetImmediate(env, [=]() -> char* { | ||
| 51 | + napi_value undefined; | ||
| 52 | + napi_value callback; | ||
| 53 | + napi_handle_scope scope; | ||
| 54 | + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); | ||
| 55 | + NAPI_CALL(env, napi_get_undefined(env, &undefined)); | ||
| 56 | + NAPI_CALL(env, napi_get_reference_value(env, cbref, &callback)); | ||
| 57 | + NAPI_CALL(env, napi_delete_reference(env, cbref)); | ||
| 58 | + NAPI_CALL(env, | ||
| 59 | + napi_call_function(env, undefined, callback, 0, nullptr, nullptr)); | ||
| 60 | + NAPI_CALL(env, napi_close_handle_scope(env, scope)); | ||
| 61 | + return &dummy; | ||
| 62 | + }); | ||
| 63 | + | ||
| 64 | + return nullptr; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + napi_value Init(napi_env env, napi_value exports) { | ||
| 68 | + napi_property_descriptor properties[] = { | ||
| 69 | + DECLARE_NAPI_PROPERTY("SetImmediate", SetImmediateBinding) | ||
| 70 | + }; | ||
| 71 | + | ||
| 72 | + NAPI_CALL(env, napi_define_properties( | ||
| 73 | + env, exports, sizeof(properties) / sizeof(*properties), properties)); | ||
| 74 | + | ||
| 75 | + return exports; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments