@reboot-dev/reboot 0.41.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/reboot_native.cc CHANGED
@@ -27,20 +27,18 @@ namespace py = pybind11;
27
27
 
28
28
  // Helper when debugging, left for future optimization work.
29
29
  struct Timer {
30
- Timer(const char* name)
31
- : name_(name) {
30
+ Timer(const char* name) : name_(name) {
32
31
  start_ = std::chrono::high_resolution_clock::now();
33
32
  }
34
33
 
35
34
  void elapsed(const char* step = nullptr) const {
36
35
  auto end = std::chrono::high_resolution_clock::now();
37
- auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
38
- end - start_);
36
+ auto duration =
37
+ std::chrono::duration_cast<std::chrono::milliseconds>(end - start_);
39
38
  std::stringstream ss;
40
39
  ss << name_
41
40
  << (step != nullptr ? " at " + std::string(step) : std::string(""))
42
- << " took " << duration.count() << "ms"
43
- << std::endl;
41
+ << " took " << duration.count() << "ms" << std::endl;
44
42
  std::cout << ss.str();
45
43
  }
46
44
 
@@ -87,9 +85,9 @@ struct PythonNodeAdaptor {
87
85
  if (const py::error_already_set* e_py =
88
86
  dynamic_cast<const py::error_already_set*>(&e)) {
89
87
  // This is a Python exception. Is it an `InputError`?
90
- if (e_py->matches(py::module::import(
91
- "rebootdev.aio.exceptions")
92
- .attr("InputError"))) {
88
+ if (e_py->matches(
89
+ py::module::import("rebootdev.aio.exceptions")
90
+ .attr("InputError"))) {
93
91
  // This is an InputError, which means it reports a mistake in the input
94
92
  // provided by the developer. We want to print _only_ the user-friendly
95
93
  // error message in the exception, without intimidating stack traces.
@@ -104,15 +102,13 @@ struct PythonNodeAdaptor {
104
102
  // help diagnose the problem.
105
103
  std::cerr << "Unexpected library exception: " << e_py->what()
106
104
  << std::endl
107
- << "Please report this bug to the maintainers!"
108
- << std::endl;
105
+ << "Please report this bug to the maintainers!" << std::endl;
109
106
  }
110
107
  } else {
111
108
  // This is a C++ exception; something went wrong in the C++ code. Request
112
109
  // that the developer reports the issue.
113
- std::cerr
114
- << "Unexpected adapter exception: " << e.what() << std::endl
115
- << "Please report this bug to the maintainers!" << std::endl;
110
+ std::cerr << "Unexpected adapter exception: " << e.what() << std::endl
111
+ << "Please report this bug to the maintainers!" << std::endl;
116
112
  }
117
113
  }
118
114
 
@@ -224,11 +220,8 @@ struct PythonNodeAdaptor {
224
220
  try {
225
221
  function(env);
226
222
  } catch (const std::exception& e) {
227
- std::cerr
228
- << "Unexpected exception: " << e.what()
229
- << "\n"
230
- << "Please report this bug to the maintainers!"
231
- << std::endl;
223
+ std::cerr << "Unexpected exception: " << e.what() << "\n"
224
+ << "Please report this bug to the maintainers!" << std::endl;
232
225
  }
233
226
  }
234
227
  }
@@ -263,10 +256,7 @@ struct PythonNodeAdaptor {
263
256
  // into Python or expecting calls from Python.
264
257
  std::atomic<int> references{0};
265
258
 
266
- Napi::TypedThreadSafeFunction<
267
- void,
268
- void,
269
- _RunNodeFunctions>
259
+ Napi::TypedThreadSafeFunction<void, void, _RunNodeFunctions>
270
260
  thread_safe_function;
271
261
  std::mutex node_functions_mutex_;
272
262
  std::list<std::function<void(Napi::Env&)>> node_functions_;
@@ -294,9 +284,7 @@ struct NapiReferenceDeleter {
294
284
  template <typename T>
295
285
  void operator()(Napi::Reference<T>* reference) {
296
286
  adaptor->ScheduleCallbackOnNodeEventLoopLowPriority(
297
- [reference](Napi::Env) {
298
- delete reference;
299
- });
287
+ [reference](Napi::Env) { delete reference; });
300
288
  }
301
289
  };
302
290
 
@@ -335,13 +323,9 @@ using NapiSafeObjectReference = NapiSafeReference<Napi::Object>;
335
323
  // also includes our C++ <-> Python class wrappers for storing NAPI
336
324
  // objects in Python to properly handle memory management.
337
325
  PYBIND11_EMBEDDED_MODULE(reboot_native, m) {
338
- py::class_<NapiSafeFunctionReference>(
339
- m,
340
- "NapiSafeFunctionReference");
326
+ py::class_<NapiSafeFunctionReference>(m, "NapiSafeFunctionReference");
341
327
 
342
- py::class_<NapiSafeObjectReference>(
343
- m,
344
- "NapiSafeObjectReference");
328
+ py::class_<NapiSafeObjectReference>(m, "NapiSafeObjectReference");
345
329
  }
346
330
 
347
331
 
@@ -354,9 +338,7 @@ Napi::External<py::object> make_napi_external(
354
338
  py_object,
355
339
  [](Napi::Env, py::object* py_object) {
356
340
  adaptor->ScheduleCallbackOnPythonEventLoopLowPriority(
357
- [py_object]() {
358
- delete py_object;
359
- });
341
+ [py_object]() { delete py_object; });
360
342
  });
361
343
 
362
344
  if (type_tag != nullptr) {
@@ -379,126 +361,119 @@ void _RunNodeFunctions(
379
361
  void PythonNodeAdaptor::Initialize(
380
362
  Napi::Env& env,
381
363
  const Napi::Function& js_callback) {
382
- thread_safe_function = Napi::TypedThreadSafeFunction<
383
- void,
384
- void,
385
- _RunNodeFunctions>::New(
386
- /* Environment: */ env,
387
- /* JS callback: */ js_callback,
388
- /* Resource name: */ "reboot_native",
389
- /* Max queue size (0 = unlimited): */ 0,
390
- /* Initial thread count: */ 1,
391
- /* Context: */ (void*) nullptr,
392
- // Finalizer:
393
- [this](Napi::Env env, void*, void*) {
394
- // Set that we've been finalized so that we don't use
395
- // `thread_safe_function` again, see comment in
396
- // `ScheduleCallbackOnNodeEventLoop`.
397
- thread_safe_function_finalized = true; },
398
- /* Finalizer data: */ (void*) nullptr);
364
+ thread_safe_function =
365
+ Napi::TypedThreadSafeFunction<void, void, _RunNodeFunctions>::New(
366
+ /* Environment: */
367
+ env,
368
+ /* JS callback: */ js_callback,
369
+ /* Resource name: */ "reboot_native",
370
+ /* Max queue size (0 = unlimited): */ 0,
371
+ /* Initial thread count: */ 1,
372
+ /* Context: */ (void*) nullptr,
373
+ // Finalizer:
374
+ [this](Napi::Env env, void*, void*) {
375
+ // Set that we've been finalized so that we don't use
376
+ // `thread_safe_function` again, see comment in
377
+ // `ScheduleCallbackOnNodeEventLoop`.
378
+ thread_safe_function_finalized = true;
379
+ },
380
+ /* Finalizer data: */ (void*) nullptr);
399
381
 
400
382
  // We start with our thread safe function unreferenced so that
401
383
  // if the user's code never calls into us we won't keep Node
402
384
  // from exiting.
403
385
  thread_safe_function.Unref(env);
404
386
 
405
- thread = std::thread(
406
- [this]() {
407
- // Set environment variables _before_ initializing the
408
- // interpreter because it may cache the variables. Also, some
409
- // of the variables need to be set before we start importing
410
- // anything.
411
- //
412
- // Don't try and manipulate signals when running within Node!
413
- setenv("REBOOT_SIGNALS_AVAILABLE", "false", 1);
414
- // Specify that we are running from within `node`.
415
- setenv("REBOOT_NODEJS", "true", 1);
416
-
417
- py::initialize_interpreter();
418
-
419
- try {
420
- py::object module = py::module::import("rebootdev.nodejs.python");
421
-
422
- module.attr("launch_subprocess_server") = py::cpp_function(
423
- [](py::str py_base64_args) {
424
- py::object py_future =
425
- py::module::import("asyncio").attr("Future")();
426
-
427
- adaptor->ScheduleCallbackOnNodeEventLoop(
428
- [base64_args = std::string(py_base64_args),
429
- py_future = new py::object(py_future)](Napi::Env env) {
430
- try {
431
- Napi::Number js_pid =
432
- js_launchSubprocessServer
433
- ->Call(
434
- {Napi::String::New(env, base64_args)})
435
- .As<Napi::Number>();
436
-
437
- adaptor->ScheduleCallbackOnPythonEventLoop(
438
- [py_future, pid = js_pid.Int64Value()]() {
439
- bool cancelled =
440
- py_future->attr("cancelled")()
441
- .cast<bool>();
442
- if (!cancelled) {
443
- py_future->attr("set_result")(pid);
444
- }
445
- delete py_future;
446
- });
447
- } catch (const Napi::Error& e) {
448
- adaptor->ScheduleCallbackOnPythonEventLoop(
449
- [py_future, what = e.what()]() {
450
- bool cancelled =
451
- py_future->attr("cancelled")()
452
- .cast<bool>();
453
- if (!cancelled) {
454
- py_future->attr("set_exception")(
455
- py::module::import("builtins")
456
- .attr("Exception")(
457
- what));
458
- }
459
- delete py_future;
460
- });
461
- }
462
- });
387
+ thread = std::thread([this]() {
388
+ // Set environment variables _before_ initializing the
389
+ // interpreter because it may cache the variables. Also, some
390
+ // of the variables need to be set before we start importing
391
+ // anything.
392
+ //
393
+ // Don't try and manipulate signals when running within Node!
394
+ setenv("REBOOT_SIGNALS_AVAILABLE", "false", 1);
395
+ // Specify that we are running from within `node`.
396
+ setenv("REBOOT_NODEJS", "true", 1);
463
397
 
464
- return py_future;
465
- });
398
+ py::initialize_interpreter();
466
399
 
467
- module.attr("run_functions") = py::cpp_function(
468
- [this]() {
469
- std::list<std::function<void()>> functions;
470
- std::vector<std::pair<py::object*, std::string>> futures;
400
+ try {
401
+ py::object module = py::module::import("rebootdev.nodejs.python");
471
402
 
472
- {
473
- std::unique_lock<std::mutex> lock(mutex);
474
- functions = std::move(python_functions);
475
- should_signal_fd_ = true;
476
- }
403
+ module.attr("launch_subprocess_server") =
404
+ py::cpp_function([](py::str py_base64_args) {
405
+ py::object py_future =
406
+ py::module::import("asyncio").attr("Future")();
477
407
 
478
- for (auto&& function : functions) {
408
+ adaptor->ScheduleCallbackOnNodeEventLoop(
409
+ [base64_args = std::string(py_base64_args),
410
+ py_future = new py::object(py_future)](Napi::Env env) {
479
411
  try {
480
- function();
481
- } catch (std::exception& e) {
482
- PythonNodeAdaptor::HandleException(e);
412
+ Napi::Number js_pid =
413
+ js_launchSubprocessServer
414
+ ->Call({Napi::String::New(env, base64_args)})
415
+ .As<Napi::Number>();
416
+
417
+ adaptor->ScheduleCallbackOnPythonEventLoop(
418
+ [py_future, pid = js_pid.Int64Value()]() {
419
+ bool cancelled =
420
+ py_future->attr("cancelled")().cast<bool>();
421
+ if (!cancelled) {
422
+ py_future->attr("set_result")(pid);
423
+ }
424
+ delete py_future;
425
+ });
426
+ } catch (const Napi::Error& e) {
427
+ adaptor->ScheduleCallbackOnPythonEventLoop(
428
+ [py_future, what = e.what()]() {
429
+ bool cancelled =
430
+ py_future->attr("cancelled")().cast<bool>();
431
+ if (!cancelled) {
432
+ py_future->attr("set_exception")(
433
+ py::module::import("builtins")
434
+ .attr("Exception")(what));
435
+ }
436
+ delete py_future;
437
+ });
483
438
  }
484
- }
485
- });
439
+ });
440
+
441
+ return py_future;
442
+ });
486
443
 
487
- py::object event_loop_thread = module.attr("EventLoopThread")(
488
- read_fd_);
444
+ module.attr("run_functions") = py::cpp_function([this]() {
445
+ std::list<std::function<void()>> functions;
446
+ std::vector<std::pair<py::object*, std::string>> futures;
489
447
 
490
- py::gil_scoped_release release;
448
+ {
449
+ std::unique_lock<std::mutex> lock(mutex);
450
+ functions = std::move(python_functions);
451
+ should_signal_fd_ = true;
452
+ }
491
453
 
492
- while (true) {
493
- std::this_thread::sleep_until(
494
- std::chrono::time_point<std::chrono::system_clock>::max());
495
- continue;
454
+ for (auto&& function : functions) {
455
+ try {
456
+ function();
457
+ } catch (std::exception& e) {
458
+ PythonNodeAdaptor::HandleException(e);
496
459
  }
497
- } catch (const std::exception& e) {
498
- std::cout << e.what() << std::endl;
499
- throw;
500
460
  }
501
461
  });
462
+
463
+ py::object event_loop_thread = module.attr("EventLoopThread")(read_fd_);
464
+
465
+ py::gil_scoped_release release;
466
+
467
+ while (true) {
468
+ std::this_thread::sleep_until(
469
+ std::chrono::time_point<std::chrono::system_clock>::max());
470
+ continue;
471
+ }
472
+ } catch (const std::exception& e) {
473
+ std::cout << e.what() << std::endl;
474
+ throw;
475
+ }
476
+ });
502
477
  }
503
478
 
504
479
 
@@ -555,21 +530,19 @@ template <typename F, typename T = std::invoke_result_t<F>>
555
530
  T RunCallbackOnPythonEventLoop(F&& f) {
556
531
  std::promise<T> promise;
557
532
 
558
- adaptor->ScheduleCallbackOnPythonEventLoop(
559
- [&f, &promise]() {
560
- try {
561
- if constexpr (std::is_void<T>::value) {
562
- f();
563
- promise.set_value();
564
- } else {
565
- promise.set_value(f());
566
- }
567
- } catch (const std::exception& e) {
568
- promise.set_exception(
569
- std::make_exception_ptr(
570
- std::runtime_error(e.what())));
571
- }
572
- });
533
+ adaptor->ScheduleCallbackOnPythonEventLoop([&f, &promise]() {
534
+ try {
535
+ if constexpr (std::is_void<T>::value) {
536
+ f();
537
+ promise.set_value();
538
+ } else {
539
+ promise.set_value(f());
540
+ }
541
+ } catch (const std::exception& e) {
542
+ promise.set_exception(
543
+ std::make_exception_ptr(std::runtime_error(e.what())));
544
+ }
545
+ });
573
546
 
574
547
  return promise.get_future().get();
575
548
  }
@@ -598,8 +571,7 @@ T RunCallbackOnNodeEventLoop(F&& f, bool warn = false) {
598
571
  .Call({e.Value(), Napi::String::New(env, "\n")});
599
572
  }
600
573
  promise.set_exception(
601
- std::make_exception_ptr(
602
- std::runtime_error(e.what())));
574
+ std::make_exception_ptr(std::runtime_error(e.what())));
603
575
  } catch (const std::exception& e) {
604
576
  if (warn) {
605
577
  env.Global()
@@ -612,8 +584,7 @@ T RunCallbackOnNodeEventLoop(F&& f, bool warn = false) {
612
584
  Napi::String::New(env, "\n")});
613
585
  }
614
586
  promise.set_exception(
615
- std::make_exception_ptr(
616
- std::runtime_error(e.what())));
587
+ std::make_exception_ptr(std::runtime_error(e.what())));
617
588
  }
618
589
  });
619
590
 
@@ -658,8 +629,7 @@ Napi::Promise NodePromiseFromPythonCallback(
658
629
  } catch (const std::exception& e) {
659
630
  // TODO: is this code unreachable because Node.js
660
631
  // will properly always only pass us a `Napi::Error`?
661
- js_deferred->Reject(
662
- Napi::Error::New(env, e.what()).Value());
632
+ js_deferred->Reject(Napi::Error::New(env, e.what()).Value());
663
633
  } catch (...) {
664
634
  // TODO: is this code unreachable because Node.js
665
635
  // will properly always only pass us a `Napi::Error`?
@@ -678,16 +648,14 @@ Napi::Promise NodePromiseFromPythonCallback(
678
648
  });
679
649
 
680
650
  // Allow Node to exit after we've resolved or rejected the promise.
681
- auto js_resolve_reject = Napi::Function::New(
682
- env,
683
- [](const Napi::CallbackInfo& info) {
651
+ auto js_resolve_reject =
652
+ Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
684
653
  adaptor->AllowNodeToExit(info.Env());
685
654
  });
686
655
 
687
- js_promise
688
- .Get("then")
689
- .As<Napi::Function>()
690
- .Call(js_promise, {js_resolve_reject, js_resolve_reject});
656
+ js_promise.Get("then").As<Napi::Function>().Call(
657
+ js_promise,
658
+ {js_resolve_reject, js_resolve_reject});
691
659
 
692
660
  return js_promise;
693
661
  }
