Skip to content

Conversation

@Nishant-ZFYII
Copy link
Contributor

Fixes #33601

What / Why

This refactors the Node.js bindings for Core.importModelSync() and Core.importModel().

The async Buffer path was still going through std::stringstd::stringstream, which adds extra copies. Also, the async worker didn’t cleanly separate “import from stream bytes” vs “import from tensor”, so it was easy to end up treating tensor data like a stream. This change switches Buffer imports to ov::SharedStreamBuffer and makes the async worker explicitly dispatch based on input type.

No JS API changes — just internal implementation cleanup.

What changed

  • Buffer imports (sync + async) now use ov::SharedStreamBuffer + std::istream instead of building a std::stringstream.
  • ImportModelContext now stores the input as std::variant<std::monostate, BufferSource, TensorSource>.
    • BufferSource keeps a persistent reference to the JS Buffer so it can’t be GC’d while the worker is running, and wraps the underlying bytes with ov::SharedStreamBuffer.
    • TensorSource keeps a persistent reference to the JS object backing TensorWrap, and stores ov::Tensor directly.
  • importModelThread uses std::visit to call the right ov::Core::import_model overload (stream vs tensor).
  • Exceptions in the native worker are surfaced to JS by rejecting the Promise with an Error.
  • Updated the unit test that checks signature-validation error strings (the allowed-signatures output changed with the refactor).

Files changed

  • src/bindings/js/node/include/core_wrap.hpp
  • src/bindings/js/node/src/core_wrap.cpp
  • src/bindings/js/node/tests/unit/basic.test.js

Checks

Ran:

  • npm run lint
  • npm run format
  • npm test

CC: @almilosz @Retribution98

…or sources

- Add required includes: <variant>, <istream>, <memory>, shared_buffer.hpp
- Replace std::stringstream with std::variant<monostate, BufferSource, TensorSource>
- BufferSource: pins JS Buffer with ObjectReference, stores SharedStreamBuffer
- TensorSource: pins JS TensorWrap, stores ov::Tensor directly
- Add _error_msg field for proper async error propagation
- Use ov::AnyMap instead of std::map<std::string, ov::Any>

Part of issue openvinotoolkit#33601: Improve implementation of Node.js API Core.import_model()
- Add required includes: <type_traits>, tensor.hpp, shared_buffer.hpp
- Replace direct _stream access with std::visit over source variant
- BufferSource: create local std::istream over SharedStreamBuffer
- TensorSource: call import_model(tensor, ...) directly
- Add try/catch with proper Promise rejection on error
- Handle both std::exception and unknown exceptions

Part of issue openvinotoolkit#33601: Improve implementation of Node.js API Core.import_model()
…nsor support

- Replace std::string + std::stringstream with ov::SharedStreamBuffer (zero-copy)
- Add Tensor input support using cast_to_tensor and direct tensor overload
- Use ov::js::validate pattern for consistent argument validation
- Use ov::AnyMap for config consistency
- Proper static_cast for Buffer length to size_t

Part of issue openvinotoolkit#33601: Improve implementation of Node.js API Core.import_model()
- Use std::make_unique for RAII safety (no leak if setup throws)
- Add Tensor input support: pin TensorWrap with ObjectReference
- Buffer input: pin JS Buffer, use SharedStreamBuffer (zero-copy)
- Store source in variant, worker thread dispatches via std::visit
- Consistent ov::AnyMap usage for config

Part of issue openvinotoolkit#33601: Improve implementation of Node.js API Core.import_model()
Auto-format core_wrap.hpp and core_wrap.cpp to match project code style.
- importModelSync now uses ov::js::validate() and reports standardized parameter mismatch errors
- Update basic.test.js to assert on the new stable error message instead of legacy per-arg type strings

