Skip to content

Commit

Permalink
n-api: add support for DataView
Browse files Browse the repository at this point in the history
Basic support for Dataview is added in this commit. This is achieved
by using three functions, napi_create_dataview(), napi_is_dataview()
and napi_get_dataview_info().

PR-URL: nodejs#14382
Fixes: nodejs#13926
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
  • Loading branch information
shivanth authored and Gabriel Schulhof committed Apr 10, 2018
1 parent b5ef731 commit 1fe2004
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 0 deletions.
84 changes: 84 additions & 0 deletions doc/api/n-api.md
Expand Up @@ -1331,6 +1331,40 @@ JavaScript TypedArray Objects are described in
[Section 22.2](https://tc39.github.io/ecma262/#sec-typedarray-objects)
of the ECMAScript Language Specification.


#### *napi_create_dataview*
<!-- YAML
added: REPLACEME
-->

```C
napi_status napi_create_dataview(napi_env env,
size_t byte_length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result)

```
- `[in] env`: The environment that the API is invoked under.
- `[in] length`: Number of elements in the DataView.
- `[in] arraybuffer`: ArrayBuffer underlying the DataView.
- `[in] byte_offset`: The byte offset within the ArrayBuffer from which to
start projecting the DataView.
- `[out] result`: A `napi_value` representing a JavaScript DataView.
Returns `napi_ok` if the API succeeded.
This API creates a JavaScript DataView object over an existing ArrayBuffer.
DataView objects provide an array-like view over an underlying data buffer,
but one which allows items of different size and type in the ArrayBuffer.
It is required that `byte_length + byte_offset` is less than or equal to the
size in bytes of the array passed in. If not, a RangeError exception is raised.
JavaScript DataView Objects are described in
[Section 24.3][] of the ECMAScript Language Specification.
### Functions to convert from C types to N-API
#### *napi_create_number*
<!-- YAML
Expand Down Expand Up @@ -1552,6 +1586,36 @@ This API returns various properties of a typed array.
*Warning*: Use caution while using this API since the underlying data buffer
is managed by the VM



#### *napi_get_dataview_info*
<!-- YAML
added: REPLACEME
-->

```C
napi_status napi_get_dataview_info(napi_env env,
napi_value dataview,
size_t* byte_length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset)
```
- `[in] env`: The environment that the API is invoked under.
- `[in] dataview`: `napi_value` representing the DataView whose
properties to query.
- `[out] byte_length`: Number of bytes in the DataView.
- `[out] data`: The data buffer underlying the DataView.
- `[out] arraybuffer`: ArrayBuffer underlying the DataView.
- `[out] byte_offset`: The byte offset within the data buffer from which
to start projecting the DataView.
Returns `napi_ok` if the API succeeded.
This API returns various properties of a DataView.
#### *napi_get_value_bool*
<!-- YAML
added: v8.0.0
Expand Down Expand Up @@ -2019,6 +2083,25 @@ Returns `napi_ok` if the API succeeded.

This API checks if the Object passsed in is a typed array.



### *napi_is_dataview*
<!-- YAML
added: REPLACEME
-->

```C
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result)
```
- `[in] env`: The environment that the API is invoked under.
- `[in] value`: The JavaScript value to check.
- `[out] result`: Whether the given `napi_value` represents a DataView.
Returns `napi_ok` if the API succeeded.
This API checks if the Object passed in is a DataView.
### *napi_strict_equals*
<!-- YAML
added: v8.0.0
Expand Down Expand Up @@ -3165,6 +3248,7 @@ support it:
[Object Wrap]: #n_api_object_wrap
[Section 9.1.6]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc
[Section 12.5.5]: https://tc39.github.io/ecma262/#sec-typeof-operator
[Section 24.3]: https://tc39.github.io/ecma262/#sec-dataview-objects
[Working with JavaScript Functions]: #n_api_working_with_javascript_functions
[Working with JavaScript Properties]: #n_api_working_with_javascript_properties
[Working with JavaScript Values]: #n_api_working_with_javascript_values
Expand Down
66 changes: 66 additions & 0 deletions src/node_api.cc
Expand Up @@ -3019,6 +3019,72 @@ napi_status napi_get_typedarray_info(napi_env env,
return napi_clear_last_error(env);
}

napi_status napi_create_dataview(napi_env env,
size_t byte_length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result) {
NAPI_PREAMBLE(env);
CHECK_ARG(env, arraybuffer);
CHECK_ARG(env, result);

v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);

v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset,
byte_length);