@@ -719,10 +687,10 @@ Napi::Promise NodePromiseFromPythonFuture(
719
687
  auto js_promise = js_deferred->Promise();
720
688
 
721
689
  adaptor->ScheduleCallbackOnPythonEventLoop(
722
- [python_future_callback = std::forward<PythonFutureCallback>(
723
- python_future_callback),
724
- python_done_callback = std::forward<PythonDoneCallback>(
725
- python_done_callback),
690
+ [python_future_callback =
691
+ std::forward<PythonFutureCallback>(python_future_callback),
692
+ python_done_callback =
693
+ std::forward<PythonDoneCallback>(python_done_callback),
726
694
  node_callback = std::forward<NodeCallback>(node_callback),
727
695
  js_deferred = std::move(js_deferred)]() mutable {
728
696
  try {
@@ -730,8 +698,8 @@ Napi::Promise NodePromiseFromPythonFuture(
730
698
  py::object py_future = python_future_callback();
731
699
 
732
700
  py_future.attr("add_done_callback")(py::cpp_function(
733
- [python_done_callback = std::forward<PythonDoneCallback>(
734
- python_done_callback),
701
+ [python_done_callback =
702
+ std::forward<PythonDoneCallback>(python_done_callback),
735
703
  node_callback = std::forward<NodeCallback>(node_callback),
736
704
  js_deferred = std::move(js_deferred),
737
705
  // NOTE: need to keep a reference to `py_future` so that it
@@ -766,9 +734,8 @@ Napi::Promise NodePromiseFromPythonFuture(
766
734
  js_deferred = std::move(js_deferred),
767
735
  result = std::move(result)](Napi::Env env) mutable {
768
736
  // TODO: try / catch around `node_callback`.
769
- auto js_result = node_callback(
770
- env,
771
- std::move(result));
737
+ auto js_result =
738
+ node_callback(env, std::move(result));
772
739
  js_deferred->Resolve(js_result);
773
740
  });
774
741
  }
@@ -787,16 +754,14 @@ Napi::Promise NodePromiseFromPythonFuture(
787
754
  });
788
755
 
789
756
  // Allow Node to exit after we've resolved or rejected the promise.
790
- auto js_resolve_reject = Napi::Function::New(
791
- env,
792
- [](const Napi::CallbackInfo& info) {
757
+ auto js_resolve_reject =
758
+ Napi::Function::New(env, [](const Napi::CallbackInfo& info) {
793
759
  adaptor->AllowNodeToExit(info.Env());
794
760
  });
795
761
 
796
- js_promise
797
- .Get("then")
798
- .As<Napi::Function>()
799
- .Call(js_promise, {js_resolve_reject, js_resolve_reject});
762
+ js_promise.Get("then").As<Napi::Function>().Call(
763
+ js_promise,
764
+ {js_resolve_reject, js_resolve_reject});
800
765
 
801
766
  return js_promise;
802
767
  }
@@ -815,9 +780,7 @@ Napi::Promise NodePromiseFromPythonFuture(
815
780
  // TODO: check that `py_result` is `None`.
816
781
  return std::nullopt;
817
782
  },
818
- [](Napi::Env env, std::nullopt_t) {
819
- return env.Null();
820
- });
783
+ [](Napi::Env env, std::nullopt_t) { return env.Null(); });
821
784
  }
822
785
 
823
786
 
@@ -838,8 +801,8 @@ Napi::Promise NodePromiseFromPythonTask(
838
801
  env,
839
802
  [name,
840
803
  create_task = std::move(create_task),
841
- python_task_callback = std::forward<PythonTaskCallback>(
842
- python_task_callback)]() mutable {
804
+ python_task_callback =
805
+ std::forward<PythonTaskCallback>(python_task_callback)]() mutable {
843
806
  py::object py_task = std::apply(
844
807
  [&name, &python_task_callback](
845
808
  const std::string& import,
@@ -875,9 +838,7 @@ Napi::Promise NodePromiseFromPythonTask(
875
838
  // TODO: check that `py_result` is `None`.
876
839
  return std::nullopt;
877
840
  },
878
- [](Napi::Env env, std::nullopt_t) {
879
- return env.Null();
880
- });
841
+ [](Napi::Env env, std::nullopt_t) { return env.Null(); });
881
842
  }
882
843
 
883
844
 
@@ -900,11 +861,9 @@ Napi::Promise NodePromiseFromPythonTaskWithContext(
900
861
  std::string("rebootdev.nodejs.python"),
901
862
  std::string("create_task_with_context"),
902
863
  py_context),
903
- [js_context, // Ensures `py_context` remains valid.
904
- python_task_callback =
905
- std::forward<PythonTaskCallback>(python_task_callback)]() mutable {
906
- return python_task_callback();
907
- },
864
+ [js_context, // Ensures `py_context` remains valid.
865
+ python_task_callback = std::forward<PythonTaskCallback>(
866
+ python_task_callback)]() mutable { return python_task_callback(); },
908
867
  std::forward<PythonDoneCallback>(python_done_callback),
909
868
  std::forward<NodeCallback>(node_callback));
910
869
  }
@@ -925,9 +884,7 @@ Napi::Promise NodePromiseFromPythonTaskWithContext(
925
884
  // TODO: check that `py_result` is `None`.
926
885
  return std::nullopt;
927
886
  },
928
- [](Napi::Env env, std::nullopt_t) {
929
- return env.Null();
930
- });
887
+ [](Napi::Env env, std::nullopt_t) { return env.Null(); });
931
888
  }
932
889
 
933
890
 
@@ -952,64 +909,58 @@ py::object PythonFutureFromNodePromise(
952
909
  try {
953
910
  Napi::Object js_promise = node_promise_callback(env);
954
911
 
955
- js_promise
956
- .Get("then")
957
- .As<Napi::Function>()
958
- .Call(
959
- js_promise,
960
- {Napi::Function::New(
961
- env,
962
- [node_promise_resolved_callback =
963
- std::forward<NodePromiseResolvedCallback>(
964
- node_promise_resolved_callback),
965
- python_callback = std::forward<PythonCallback>(
966
- python_callback),
967
- py_future](const Napi::CallbackInfo& info) mutable {
968
- // TODO: put a try/catch around
969
- // `node_promise_resolved_callback` to handle
970
- // any errors.
971
-
972
- auto result = node_promise_resolved_callback(
973
- info.Env(),
974
- info[0]);
975
-
976
- adaptor->ScheduleCallbackOnPythonEventLoop(
977
- [python_callback = std::forward<PythonCallback>(
978
- python_callback),
979
- py_future,
980
- result = std::move(result)]() mutable {
981
- bool cancelled =
982
- py_future->attr("cancelled")().cast<bool>();
983
- if (!cancelled) {
984
- // TODO: put a try/catch around
985
- // `python_callback` to handle any
986
- // errors.
987
- py_future->attr("set_result")(
988
- python_callback(std::move(result)));
989
- }
990
- delete py_future;
991
- });
992
- }),
993
- Napi::Function::New(
994
- env,
995
- [py_future](const Napi::CallbackInfo& info) {
996
- std::string message = message_from_js_error(
997
- info[0].As<Napi::Object>());
998
-
999
- adaptor->ScheduleCallbackOnPythonEventLoop(
1000
- [py_future, message = std::move(message)]() {
1001
- bool cancelled =
1002
- py_future->attr("cancelled")()
1003
- .cast<bool>();
1004
- if (!cancelled) {
1005
- py_future->attr("set_exception")(
1006
- py::module::import("builtins")
1007
- .attr("Exception")(
1008
- message));
1009
- }
1010
- delete py_future;
1011
- });
1012
- })});
912
+ js_promise.Get("then").As<Napi::Function>().Call(
913
+ js_promise,
914
+ {Napi::Function::New(
915
+ env,
916
+ [node_promise_resolved_callback =
917
+ std::forward<NodePromiseResolvedCallback>(
918
+ node_promise_resolved_callback),
919
+ python_callback =
920
+ std::forward<PythonCallback>(python_callback),
921
+ py_future](const Napi::CallbackInfo& info) mutable {
922
+ // TODO: put a try/catch around
923
+ // `node_promise_resolved_callback` to handle
924
+ // any errors.
925
+
926
+ auto result =
927
+ node_promise_resolved_callback(info.Env(), info[0]);
928
+
929
+ adaptor->ScheduleCallbackOnPythonEventLoop(
930
+ [python_callback =
931
+ std::forward<PythonCallback>(python_callback),
932
+ py_future,
933
+ result = std::move(result)]() mutable {
934
+ bool cancelled =
935
+ py_future->attr("cancelled")().cast<bool>();
936
+ if (!cancelled) {
937
+ // TODO: put a try/catch around
938
+ // `python_callback` to handle any
939
+ // errors.
940
+ py_future->attr("set_result")(
941
+ python_callback(std::move(result)));
942
+ }
943
+ delete py_future;
944
+ });
945
+ }),
946
+ Napi::Function::New(
947
+ env,
948
+ [py_future](const Napi::CallbackInfo& info) {
949
+ std::string message =
950
+ message_from_js_error(info[0].As<Napi::Object>());
951
+
952
+ adaptor->ScheduleCallbackOnPythonEventLoop(
953
+ [py_future, message = std::move(message)]() {
954
+ bool cancelled =
955
+ py_future->attr("cancelled")().cast<bool>();
956
+ if (!cancelled) {
957
+ py_future->attr("set_exception")(
958
+ py::module::import("builtins")
959
+ .attr("Exception")(message));
960
+ }
961
+ delete py_future;
962
+ });
963
+ })});
1013
964
  } catch (const std::exception& e) {
1014
965
  // NOTE: we're just catching exception here vs `Napi::Error`
1015
966
  // since all we care about is `what()` but we're making sure
@@ -1021,31 +972,28 @@ py::object PythonFutureFromNodePromise(
1021
972
 
1022
973
  std::string message = e.what();
1023
974
 
1024
- adaptor->ScheduleCallbackOnPythonEventLoop(
1025
- [py_future, message = std::move(message)]() {
1026
- bool cancelled =
1027
- py_future->attr("cancelled")().cast<bool>();
1028
- if (!cancelled) {
1029
- py_future->attr("set_exception")(
1030
- py::module::import("builtins")
1031
- .attr("Exception")(message));
1032
- }
1033
- delete py_future;
1034
- });
975
+ adaptor->ScheduleCallbackOnPythonEventLoop([py_future,
976
+ message = std::move(
977
+ message)]() {
978
+ bool cancelled = py_future->attr("cancelled")().cast<bool>();
979
+ if (!cancelled) {
980
+ py_future->attr("set_exception")(
981
+ py::module::import("builtins").attr("Exception")(message));
982
+ }
983
+ delete py_future;
984
+ });
1035
985
  } catch (...) {
1036
986
  // TODO: is this code unreachable because Node.js
1037
987
  // will properly always only pass us a `Napi::Error`?
1038
- adaptor->ScheduleCallbackOnPythonEventLoop(
1039
- [py_future]() {
1040
- bool cancelled =
1041
- py_future->attr("cancelled")().cast<bool>();
1042
- if (!cancelled) {
1043
- py_future->attr("set_exception")(
1044
- py::module::import("builtins")
1045
- .attr("Exception")("Unknown error"));
1046
- }
1047
- delete py_future;
1048
- });
988
+ adaptor->ScheduleCallbackOnPythonEventLoop([py_future]() {
989
+ bool cancelled = py_future->attr("cancelled")().cast<bool>();
990
+ if (!cancelled) {
991
+ py_future->attr("set_exception")(
992
+ py::module::import("builtins")
993
+ .attr("Exception")("Unknown error"));
994
+ }
995
+ delete py_future;
996
+ });
1049
997
  }
1050
998
  });
1051
999
 
@@ -1053,19 +1001,14 @@ py::object PythonFutureFromNodePromise(
1053
1001
  }
1054
1002
 
1055
1003
 
1056
- template <
1057
- typename NodePromiseCallback,
1058
- typename NodePromiseResolvedCallback>
1004
+ template <typename NodePromiseCallback, typename NodePromiseResolvedCallback>
1059
1005
  py::object PythonFutureFromNodePromise(
1060
1006
  NodePromiseCallback&& node_promise_callback,
1061
1007
  NodePromiseResolvedCallback&& node_promise_resolved_callback) {
1062
1008
  return PythonFutureFromNodePromise(
1063
1009
  std::forward<NodePromiseCallback>(node_promise_callback),
1064
- std::forward<NodePromiseResolvedCallback>(
1065
- node_promise_resolved_callback),
1066
- [](auto&& result) {
1067
- return std::move(result);
1068
- });
1010
+ std::forward<NodePromiseResolvedCallback>(node_promise_resolved_callback),
1011
+ [](auto&& result) { return std::move(result); });
1069
1012
  }
