Working with BigInt Using JSVM-API
Introduction
BigInt is a data type used to represent integers of any precision in JavaScript (JS), with values greater than the value range of the Number type. You can use JSVM-API to create, obtain, and operate JS BigInt values.
Basic Concepts
Before using JSVM-API to operate BigInt values, you need to understand the following basic concepts:
- BigInt: a data type used to represent integers of any precision in JS. Unlike the Number type, BigInt can accurately represent very large integers without losing precision or causing overflows.
- BigInt creation: You can use JSVM-API to create a JS BigInt object from a C Int64 or Uint64 value. This makes it easy to create BigInt values using C/C++.
- BigInt operation: JSVM-API provides APIs for operating BigInt values. You can use these APIs to obtain and convert BigInt values and perform arithmetic and bitwise operations.
Available APIs
| API | Description |
|---|---|
| OH_JSVM_CreateBigintInt64 | Creates a JS BigInt object from a C int64_t object. |
| OH_JSVM_CreateBigintUint64 | Creates a JS BigInt object from a C uint64_t object. |
| OH_JSVM_CreateBigintWords | Creates a JS BigInt object from a C uint64_t array. |
| OH_JSVM_GetValueBigintInt64 | Obtains the C int64_t primitive equivalent of the given JS BigInt. If necessary, it truncates the value and sets lossless to false. |
| OH_JSVM_GetValueBigintUint64 | Obtains the C uint64_t primitive equivalent of the given JS BigInt. If necessary, it truncates the value and sets lossless to false. |
| OH_JSVM_GetValueBigintWords | Obtains the underlying data (word representation) of a given JS BigInt object. The word representation includes a sign bit, a 64-bit little-endian array, and the length of the array. If signBit and words are set to NULL, only wordCount is obtained. |
Example
If you are just starting out with JSVM-API, see JSVM-API Development Process. The following demonstrates only the C++ code and ArkTS code involved in related APIs.
OH_JSVM_GetValueBigintWords
Use OH_JSVM_GetValueBigintWords to obtain the underlying data of a given JS BigInt object, that is, the word representation of BigInt data.
CPP code:
// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
#include <fstream>
// Define OH_JSVM_GetValueBigintWords.
static JSVM_Value GetValueBigintWords(JSVM_Env env, JSVM_CallbackInfo info) {
size_t argc = 1;
JSVM_Value args[1] = {nullptr};
OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
int signBit = 0;
size_t wordCount = 0;
uint64_t* words{nullptr};
// Call OH_JSVM_GetValueBigintWords to obtain wordCount.
JSVM_Status status = OH_JSVM_GetValueBigintWords(env, args[0], nullptr, &wordCount, nullptr);
OH_LOG_INFO(LOG_APP, "OH_JSVM_GetValueBigintWords wordCount:%{public}d.", wordCount);
words = (uint64_t*)malloc(wordCount*sizeof(uint64_t));
if (words == nullptr) {
OH_LOG_ERROR(LOG_APP, "OH_JSVM_GetValueBigintWords malloc failed.");
return nullptr;
}
// Call OH_JSVM_GetValueBigintWords to obtain BigInt information, such as whether the value passed by signBit is a positive or negative number.
status = OH_JSVM_GetValueBigintWords(env, args[0], &signBit, &wordCount, words);
free(words);
words = nullptr;
if (status != JSVM_OK) {
OH_LOG_ERROR(LOG_APP, "OH_JSVM_GetValueBigintWords fail, status:%{public}d.", status);
} else {
OH_LOG_INFO(LOG_APP, "OH_JSVM_GetValueBigintWords signBit: %{public}d.", signBit);
}
// Convert the sign bit into a value of Int type and pass it.
JSVM_Value returnValue = nullptr;
OH_JSVM_CreateInt32(env, signBit, &returnValue);
return returnValue;
}
// Register the GetValueBigintWords callback.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = GetValueBigintWords},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named getValueBigintWords and associate it with a callback. This allows the GetValueBigintWords callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"getValueBigintWords", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char* srcCallNative = R"JS(getValueBigintWords(BigInt(5555555555555555)))JS";
Expected result:
OH_JSVM_GetValueBigintWords wordCount:1.
OH_JSVM_GetValueBigintWords signBit: 0.
OH_JSVM_CreateBigintWords
Use OH_JSVM_GetValueBigintWords to create a JS BigInt object from a C uint64_t array.
CPP code:
// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_CreateBigintWords.
static int DIFF_VALUE_THREE = 3;
static JSVM_Value CreateBigintWords(JSVM_Env env, JSVM_CallbackInfo info)
{
// Call OH_JSVM_CreateBigintWords to create a BigInt object.
int signBit = 0;
size_t wordCount = DIFF_VALUE_THREE;
uint64_t words[] = {12ULL, 34ULL, 56ULL};
JSVM_Value returnValue = nullptr;
JSVM_Status status = OH_JSVM_CreateBigintWords(env, signBit, wordCount, words, &returnValue);
if (status != JSVM_OK) {
OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateBigintWords fail");
} else {
OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_CreateBigintWords success");
}
return returnValue;
}
// Register the CreateBigintWords callback.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = CreateBigintWords},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named createBigintWords and associate it with a callback. This allows the CreateBigintWords callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"createBigintWords", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char* srcCallNative = R"JS(createBigintWords())JS";
Expected result:
JSVM OH_JSVM_CreateBigintWords success
OH_JSVM_CreateBigintUint64
Use OH_JSVM_CreateBigintUint64 to create a JavaScript BigInt object from a Uint64 object.
CPP code:
// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Declare the variable value of uint64_t.
static uint64_t TEST_VALUE = 5555555555555555555;
// Define OH_JSVM_CreateBigintUint64.
static JSVM_Value CreateBigintUint64(JSVM_Env env, JSVM_CallbackInfo info)
{
// Convert value to the JSVM_Value type and return the value.
JSVM_Value returnValue = nullptr;
JSVM_Status status = OH_JSVM_CreateBigintUint64(env, TEST_VALUE, &returnValue);
if (status != JSVM_OK) {
OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateBigintUint64 fail");
} else {
OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_CreateBigintUint64 success");
}
return returnValue;
}
// Define CreateBigintUint64.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = CreateBigintUint64},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named createBigintUint64 and associate it with a callback. This allows the CreateBigintUint64 callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"createBigintUint64", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char* srcCallNative = R"JS(createBigintUint64())JS";
Expected result:
JSVM OH_JSVM_CreateBigintUint64 success
OH_JSVM_GetValueBigintUint64
Use OH_JSVM_GetValueBigintUint64 to obtain the C uint64_t primitive equivalent of the given JS BigInt object.
CPP code:
// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_GetValueBigintUint64.
static JSVM_Value GetValueBigintUint64(JSVM_Env env, JSVM_CallbackInfo info)
{
size_t argc = 1;
JSVM_Value args[1] = {nullptr};
OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
// Obtain the BigInt value.
uint64_t value = 0;
bool lossLess = false;
OH_JSVM_GetValueBigintUint64(env, args[0], &value, &lossLess);
// Check whether the BigInt value obtained is a product of lossless conversion. If no, an exception is thrown.
if (!lossLess) {
OH_JSVM_ThrowError(env, nullptr, "BigInt values have no lossless converted");
return nullptr;
} else {
OH_LOG_INFO(LOG_APP, "JSVM GetValueBigintUint64 success");
}
JSVM_Value returnValue = nullptr;
OH_JSVM_CreateBigintUint64(env, value, &returnValue);
return returnValue;
}
// Register the GetValueBigintUint64 callback.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = GetValueBigintUint64},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named getValueBigintUint64 and associate it with a callback. This allows the GetValueBigintUint64 callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"getValueBigintUint64", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char* srcCallNative = R"JS(getValueBigintUint64(BigInt(5555555555555555)))JS";
Expected result:
JSVM GetValueBigintUint64 success
OH_JSVM_CreateBigintInt64
Use OH_JSVM_CreateBigintInt64 to create a JavaScript BigInt object from an int64_t object.
CPP code:
// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Declare the variable value of int64_t.
static int64_t TEST_VALUE_DEMO = -5555555555555555555;
// Define OH_JSVM_CreateBigintInt64.
static JSVM_Value CreateBigintInt64(JSVM_Env env, JSVM_CallbackInfo info)
{
JSVM_Value returnValue = nullptr;
JSVM_Status status = OH_JSVM_CreateBigintInt64(env, TEST_VALUE_DEMO, &returnValue);
if (status != JSVM_OK) {
OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_CreateBigintInt64 fail");
} else {
OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_CreateBigintInt64 success");
}
return returnValue;
}
// Register the CreateBigintInt64 callback.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = CreateBigintInt64},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named createBigintInt64 and associate it with a callback. This allows the CreateBigintInt64 callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"createBigintInt64", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char* srcCallNative = R"JS(createBigintInt64())JS";
Expected result:
JSVM OH_JSVM_CreateBigintInt64 success
OH_JSVM_GetValueBigintInt64
Use OH_JSVM_GetValueBigintInt64 to obtain the C int64_t primitive equivalent of the given JS BigInt object.
CPP code:
// hello.cpp
#include "napi/native_api.h"
#include "ark_runtime/jsvm.h"
#include <hilog/log.h>
// Define OH_JSVM_GetValueBigintInt64.
static JSVM_Value GetBigintInt64(JSVM_Env env, JSVM_CallbackInfo info)
{
size_t argc = 1;
JSVM_Value args[1] = {nullptr};
OH_JSVM_GetCbInfo(env, info, &argc, args, nullptr, nullptr);
// Obtain the 64-bit big integer from the input parameter.
int64_t value = 0;
bool lossLess = false;
OH_JSVM_GetValueBigintInt64(env, args[0], &value, &lossLess);
// Check whether the BigInt value obtained is a product of lossless conversion. If no, an exception is thrown.
if (!lossLess) {
OH_JSVM_ThrowError(env, nullptr, "BigInt values have no lossless converted");
return nullptr;
} else {
OH_LOG_INFO(LOG_APP, "JSVM GetBigintInt64 success");
}
JSVM_Value returnValue = nullptr;
OH_JSVM_CreateBigintInt64(env, value, &returnValue);
return returnValue;
}
// Register the GetBigintInt64 callback.
static JSVM_CallbackStruct param[] = {
{.data = nullptr, .callback = GetBigintInt64},
};
static JSVM_CallbackStruct *method = param;
// Set a property descriptor named getBigintInt64 and associate it with a callback. This allows the GetBigintInt64 callback to be called from JS.
static JSVM_PropertyDescriptor descriptor[] = {
{"getBigintInt64", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
};
// Call the C++ code from JS.
const char* srcCallNative = R"JS(getBigintInt64(BigInt(-5555555555555555)))JS";
Expected result:
JSVM GetValueBigintUint64 success