GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/api/exceptions.cc Lines: 65 65 100.0 %
Date: 2020-07-19 22:14:24 Branches: 23 32 71.9 %

Line Branch Exec Source
1
// This file contains implementation of error APIs exposed in node.h
2
3
#include "env-inl.h"
4
#include "node.h"
5
#include "node_errors.h"
6
#include "util-inl.h"
7
#include "uv.h"
8
#include "v8.h"
9
10
#include <cstring>
11
12
namespace node {
13
14
using v8::Exception;
15
using v8::Integer;
16
using v8::Isolate;
17
using v8::Local;
18
using v8::Object;
19
using v8::String;
20
using v8::Value;
21
22
4
Local<Value> ErrnoException(Isolate* isolate,
23
                            int errorno,
24
                            const char* syscall,
25
                            const char* msg,
26
                            const char* path) {
27
4
  Environment* env = Environment::GetCurrent(isolate);
28
4
  CHECK_NOT_NULL(env);
29
30
  Local<Value> e;
31
4
  Local<String> estring = OneByteString(isolate, errors::errno_string(errorno));
32

4
  if (msg == nullptr || msg[0] == '\0') {
33
3
    msg = strerror(errorno);
34
  }
35
4
  Local<String> message = OneByteString(isolate, msg);
36
37
  Local<String> cons =
38
4
      String::Concat(isolate, estring, FIXED_ONE_BYTE_STRING(isolate, ", "));
39
4
  cons = String::Concat(isolate, cons, message);
40
41
  Local<String> path_string;
42
4
  if (path != nullptr) {
43
    // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
44
2
    path_string = String::NewFromUtf8(isolate, path).ToLocalChecked();
45
  }
46
47
4
  if (path_string.IsEmpty() == false) {
48
1
    cons = String::Concat(isolate, cons, FIXED_ONE_BYTE_STRING(isolate, " '"));
49
1
    cons = String::Concat(isolate, cons, path_string);
50
1
    cons = String::Concat(isolate, cons, FIXED_ONE_BYTE_STRING(isolate, "'"));
51
  }
52
4
  e = Exception::Error(cons);
53
54
4
  Local<Object> obj = e.As<Object>();
55
8
  obj->Set(env->context(),
56
           env->errno_string(),
57
20
           Integer::New(isolate, errorno)).Check();
58
16
  obj->Set(env->context(), env->code_string(), estring).Check();
59
60
4
  if (path_string.IsEmpty() == false) {
61
4
    obj->Set(env->context(), env->path_string(), path_string).Check();
62
  }
63
64
4
  if (syscall != nullptr) {
65
8
    obj->Set(env->context(),
66
             env->syscall_string(),
67
20
             OneByteString(isolate, syscall)).Check();
68
  }
69
70
4
  return e;
71
}
72
73
4478
static Local<String> StringFromPath(Isolate* isolate, const char* path) {
74
#ifdef _WIN32
75
  if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
76
    return String::Concat(
77
        isolate,
78
        FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
79
        String::NewFromUtf8(isolate, path + 8).ToLocalChecked());
80
  } else if (strncmp(path, "\\\\?\\", 4) == 0) {
81
    return String::NewFromUtf8(isolate, path + 4).ToLocalChecked();
82
  }
83
#endif
84
85
8956
  return String::NewFromUtf8(isolate, path).ToLocalChecked();
86
}
87
88
89
4431
Local<Value> UVException(Isolate* isolate,
90
                         int errorno,
91
                         const char* syscall,
92
                         const char* msg,
93
                         const char* path,
94
                         const char* dest) {
95
4431
  Environment* env = Environment::GetCurrent(isolate);
96
4431
  CHECK_NOT_NULL(env);
97
98

4431
  if (!msg || !msg[0])
99
4431
    msg = uv_strerror(errorno);
100
101
4431
  Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
102
4431
  Local<String> js_syscall = OneByteString(isolate, syscall);
103
  Local<String> js_path;
104
  Local<String> js_dest;
105
106
4431
  Local<String> js_msg = js_code;
107
  js_msg =
108
4431
      String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
109
4431
  js_msg = String::Concat(isolate, js_msg, OneByteString(isolate, msg));
110
  js_msg =
111
4431
      String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
112
4431
  js_msg = String::Concat(isolate, js_msg, js_syscall);
113
114
4431
  if (path != nullptr) {
115
4401
    js_path = StringFromPath(isolate, path);
116
117
    js_msg =
118
4401
        String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
119
4401
    js_msg = String::Concat(isolate, js_msg, js_path);
120
    js_msg =
121
4401
        String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
122
  }
123
124
4431
  if (dest != nullptr) {
125
77
    js_dest = StringFromPath(isolate, dest);
126
127
    js_msg = String::Concat(
128
77
        isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
129
77
    js_msg = String::Concat(isolate, js_msg, js_dest);
130
    js_msg =
131
77
        String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
132
  }
133
134
  Local<Object> e =
135
13293
    Exception::Error(js_msg)->ToObject(isolate->GetCurrentContext())
136
4431
      .ToLocalChecked();
137
138
8862
  e->Set(env->context(),
139
         env->errno_string(),
140
22155
         Integer::New(isolate, errorno)).Check();
141
17724
  e->Set(env->context(), env->code_string(), js_code).Check();
142
17724
  e->Set(env->context(), env->syscall_string(), js_syscall).Check();
143
4431
  if (!js_path.IsEmpty())
144
17604
    e->Set(env->context(), env->path_string(), js_path).Check();
145
4431
  if (!js_dest.IsEmpty())
146
308
    e->Set(env->context(), env->dest_string(), js_dest).Check();
147
148
4431
  return e;
149
}
150
151
#ifdef _WIN32
152
// Does about the same as strerror(),
153
// but supports all windows error messages
154
static const char* winapi_strerror(const int errorno, bool* must_free) {
155
  char* errmsg = nullptr;
156
157
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
158
                    FORMAT_MESSAGE_IGNORE_INSERTS,
159
                nullptr,
160
                errorno,
161
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
162
                reinterpret_cast<LPTSTR>(&errmsg),
163
                0,
164
                nullptr);
165
166
  if (errmsg) {
167
    *must_free = true;
168
169
    // Remove trailing newlines
170
    for (int i = strlen(errmsg) - 1;
171
         i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r');
172
         i--) {
173
      errmsg[i] = '\0';
174
    }
175
176
    return errmsg;
177
  } else {
178
    // FormatMessage failed
179
    *must_free = false;
180
    return "Unknown error";
181
  }
182
}
183
184
Local<Value> WinapiErrnoException(Isolate* isolate,
185
                                  int errorno,
186
                                  const char* syscall,
187
                                  const char* msg,
188
                                  const char* path) {
189
  Environment* env = Environment::GetCurrent(isolate);
190
  CHECK_NOT_NULL(env);
191
  Local<Value> e;
192
  bool must_free = false;
193
  if (!msg || !msg[0]) {
194
    msg = winapi_strerror(errorno, &must_free);
195
  }
196
  Local<String> message = OneByteString(isolate, msg);
197
198
  if (path) {
199
    Local<String> cons1 =
200
        String::Concat(isolate, message, FIXED_ONE_BYTE_STRING(isolate, " '"));
201
    Local<String> cons2 = String::Concat(
202
        isolate,
203
        cons1,
204
        String::NewFromUtf8(isolate, path).ToLocalChecked());
205
    Local<String> cons3 =
206
        String::Concat(isolate, cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
207
    e = Exception::Error(cons3);
208
  } else {
209
    e = Exception::Error(message);
210
  }
211
212
  Local<Object> obj = e.As<Object>();
213
  obj->Set(env->context(), env->errno_string(), Integer::New(isolate, errorno))
214
      .Check();
215
216
  if (path != nullptr) {
217
    obj->Set(env->context(),
218
             env->path_string(),
219
             String::NewFromUtf8(isolate, path).ToLocalChecked())
220
        .Check();
221
  }
222
223
  if (syscall != nullptr) {
224
    obj->Set(env->context(),
225
             env->syscall_string(),
226
             OneByteString(isolate, syscall))
227
        .Check();
228
  }
229
230
  if (must_free) {
231
    LocalFree(const_cast<char*>(msg));
232
  }
233
234
  return e;
235
}
236
#endif
237
238
// Implement the legacy name exposed in node.h. This has not been in fact
239
// fatal any more, as the user can handle the exception in the
240
// TryCatch by listening to `uncaughtException`.
241
// TODO(joyeecheung): deprecate it in favor of a more accurate name.
242
1
void FatalException(Isolate* isolate, const v8::TryCatch& try_catch) {
243
1
  errors::TriggerUncaughtException(isolate, try_catch);
244
1
}
245
246

14970
}  // namespace node