Working with ArrayBuffer Using JSVM-API

Introduction

ArrayBuffer in JavaScript (JS) is a type of object that represents a generic, fixed-length buffer of raw binary data. It provides a way to effectively represent and manipulate raw binary data in JS.

Basic Concepts

  • ArrayBuffer: An ArrayBuffer object represents a generic, fixed-length buffer of raw binary data. The ArrayBuffer content cannot be directly operated. Instead, you need to use a TypedArray or DataView object to interpret the buffer data in specific formats. ArrayBuffer is used to process original binary data of a fixed length, such as files and network data packets.
  • Lifecycle and memory management: When using ArrayBuffer with JSVM-API, pay special attention to lifecycle and memory management, ensuring timely memory release.

Available APIs

API Description
OH_JSVM_GetArraybufferInfo Obtains the underlying data buffer of an ArrayBuffer object and its length.
OH_JSVM_IsArraybuffer Checks whether a JS object is an ArrayBuffer object.
OH_JSVM_DetachArraybuffer Calls the Detach() operation of an ArrayBuffer object.
OH_JSVM_IsDetachedArraybuffer Checks whether an ArrayBuffer object has been detached.
OH_JSVM_CreateArraybuffer Creates an ArrayBuffer object of the specified size.

Example

If you are just starting out with JSVM-API, see JSVM-API Development Process. The following demonstrates only the C++ code involved in ArrayBuffer development.

OH_JSVM_GetArraybufferInfo

Use OH_JSVM_GetArraybufferInfo to obtain the underlying data buffer of an ArrayBuffer object and its length.

CPP code:

// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_GetArraybufferInfo.
static JSVM_Value GetArraybufferInfo(JSVM_Env env, JSVM_CallbackInfo info)
{
    size_t argc = 1;
    JSVM_Value args[1] = {nullptr};
    // Parse the input parameters.
    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    // Check whether the parameter is an ArrayBuffer object.
    bool isArrayBuffer = false;
    OH_JSVM_IsArraybuffer(env, args[0], &isArrayBuffer);
    if (!isArrayBuffer) {
        OH_LOG_ERROR(LOG_APP, "JSVM GetArraybufferInfo isArrayBuffer:false");
        return nullptr;
    }
    void *data;
    size_t byteLength = 0;
    // Obtain the underlying data buffer and length of the ArrayBuffer object.
    JSVM_Status status = OH_JSVM_GetArraybufferInfo(env, args[0], &data, &byteLength);
    if (status != JSVM_OK) {
        OH_LOG_ERROR(LOG_APP, "JSVM GetArraybufferInfo: failed");
    } else {
        OH_LOG_INFO(LOG_APP, "JSVM GetArraybufferInfo: success");
    }
    return args[0];
}
// Register the GetArraybufferInfo callback.
static JSVM_CallbackStruct param[] = {
    {.data = nullptr, .callback = GetArraybufferInfo},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named getArraybufferInfo and associate it with a callback. This allows the GetArraybufferInfo callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
    {"getArraybufferInfo", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Sample test JS code.
const char *srcCallNative = R"JS(
getArraybufferInfo(new ArrayBuffer(10));
)JS";

Expected result:

JSVM GetArraybufferInfo: success

OH_JSVM_IsArraybuffer

Use OH_JSVM_IsArraybuffer to check whether a JS object is an ArrayBuffer object.

CPP code:

// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_IsArraybuffer.
static JSVM_Value IsArrayBuffer(JSVM_Env env, JSVM_CallbackInfo info)
{
    size_t argc = 1;
    JSVM_Value args[1] = {nullptr};
    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    // Call OH_JSVM_IsArraybuffer to check whether the input parameter is an ArrayBuffer object.
    bool isArrayBuffer = false;
    JSVM_Status status = OH_JSVM_IsArraybuffer(env, args[0], &isArrayBuffer);
    if (status != JSVM_OK) {
        OH_LOG_ERROR(LOG_APP, "JSVM IsArrayBuffer: failed");
    } else {
        OH_LOG_INFO(LOG_APP, "JSVM IsArrayBuffer: success");
        OH_LOG_INFO(LOG_APP, "JSVM IsArrayBuffer: %{public}d", isArrayBuffer);
    }
    JSVM_Value boolean = nullptr;
    OH_JSVM_GetBoolean(env, isArrayBuffer, &boolean);
    return boolean;
}
// Register the IsArrayBuffer callback.
static JSVM_CallbackStruct param[] = {
    {.data = nullptr, .callback = IsArrayBuffer},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named isArrayBuffer and associate it with a callback. This allows the IsArrayBuffer callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
    {"isArrayBuffer", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Sample test JS code.
const char *srcCallNative = R"JS(
isArrayBuffer(new ArrayBuffer(8));
)JS";

Expected result:

JSVM IsArrayBuffer: success
JSVM IsArrayBuffer: 1

OH_JSVM_DetachArraybuffer

Use OH_JSVM_DetachArraybuffer to call the Detach() operation of an ArrayBuffer object.

OH_JSVM_IsDetachedArraybuffer

Use OH_JSVM_IsDetachedArraybuffer to check whether an ArrayBuffer object has been detached.

CPP code:

// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_DetachArraybuffer and OH_JSVM_IsDetachedArraybuffer.
static JSVM_Value DetachArraybuffer(JSVM_Env env, JSVM_CallbackInfo info)
{
    size_t argc = 1;
    JSVM_Value args[1] = {nullptr};
    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    JSVM_Value arraybuffer = args[0];
    JSVM_Status status = OH_JSVM_DetachArraybuffer(env, arraybuffer);
    if (status != JSVM_OK) {
        OH_LOG_ERROR(LOG_APP, "JSVM DetachArraybuffer: failed");
    } else {
        OH_LOG_INFO(LOG_APP, "JSVM DetachArraybuffer: success");
    }
    return arraybuffer;
}
static JSVM_Value IsDetachedArraybuffer(JSVM_Env env, JSVM_CallbackInfo info)
{
    size_t argc = 1;
    JSVM_Value args[1] = {nullptr};
    OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
    JSVM_Value arraybuffer = args[0];
    OH_JSVM_DetachArraybuffer(env, arraybuffer);
    bool result = false;
    JSVM_Status status = OH_JSVM_IsDetachedArraybuffer(env, arraybuffer, &result);
    if (status != JSVM_OK) {
        OH_LOG_ERROR(LOG_APP, "JSVM IsDetachedArraybuffer: failed");
    } else {
        OH_LOG_INFO(LOG_APP, "JSVM IsDetachedArraybuffer: success");
        OH_LOG_INFO(LOG_APP, "JSVM IsArrayBuffer: %{public}d", result);
    }
    JSVM_Value isDetached = nullptr;
    OH_JSVM_GetBoolean(env, result, &isDetached);
    return isDetached;
}
// Register the DetachArraybuffer and IsDetachedArraybuffer callbacks.
static JSVM_CallbackStruct param[] = {
    {.data = nullptr, .callback = DetachArraybuffer},
    {.data = nullptr, .callback = IsDetachedArraybuffer},
};
static JSVM_CallbackStruct *method = param;
// Set property descriptors named DetachArraybuffer and IsDetachedArraybuffer, and associate them with a callback each. This allows the DetachArraybuffer and IsDetachedArraybuffer callbacks to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
    {"detachArraybuffer", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
    {"isDetachedArraybuffer", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Sample test JS code.
const char *srcCallNative = R"JS(
let arrayBuffer = new ArrayBuffer(10);
detachArraybuffer(arrayBuffer);
isDetachedArraybuffer(arrayBuffer);
)JS";

Expected result:

JSVM DetachArraybuffer: success
JSVM IsDetachedArraybuffer: success
JSVM IsArrayBuffer: 1

OH_JSVM_CreateArraybuffer

Use OH_JSVM_CreateArraybuffer to create an ArrayBuffer object of the specified size.

CPP code:

// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_CreateArraybuffer.
static JSVM_Value CreateArraybuffer(JSVM_Env env, JSVM_CallbackInfo info)
{
    size_t argc = 1;
    JSVM_Value argv[1] = {nullptr};
    JSVM_Value result = nullptr;
    // Parse the input parameters.
    OH_JSVM_GetCbInfo(env, info, &argc, argv, nullptr, nullptr);
    int32_t value = 0;
    size_t length = 0;
    JSVM_CALL(OH_JSVM_GetValueInt32(env, argv[0], &value));
    length = size_t(value);
    void *data;
    // Create an ArrayBuffer object.
    JSVM_Status status = OH_JSVM_CreateArraybuffer(env, length, &data, &result);
    if (status != JSVM_OK) {
        OH_LOG_ERROR(LOG_APP, "JSVM CreateArraybuffer: failed");
        return nullptr;
    } else {
        OH_LOG_INFO(LOG_APP, "JSVM CreateArraybuffer: success");
        OH_LOG_INFO(LOG_APP, "JSVM ArrayBuffer length: %{public}d", length);
    }
    // Return the created ArrayBuffer.
    return result;
}
// Register the CreateArraybuffer callback.
static JSVM_CallbackStruct param[] = {
    {.data = nullptr, .callback = CreateArraybuffer},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named createArraybuffer and associate it with a callback. This allows the CreateArraybuffer callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
    {"createArraybuffer", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Sample test JS code.
const char *srcCallNative = R"JS(
createArraybuffer(8);
)JS";

Expected result:

JSVM CreateArraybuffer: success
JSVM ArrayBuffer length: 8