GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_errors.cc Lines: 277 409 67.7 %
Date: 2020-06-24 22:13:30 Branches: 174 335 51.9 %

Line Branch Exec Source
1
#include <cerrno>
2
#include <cstdarg>
3
4
#include "debug_utils-inl.h"
5
#include "node_errors.h"
6
#include "node_internals.h"
7
#include "node_report.h"
8
#include "node_process.h"
9
#include "node_v8_platform-inl.h"
10
#include "util-inl.h"
11
12
namespace node {
13
14
using errors::TryCatchScope;
15
using v8::Boolean;
16
using v8::Context;
17
using v8::Exception;
18
using v8::Function;
19
using v8::FunctionCallbackInfo;
20
using v8::HandleScope;
21
using v8::Int32;
22
using v8::Isolate;
23
using v8::Just;
24
using v8::Local;
25
using v8::Maybe;
26
using v8::MaybeLocal;
27
using v8::Message;
28
using v8::Object;
29
using v8::ScriptOrigin;
30
using v8::StackFrame;
31
using v8::StackTrace;
32
using v8::String;
33
using v8::Undefined;
34
using v8::Value;
35
36
487
bool IsExceptionDecorated(Environment* env, Local<Value> er) {
37

974
  if (!er.IsEmpty() && er->IsObject()) {
38
479
    Local<Object> err_obj = er.As<Object>();
39
    auto maybe_value =
40
958
        err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
41
    Local<Value> decorated;
42

958
    return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
43
  }
44
8
  return false;
45
}
46
47
namespace per_process {
48
4399
static Mutex tty_mutex;
49
}  // namespace per_process
50
51
924
static std::string GetErrorSource(Isolate* isolate,
52
                                  Local<Context> context,
53
                                  Local<Message> message,
54
                                  bool* added_exception_line) {
55
924
  MaybeLocal<String> source_line_maybe = message->GetSourceLine(context);
56
1848
  node::Utf8Value encoded_source(isolate, source_line_maybe.ToLocalChecked());
57
1848
  std::string sourceline(*encoded_source, encoded_source.length());
58
924
  *added_exception_line = false;
59
60
  // If source maps have been enabled, the exception line will instead be
61
  // added in the JavaScript context:
62
924
  Environment* env = Environment::GetCurrent(isolate);
63
  const bool has_source_map_url =
64
2772
      !message->GetScriptOrigin().SourceMapUrl().IsEmpty();
65

924
  if (has_source_map_url && env->source_maps_enabled()) {
66
10
    return sourceline;
67
  }
68
69
914
  if (sourceline.find("node-do-not-add-exception-line") != std::string::npos) {
70
8
    return sourceline;
71
  }
72
73
  // Because of how node modules work, all scripts are wrapped with a
74
  // "function (module, exports, __filename, ...) {"
75
  // to provide script local variables.
76
  //
77
  // When reporting errors on the first line of a script, this wrapper
78
  // function is leaked to the user. There used to be a hack here to
79
  // truncate off the first 62 characters, but it caused numerous other
80
  // problems when vm.runIn*Context() methods were used for non-module
81
  // code.
82
  //
83
  // If we ever decide to re-instate such a hack, the following steps
84
  // must be taken:
85
  //
86
  // 1. Pass a flag around to say "this code was wrapped"
87
  // 2. Update the stack frame output so that it is also correct.
88
  //
89
  // It would probably be simpler to add a line rather than add some
90
  // number of characters to the first line, since V8 truncates the
91
  // sourceline to 78 characters, and we end up not providing very much
92
  // useful debugging info to the user if we remove 62 characters.
93
94
  // Print (filename):(line number): (message).
95
906
  ScriptOrigin origin = message->GetScriptOrigin();
96
1812
  node::Utf8Value filename(isolate, message->GetScriptResourceName());
97
906
  const char* filename_string = *filename;
98
1812
  int linenum = message->GetLineNumber(context).FromJust();
99
100
3624
  int script_start = (linenum - origin.ResourceLineOffset()->Value()) == 1
101
1204
                         ? origin.ResourceColumnOffset()->Value()
102
1055
                         : 0;
103
2718
  int start = message->GetStartColumn(context).FromMaybe(0);
104
2718
  int end = message->GetEndColumn(context).FromMaybe(0);
105
906
  if (start >= script_start) {
106
906
    CHECK_GE(end, start);
107
906
    start -= script_start;
108
906
    end -= script_start;
109
  }
110
111
  std::string buf = SPrintF("%s:%i\n%s\n",
112
                            filename_string,
113
                            linenum,
114
1812
                            sourceline.c_str());
115
906
  CHECK_GT(buf.size(), 0);
116
906
  *added_exception_line = true;
117
118

2718
  if (start > end ||
119

1812
      start < 0 ||
120
906
      static_cast<size_t>(end) > sourceline.size()) {
121
17
    return buf;
122
  }
123
124
889
  constexpr int kUnderlineBufsize = 1020;
125
  char underline_buf[kUnderlineBufsize + 4];
126
889
  int off = 0;
127
  // Print wavy underline (GetUnderline is deprecated).
128
5120
  for (int i = 0; i < start; i++) {
129

4231
    if (sourceline[i] == '\0' || off >= kUnderlineBufsize) {
130
      break;
131
    }
132
4231
    CHECK_LT(off, kUnderlineBufsize);
133
4231
    underline_buf[off++] = (sourceline[i] == '\t') ? '\t' : ' ';
134
  }
135
3441
  for (int i = start; i < end; i++) {
136

2552
    if (sourceline[i] == '\0' || off >= kUnderlineBufsize) {
137
      break;
138
    }
139
2552
    CHECK_LT(off, kUnderlineBufsize);
140
2552
    underline_buf[off++] = '^';
141
  }
142
889
  CHECK_LE(off, kUnderlineBufsize);
143
889
  underline_buf[off++] = '\n';
144
145
889
  return buf + std::string(underline_buf, off);
146
}
147
148
6
void PrintStackTrace(Isolate* isolate, Local<StackTrace> stack) {
149
96
  for (int i = 0; i < stack->GetFrameCount(); i++) {
150
84
    Local<StackFrame> stack_frame = stack->GetFrame(isolate, i);
151
126
    node::Utf8Value fn_name_s(isolate, stack_frame->GetFunctionName());
152
126
    node::Utf8Value script_name(isolate, stack_frame->GetScriptName());
153
42
    const int line_number = stack_frame->GetLineNumber();
154
42
    const int column = stack_frame->GetColumn();
155
156
42
    if (stack_frame->IsEval()) {
157
      if (stack_frame->GetScriptId() == Message::kNoScriptIdInfo) {
158
        FPrintF(stderr, "    at [eval]:%i:%i\n", line_number, column);
159
      } else {
160
        FPrintF(stderr,
161
                "    at [eval] (%s:%i:%i)\n",
162
                *script_name,
163
                line_number,
164
                column);
165
      }
166
      break;
167
    }
168
169
42
    if (fn_name_s.length() == 0) {
170
11
      FPrintF(stderr, "    at %s:%i:%i\n", script_name, line_number, column);
171
    } else {
172
      FPrintF(stderr,
173
              "    at %s (%s:%i:%i)\n",
174
              fn_name_s,
175
              script_name,
176
              line_number,
177
31
              column);
178
    }
179
  }
180
6
  fflush(stderr);
181
6
}
182
183
423
void PrintException(Isolate* isolate,
184
                    Local<Context> context,
185
                    Local<Value> err,
186
                    Local<Message> message) {
187
  node::Utf8Value reason(isolate,
188
846
                         err->ToDetailString(context)
189
1269
                             .FromMaybe(Local<String>()));
190
423
  bool added_exception_line = false;
191
  std::string source =
192
846
      GetErrorSource(isolate, context, message, &added_exception_line);
193
423
  FPrintF(stderr, "%s\n", source);
194
423
  FPrintF(stderr, "%s\n", reason);
195
196
423
  Local<v8::StackTrace> stack = message->GetStackTrace();
197
423
  if (!stack.IsEmpty()) PrintStackTrace(isolate, stack);
198
423
}
199
200
423
void PrintCaughtException(Isolate* isolate,
201
                          Local<Context> context,
202
                          const v8::TryCatch& try_catch) {
203
423
  CHECK(try_catch.HasCaught());
204
423
  PrintException(isolate, context, try_catch.Exception(), try_catch.Message());
205
423
}
206
207
501
void AppendExceptionLine(Environment* env,
208
                         Local<Value> er,
209
                         Local<Message> message,
210
                         enum ErrorHandlingMode mode) {
211
533
  if (message.IsEmpty()) return;
212
213
970
  HandleScope scope(env->isolate());
214
  Local<Object> err_obj;
215

1002
  if (!er.IsEmpty() && er->IsObject()) {
216
493
    err_obj = er.As<Object>();
217
  }
218
219
501
  bool added_exception_line = false;
220
  std::string source = GetErrorSource(
221
970
      env->isolate(), env->context(), message, &added_exception_line);
222
501
  if (!added_exception_line) {
223
18
    return;
224
  }
225
483
  MaybeLocal<Value> arrow_str = ToV8Value(env->context(), source);
226
227

966
  const bool can_set_arrow = !arrow_str.IsEmpty() && !err_obj.IsEmpty();
228
  // If allocating arrow_str failed, print it out. There's not much else to do.
229
  // If it's not an error, but something needs to be printed out because
230
  // it's a fatal exception, also print it out from here.
231
  // Otherwise, the arrow property will be attached to the object and handled
232
  // by the caller.
233


665
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
234
14
    if (env->printed_error()) return;
235
28
    Mutex::ScopedLock lock(per_process::tty_mutex);
236
14
    env->set_printed_error(true);
237
238
14
    ResetStdio();
239
14
    FPrintF(stderr, "\n%s", source);
240
14
    return;
241
  }
242
243

1876
  CHECK(err_obj
244
            ->SetPrivate(env->context(),
245
                         env->arrow_message_private_symbol(),
246
                         arrow_str.ToLocalChecked())
247
            .FromMaybe(false));
248
}
249
250
[[noreturn]] void Abort() {
251
  DumpBacktrace(stderr);
252
  fflush(stderr);
253
  ABORT_NO_BACKTRACE();
254
}
255
256
[[noreturn]] void Assert(const AssertionInfo& info) {
257
  std::string name = GetHumanReadableProcessName();
258
259
  fprintf(stderr,
260
          "%s: %s:%s%s Assertion `%s' failed.\n",
261
          name.c_str(),
262
          info.file_line,
263
          info.function,
264
          *info.function ? ":" : "",
265
          info.message);
266
  fflush(stderr);
267
268
  Abort();
269
}
270
271
enum class EnhanceFatalException { kEnhance, kDontEnhance };
272
273
/**
274
 * Report the exception to the inspector, then print it to stderr.
275
 * This should only be used when the Node.js instance is about to exit
276
 * (i.e. this should be followed by a env->Exit() or an Abort()).
277
 *
278
 * Use enhance_stack = EnhanceFatalException::kDontEnhance
279
 * when it's unsafe to call into JavaScript.
280
 */
