Skip to content

Commit 5202b84

Browse files
joyeecheungdanielleadams
authored andcommitted
bootstrap: print stack trace during environment creation failure
#45888 took the environment creation code out of the scope covered by the v8::TryCatch that we use to print early failures during environment creation. So e.g. when adding something that would fail in node.js, we get ``` node:internal/options:554: Uncaught Error: Should not query options before bootstrapping is done ``` This patch restores that by adding another v8::TryCatch for it: ``` node:internal/options:20 ({ options: optionsMap } = getCLIOptions()); ^ Error: Should not query options before bootstrapping is done at getCLIOptionsFromBinding (node:internal/options:20:32) at getOptionValue (node:internal/options:45:19) at node:internal/bootstrap/node:433:29 ``` PR-URL: #46533 Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 307d096 commit 5202b84

File tree

3 files changed

+69
-25
lines changed

3 files changed

+69
-25
lines changed

src/api/embed_helpers.cc

+11-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ using v8::Locker;
1212
using v8::Maybe;
1313
using v8::Nothing;
1414
using v8::SealHandleScope;
15+
using v8::TryCatch;
1516

1617
namespace node {
1718

@@ -109,10 +110,19 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
109110
{
110111
Locker locker(isolate);
111112
Isolate::Scope isolate_scope(isolate);
113+
HandleScope handle_scope(isolate);
114+
115+
TryCatch bootstrapCatch(isolate);
116+
auto print_Exception = OnScopeLeave([&]() {
117+
if (bootstrapCatch.HasCaught()) {
118+
errors->push_back(FormatCaughtException(
119+
isolate, isolate->GetCurrentContext(), bootstrapCatch));
120+
}
121+
});
122+
112123
impl_->isolate_data.reset(CreateIsolateData(
113124
isolate, loop, platform, impl_->allocator.get()));
114125

115-
HandleScope handle_scope(isolate);
116126
Local<Context> context = NewContext(isolate);
117127
impl_->context.Reset(isolate, context);
118128
if (context.IsEmpty()) {

src/node_errors.cc

+55-24
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ static std::string GetErrorSource(Isolate* isolate,
185185
return buf + std::string(underline_buf, off);
186186
}
187187

188-
void PrintStackTrace(Isolate* isolate, Local<StackTrace> stack) {
188+
static std::string FormatStackTrace(Isolate* isolate, Local<StackTrace> stack) {
189+
std::string result;
189190
for (int i = 0; i < stack->GetFrameCount(); i++) {
190191
Local<StackFrame> stack_frame = stack->GetFrame(isolate, i);
191192
node::Utf8Value fn_name_s(isolate, stack_frame->GetFunctionName());
@@ -195,53 +196,82 @@ void PrintStackTrace(Isolate* isolate, Local<StackTrace> stack) {
195196

196197
if (stack_frame->IsEval()) {
197198
if (stack_frame->GetScriptId() == Message::kNoScriptIdInfo) {
198-
FPrintF(stderr, " at [eval]:%i:%i\n", line_number, column);
199+
result += SPrintF(" at [eval]:%i:%i\n", line_number, column);
199200
} else {
200-
FPrintF(stderr,
201-
" at [eval] (%s:%i:%i)\n",
202-
*script_name,
203-
line_number,
204-
column);
201+
std::vector<char> buf(script_name.length() + 64);
202+
snprintf(buf.data(),
203+
buf.size(),
204+
" at [eval] (%s:%i:%i)\n",
205+
*script_name,
206+
line_number,
207+
column);
208+
result += std::string(buf.data());
205209
}
206210
break;
207211
}
208212

209213
if (fn_name_s.length() == 0) {
210-
FPrintF(stderr, " at %s:%i:%i\n", script_name, line_number, column);
214+
std::vector<char> buf(script_name.length() + 64);
215+
snprintf(buf.data(),
216+
buf.size(),
217+
" at %s:%i:%i\n",
218+
*script_name,
219+
line_number,
220+
column);
221+
result += std::string(buf.data());
211222
} else {
212-
FPrintF(stderr,
213-
" at %s (%s:%i:%i)\n",
214-
fn_name_s,
215-
script_name,
216-
line_number,
217-
column);
223+
std::vector<char> buf(fn_name_s.length() + script_name.length() + 64);
224+
snprintf(buf.data(),
225+
buf.size(),
226+
" at %s (%s:%i:%i)\n",
227+
*fn_name_s,
228+
*script_name,
229+
line_number,
230+
column);
231+
result += std::string(buf.data());
218232
}
219233
}
234+
return result;
235+
}
236+
237+
static void PrintToStderrAndFlush(const std::string& str) {
238+
FPrintF(stderr, "%s\n", str);
220239
fflush(stderr);
221240
}
222241

223-
void PrintException(Isolate* isolate,
224-
Local<Context> context,
225-
Local<Value> err,
226-
Local<Message> message) {
242+
void PrintStackTrace(Isolate* isolate, Local<StackTrace> stack) {
243+
PrintToStderrAndFlush(FormatStackTrace(isolate, stack));
244+
}
245+
246+
std::string FormatCaughtException(Isolate* isolate,
247+
Local<Context> context,
248+
Local<Value> err,
249+
Local<Message> message) {
227250
node::Utf8Value reason(isolate,
228251
err->ToDetailString(context)
229252
.FromMaybe(Local<String>()));
230253
bool added_exception_line = false;
231254
std::string source =
232255
GetErrorSource(isolate, context, message, &added_exception_line);
233-
FPrintF(stderr, "%s\n", source);
234-
FPrintF(stderr, "%s\n", reason);
256+
std::string result = source + '\n' + reason.ToString() + '\n';
235257

236258
Local<v8::StackTrace> stack = message->GetStackTrace();
237-
if (!stack.IsEmpty()) PrintStackTrace(isolate, stack);
259+
if (!stack.IsEmpty()) result += FormatStackTrace(isolate, stack);
260+
return result;
261+
}
262+
263+
std::string FormatCaughtException(Isolate* isolate,
264+
Local<Context> context,
265+
const v8::TryCatch& try_catch) {
266+
CHECK(try_catch.HasCaught());
267+
return FormatCaughtException(
268+
isolate, context, try_catch.Exception(), try_catch.Message());
238269
}
239270

240271
void PrintCaughtException(Isolate* isolate,
241272
Local<Context> context,
242273
const v8::TryCatch& try_catch) {
243-
CHECK(try_catch.HasCaught());
244-
PrintException(isolate, context, try_catch.Exception(), try_catch.Message());
274+
PrintToStderrAndFlush(FormatCaughtException(isolate, context, try_catch));
245275
}
246276

247277
void AppendExceptionLine(Environment* env,
@@ -1076,7 +1106,8 @@ void TriggerUncaughtException(Isolate* isolate,
10761106
// error is supposed to be thrown at this point.
10771107
// Since we don't have access to Environment here, there is not
10781108
// much we can do, so we just print whatever is useful and crash.
1079-
PrintException(isolate, context, error, message);
1109+
PrintToStderrAndFlush(
1110+
FormatCaughtException(isolate, context, error, message));
10801111
Abort();
10811112
}
10821113

src/node_internals.h

+3
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ void PrintStackTrace(v8::Isolate* isolate, v8::Local<v8::StackTrace> stack);
8383
void PrintCaughtException(v8::Isolate* isolate,
8484
v8::Local<v8::Context> context,
8585
const v8::TryCatch& try_catch);
86+
std::string FormatCaughtException(v8::Isolate* isolate,
87+
v8::Local<v8::Context> context,
88+
const v8::TryCatch& try_catch);
8689

8790
void ResetStdio(); // Safe to call more than once and from signal handlers.
8891
#ifdef __POSIX__

0 commit comments

Comments
 (0)