11cb0ef41Sopenharmony_ci#include "node.h" 21cb0ef41Sopenharmony_ci#include "env-inl.h" 31cb0ef41Sopenharmony_ci#include "debug_utils-inl.h" 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciusing v8::Context; 61cb0ef41Sopenharmony_ciusing v8::Function; 71cb0ef41Sopenharmony_ciusing v8::Global; 81cb0ef41Sopenharmony_ciusing v8::HandleScope; 91cb0ef41Sopenharmony_ciusing v8::Isolate; 101cb0ef41Sopenharmony_ciusing v8::Local; 111cb0ef41Sopenharmony_ciusing v8::Locker; 121cb0ef41Sopenharmony_ciusing v8::Maybe; 131cb0ef41Sopenharmony_ciusing v8::Nothing; 141cb0ef41Sopenharmony_ciusing v8::SealHandleScope; 151cb0ef41Sopenharmony_ciusing v8::TryCatch; 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cinamespace node { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciMaybe<int> SpinEventLoop(Environment* env) { 201cb0ef41Sopenharmony_ci CHECK_NOT_NULL(env); 211cb0ef41Sopenharmony_ci MultiIsolatePlatform* platform = GetMultiIsolatePlatform(env); 221cb0ef41Sopenharmony_ci CHECK_NOT_NULL(platform); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci Isolate* isolate = env->isolate(); 251cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 261cb0ef41Sopenharmony_ci Context::Scope context_scope(env->context()); 271cb0ef41Sopenharmony_ci SealHandleScope seal(isolate); 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci if (env->is_stopping()) return Nothing<int>(); 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci env->set_trace_sync_io(env->options()->trace_sync_io); 321cb0ef41Sopenharmony_ci { 331cb0ef41Sopenharmony_ci bool more; 341cb0ef41Sopenharmony_ci env->performance_state()->Mark( 351cb0ef41Sopenharmony_ci node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START); 361cb0ef41Sopenharmony_ci do { 371cb0ef41Sopenharmony_ci if (env->is_stopping()) break; 381cb0ef41Sopenharmony_ci uv_run(env->event_loop(), UV_RUN_DEFAULT); 391cb0ef41Sopenharmony_ci if (env->is_stopping()) break; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci platform->DrainTasks(isolate); 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci more = uv_loop_alive(env->event_loop()); 441cb0ef41Sopenharmony_ci if (more && !env->is_stopping()) continue; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci if (EmitProcessBeforeExit(env).IsNothing()) 471cb0ef41Sopenharmony_ci break; 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci { 501cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 511cb0ef41Sopenharmony_ci if (env->RunSnapshotSerializeCallback().IsEmpty()) { 521cb0ef41Sopenharmony_ci break; 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci // Emit `beforeExit` if the loop became alive either after emitting 571cb0ef41Sopenharmony_ci // event, or after running some callbacks. 581cb0ef41Sopenharmony_ci more = uv_loop_alive(env->event_loop()); 591cb0ef41Sopenharmony_ci } while (more == true && !env->is_stopping()); 601cb0ef41Sopenharmony_ci env->performance_state()->Mark( 611cb0ef41Sopenharmony_ci node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT); 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci if (env->is_stopping()) return Nothing<int>(); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci env->set_trace_sync_io(false); 661cb0ef41Sopenharmony_ci // Clear the serialize callback even though the JS-land queue should 671cb0ef41Sopenharmony_ci // be empty this point so that the deserialized instance won't 681cb0ef41Sopenharmony_ci // attempt to call into JS again. 691cb0ef41Sopenharmony_ci env->set_snapshot_serialize_callback(Local<Function>()); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci env->PrintInfoForSnapshotIfDebug(); 721cb0ef41Sopenharmony_ci env->ForEachRealm([](Realm* realm) { realm->VerifyNoStrongBaseObjects(); }); 731cb0ef41Sopenharmony_ci return EmitProcessExit(env); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_cistruct CommonEnvironmentSetup::Impl { 771cb0ef41Sopenharmony_ci MultiIsolatePlatform* platform = nullptr; 781cb0ef41Sopenharmony_ci uv_loop_t loop; 791cb0ef41Sopenharmony_ci std::shared_ptr<ArrayBufferAllocator> allocator; 801cb0ef41Sopenharmony_ci Isolate* isolate = nullptr; 811cb0ef41Sopenharmony_ci DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data; 821cb0ef41Sopenharmony_ci DeleteFnPtr<Environment, FreeEnvironment> env; 831cb0ef41Sopenharmony_ci Global<Context> context; 841cb0ef41Sopenharmony_ci}; 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ciCommonEnvironmentSetup::CommonEnvironmentSetup( 871cb0ef41Sopenharmony_ci MultiIsolatePlatform* platform, 881cb0ef41Sopenharmony_ci std::vector<std::string>* errors, 891cb0ef41Sopenharmony_ci std::function<Environment*(const CommonEnvironmentSetup*)> make_env) 901cb0ef41Sopenharmony_ci : impl_(new Impl()) { 911cb0ef41Sopenharmony_ci CHECK_NOT_NULL(platform); 921cb0ef41Sopenharmony_ci CHECK_NOT_NULL(errors); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci impl_->platform = platform; 951cb0ef41Sopenharmony_ci uv_loop_t* loop = &impl_->loop; 961cb0ef41Sopenharmony_ci // Use `data` to tell the destructor whether the loop was initialized or not. 971cb0ef41Sopenharmony_ci loop->data = nullptr; 981cb0ef41Sopenharmony_ci int ret = uv_loop_init(loop); 991cb0ef41Sopenharmony_ci if (ret != 0) { 1001cb0ef41Sopenharmony_ci errors->push_back( 1011cb0ef41Sopenharmony_ci SPrintF("Failed to initialize loop: %s", uv_err_name(ret))); 1021cb0ef41Sopenharmony_ci return; 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci loop->data = this; 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci impl_->allocator = ArrayBufferAllocator::Create(); 1071cb0ef41Sopenharmony_ci impl_->isolate = NewIsolate(impl_->allocator, &impl_->loop, platform); 1081cb0ef41Sopenharmony_ci Isolate* isolate = impl_->isolate; 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci { 1111cb0ef41Sopenharmony_ci Locker locker(isolate); 1121cb0ef41Sopenharmony_ci Isolate::Scope isolate_scope(isolate); 1131cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate); 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci TryCatch bootstrapCatch(isolate); 1161cb0ef41Sopenharmony_ci auto print_Exception = OnScopeLeave([&]() { 1171cb0ef41Sopenharmony_ci if (bootstrapCatch.HasCaught()) { 1181cb0ef41Sopenharmony_ci errors->push_back(FormatCaughtException( 1191cb0ef41Sopenharmony_ci isolate, isolate->GetCurrentContext(), bootstrapCatch)); 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci }); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci impl_->isolate_data.reset(CreateIsolateData( 1241cb0ef41Sopenharmony_ci isolate, loop, platform, impl_->allocator.get())); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci Local<Context> context = NewContext(isolate); 1271cb0ef41Sopenharmony_ci impl_->context.Reset(isolate, context); 1281cb0ef41Sopenharmony_ci if (context.IsEmpty()) { 1291cb0ef41Sopenharmony_ci errors->push_back("Failed to initialize V8 Context"); 1301cb0ef41Sopenharmony_ci return; 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci Context::Scope context_scope(context); 1341cb0ef41Sopenharmony_ci impl_->env.reset(make_env(this)); 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ciCommonEnvironmentSetup::~CommonEnvironmentSetup() { 1391cb0ef41Sopenharmony_ci if (impl_->isolate != nullptr) { 1401cb0ef41Sopenharmony_ci Isolate* isolate = impl_->isolate; 1411cb0ef41Sopenharmony_ci { 1421cb0ef41Sopenharmony_ci Locker locker(isolate); 1431cb0ef41Sopenharmony_ci Isolate::Scope isolate_scope(isolate); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci impl_->context.Reset(); 1461cb0ef41Sopenharmony_ci impl_->env.reset(); 1471cb0ef41Sopenharmony_ci impl_->isolate_data.reset(); 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci bool platform_finished = false; 1511cb0ef41Sopenharmony_ci impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) { 1521cb0ef41Sopenharmony_ci *static_cast<bool*>(data) = true; 1531cb0ef41Sopenharmony_ci }, &platform_finished); 1541cb0ef41Sopenharmony_ci impl_->platform->UnregisterIsolate(isolate); 1551cb0ef41Sopenharmony_ci isolate->Dispose(); 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci // Wait until the platform has cleaned up all relevant resources. 1581cb0ef41Sopenharmony_ci while (!platform_finished) 1591cb0ef41Sopenharmony_ci uv_run(&impl_->loop, UV_RUN_ONCE); 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci if (impl_->isolate || impl_->loop.data != nullptr) 1631cb0ef41Sopenharmony_ci CheckedUvLoopClose(&impl_->loop); 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci delete impl_; 1661cb0ef41Sopenharmony_ci} 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ciuv_loop_t* CommonEnvironmentSetup::event_loop() const { 1701cb0ef41Sopenharmony_ci return &impl_->loop; 1711cb0ef41Sopenharmony_ci} 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_cistd::shared_ptr<ArrayBufferAllocator> 1741cb0ef41Sopenharmony_ciCommonEnvironmentSetup::array_buffer_allocator() const { 1751cb0ef41Sopenharmony_ci return impl_->allocator; 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ciIsolate* CommonEnvironmentSetup::isolate() const { 1791cb0ef41Sopenharmony_ci return impl_->isolate; 1801cb0ef41Sopenharmony_ci} 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ciIsolateData* CommonEnvironmentSetup::isolate_data() const { 1831cb0ef41Sopenharmony_ci return impl_->isolate_data.get(); 1841cb0ef41Sopenharmony_ci} 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ciEnvironment* CommonEnvironmentSetup::env() const { 1871cb0ef41Sopenharmony_ci return impl_->env.get(); 1881cb0ef41Sopenharmony_ci} 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_civ8::Local<v8::Context> CommonEnvironmentSetup::context() const { 1911cb0ef41Sopenharmony_ci return impl_->context.Get(impl_->isolate); 1921cb0ef41Sopenharmony_ci} 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci} // namespace node 195