281
208
static void ReportFatalException(Environment* env,
282
                                 Local<Value> error,
283
                                 Local<Message> message,
284
                                 EnhanceFatalException enhance_stack) {
285
208
  if (!env->can_call_into_js())
286
    enhance_stack = EnhanceFatalException::kDontEnhance;
287
288
208
  Isolate* isolate = env->isolate();
289
208
  CHECK(!error.IsEmpty());
290
208
  CHECK(!message.IsEmpty());
291
416
  HandleScope scope(isolate);
292
293
208
  AppendExceptionLine(env, error, message, FATAL_ERROR);
294
295
208
  auto report_to_inspector = [&]() {
296
#if HAVE_INSPECTOR
297
208
    env->inspector_agent()->ReportUncaughtException(error, message);
298
#endif
299
416
  };
300
301
  Local<Value> arrow;
302
  Local<Value> stack_trace;
303
208
  bool decorated = IsExceptionDecorated(env, error);
304
305
208
  if (!error->IsObject()) {  // We can only enhance actual errors.
306
8
    report_to_inspector();
307
16
    stack_trace = Undefined(isolate);
308
    // If error is not an object, AppendExceptionLine() has already print the
309
    // source line and the arrow to stderr.
310
    // TODO(joyeecheung): move that side effect out of AppendExceptionLine().
311
    // It is done just to preserve the source line as soon as possible.
312
  } else {
313
200
    Local<Object> err_obj = error.As<Object>();
314
315
400
    auto enhance_with = [&](Local<Function> enhancer) {
316
      Local<Value> enhanced;
317
800
      Local<Value> argv[] = {err_obj};
318

1200
      if (!enhancer.IsEmpty() &&
319
          enhancer
320
1600
              ->Call(env->context(), Undefined(isolate), arraysize(argv), argv)
321
400
              .ToLocal(&enhanced)) {
322
396
        stack_trace = enhanced;
323
      }
324
600
    };
325
326
200
    switch (enhance_stack) {
327
      case EnhanceFatalException::kEnhance: {
328
200
        enhance_with(env->enhance_fatal_stack_before_inspector());
329
200
        report_to_inspector();
330
200
        enhance_with(env->enhance_fatal_stack_after_inspector());
331
200
        break;
332
      }
333
      case EnhanceFatalException::kDontEnhance: {
334
        USE(err_obj->Get(env->context(), env->stack_string())
335
                .ToLocal(&stack_trace));
336
        report_to_inspector();
337
        break;
338
      }
339
      default:
340
        UNREACHABLE();
341
    }
342
343
    arrow =
344
600
        err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol())
345
200
            .ToLocalChecked();
346
  }
