Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4b24ddf

Browse files
authoredApr 15, 2025··
[node.js] fix handling null value for externalData (#24428)
### Description <!-- Describe your changes. --> Fix a bug when `sessionOptions.externalData === undefined` for Node.js binding. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. -->
1 parent c27975f commit 4b24ddf

File tree

1 file changed

+33
-31
lines changed

1 file changed

+33
-31
lines changed
 

‎js/node/src/session_options_helper.cc

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -321,44 +321,46 @@ void ParseSessionOptions(const Napi::Object options, Ort::SessionOptions& sessio
321321
// external data
322322
if (options.Has("externalData")) {
323323
auto externalDataValue = options.Get("externalData");
324-
ORT_NAPI_THROW_TYPEERROR_IF(!externalDataValue.IsArray(), options.Env(),
325-
"Invalid argument: sessionOptions.externalData must be an array.");
326-
auto externalData = externalDataValue.As<Napi::Array>();
327-
std::vector<std::basic_string<ORTCHAR_T>> paths;
328-
std::vector<char*> buffs;
329-
std::vector<size_t> sizes;
324+
if (!externalDataValue.IsNull() && !externalDataValue.IsUndefined()) {
325+
ORT_NAPI_THROW_TYPEERROR_IF(!externalDataValue.IsArray(), options.Env(),
326+
"Invalid argument: sessionOptions.externalData must be an array.");
327+
auto externalData = externalDataValue.As<Napi::Array>();
328+
std::vector<std::basic_string<ORTCHAR_T>> paths;
329+
std::vector<char*> buffs;
330+
std::vector<size_t> sizes;
330331

331-
for (const auto& kvp : externalData) {
332-
Napi::Value value = kvp.second;
333-
ORT_NAPI_THROW_TYPEERROR_IF(!value.IsObject(), options.Env(),
334-
"Invalid argument: sessionOptions.externalData value must be an object in Node.js binding.");
335-
Napi::Object obj = value.As<Napi::Object>();
336-
ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("path") || !obj.Get("path").IsString(), options.Env(),
337-
"Invalid argument: sessionOptions.externalData value must have a 'path' property of type string in Node.js binding.");
332+
for (const auto& kvp : externalData) {
333+
Napi::Value value = kvp.second;
334+
ORT_NAPI_THROW_TYPEERROR_IF(!value.IsObject(), options.Env(),
335+
"Invalid argument: sessionOptions.externalData value must be an object in Node.js binding.");
336+
Napi::Object obj = value.As<Napi::Object>();
337+
ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("path") || !obj.Get("path").IsString(), options.Env(),
338+
"Invalid argument: sessionOptions.externalData value must have a 'path' property of type string in Node.js binding.");
338339
#ifdef _WIN32
339-
auto path = obj.Get("path").As<Napi::String>().Utf16Value();
340-
paths.push_back(std::wstring{path.begin(), path.end()});
340+
auto path = obj.Get("path").As<Napi::String>().Utf16Value();
341+
paths.push_back(std::wstring{path.begin(), path.end()});
341342
#else
342-
auto path = obj.Get("path").As<Napi::String>().Utf8Value();
343-
paths.push_back(path);
343+
auto path = obj.Get("path").As<Napi::String>().Utf8Value();
344+
paths.push_back(path);
344345
#endif
345-
ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("data") ||
346-
!obj.Get("data").IsBuffer() ||
347-
!(obj.Get("data").IsTypedArray() && obj.Get("data").As<Napi::TypedArray>().TypedArrayType() == napi_uint8_array),
348-
options.Env(),
349-
"Invalid argument: sessionOptions.externalData value must have an 'data' property of type buffer or typed array in Node.js binding.");
346+
ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("data") ||
347+
!obj.Get("data").IsBuffer() ||
348+
!(obj.Get("data").IsTypedArray() && obj.Get("data").As<Napi::TypedArray>().TypedArrayType() == napi_uint8_array),
349+
options.Env(),
350+
"Invalid argument: sessionOptions.externalData value must have an 'data' property of type buffer or typed array in Node.js binding.");
350351

351-
auto data = obj.Get("data");
352-
if (data.IsBuffer()) {
353-
buffs.push_back(data.As<Napi::Buffer<char>>().Data());
354-
sizes.push_back(data.As<Napi::Buffer<char>>().Length());
355-
} else {
356-
auto typedArray = data.As<Napi::TypedArray>();
357-
buffs.push_back(reinterpret_cast<char*>(typedArray.ArrayBuffer().Data()) + typedArray.ByteOffset());
358-
sizes.push_back(typedArray.ByteLength());
352+
auto data = obj.Get("data");
353+
if (data.IsBuffer()) {
354+
buffs.push_back(data.As<Napi::Buffer<char>>().Data());
355+
sizes.push_back(data.As<Napi::Buffer<char>>().Length());
356+
} else {
357+
auto typedArray = data.As<Napi::TypedArray>();
358+
buffs.push_back(reinterpret_cast<char*>(typedArray.ArrayBuffer().Data()) + typedArray.ByteOffset());
359+
sizes.push_back(typedArray.ByteLength());
360+
}
359361
}
362+
sessionOptions.AddExternalInitializersFromFilesInMemory(paths, buffs, sizes);
360363
}
361-
sessionOptions.AddExternalInitializersFromFilesInMemory(paths, buffs, sizes);
362364
}
363365
}
364366

0 commit comments

Comments
 (0)
Please sign in to comment.