From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Shelley Vohr 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/internal/assert/utils.js b/lib/internal/assert/utils.js index 59b5a16f1309a5e4055bccfdb7a529045ad30402..bfdaf6211466a01b64b7942f7b16c480283278ff 100644 --- a/lib/internal/assert/utils.js +++ b/lib/internal/assert/utils.js @@ -25,6 +25,7 @@ const AssertionError = require('internal/assert/assertion_error'); const { openSync, closeSync, readSync } = require('fs'); const { EOL } = require('internal/constants'); const { BuiltinModule } = require('internal/bootstrap/realm'); +const { getEmbedderOptions } = require('internal/options'); const { isError } = require('internal/util'); const errorCache = new SafeMap(); @@ -167,8 +168,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 f59abcb21d64b910d8d42eb23c03109f62558813..1b6613d1de8c89c8271066a652afd1024988362d 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -244,6 +244,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()); } } diff --git a/src/node_options.cc b/src/node_options.cc index 29630fcccc3bd9d24ad6aec64bef2fedfc3c4031..4b3f7751db2871c8ce76b197a84a2417097030ea 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -1464,14 +1464,16 @@ void GetEmbedderOptions(const FunctionCallbackInfo& args) { } Isolate* isolate = args.GetIsolate(); - constexpr size_t kOptionsSize = 4; + constexpr size_t kOptionsSize = 5; std::array, kOptionsSize> names = { + FIXED_ONE_BYTE_STRING(env->isolate(), "hasPrepareStackTraceCallback"), FIXED_ONE_BYTE_STRING(env->isolate(), "shouldNotRegisterESMLoader"), FIXED_ONE_BYTE_STRING(env->isolate(), "noGlobalSearchPaths"), FIXED_ONE_BYTE_STRING(env->isolate(), "noBrowserGlobals"), FIXED_ONE_BYTE_STRING(env->isolate(), "hasEmbedderPreload")}; std::array, kOptionsSize> values = { + Boolean::New(isolate, env->prepare_stack_trace_callback().IsEmpty()), Boolean::New(isolate, env->should_not_register_esm_loader()), Boolean::New(isolate, env->no_global_search_paths()), Boolean::New(isolate, env->no_browser_globals()),