Skip to content

Commit cc74821

Browse files
joyeecheungtargos
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 <legendecas@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 724f9d6 commit cc74821

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
@@ -15,6 +15,7 @@ using v8::Maybe;
1515
using v8::Nothing;
1616
using v8::SealHandleScope;
1717
using v8::SnapshotCreator;
18+
using v8::TryCatch;
1819

1920
namespace node {
2021

@@ -129,12 +130,21 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
129130
{
130131
Locker locker(isolate);
131132
Isolate::Scope isolate_scope(isolate);
133+
HandleScope handle_scope(isolate);
134+
135+
TryCatch bootstrapCatch(isolate);
136+
auto print_Exception = OnScopeLeave([&]() {
137+
if (bootstrapCatch.HasCaught()) {
138+
errors->push_back(FormatCaughtException(
139+
isolate, isolate->GetCurrentContext(), bootstrapCatch));
140+
}
141+
});
142+
132143
impl_->isolate_data.reset(CreateIsolateData(
133144
isolate, loop, platform, impl_->allocator.get(), snapshot_data));
134145
impl_->isolate_data->options()->build_snapshot =
135146
impl_->snapshot_creator.has_value();
136147

137-
HandleScope handle_scope(isolate);
138148
if (snapshot_data) {
139149
impl_->env.reset(make_env(this));
140150
if (impl_->env) {

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,
@@ -1089,7 +1119,8 @@ void TriggerUncaughtException(Isolate* isolate,
10891119
// error is supposed to be thrown at this point.
10901120
// Since we don't have access to Environment here, there is not
10911121
// much we can do, so we just print whatever is useful and crash.
1092-
PrintException(isolate, context, error, message);
1122+
PrintToStderrAndFlush(
1123+
FormatCaughtException(isolate, context, error, message));
10931124
Abort();
10941125
}
10951126

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)