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: 262 391 67.0 %
Date: 2020-02-27 22:14:15 Branches: 162 323 50.2 %

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

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

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

4402
    if (sourceline[i] == '\0' || off >= kUnderlineBufsize) {
117
      break;
118
    }
119
4402
    CHECK_LT(off, kUnderlineBufsize);
120
4402
    underline_buf[off++] = (sourceline[i] == '\t') ? '\t' : ' ';
121
  }
122
3459
  for (int i = start; i < end; i++) {
123

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

944
  if (!er.IsEmpty() && er->IsObject()) {
204
464
    err_obj = er.As<Object>();
205
  }
206
207
472
  bool added_exception_line = false;
208
  std::string source = GetErrorSource(
209
919
      env->isolate(), env->context(), message, &added_exception_line);
210
472
  if (!added_exception_line) {
211
11
    return;
212
  }
213
461
  MaybeLocal<Value> arrow_str = ToV8Value(env->context(), source);
214
215

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


641
  if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
222
14
    if (env->printed_error()) return;
223
28
    Mutex::ScopedLock lock(per_process::tty_mutex);
224
14
    env->set_printed_error(true);
225
226
14
    ResetStdio();
227
14
    FPrintF(stderr, "\n%s", source);
228
14
    return;
229
  }
230
231

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

1146
      if (!enhancer.IsEmpty() &&
307
          enhancer
308
1528
              ->Call(env->context(), Undefined(isolate), arraysize(argv), argv)
309
382
              .ToLocal(&enhanced)) {
310
378
        stack_trace = enhanced;
311
      }
312
573
    };
313
314
191
    switch (enhance_stack) {
315
      case EnhanceFatalException::kEnhance: {
316
191
        enhance_with(env->enhance_fatal_stack_before_inspector());
317
191
        report_to_inspector();
318
191
        enhance_with(env->enhance_fatal_stack_after_inspector());
319
191
        break;
320
      }
321
      case EnhanceFatalException::kDontEnhance: {
322
        USE(err_obj->Get(env->context(), env->stack_string())
323
                .ToLocal(&stack_trace));
324
        report_to_inspector();
325
        break;
326
      }
327
      default:
328
        UNREACHABLE();
329
    }
330
331
    arrow =
332
573
        err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol())
333
191
            .ToLocalChecked();
334
  }
335
336
398
  node::Utf8Value trace(env->isolate(), stack_trace);
337
338
  // range errors have a trace member set to undefined
339

593
  if (trace.length() > 0 && !stack_trace->IsUndefined()) {
340


567
    if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
341
63
      FPrintF(stderr, "%s\n", trace);
342
    } else {
343
252
      node::Utf8Value arrow_string(env->isolate(), arrow);
344
126
      FPrintF(stderr, "%s\n%s\n", arrow_string, trace);
345
    }
346
  } else {
347
    // this really only happens for RangeErrors, since they're the only
348
    // kind that won't have all this info in the trace, or when non-Error
349
    // objects are thrown manually.
350
    MaybeLocal<Value> message;
351
    MaybeLocal<Value> name;
352
353
10
    if (error->IsObject()) {
354
2
      Local<Object> err_obj = error.As<Object>();
355
6
      message = err_obj->Get(env->context(), env->message_string());
356
6
      name = err_obj->Get(env->context(), env->name_string());
357
    }
358
359

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

20
        name.IsEmpty() || name.ToLocalChecked()->IsUndefined()) {
361
      // Not an error object. Just print as-is.
362
20
      node::Utf8Value message(env->isolate(), error);
363
364
      FPrintF(stderr, "%s\n",
365

10
              *message ? message.ToString() : "<toString() threw exception>");
366
    } else {
367
      node::Utf8Value name_string(env->isolate(), name.ToLocalChecked());
368
      node::Utf8Value message_string(env->isolate(), message.ToLocalChecked());
369
370
      if (arrow.IsEmpty() || !arrow->IsString() || decorated) {
371
        FPrintF(stderr, "%s: %s\n", name_string, message_string);
372
      } else {
373
        node::Utf8Value arrow_string(env->isolate(), arrow);
374
        FPrintF(stderr,
375
            "%s\n%s: %s\n", arrow_string, name_string, message_string);
376
      }
377
    }
378
379
10
    if (!env->options()->trace_uncaught) {
380
      FPrintF(stderr, "(Use `node --trace-uncaught ...` to show "
381
7
                      "where the exception was thrown)\n");
382
    }
383
  }
384
385
199
  if (env->options()->trace_uncaught) {
386
3
    Local<StackTrace> trace = message->GetStackTrace();
387
3
    if (!trace.IsEmpty()) {
388
3
      FPrintF(stderr, "Thrown at:\n");
389
3
      PrintStackTrace(env->isolate(), trace);
390
    }
391
  }
392
393
199
  fflush(stderr);