1070
1013
 
1071
1014
 
@@ -1074,12 +1017,8 @@ py::object PythonFutureFromNodePromise(
1074
1017
  NodePromiseCallback&& node_promise_callback) {
1075
1018
  return PythonFutureFromNodePromise(
1076
1019
  std::forward<NodePromiseCallback>(node_promise_callback),
1077
- [](Napi::Env, Napi::Value) {
1078
- return std::nullopt;
1079
- },
1080
- [](auto&&) {
1081
- return py::none();
1082
- });
1020
+ [](Napi::Env, Napi::Value) { return std::nullopt; },
1021
+ [](auto&&) { return py::none(); });
1083
1022
  }
1084
1023
 
1085
1024
 
@@ -1105,11 +1044,10 @@ void ImportPy(const Napi::CallbackInfo& info) {
1105
1044
  std::string module = info[0].As<Napi::String>().Utf8Value();
1106
1045
  std::string base64_encoded_rbt_py = info[1].As<Napi::String>().Utf8Value();
1107
1046
 
1108
- RunCallbackOnPythonEventLoop(
1109
- [&module, &base64_encoded_rbt_py]() {
1110
- py::module::import("rebootdev.nodejs.python")
1111
- .attr("import_py")(module, base64_encoded_rbt_py);
1112
- });
1047
+ RunCallbackOnPythonEventLoop([&module, &base64_encoded_rbt_py]() {
1048
+ py::module::import("rebootdev.nodejs.python")
1049
+ .attr("import_py")(module, base64_encoded_rbt_py);
1050
+ });
1113
1051
  }
1114
1052
 
1115
1053
 
@@ -1134,19 +1072,16 @@ napi_type_tag MakeTypeTag(const std::string& module, const std::string& type) {
1134
1072
  }
1135
1073
 
1136
1074
 
1137
- static const napi_type_tag reboot_aio_tests_Reboot = MakeTypeTag(
1138
- "reboot.aio.tests",
1139
- "Reboot");
1075
+ static const napi_type_tag reboot_aio_tests_Reboot =
1076
+ MakeTypeTag("reboot.aio.tests", "Reboot");
1140
1077
 
1141
1078
 
1142
- static const napi_type_tag reboot_aio_applications_Application = MakeTypeTag(
1143
- "reboot.aio.applications",
1144
- "Application");
1079
+ static const napi_type_tag reboot_aio_applications_Application =
1080
+ MakeTypeTag("reboot.aio.applications", "Application");
1145
1081
 
1146
1082
 
1147
- static const napi_type_tag reboot_aio_external_ExternalContext = MakeTypeTag(
1148
- "rebootdev.aio.external",
1149
- "ExternalContext");
1083
+ static const napi_type_tag reboot_aio_external_ExternalContext =
1084
+ MakeTypeTag("rebootdev.aio.external", "ExternalContext");
1150
1085
 
1151
1086
 
