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 9dfcf80a913942c93b206c6f871ac7807c7a7e81..4d25a22aedf7d7182bb709864e29b7e725336323 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();
@@ -294,8 +295,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;
+  }
 
   let filename = call.getFileName();
   const line = call.getLineNumber() - 1;
diff --git a/src/api/environment.cc b/src/api/environment.cc
index 11f8b8dea7bf4119c2d99ee451e3f1bc7bde8902..9045de3b17c93c4864a1bb1024b08f7d1ffa83be 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 a3d25cdd52f18e319ae3ac81437c8a0206b18690..48ce3f3b68a94fc35e5ce93a385ddbebb03741b9 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -1269,6 +1269,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()))
