Skip to content

Commit fc0d6e4

Browse files
devsnektargos
authored andcommitted
src: add error formatting support
PR-URL: #37598 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent 5ef2a8d commit fc0d6e4

File tree

4 files changed

+51
-28
lines changed

4 files changed

+51
-28
lines changed

doc/api/errors.md

+5
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,11 @@ than the parent module. Linked modules must share the same context.
21382138

21392139
The linker function returned a module for which linking has failed.
21402140

2141+
<a id="ERR_VM_MODULE_LINK_FAILURE"></a>
2142+
### `ERR_VM_MODULE_LINK_FAILURE`
2143+
2144+
The module was unable to be linked due to a failure.
2145+
21412146
<a id="ERR_VM_MODULE_NOT_MODULE"></a>
21422147
### `ERR_VM_MODULE_NOT_MODULE`
21432148

lib/internal/vm/module.js

+2
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ class SourceTextModule extends Module {
324324
throw new ERR_VM_MODULE_DIFFERENT_CONTEXT();
325325
}
326326
if (module.status === 'errored') {
327+
// TODO(devsnek): replace with ERR_VM_MODULE_LINK_FAILURE
328+
// and error cause proposal.
327329
throw new ERR_VM_MODULE_LINKING_ERRORED();
328330
}
329331
if (module.status === 'unlinked') {

src/module_wrap.cc

+14-10
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,9 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
291291
Local<Value> resolve_return_value =
292292
maybe_resolve_return_value.ToLocalChecked();
293293
if (!resolve_return_value->IsPromise()) {
294-
env->ThrowError("linking error, expected resolver to return a promise");
294+
THROW_ERR_VM_MODULE_LINK_FAILURE(
295+
env, "request for '%s' did not return promise", specifier_std);
296+
return;
295297
}
296298
Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
297299
obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
@@ -485,33 +487,35 @@ MaybeLocal<Module> ModuleWrap::ResolveCallback(Local<Context> context,
485487

486488
Isolate* isolate = env->isolate();
487489

490+
Utf8Value specifier_utf8(isolate, specifier);
491+
std::string specifier_std(*specifier_utf8, specifier_utf8.length());
492+
488493
ModuleWrap* dependent = GetFromModule(env, referrer);
489494
if (dependent == nullptr) {
490-
env->ThrowError("linking error, null dep");
495+
THROW_ERR_VM_MODULE_LINK_FAILURE(
496+
env, "request for '%s' is from invalid module", specifier_std);
491497
return MaybeLocal<Module>();
492498
}
493499

494-
Utf8Value specifier_utf8(isolate, specifier);
495-
std::string specifier_std(*specifier_utf8, specifier_utf8.length());
496-
497500
if (dependent->resolve_cache_.count(specifier_std) != 1) {
498-
env->ThrowError("linking error, not in local cache");
501+
THROW_ERR_VM_MODULE_LINK_FAILURE(
502+
env, "request for '%s' is not in cache", specifier_std);
499503
return MaybeLocal<Module>();
500504
}
501505

502506
Local<Promise> resolve_promise =
503507
dependent->resolve_cache_[specifier_std].Get(isolate);
504508

505509
if (resolve_promise->State() != Promise::kFulfilled) {
506-
env->ThrowError("linking error, dependency promises must be resolved on "
507-
"instantiate");
510+
THROW_ERR_VM_MODULE_LINK_FAILURE(
511+
env, "request for '%s' is not yet fulfilled", specifier_std);
508512
return MaybeLocal<Module>();
509513
}
510514

511515
Local<Object> module_object = resolve_promise->Result().As<Object>();
512516
if (module_object.IsEmpty() || !module_object->IsObject()) {
513-
env->ThrowError("linking error, expected a valid module object from "
514-
"resolver");
517+
THROW_ERR_VM_MODULE_LINK_FAILURE(
518+
env, "request for '%s' did not return an object", specifier_std);
515519
return MaybeLocal<Module>();
516520
}
517521

src/node_errors.h

+30-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

6+
#include "debug_utils-inl.h"
67
#include "env.h"
78
#include "v8.h"
89

@@ -56,29 +57,40 @@ void OnFatalError(const char* location, const char* message);
5657
V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \
5758
V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error) \
5859
V(ERR_VM_MODULE_CACHED_DATA_REJECTED, Error) \
60+
V(ERR_VM_MODULE_LINK_FAILURE, Error) \
5961
V(ERR_WASI_NOT_STARTED, Error) \
6062
V(ERR_WORKER_INIT_FAILED, Error) \
6163
V(ERR_PROTO_ACCESS, Error)
6264

63-
#define V(code, type) \
64-
inline v8::Local<v8::Value> code(v8::Isolate* isolate, \
65-
const char* message) { \
66-
v8::Local<v8::String> js_code = OneByteString(isolate, #code); \
67-
v8::Local<v8::String> js_msg = OneByteString(isolate, message); \
68-
v8::Local<v8::Object> e = \
69-
v8::Exception::type(js_msg)->ToObject( \
70-
isolate->GetCurrentContext()).ToLocalChecked(); \
71-
e->Set(isolate->GetCurrentContext(), OneByteString(isolate, "code"), \
72-
js_code).Check(); \
73-
return e; \
74-
} \
75-
inline void THROW_ ## code(v8::Isolate* isolate, const char* message) { \
76-
isolate->ThrowException(code(isolate, message)); \
77-
} \
78-
inline void THROW_ ## code(Environment* env, const char* message) { \
79-
THROW_ ## code(env->isolate(), message); \
65+
#define V(code, type) \
66+
template <typename... Args> \
67+
inline v8::Local<v8::Value> code( \
68+
v8::Isolate* isolate, const char* format, Args&&... args) { \
69+
std::string message = SPrintF(format, std::forward<Args>(args)...); \
70+
v8::Local<v8::String> js_code = OneByteString(isolate, #code); \
71+
v8::Local<v8::String> js_msg = \
72+
OneByteString(isolate, message.c_str(), message.length()); \
73+
v8::Local<v8::Object> e = v8::Exception::type(js_msg) \
74+
->ToObject(isolate->GetCurrentContext()) \
75+
.ToLocalChecked(); \
76+
e->Set(isolate->GetCurrentContext(), \
77+
OneByteString(isolate, "code"), \
78+
js_code) \
79+
.Check(); \
80+
return e; \
81+
} \
82+
template <typename... Args> \
83+
inline void THROW_##code( \
84+
v8::Isolate* isolate, const char* format, Args&&... args) { \
85+
isolate->ThrowException( \
86+
code(isolate, format, std::forward<Args>(args)...)); \
87+
} \
88+
template <typename... Args> \
89+
inline void THROW_##code( \
90+
Environment* env, const char* format, Args&&... args) { \
91+
THROW_##code(env->isolate(), format, std::forward<Args>(args)...); \
8092
}
81-
ERRORS_WITH_CODE(V)
93+
ERRORS_WITH_CODE(V)
8294
#undef V
8395

8496
// Errors with predefined static messages

0 commit comments

Comments
 (0)