347
348
416
  node::Utf8Value trace(env->isolate(), stack_trace);
349
350
  // range errors have a trace member set to undefined
351

620
  if (trace.length() > 0 && !stack_trace->IsUndefined()) {
352


594
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
353
71
      FPrintF(stderr, "%s\n", trace);
354
    } else {
355
254
      node::Utf8Value arrow_string(env->isolate(), arrow);
356
127
      FPrintF(stderr, "%s\n%s\n", arrow_string, trace);
357
    }
358
  } else {
359
    // this really only happens for RangeErrors, since they're the only
360
    // kind that won't have all this info in the trace, or when non-Error
361
    // objects are thrown manually.
362
    MaybeLocal<Value> message;
363
    MaybeLocal<Value> name;
364
365
10
    if (error->IsObject()) {
366
2
      Local<Object> err_obj = error.As<Object>();
367
6
      message = err_obj->Get(env->context(), env->message_string());
368
6
      name = err_obj->Get(env->context(), env->name_string());
369
    }
370
371

36
    if (message.IsEmpty() || message.ToLocalChecked()->IsUndefined() ||
372

20
        name.IsEmpty() || name.ToLocalChecked()->IsUndefined()) {
373
      // Not an error object. Just print as-is.
374
20
      node::Utf8Value message(env->isolate(), error);
375
376
      FPrintF(stderr, "%s\n",
377

10
              *message ? message.ToString() : "<toString() threw exception>");
378
    } else {
379
      node::Utf8Value name_string(env->isolate(), name.ToLocalChecked());
380
      node::Utf8Value message_string(env->isolate(), message.ToLocalChecked());
381
382
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
383
        FPrintF(stderr, "%s: %s\n", name_string, message_string);
384
      } else {
385
        node::Utf8Value arrow_string(env->isolate(), arrow);
386
        FPrintF(stderr,
387
            "%s\n%s: %s\n", arrow_string, name_string, message_string);
388
      }
389
    }
