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: 33 61 54.1 %
Date: 2019-02-01 22:03:38 Branches: 7 28 25.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 <string.h>
11
12
namespace node {
13
14
using v8::Exception;
15
using v8::HandleScope;
16
using v8::Integer;
17
using v8::Isolate;
18
using v8::Local;
19
using v8::Message;
20
using v8::NewStringType;
21
using v8::Object;
22
using v8::String;
23
using v8::Value;
24
25
Local<Value> ErrnoException(Isolate* isolate,
26
                            int errorno,
27
                            const char* syscall,
28
                            const char* msg,
29
                            const char* path) {
30
  Environment* env = Environment::GetCurrent(isolate);
31
32
  Local<Value> e;
33
  Local<String> estring = OneByteString(isolate, errors::errno_string(errorno));
34
  if (msg == nullptr || msg[0] == '\0') {
35
    msg = strerror(errorno);
36
  }
37
  Local<String> message = OneByteString(isolate, msg);
38
39
  Local<String> cons =
40
      String::Concat(isolate, estring, FIXED_ONE_BYTE_STRING(isolate, ", "));
41
  cons = String::Concat(isolate, cons, message);
42
43
  Local<String> path_string;
44
  if (path != nullptr) {
45
    // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8.
46
    path_string = String::NewFromUtf8(isolate, path, NewStringType::kNormal)
47
                      .ToLocalChecked();
48
  }
49
50
  if (path_string.IsEmpty() == false) {
51
    cons = String::Concat(isolate, cons, FIXED_ONE_BYTE_STRING(isolate, " '"));
52
    cons = String::Concat(isolate, cons, path_string);
53
    cons = String::Concat(isolate, cons, FIXED_ONE_BYTE_STRING(isolate, "'"));
54
  }
55
  e = Exception::Error(cons);
56
57
  Local<Object> obj = e.As<Object>();
58
  obj->Set(env->context(),
59
           env->errno_string(),
60
           Integer::New(isolate, errorno)).FromJust();
61
  obj->Set(env->context(), env->code_string(), estring).FromJust();
62
63
  if (path_string.IsEmpty() == false) {
64
    obj->Set(env->context(), env->path_string(), path_string).FromJust();
65
  }
66
67
  if (syscall != nullptr) {
68
    obj->Set(env->context(),
69
             env->syscall_string(),
70
             OneByteString(isolate, syscall)).FromJust();
71
  }
72
73
  return e;
74
}
75
76
5791
static Local<String> StringFromPath(Isolate* isolate, const char* path) {
77
#ifdef _WIN32
78
  if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
79
    return String::Concat(
80
        isolate,
81
        FIXED_ONE_BYTE_STRING(isolate, "\\\\"),
82
        String::NewFromUtf8(isolate, path + 8, NewStringType::kNormal)
83
            .ToLocalChecked());
84
  } else if (strncmp(path, "\\\\?\\", 4) == 0) {
85
    return String::NewFromUtf8(isolate, path + 4, NewStringType::kNormal)
86
        .ToLocalChecked();
87
  }
88
#endif
89
90
  return String::NewFromUtf8(isolate, path, NewStringType::kNormal)
91
11582
      .ToLocalChecked();
92
}
93
94
95
5682
Local<Value> UVException(Isolate* isolate,
96
                         int errorno,
97
                         const char* syscall,
98
                         const char* msg,
99
                         const char* path,
100
                         const char* dest) {
101
5682
  Environment* env = Environment::GetCurrent(isolate);
102
103

5682
  if (!msg || !msg[0])
104
5682
    msg = uv_strerror(errorno);
105
106
5682
  Local<String> js_code = OneByteString(isolate, uv_err_name(errorno));
107
5682
  Local<String> js_syscall = OneByteString(isolate, syscall);
108
  Local<String> js_path;
109
  Local<String> js_dest;
110
111
5682
  Local<String> js_msg = js_code;
112
  js_msg =
113
5682
      String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ": "));
114
5682
  js_msg = String::Concat(isolate, js_msg, OneByteString(isolate, msg));
115
  js_msg =
116
5682
      String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, ", "));
117
5682
  js_msg = String::Concat(isolate, js_msg, js_syscall);
118
119
5682
  if (path != nullptr) {
120
5682
    js_path = StringFromPath(isolate, path);
121
122
    js_msg =
123
5682
        String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, " '"));
124
5682
    js_msg = String::Concat(isolate, js_msg, js_path);
125
    js_msg =
126
5682
        String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
127
  }
128
129
5682
  if (dest != nullptr) {
130
109
    js_dest = StringFromPath(isolate, dest);
131
132
    js_msg = String::Concat(
133
109
        isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '"));
134
109
    js_msg = String::Concat(isolate, js_msg, js_dest);
135
    js_msg =
136
109
        String::Concat(isolate, js_msg, FIXED_ONE_BYTE_STRING(isolate, "'"));
137
  }
138
139
  Local<Object> e =
140
17046
    Exception::Error(js_msg)->ToObject(isolate->GetCurrentContext())
141
11364
      .ToLocalChecked();
142
143
  e->Set(env->context(),
144
         env->errno_string(),
145
28410
         Integer::New(isolate, errorno)).FromJust();
146
22728
  e->Set(env->context(), env->code_string(), js_code).FromJust();
147
22728
  e->Set(env->context(), env->syscall_string(), js_syscall).FromJust();
148
5682
  if (!js_path.IsEmpty())
149
22728
    e->Set(env->context(), env->path_string(), js_path).FromJust();
150
5682
  if (!js_dest.IsEmpty())
151
436
    e->Set(env->context(), env->dest_string(), js_dest).FromJust();
152
153
5682
  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, nullptr, errorno,
164
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, 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'); i--) {
172
      errmsg[i] = '\0';
173
    }
174
175
    return errmsg;
176
  } else {
177
    // FormatMessage failed
178
    *must_free = false;
179
    return "Unknown error";
180
  }
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
  Local<Value> e;
191
  bool must_free = false;
192
  if (!msg || !msg[0]) {
193
    msg = winapi_strerror(errorno, &must_free);
194
  }
195
  Local<String> message = OneByteString(isolate, msg);
196
197
  if (path) {
198
    Local<String> cons1 =
199
        String::Concat(isolate, message, FIXED_ONE_BYTE_STRING(isolate, " '"));
200
    Local<String> cons2 = String::Concat(
201
        isolate,
202
        cons1,
203
        String::NewFromUtf8(isolate, path, NewStringType::kNormal)
204
            .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->errno_string(), Integer::New(isolate, errorno));
214
215
  if (path != nullptr) {
216
    obj->Set(env->path_string(),
217
             String::NewFromUtf8(isolate, path, NewStringType::kNormal)
218
                 .ToLocalChecked());
219
  }
220
221
  if (syscall != nullptr) {
222
    obj->Set(env->syscall_string(), OneByteString(isolate, syscall));
223
  }
224
225
  if (must_free)
226
    LocalFree((HLOCAL)msg);
227
228
  return e;
229
}
230
#endif
231
232
void FatalException(Isolate* isolate, const v8::TryCatch& try_catch) {
233
  // If we try to print out a termination exception, we'd just get 'null',
234
  // so just crashing here with that information seems like a better idea,
235
  // and in particular it seems like we should handle terminations at the call
236
  // site for this function rather than by printing them out somewhere.
237
  CHECK(!try_catch.HasTerminated());
238
239
  HandleScope scope(isolate);
240
  if (!try_catch.IsVerbose()) {
241
    FatalException(isolate, try_catch.Exception(), try_catch.Message());
242
  }
243
}
244
245
}  // namespace node