Part of issue openvinotoolkit#33601: Improve implementation of Node.js API Core.import_model()
@Nishant-ZFYII Nishant-ZFYII requested a review from a team as a code owner January 17, 2026 05:35
@github-actions github-actions bot added the category: JS API OpenVino JS API Bindings label Jan 17, 2026
@sys-openvino-ci sys-openvino-ci added the ExternalPR External contributor label Jan 17, 2026
@almilosz
Copy link
Contributor

build_jenkins

Copy link
Contributor

@almilosz almilosz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I left a few comments

- Remove explicit casts in SharedStreamBuffer construction
- Use overloaded helper for std::visit instead of if constexpr chain
- Remove redundant data/size fields from BufferSource struct
- Use raw new with try-catch guard instead of make_unique + release
- Remove unnecessary regex escape in test assertions
- Add test for importModel promise rejection on invalid buffer
@almilosz
Copy link
Contributor

build_jenkins

@almilosz
Copy link
Contributor

Hey, I can see that all my comments are addressed, thank you. Unfortunately, code style check failed :( do you need help with fixing it?

@Nishant-ZFYII Nishant-ZFYII requested review from a team as code owners January 27, 2026 08:06
@Nishant-ZFYII Nishant-ZFYII requested review from ValentinaKats, akuporos and p-wysocki and removed request for a team January 27, 2026 08:06
@github-actions github-actions bot added category: CPU OpenVINO CPU plugin category: build OpenVINO cmake script / infra category: docs OpenVINO documentation labels Jan 27, 2026
@github-actions github-actions bot added category: ONNX FE OpenVINO ONNX FrontEnd category: dependency_changes Pull requests that update a dependency file category: docker_env labels Jan 27, 2026
@Nishant-ZFYII
Copy link
Contributor Author

Thanks @almilosz for the careful review and being patient with me — appreciate it!

I ran clang-format-18 locally via cmake --build . --target clang_format_fix_all, verified with clang_format_check_all, and pushed a formatting-only commit. I followed the repo guidelines in docs/dev/coding_style.md.

Could you please take another look when you have a moment? If anything is still not aligned with the expected style checks, I’m happy to adjust.Thanks again for offering to help — really appreciate it.

@almilosz
Copy link
Contributor

Over 300 files is changed. Only changes to files you modified should stay

@Nishant-ZFYII Nishant-ZFYII force-pushed the js-importmodel-sharedstreambuffer-variant branch from e94aa96 to 47cb1a5 Compare January 27, 2026 13:02
@github-actions github-actions bot removed category: CPU OpenVINO CPU plugin category: build OpenVINO cmake script / infra category: docs OpenVINO documentation category: ONNX FE OpenVINO ONNX FrontEnd category: dependency_changes Pull requests that update a dependency file category: docker_env labels Jan 27, 2026
@Nishant-ZFYII
Copy link
Contributor Author

Apologies for the noise on that last push — I ran clang_format_fix_all and did git add . Which caused the huge file dump

I've reset that commit and force-pushed a clean one that applies clang-format only to core_wrap.cpp (the only file that needed formatting changes).

@almilosz
Copy link
Contributor

build_jenkins

@almilosz
Copy link
Contributor

almilosz commented Feb 3, 2026

build_jenkins

@almilosz almilosz added this pull request to the merge queue Feb 4, 2026
@praasz praasz removed this pull request from the merge queue due to a manual request Feb 4, 2026
};

using Source = std::variant<std::monostate, BufferSource, TensorSource>;
Source source{std::monostate{}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Source source{std::monostate{}};
Source source{};

It should use first variant as default initializer


// Helper for std::visit with multiple lambdas
template <class... Ts>
struct overloaded : Ts... {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is helper in OV with this implementation variant_visitor.hpp

context->_compiled_model =
std::visit(overloaded{
[](std::monostate&) -> ov::CompiledModel {
throw std::runtime_error("ImportModelContext source not initialized");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not OPENVINO_THROW/ASSERT is not used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: JS API OpenVino JS API Bindings ExternalPR External contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Good First Issue]: Improve implementation of Node.js API Core.import_model()

4 participants