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: 197 320 61.6 %
Date: 2019-05-05 22:32:45 Branches: 161 300 53.7 %

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
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::HandleScope;
20
using v8::Int32;
21
using v8::Isolate;
22
using v8::Just;
23
using v8::Local;
24
using v8::Maybe;
25
using v8::MaybeLocal;
26
using v8::Message;
27
using v8::Number;
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
430
bool IsExceptionDecorated(Environment* env, Local<Value> er) {
37

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

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

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

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

870
  if (!er.IsEmpty() && er->IsObject()) {
208
429
    err_obj = er.As<Object>();
209
  }
210
211
435
  bool added_exception_line = false;
212
  std::string source = GetErrorSource(
213
840
      env->isolate(), env->context(), message, &added_exception_line);
214
435
  if (!added_exception_line) {
215
18
    return;
216
  }
217
417
  MaybeLocal<Value> arrow_str = ToV8Value(env->context(), source);
218
219

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


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

1620
  CHECK(err_obj
236
            ->SetPrivate(env->context(),
237
                         env->arrow_message_private_symbol(),
238
                         arrow_str.ToLocalChecked())
239
405
            .FromMaybe(false));
240
}
241
242
[[noreturn]] void Abort() {
243
  DumpBacktrace(stderr);
244
  fflush(stderr);
245
  ABORT_NO_BACKTRACE();
246
}
247
248
[[noreturn]] void Assert(const AssertionInfo& info) {
249
  char name[1024];
250
  GetHumanReadableProcessName(&name);
251
252
  fprintf(stderr,
253
          "%s: %s:%s%s Assertion `%s' failed.\n",
254
          name,
255
          info.file_line,
256
          info.function,
257
          *info.function ? ":" : "",
258
          info.message);
259
  fflush(stderr);
260
261
  Abort();
262
}
263
264
160
void ReportException(Environment* env,
265
                     Local<Value> er,
266
                     Local<Message> message) {
267
160
  CHECK(!er.IsEmpty());
268
160
  HandleScope scope(env->isolate());
269
270
160
  if (message.IsEmpty()) message = Exception::CreateMessage(env->isolate(), er);
271
272
160
  AppendExceptionLine(env, er, message, FATAL_ERROR);
273
274
  Local<Value> trace_value;
275
  Local<Value> arrow;
276
160
  const bool decorated = IsExceptionDecorated(env, er);
277
278

638
  if (er->IsUndefined() || er->IsNull()) {
279
4
    trace_value = Undefined(env->isolate());
280
  } else {
281
474
    Local<Object> err_obj = er->ToObject(env->context()).ToLocalChecked();
282
283
790
    if (!err_obj->Get(env->context(), env->stack_string())
284
474
             .ToLocal(&trace_value)) {
285
2
      trace_value = Undefined(env->isolate());
286
    }
287
    arrow =
288
316
        err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol())
289
316
            .ToLocalChecked();
290
  }
291
292
320
  node::Utf8Value trace(env->isolate(), trace_value);
293
294
  // range errors have a trace member set to undefined
295

480
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
296


447
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
297
52
      PrintErrorString("%s\n", *trace);
298
    } else {
299
97
      node::Utf8Value arrow_string(env->isolate(), arrow);
300
97
      PrintErrorString("%s\n%s\n", *arrow_string, *trace);
301
    }
302
  } else {
303
    // this really only happens for RangeErrors, since they're the only
304
    // kind that won't have all this info in the trace, or when non-Error
305
    // objects are thrown manually.
306
    MaybeLocal<Value> message;
307
    MaybeLocal<Value> name;
308
309
11
    if (er->IsObject()) {
310
5
      Local<Object> err_obj = er.As<Object>();
311
15
      message = err_obj->Get(env->context(), env->message_string());
312
15
      name = err_obj->Get(env->context(), env->name_string());
313
    }
314
315


49
    if (message.IsEmpty() || message.ToLocalChecked()->IsUndefined() ||
316

37
        name.IsEmpty() || name.ToLocalChecked()->IsUndefined()) {
317
      // Not an error object. Just print as-is.
318
10
      String::Utf8Value message(env->isolate(), er);
319
320
      PrintErrorString("%s\n",
321
10
                       *message ? *message : "<toString() threw exception>");
322
    } else {
323
1
      node::Utf8Value name_string(env->isolate(), name.ToLocalChecked());
324
2
      node::Utf8Value message_string(env->isolate(), message.ToLocalChecked());
325
326


3
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
327
1
        PrintErrorString("%s: %s\n", *name_string, *message_string);
328
      } else {
329
        node::Utf8Value arrow_string(env->isolate(), arrow);
330
        PrintErrorString(
331
            "%s\n%s: %s\n", *arrow_string, *name_string, *message_string);
332
1
      }
333
    }
