From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Wed, 16 Aug 2023 19:15:29 +0200
Subject: fix: assert module in the renderer process

When creating a Node.js Environment, embedders have the option to disable Node.js'
default overriding of Error.prepareStackTrace. However, the assert module depends on
a WeakMap that is populated with the error stacktraces in the overridden function.

This adds handling to fall back to the default implementation if Error.prepareStackTrace
if the override has been disabled.

This will be upstreamed.

diff --git a/lib/assert.js b/lib/assert.js
index b7d7a3da01d520984a5903cb9a0f1c288e0d5fa0..66a60c3726cd57e65db3e4fb57fb85721368c3ce 100644
--- a/lib/assert.js
+++ b/lib/assert.js
@@ -66,6 +66,7 @@ const { inspect } = require('internal/util/inspect');
 const { isPromise, isRegExp } = require('internal/util/types');
 const { EOL } = require('internal/constants');
 const { BuiltinModule } = require('internal/bootstrap/realm');
+const { getEmbedderOptions } = require('internal/options');
 const { isError, deprecate } = require('internal/util');
 
 const errorCache = new SafeMap();
@@ -293,8 +294,16 @@ function getErrMessage(message, fn) {
   ErrorCaptureStackTrace(err, fn);
   if (errorStackTraceLimitIsWritable) Error.stackTraceLimit = tmpLimit;
 
-  overrideStackTrace.set(err, (_, stack) => stack);
-  const call = err.stack[0];
+  let call;
+  if (getEmbedderOptions().hasPrepareStackTraceCallback) {
+    overrideStackTrace.set(err, (_, stack) => stack);
+    call = err.stack[0];
+  } else {
+    const tmpPrepare = Error.prepareStackTrace;
+    Error.prepareStackTrace = (_, stack) => stack;
+    call = err.stack[0];
+    Error.prepareStackTrace = tmpPrepare;
+  }
 
   const filename = call.getFileName();
   const line = call.getLineNumber() - 1;
diff --git a/src/api/environment.cc b/src/api/environment.cc
index c02906eacd90ac27d618e7578d1f928f16a858f7..74b4e15b8230c6380d41e84aa504824bb79b2ee5 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -277,6 +277,9 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
     auto* prepare_stack_trace_cb = s.prepare_stack_trace_callback ?
         s.prepare_stack_trace_callback : PrepareStackTraceCallback;
     isolate->SetPrepareStackTraceCallback(prepare_stack_trace_cb);
+  } else {
+    auto env = Environment::GetCurrent(isolate);
+    env->set_prepare_stack_trace_callback(Local<Function>());
   }
 }
 
diff --git a/src/node_options.cc b/src/node_options.cc
index f711ac936e76f9c16d15d7db759d0081a9eb018d..6eb2c137e1dd05b05e781820905cf6778107275d 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -1239,6 +1239,11 @@ void GetEmbedderOptions(const FunctionCallbackInfo<Value>& args) {
   Local<Context> context = env->context();
   Local<Object> ret = Object::New(isolate);
 
+  if (ret->Set(context,
+           FIXED_ONE_BYTE_STRING(env->isolate(), "hasPrepareStackTraceCallback"),
+           Boolean::New(isolate, !env->prepare_stack_trace_callback().IsEmpty()))
+      .IsNothing()) return;
+
   if (ret->Set(context,
            FIXED_ONE_BYTE_STRING(env->isolate(), "shouldNotRegisterESMLoader"),
            Boolean::New(isolate, env->should_not_register_esm_loader()))
