From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Tue, 7 Feb 2023 10:53:11 +0100
Subject: src: allow optional isolation termination in node

This patch allows for node::Stop() to conditionally call
V8:Isolate::TerminateExecution().

We do not want to invoke a termination exception at exit when
we're running with only_terminate_in_safe_scope set to false. Heap and
coverage profilers run after environment exit and if there is a pending
exception at this stage then they will fail to generate the appropriate
profiles. Node.js does not call node::Stop(), which previously always
called isolate->TerminateExecution(), and therefore does not have this
issue when also running with only_terminate_in_safe_scope set to false.

diff --git a/src/env.cc b/src/env.cc
index 837a879864c46d6f500684444ec38583c05f8be2..69a8b9ea405a400254041734b037c00aff4758f7 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -902,10 +902,11 @@ void Environment::InitializeLibuv() {
   StartProfilerIdleNotifier();
 }
 
-void Environment::ExitEnv() {
+void Environment::ExitEnv(bool terminate) {
   // Should not access non-thread-safe methods here.
   set_stopping(true);
-  isolate_->TerminateExecution();
+  if (terminate)
+    isolate_->TerminateExecution();
   SetImmediateThreadsafe([](Environment* env) {
     env->set_can_call_into_js(false);
     uv_stop(env->event_loop());
diff --git a/src/env.h b/src/env.h
index 562610e6827d8302f146b81d599dd366ba25cd74..c358c139aafcd7c958915b036f8d176909341556 100644
--- a/src/env.h
+++ b/src/env.h
@@ -628,7 +628,7 @@ class Environment : public MemoryRetainer {
   void RegisterHandleCleanups();
   void CleanupHandles();
   void Exit(int code);
-  void ExitEnv();
+  void ExitEnv(bool terminate);
 
   // Register clean-up cb to be called on environment destruction.
   inline void RegisterHandleCleanup(uv_handle_t* handle,
diff --git a/src/node.cc b/src/node.cc
index 1067dee74c8877d9a3a0da6527c4c37faf9bd15f..b550fd4aa8488c6d721db3dee94cc4ce1346c708 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1229,8 +1229,8 @@ int Start(int argc, char** argv) {
   return LoadSnapshotDataAndRun(&snapshot_data, result.get());
 }
 
-int Stop(Environment* env) {
-  env->ExitEnv();
+int Stop(Environment* env, bool terminate) {
+  env->ExitEnv(terminate);
   return 0;
 }
 
diff --git a/src/node.h b/src/node.h
index 47ac8c24ef5e26822f694b583767e850fc5f7d96..f1fb363becf1f1b3b3ef0b2782c6561d29aa7cbd 100644
--- a/src/node.h
+++ b/src/node.h
@@ -316,7 +316,7 @@ NODE_EXTERN int Start(int argc, char* argv[]);
 
 // Tear down Node.js while it is running (there are active handles
 // in the loop and / or actively executing JavaScript code).
-NODE_EXTERN int Stop(Environment* env);
+NODE_EXTERN int Stop(Environment* env, bool terminate = true);
 
 // This runs a subset of the initialization performed by
 // InitializeOncePerProcess(), which supersedes this function.