394
199
}
395
396
[[noreturn]] void FatalError(const char* location, const char* message) {
397
  OnFatalError(location, message);
398
  // to suppress compiler warning
399
  ABORT();
400
}
401
402
void OnFatalError(const char* location, const char* message) {
403
  if (location) {
404
    FPrintF(stderr, "FATAL ERROR: %s %s\n", location, message);
405
  } else {
406
    FPrintF(stderr, "FATAL ERROR: %s\n", message);
407
  }
408
#ifdef NODE_REPORT
409
  Isolate* isolate = Isolate::GetCurrent();
410
  Environment* env = Environment::GetCurrent(isolate);
411
  if (env == nullptr || env->isolate_data()->options()->report_on_fatalerror) {
412
    report::TriggerNodeReport(
413
        isolate, env, message, "FatalError", "", Local<String>());
414
  }
415
#endif  // NODE_REPORT
416
  fflush(stderr);
417
  ABORT();
418
}
419
420
namespace errors {
421
422
1392075
TryCatchScope::~TryCatchScope() {
423


696039
  if (HasCaught() && !HasTerminated() && mode_ == CatchMode::kFatal) {
424
5
    HandleScope scope(env_->isolate());
425
5
    Local<v8::Value> exception = Exception();
426
5
    Local<v8::Message> message = Message();
427
5
    EnhanceFatalException enhance = CanContinue() ?
428
5
        EnhanceFatalException::kEnhance : EnhanceFatalException::kDontEnhance;
429
5
    if (message.IsEmpty())
430
      message = Exception::CreateMessage(env_->isolate(), exception);
431
5
    ReportFatalException(env_, exception, message, enhance);
432
5
    env_->Exit(7);
433
  }
434
696032
}
435
436
4
const char* errno_string(int errorno) {
437
#define ERRNO_CASE(e)                                                          \
438
  case e:                                                                      \
439
    return #e;
440



















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

22
  if (env != nullptr && env->abort_on_uncaught_exception()) {
819
    ReportFatalException(
820
        env, exception, message, EnhanceFatalException::kEnhance);
821
    Abort();
822
  }
823
44
  bool from_promise = args[1]->IsTrue();
824
22
  errors::TriggerUncaughtException(isolate, exception, message, from_promise);
825
5
}
826
827
4392
void Initialize(Local<Object> target,
828
                Local<Value> unused,
829
                Local<Context> context,
830
                void* priv) {
831
4392
  Environment* env = Environment::GetCurrent(context);
832
  env->SetMethod(
833
4392
      target, "setPrepareStackTraceCallback", SetPrepareStackTraceCallback);
834
  env->SetMethod(target,
835
                 "setEnhanceStackForFatalException",
836
4392
                 SetEnhanceStackForFatalException);
837
  env->SetMethodNoSideEffect(
838
4392
      target, "noSideEffectsToString", NoSideEffectsToString);
839
4392
  env->SetMethod(target, "triggerUncaughtException", TriggerUncaughtException);
840
4392
}
841
842
272
void DecorateErrorStack(Environment* env,
843
                        const errors::TryCatchScope& try_catch) {
844
272
  Local<Value> exception = try_catch.Exception();
845
846
283
  if (!exception->IsObject()) return;
847
848
266
  Local<Object> err_obj = exception.As<Object>();
849
850
266
  if (IsExceptionDecorated(env, err_obj)) return;
851
852
263
  AppendExceptionLine(env, exception, try_catch.Message(), CONTEXTIFY_ERROR);
853
524
  TryCatchScope try_catch_scope(env);  // Ignore exceptions below.
854
789
  MaybeLocal<Value> stack = err_obj->Get(env->context(), env->stack_string());
855
  MaybeLocal<Value> maybe_value =
856
526
      err_obj->GetPrivate(env->context(), env->arrow_message_private_symbol());
857
858
  Local<Value> arrow;
859

789
  if (!(maybe_value.ToLocal(&arrow) && arrow->IsString())) {
860
    return;
861
  }
862
863

1052
  if (stack.IsEmpty() || !stack.ToLocalChecked()->IsString()) {
864
2
    return;
865
  }
866
867
  Local<String> decorated_stack = String::Concat(
868
      env->isolate(),
869
      String::Concat(env->isolate(),
870
                     arrow.As<String>(),
871
                     FIXED_ONE_BYTE_STRING(env->isolate(), "\n")),
872
783
      stack.ToLocalChecked().As<String>());
873
783
  USE(err_obj->Set(env->context(), env->stack_string(), decorated_stack));
874
  err_obj->SetPrivate(
875
783
      env->context(), env->decorated_private_symbol(), True(env->isolate()));
876
}
877
878
1406
void TriggerUncaughtException(Isolate* isolate,
879
                              Local<Value> error,
880
                              Local<Message> message,
881
                              bool from_promise) {
882
1406
  CHECK(!error.IsEmpty());
883
1406
  HandleScope scope(isolate);
884
885
1406
  if (message.IsEmpty()) message = Exception::CreateMessage(isolate, error);
886
887
1406
  CHECK(isolate->InContext());
888
1406
  Local<Context> context = isolate->GetCurrentContext();
889
1406
  Environment* env = Environment::GetCurrent(context);
890
1406
  if (env == nullptr) {
891
    // This means that the exception happens before Environment is assigned
892
    // to the context e.g. when there is a SyntaxError in a per-context
893
    // script - which usually indicates that there is a bug because no JS
894
    // error is supposed to be thrown at this point.
895
    // Since we don't have access to Environment here, there is not
896
    // much we can do, so we just print whatever is useful and crash.
897
    PrintException(isolate, context, error, message);
898
    Abort();
899
  }
900
901
  // Invoke process._fatalException() to give user a chance to handle it.
902
  // We have to grab it from the process object since this has been
903
  // monkey-patchable.
904
1406
  Local<Object> process_object = env->process_object();
905
1406
  Local<String> fatal_exception_string = env->fatal_exception_string();
906
  Local<Value> fatal_exception_function =
907
2812
      process_object->Get(env->context(),
908
5624
                          fatal_exception_string).ToLocalChecked();
909
  // If the exception happens before process._fatalException is attached
910
  // during bootstrap, or if the user has patched it incorrectly, exit
911
  // the current Node.js instance.
912
1406
  if (!fatal_exception_function->IsFunction()) {
913
    ReportFatalException(
914
        env, error, message, EnhanceFatalException::kDontEnhance);
915
    env->Exit(6);
916
    return;
917
  }
918
919
  MaybeLocal<Value> handled;
920
1406
  if (env->can_call_into_js()) {
921
    // We do not expect the global uncaught exception itself to throw any more
922
    // exceptions. If it does, exit the current Node.js instance.
923
    errors::TryCatchScope try_catch(env,
924
2810
                                    errors::TryCatchScope::CatchMode::kFatal);
925
    // Explicitly disable verbose exception reporting -
926
    // if process._fatalException() throws an error, we don't want it to
927
    // trigger the per-isolate message listener which will call this
928
    // function and recurse.
929
1406
    try_catch.SetVerbose(false);
930
    Local<Value> argv[2] = { error,
931
2812
                             Boolean::New(env->isolate(), from_promise) };
932
933
2810
    handled = fatal_exception_function.As<Function>()->Call(
934
5622
        env->context(), process_object, arraysize(argv), argv);
935
  }
936
937
  // If process._fatalException() throws, we are now exiting the Node.js
938
  // instance so return to continue the exit routine.
939
  // TODO(joyeecheung): return a Maybe here to prevent the caller from
940
  // stepping on the exit.
941
1399
  if (handled.IsEmpty()) {
942
1
    return;
943
  }
944
945
  // The global uncaught exception handler returns true if the user handles it
946
  // by e.g. listening to `uncaughtException`. In that case, continue program
947
  // execution.
948
  // TODO(joyeecheung): This has been only checking that the return value is
949
  // exactly false. Investigate whether this can be turned to an "if true"
950
  // similar to how the worker global uncaught exception handler handles it.
951
2796
  if (!handled.ToLocalChecked()->IsFalse()) {
952
1204
    return;
953
  }
954
955
  // Now we are certain that the exception is fatal.
956
194
  ReportFatalException(env, error, message, EnhanceFatalException::kEnhance);
957
194
  RunAtExit(env);
958
959
  // If the global uncaught exception handler sets process.exitCode,
960
  // exit with that code. Otherwise, exit with 1.
961
194
  Local<String> exit_code = env->exit_code_string();
962
  Local<Value> code;
963

776
  if (process_object->Get(env->context(), exit_code).ToLocal(&code) &&
964
194
      code->IsInt32()) {
965
386
    env->Exit(code.As<Int32>()->Value());
966
  } else {
967
1
    env->Exit(1);
968
  }
969
}
970
971
6
void TriggerUncaughtException(Isolate* isolate, const v8::TryCatch& try_catch) {
972
  // If the try_catch is verbose, the per-isolate message listener is going to
973
  // handle it (which is going to call into another overload of
974
  // TriggerUncaughtException()).
975
6
  if (try_catch.IsVerbose()) {
976
    return;
977
  }
978
979
  // If the user calls TryCatch::TerminateExecution() on this TryCatch
980
  // they must call CancelTerminateExecution() again before invoking
981
  // TriggerUncaughtException() because it will invoke
982
  // process._fatalException() in the JS land.
983
6
  CHECK(!try_catch.HasTerminated());
984
6
  CHECK(try_catch.HasCaught());
985
11
  HandleScope scope(isolate);
986
6
  TriggerUncaughtException(isolate,
987
                           try_catch.Exception(),
988
                           try_catch.Message(),
989
6
                           false /* from_promise */);
990
}
991
992
}  // namespace errors
993
994
}  // namespace node
995
996

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