1152
1087
  Napi::Value python3Path(const Napi::CallbackInfo& info) {
@@ -1173,16 +1108,13 @@ std::string uint8array_to_str(const Napi::Uint8Array& arr) {
1173
1108
 
1174
1109
 
1175
1110
  Napi::Value Reboot_constructor(const Napi::CallbackInfo& info) {
1176
- py::object* py_reboot = RunCallbackOnPythonEventLoop(
1177
- []() {
1178
- py::object tests = py::module::import("reboot.aio.tests");
1179
- return new py::object(tests.attr("Reboot")());
1180
- });
1111
+ py::object* py_reboot = RunCallbackOnPythonEventLoop([]() {
1112
+ py::object tests = py::module::import("reboot.aio.tests");
1113
+ return new py::object(tests.attr("Reboot")());
1114
+ });
1181
1115
 
1182
- Napi::External<py::object> js_external_reboot = make_napi_external(
1183
- info.Env(),
1184
- py_reboot,
1185
- &reboot_aio_tests_Reboot);
1116
+ Napi::External<py::object> js_external_reboot =
1117
+ make_napi_external(info.Env(), py_reboot, &reboot_aio_tests_Reboot);
1186
1118
 
1187
1119
  return js_external_reboot;
1188
1120
  }
@@ -1216,27 +1148,21 @@ Napi::Value Reboot_createExternalContext(const Napi::CallbackInfo& info) {
1216
1148
  }
1217
1149
 
1218
1150
  py::object* py_context = RunCallbackOnPythonEventLoop(
1219
- [py_reboot,
1220
- &name,
1221
- &idempotency_seed,
1222
- &bearer_token,
1223
- app_internal]() {
1151
+ [py_reboot, &name, &idempotency_seed, &bearer_token, app_internal]() {
1224
1152
  py::object py_idempotency_seed = py::none();
1225
1153
  if (idempotency_seed.has_value()) {
1226
- py_idempotency_seed =
1227
- py::module::import("uuid")
1228
- .attr("UUID")(py::str(*idempotency_seed));
1154
+ py_idempotency_seed = py::module::import("uuid").attr("UUID")(
1155
+ py::str(*idempotency_seed));
1229
1156
  }
1230
1157
  py::object py_bearer_token = py::none();
1231
1158
  if (bearer_token.has_value()) {
1232
1159
  py_bearer_token = py::str(*bearer_token);
1233
1160
  }
1234
- return new py::object(
1235
- py_reboot->attr("create_external_context")(
1236
- "name"_a = name,
1237
- "idempotency_seed"_a = py_idempotency_seed,
1238
- "bearer_token"_a = py_bearer_token,
1239
- "app_internal"_a = app_internal));
1161
+ return new py::object(py_reboot->attr("create_external_context")(
1162
+ "name"_a = name,
1163
+ "idempotency_seed"_a = py_idempotency_seed,
1164
+ "bearer_token"_a = py_bearer_token,
1165
+ "app_internal"_a = app_internal));
1240
1166
  });
1241
1167
 
1242
1168
  Napi::External<py::object> js_external_context = make_napi_external(
@@ -1244,17 +1170,14 @@ Napi::Value Reboot_createExternalContext(const Napi::CallbackInfo& info) {
1244
1170
  py_context,
1245
1171
  &reboot_aio_external_ExternalContext);
1246
1172
 
1247
- return js_from_native_external
1248
- .Call(
1249
- info.Env().Global(),
1250
- {js_external_context});
1173
+ return js_from_native_external.Call(
1174
+ info.Env().Global(),
1175
+ {js_external_context});
1251
1176
  }
1252
1177
 
1253
1178
 
1254
1179
  // NOTE: must be called within _Node_.
1255
- Napi::Promise make_js_cancelled(
1256
- Napi::Env& env,
1257
- py::object* py_cancelled) {
1180
+ Napi::Promise make_js_cancelled(Napi::Env& env, py::object* py_cancelled) {
1258
1181
  return NodePromiseFromPythonFuture(
1259
1182
  "make_js_cancelled",
1260
1183
  env,
@@ -1303,8 +1226,7 @@ py::object make_py_authorizer(NapiSafeObjectReference js_authorizer) {
1303
1226
  py::object py_cancelled,
1304
1227
  std::string bytes_call) {
1305
1228
  NapiSafeObjectReference* js_authorizer_reference =
1306
- self.attr("_js_authorizer")
1307
- .cast<NapiSafeObjectReference*>();
1229
+ self.attr("_js_authorizer").cast<NapiSafeObjectReference*>();
1308
1230
 
1309
1231
  return PythonFutureFromNodePromise(
1310
1232
  [js_authorizer_reference,
@@ -1346,12 +1268,11 @@ py::object make_py_authorizer(NapiSafeObjectReference js_authorizer) {
1346
1268
  py::is_method(py::none()));
1347
1269
 
1348
1270
  // Now define our subclass.
1349
- py::object py_parent_class =
1350
- py::module::import("rebootdev.nodejs.python")
1351
- .attr("NodeAdaptorAuthorizer");
1271
+ py::object py_parent_class = py::module::import("rebootdev.nodejs.python")
1272
+ .attr("NodeAdaptorAuthorizer");
1352
1273
 
1353
- py::object py_parent_metaclass = py::reinterpret_borrow<py::object>(
1354
- (PyObject*) &PyType_Type);
1274
+ py::object py_parent_metaclass =
1275
+ py::reinterpret_borrow<py::object>((PyObject*) &PyType_Type);
1355
1276
 
1356
1277
  py::object py_class = py_parent_metaclass(
1357
1278
  "_NodeAdaptorAuthorizer",
@@ -1389,20 +1310,14 @@ std::vector<std::shared_ptr<ServicerDetails>> make_servicer_details(
1389
1310
  Napi::Function js_servicer_constructor = value.As<Napi::Function>();
1390
1311
 
1391
1312
  std::string name =
1392
- js_servicer_constructor
1393
- .Get("name")
1394
- .As<Napi::String>()
1395
- .Utf8Value();
1313
+ js_servicer_constructor.Get("name").As<Napi::String>().Utf8Value();
1396
1314
 
1397
- std::string rbt_module =
1398
- js_servicer_constructor
1399
- .Get("__rbtModule__")
1400
- .As<Napi::String>()
1401
- .Utf8Value();
1315
+ std::string rbt_module = js_servicer_constructor.Get("__rbtModule__")
1316
+ .As<Napi::String>()
1317
+ .Utf8Value();
1402
1318
 
1403
1319
  std::string servicer_node_adaptor =
1404
- js_servicer_constructor
1405
- .Get("__servicerNodeAdaptor__")
1320
+ js_servicer_constructor.Get("__servicerNodeAdaptor__")
1406
1321
  .As<Napi::String>()
1407
1322
  .Utf8Value();
1408
1323
 
@@ -1418,23 +1333,17 @@ std::vector<std::shared_ptr<ServicerDetails>> make_servicer_details(
1418
1333
  Napi::Persistent(js_servicer_constructor))}));
1419
1334
  } else if (
1420
1335
  value.IsObject()
1421
- && !value
1422
- .As<Napi::Object>()
1336
+ && !value.As<Napi::Object>()
1423
1337
  .Get("nativeServicerModule")
1424
1338
  .IsUndefined()) {
1425
- std::string module =
1426
- value
1427
- .As<Napi::Object>()
1428
- .Get("nativeServicerModule")
1429
- .As<Napi::String>()
1430
- .Utf8Value();
1339
+ std::string module = value.As<Napi::Object>()
1340
+ .Get("nativeServicerModule")
1341
+ .As<Napi::String>()
1342
+ .Utf8Value();
1431
1343
  servicer_details.push_back(
1432
- std::make_shared<ServicerDetails>(NativeServicerDetails{
1433
- module}));
1344
+ std::make_shared<ServicerDetails>(NativeServicerDetails{module}));
1434
1345
  } else {
1435
- Napi::Error::New(
1436
- env,
1437
- "Unexpected `servicer` type.")
1346
+ Napi::Error::New(env, "Unexpected `servicer` type.")
1438
1347
  .ThrowAsJavaScriptException();
1439
1348
  }
1440
1349
  }
@@ -1484,8 +1393,7 @@ py::object make_py_user_servicer(
1484
1393
  Napi::External<py::object> js_external_self =
1485
1394
  make_napi_external(env, py_self);
1486
1395
 
1487
- js_servicer
1488
- .Get("__storeExternal")
1396
+ js_servicer.Get("__storeExternal")
1489
1397
  .As<Napi::Function>()
1490
1398
  .Call(js_servicer, {js_external_self});
1491
1399
 
@@ -1505,11 +1413,11 @@ py::object make_py_user_servicer(
1505
1413
 
1506
1414
  // Trampolines us from Python through C++ into Node for Servicer method
1507
1415
  // calls.
1508
- attributes["_trampoline"] = py::cpp_function(
1509
- [](NapiSafeObjectReference& js_servicer_reference,
1510
- py::object py_context,
1511
- py::object py_cancelled,
1512
- std::string bytes_call) {
1416
+ attributes["_trampoline"] =
1417
+ py::cpp_function([](NapiSafeObjectReference& js_servicer_reference,
1418
+ py::object py_context,
1419
+ py::object py_cancelled,
1420
+ std::string bytes_call) {
1513
1421
  return PythonFutureFromNodePromise(
1514
1422
  [&js_servicer_reference,
1515
1423
  py_context = new py::object(py_context),
@@ -1528,11 +1436,9 @@ py::object make_py_user_servicer(
1528
1436
 
1529
1437
  js_args.push_back(str_to_uint8array(env, bytes_call));
1530
1438
 
1531
- Napi::Object js_servicer =
1532
- js_servicer_reference.Value(env);
1439
+ Napi::Object js_servicer = js_servicer_reference.Value(env);
1533
1440
 
1534
- return js_servicer
1535
- .Get("__dispatch")
1441
+ return js_servicer.Get("__dispatch")
1536
1442
  .As<Napi::Function>()
1537
1443
  .Call(js_servicer, js_args)
1538
1444
  .As<Napi::Object>();
@@ -1551,13 +1457,12 @@ py::object make_py_user_servicer(
1551
1457
  std::optional<NapiSafeObjectReference> js_authorizer;
1552
1458
  try {
1553
1459
  js_authorizer = RunCallbackOnNodeEventLoop(
1554
- [&js_servicer_reference](Napi::Env env)
1555
- -> std::optional<NapiSafeObjectReference> {
1460
+ [&js_servicer_reference](
1461
+ Napi::Env env) -> std::optional<NapiSafeObjectReference> {
1556
1462
  Napi::Object js_servicer = js_servicer_reference.Value(env);
1557
- Napi::Value js_authorizer =
1558
- js_servicer.Get("_authorizer")
1559
- .As<Napi::Function>()
1560
- .Call(js_servicer, {});
1463
+ Napi::Value js_authorizer = js_servicer.Get("_authorizer")
1464
+ .As<Napi::Function>()
1465
+ .Call(js_servicer, {});
1561
1466
  if (!js_authorizer.IsNull()) {
1562
1467
  return NapiSafeObjectReference(
1563
1468
  js_authorizer.As<Napi::Object>());
@@ -1587,8 +1492,8 @@ py::object make_py_user_servicer(
1587
1492
  py::module::import(details.rbt_module.c_str())
1588
1493
  .attr(details.servicer_node_adaptor.c_str());
1589
1494
 
1590
- py::object py_metaclass = py::reinterpret_borrow<py::object>(
1591
- (PyObject*) &PyType_Type);
1495
+ py::object py_metaclass =
1496
+ py::reinterpret_borrow<py::object>((PyObject*) &PyType_Type);
1592
1497
 
1593
1498
  // Our subclass will be in the `reboot_native` module with
1594
1499
  // the same name as what is used in JS/TS, e.g.,
@@ -1606,8 +1511,7 @@ py::object make_py_user_servicer(
1606
1511
 
1607
1512
  // NOTE: must be called from within _Python_.
1608
1513
  py::list make_py_servicers(
1609
- const std::vector<
1610
- std::shared_ptr<ServicerDetails>>& servicer_details) {
1514
+ const std::vector<std::shared_ptr<ServicerDetails>>& servicer_details) {
1611
1515
  py::module_ module = py::module::import("reboot_native");
1612
1516
 
1613
1517
  py::list py_servicers;
@@ -1619,8 +1523,7 @@ py::list make_py_servicers(
1619
1523
  auto native_details =
1620
1524
  std::get_if<NativeServicerDetails>(details.get())) {
1621
1525
  py_servicers.attr("extend")(
1622
- py::module::import(
1623
- native_details->py_servicers_module.c_str())
1526
+ py::module::import(native_details->py_servicers_module.c_str())
1624
1527
  .attr("servicers")());
1625
1528
  }
1626
1529
  // TODO: Can I get exhaustiveness checking for the std::variant?
@@ -1659,8 +1562,7 @@ py::object make_py_token_verifier(NapiSafeObjectReference js_token_verifier) {
1659
1562
  py::object py_cancelled,
1660
1563
  std::string bytes_call) {
1661
1564
  NapiSafeObjectReference* js_token_verifier_reference =
1662
- self.attr("_js_token_verifier")
1663
- .cast<NapiSafeObjectReference*>();
1565
+ self.attr("_js_token_verifier").cast<NapiSafeObjectReference*>();
1664
1566
 
1665
1567
  return PythonFutureFromNodePromise(
1666
1568
  [js_token_verifier_reference,
@@ -1687,8 +1589,7 @@ py::object make_py_token_verifier(NapiSafeObjectReference js_token_verifier) {
1687
1589
  Napi::Object js_token_verifier =
1688
1590
  js_token_verifier_reference->Value(env);
1689
1591
 
1690
- return js_token_verifier
1691
- .Get("_verifyToken")
1592
+ return js_token_verifier.Get("_verifyToken")
1692
1593
  .As<Napi::Function>()
1693
1594
  .Call(js_token_verifier, {js_args})
1694
1595
  .As<Napi::Object>();
@@ -1714,12 +1615,11 @@ py::object make_py_token_verifier(NapiSafeObjectReference js_token_verifier) {
1714
1615
  py::arg("bytes_call"),
1715
1616
  py::is_method(py::none()));
1716
1617
 
1717
- py::object py_parent_class =
1718
- py::module::import("rebootdev.nodejs.python")
1719
- .attr("NodeAdaptorTokenVerifier");
1618
+ py::object py_parent_class = py::module::import("rebootdev.nodejs.python")
1619
+ .attr("NodeAdaptorTokenVerifier");
1720
1620
 
1721
- py::object py_parent_metaclass = py::reinterpret_borrow<py::object>(
1722
- (PyObject*) &PyType_Type);
1621
+ py::object py_parent_metaclass =
1622
+ py::reinterpret_borrow<py::object>((PyObject*) &PyType_Type);
1723
1623
 
1724
1624
  py::object py_token_verifier = py_parent_metaclass(
1725
1625
  "_NodeAdaptorTokenVerifier",
@@ -1734,15 +1634,15 @@ Napi::Value Reboot_up(const Napi::CallbackInfo& info) {
1734
1634
  // NOTE: we immediately get a safe reference to the `Napi::External`
1735
1635
  // so that Node will not garbage collect it and the `py::object*` we
1736
1636
  // get out of it will remain valid.
1737
- auto js_external_reboot = NapiSafeReference(
1738
- info[0].As<Napi::External<py::object>>());
1637
+ auto js_external_reboot =
1638
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
1739
1639
 
1740
1640
  // CHECK(js_external_reboot.CheckTypeTag(&reboot_aio_tests_Reboot));
1741
1641
 
1742
1642
  py::object* py_reboot = js_external_reboot.Value(info.Env()).Data();
1743
1643
 
1744
- auto js_external_application = NapiSafeReference(
1745
- info[1].As<Napi::External<py::object>>());
1644
+ auto js_external_application =
1645
+ NapiSafeReference(info[1].As<Napi::External<py::object>>());
1746
1646
 
1747
1647
  py::object* py_application = js_external_application.Value(info.Env()).Data();
1748
1648
 
@@ -1760,9 +1660,9 @@ Napi::Value Reboot_up(const Napi::CallbackInfo& info) {
1760
1660
  info.Env(),
1761
1661
  "Reboot.up(...) in nodejs",
1762
1662
  {"asyncio", "create_task"},
1763
- [js_external_reboot, // Ensures `py_reboot` remains valid.
1663
+ [js_external_reboot, // Ensures `py_reboot` remains valid.
1764
1664
  py_reboot,
1765
- js_external_application, // Ensures `py_application` remains valid.
1665
+ js_external_application, // Ensures `py_application` remains valid.
1766
1666
  py_application,
1767
1667
  local_envoy,
1768
1668
  local_envoy_port]() {
@@ -1790,8 +1690,8 @@ Napi::Value Reboot_up(const Napi::CallbackInfo& info) {
1790
1690
  }
1791
1691
 
1792
1692
  Napi::Value Reboot_down(const Napi::CallbackInfo& info) {
1793
- auto js_external_reboot = NapiSafeReference(
1794
- info[0].As<Napi::External<py::object>>());
1693
+ auto js_external_reboot =
1694
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
1795
1695
 
1796
1696
  // CHECK(js_external_reboot.CheckTypeTag(&reboot_aio_tests_Reboot));
1797
1697
 
@@ -1801,18 +1701,16 @@ Napi::Value Reboot_down(const Napi::CallbackInfo& info) {
1801
1701
  info.Env(),
1802
1702
  "Reboot.down() in nodejs",
1803
1703
  {"asyncio", "create_task"},
1804
- [js_external_reboot, // Ensures `py_reboot` remains valid.
1805
- py_reboot]() {
1806
- return py_reboot->attr("down")();
1807
- });
1704
+ [js_external_reboot, // Ensures `py_reboot` remains valid.
1705
+ py_reboot]() { return py_reboot->attr("down")(); });
1808
1706
  }
1809
1707
 
1810
1708
  Napi::Value Reboot_start(const Napi::CallbackInfo& info) {
1811
1709
  // NOTE: we immediately get a safe reference to the `Napi::External`
1812
1710
  // so that Node will not garbage collect it and the `py::object*` we
1813
1711
  // get out of it will remain valid.
1814
- auto js_external_reboot = NapiSafeReference(
1815
- info[0].As<Napi::External<py::object>>());
1712
+ auto js_external_reboot =
1713
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
1816
1714
 
1817
1715
  // CHECK(js_external_reboot.CheckTypeTag(&reboot_aio_tests_Reboot));
1818
1716
 
@@ -1826,18 +1724,16 @@ Napi::Value Reboot_start(const Napi::CallbackInfo& info) {
1826
1724
  info.Env(),
1827
1725
  "Reboot.start() in nodejs",
1828
1726
  {"asyncio", "create_task"},
1829
- [js_external_reboot, // Ensures `py_reboot` remains valid.
1830
- py_reboot]() {
1831
- return py_reboot->attr("start")();
1832
- });
1727
+ [js_external_reboot, // Ensures `py_reboot` remains valid.
1728
+ py_reboot]() { return py_reboot->attr("start")(); });
1833
1729
  }
1834
1730
 
1835
1731
  Napi::Value Reboot_stop(const Napi::CallbackInfo& info) {
1836
1732
  // NOTE: we immediately get a safe reference to the `Napi::External`
1837
1733
  // so that Node will not garbage collect it and the `py::object*` we
1838
1734
  // get out of it will remain valid.
1839
- auto js_external_reboot = NapiSafeReference(
1840
- info[0].As<Napi::External<py::object>>());
1735
+ auto js_external_reboot =
1736
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
1841
1737
 
1842
1738
  // CHECK(js_external_reboot.CheckTypeTag(&reboot_aio_tests_Reboot));
1843
1739
 
@@ -1847,22 +1743,18 @@ Napi::Value Reboot_stop(const Napi::CallbackInfo& info) {
1847
1743
  info.Env(),
1848
1744
  "Reboot.stop() in nodejs",
1849
1745
  {"asyncio", "create_task"},
1850
- [js_external_reboot, // Ensures `py_reboot` remains valid.
1851
- py_reboot]() {
1852
- return py_reboot->attr("stop")();
1853
- });
1746
+ [js_external_reboot, // Ensures `py_reboot` remains valid.
1747
+ py_reboot]() { return py_reboot->attr("stop")(); });
1854
1748
 
1855
1749
  // Allow Node to exit after we've resolved or rejected the promise.
1856
- auto js_resolve_reject = Napi::Function::New(
1857
- info.Env(),
1858
- [](const Napi::CallbackInfo& info) {
1750
+ auto js_resolve_reject =
1751
+ Napi::Function::New(info.Env(), [](const Napi::CallbackInfo& info) {
1859
1752
  adaptor->AllowNodeToExit(info.Env());
1860
1753
  });
1861
1754
 
1862
- js_promise
1863
- .Get("then")
1864
- .As<Napi::Function>()
1865
- .Call(js_promise, {js_resolve_reject, js_resolve_reject});
1755
+ js_promise.Get("then").As<Napi::Function>().Call(
1756
+ js_promise,
1757
+ {js_resolve_reject, js_resolve_reject});
1866
1758
 
1867
1759
  return js_promise;
1868
1760
  }
@@ -1873,18 +1765,17 @@ Napi::Value Reboot_url(const Napi::CallbackInfo& info) {
1873
1765
  // NOTE: we immediately get a safe reference to the `Napi::External`
1874
1766
  // so that Node will not garbage collect it and the `py::object*` we
1875
1767
  // get out of it will remain valid.
1876
- auto js_external_reboot = NapiSafeReference(
1877
- info[0].As<Napi::External<py::object>>());
1768
+ auto js_external_reboot =
1769
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
1878
1770
 
1879
1771
  // CHECK(...CheckTypeTag(...));
1880
1772
 
1881
1773
  py::object* py_reboot = js_external_reboot.Value(info.Env()).Data();
1882
1774
 
1883
- std::string url = RunCallbackOnPythonEventLoop(
1884
- [py_reboot]() {
1885
- py::str url = py_reboot->attr("url")();
1886
- return std::string(url);
1887
- });
1775
+ std::string url = RunCallbackOnPythonEventLoop([py_reboot]() {
1776
+ py::str url = py_reboot->attr("url")();
1777
+ return std::string(url);
1778
+ });
1888
1779
 
1889
1780
  return Napi::String::New(info.Env(), url);
1890
1781
  }
@@ -1900,13 +1791,11 @@ Napi::Value Service_constructor(const Napi::CallbackInfo& info) {
1900
1791
 
1901
1792
  std::string id = js_args.Get("id").As<Napi::String>().Utf8Value();
1902
1793
 
1903
- py::object* py_service = RunCallbackOnPythonEventLoop(
1904
- [&rbt_module, &node_adaptor, &id]() {
1794
+ py::object* py_service =
1795
+ RunCallbackOnPythonEventLoop([&rbt_module, &node_adaptor, &id]() {
1905
1796
  py::object py_module = py::module::import(rbt_module.c_str());
1906
1797
  py::object py_schedule_type =
1907
- py_module
1908
- .attr(node_adaptor.c_str())
1909
- .attr("_Schedule");
1798
+ py_module.attr(node_adaptor.c_str()).attr("_Schedule");
1910
1799
  return new py::object(py_module.attr(node_adaptor.c_str())(
1911
1800
  // The call will stay within the same application.
1912
1801
  "application_id"_a = py::none(),
@@ -1950,8 +1839,7 @@ Napi::Value Service_call(const Napi::CallbackInfo& info) {
1950
1839
 
1951
1840
  // CHECK(...CheckTypeTag(...));
1952
1841
 
1953
- py::object* py_context =
1954
- js_external_context.Value(info.Env()).Data();
1842
+ py::object* py_context = js_external_context.Value(info.Env()).Data();
1955
1843
 
1956
1844
  std::string json_request = js_args.Get("jsonRequest").As<Napi::String>();
1957
1845
 
@@ -1961,13 +1849,13 @@ Napi::Value Service_call(const Napi::CallbackInfo& info) {
1961
1849
  info.Env(),
1962
1850
  "servicer._" + kind + "(\"" + method + "\", ...) in nodejs",
1963
1851
  js_external_context,
1964
- [js_external_service, // Ensures `py_service` remains valid.
1852
+ [js_external_service, // Ensures `py_service` remains valid.
1965
1853
  py_service,
1966
1854
  kind,
1967
1855
  method,
1968
1856
  request_module,
1969
1857
  request_type,
1970
- js_external_context, // Ensures `py_context` remains valid.
1858
+ js_external_context, // Ensures `py_context` remains valid.
1971
1859
  py_context,
1972
1860
  json_request,
1973
1861
  json_options]() {
@@ -1994,9 +1882,7 @@ Napi::Value Service_call(const Napi::CallbackInfo& info) {
1994
1882
  json_request,
1995
1883
  json_options);
1996
1884
  },
1997
- [](py::object py_json) {
1998
- return py_json.cast<std::string>();
1999
- },
1885
+ [](py::object py_json) { return py_json.cast<std::string>(); },
2000
1886
  [](Napi::Env env, std::string&& json) {
2001
1887
  return Napi::String::New(env, json);
2002
1888
  });
@@ -2014,8 +1900,7 @@ Napi::Value Task_await(const Napi::CallbackInfo& info) {
2014
1900
 
2015
1901
  // CHECK(...CheckTypeTag(...));
2016
1902
 
2017
- py::object* py_context =
2018
- js_external_context.Value(info.Env()).Data();
1903
+ py::object* py_context = js_external_context.Value(info.Env()).Data();
2019
1904
 
2020
1905
  std::string rbt_module = js_args.Get("rbtModule").As<Napi::String>();
2021
1906
 
@@ -2027,27 +1912,23 @@ Napi::Value Task_await(const Napi::CallbackInfo& info) {
2027
1912
 
2028
1913
  return NodePromiseFromPythonTaskWithContext(
2029
1914
  info.Env(),
2030
- "rebootdev.nodejs.python.task_await(\""
2031
- + state_name + "\", \""
2032
- + method + "\", ...) in nodejs",
1915
+ "rebootdev.nodejs.python.task_await(\"" + state_name + "\", \"" + method
1916
+ + "\", ...) in nodejs",
2033
1917
  js_external_context,
2034
1918
  [rbt_module = std::move(rbt_module),
2035
1919
  state_name = std::move(state_name),
2036
1920
  method = std::move(method),
2037
- js_external_context, // Ensures `py_context` remains valid.
1921
+ js_external_context, // Ensures `py_context` remains valid.
2038
1922
  py_context,
2039
1923
  json_task_id]() {
2040
1924
  return py::module::import("rebootdev.nodejs.python")
2041
1925
  .attr("task_await")(
2042
1926
  py_context,
2043
- py::module::import(rbt_module.c_str())
2044
- .attr(state_name.c_str()),
1927
+ py::module::import(rbt_module.c_str()).attr(state_name.c_str()),
2045
1928
  method,
2046
1929
  json_task_id);
2047
1930
  },
2048
- [](py::object py_json) {
2049
- return py_json.cast<std::string>();
2050
- },
1931
+ [](py::object py_json) { return py_json.cast<std::string>(); },
2051
1932
  [](Napi::Env env, std::string&& json) {
2052
1933
  return Napi::String::New(env, json);
2053
1934
  });
@@ -2078,21 +1959,17 @@ Napi::Value ExternalContext_constructor(const Napi::CallbackInfo& info) {
2078
1959
 
2079
1960
  std::optional<std::string> idempotency_required_reason;
2080
1961
  if (!info[6].IsUndefined()) {
2081
- idempotency_required_reason =
2082
- info[6]
2083
- .As<Napi::String>()
2084
- .Utf8Value();
1962
+ idempotency_required_reason = info[6].As<Napi::String>().Utf8Value();
2085
1963
  }
2086
1964
 
2087
- py::object* py_external_context = RunCallbackOnPythonEventLoop(
2088
- [&name,
2089
- &url,
2090
- &bearer_token,
2091
- &idempotency_seed,
2092
- &idempotency_required,
2093
- &idempotency_required_reason]() {
2094
- py::object py_external = py::module::import(
2095
- "rebootdev.aio.external");
1965
+ py::object* py_external_context =
1966
+ RunCallbackOnPythonEventLoop([&name,
1967
+ &url,
1968
+ &bearer_token,
1969
+ &idempotency_seed,
1970
+ &idempotency_required,
1971
+ &idempotency_required_reason]() {
1972
+ py::object py_external = py::module::import("rebootdev.aio.external");
2096
1973
 
2097
1974
  auto convert_str =
2098
1975
  [](const std::optional<std::string>& optional) -> py::object {
@@ -2109,8 +1986,8 @@ Napi::Value ExternalContext_constructor(const Napi::CallbackInfo& info) {
2109
1986
  "bearer_token"_a = convert_str(bearer_token),
2110
1987
  "idempotency_seed"_a = convert_str(idempotency_seed),
2111
1988
  "idempotency_required"_a = py::bool_(idempotency_required),
2112
- "idempotency_required_reason"_a = convert_str(
2113
- idempotency_required_reason)));
1989
+ "idempotency_required_reason"_a =
1990
+ convert_str(idempotency_required_reason)));
2114
1991
  });
2115
1992
 
2116
1993
  Napi::External<py::object> js_external_context = make_napi_external(
@@ -2122,8 +1999,8 @@ Napi::Value ExternalContext_constructor(const Napi::CallbackInfo& info) {
2122
1999
  }
2123
2000
 
2124
2001
  Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2125
- auto js_from_native_external = NapiSafeFunctionReference(
2126
- info[0].As<Napi::Function>());
2002
+ auto js_from_native_external =
2003
+ NapiSafeFunctionReference(info[0].As<Napi::Function>());
2127
2004
 
2128
2005
  Napi::Array js_servicers = info[1].As<Napi::Array>();
2129
2006
 
@@ -2137,8 +2014,7 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2137
2014
 
2138
2015
  auto servicer_details = make_servicer_details(info.Env(), js_servicers);
2139
2016
 
2140
- auto js_initialize = NapiSafeFunctionReference(
2141
- info[3].As<Napi::Function>());
2017
+ auto js_initialize = NapiSafeFunctionReference(info[3].As<Napi::Function>());
2142
2018
 
2143
2019
  std::optional<std::string> initialize_bearer_token;
2144
2020
  if (!info[4].IsUndefined()) {
@@ -2184,31 +2060,27 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2184
2060
  Napi::Function js_create_external_context =
2185
2061
  Napi::Function::New(
2186
2062
  env,
2187
- [js_from_native_external = std::move(
2188
- js_from_native_external),
2063
+ [js_from_native_external =
2064
+ std::move(js_from_native_external),
2189
2065
  // Ensures `py_channel_manager` remains valid.
2190
2066
  js_external_channel_manager = NapiSafeReference(
2191
2067
  js_external_channel_manager)](
2192
2068
  const Napi::CallbackInfo& info) mutable {
2193
2069
  Napi::Object js_args = info[0].As<Napi::Object>();
2194
2070
 
2195
- std::string name =
2196
- js_args
2197
- .Get("name")
2198
- .As<Napi::String>()
2199
- .Utf8Value();
2071
+ std::string name = js_args.Get("name")
2072
+ .As<Napi::String>()
2073
+ .Utf8Value();
2200
2074
 
2201
2075
  std::optional<std::string> bearer_token;
2202
2076
  if (!js_args.Get("bearerToken").IsUndefined()) {
2203
- bearer_token =
2204
- js_args.Get("bearerToken")
2205
- .As<Napi::String>()
2206
- .Utf8Value();
2077
+ bearer_token = js_args.Get("bearerToken")
2078
+ .As<Napi::String>()
2079
+ .Utf8Value();
2207
2080
  }
2208
2081
 
2209
2082
  py::object* py_channel_manager =
2210
- js_external_channel_manager
2211
- .Value(info.Env())
2083
+ js_external_channel_manager.Value(info.Env())
2212
2084
  .Data();
2213
2085
 
2214
2086
  return NodePromiseFromPythonCallback(
@@ -2246,32 +2118,30 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2246
2118
  js_from_native_external](
2247
2119
  Napi::Env env,
2248
2120
  py::object* py_context) {
2249
- // (check_line_length skip)
2250
- Napi::External<py::object> js_external_context =
2251
- make_napi_external(
2121
+ Napi::External<py::object>
2122
+ // (check_line_length skip)
2123
+ js_external_context = make_napi_external(
2252
2124
  env,
2253
2125
  py_context,
2254
2126
  // (check_line_length skip)
2255
2127
  &reboot_aio_external_ExternalContext);
2256
2128
 
2257
- return js_from_native_external
2258
- .Value(env)
2129
+ return js_from_native_external.Value(env)
2259
2130
  .Call(
2260
2131
  env.Global(),
2261
2132
  {js_external_context,
2262
- // (check_line_length skip)
2263
- Napi::String::New(env, "external")});
2133
+ Napi::String::New(
2134
+ env,
2135
+ "external")});
2264
2136
  });
2265
2137
  });
2266
2138
 
2267
- return js_web_framework_start
2268
- .Value(env)
2139
+ return js_web_framework_start.Value(env)
2269
2140
  .Call(
2270
2141
  env.Global(),
2271
2142
  {Napi::String::New(env, server_id),
2272
- port.has_value()
2273
- ? Napi::Number::New(env, *port)
2274
- : env.Null(),
2143
+ port.has_value() ? Napi::Number::New(env, *port)
2144
+ : env.Null(),
2275
2145
  js_create_external_context})
2276
2146
  .As<Napi::Object>();
2277
2147
  },
@@ -2282,17 +2152,13 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2282
2152
  });
2283
2153
 
2284
2154
  py::object py_web_framework_stop = py::cpp_function(
2285
- [js_web_framework_stop = std::move(js_web_framework_stop)](
2286
- std::string server_id) {
2155
+ [js_web_framework_stop =
2156
+ std::move(js_web_framework_stop)](std::string server_id) {
2287
2157
  return PythonFutureFromNodePromise(
2288
2158
  [js_web_framework_stop = std::move(js_web_framework_stop),
2289
- server_id = std::move(server_id)](
2290
- Napi::Env env) mutable {
2291
- return js_web_framework_stop
2292
- .Value(env)
2293
- .Call(
2294
- env.Global(),
2295
- {Napi::String::New(env, server_id)})
2159
+ server_id = std::move(server_id)](Napi::Env env) mutable {
2160
+ return js_web_framework_stop.Value(env)
2161
+ .Call(env.Global(), {Napi::String::New(env, server_id)})
2296
2162
  .As<Napi::Object>();
2297
2163
  });
2298
2164
  });
@@ -2303,15 +2169,15 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2303
2169
  py::object py_context) mutable {
2304
2170
  return PythonFutureFromNodePromise(
2305
2171
  [js_initialize,
2306
- js_from_native_external, // NOTE: need a _copy_ of
2307
- // both `js_initialize`
2308
- // and
2309
- // `js_from_native_external`
2310
- // here since
2311
- // `py_initialize` may be
2312
- // called more than once!
2313
- py_context = new py::object(py_context)](
2314
- Napi::Env env) mutable {
2172
+ js_from_native_external, // NOTE: need a _copy_ of
2173
+ // both `js_initialize`
2174
+ // and
2175
+ // `js_from_native_external`
2176
+ // here since
2177
+ // `py_initialize` may be
2178
+ // called more than once!
2179
+ py_context =
2180
+ new py::object(py_context)](Napi::Env env) mutable {
2315
2181
  Napi::External<py::object> js_external_context =
2316
2182
  make_napi_external(
2317
2183
  env,
@@ -2319,16 +2185,14 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2319
2185
  &reboot_aio_external_ExternalContext);
2320
2186
 
2321
2187
  Napi::Object js_context =
2322
- js_from_native_external
2323
- .Value(env)
2188
+ js_from_native_external.Value(env)
2324
2189
  .Call(
2325
2190
  env.Global(),
2326
2191
  {js_external_context,
2327
2192
  Napi::String::New(env, "initialize")})
2328
2193
  .As<Napi::Object>();
2329
2194
 
2330
- return js_initialize
2331
- .Value(env)
2195
+ return js_initialize.Value(env)
2332
2196
  .Call(env.Global(), {js_context})
2333
2197
  .As<Napi::Object>();
2334
2198
  });
@@ -2351,8 +2215,7 @@ Napi::Value Application_constructor(const Napi::CallbackInfo& info) {
2351
2215
  "web_framework_start"_a = py_web_framework_start,
2352
2216
  "web_framework_stop"_a = py_web_framework_stop,
2353
2217
  "initialize"_a = py_initialize,
2354
- "initialize_bearer_token"_a =
2355
- py_initialize_bearer_token,
2218
+ "initialize_bearer_token"_a = py_initialize_bearer_token,
2356
2219
  "token_verifier"_a = py_token_verifier));
2357
2220
  });
2358
2221
 
@@ -2370,47 +2233,37 @@ Napi::Value Application_run(const Napi::CallbackInfo& info) {
2370
2233
  // that we can get calls from Python.
2371
2234
  adaptor->KeepNodeFromExiting(info.Env());
2372
2235
 
2373
- auto js_external_application = NapiSafeReference(
2374
- info[0].As<Napi::External<py::object>>());
2236
+ auto js_external_application =
2237
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2375
2238
 
2376
- py::object* py_application =
2377
- js_external_application.Value(info.Env()).Data();
2239
+ py::object* py_application = js_external_application.Value(info.Env()).Data();
2378
2240
 
2379
2241
  Napi::Promise js_promise = NodePromiseFromPythonTask(
2380
2242
  info.Env(),
2381
2243
  "Application.run() in nodejs",
2382
2244
  {"rebootdev.nodejs.python", "create_task"},
2383
- [js_external_application, // Ensures `py_application` remains valid.
2384
- py_application]() {
2385
- return py_application->attr("run")();
2386
- });
2245
+ [js_external_application, // Ensures `py_application` remains valid.
2246
+ py_application]() { return py_application->attr("run")(); });
2387
2247
 
2388
2248
  // More to do if `Application.run` returns ...
2389
- js_promise
2390
- .Get("then")
2391
- .As<Napi::Function>()
2392
- .Call(
2393
- js_promise,
2394
- {Napi::Function::New(
2395
- info.Env(),
2396
- [](const Napi::CallbackInfo& info) {
2397
- // Allow Node to exit after `Application.run` returns.
2398
- adaptor->AllowNodeToExit(info.Env());
2399
- }),
2400
- Napi::Function::New(
2401
- info.Env(),
2402
- [](const Napi::CallbackInfo& info) {
2403
- // There was an error, let's also set the
2404
- // `process.exitCode` to reflect this.
2405
- info.Env()
2406
- .Global()
2407
- .Get("process")
2408
- .As<Napi::Object>()
2409
- .Set("exitCode", 1);
2410
-
2411
- // Allow Node to exit after `Application.run` returns.
2412
- adaptor->AllowNodeToExit(info.Env());
2413
- })});
2249
+ js_promise.Get("then").As<Napi::Function>().Call(
2250
+ js_promise,
2251
+ {Napi::Function::New(
2252
+ info.Env(),
2253
+ [](const Napi::CallbackInfo& info) {
2254
+ // Allow Node to exit after `Application.run` returns.
2255
+ adaptor->AllowNodeToExit(info.Env());
2256
+ }),
2257
+ Napi::Function::New(info.Env(), [](const Napi::CallbackInfo& info) {
2258
+ // There was an error, let's also set the
2259
+ // `process.exitCode` to reflect this.
2260
+ info.Env().Global().Get("process").As<Napi::Object>().Set(
2261
+ "exitCode",
2262
+ 1);
2263
+
2264
+ // Allow Node to exit after `Application.run` returns.
2265
+ adaptor->AllowNodeToExit(info.Env());
2266
+ })});
2414
2267
 
2415
2268
  return js_promise;
2416
2269
  }
@@ -2420,22 +2273,18 @@ Napi::Value Context_generateIdempotentStateId(const Napi::CallbackInfo& info) {
2420
2273
  // NOTE: we immediately get a safe reference to the `Napi::External`
2421
2274
  // so that Node will not garbage collect it and the `py::object*` we
2422
2275
  // get out of it will remain valid.
2423
- auto js_external_context = NapiSafeReference(
2424
- info[0].As<Napi::External<py::object>>());
2276
+ auto js_external_context =
2277
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2425
2278
 
2426
2279
  py::object* py_context = js_external_context.Value(info.Env()).Data();
2427
2280
 
2428
- std::string state_type =
2429
- info[1].As<Napi::String>().Utf8Value();
2281
+ std::string state_type = info[1].As<Napi::String>().Utf8Value();
2430
2282
 
2431
- std::string service_name =
2432
- info[2].As<Napi::String>().Utf8Value();
2283
+ std::string service_name = info[2].As<Napi::String>().Utf8Value();
2433
2284
 
2434
- std::string method =
2435
- info[3].As<Napi::String>().Utf8Value();
2285
+ std::string method = info[3].As<Napi::String>().Utf8Value();
2436
2286
 
2437
- Napi::Object idempotency_options =
2438
- info[4].As<Napi::Object>();
2287
+ Napi::Object idempotency_options = info[4].As<Napi::Object>();
2439
2288
  auto js_key = idempotency_options.Get("key");
2440
2289
  std::optional<std::string> key;
2441
2290
  if (js_key.IsString()) {
@@ -2454,7 +2303,7 @@ Napi::Value Context_generateIdempotentStateId(const Napi::CallbackInfo& info) {
2454
2303
 
2455
2304
  return NodePromiseFromPythonCallback(
2456
2305
  info.Env(),
2457
- [js_external_context, // Ensures `py_context` remains valid.
2306
+ [js_external_context, // Ensures `py_context` remains valid.
2458
2307
  py_context,
2459
2308
  state_type = std::move(state_type),
2460
2309
  service_name = std::move(service_name),
@@ -2510,25 +2359,23 @@ Napi::Value WriterContext_set_sync(const Napi::CallbackInfo& info) {
2510
2359
  // NOTE: we immediately get a safe reference to the `Napi::External`
2511
2360
  // so that Node will not garbage collect it and the `py::object*` we
2512
2361
  // get out of it will remain valid.
2513
- auto js_external_context = NapiSafeReference(
2514
- info[0].As<Napi::External<py::object>>());
2362
+ auto js_external_context =
2363
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2515
2364
 
2516
2365
  py::object* py_context = js_external_context.Value(info.Env()).Data();
2517
2366
 
2518
2367
  bool sync = info[1].As<Napi::Boolean>();
2519
2368
 
2520
2369
  RunCallbackOnPythonEventLoop(
2521
- [&py_context, sync]() {
2522
- py_context->attr("sync") = sync;
2523
- });
2370
+ [&py_context, sync]() { py_context->attr("sync") = sync; });
2524
2371
 
2525
2372
  return info.Env().Undefined();
2526
2373
  }
2527
2374
 
2528
2375
 
2529
2376
  Napi::Value WorkflowContext_loop(const Napi::CallbackInfo& info) {
2530
- auto js_external_context = NapiSafeReference(
2531
- info[0].As<Napi::External<py::object>>());
2377
+ auto js_external_context =
2378
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2532
2379
 
2533
2380
  // CHECK(...CheckTypeTag(...));
2534
2381
 
@@ -2540,51 +2387,47 @@ Napi::Value WorkflowContext_loop(const Napi::CallbackInfo& info) {
2540
2387
  info.Env(),
2541
2388
  "context.loop(...) in nodejs",
2542
2389
  js_external_context,
2543
- [js_external_context, // Ensures `py_context` remains valid.
2390
+ [js_external_context, // Ensures `py_context` remains valid.
2544
2391
  py_context,
2545
2392
  alias = std::move(alias)]() {
2546
2393
  return py::module::import("rebootdev.nodejs.python")
2547
2394
  .attr("loop")(py_context, alias);
2548
2395
  },
2549
- [](py::object py_iterate) {
2550
- return new py::object(py_iterate);
2551
- },
2396
+ [](py::object py_iterate) { return new py::object(py_iterate); },
2552
2397
  [js_external_context](Napi::Env env, py::object* py_iterate) mutable {
2553
2398
  Napi::External<py::object> js_iterate_external =
2554
2399
  make_napi_external(env, py_iterate);
2555
2400
 
2556
- Napi::Function js_iterate =
2557
- Napi::Function::New(
2558
- env,
2559
- [js_external_context,
2560
- js_iterate_external = // Ensures `py_iterate` remains valid.
2561
- NapiSafeReference(js_iterate_external),
2562
- py_iterate](
2563
- const Napi::CallbackInfo& info) mutable {
2564
- bool more = info[0].As<Napi::Boolean>();
2565
- return NodePromiseFromPythonTaskWithContext(
2566
- info.Env(),
2567
- "iterate(...) in nodejs",
2568
- js_external_context,
2569
- [js_iterate_external, py_iterate, more]() {
2570
- return (*py_iterate)(more);
2571
- },
2572
- [](py::object py_iteration) -> std::optional<int> {
2573
- if (!py_iteration.is_none()) {
2574
- return py_iteration.cast<int>();
2575
- } else {
2576
- return std::nullopt;
2577
- }
2578
- },
2579
- [](Napi::Env env,
2580
- std::optional<int>&& iteration) -> Napi::Value {
2581
- if (iteration.has_value()) {
2582
- return Napi::Number::New(env, *iteration);
2583
- } else {
2584
- return env.Null();
2585
- }
2586
- });
2587
- });
2401
+ Napi::Function js_iterate = Napi::Function::New(
2402
+ env,
2403
+ [js_external_context,
2404
+ js_iterate_external = // Ensures `py_iterate` remains valid.
2405
+ NapiSafeReference(js_iterate_external),
2406
+ py_iterate](const Napi::CallbackInfo& info) mutable {
2407
+ bool more = info[0].As<Napi::Boolean>();
2408
+ return NodePromiseFromPythonTaskWithContext(
2409
+ info.Env(),
2410
+ "iterate(...) in nodejs",
2411
+ js_external_context,
2412
+ [js_iterate_external, py_iterate, more]() {
2413
+ return (*py_iterate)(more);
2414
+ },
2415
+ [](py::object py_iteration) -> std::optional<int> {
2416
+ if (!py_iteration.is_none()) {
2417
+ return py_iteration.cast<int>();
2418
+ } else {
2419
+ return std::nullopt;
2420
+ }
2421
+ },
2422
+ [](Napi::Env env,
2423
+ std::optional<int>&& iteration) -> Napi::Value {
2424
+ if (iteration.has_value()) {
2425
+ return Napi::Number::New(env, *iteration);
2426
+ } else {
2427
+ return env.Null();
2428
+ }
2429
+ });
2430
+ });
2588
2431
 
2589
2432
  return js_iterate;
2590
2433
  });
@@ -2592,21 +2435,20 @@ Napi::Value WorkflowContext_loop(const Napi::CallbackInfo& info) {
2592
2435
 
2593
2436
 
2594
2437
  Napi::Value retry_reactively_until(const Napi::CallbackInfo& info) {
2595
- auto js_external_context = NapiSafeReference(
2596
- info[0].As<Napi::External<py::object>>());
2438
+ auto js_external_context =
2439
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2597
2440
 
2598
2441
  // CHECK(...CheckTypeTag(...));
2599
2442
 
2600
2443
  py::object* py_context = js_external_context.Value(info.Env()).Data();
2601
2444
 
2602
- auto js_condition = NapiSafeFunctionReference(
2603
- info[1].As<Napi::Function>());
2445
+ auto js_condition = NapiSafeFunctionReference(info[1].As<Napi::Function>());
2604
2446
 
2605
2447
  return NodePromiseFromPythonTaskWithContext(
2606
2448
  info.Env(),
2607
2449
  "retry_reactively_until(...) in nodejs",
2608
2450
  js_external_context,
2609
- [js_external_context, // Ensures `py_context` remains valid.
2451
+ [js_external_context, // Ensures `py_context` remains valid.
2610
2452
  py_context,
2611
2453
  js_condition = std::move(js_condition)]() {
2612
2454
  py::object py_condition = py::cpp_function(
@@ -2617,8 +2459,7 @@ Napi::Value retry_reactively_until(const Napi::CallbackInfo& info) {
2617
2459
  // `py_condition` may be called more
2618
2460
  // than once!
2619
2461
  [js_condition](Napi::Env env) mutable {
2620
- return js_condition
2621
- .Value(env)
2462
+ return js_condition.Value(env)
2622
2463
  .Call(env.Global(), {})
2623
2464
  .As<Napi::Object>();
2624
2465
  },
@@ -2634,8 +2475,8 @@ Napi::Value retry_reactively_until(const Napi::CallbackInfo& info) {
2634
2475
 
2635
2476
 
2636
2477
  Napi::Value memoize(const Napi::CallbackInfo& info) {
2637
- auto js_external_context = NapiSafeReference(
2638
- info[0].As<Napi::External<py::object>>());
2478
+ auto js_external_context =
2479
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2639
2480
 
2640
2481
  // CHECK(...CheckTypeTag(...));
2641
2482
 
@@ -2647,8 +2488,7 @@ Napi::Value memoize(const Napi::CallbackInfo& info) {
2647
2488
  auto js_how = idempotency_tuple.Get((uint32_t) 1);
2648
2489
  std::string how = js_how.As<Napi::String>().Utf8Value();
2649
2490
 
2650
- auto js_callable = NapiSafeFunctionReference(
2651
- info[2].As<Napi::Function>());
2491
+ auto js_callable = NapiSafeFunctionReference(info[2].As<Napi::Function>());
2652
2492
 
2653
2493
  bool at_most_once = info[3].As<Napi::Boolean>();
2654
2494
 
@@ -2658,21 +2498,20 @@ Napi::Value memoize(const Napi::CallbackInfo& info) {
2658
2498
  info.Env(),
2659
2499
  "memoize(...) in nodejs",
2660
2500
  js_external_context,
2661
- [js_external_context, // Ensures `py_context` remains valid.
2501
+ [js_external_context, // Ensures `py_context` remains valid.
2662
2502
  py_context,
2663
2503
  alias = std::move(alias),
2664
2504
  how = std::move(how),
2665
2505
  js_callable = std::move(js_callable),
2666
2506
  at_most_once,
2667
2507
  until]() {
2668
- py::object py_callable = py::cpp_function(
2669
- [js_callable = std::move(js_callable)]() mutable {
2508
+ py::object py_callable =
2509
+ py::cpp_function([js_callable = std::move(js_callable)]() mutable {
2670
2510
  return PythonFutureFromNodePromise(
2671
2511
  // NOTE: need a _copy_ of `js_callable` here since
2672
2512
  // `py_callable` may be called more than once!
2673
2513
  [js_callable](Napi::Env env) mutable {
2674
- return js_callable
2675
- .Value(env)
2514
+ return js_callable.Value(env)
2676
2515
  .Call(env.Global(), {})
2677
2516
  .As<Napi::Object>();
2678
2517
  },
@@ -2690,9 +2529,7 @@ Napi::Value memoize(const Napi::CallbackInfo& info) {
2690
2529
  "at_most_once"_a = at_most_once,
2691
2530
  "until"_a = until);
2692
2531
  },
2693
- [](py::object py_json) {
2694
- return py_json.cast<std::string>();
2695
- },
2532
+ [](py::object py_json) { return py_json.cast<std::string>(); },
2696
2533
  [](Napi::Env env, std::string&& json) {
2697
2534
  return Napi::String::New(env, json);
2698
2535
  });
@@ -2700,15 +2537,15 @@ Napi::Value memoize(const Napi::CallbackInfo& info) {
2700
2537
 
2701
2538
 
2702
2539
  Napi::Value Servicer_read(const Napi::CallbackInfo& info) {
2703
- auto js_external_servicer = NapiSafeReference(
2704
- info[0].As<Napi::External<py::object>>());
2540
+ auto js_external_servicer =
2541
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2705
2542
 
2706
2543
  // CHECK(...CheckTypeTag(...));
2707
2544
 
2708
2545
  py::object* py_servicer = js_external_servicer.Value(info.Env()).Data();
2709
2546
 
2710
- auto js_external_context = NapiSafeReference(
2711
- info[1].As<Napi::External<py::object>>());
2547
+ auto js_external_context =
2548
+ NapiSafeReference(info[1].As<Napi::External<py::object>>());
2712
2549
 
2713
2550
  // CHECK(...CheckTypeTag(...));
2714
2551
 
@@ -2720,16 +2557,14 @@ Napi::Value Servicer_read(const Napi::CallbackInfo& info) {
2720
2557
  info.Env(),
2721
2558
  "servicer._read(...) in nodejs",
2722
2559
  js_external_context,
2723
- [js_external_servicer, // Ensures `py_servicer` remains valid.
2560
+ [js_external_servicer, // Ensures `py_servicer` remains valid.
2724
2561
  py_servicer,
2725
- js_external_context, // Ensures `py_context` remains valid.
2562
+ js_external_context, // Ensures `py_context` remains valid.
2726
2563
  py_context,
2727
2564
  json_options = std::move(json_options)]() {
2728
2565
  return py_servicer->attr("_read")(py_context, json_options);
2729
2566
  },
2730
- [](py::object py_json) {
2731
- return py_json.cast<std::string>();
2732
- },
2567
+ [](py::object py_json) { return py_json.cast<std::string>(); },
2733
2568
  [](Napi::Env env, std::string&& json) {
2734
2569
  return Napi::String::New(env, json);
2735
2570
  });
@@ -2737,22 +2572,21 @@ Napi::Value Servicer_read(const Napi::CallbackInfo& info) {
2737
2572
 
2738
2573
 
2739
2574
  Napi::Value Servicer_write(const Napi::CallbackInfo& info) {
2740
- auto js_external_servicer = NapiSafeReference(
2741
- info[0].As<Napi::External<py::object>>());
2575
+ auto js_external_servicer =
2576
+ NapiSafeReference(info[0].As<Napi::External<py::object>>());
2742
2577
 
2743
2578
  // CHECK(...CheckTypeTag(...));
2744
2579
 
2745
2580
  py::object* py_servicer = js_external_servicer.Value(info.Env()).Data();
2746
2581
 
2747
- auto js_external_context = NapiSafeReference(
2748
- info[1].As<Napi::External<py::object>>());
2582
+ auto js_external_context =
2583
+ NapiSafeReference(info[1].As<Napi::External<py::object>>());
2749
2584
 
2750
2585
  // CHECK(...CheckTypeTag(...));
2751
2586
 
2752
2587
  py::object* py_context = js_external_context.Value(info.Env()).Data();
2753
2588
 
2754
- auto js_writer = NapiSafeFunctionReference(
2755
- info[2].As<Napi::Function>());
2589
+ auto js_writer = NapiSafeFunctionReference(info[2].As<Napi::Function>());
2756
2590
 
2757
2591
  std::string json_options = info[3].As<Napi::String>().Utf8Value();
2758
2592
 
@@ -2760,23 +2594,21 @@ Napi::Value Servicer_write(const Napi::CallbackInfo& info) {
2760
2594
  info.Env(),
2761
2595
  "servicer._write(...) in nodejs",
2762
2596
  js_external_context,
2763
- [js_external_servicer, // Ensures `py_servicer` remains valid.
2597
+ [js_external_servicer, // Ensures `py_servicer` remains valid.
2764
2598
  py_servicer,
2765
- js_external_context, // Ensures `py_context` remains valid.
2599
+ js_external_context, // Ensures `py_context` remains valid.
2766
2600
  py_context,
2767
2601
  js_writer = std::move(js_writer),
2768
2602
  json_options = std::move(json_options)]() {
2769
2603
  py::object py_writer = py::cpp_function(
2770
- [js_writer = std::move(js_writer)](
2771
- std::string state_json) mutable {
2604
+ [js_writer = std::move(js_writer)](std::string state_json) mutable {
2772
2605
  return PythonFutureFromNodePromise(
2773
- [js_writer, // NOTE: need a _copy_ of
2774
- // `js_writer` here since
2775
- // `py_writer` may be called more
2776
- // than once!
2606
+ [js_writer, // NOTE: need a _copy_ of
2607
+ // `js_writer` here since
2608
+ // `py_writer` may be called more
2609
+ // than once!
2777
2610
  state_json](Napi::Env env) mutable {
2778
- return js_writer
2779
- .Value(env)
2611
+ return js_writer.Value(env)
2780
2612
  .Call(
2781
2613
  env.Global(),
2782
2614
  {Napi::String::New(env, state_json)})
@@ -2787,14 +2619,9 @@ Napi::Value Servicer_write(const Napi::CallbackInfo& info) {
2787
2619
  });
2788
2620
  });
2789
2621
 
2790
- return py_servicer->attr("_write")(
2791
- py_context,
2792
- py_writer,
2793
- json_options);
2794
- },
2795
- [](py::object py_result) {
2796
- return py_result.cast<std::string>();
2622
+ return py_servicer->attr("_write")(py_context, py_writer, json_options);
2797
2623
  },
2624
+ [](py::object py_result) { return py_result.cast<std::string>(); },
2798
2625
  [](Napi::Env env, std::string&& result) {
2799
2626
  return Napi::String::New(env, result);
2800
2627
  });