334
  }
335
336
160
  fflush(stderr);
337
338
#if HAVE_INSPECTOR
339
320
  env->inspector_agent()->FatalException(er, message);
340
#endif
341
160
}
342
343
3
void ReportException(Environment* env, const v8::TryCatch& try_catch) {
344
3
  ReportException(env, try_catch.Exception(), try_catch.Message());
345
3
}
346
347
184
void PrintErrorString(const char* format, ...) {
348
  va_list ap;
349
184
  va_start(ap, format);
350
#ifdef _WIN32
351
  HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
352
353
  // Check if stderr is something other than a tty/console
354
  if (stderr_handle == INVALID_HANDLE_VALUE || stderr_handle == nullptr ||
355
      uv_guess_handle(_fileno(stderr)) != UV_TTY) {
356
    vfprintf(stderr, format, ap);
357
    va_end(ap);
358
    return;
359
  }
360
361
  // Fill in any placeholders
362
  int n = _vscprintf(format, ap);
363
  std::vector<char> out(n + 1);
364
  vsprintf(out.data(), format, ap);
365
366
  // Get required wide buffer size
367
  n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
368
369
  std::vector<wchar_t> wbuf(n);
370
  MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
371
372
  // Don't include the null character in the output
373
  CHECK_GT(n, 0);
374
  WriteConsoleW(stderr_handle, wbuf.data(), n - 1, nullptr, nullptr);
375
#else
376
184
  vfprintf(stderr, format, ap);
377
#endif
378
184
  va_end(ap);
379
184
}
380
381
[[noreturn]] void FatalError(const char* location, const char* message) {
382
  OnFatalError(location, message);
383
  // to suppress compiler warning
384
  ABORT();
385
}
386
387
void OnFatalError(const char* location, const char* message) {
388
  if (location) {
389
    PrintErrorString("FATAL ERROR: %s %s\n", location, message);
390
  } else {
391
    PrintErrorString("FATAL ERROR: %s\n", message);
392
  }
393
#ifdef NODE_REPORT
394
  Isolate* isolate = Isolate::GetCurrent();
395
  Environment* env = Environment::GetCurrent(isolate);
396
  if (env == nullptr || env->isolate_data()->options()->report_on_fatalerror) {
397
    report::TriggerNodeReport(
398
        isolate, env, message, "FatalError", "", Local<String>());
399
  }
400
#endif  // NODE_REPORT
401
  fflush(stderr);
402
  ABORT();
403
}
404
405
namespace errors {
406
407
308436
TryCatchScope::~TryCatchScope() {
408


154218
  if (HasCaught() && !HasTerminated() && mode_ == CatchMode::kFatal) {
409
    HandleScope scope(env_->isolate());
410
    ReportException(env_, Exception(), Message());
411
    env_->Exit(7);
412
  }
413
154217
}
414
415
4
const char* errno_string(int errorno) {
416
#define ERRNO_CASE(e)                                                          \
417
  case e:                                                                      \
418
    return #e;
419



















4
  switch (errorno) {
420
#ifdef EACCES
421
    ERRNO_CASE(EACCES);
422
#endif
423
424
#ifdef EADDRINUSE
425
    ERRNO_CASE(EADDRINUSE);
426
#endif
427
428
#ifdef EADDRNOTAVAIL
429
    ERRNO_CASE(EADDRNOTAVAIL);
430
#endif
431
432
#ifdef EAFNOSUPPORT
433
    ERRNO_CASE(EAFNOSUPPORT);
434
#endif
435
436
#ifdef EAGAIN
437
    ERRNO_CASE(EAGAIN);
438
#endif
439
440
#ifdef EWOULDBLOCK
441
#if EAGAIN != EWOULDBLOCK
442
    ERRNO_CASE(EWOULDBLOCK);
443
#endif
444
#endif
445
446
#ifdef EALREADY
447
    ERRNO_CASE(EALREADY);
448
#endif
449
450
#ifdef EBADF
451
    ERRNO_CASE(EBADF);
452
#endif
453
454
#ifdef EBADMSG
455
    ERRNO_CASE(EBADMSG);
456
#endif
457
458
#ifdef EBUSY
459
    ERRNO_CASE(EBUSY);
460
#endif
461
462
#ifdef ECANCELED
463
    ERRNO_CASE(ECANCELED);
464
#endif
465
466
#ifdef ECHILD
467
1
    ERRNO_CASE(ECHILD);
468
#endif
469
470
#ifdef ECONNABORTED
471
    ERRNO_CASE(ECONNABORTED);
472
#endif
473
474
#ifdef ECONNREFUSED
475
    ERRNO_CASE(ECONNREFUSED);
476
#endif
477
478
#ifdef ECONNRESET
479
    ERRNO_CASE(ECONNRESET);
480
#endif
481
482
#ifdef EDEADLK
483
    ERRNO_CASE(EDEADLK);
484
#endif
485
486
#ifdef EDESTADDRREQ
487
    ERRNO_CASE(EDESTADDRREQ);
488
#endif
489
490
#ifdef EDOM
491
    ERRNO_CASE(EDOM);
492
#endif
493
494
#ifdef EDQUOT
495
    ERRNO_CASE(EDQUOT);
496
#endif
497
498
#ifdef EEXIST
499
    ERRNO_CASE(EEXIST);
500
#endif
501
502
#ifdef EFAULT
503
    ERRNO_CASE(EFAULT);
504
#endif
505
506
#ifdef EFBIG
507
    ERRNO_CASE(EFBIG);
508
#endif
509
510
#ifdef EHOSTUNREACH
511
    ERRNO_CASE(EHOSTUNREACH);
512
#endif
513
514
#ifdef EIDRM
515
    ERRNO_CASE(EIDRM);
516
#endif
517
518
#ifdef EILSEQ
519
    ERRNO_CASE(EILSEQ);
520
#endif
521
522
#ifdef EINPROGRESS
523
    ERRNO_CASE(EINPROGRESS);
524
#endif
525
526
#ifdef EINTR
527
    ERRNO_CASE(EINTR);
528
#endif
529
530
#ifdef EINVAL
531
    ERRNO_CASE(EINVAL);
532
#endif
533
534
#ifdef EIO
535
    ERRNO_CASE(EIO);
536
#endif
537
538
#ifdef EISCONN
539
    ERRNO_CASE(EISCONN);
540
#endif
541
542
#ifdef EISDIR
543
    ERRNO_CASE(EISDIR);
544
#endif
545
546
#ifdef ELOOP
547
    ERRNO_CASE(ELOOP);
548
#endif
549
550
#ifdef EMFILE
551
    ERRNO_CASE(EMFILE);
552
#endif
553
554
#ifdef EMLINK
555
    ERRNO_CASE(EMLINK);
556
#endif
557
558
#ifdef EMSGSIZE
559
    ERRNO_CASE(EMSGSIZE);
560
#endif
561
562
#ifdef EMULTIHOP
563
    ERRNO_CASE(EMULTIHOP);
564
#endif
565
566
#ifdef ENAMETOOLONG
567
    ERRNO_CASE(ENAMETOOLONG);
568
#endif
569
570
#ifdef ENETDOWN
571
    ERRNO_CASE(ENETDOWN);
572
#endif
573
574
#ifdef ENETRESET
575
    ERRNO_CASE(ENETRESET);
576
#endif
577
578
#ifdef ENETUNREACH
579
    ERRNO_CASE(ENETUNREACH);
580
#endif
581
582
#ifdef ENFILE
583
    ERRNO_CASE(ENFILE);
584
#endif
585
586
#ifdef ENOBUFS
587
    ERRNO_CASE(ENOBUFS);
588
#endif
589
590
#ifdef ENODATA
591
    ERRNO_CASE(ENODATA);
592
#endif
593
594
#ifdef ENODEV
595
    ERRNO_CASE(ENODEV);
596
#endif
597
598
#ifdef ENOENT
599
    ERRNO_CASE(ENOENT);
600
#endif
601
602
#ifdef ENOEXEC
603
    ERRNO_CASE(ENOEXEC);
604
#endif
605
606
#ifdef ENOLINK
607
    ERRNO_CASE(ENOLINK);
608
#endif
609
610
#ifdef ENOLCK
611
#if ENOLINK != ENOLCK
612
    ERRNO_CASE(ENOLCK);
613
#endif
614
#endif
615
616
#ifdef ENOMEM
617
    ERRNO_CASE(ENOMEM);
618
#endif
619
620
#ifdef ENOMSG
621
    ERRNO_CASE(ENOMSG);
622
#endif
623
624
#ifdef ENOPROTOOPT
625
    ERRNO_CASE(ENOPROTOOPT);
626
#endif
627
628
#ifdef ENOSPC
629
    ERRNO_CASE(ENOSPC);
630
#endif
631
632
#ifdef ENOSR
633
    ERRNO_CASE(ENOSR);
634
#endif
635
636
#ifdef ENOSTR
637
    ERRNO_CASE(ENOSTR);
638
#endif
639
640
#ifdef ENOSYS
641
    ERRNO_CASE(ENOSYS);
642
#endif
643
644
#ifdef ENOTCONN
645
    ERRNO_CASE(ENOTCONN);
646
#endif
647
648
#ifdef ENOTDIR
649
    ERRNO_CASE(ENOTDIR);
650
#endif
651
652
#ifdef ENOTEMPTY
653
#if ENOTEMPTY != EEXIST
654
    ERRNO_CASE(ENOTEMPTY);
655
#endif
656
#endif
657
658
#ifdef ENOTSOCK
659
    ERRNO_CASE(ENOTSOCK);
660
#endif
661
662
#ifdef ENOTSUP
663
    ERRNO_CASE(ENOTSUP);
664
#else
665
#ifdef EOPNOTSUPP
666
    ERRNO_CASE(EOPNOTSUPP);
667
#endif
668
#endif
669
670
#ifdef ENOTTY
671
    ERRNO_CASE(ENOTTY);
672
#endif
673
674
#ifdef ENXIO
675
    ERRNO_CASE(ENXIO);
676
#endif
677
678
#ifdef EOVERFLOW
679
    ERRNO_CASE(EOVERFLOW);
680
#endif
681
682
#ifdef EPERM
683
2
    ERRNO_CASE(EPERM);
684
#endif
685
686
#ifdef EPIPE
687
    ERRNO_CASE(EPIPE);
688
#endif
689
690
#ifdef EPROTO
691
    ERRNO_CASE(EPROTO);
692
#endif
693
694
#ifdef EPROTONOSUPPORT
695
    ERRNO_CASE(EPROTONOSUPPORT);
696
#endif
697
698
#ifdef EPROTOTYPE
699
    ERRNO_CASE(EPROTOTYPE);
700
#endif
701
702
#ifdef ERANGE
703
    ERRNO_CASE(ERANGE);
704
#endif
705
706
#ifdef EROFS
707
    ERRNO_CASE(EROFS);
708
#endif
709
710
#ifdef ESPIPE
711
    ERRNO_CASE(ESPIPE);
712
#endif
713
714
#ifdef ESRCH
715
1
    ERRNO_CASE(ESRCH);
716
#endif
717
718
#ifdef ESTALE
719
    ERRNO_CASE(ESTALE);
720
#endif
721
722
#ifdef ETIME
723
    ERRNO_CASE(ETIME);
724
#endif
725
726
#ifdef ETIMEDOUT
727
    ERRNO_CASE(ETIMEDOUT);
728
#endif
729
730
#ifdef ETXTBSY
731
    ERRNO_CASE(ETXTBSY);
732
#endif
733
734
#ifdef EXDEV
735
    ERRNO_CASE(EXDEV);
736
#endif
737
738
    default:
739
      return "";
740
  }
741
}
742
743
1322
void PerIsolateMessageListener(Local<Message> message, Local<Value> error) {
744
1322
  Isolate* isolate = message->GetIsolate();
745
1322
  switch (message->ErrorLevel()) {
746
    case Isolate::MessageErrorLevel::kMessageWarning: {
747
1
      Environment* env = Environment::GetCurrent(isolate);
748
1
      if (!env) {
749
        break;
750
      }
751
2
      Utf8Value filename(isolate, message->GetScriptOrigin().ResourceName());
752
      // (filename):(line) (message)
753
2
      std::stringstream warning;
754
1
      warning << *filename;
755
1
      warning << ":";
756
3
      warning << message->GetLineNumber(env->context()).FromMaybe(-1);
757
1
      warning << " ";
758
3
      v8::String::Utf8Value msg(isolate, message->Get());
759
1
      warning << *msg;
760
1
      USE(ProcessEmitWarningGeneric(env, warning.str().c_str(), "V8"));
761
2
      break;
762
    }
763
    case Isolate::MessageErrorLevel::kMessageError:
764
1321
      FatalException(isolate, error, message);
765
1176
      break;
766
  }
767
1177
}
768
769
}  // namespace errors
770
771
280
void DecorateErrorStack(Environment* env,
772
                        const errors::TryCatchScope& try_catch) {
773
280
  Local<Value> exception = try_catch.Exception();
774
775
295
  if (!exception->IsObject()) return;
776
777
270
  Local<Object> err_obj = exception.As<Object>();
778
779
270
  if (IsExceptionDecorated(env, err_obj)) return;
780
781
267
  AppendExceptionLine(env, exception, try_catch.Message(), CONTEXTIFY_ERROR);
782
267
  TryCatchScope try_catch_scope(env);  // Ignore exceptions below.
783
801
  MaybeLocal<Value> stack = err_obj->Get(env->context(), env->stack_string());
784
  MaybeLocal<Value> maybe_value =
785
534
      err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol());
