-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[OV JS][DOCS] Edits in JS API docs (#27064)
Porting: #26875 --------- Co-authored-by: Roman Kazantsev <roman.kazantsev@intel.com>
- Loading branch information
1 parent
e16e4d4
commit cb56c19
Showing
8 changed files
with
342 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# How to extend the OpenVINO™ JavaScript API code | ||
|
||
## Build the OpenVINO™ JavaScript API | ||
|
||
For detailed build instructions, refer to the [OpenVINO™ JavaScript API documentation](./README.md). | ||
|
||
|
||
## Project's naming conventions | ||
|
||
When implementing the C++ sources for the JavaScript API, it is essential to adhere to the OpenVINO naming conventions described in the [OpenVINO Coding Style Guide](../../../../docs/dev/coding_style.md). In summary, the naming style employs `Snake Case` for methods, functions, and variables, while `Camel Case` is used for class names. Additionally, the naming of entities in the C++ sources should closely mirror their equivalents in the C++ API to maintain consistency. | ||
|
||
For methods that are exposed to JavaScript, the naming convention transitions to `Camel Case`, aligning with common JavaScript practices. As an example, a method in the C++ API named `get_element_type` would be represented in the JavaScript API as `getElementType()`. | ||
|
||
|
||
## node-addon-api module | ||
|
||
[node addon api](https://github.com/nodejs/node-addon-api) is used to create OpenVINO JavaScript API for Node.js. The quickest way to learn is to follow the official [examples](https://github.com/nodejs/node-addon-examples). It is recommended to check out the tutorial on [how to create a JavaScript object from a C++ object](https://github.com/nodejs/node-addon-examples/tree/main/src/2-js-to-native-conversion/object-wrap-demo/node-addon-api). | ||
|
||
|
||
## Adding a new class and method | ||
|
||
To introduce a new `MyTensor` class that interacts with the `ov::Tensor` class, follow these steps: | ||
- The class should facilitate construction from an ov::Tensor instance and allow initialization from a JavaScript element type and shape. | ||
- It should also provide a getElementType method that retrieves the ov::Tensor element type. | ||
|
||
Begin by creating a header file for the `MyTensor` class in the OpenVINO repository at `<openvino_repo>/src/bindings/js/node/include/my_tensor.hpp`. This file should contain the necessary includes and class definitions: | ||
```cpp | ||
class MyTensor : public Napi::ObjectWrap<MyTensor> { | ||
public: | ||
// Constructor for the wrapper class | ||
MyTensor(const Napi::CallbackInfo& info); | ||
|
||
// It returns a JavaScript class definition | ||
static Napi::Function get_class(Napi::Env env); | ||
|
||
// It returns the element type of ov::Tensor | ||
Napi::Value get_element_type(const Napi::CallbackInfo& info); | ||
|
||
private: | ||
ov::Tensor _tensor; | ||
}; | ||
``` | ||
The implementation of the class methods should be placed in a source file at `<openvino_repo>/src/bindings/js/node/src/my_tensor.cpp` | ||
```cpp | ||
MyTensor::MyTensor(const Napi::CallbackInfo& info) : Napi::ObjectWrap<MyTensor>(info) { | ||
std::vector<std::string> allowed_signatures; | ||
try { | ||
if (ov::js::validate<Napi::String, Napi::Array>(info, allowed_signatures)) { | ||
const auto type = js_to_cpp<ov::element::Type_t>(info, 0); | ||
const auto& shape = js_to_cpp<ov::Shape>(info, 1); | ||
this->_tensor = ov::Tensor(type, shape); | ||
} else { | ||
OPENVINO_THROW("'MyTensor' constructor", ov::js::get_parameters_error_msg(info, allowed_signatures)); | ||
} | ||
} catch (std::exception& err) { | ||
reportError(info.Env(), err.what()); | ||
} | ||
} | ||
Napi::Function MyTensor::get_class(Napi::Env env) { | ||
return DefineClass(env, | ||
"MyTensor", | ||
{ | ||
InstanceMethod("getElementType", &MyTensor::get_element_type), | ||
}); | ||
} | ||
Napi::Value MyTensor::get_element_type(const Napi::CallbackInfo& info) { | ||
return Napi::String::New(info.Env(), _tensor.get_element_type().to_string()); | ||
} | ||
``` | ||
Finally, update the `CMakeLists.txt` file at `<openvino_repo>/src/bindings/js/node/` to include the new source file in the build process: | ||
```cmake | ||
add_library(${PROJECT_NAME} SHARED | ||
${CMAKE_CURRENT_SOURCE_DIR}/src/my_tensor.cpp | ||
) | ||
``` | ||
|
||
|
||
### Argument validation and conversion | ||
|
||
When binding JavaScript arguments with C++ functions, it is crucial to validate and convert the arguments appropriately. The template `ov::js::validate` function is a utility that facilitates this process. It is particularly useful for handling different overloads of functions and ensuring standardized error messages when arguments do not match expected signatures. | ||
Before implementing a new conversion function, such as `js_to_cpp<ov::Shape>`, review the existing [helper methods](../../node/include/helper.hpp) to see if one already meets your requirements. | ||
|
||
|
||
### New class initialization | ||
|
||
When a new class is introduced to the `openvino-node` module, it must be initialized upon module loading. This is done in the [addon.cpp](../../src/addon.cpp) file. The initialization process registers the class with the Node.js environment so that it can be used within JavaScript code. | ||
```cpp | ||
Napi::Object init_module(Napi::Env env, Napi::Object exports) { | ||
auto addon_data = new AddonData(); | ||
env.SetInstanceData<AddonData>(addon_data); | ||
init_class(env, exports, "MyTensor", &MyTensor::get_class, addon_data->my_tensor); | ||
|
||
return exports; | ||
} | ||
``` | ||
To keep track of the JavaScript class definitions, they are kept in `<openvino_repo>/src/bindings/js/node/include/addon.hpp`. | ||
```cpp | ||
struct AddonData { | ||
Napi::FunctionReference my_tensor; | ||
// and other class references | ||
}; | ||
``` | ||
|
||
### Document the new functionality | ||
|
||
The last step is to add the TypeScript type definitions and describe the new functionality. | ||
```typescript | ||
/** | ||
* The {@link MyTensor} class and its documentation. | ||
*/ | ||
interface MyTensor { | ||
/** | ||
* It gets the tensor element type. | ||
*/ | ||
getElementType(): element; | ||
|
||
} | ||
interface MyTensorConstructor { | ||
/** | ||
* It constructs a tensor using the element type and shape. The new tensor | ||
* data will be allocated by default. | ||
* @param type The element type of the new tensor. | ||
* @param shape The shape of the new tensor. | ||
*/ | ||
new(type: element | elementTypeString, shape: number[]): MyTensor; | ||
} | ||
|
||
export interface NodeAddon { | ||
MyTensor: MyTensorConstructor, | ||
} | ||
``` | ||
|
||
|
||
## Testing the new code | ||
|
||
Now that coding is finished, remember to rebuild the project and test it out. | ||
|
||
To learn how to test your code, refer to the guide on [how to test OpenVINO™ JavaScript API.](./test_examples.md) | ||
|
||
## See also | ||
* [OpenVINO™ README](../../../../README.md) | ||
* [OpenVINO™ bindings README](../../README.md) | ||
* [Developer documentation](../../../../docs/dev/index.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# How to test the OpenVINO™ JavaScript API | ||
|
||
## Build the OpenVINO™ JavaScript API | ||
For detailed build instructions, refer to the [OpenVINO™ JavaScript API documentation](./README.md). | ||
|
||
|
||
## Run OpenVINO™ JavaScript API tests | ||
*For simplicity, begin by navigating to the [main JavaScript API folder](./../node):* | ||
```shell | ||
cd <openvino_repo>/src/bindings/js/node | ||
``` | ||
|
||
Use this command to run OpenVINO JavaScript API tests: | ||
```shell | ||
npm run test | ||
``` | ||
|
||
To run specific test files, you can pass one or more glob patterns: | ||
```shell | ||
node --test "tests/unit/core.test.js" "tests/unit/*model.test.js" | ||
``` | ||
|
||
Before executing individual test files, a one-time setup is required. If you have not previously executed `npm run test`, initiate the setup by running the following command: | ||
|
||
```shell | ||
npm run test_setup | ||
``` | ||
|
||
More information on running tests from the command line can be found in the [Node.js documentation]( https://nodejs.org/docs/latest/api/test.html#running-tests-from-the-command-line). | ||
|
||
|
||
## Check the code style of the JavaScript API | ||
*ESLint* is a tool to enforce a consistent coding style and to identify and fix potential issues in JavaScript code. | ||
|
||
To check the code style of the JavaScript API, run the following commands: | ||
```shell | ||
npm run lint | ||
``` | ||
*ESLint* can automatically fix many of the issues it detects. Use following command to run *ESLint* with the fix option on a single file: | ||
```shell | ||
npx eslint --fix "tests/unit/core.test.js" | ||
``` | ||
|
||
It is recommended to run the code style check each time new tests are added. | ||
|
||
|
||
## Writing OpenVINO™ JavaScript API tests | ||
|
||
### Before start | ||
Follow and complete [Examples of OpenVINO™ JavaScript API code](./code_examples.md). | ||
|
||
|
||
### Adding new test-case in the correct place | ||
Each new test should verify the correct behavior of the new functionality (e.g. class, method). | ||
|
||
Unit test files are located in the `<openvino_repo>/src/bindings/js/node/tests/unit/` directory and their names correspond to the class/module to be tested. | ||
|
||
Always add tests to the correct locations and create new files only when necessary. *Remember to include the license on top of each new file*. | ||
|
||
|
||
### Test writing guidelines | ||
Each test file starts with a `describe` block to group all tests related to a specific class or module. The name of the `describe` block should match the name of the class or module being tested, for example *ov.Core tests*. | ||
|
||
Within the `describe` block, individual tests are defined using `test` or `it` blocks, with the name of the test reflecting what is being tested. If multiple tests relate to the same method, they can be grouped within a nested `describe` block. | ||
|
||
```js | ||
const { describe, it, beforeEach } = require('node:test'); | ||
describe('ov.Tensor tests', () => { | ||
test('MyTensor.getElementType()', () => { | ||
const tensor = new ov.MyTensor(ov.element.f32, [1, 3]); | ||
assert.strictEqual(tensor.getElementType(), ov.element.f32); | ||
}); | ||
|
||
}); | ||
``` | ||
When writing tests, keep the following best practices in mind: | ||
|
||
* Focus on testing general usage and edge cases, but avoid excessive testing that leads to redundant test cases and can slow down validation pipelines. | ||
* Avoid initializing shared variables outside of `test` or `beforeEach` blocks to prevent tests from affecting each other. | ||
* Do not test built-in language features; instead, focus on the functionality provided by your code. | ||
* Use hardcoded expected results to verify the correctness of your code. Alternatively, generate reference values at runtime using reliable libraries or methods. | ||
* Extract and reuse common code snippets, such as helper functions or setup code, to improve test readability and maintainability. | ||
|
||
|
||
## See also | ||
* [OpenVINO™ README](../../../../README.md) | ||
* [OpenVINO™ bindings README](../../README.md) | ||
* [Developer documentation](../../../../docs/dev/index.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Contributing to OpenVINO™ Node.js API | ||
|
||
Your commitment to this project is greatly appreciated and the following guide is intended to help you contribute. | ||
|
||
Make sure to read [main contribution guide](https://github.com/openvinotoolkit/openvino/blob/master/CONTRIBUTING.md) first. It covers most topics related to contributing to OpenVINO. | ||
|
||
|
||
## TLDR | ||
|
||
1. Decide what you want to change. | ||
2. Create your fork of the OpenVINO repository. | ||
3. Create a branch with a meaningful name for your changes. | ||
4. Align the code style, commit the changes, and run tests. | ||
5. Create a Pull Request, which clearly describes what has been changed and why. | ||
6. Go through the Code Review. | ||
7. Get your awesome code merged! | ||
|
||
Read the section below for more details. | ||
|
||
|
||
## How to Decide What to Change | ||
|
||
In case of minor fixes, like changing variable names, additional parameter checks, etc., go to the next step. | ||
|
||
However, if you want to bring significant changes, for example, the extension of architecture or a big part of functionality, that involves a large amount | ||
of source code, open [an issue](https://github.com/openvinotoolkit/openvino/issues/new?assignees=octocat&labels=enhancement%2Cfeature&projects=&template=feature_request.yml&title=%5BFeature+Request%5D%3A+) first and discuss your idea with | ||
codeowners. It will prevent you from doing extra work. | ||
|
||
You can also take one of the well-described tasks from the [Good First Issue](https://github.com/orgs/openvinotoolkit/projects/3/views/14) section. It can be a great start to contributing with codeowners' support! | ||
|
||
|
||
## Let's code | ||
|
||
Get familiar with Node.js API architecture and code samples. | ||
Refer to the [guide](../docs/code_examples.md), which will help you understand the component structure and the code style. | ||
|
||
The environment setup and build instructions can be found in [Building the Node.js API](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/js/docs/README.md#openvino-node-package-developer-documentation). | ||
|
||
Run tests! If you add a new functionality, make sure that it is covered by tests first. | ||
Read [the guide](../docs/test_examples.md) for more details about the tests and their runs. | ||
Many CI checks will run after getting a Code Review. Make sure that | ||
all checks have passed. CI checks are composed of both functional tests and code-style checks and may fail because of warnings/errors in both stages. | ||
|
||
Remember to follow [our codestyle](../docs/CODESTYLE.md). | ||
By following the provided guide and using an automotive code style checking tool, like | ||
**eslint** and **clang-format-9**, you will save some time and help with the code review of proposed changes. | ||
|
||
|
||
## Description of the Pull Request | ||
|
||
Append all PR titles with the `[OV JS]` tag. Provide any relevant details in the description, as it will definitely help with the review. The minimum requirement is a compact, bulleted list of proposed changes. | ||
|
||
Use the following template: | ||
``` | ||
*Describe what is the purpose of this PR* | ||
### Details: | ||
- *Describe your changes.* | ||
- ... | ||
``` | ||
|
||
|
||
## License | ||
|
||
By contributing to the OpenVINO project, you agree that your contributions will be | ||
licensed under the terms of the [LICENSE](https://github.com/openvinotoolkit/openvino/blob/master/LICENSE). |
Oops, something went wrong.