Skip to content

Commit 5990609

Browse files
committed
src: handle empty MaybeLocal in cjs_lexer::Parse
CreateString() and Parse() in node_cjs_lexer.cc unconditionally called ToLocalChecked() on the results of String::NewFromOneByte(), String::NewFromUtf8() and Set::Add(). If string or handle allocation fails or an exception is pending on the isolate, these return an empty MaybeLocal and ToLocalChecked() aborts the process with "FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal". Since Parse() is on the hot path of every ESM import of a CJS module (cjsPreparseModuleExports), propagate the failure as a regular pending JavaScript exception instead so callers can recover. Fixes: #63323 Refs: #61456 Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 4383f67 commit 5990609

1 file changed

Lines changed: 14 additions & 7 deletions

File tree

src/node_cjs_lexer.cc

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ using v8::FunctionCallbackInfo;
1515
using v8::Isolate;
1616
using v8::Local;
1717
using v8::LocalVector;
18+
using v8::MaybeLocal;
1819
using v8::NewStringType;
1920
using v8::Object;
2021
using v8::Set;
@@ -23,22 +24,20 @@ using v8::Value;
2324

2425
// Create a V8 string from an export_string variant, using fast path for ASCII
2526
template <typename T>
26-
inline Local<String> CreateString(Isolate* isolate, const T& str) {
27+
inline MaybeLocal<String> CreateString(Isolate* isolate, const T& str) {
2728
std::string_view sv = lexer::get_string_view(str);
2829

2930
if (simdutf::validate_ascii(sv.data(), sv.size())) {
3031
return String::NewFromOneByte(isolate,
3132
reinterpret_cast<const uint8_t*>(sv.data()),
3233
NewStringType::kInternalized,
33-
static_cast<int>(sv.size()))
34-
.ToLocalChecked();
34+
static_cast<int>(sv.size()));
3535
}
3636

3737
return String::NewFromUtf8(isolate,
3838
sv.data(),
3939
NewStringType::kInternalized,
40-
static_cast<int>(sv.size()))
41-
.ToLocalChecked();
40+
static_cast<int>(sv.size()));
4241
}
4342

4443
void Parse(const FunctionCallbackInfo<Value>& args) {
@@ -71,14 +70,22 @@ void Parse(const FunctionCallbackInfo<Value>& args) {
7170
// Convert exports to JS Set
7271
Local<Set> exports_set = Set::New(isolate);
7372
for (const auto& exp : analysis.exports) {
74-
exports_set->Add(context, CreateString(isolate, exp)).ToLocalChecked();
73+
Local<String> exp_str;
74+
if (!CreateString(isolate, exp).ToLocal(&exp_str) ||
75+
exports_set->Add(context, exp_str).IsEmpty()) {
76+
return;
77+
}
7578
}
7679

7780
// Convert reexports to JS array using batch creation
7881
LocalVector<Value> reexports_vec(isolate);
7982
reexports_vec.reserve(analysis.re_exports.size());
8083
for (const auto& reexp : analysis.re_exports) {
81-
reexports_vec.push_back(CreateString(isolate, reexp));
84+
Local<String> reexp_str;
85+
if (!CreateString(isolate, reexp).ToLocal(&reexp_str)) {
86+
return;
87+
}
88+
reexports_vec.push_back(reexp_str);
8289
}
8390

8491
// Create result array [exports (Set), reexports (Array)]

0 commit comments

Comments
 (0)