786
787
  Local<Value> arrow;
788

801
  if (!(maybe_value.ToLocal(&arrow) && arrow->IsString())) {
789
    return;
790
  }
791
792


1335
  if (stack.IsEmpty() || !stack.ToLocalChecked()->IsString()) {
793
2
    return;
794
  }
795
796
  Local<String> decorated_stack = String::Concat(
797
      env->isolate(),
798
      String::Concat(env->isolate(),
799
                     arrow.As<String>(),
800
                     FIXED_ONE_BYTE_STRING(env->isolate(), "\n")),
801
795
      stack.ToLocalChecked().As<String>());
802
795
  USE(err_obj->Set(env->context(), env->stack_string(), decorated_stack));
803
  err_obj->SetPrivate(
804
795
      env->context(), env->decorated_private_symbol(), True(env->isolate()));
805
}
806
807
1347
void FatalException(Isolate* isolate,
808
                    Local<Value> error,
809
                    Local<Message> message,
810
                    bool from_promise) {
811
1347
  CHECK(!error.IsEmpty());
812
1347
  HandleScope scope(isolate);
813
814
1347
  CHECK(isolate->InContext());
815
1347
  Local<Context> context = isolate->GetCurrentContext();
816
1347
  Environment* env = Environment::GetCurrent(context);
817
1347
  if (env == nullptr) {
818
    // This means that the exception happens before Environment is assigned
819
    // to the context e.g. when there is a SyntaxError in a per-context
820
    // script - which usually indicates that there is a bug because no JS
821
    // error is supposed to be thrown at this point.
822
    // Since we don't have access to Environment here, there is not
823
    // much we can do, so we just print whatever is useful and crash.
824
    PrintException(isolate, context, error, message);
825
    Abort();
826
  }
827
828
1347
  Local<Object> process_object = env->process_object();
829
1347
  Local<String> fatal_exception_string = env->fatal_exception_string();
830
  Local<Value> fatal_exception_function =
831
      process_object->Get(env->context(),
832
4041
                          fatal_exception_string).ToLocalChecked();
833
834
1347
  if (!fatal_exception_function->IsFunction()) {
835
    // Failed before the process._fatalException function was added!
836
    // this is probably pretty bad.  Nothing to do but report and exit.
837
    ReportException(env, error, message);
838
    env->Exit(6);
839
  } else {
840
1347
    errors::TryCatchScope fatal_try_catch(env);
841
842
    // Do not call FatalException when _fatalException handler throws
843
1347
    fatal_try_catch.SetVerbose(false);
844
845
    Local<Value> argv[2] = { error,
846
2694
                             Boolean::New(env->isolate(), from_promise) };
847
848
    // This will return true if the JS layer handled it, false otherwise
849
    MaybeLocal<Value> caught = fatal_exception_function.As<Function>()->Call(
850
5388
        env->context(), process_object, arraysize(argv), argv);
851
852
2530
    if (fatal_try_catch.HasTerminated()) return;
853
854
1344
    if (fatal_try_catch.HasCaught()) {
855
      // The fatal exception function threw, so we must exit
856
3
      ReportException(env, fatal_try_catch);
857
3
      env->Exit(7);
858
859
2682
    } else if (caught.ToLocalChecked()->IsFalse()) {
860
157
      ReportException(env, error, message);
861
862
      // fatal_exception_function call before may have set a new exit code ->
863
      // read it again, otherwise use default for uncaughtException 1
864
157
      Local<String> exit_code = env->exit_code_string();
865
      Local<Value> code;
866


785
      if (!process_object->Get(env->context(), exit_code).ToLocal(&code) ||
867
157
          !code->IsInt32()) {
868
1
        env->Exit(1);
869
      }
870
312
      env->Exit(code.As<Int32>()->Value());
871
1184
    }
872
1184
  }
873
}
874
875
1327
void FatalException(Isolate* isolate,
876
                    Local<Value> error,
877
                    Local<Message> message) {
878
1327
  FatalException(isolate, error, message, false /* from_promise */);
879
1180
}
880
881

13575
}  // namespace node