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: 260 382 68.1 %
Date: 2019-10-06 22:30:00 Branches: 167 329 50.8 %

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

952
  if (!er.IsEmpty() && er->IsObject()) {
40
470
    Local<Object> err_obj = er.As<Object>();
41
    auto maybe_value =
42
940
        err_obj->GetPrivate(env->context(), env->decorated_private_symbol());
43
    Local<Value> decorated;
44

940
    return maybe_value.ToLocal(&decorated) && decorated->IsTrue();
45
  }
46
6
  return false;
47
}
48
49
namespace per_process {
50
5059
static Mutex tty_mutex;
51
}  // namespace per_process
52
53
static const int kMaxErrorSourceLength = 1024;
54
55
904
static std::string GetErrorSource(Isolate* isolate,
56
                                  Local<Context> context,
57
                                  Local<Message> message,
58
                                  bool* added_exception_line) {
59
904
  MaybeLocal<String> source_line_maybe = message->GetSourceLine(context);
60
904
  node::Utf8Value encoded_source(isolate, source_line_maybe.ToLocalChecked());
61
1808
  std::string sourceline(*encoded_source, encoded_source.length());
62
63
904
  if (sourceline.find("node-do-not-add-exception-line") != std::string::npos) {
64
10
    *added_exception_line = false;
65
10
    return sourceline;
66
  }
67
68
  // Because of how node modules work, all scripts are wrapped with a
69
  // "function (module, exports, __filename, ...) {"
70
  // to provide script local variables.
71
  //
72
  // When reporting errors on the first line of a script, this wrapper
73
  // function is leaked to the user. There used to be a hack here to
74
  // truncate off the first 62 characters, but it caused numerous other
75
  // problems when vm.runIn*Context() methods were used for non-module
76
  // code.
77
  //
78
  // If we ever decide to re-instate such a hack, the following steps
79
  // must be taken:
80
  //
81
  // 1. Pass a flag around to say "this code was wrapped"
82
  // 2. Update the stack frame output so that it is also correct.
83
  //
84
  // It would probably be simpler to add a line rather than add some
85
  // number of characters to the first line, since V8 truncates the
86
  // sourceline to 78 characters, and we end up not providing very much
87
  // useful debugging info to the user if we remove 62 characters.
88
89
  // Print (filename):(line number): (message).
90
894
  ScriptOrigin origin = message->GetScriptOrigin();
91
1788
  node::Utf8Value filename(isolate, message->GetScriptResourceName());
92
894
  const char* filename_string = *filename;
93
1788
  int linenum = message->GetLineNumber(context).FromJust();
94
95
3576
  int script_start = (linenum - origin.ResourceLineOffset()->Value()) == 1
96
1166
                         ? origin.ResourceColumnOffset()->Value()
97
1166
                         : 0;
98
2682
  int start = message->GetStartColumn(context).FromMaybe(0);
99
2682
  int end = message->GetEndColumn(context).FromMaybe(0);
100
894
  if (start >= script_start) {
101
894
    CHECK_GE(end, start);
102
894
    start -= script_start;
103
894
    end -= script_start;
104
  }
105
106
894
  int max_off = kMaxErrorSourceLength - 2;
107
108
  char buf[kMaxErrorSourceLength];
109
  int off = snprintf(buf,
110
                     kMaxErrorSourceLength,
111
                     "%s:%i\n%s\n",
112
                     filename_string,
113
                     linenum,
114
894
                     sourceline.c_str());
115
894
  CHECK_GE(off, 0);
116
894
  if (off > max_off) {
117
1
    off = max_off;
118
  }
119
120
  // Print wavy underline (GetUnderline is deprecated).
121
5078
  for (int i = 0; i < start; i++) {
122

4184
    if (sourceline[i] == '\0' || off >= max_off) {
123
      break;
124
    }
125
4184
    CHECK_LT(off, max_off);
126
4184
    buf[off++] = (sourceline[i] == '\t') ? '\t' : ' ';
127
  }
128
2363
  for (int i = start; i < end; i++) {
129

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

964
  if (!er.IsEmpty() && er->IsObject()) {
211
476
    err_obj = er.As<Object>();
212
  }
213
214
482
  bool added_exception_line = false;
215
  std::string source = GetErrorSource(
216
942
      env->isolate(), env->context(), message, &added_exception_line);
217
482
  if (!added_exception_line) {
218
10
    return;
219
  }
220
472
  MaybeLocal<Value> arrow_str = ToV8Value(env->context(), source);
221
222

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


644
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
229
12
    if (env->printed_error()) return;
230
12
    Mutex::ScopedLock lock(per_process::tty_mutex);
231
12
    env->set_printed_error(true);
232
233
12
    ResetStdio();
234
12
    PrintErrorString("\n%s", source.c_str());
235
12
    return;
236
  }
237
238

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

1820
      if (!enhancer.IsEmpty() &&
312
          enhancer
313
1820
              ->Call(env->context(), Undefined(isolate), arraysize(argv), argv)
314
1456
              .ToLocal(&enhanced)) {
315
362
        stack_trace = enhanced;
316
      }
317
546
    };