390
391
10
    if (!env->options()->trace_uncaught) {
392
14
      std::string argv0;
393
7
      if (!env->argv().empty()) argv0 = env->argv()[0];
394
7
      if (argv0.empty()) argv0 = "node";
395
      FPrintF(stderr,
396
              "(Use `%s --trace-uncaught ...` to show where the exception "
397
              "was thrown)\n",
398
7
              fs::Basename(argv0, ".exe"));
399
    }
400
  }
401
402
208
  if (env->options()->trace_uncaught) {
403
3
    Local<StackTrace> trace = message->GetStackTrace();
404
3
    if (!trace.IsEmpty()) {
405
3
      FPrintF(stderr, "Thrown at:\n");
406
3
      PrintStackTrace(env->isolate(), trace);
407
    }
408
  }
409
410
208
  fflush(stderr);
411
208
}
412
413
[[noreturn]] void FatalError(const char* location, const char* message) {
414
  OnFatalError(location, message);
415
  // to suppress compiler warning
416
  ABORT();
417
}
418
419
void OnFatalError(const char* location, const char* message) {
420
  if (location) {
421
    FPrintF(stderr, "FATAL ERROR: %s %s\n", location, message);
422
  } else {
423
    FPrintF(stderr, "FATAL ERROR: %s\n", message);
424
  }
425
426
  Isolate* isolate = Isolate::GetCurrent();
427
  Environment* env = Environment::GetCurrent(isolate);
428
  bool report_on_fatalerror;
429
  {
430
    Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
431
    report_on_fatalerror = per_process::cli_options->report_on_fatalerror;
432
  }
433
434
  if (report_on_fatalerror) {
435
    report::TriggerNodeReport(
436
        isolate, env, message, "FatalError", "", Local<String>());
437
  }
438
439
  fflush(stderr);
440
  ABORT();
441
}
442
443
namespace errors {
444
445
2370724
TryCatchScope::~TryCatchScope() {
446


1185294
  if (HasCaught() && !HasTerminated() && mode_ == CatchMode::kFatal) {
447
5
    HandleScope scope(env_->isolate());
448
5
    Local<v8::Value> exception = Exception();
449
5
    Local<v8::Message> message = Message();
450
5
    EnhanceFatalException enhance = CanContinue() ?
451
5
        EnhanceFatalException::kEnhance : EnhanceFatalException::kDontEnhance;
452
5
    if (message.IsEmpty())
453
      message = Exception::CreateMessage(env_->isolate(), exception);
454
5
    ReportFatalException(env_, exception, message, enhance);
455
5
    env_->Exit(7);
456
  }
457
1185303
}
458
459
4
const char* errno_string(int errorno) {
460
#define ERRNO_CASE(e)                                                          \
461
  case e:                                                                      \
462
    return #e;
463



















4
  switch (errorno) {
464
#ifdef EACCES
465
    ERRNO_CASE(EACCES);
466
#endif
467
468
#ifdef EADDRINUSE
469
    ERRNO_CASE(EADDRINUSE);
470
#endif
471
472
#ifdef EADDRNOTAVAIL
473
    ERRNO_CASE(EADDRNOTAVAIL);
474
#endif
475
476
#ifdef EAFNOSUPPORT
477
    ERRNO_CASE(EAFNOSUPPORT);
478
#endif
479
480
#ifdef EAGAIN
481
    ERRNO_CASE(EAGAIN);
482
#endif
483
484
#ifdef EWOULDBLOCK
485
#if EAGAIN != EWOULDBLOCK
486
    ERRNO_CASE(EWOULDBLOCK);
487
#endif
488
#endif
489
490
#ifdef EALREADY
491
    ERRNO_CASE(EALREADY);
492
#endif
493
494
#ifdef EBADF
495
    ERRNO_CASE(EBADF);
496
#endif
497
498
#ifdef EBADMSG
499
    ERRNO_CASE(EBADMSG);
500
#endif
501
502
#ifdef EBUSY
503
    ERRNO_CASE(EBUSY);
504
#endif
505
506
#ifdef ECANCELED
507
    ERRNO_CASE(ECANCELED);
508
#endif
509
510
#ifdef ECHILD
511
1
    ERRNO_CASE(ECHILD);
512
#endif
513
514
#ifdef ECONNABORTED
515
    ERRNO_CASE(ECONNABORTED);
516
#endif
517
518
#ifdef ECONNREFUSED
519
    ERRNO_CASE(ECONNREFUSED);
520
#endif
521
522
#ifdef ECONNRESET
523
    ERRNO_CASE(ECONNRESET);
524
#endif
525
526
#ifdef EDEADLK
527
    ERRNO_CASE(EDEADLK);
528
#endif
529
530
#ifdef EDESTADDRREQ
531
    ERRNO_CASE(EDESTADDRREQ);
532
#endif
533
534
#ifdef EDOM
535
    ERRNO_CASE(EDOM);
536
#endif
537
538
#ifdef EDQUOT
539
    ERRNO_CASE(EDQUOT);
540
#endif
541
542
#ifdef EEXIST
543
    ERRNO_CASE(EEXIST);
544
#endif
545
546
#ifdef EFAULT
547
    ERRNO_CASE(EFAULT);
548
#endif
549
550
#ifdef EFBIG
551
    ERRNO_CASE(EFBIG);
552
#endif
553
554
#ifdef EHOSTUNREACH
555
    ERRNO_CASE(EHOSTUNREACH);
556
#endif
557
558
#ifdef EIDRM
559
    ERRNO_CASE(EIDRM);
560
#endif
561
562
#ifdef EILSEQ
563
    ERRNO_CASE(EILSEQ);
564
#endif
565
566
#ifdef EINPROGRESS
567
    ERRNO_CASE(EINPROGRESS);
568
#endif
569
570
#ifdef EINTR
571
    ERRNO_CASE(EINTR);
572
#endif
573
574
#ifdef EINVAL
575
    ERRNO_CASE(EINVAL);
576
#endif
577
578
#ifdef EIO
579
    ERRNO_CASE(EIO);
580
#endif
581
582
#ifdef EISCONN
583
    ERRNO_CASE(EISCONN);
584
#endif
585
586
#ifdef EISDIR
587
    ERRNO_CASE(EISDIR);
588
#endif
589
590
#ifdef ELOOP
591
    ERRNO_CASE(ELOOP);
592
#endif
593
594
#ifdef EMFILE
595
    ERRNO_CASE(EMFILE);
596
#endif
597
598
#ifdef EMLINK
599
    ERRNO_CASE(EMLINK);
600
#endif
601
602
#ifdef EMSGSIZE
603
    ERRNO_CASE(EMSGSIZE);
604
#endif
605
606
#ifdef EMULTIHOP
607
    ERRNO_CASE(EMULTIHOP);
608
#endif
609
610
#ifdef ENAMETOOLONG
611
    ERRNO_CASE(ENAMETOOLONG);
612
#endif
613
614
#ifdef ENETDOWN
615
    ERRNO_CASE(ENETDOWN);
616
#endif
617
618
#ifdef ENETRESET
619
    ERRNO_CASE(ENETRESET);
620
#endif
621
622
#ifdef ENETUNREACH
623
    ERRNO_CASE(ENETUNREACH);
624
#endif
625
626
#ifdef ENFILE
627
    ERRNO_CASE(ENFILE);
628
#endif
629
630
#ifdef ENOBUFS
631
    ERRNO_CASE(ENOBUFS);
632
#endif
633
634
#ifdef ENODATA
635
    ERRNO_CASE(ENODATA);
636
#endif
637
638
#ifdef ENODEV
639
    ERRNO_CASE(ENODEV);
640
#endif
641
642
#ifdef ENOENT
643
    ERRNO_CASE(ENOENT);
644
#endif
645
646
#ifdef ENOEXEC
647
    ERRNO_CASE(ENOEXEC);
648
#endif
649
650
#ifdef ENOLINK
651
    ERRNO_CASE(ENOLINK);
652
#endif
653
654
#ifdef ENOLCK
655
#if ENOLINK != ENOLCK
656
    ERRNO_CASE(ENOLCK);
657
#endif
658
#endif
659
660
#ifdef ENOMEM
661
    ERRNO_CASE(ENOMEM);
662
#endif
663
664
#ifdef ENOMSG
665
    ERRNO_CASE(ENOMSG);
666
#endif
667
668
#ifdef ENOPROTOOPT
669
    ERRNO_CASE(ENOPROTOOPT);
670
#endif
671
672
#ifdef ENOSPC
673
    ERRNO_CASE(ENOSPC);
674
#endif
675
676
#ifdef ENOSR
677
    ERRNO_CASE(ENOSR);
678
#endif
679
680
#ifdef ENOSTR
681
    ERRNO_CASE(ENOSTR);
682
#endif
683
684
#ifdef ENOSYS
685
    ERRNO_CASE(ENOSYS);
686
#endif
687
688
#ifdef ENOTCONN
689
    ERRNO_CASE(ENOTCONN);
690
#endif
691
692
#ifdef ENOTDIR
693
    ERRNO_CASE(ENOTDIR);
694
#endif
695
696
#ifdef ENOTEMPTY
697
#if ENOTEMPTY != EEXIST
698
    ERRNO_CASE(ENOTEMPTY);
699
#endif
700
#endif
701
702
#ifdef ENOTSOCK
703
    ERRNO_CASE(ENOTSOCK);
704
#endif
705
706
#ifdef ENOTSUP
707
    ERRNO_CASE(ENOTSUP);
708
#else
709
#ifdef EOPNOTSUPP
710
    ERRNO_CASE(EOPNOTSUPP);
711
#endif
712
#endif
713
714
#ifdef ENOTTY
715
    ERRNO_CASE(ENOTTY);
716
#endif
717
718
#ifdef ENXIO
719
    ERRNO_CASE(ENXIO);
720
#endif
721
722
#ifdef EOVERFLOW
723
    ERRNO_CASE(EOVERFLOW);
724
#endif
725
726
#ifdef EPERM
727
2
    ERRNO_CASE(EPERM);
728
#endif
729
730
#ifdef EPIPE
731
    ERRNO_CASE(EPIPE);
732
#endif
733
734
#ifdef EPROTO
735
    ERRNO_CASE(EPROTO);
736
#endif
737
738
#ifdef EPROTONOSUPPORT
739
    ERRNO_CASE(EPROTONOSUPPORT);
740
#endif
741
742
#ifdef EPROTOTYPE
743
    ERRNO_CASE(EPROTOTYPE);
744
#endif
745
746
#ifdef ERANGE
747
    ERRNO_CASE(ERANGE);
748
#endif
749
750
#ifdef EROFS
751
    ERRNO_CASE(EROFS);
752
#endif
753
754
#ifdef ESPIPE
755
    ERRNO_CASE(ESPIPE);
756
#endif
757
758
#ifdef ESRCH
759
1
    ERRNO_CASE(ESRCH);
760
#endif
761
762
#ifdef ESTALE
763
    ERRNO_CASE(ESTALE);
764
#endif
765
766
#ifdef ETIME
767
    ERRNO_CASE(ETIME);
768
#endif
769
770
#ifdef ETIMEDOUT
771
    ERRNO_CASE(ETIMEDOUT);
772
#endif
773
774
#ifdef ETXTBSY
775
    ERRNO_CASE(ETXTBSY);
776
#endif
777
778
#ifdef EXDEV
779
    ERRNO_CASE(EXDEV);
780
#endif
781
782
    default:
783
      return "";
784
  }
785
}
786
787
1396
void PerIsolateMessageListener(Local<Message> message, Local<Value> error) {
788
1396
  Isolate* isolate = message->GetIsolate();
789
1396
  switch (message->ErrorLevel()) {
790
    case Isolate::MessageErrorLevel::kMessageWarning: {
791
1
      Environment* env = Environment::GetCurrent(isolate);
792
1
      if (!env) {
793
        break;
794
      }
795
3
      Utf8Value filename(isolate, message->GetScriptOrigin().ResourceName());
796
      // (filename):(line) (message)
797
2
      std::stringstream warning;
798
1
      warning << *filename;
799
1
      warning << ":";
800
3
      warning << message->GetLineNumber(env->context()).FromMaybe(-1);
801
1
      warning << " ";
802
3
      v8::String::Utf8Value msg(isolate, message->Get());
803
1
      warning << *msg;
804
1
      USE(ProcessEmitWarningGeneric(env, warning.str().c_str(), "V8"));
805
1
      break;
806
    }
807
    case Isolate::MessageErrorLevel::kMessageError:
808
1395
      TriggerUncaughtException(isolate, error, message);
809
1206
      break;
810
  }
811
1207
}
812
813
4716
void SetPrepareStackTraceCallback(const FunctionCallbackInfo<Value>& args) {
814
4716
  Environment* env = Environment::GetCurrent(args);
815
9432
  CHECK(args[0]->IsFunction());
816
9432
  env->set_prepare_stack_trace_callback(args[0].As<Function>());
817
4716
}
818
819
13
static void EnableSourceMaps(const FunctionCallbackInfo<Value>& args) {
820
13
  Environment* env = Environment::GetCurrent(args);
821
13
  env->set_source_maps_enabled(true);
822
13
}
823
824
4703
static void SetEnhanceStackForFatalException(
825
    const FunctionCallbackInfo<Value>& args) {
826
4703
  Environment* env = Environment::GetCurrent(args);
827
9406
  CHECK(args[0]->IsFunction());
828
9406
  CHECK(args[1]->IsFunction());
829
9406
  env->set_enhance_fatal_stack_before_inspector(args[0].As<Function>());
830
9406
  env->set_enhance_fatal_stack_after_inspector(args[1].As<Function>());
831
4703
}
832
833
// Side effect-free stringification that will never throw exceptions.
834
10
static void NoSideEffectsToString(const FunctionCallbackInfo<Value>& args) {
835
10
  Local<Context> context = args.GetIsolate()->GetCurrentContext();
836
  Local<String> detail_string;
837
30
  if (args[0]->ToDetailString(context).ToLocal(&detail_string))
838
20
    args.GetReturnValue().Set(detail_string);
839
10
}
840
841
23
static void TriggerUncaughtException(const FunctionCallbackInfo<Value>& args) {
842
23
  Isolate* isolate = args.GetIsolate();
843
23
  Environment* env = Environment::GetCurrent(isolate);
844
23
  Local<Value> exception = args[0];
845
23
  Local<Message> message = Exception::CreateMessage(isolate, exception);
846

23
  if (env != nullptr && env->abort_on_uncaught_exception()) {
847
    ReportFatalException(
848
        env, exception, message, EnhanceFatalException::kEnhance);
849
    Abort();
850
  }
851
46
  bool from_promise = args[1]->IsTrue();
852
23
  errors::TriggerUncaughtException(isolate, exception, message, from_promise);
853
4
}
854
855
4703
void Initialize(Local<Object> target,
856
                Local<Value> unused,
857
                Local<Context> context,
858
                void* priv) {
859
4703
  Environment* env = Environment::GetCurrent(context);
860
  env->SetMethod(
861
4703
      target, "setPrepareStackTraceCallback", SetPrepareStackTraceCallback);
862
4703
  env->SetMethod(target, "enableSourceMaps", EnableSourceMaps);
863
  env->SetMethod(target,
864
                 "setEnhanceStackForFatalException",
865
4703
                 SetEnhanceStackForFatalException);
866
  env->SetMethodNoSideEffect(
867
4703
      target, "noSideEffectsToString", NoSideEffectsToString);
868
4703
  env->SetMethod(target, "triggerUncaughtException", TriggerUncaughtException);
869
4703
}
870
871
286
void DecorateErrorStack(Environment* env,
872
                        const errors::TryCatchScope& try_catch) {
873
286
  Local<Value> exception = try_catch.Exception();
874
875
298
  if (!exception->IsObject()) return;
876
877
279
  Local<Object> err_obj = exception.As<Object>();
878
879
279
  if (IsExceptionDecorated(env, err_obj)) return;
880
881
276
  AppendExceptionLine(env, exception, try_catch.Message(), CONTEXTIFY_ERROR);
882
550
  TryCatchScope try_catch_scope(env);  // Ignore exceptions below.
883
828
  MaybeLocal<Value> stack = err_obj->Get(env->context(), env->stack_string());
884
  MaybeLocal<Value> maybe_value =
885
552
      err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol());
886
887
  Local<Value> arrow;
888

828
  if (!(maybe_value.ToLocal(&arrow) && arrow->IsString())) {
889
    return;
890
  }
891
892

1104
  if (stack.IsEmpty() || !stack.ToLocalChecked()->IsString()) {
893
2
    return;
894
  }
895
896
  Local<String> decorated_stack = String::Concat(
897
      env->isolate(),
898
      String::Concat(env->isolate(),
899
                     arrow.As<String>(),
900
                     FIXED_ONE_BYTE_STRING(env->isolate(), "\n")),
901
822
      stack.ToLocalChecked().As<String>());
902
822
  USE(err_obj->Set(env->context(), env->stack_string(), decorated_stack));
903
  err_obj->SetPrivate(
904
822
      env->context(), env->decorated_private_symbol(), True(env->isolate()));
905
}
906
907
1425
void TriggerUncaughtException(Isolate* isolate,
908
                              Local<Value> error,
909
                              Local<Message> message,
910
                              bool from_promise) {
911
1425
  CHECK(!error.IsEmpty());
912
1425
  HandleScope scope(isolate);
913
914
1425
  if (message.IsEmpty()) message = Exception::CreateMessage(isolate, error);
915
916
1425
  CHECK(isolate->InContext());
917
1425
  Local<Context> context = isolate->GetCurrentContext();
918
1425
  Environment* env = Environment::GetCurrent(context);
919
1425
  if (env == nullptr) {
920
    // This means that the exception happens before Environment is assigned
921
    // to the context e.g. when there is a SyntaxError in a per-context
922
    // script - which usually indicates that there is a bug because no JS
923
    // error is supposed to be thrown at this point.
924
    // Since we don't have access to Environment here, there is not
925
    // much we can do, so we just print whatever is useful and crash.
926
    PrintException(isolate, context, error, message);
927
    Abort();
928
  }
929
930
  // Invoke process._fatalException() to give user a chance to handle it.
931
  // We have to grab it from the process object since this has been
932
  // monkey-patchable.
933
1425
  Local<Object> process_object = env->process_object();
934
1425
  Local<String> fatal_exception_string = env->fatal_exception_string();
935
  Local<Value> fatal_exception_function =
936
2850
      process_object->Get(env->context(),
937
5700
                          fatal_exception_string).ToLocalChecked();
938
  // If the exception happens before process._fatalException is attached
939
  // during bootstrap, or if the user has patched it incorrectly, exit
940
  // the current Node.js instance.
941
1425
  if (!fatal_exception_function->IsFunction()) {
942
    ReportFatalException(
943
        env, error, message, EnhanceFatalException::kDontEnhance);
944
    env->Exit(6);
945
    return;
946
  }
947
948
  MaybeLocal<Value> handled;
949
1425
  if (env->can_call_into_js()) {
950
    // We do not expect the global uncaught exception itself to throw any more
951
    // exceptions. If it does, exit the current Node.js instance.
952
    errors::TryCatchScope try_catch(env,
953
2836
                                    errors::TryCatchScope::CatchMode::kFatal);
954
    // Explicitly disable verbose exception reporting -
955
    // if process._fatalException() throws an error, we don't want it to
956
    // trigger the per-isolate message listener which will call this
957
    // function and recurse.
958
1419
    try_catch.SetVerbose(false);
959
    Local<Value> argv[2] = { error,
960
2838
                             Boolean::New(env->isolate(), from_promise) };
961
962
2836
    handled = fatal_exception_function.As<Function>()->Call(
963
5674
        env->context(), process_object, arraysize(argv), argv);
964
  }
965
966
  // If process._fatalException() throws, we are now exiting the Node.js
967
  // instance so return to continue the exit routine.
968
  // TODO(joyeecheung): return a Maybe here to prevent the caller from
969
  // stepping on the exit.
970
1418
  if (handled.IsEmpty()) {
971
7
    return;
972
  }
973
974
  // The global uncaught exception handler returns true if the user handles it
975
  // by e.g. listening to `uncaughtException`. In that case, continue program
976
  // execution.
977
  // TODO(joyeecheung): This has been only checking that the return value is
978
  // exactly false. Investigate whether this can be turned to an "if true"
979
  // similar to how the worker global uncaught exception handler handles it.
980
2822
  if (!handled.ToLocalChecked()->IsFalse()) {
981
1208
    return;
982
  }
983
984
  // Now we are certain that the exception is fatal.
985
203
  ReportFatalException(env, error, message, EnhanceFatalException::kEnhance);
986
203
  RunAtExit(env);
987
988
  // If the global uncaught exception handler sets process.exitCode,
989
  // exit with that code. Otherwise, exit with 1.
990
203
  Local<String> exit_code = env->exit_code_string();
991
  Local<Value> code;
992

812
  if (process_object->Get(env->context(), exit_code).ToLocal(&code) &&
993
203
      code->IsInt32()) {
994
404
    env->Exit(code.As<Int32>()->Value());
995
  } else {
996
1
    env->Exit(1);
997
  }
998
}
999
1000
4
void TriggerUncaughtException(Isolate* isolate, const v8::TryCatch& try_catch) {
1001
  // If the try_catch is verbose, the per-isolate message listener is going to
1002
  // handle it (which is going to call into another overload of
1003
  // TriggerUncaughtException()).
1004
4
  if (try_catch.IsVerbose()) {
1005
    return;
1006
  }
1007
1008
  // If the user calls TryCatch::TerminateExecution() on this TryCatch
1009
  // they must call CancelTerminateExecution() again before invoking
1010
  // TriggerUncaughtException() because it will invoke
1011
  // process._fatalException() in the JS land.
1012
4
  CHECK(!try_catch.HasTerminated());
1013
4
  CHECK(try_catch.HasCaught());
1014
7
  HandleScope scope(isolate);
1015
4
  TriggerUncaughtException(isolate,
1016
                           try_catch.Exception(),
1017
                           try_catch.Message(),
1018
4
                           false /* from_promise */);
1019
}
1020
1021
}  // namespace errors
1022
1023
}  // namespace node
1024
1025

17595
NODE_MODULE_CONTEXT_AWARE_INTERNAL(errors, node::errors::Initialize)