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: 61 61 100.0 %
Date: 2019-09-24 22:36:24 Branches: 21 28 75.0 %

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::NewStringType;
19
using v8::Object;
20
using v8::String;
21
using v8::Value;
22
23
4
Local<Value> ErrnoException(Isolate* isolate,
24
                            int errorno,
25
                            const char* syscall,
26
                            const char* msg,
27
                            const char* path) {
28
4
  Environment* env = Environment::GetCurrent(isolate);
29
4
  CHECK_NOT_NULL(env);
30
31
  Local<Value> e;
32
4
  Local<String> estring = OneByteString(isolate, errors::errno_string(errorno));
33

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

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