318
319
182
    switch (enhance_stack) {
320
      case EnhanceFatalException::kEnhance: {
321
182
        enhance_with(env->enhance_fatal_stack_before_inspector());
322
182
        report_to_inspector();
323
182
        enhance_with(env->enhance_fatal_stack_after_inspector());
324
182
        break;
325
      }
326
      case EnhanceFatalException::kDontEnhance: {
327
        USE(err_obj->Get(env->context(), env->stack_string())
328
                .ToLocal(&stack_trace));
329
        report_to_inspector();
330
        break;
331
      }
332
      default:
333
        UNREACHABLE();
334
    }
335
336
    arrow =
337
364
        err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol())
338
364
            .ToLocalChecked();
339
  }
340
341
188
  node::Utf8Value trace(env->isolate(), stack_trace);
342
343
  // range errors have a trace member set to undefined
344

562
  if (trace.length() > 0 && !stack_trace->IsUndefined()) {
345


543
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
346
64
      PrintErrorString("%s\n", *trace);
347
    } else {
348
117
      node::Utf8Value arrow_string(env->isolate(), arrow);
349
117
      PrintErrorString("%s\n%s\n", *arrow_string, *trace);
350
    }
351
  } else {
352
    // this really only happens for RangeErrors, since they're the only
353
    // kind that won't have all this info in the trace, or when non-Error
354
    // objects are thrown manually.
355
    MaybeLocal<Value> message;
356
    MaybeLocal<Value> name;
357
358
7
    if (error->IsObject()) {
359
1
      Local<Object> err_obj = error.As<Object>();
360
3
      message = err_obj->Get(env->context(), env->message_string());
361
3
      name = err_obj->Get(env->context(), env->name_string());
362
    }
363
364


24
    if (message.IsEmpty() || message.ToLocalChecked()->IsUndefined() ||
365

21
        name.IsEmpty() || name.ToLocalChecked()->IsUndefined()) {
366
      // Not an error object. Just print as-is.
367
7
      String::Utf8Value message(env->isolate(), error);
368
369
      PrintErrorString("%s\n",
370
7
                       *message ? *message : "<toString() threw exception>");
371
    } else {
372
      node::Utf8Value name_string(env->isolate(), name.ToLocalChecked());
373
      node::Utf8Value message_string(env->isolate(), message.ToLocalChecked());
374
375
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
376
        PrintErrorString("%s: %s\n", *name_string, *message_string);
377
      } else {
378
        node::Utf8Value arrow_string(env->isolate(), arrow);
379
        PrintErrorString(
380
            "%s\n%s: %s\n", *arrow_string, *name_string, *message_string);
381
      }
382
    }
383
  }
384
385
188
  fflush(stderr);
386
188
}
387
388
218
void PrintErrorString(const char* format, ...) {
389
  va_list ap;
390
218
  va_start(ap, format);
391
#ifdef _WIN32
392
  HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
393
394
  // Check if stderr is something other than a tty/console
395
  if (stderr_handle == INVALID_HANDLE_VALUE || stderr_handle == nullptr ||
396
      uv_guess_handle(_fileno(stderr)) != UV_TTY) {
397
    vfprintf(stderr, format, ap);
398
    va_end(ap);
399
    return;
400
  }
401
402
  // Fill in any placeholders
403
  int n = _vscprintf(format, ap);
404
  std::vector<char> out(n + 1);
405
  vsprintf(out.data(), format, ap);
406
407
  // Get required wide buffer size
408
  n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
409
410
  std::vector<wchar_t> wbuf(n);
411
  MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
412
413
  // Don't include the null character in the output
414
  CHECK_GT(n, 0);
415
  WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
416
#else
417
218
  vfprintf(stderr, format, ap);
418
#endif
419
218
  va_end(ap);
420
218
}
421
422
[[noreturn]] void FatalError(const char* location, const char* message) {
423
  OnFatalError(location, message);
424
  // to suppress compiler warning
425
  ABORT();
426
}
427
428
void OnFatalError(const char* location, const char* message) {
429
  if (location) {
430
    PrintErrorString("FATAL ERROR: %s %s\n", location, message);
431
  } else {
432
    PrintErrorString("FATAL ERROR: %s\n", message);
433
  }
434
#ifdef NODE_REPORT
435
  Isolate* isolate = Isolate::GetCurrent();
436
  Environment* env = Environment::GetCurrent(isolate);
437
  if (env == nullptr || env->isolate_data()->options()->report_on_fatalerror) {
438
    report::TriggerNodeReport(
439
        isolate, env, message, "FatalError", "", Local<String>());
440
  }
441
#endif  // NODE_REPORT
442
  fflush(stderr);
443
  ABORT();
444
}
445
446
namespace errors {
447
448
465664
TryCatchScope::~TryCatchScope() {
449


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



















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

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

855
  if (!(maybe_value.ToLocal(&arrow) && arrow->IsString())) {
886
    return;
887
  }
888
889


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


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

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