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 82c3a285f51abd1d517e7930887492652628e8c6..f68f22a4737ce395d3ee8a375513cb24ed1e8d2d 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/loaders');
+const { getEmbedderOptions } = require('internal/options');
 const { isError } = require('internal/util');
 
 const errorCache = new SafeMap();
@@ -289,8 +290,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 c718b9919bb30627e5da2b92a8de58c494bf4b93..64f8bef214fa4d55114aa9d04c111fcc3033ad10 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -262,6 +262,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 99f5274aec7512956a5e13a5ca9c0b593a57cc7a..2094efecfb83e80a01d582fde7566f3eed79cd55 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -1186,6 +1186,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()))