*result = v8impl::JsValueFromV8LocalValue(DataView);
return GET_RETURN_STATUS(env);
}

napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) {
CHECK_ENV(env);
CHECK_ARG(env, value);
CHECK_ARG(env, result);

v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
*result = val->IsDataView();

return napi_clear_last_error(env);
}

napi_status napi_get_dataview_info(napi_env env,
napi_value dataview,
size_t* byte_length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset) {
CHECK_ENV(env);
CHECK_ARG(env, dataview);

v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(dataview);
RETURN_STATUS_IF_FALSE(env, value->IsDataView(), napi_invalid_arg);

v8::Local<v8::DataView> array = value.As<v8::DataView>();

if (byte_length != nullptr) {
*byte_length = array->ByteLength();
}

v8::Local<v8::ArrayBuffer> buffer = array->Buffer();
if (data != nullptr) {
*data = static_cast<uint8_t*>(buffer->GetContents().Data()) +
array->ByteOffset();
}

if (arraybuffer != nullptr) {
*arraybuffer = v8impl::JsValueFromV8LocalValue(buffer);
}

if (byte_offset != nullptr) {
*byte_offset = array->ByteOffset();
}

return napi_clear_last_error(env);
}

napi_status napi_get_version(napi_env env, uint32_t* result) {
CHECK_ENV(env);
CHECK_ARG(env, result);
Expand Down
15 changes: 15 additions & 0 deletions src/node_api.h
Expand Up @@ -494,6 +494,21 @@ NAPI_EXTERN napi_status napi_get_typedarray_info(napi_env env,
napi_value* arraybuffer,
size_t* byte_offset);

NAPI_EXTERN napi_status napi_create_dataview(napi_env env,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result);
NAPI_EXTERN napi_status napi_is_dataview(napi_env env,
napi_value value,
bool* result);
NAPI_EXTERN napi_status napi_get_dataview_info(napi_env env,
napi_value dataview,
size_t* bytelength,
void** data,
napi_value* arraybuffer,
size_t* byte_offset);

// Methods to manage simple async operations
NAPI_EXTERN
napi_status napi_create_async_work(napi_env env,
Expand Down
8 changes: 8 additions & 0 deletions test/addons-napi/test_dataview/binding.gyp
@@ -0,0 +1,8 @@
{
"targets": [
{
"target_name": "test_dataview",
"sources": [ "test_dataview.c" ]
}
]
}
14 changes: 14 additions & 0 deletions test/addons-napi/test_dataview/test.js
@@ -0,0 +1,14 @@
'use strict';
const common = require('../../common');
const assert = require('assert');

// Testing api calls for arrays
const test_dataview = require(`./build/${common.buildType}/test_dataview`);

//create dataview
const buffer = new ArrayBuffer(128);
const template = Reflect.construct(DataView, [buffer]);

const theDataview = test_dataview.CreateDataView(template);
assert.ok(theDataview instanceof DataView,
'The new variable should be of type Dataview');
49 changes: 49 additions & 0 deletions test/addons-napi/test_dataview/test_dataview.c
@@ -0,0 +1,49 @@
#include <node_api.h>
#include <string.h>
#include "../common.h"

napi_value CreateDataView(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args [1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));

NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");

napi_valuetype valuetype;
napi_value input_dataview = args[0];

NAPI_CALL(env, napi_typeof(env, input_dataview, &valuetype));
NAPI_ASSERT(env, valuetype == napi_object,
"Wrong type of arguments. Expects a DataView as the first "
"argument.");

bool is_dataview;
NAPI_CALL(env, napi_is_dataview(env, input_dataview, &is_dataview));
NAPI_ASSERT(env, is_dataview,
"Wrong type of arguments. Expects a DataView as the first "
"argument.");
size_t byte_offset = 0;
size_t length = 0;
napi_value buffer;
NAPI_CALL(env,
napi_get_dataview_info(env, input_dataview, &length, NULL,
&buffer, &byte_offset));

napi_value output_dataview;
NAPI_CALL(env,
napi_create_dataview(env, length, buffer,
byte_offset, &output_dataview));

return output_dataview;
}

void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_PROPERTY("CreateDataView", CreateDataView)
};

NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}

NAPI_MODULE(addon, Init)

0 comments on commit 1fe2004

Please sign in to comment.