JSVM-API 支持的数据类型和接口
===================

#### JSVM-API 的数据类型

#### \[h2\]JSVM\_Status

这是一个枚举数据类型，用来表示JSVM-API接口返回的状态信息。

每调用一次JSVM-API函数，都会返回一个值，用来表示操作成功与否的相关信息。

    typedef enum {
        JSVM\_OK,                              /\* 成功状态 \*/
        JSVM\_INVALID\_ARG,                     /\* 无效的状态 \*/
        JSVM\_OBJECT\_EXPECTED,                 /\* 期待传入对象类型 \*/
        JSVM\_STRING\_EXPECTED,                 /\* 期待传入字符串类型 \*/
        JSVM\_NAME\_EXPECTED,                   /\* 期待传入名字 \*/
        JSVM\_FUNCTION\_EXPECTED,               /\* 期待传入函数类型 \*/
        JSVM\_NUMBER\_EXPECTED,                 /\* 期待传入数字类型 \*/
        JSVM\_BOOL\_EXPECTED,                   /\* 期待传入布尔类型 \*/
        JSVM\_ARRAY\_EXPECTED,                  /\* 期待传入数组类型 \*/
        JSVM\_GENERIC\_FAILURE,                 /\* 泛型失败状态 \*/
        JSVM\_PENDING\_EXCEPTION,               /\* 挂起异常状态 \*/
        JSVM\_CANCELLED,                       /\* 取消状态 \*/
        JSVM\_ESCAPE\_CALLED\_TWICE,             /\* 转义调用了2次 \*/
        JSVM\_HANDLE\_SCOPE\_MISMATCH,           /\* 句柄作用域不匹配 \*/
        JSVM\_CALLBACK\_SCOPE\_MISMATCH,         /\* 回调作用域不匹配 \*/
        JSVM\_QUEUE\_FULL,                      /\* 队列满 \*/
        JSVM\_CLOSING,                         /\* 关闭中 \*/
        JSVM\_BIGINT\_EXPECTED,                 /\* 期望传入Bigint类型 \*/
        JSVM\_DATE\_EXPECTED,                   /\* 期望传入日期类型 \*/
        JSVM\_ARRAYBUFFER\_EXPECTED,            /\* 期望传入ArrayBuffer类型 \*/
        JSVM\_DETACHABLE\_ARRAYBUFFER\_EXPECTED, /\* 可分离的数组缓冲区预期状态 \*/
        JSVM\_WOULD\_DEADLOCK,                  /\* 将死锁状态 \*/
        JSVM\_NO\_EXTERNAL\_BUFFERS\_ALLOWED,     /\* 不允许外部缓冲区 \*/
        JSVM\_CANNOT\_RUN\_JS,                   /\* 不能执行JS \*/
        JSVM\_INVALID\_TYPE,                    /\* 非法类型 \*/
        JSVM\_JIT\_MODE\_EXPECTED,                /\* 期望在JIT模式下执行 \*/
    } JSVM\_Status;

#### \[h2\]JSVM\_ExtendedErrorInfo

一个结构体，在调用函数不成功时存储了较为详细的错误信息。

typedef struct {
    const char\* errorMessage;
    void\* engineReserved;
    uint32\_t engineErrorCode;
    JSVM\_Status errorCode;
} JSVM\_ExtendedErrorInfo;

#### \[h2\]JSVM\_Value

在C++代码中，用于表示JavaScript值。

#### \[h2\]JSVM\_Env

*   表示JSVM-API执行时的上下文，作为Native函数的参数传递给JSVM-API接口。
    
*   退出Native侧插件时，JSVM\_Env将失效，该事件通过回调传递给OH\_JSVM\_SetInstanceData接口。
    
*   禁止缓存JSVM\_Env，并禁止在不同Worker中传递JSVM\_Env。
    
*   在不同线程间共享JSVM\_Env时，要保证在线程切换时在前一个线程中关闭env scope并在新的线程中打开新的env scope，以保证threadlocal变量的线程隔离。
    

#### \[h2\]JSVM\_ValueType

JSVM\_Value的类型。包含了ECMAScript语言规范中定义的类型，其中JSVM\_EXTERNAL表示外部数据类型。

typedef enum {
    JSVM\_UNDEFINED,
    JSVM\_NULL,
    JSVM\_BOOLEAN,
    JSVM\_NUMBER,
    JSVM\_STRING,
    JSVM\_SYMBOL,
    JSVM\_OBJECT,
    JSVM\_FUNCTION,
    JSVM\_EXTERNAL,
    JSVM\_BIGINT,
} JSVM\_ValueType;

#### \[h2\]JSVM\_TypedarrayType

TypedArray 的基本二进制标量数据类型。

typedef enum {
    JSVM\_INT8\_ARRAY,
    JSVM\_UINT8\_ARRAY,
    JSVM\_UINT8\_CLAMPED\_ARRAY,
    JSVM\_INT16\_ARRAY,
    JSVM\_UINT16\_ARRAY,
    JSVM\_INT32\_ARRAY,
    JSVM\_UINT32\_ARRAY,
    JSVM\_FLOAT32\_ARRAY,
    JSVM\_FLOAT64\_ARRAY,
    JSVM\_BIGINT64\_ARRAY,
    JSVM\_BIGUINT64\_ARRAY,
} JSVM\_TypedarrayType;

#### \[h2\]JSVM\_RegExpFlags

正则表达式标志位。

typedef enum {
    JSVM\_REGEXP\_NONE = 0,
    JSVM\_REGEXP\_GLOBAL = 1 << 0,
    JSVM\_REGEXP\_IGNORE\_CASE = 1 << 1,
    JSVM\_REGEXP\_MULTILINE = 1 << 2,
    JSVM\_REGEXP\_STICKY = 1 << 3,
    JSVM\_REGEXP\_UNICODE = 1 << 4,
    JSVM\_REGEXP\_DOT\_ALL = 1 << 5,
    JSVM\_REGEXP\_LINEAR = 1 << 6,
    JSVM\_REGEXP\_HAS\_INDICES = 1 << 7,
    JSVM\_REGEXP\_UNICODE\_SETS = 1 << 8,
} JSVM\_RegExpFlags;

#### \[h2\]编译选项相关类型

**JSVM\_CompileOptions**

配合 OH\_JSVM\_CompileScriptWithOptions 接口使用，是其参数中 options 数组的元素类型。

其中：

*   id 代表这个编译选项的类型。
*   content 代表编译选项的内容。

id 的值和 content 的类型需对应使用，具体对应关系请参见各选项类型的介绍。

typedef struct {
    /\*\* compile option id. \*/
    JSVM\_CompileOptionId id;
    /\*\* option content. \*/
    union {
      /\*\* ptr type. \*/
      void \*ptr;
      /\*\* int type. \*/
      int num;
      /\*\* bool type. \*/
      \_Bool boolean;
    } content;
} JSVM\_CompileOptions;

**JSVM\_CompileOptionId**

JSVM\_CompileOptions 中的 id 对应类型，每个值有对应的 content 类型。JSVM\_COMPILE\_ENABLE\_SOURCE\_MAP 的类型为 bool，当 JSVM\_ScriptOrigin 中的 sourceMapUrl 不为空时生效。

typedef enum {
    /\*\* compile mode. \*/
    JSVM\_COMPILE\_MODE,
    /\*\* code cache content. \*/
    JSVM\_COMPILE\_CODE\_CACHE,
    /\*\* script origin. \*/
    JSVM\_COMPILE\_SCRIPT\_ORIGIN,
    /\*\* compile profile content. \*/
    JSVM\_COMPILE\_COMPILE\_PROFILE,
    /\*\* switch for source map support. \*/
    JSVM\_COMPILE\_ENABLE\_SOURCE\_MAP,
    /\*\* background deserialize code cache result.
     \* @since 24
     \*/
    JSVM\_COMPILE\_BACKGROUND\_DESERIALIZE\_RESULT,
    /\*\* whether the code cache is rejected.
     \* @since 24
     \*/
    JSVM\_COMPILE\_CODE\_CACHE\_REJECTED,
} JSVM\_CompileOptionId;

**JSVM\_CompileMode**

当 id 为 JSVM\_COMPILE\_MODE 时，content 类型的每个值代表一种编译模式。

*   JSVM\_COMPILE\_MODE\_DEFAULT : 默认的编译选项。
*   JSVM\_COMPILE\_MODE\_CONSUME\_CODE\_CACHE : 消耗 codecache 进行编译。
*   JSVM\_COMPILE\_MODE\_EAGER\_COMPILE : 进行全量编译，不再进行 lazy compile。
*   JSVM\_COMPILE\_MODE\_PRODUCE\_COMPILE\_PROFILE/JSVM\_COMPILE\_MODE\_CONSUME\_COMPILE\_PROFILE : 当前暂无效果，请等待后续更新。

typedef enum {
    /\*\* default mode. \*/
    JSVM\_COMPILE\_MODE\_DEFAULT,
    /\*\* consume code cache. \*/
    JSVM\_COMPILE\_MODE\_CONSUME\_CODE\_CACHE,
    /\*\* apply eager compile. \*/
    JSVM\_COMPILE\_MODE\_EAGER\_COMPILE,
    /\*\* preset for compile profile. \*/
    JSVM\_COMPILE\_MODE\_PRODUCE\_COMPILE\_PROFILE,
    /\*\* consume compile profile. \*/
    JSVM\_COMPILE\_MODE\_CONSUME\_COMPILE\_PROFILE,
} JSVM\_CompileMode;

**JSVM\_CodeCache**

当 id 为 JSVM\_COMPILE\_CODE\_CACHE 时，content 的类型为：

*   cache : 指向 code cache 的指针。
*   length : 代表 code cache 的大小。

typedef struct {
    /\*\* cache pointer. \*/
    uint8\_t \*cache;
    /\*\* length. \*/
    size\_t length;
} JSVM\_CodeCache;

**JSVM\_ScriptOrigin**

当 id 为 JSVM\_COMPILE\_SCRIPT\_ORIGIN 时，content 存放待编译脚本的源码信息。

*   sourceMapUrl : sourceMap 的路径，当前仅支持运行设备上的本地路径，可以为空。
*   resourceName : 待编译的 js script 的名字。

typedef struct {
    /\*\* Sourcemap url. \*/
    const char\* sourceMapUrl;
    /\*\* Resource name. \*/
    const char\* resourceName;
    /\*\* Resource line offset. \*/
    size\_t resourceLineOffset;
    /\*\* Resource column offset. \*/
    size\_t resourceColumnOffset;
} JSVM\_ScriptOrigin;

#### \[h2\]内存管理类型

JSVM-API 包含以下内存管理类型：

**JSVM\_HandleScope**

JSVM\_HandleScope 数据类型用于管理 JavaScript 对象的生命周期。它确保在指定范围内创建的 JavaScript 对象保持活动状态，直到该范围结束。这样可以防止使用已释放的对象，提高代码的可靠性和性能。

**JSVM\_EscapableHandleScope**

*   由 OH\_JSVM\_OpenEscapableHandleScope 接口创建，由 OH\_JSVM\_CloseEscapableHandleScope 接口关闭。
    
*   表示一种特殊类型的句柄范围，用于将在JSVM\_EscapableHandleScope范围内创建的值返回给父scope。
    
*   用于 OH\_JSVM\_EscapeHandle 接口，将 JSVM\_EscapableHandleScope 范围内的值提升为 JavaScript 对象，以便在外部作用域使用。
    

**JSVM\_Ref**

指向JSVM\_Value，允许开发者管理JavaScript值的生命周期。

**JSVM\_TypeTag**

该结构体定义了一个包含两个无符号64位整数的类型标签，用于标识一个JSVM-API值的类型信息。

typedef struct {
    uint64\_t lower;
    uint64\_t upper;
} JSVM\_TypeTag;

*   存储了两个无符号64位整数的128位值，用它来标识JavaScript对象，确保它们属于某种类型。
    
*   比OH\_JSVM\_Instanceof更强的类型检查，如果对象的原型被操纵，OH\_JSVM\_Instanceof可能会报告误报。
    
*   JSVM\_TypeTag 在与 OH\_JSVM\_Wrap 结合使用时最有用，因为它确保从包装对象检索的指针可以安全地转换为与先前应用于JavaScript对象的类型标签相对应的Native类型。
    

#### \[h2\]回调类型

JSVM-API包含以下回调类型：

**JSVM\_CallbackStruct**

用户提供的 Native callback 的回调函数指针和数据，JSVM\_CallbackStruct 将通过 JSVM-API 暴露给 JavaScript。例如，可以使用 OH\_JSVM\_CreateFunction 接口创建绑定到 Native callback 的 JS 函数，其中 Native callback 就是通过 JSVM\_CallbackStruct 结构定义。除非在对象生命周期管理中有特殊要求，一般不在此 callback 中创建 handle 或者 callback scope。

typedef struct {
  JSVM\_Value(\*callback)(JSVM\_Env env, JSVM\_CallbackInfo info);
  void\* data;
} JSVM\_CallbackStruct;

**JSVM\_Callback**

JSVM\_CallbackStruct 指针类型的别名。

定义如下:

typedef JSVM\_CallbackStruct\* JSVM\_Callback;

**JSVM\_CallbackInfo**

用户定义的 Native callback，第一个参数类型是 JSVM\_Env，第二个参数类型是 JSVM\_CallbackInfo。JSVM\_CallbackInfo 表示从 JS 侧调用到 Native 侧时携带的调用信息，如参数列表。在实现 Native callback 时，一般使用 OH\_JSVM\_GetCbInfo 接口从 JSVM\_CallbackInfo 中获取调用信息。

**JSVM\_Finalize**

函数指针，用于传入OH\_JSVM\_SetInstanceData、OH\_JSVM\_CreateExternal、OH\_JSVM\_Wrap等接口。JSVM\_Finalize在对象被回收后会被调用，可用于在JavaScript对象被垃圾回收时释放Native对象。JSVM 不保证是否执行该回调函数，也不保证执行该回调函数的时机，**开发者不应依赖于该回调的执行时机**。

写法如下：

typedef void (\*JSVM\_Finalize)(JSVM\_Env env, void\* finalizeData, void\* finalizeHint);

**JSVM\_PropertyHandlerConfigurationStruct**

当执行对象的getter、setter、deleter和enumerator操作时，对应的回调将会触发。

typedef struct {
    JSVM\_Value(JSVM\_CDECL\* genericNamedPropertyGetterCallback)(JSVM\_Env env,
                                                               JSVM\_Value name,
                                                               JSVM\_Value thisArg,
                                                               JSVM\_Value namedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericNamedPropertySetterCallback)(JSVM\_Env env,
                                                               JSVM\_Value name,
                                                               JSVM\_Value property,
                                                               JSVM\_Value thisArg,
                                                               JSVM\_Value namedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericNamedPropertyDeleterCallback)(JSVM\_Env env,
                                                                JSVM\_Value name,
                                                                JSVM\_Value thisArg,
                                                                JSVM\_Value namedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericNamedPropertyEnumeratorCallback)(JSVM\_Env env,
                                                                   JSVM\_Value thisArg,
                                                                   JSVM\_Value namedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericIndexedPropertyGetterCallback)(JSVM\_Env env,
                                                                JSVM\_Value index,
                                                                JSVM\_Value thisArg,
                                                                JSVM\_Value indexedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericIndexedPropertySetterCallback)(JSVM\_Env env,
                                                                 JSVM\_Value index,
                                                                 JSVM\_Value property,
                                                                 JSVM\_Value thisArg,
                                                                 JSVM\_Value indexedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericIndexedPropertyDeleterCallback)(JSVM\_Env env,
                                                                  JSVM\_Value index,
                                                                  JSVM\_Value thisArg,
                                                                  JSVM\_Value indexedPropertyData);
    JSVM\_Value(JSVM\_CDECL\* genericIndexedPropertyEnumeratorCallback)(JSVM\_Env env,
                                                                     JSVM\_Value thisArg,
                                                                     JSVM\_Value indexedPropertyData);
    JSVM\_Value namedPropertyData;
    JSVM\_Value indexedPropertyData;
} JSVM\_PropertyHandlerConfigurationStruct;

**JSVM\_PropertyHandlerCfg**

包含属性监听回调的结构指针。

基本用法如下:

typedef JSVM\_PropertyHandlerConfigurationStruct\* JSVM\_PropertyHandlerCfg;

#### 支持的JSVM-API接口

标准JS引擎的能力通过JSVM-API提供。JSVM-API支持动态链接到不同版本的JS引擎库，从而为开发者屏蔽掉不同引擎接口的差异。JSVM-API提供引擎生命周期管理、JS context管理、JS代码执行、JS/C++互操作、执行环境快照、codecache等能力，具体可见下文。

#### \[h2\]使用 JSVM-API 接口创建引擎实例及 JS 执行上下文环境

**场景介绍**

执行JS代码需要先创建JavaScript VM，创建JS执行的上下文环境。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_Init | 初始化JavaScript引擎实例 |
| OH\_JSVM\_CreateVM | 创建JavaScript引擎实例 |
| OH\_JSVM\_DestroyVM | 销毁JavaScript引擎实例 |
| OH\_JSVM\_OpenVMScope | 打开一个新的VM scope，引擎实例只能在scope范围内使用，可以保证引擎实例不被销毁 |
| OH\_JSVM\_CloseVMScope | 关闭VM scope |
| OH\_JSVM\_CreateEnv | 创建一个新的JS执行上下文环境，并注册指定的Native函数 |
| OH\_JSVM\_DestroyEnv | 销毁一个JS执行上下文环境 |
| OH\_JSVM\_OpenEnvScope | 打开一个新的Env scope，Env只能在scope范围内使用 |
| OH\_JSVM\_CloseEnvScope | 关闭Env scope |
| OH\_JSVM\_OpenHandleScope | 打开一个Handle scope，确保scope范围内的JSVM\_Value不被GC回收 |
| OH\_JSVM\_CloseHandleScope | 关闭Handle scope |

**JSVM\_InitOptions 的使用描述**

JSVM 提供了多种配置选项，允许开发者在执行 OH\_JSVM\_Init 时灵活配置其行为。可以通过 OH\_JSVM\_GetVMInfo 接口获取当前 JSVM 版本所对应的 V8 引擎版本。JSVM 中可支持的选项范围与对应的 V8 引擎版本可支持的选项范围保持一致。OH\_JSVM\_GetVMInfo 接口的使用参考[使用JSVM-API接口获取JSVM API的版本号](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-about-version)。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/90/v3/-Yy2h_ELTqqH1lncbQv4eA/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132818Z&HW-CC-Expire=86400&HW-CC-Sign=6657576AE13497FDA9882AF0B68832A9193A182130ED0739595AD9FBD3AEFD2A)

*   建议开发者在没有特殊需求的情况下，仅使用JSVM内部的默认配置选项。

场景示例：

常规模式下初始化 VM 平台。

static void NormalInit(bool &vmInit) {
    if (!vmInit) {
        // JSVM only need init once
        JSVM\_InitOptions initOptions;
        memset(&initOptions, 0, sizeof(initOptions));
        JSVM\_Status cond = OH\_JSVM\_Init(&initOptions);
        if(cond == JSVM\_OK) {
            vmInit = true;
        } else {
            vmInit = false;
        }
    }
}

场景示例：

初始化低内存占用的 VM 平台。

static void LowMemoryInit(bool &vmInit) {
    if (!vmInit) {
        // JSVM only need init once
        JSVM\_InitOptions initOptions;
        int argc = 4;
        initOptions.argc = &argc;
        const char\* argv\[4\];
        argv\[1\] = "--incremental-marking-hard-trigger=40";
        argv\[2\] = "--min-semi-space-size=1";
        argv\[3\] = "--max-semi-space-size=4";
        initOptions.argv = const\_cast<char\*\*>(argv);
        OH\_JSVM\_Init(&initOptions);
        vmInit = true;
    }
}

场景示例：

初始化低GC触发频次的 VM 平台。

static void LowGCFrequencyInit(bool &vmInit) {
    if (!vmInit) {
        // JSVM only need init once
        JSVM\_InitOptions initOptions;
        int argc = 4;
        initOptions.argc = &argc;
        const char\* argv\[4\];
        argv\[1\] = "--incremental-marking-hard-trigger=80";
        argv\[2\] = "--min-semi-space-size=16";
        argv\[3\] = "--max-semi-space-size=16";
        initOptions.argv = const\_cast<char\*\*>(argv);
        OH\_JSVM\_Init(&initOptions);
        vmInit = true;
    }
}

执行结果：

使用以上三个接口可以分别初始化具备不同特性的 VM 平台。初始化之后，可以创建 VM 实例，并执行 JavaScript 脚本。

相比 NormalInit 接口，LowGCFrequencyInit 接口初始化的VM平台 GC 触发频次更低。

相比 NormalInit 接口，LowMemoryInit 接口初始化的VM平台内存占用更少。

**创建 VM 实例**

场景示例:

创建及销毁 JavaScript 引擎实例，包含创建及销毁 JS 执行上下文环境

bool VM\_INIT = false;

static JSVM\_Value ConsoleInfo(JSVM\_Env env, JSVM\_CallbackInfo info) {
    size\_t argc = 1;
    JSVM\_Value args\[1\];
    char log\[256\] = "";
    size\_t logLength = 0;
    OH\_JSVM\_GetCbInfo(env, info, &argc, args, NULL, NULL);

    OH\_JSVM\_GetValueStringUtf8(env, args\[0\], log, 255, &logLength);
    log\[255\] = 0;
    OH\_LOG\_INFO(LOG\_APP, "JSVM API TEST: %{public}s", log);
    return nullptr;
}

static JSVM\_Value Add(JSVM\_Env env, JSVM\_CallbackInfo info) {
    size\_t argc = 2;
    JSVM\_Value args\[2\];
    OH\_JSVM\_GetCbInfo(env, info, &argc, args, NULL, NULL);
    double num1 = 0;
    double num2 = 0;
    OH\_JSVM\_GetValueDouble(env, args\[0\], &num1);
    OH\_JSVM\_GetValueDouble(env, args\[1\], &num2);
    JSVM\_Value sum = nullptr;
    OH\_JSVM\_CreateDouble(env, num1 + num2, &sum);
    return sum;
}

static napi\_value MyJSVMDemo(\[\[maybe\_unused\]\] napi\_env \_env, \[\[maybe\_unused\]\] napi\_callback\_info \_info) {
    std::thread t(\[\]() {
        // 可以根据不同的业务需求初始化具备不同能力的 VM 平台：
        // 1. 初始化默认的 VM 平台：调用'NormalInit'接口。
        // 2. 初始化低内存占用的 VM 平台：调用'LowMemoryInit'接口。
        // 3. 初始化低 GC 触发频次的 VM 平台：调用'LowGCFrequencyInit'接口。
        NormalInit(VM\_INIT);
        // create vm, and open vm scope
        JSVM\_VM vm;
        JSVM\_CreateVMOptions options;
        memset(&options, 0, sizeof(options));
        OH\_JSVM\_CreateVM(&options, &vm);

        JSVM\_VMScope vmScope;
        OH\_JSVM\_OpenVMScope(vm, &vmScope);

        JSVM\_CallbackStruct param\[\] = {
            {.data = nullptr, .callback = ConsoleInfo},
            {.data = nullptr, .callback = Add},
        };
        JSVM\_PropertyDescriptor descriptor\[\] = {
            {"consoleinfo", NULL, &param\[0\], NULL, NULL, NULL, JSVM\_DEFAULT},
            {"add", NULL, &param\[1\], NULL, NULL, NULL, JSVM\_DEFAULT},
        };
        // create env, register native method, and open env scope
        JSVM\_Env env;
        OH\_JSVM\_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor\[0\]), descriptor, &env);

        JSVM\_EnvScope envScope;
        OH\_JSVM\_OpenEnvScope(env, &envScope);

        // open handle scope
        JSVM\_HandleScope handleScope;
        OH\_JSVM\_OpenHandleScope(env, &handleScope);

        std::string sourceCodeStr = "\\
        {\\
            let value = add(4.96, 5.28);\\
            consoleinfo('Result is:' + value);\\
        }";
        // compile js script
        JSVM\_Value sourceCodeValue;
        OH\_JSVM\_CreateStringUtf8(env, sourceCodeStr.c\_str(), sourceCodeStr.size(), &sourceCodeValue);
        JSVM\_Script script;
        OH\_JSVM\_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script);
        JSVM\_Value result;
        // run js script
        OH\_JSVM\_RunScript(env, script, &result);
        JSVM\_ValueType type;
        OH\_JSVM\_Typeof(env, result, &type);
        OH\_LOG\_INFO(LOG\_APP, "JSVM API TEST type: %{public}d", type);

        // exit vm and clean memory
        OH\_JSVM\_CloseHandleScope(env, handleScope);

        OH\_JSVM\_CloseEnvScope(env, envScope);
        OH\_JSVM\_DestroyEnv(env);

        OH\_JSVM\_CloseVMScope(vm, vmScope);
        OH\_JSVM\_DestroyVM(vm);
    });

    t.detach();

    return nullptr;
}

#### \[h2\]使用 JSVM-API 接口编译及执行 JS 代码

**场景介绍**

编译及执行JS代码。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CompileScript | 编译JavaScript代码并返回绑定到当前环境的编译脚本 |
| OH\_JSVM\_CompileScriptWithOrigin | 编译JavaScript代码并返回绑定到当前环境的编译脚本，同时传入包括 sourceMapUrl 和源文件名在内的源代码信息，用于处理 source map 信息 |
| OH\_JSVM\_CompileScriptWithOptions | 通用的编译接口，通过传入 option 数组完成前面的 compile 接口全部功能，同时支持后续选项扩展 |
| OH\_JSVM\_CreateCodeCache | 为编译脚本创建code cache |
| OH\_JSVM\_RunScript | 执行编译脚本，如果没有 JIT 权限支持，执行含wasm的脚本会失败，在特定场景下存在性能差异，并打印一行日志提示开发者 |

场景示例：

编译及执行 JS 代码（创建 VM 实例，注册函数，执行 JS，销毁 VM 实例）

cpp 部分代码

#include <cstring>
#include <fstream>
#include <string>
#include <vector>

// 依赖libjsvm.so
#include "ark\_runtime/jsvm.h"

using namespace std;

static JSVM\_Value Hello(JSVM\_Env env, JSVM\_CallbackInfo info) {
    JSVM\_Value output;
    void\* data = nullptr;
    OH\_JSVM\_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data);
    OH\_JSVM\_CreateStringUtf8(env, (char\*)data, strlen((char\*)data), &output);
    return output;
}

static JSVM\_CallbackStruct hello\_cb = { Hello, (void\*)"Hello" };

static string srcGlobal = R"JS(
const concat = (...args) => args.reduce((a, b) => a + b);
)JS";

static void RunScriptWithOption(JSVM\_Env env, string& src,
                                uint8\_t\*\* dataPtr = nullptr,
                                size\_t\* lengthPtr = nullptr) {
    JSVM\_HandleScope handleScope;
    OH\_JSVM\_OpenHandleScope(env, &handleScope);

    JSVM\_Value jsSrc;
    OH\_JSVM\_CreateStringUtf8(env, src.c\_str(), src.size(), &jsSrc);

    uint8\_t\* data = dataPtr ? \*dataPtr : nullptr;
    auto compileMode = data ? JSVM\_COMPILE\_MODE\_CONSUME\_CODE\_CACHE :  JSVM\_COMPILE\_MODE\_DEFAULT;
    size\_t length = lengthPtr ? \*lengthPtr : 0;
    JSVM\_Script script;
    // 编译js代码
    JSVM\_ScriptOrigin origin {
        // 以包名 helloworld 为例, 假如存在对应的 sourcemap, sourcemap 的路径可以是 /data/app/el2/100/base/com.example.helloworld/files/index.js.map
        .sourceMapUrl = "/data/app/el2/100/base/com.example.helloworld/files/index.js.map",
        // 源文件名字
        .resourceName = "index.js",
        // script 在源文件中的起始行列号
        .resourceLineOffset = 0,
        .resourceColumnOffset = 0,
    };
    JSVM\_CompileOptions option\[3\];
    option\[0\] = {
        .id = JSVM\_COMPILE\_MODE,
        .content = { .num = compileMode }
    };
    JSVM\_CodeCache codeCache = {
        .cache = data,
        .length = length
    };
    option\[1\] = {
        .id = JSVM\_COMPILE\_CODE\_CACHE,
        .content = { .ptr = &codeCache }
    };
    // JSVM\_COMPILE\_ENABLE\_SOURCE\_MAP 选项默认值为 false，若为 true 那么对应的 sourceMapUrl 必须不为空
    option\[2\] = {
        .id = JSVM\_COMPILE\_ENABLE\_SOURCE\_MAP,
        .content = { .boolean = true }
    };
    OH\_JSVM\_CompileScriptWithOptions(env, jsSrc, 3, option, &script);

    JSVM\_Value result;
    // 执行js代码
    OH\_JSVM\_RunScript(env, script, &result);

    char resultStr\[128\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, result, resultStr, 128, &size);

    OH\_JSVM\_CloseHandleScope(env, handleScope);
}

static void RunScript(JSVM\_Env env, string& src,
                       bool withOrigin = false,
                       uint8\_t\*\* dataPtr = nullptr,
                       size\_t\* lengthPtr = nullptr) {
    JSVM\_HandleScope handleScope;
    OH\_JSVM\_OpenHandleScope(env, &handleScope);

    JSVM\_Value jsSrc;
    OH\_JSVM\_CreateStringUtf8(env, src.c\_str(), src.size(), &jsSrc);

    uint8\_t\* data = dataPtr ? \*dataPtr : nullptr;
    size\_t length = lengthPtr ? \*lengthPtr : 0;
    bool cacheRejected = true;
    JSVM\_Script script;
    // 编译js代码
    if (withOrigin) {
        JSVM\_ScriptOrigin origin {
            // 以包名 helloworld 为例, 假如存在对应的 sourcemap, sourcemap 的路径可以是 /data/app/el2/100/base/com.example.helloworld/files/index.js.map
            .sourceMapUrl = "/data/app/el2/100/base/com.example.helloworld/files/index.js.map",
            // 源文件名字
            .resourceName = "index.js",
            // script 在源文件中的起始行列号
            .resourceLineOffset = 0,
            .resourceColumnOffset = 0,
        };
        OH\_JSVM\_CompileScriptWithOrigin(env, jsSrc, data, length, true, &cacheRejected, &origin, &script);
    } else {
        OH\_JSVM\_CompileScript(env, jsSrc, data, length, true, &cacheRejected, &script);
    }
    printf("Code cache is %s\\n", cacheRejected ? "rejected" : "used");

    JSVM\_Value result;
    // 执行js代码
    OH\_JSVM\_RunScript(env, script, &result);

    char resultStr\[128\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, result, resultStr, 128, &size);

    OH\_JSVM\_CloseHandleScope(env, handleScope);
}

void RunWithOption(uint8\_t\*\* dataPtr, size\_t\* lengthPtr) {
    // 创建虚拟机实例
    JSVM\_VM vm;
    OH\_JSVM\_CreateVM(nullptr, &vm);
    JSVM\_VMScope vmScope;
    OH\_JSVM\_OpenVMScope(vm, &vmScope);

    JSVM\_Env env;
    // 将native函数注册成js可调用的方法，hello\_cb中记录该native方法的指针和参数等信息
    JSVM\_PropertyDescriptor descriptors\[\] = {
        { "hello", NULL, &hello\_cb, NULL, NULL, NULL, JSVM\_DEFAULT }
    };
    OH\_JSVM\_CreateEnv(vm, 1, descriptors, &env);
    JSVM\_EnvScope envScope;
    OH\_JSVM\_OpenEnvScope(env, &envScope);
    // 执行js源码src，src中可以包含任何js语法。也可以调用已注册的native方法。
    auto src = srcGlobal + "concat(hello(), ', ', 'World', ' from RunWithOption!')";
    // 其中使用新增接口，可以覆盖原有 Compile 系列接口的功能且具有拓展性
    RunScriptWithOption(env, src, dataPtr, lengthPtr);

    OH\_JSVM\_CloseEnvScope(env, envScope);
    OH\_JSVM\_DestroyEnv(env);
    OH\_JSVM\_CloseVMScope(vm, vmScope);
    OH\_JSVM\_DestroyVM(vm);

    bool result = true;
    OH\_LOG\_INFO(LOG\_APP, "RunWithOption: success: %{public}d", result);
}

void RunWithOrigin(uint8\_t \*\*dataPtr, size\_t \*lengthPtr) {
    // 创建虚拟机实例
    JSVM\_VM vm;
    JSVM\_CreateVMOptions options;
    memset(&options, 0, sizeof(options));
    options.isForSnapshotting = true;
    OH\_JSVM\_CreateVM(&options, &vm);
    JSVM\_VMScope vmScope;
    OH\_JSVM\_OpenVMScope(vm, &vmScope);

    // 从快照中创建env
    JSVM\_Env env;
    // 将native函数注册成js可调用的方法，hello\_cb中记录该native方法的指针和参数等信息
    JSVM\_PropertyDescriptor descriptors\[\] = {
        { "hello", NULL, &hello\_cb, NULL, NULL, NULL, JSVM\_DEFAULT }
    };
    OH\_JSVM\_CreateEnv(vm, 1, descriptors, &env);
    JSVM\_EnvScope envScope;
    OH\_JSVM\_OpenEnvScope(env, &envScope);
    // 执行js脚本，因为快照记录的env中定义了hello()，所以无需重新定义。dataPtr中如果保存了编译后的js脚本，就能直接执行js脚本，避免从源码重复编译。
    string src = "concat(hello(), ', ', 'World', ' from RunWithOrigin!')";
    RunScript(env, src, true, dataPtr, lengthPtr);

    OH\_JSVM\_CloseEnvScope(env, envScope);
    OH\_JSVM\_DestroyEnv(env);
    OH\_JSVM\_CloseVMScope(vm, vmScope);
    OH\_JSVM\_DestroyVM(vm);

    bool result = true;
    OH\_LOG\_INFO(LOG\_APP, "RunWithOrigin: success: %{public}d", result);
}

static JSVM\_Value RunDemo(JSVM\_Env env, JSVM\_CallbackInfo info) {
    size\_t argc = 1;
    JSVM\_Value args\[1\] = {nullptr};
    OH\_JSVM\_GetCbInfo(env, info, &argc, args, nullptr, nullptr);

    char\* str = "WithOrigin";
    size\_t len = strlen(str);
    JSVM\_Value result = nullptr;
    OH\_JSVM\_CreateStringUtf8(env, str, len, &result);

    uint8\_t\* data = nullptr;
    size\_t length = 0;
    bool equal = false;
    OH\_JSVM\_StrictEquals(env, args\[0\], result, &equal);
    const auto run = equal ? RunWithOrigin : RunWithOption;
    run(&data, &length);
    delete\[\] data;

    return nullptr;
}

// RunDemo注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = RunDemo},
};
static JSVM\_CallbackStruct \*method = param;
// RunDemo方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"RunDemo", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};

// 样例测试js
const char \*srcCallNative = R"JS(RunDemo("WithOrigin"); RunDemo("WithOption"))JS";

预期输出结果

RunWithOption: success: 1
RunWithOrigin: success: 1

OH\_JSVM\_CreateCodeCache接口用法可参考[使用code cache加速编译](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-about-code-cache)。

#### \[h2\]使用 JSVM-API WebAssembly 接口编译 wasm module

**场景介绍**

JSVM-API WebAssembly 接口提供了 WebAssembly 字节码编译、WebAssembly 函数优化、WebAssembly cache 序列化和反序列化的能力。

详见[使用 JSVM-API WebAssembly 接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-about-wasm)。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CompileWasmModule | 将 wasm 字节码同步编译为 wasm module。如果提供了 cache 参数，先尝试将 cache 反序列为 wasm module，反序列化失败时再执行编译。如果没有 JIT 权限支持，则打印一行日志提示开发者。 |
| OH\_JSVM\_CompileWasmFunction | 将 wasm module 中指定编号的函数编译为优化后的机器码，目前只使能了最高的优化等级，函数编号的合法性由接口调用者保证。如果没有 JIT 权限支持，则打印一行日志提示开发者。 |
| OH\_JSVM\_IsWasmModuleObject | 判断传入的值是否是一个 wasm module。 |
| OH\_JSVM\_CreateWasmCache | 将 wasm module 中的机器码序列化为 wasm cache，如果 wasm module 不包含机器码，则会序列化失败。如果没有 JIT 权限支持，则打印一行日志提示开发者。 |
| OH\_JSVM\_ReleaseCache | 释放由 JSVM 接口生成的 cache。传入的 cacheType 和 cacheData 必须匹配，否则会产生未定义行为。 |

**场景示例**

详见[使用 JSVM-API WebAssembly 接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-about-wasm)。

#### \[h2\]异常处理

**场景介绍**

获取、抛出、清理JS异常。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_Throw | 抛出一个JS值 |
| OH\_JSVM\_ThrowTypeError | 抛出一个JS TypeError |
| OH\_JSVM\_ThrowRangeError | 抛出一个JS RangeError |
| OH\_JSVM\_IsError | 判断JS值是否为JS异常 |
| OH\_JSVM\_CreateError | 创建一个JS异常 |
| OH\_JSVM\_CreateTypeError | 创建一个JS TypeError并返回 |
| OH\_JSVM\_CreateRangeError | 创建一个JS RangeError并返回 |
| OH\_JSVM\_ThrowError | 抛出一个JS异常 |
| OH\_JSVM\_GetAndClearLastException | 清理并返回最后一个JS异常 |
| OH\_JSVM\_IsExceptionPending | 判断当前是否有异常 |
| OH\_JSVM\_GetLastErrorInfo | 获取最后一个异常的信息 |
| OH\_JSVM\_ThrowSyntaxError | 抛出一个JS SyntaxError |
| OH\_JSVM\_CreateSyntaxError | 创建一个JS SyntaxError并返回 |

场景示例：

以TypeError为例。创建、判断，并抛出JS TypeError。

JSVM\_Value code = nullptr;
JSVM\_Value message = nullptr;
OH\_JSVM\_CreateStringUtf8(env, "500", JSVM\_AUTO\_LENGTH, &code);
OH\_JSVM\_CreateStringUtf8(env, "type error 500", JSVM\_AUTO\_LENGTH, &message);
JSVM\_Value error = nullptr;
OH\_JSVM\_CreateTypeError(env, code, message, &error);
bool isError = false;
OH\_JSVM\_IsError(env, error, &isError);
OH\_JSVM\_ThrowTypeError(env, nullptr, "type error1");

使用OH\_JSVM\_GetAndClearLastException后将异常信息以字符串形式打印

if (status != JSVM\_OK) // 当执行失败出现异常时
{
    bool isPending = false;
    if (JSVM\_OK == OH\_JSVM\_IsExceptionPending((env), &isPending) && isPending)
    {
        JSVM\_Value error;
        if (JSVM\_OK == OH\_JSVM\_GetAndClearLastException((env), &error))
        {
            // 获取异常堆栈
            JSVM\_Value stack;
            OH\_JSVM\_GetNamedProperty((env), error, "stack", &stack);

            JSVM\_Value message;
            OH\_JSVM\_GetNamedProperty((env), error, "message", &message);

            char stackstr\[256\];
            OH\_JSVM\_GetValueStringUtf8(env, stack, stackstr, 256, nullptr);
            OH\_LOG\_INFO(LOG\_APP, "JSVM error stack: %{public}s", stackstr);

            char messagestr\[256\];
            OH\_JSVM\_GetValueStringUtf8(env, message, messagestr, 256, nullptr);
            OH\_LOG\_INFO(LOG\_APP, "JSVM error message: %{public}s", messagestr);
        }
    }
}

#### \[h2\]对象生命周期管理

在调用JSVM-API接口时，底层VM堆中的对象可能会作为JSVM\_Values返回句柄。这些句柄必须在Native方法销毁或主动释放掉前，使其关联的对象处于“活动”状态，防止被引擎回收掉。

当对象句柄被返回时，它们与一个“scope”相关联。默认作用域的生命周期与Native方法调用的生命周期相关联，这些句柄及关联的对象将在Native方法的生命周期内保持活动状态。

然而，在许多情况下，句柄必须保持有效的时间范围并不与Native方法的生命周期相同。下面将介绍可用于更改句柄的生命周期的JSVM-API方法。

**对象生命周期管理接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_OpenHandleScope | 打开一个新的scope，在关闭该scope之前创建的对象在scope范围内不会被GC回收 |
| OH\_JSVM\_CloseHandleScope | 关闭一个scope，在此scope范围内创建的对象在关闭scope后可以被GC回收 |
| OH\_JSVM\_OpenEscapableHandleScope | 打开一个新的scope逃逸handle scope，在关闭该scope之前创建的对象与父作用域有相同的生命周期 |
| OH\_JSVM\_CloseEscapableHandleScope | 关闭一个scope，在此scope范围外创建的对象不受父作用域保护 |
| OH\_JSVM\_EscapeHandle | 将 JavaScript 对象的句柄提升到外部作用域，确保在外部作用域中可以持续地使用该对象 |
| OH\_JSVM\_CreateReference | 以指定的引用计数为JavaScript对象创建一个新的引用，该引用将指向传入的对象，引用允许在不同的上下文中使用和共享对象，并且可以有效地监测对象的生命周期 |
| OH\_JSVM\_DeleteReference | 释放由 OH\_JSVM\_CreateReference 创建的引用，确保对象在不再被使用时能够被正确地释放和回收，避免内存泄漏 |
| OH\_JSVM\_ReferenceRef | 增加由OH\_JSVM\_CreateReference 创建的引用的引用计数，以确保对象在有引用时不会被提前释放 |
| OH\_JSVM\_ReferenceUnref | 减少由OH\_JSVM\_CreateReference 创建的引用的引用计数，以确保没有任何引用指向该对象时能正确地释放和回收 |
| OH\_JSVM\_GetReferenceValue | 返回由 OH\_JSVM\_CreateReference 创建的引用的对象 |
| OH\_JSVM\_RetainScript | 持久化保存一个 JSVM\_Script, 使其能够跨过当前 scope 使用 |
| OH\_JSVM\_ReleaseScript | 释放持久化保存过的 JSVM\_Script，释放之后 JSVM\_Script 不再可用，应当置为空 |

场景示例：

通过handle scope保护在scope范围内创建的对象在该范围内不被回收。

JSVM\_HandleScope scope;
OH\_JSVM\_OpenHandleScope(env, &scope);
JSVM\_Value obj = nullptr;
OH\_JSVM\_CreateObject(env, &obj);
OH\_JSVM\_CloseHandleScope(env, scope);

通过escapable handle scope保护在scope范围内创建的对象在父作用域范围内不被回收

JSVM\_EscapableHandleScope scope;
JSVM\_CALL(OH\_JSVM\_OpenEscapableHandleScope(env, &scope));
JSVM\_Value output = NULL;
JSVM\_Value escapee = NULL;
JSVM\_CALL(OH\_JSVM\_CreateObject(env, &output));
JSVM\_CALL(OH\_JSVM\_EscapeHandle(env, scope, output, &escapee));
JSVM\_CALL(OH\_JSVM\_CloseEscapableHandleScope(env, scope));
return escapee;

通过CreateReference创建对象引用和释放

JSVM\_Value obj = nullptr;
OH\_JSVM\_CreateObject(env, &obj);
// 创建引用
JSVM\_Ref reference;
OH\_JSVM\_CreateReference(env, obj, 1, &reference);

// 使用引用
JSVM\_Value result;
OH\_JSVM\_GetReferenceValue(env, reference, &result);

// 释放引用
OH\_JSVM\_DeleteReference(env, reference);

通过 RetainScript 持久化保存 JSVM\_Script 并使用

JSVM\_HandleScope scope;
JSVM\_CALL(OH\_JSVM\_OpenHandleScope(env, &scope));
JSVM\_Script script;
JSVM\_Value jsSrc;
std::string src(R"JS(
let a = 37;
a = a \* 9;
)JS");
JSVM\_CALL(OH\_JSVM\_CreateStringUtf8(env, src.c\_str(), src.size(), &jsSrc));
JSVM\_CALL(OH\_JSVM\_CompileScriptWithOptions(env, jsSrc, 0, nullptr, &script));
JSVM\_CALL(OH\_JSVM\_RetainScript(env, script));
JSVM\_CALL(OH\_JSVM\_CloseHandleScope(env, scope));

// 使用JSVM\_Script
JSVM\_CALL(OH\_JSVM\_OpenHandleScope(env, &scope));
JSVM\_Value result;
JSVM\_CALL(OH\_JSVM\_RunScript(env, script, &result));

// 释放JSVM\_Script，并置空
JSVM\_CALL(OH\_JSVM\_ReleaseScript(env, script));
script = nullptr;
JSVM\_CALL(OH\_JSVM\_CloseHandleScope(env, scope));

#### \[h2\]创建JS对象类型和基本类型

**场景介绍**

创建JS对象类型和基本类型。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CreateArray | 创建一个新的 JavaScript 数组对象 |
| OH\_JSVM\_CreateArrayWithLength | 创建一个指定长度的 JavaScript 数组对象 |
| OH\_JSVM\_CreateArraybuffer | 创建一个指定大小的 ArrayBuffer 对象 |
| OH\_JSVM\_CreateDate | 创建了一个表示给定毫秒数的 Date 对象 |
| OH\_JSVM\_CreateExternal | 创建一个包装了外部指针的 JavaScript 对象 |
| OH\_JSVM\_CreateObject | 创建一个默认的JavaScript Object对象 |
| OH\_JSVM\_CreateSymbol | 根据给定的描述符创建一个 Symbol 对象 |
| OH\_JSVM\_SymbolFor | 在全局注册表中搜索具有给定描述的现有Symbol，如果该Symbol已经存在，它将被返回，否则将在注册表中创建一个新Symbol |
| OH\_JSVM\_CreateTypedarray | 在现有的 ArrayBuffer 上创建一个 JavaScript TypedArray 对象，TypedArray 对象在底层数据缓冲区上提供类似数组的视图，其中每个元素都具有相同的底层二进制标量数据类型 |
| OH\_JSVM\_CreateDataview | 在现有的 ArrayBuffer 上创建一个 JavaScript DataView 对象，DataView 对象在底层数据缓冲区上提供类似数组的视图 |
| OH\_JSVM\_CreateInt32 | 根据 Int32\_t 类型对象创建 JavaScript number 对象 |
| OH\_JSVM\_CreateUint32 | 根据 Uint32\_t 类型对象创建 JavaScript number 对象 |
| OH\_JSVM\_CreateInt64 | 根据 Int64\_t 类型对象创建 JavaScript number 对象 |
| OH\_JSVM\_CreateDouble | 根据 Double 类型对象创建 JavaScript number 对象 |
| OH\_JSVM\_CreateBigintInt64 | 根据 Int64 类型对象创建 JavaScript Bigint 对象 |
| OH\_JSVM\_CreateBigintUint64 | 根据 Uint64 类型对象创建 JavaScript Bigint 对象 |
| OH\_JSVM\_CreateBigintWords | 根据给定的 Uint64\_t 数组创建一个 JavaScript BigInt 对象 |
| OH\_JSVM\_CreateStringLatin1 | 根据 Latin-1 编码的字符串创建一个 JavaScript string 对象 |
| OH\_JSVM\_CreateStringUtf16 | 根据 Utf16 编码的字符串创建一个 JavaScript string 对象 |
| OH\_JSVM\_CreateStringUtf8 | 根据 Utf8 编码的字符串创建一个 JavaScript string 对象 |
| OH\_JSVM\_CreateMap | 创建一个新的 JavaScript Map对象 |
| OH\_JSVM\_CreateRegExp | 根据输入的字符串创建一个JavaScript 正则对象 |
| OH\_JSVM\_CreateSet | 创建一个新的 JavaScript Set对象 |

场景示例:

创建指定长度的JavaScript数组。

size\_t arrayLength = 2;
JSVM\_Value arr;

OH\_JSVM\_CreateArrayWithLength(env, arrayLength, &arr);
for (uint32\_t i = 0; i < arrayLength; i++)
{
    JSVM\_Value element;
    OH\_JSVM\_CreateUint32(env, i \* 2, &element);
    OH\_JSVM\_SetElement(env, arr, i, element);
}

创建TypedArray，以Int32Array为例：

JSVM\_Value arrayBuffer = nullptr;
void \*arrayBufferPtr = nullptr;
size\_t arrayBufferSize = 16;
size\_t typedArrayLength = 4;
OH\_JSVM\_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer);

void \*tmpArrayBufferPtr = nullptr;
size\_t arrayBufferLength = 0;
OH\_JSVM\_GetArraybufferInfo(env, arrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength);

JSVM\_Value result;
OH\_JSVM\_CreateTypedarray(env, JSVM\_TypedarrayType::JSVM\_INT32\_ARRAY, typedArrayLength, arrayBuffer, 0, &result);
return result;

创建number和string：

const char \*testStringStr = "test";
JSVM\_Value testString = nullptr;
OH\_JSVM\_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString);

JSVM\_Value testNumber1 = nullptr;
JSVM\_Value testNumber2 = nullptr;
OH\_JSVM\_CreateDouble(env, 10.1, &testNumber1);
OH\_JSVM\_CreateInt32(env, 10, &testNumber2);

创建Map：

JSVM\_Value value = nullptr;
OH\_JSVM\_CreateMap(env, &value);

创建RegExp：

JSVM\_Value value = nullptr;
const char testStr\[\] = "ab+c";
OH\_JSVM\_CreateStringUtf8(env, testStr, strlen(testStr), &value);
JSVM\_Value result = nullptr;
OH\_JSVM\_CreateRegExp(env, value, JSVM\_RegExpFlags::JSVM\_REGEXP\_GLOBAL, &result);

创建Set：

JSVM\_Value value = nullptr;
OH\_JSVM\_CreateSet(env, &value);

#### \[h2\]从JS类型获取C类型&JS类型信息

**场景介绍**

从JS类型获取C类型&JS类型信息。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_GetArrayLength | 返回 Array 对象的长度 |
| OH\_JSVM\_GetArraybufferInfo | 检索 ArrayBuffer 的底层数据缓冲区及其长度 |
| OH\_JSVM\_GetPrototype | 获取给定 JavaScript 对象的原型 |
| OH\_JSVM\_GetTypedarrayInfo | 获取 TypedArray（类型化数组）对象的信息 |
| OH\_JSVM\_GetDataviewInfo | 获取 Dataview 对象的信息 |
| OH\_JSVM\_GetDateValue | 获取给定 JavaScript Date 的时间值的 Double 基础类型值 |
| OH\_JSVM\_GetValueBool | 获取给定 JavaScript Boolean 的 C 布尔基础类型值 |
| OH\_JSVM\_GetValueDouble | 获取给定 JavaScript number 的 Double 基础类型值 |
| OH\_JSVM\_GetValueBigintInt64 | 获取给定 JavaScript BigInt 的 Int64\_t 基础类型值 |
| OH\_JSVM\_GetValueBigintUint64 | 获取给定 JavaScript BigInt 的 Uint64\_t 基础类型值 |
| OH\_JSVM\_GetValueBigintWords | 获取给定 JavaScript BigInt 对象的底层数据，即 BigInt 数据的字词表示 |
| OH\_JSVM\_GetValueExternal | 获取先前传递给 OH\_JSVM\_CreateExternal 的外部数据指针 |
| OH\_JSVM\_GetValueInt32 | 获取给定 JavaScript number 的 Int32 基础类型值 |
| OH\_JSVM\_GetValueInt64 | 获取给定 JavaScript number 的 Int64 基础类型值 |
| OH\_JSVM\_GetValueStringLatin1 | 获取给定 JavaScript string 对象的 Latin1 编码字符串 |
| OH\_JSVM\_GetValueStringUtf8 | 获取给定 JavaScript string 对象的 Utf8 编码字符串 |
| OH\_JSVM\_GetValueStringUtf16 | 获取给定 JavaScript string 对象的 Utf16 编码字符串 |
| OH\_JSVM\_GetValueUint32 | 获取给定 JavaScript number 的 Uint32 基础类型值 |
| OH\_JSVM\_GetBoolean | 返回用于表示给定布尔值的 JavaScript 单例对象 |
| OH\_JSVM\_GetGlobal | 返回当前环境中的全局 global 对象 |
| OH\_JSVM\_GetNull | 返回 JavaScript null 对象 |
| OH\_JSVM\_GetUndefined | 返回 JavaScript Undefined 对象 |

场景示例：

创建64位的 BigInt，并获取64位 Int 值。

int64\_t testValue = INT64\_MAX;
JSVM\_Value result = nullptr;
OH\_JSVM\_CreateBigintInt64(env, testValue, &result);
int64\_t resultValue = 0;
bool flag = false;
OH\_JSVM\_GetValueBigintInt64(env, result, &resultValue, &flag);

创建一个 Int32Array，并获取其长度、byteOffset 等信息。

JSVM\_Value arrayBuffer = nullptr;
void \*arrayBufferPtr = nullptr;
size\_t arrayBufferSize = 16;
size\_t typedArrayLength = 4;
OH\_JSVM\_CreateArraybuffer(env, arrayBufferSize, &arrayBufferPtr, &arrayBuffer);

bool isArrayBuffer = false;
OH\_JSVM\_IsArraybuffer(env, arrayBuffer, &isArrayBuffer);

JSVM\_Value result;
OH\_JSVM\_CreateTypedarray(env, JSVM\_TypedarrayType::JSVM\_INT32\_ARRAY, typedArrayLength, arrayBuffer, 0, &result);

bool isTypedArray = false;
OH\_JSVM\_IsTypedarray(env, result, &isTypedArray);


JSVM\_TypedarrayType type;
size\_t length = 0;
void \*data = nullptr;
JSVM\_Value retArrayBuffer;
size\_t byteOffset = -1;
OH\_JSVM\_GetTypedarrayInfo(env, result, &type, &length, &data, &retArrayBuffer, &byteOffset);


bool retIsArrayBuffer = false;
OH\_JSVM\_IsArraybuffer(env, retArrayBuffer, &retIsArrayBuffer);
void \*tmpArrayBufferPtr = nullptr;
size\_t arrayBufferLength = 0;
OH\_JSVM\_GetArraybufferInfo(env, retArrayBuffer, &tmpArrayBufferPtr, &arrayBufferLength);

根据 UTF-8 编码的 C 字符串创建一个 JavaScript 字符串，以及获取给定 JavaScript 字符串的 UTF-8 编码 C 字符串。

const char \*testStringStr = "testString";
JSVM\_Value testString = nullptr;
JSVM\_CALL(OH\_JSVM\_CreateStringUtf8(env, testStringStr, strlen(testStringStr), &testString));

char buffer\[128\];
size\_t bufferSize = 128;
size\_t copied = 0;

JSVM\_CALL(OH\_JSVM\_GetValueStringUtf8(env, testString, buffer, bufferSize, &copied));

#### \[h2\]JS值操作和抽象操作

**场景介绍**

JS值操作和抽象操作。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CoerceToBool | 将目标值转换为 Boolean 类型对象 |
| OH\_JSVM\_CoerceToNumber | 将目标值转换为 Number 类型对象 |
| OH\_JSVM\_CoerceToObject | 将目标值转换为 Object 类型对象 |
| OH\_JSVM\_CoerceToString | 将目标值转换为 String 类型对象 |
| OH\_JSVM\_CoerceToBigInt | 将目标值转换为 BigInt 类型对象 |
| OH\_JSVM\_Typeof | 返回 JavaScript 对象的类型 |
| OH\_JSVM\_Instanceof | 判断一个对象是否是某个构造函数的实例 |
| OH\_JSVM\_IsArray | 判断一个 JavaScript 对象是否为 Array 类型对象 |
| OH\_JSVM\_IsArraybuffer | 判断一个 JavaScript 对象是否为 ArrayBuffer 类型对象 |
| OH\_JSVM\_IsDate | 判断一个 JavaScript 对象是否为 Date 类型对象 |
| OH\_JSVM\_IsTypedarray | 判断一个 JavaScript 对象是否为 TypedArray 类型对象 |
| OH\_JSVM\_IsDataview | 判断一个 JavaScript 对象是否为 DataView 类型对象 |
| OH\_JSVM\_IsUndefined | 此API检查传入的值是否为Undefined。这相当于JS中的value === undefined。 |
| OH\_JSVM\_IsNull | 此API检查传入的值是否为Null对象。这相当于JS中的value === null。 |
| OH\_JSVM\_IsNullOrUndefined | 此API检查传入的值是否为Null或Undefined。这相当于JS中的value == null。 |
| OH\_JSVM\_IsBoolean | 此API检查传入的值是否为Boolean。这相当于JS中的typeof value === 'boolean'。 |
| OH\_JSVM\_IsNumber | 此API检查传入的值是否为Number。这相当于JS中的typeof value === 'number'。 |
| OH\_JSVM\_IsString | 此API检查传入的值是否为String。这相当于JS中的typeof value === 'string'。 |
| OH\_JSVM\_IsSymbol | 此API检查传入的值是否为Symbol。这相当于JS中的typeof value === 'symbol'。 |
| OH\_JSVM\_IsFunction | 此API检查传入的值是否为Function。这相当于JS中的typeof value === 'function'。 |
| OH\_JSVM\_IsObject | 此API检查传入的值是否为Object。 |
| OH\_JSVM\_IsBigInt | 此API检查传入的值是否为BigInt。这相当于JS中的typeof value === 'bigint'。 |
| OH\_JSVM\_IsConstructor | 此API检查传入的值是否为构造函数。 |
| OH\_JSVM\_IsMap | 此API检查传入的值是否为Map。 |
| OH\_JSVM\_IsSet | 此API检查传入的值是否为Set。 |
| OH\_JSVM\_IsRegExp | 此API检查传入的值是否为RegExp。 |
| OH\_JSVM\_StrictEquals | 判断两个 JSVM\_Value 对象是否严格相等 |
| OH\_JSVM\_Equals | 判断两个 JSVM\_Value 对象是否宽松相等 |
| OH\_JSVM\_DetachArraybuffer | 调用 ArrayBuffer 对象的Detach操作 |
| OH\_JSVM\_IsDetachedArraybuffer | 检查给定的 ArrayBuffer 是否已被分离(detached) |

场景示例:

判断JS值是否为Array类型

JSVM\_Value array = nullptr;
OH\_JSVM\_CreateArray(env, &array);
bool isArray = false;
OH\_JSVM\_IsArray(env, array, &isArray);

将int32类型的目标值转换为string类型

int32\_t num = 123;
JSVM\_Value intValue;
OH\_JSVM\_CreateInt32(env, num, &intValue);
JSVM\_Value stringValue;
OH\_JSVM\_CoerceToString(env, intValue, &stringValue);

char buffer\[128\];
size\_t bufferSize = 128;
size\_t copied = 0;

OH\_JSVM\_GetValueStringUtf8(env, stringValue, buffer, bufferSize, &copied);
// buffer:"123";

将boolean类型的目标值转换为bigint类型

JSVM\_Value boolValue;
OH\_JSVM\_GetBoolean(env, false, &boolValue);
JSVM\_Value bigIntValue;
OH\_JSVM\_CoerceToBigInt(env, boolValue, &bigIntValue);

判断两个JSVM\_Value对象类型是否严格相同：先比较操作数类型，操作数类型不同就是不相等，操作数类型相同时，比较值是否相等，相等才返回true。

JSVM\_Value value = nullptr;
JSVM\_Value value1 = nullptr;
OH\_JSVM\_CreateArray(env, &value);

OH\_JSVM\_CreateInt32(env, 10, &value1);
bool isArray = true;
OH\_JSVM\_StrictEquals(env, value, value, &isArray);

判断两个JSVM\_Value对象类型是否宽松相同：判断两个操作数的类型是否相同，若不相同，且可以转换为相同的数据类型，转换为相同的数据类型后，值做严格相等比较，其他的都返回false。

JSVM\_HandleScope handleScope;
OH\_JSVM\_OpenHandleScope(env, &handleScope);
const char testStr\[\] = "1";
JSVM\_Value lhs = nullptr;
OH\_JSVM\_CreateStringUtf8(env, testStr, strlen(testStr), &lhs);
JSVM\_Value rhs;
OH\_JSVM\_CreateInt32(env, 1, &rhs);
bool isEquals = false;
OH\_JSVM\_Equals(env, lhs, rhs, &isEquals); // 这里isEquals的值是true
OH\_JSVM\_CloseHandleScope(env, handleScope);

判断传入的JS值是否为构造函数

JSVM\_Value SayHello(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    return nullptr;
}
JSVM\_Value value = nullptr;
JSVM\_CallbackStruct param;
param.data = nullptr;
param.callback = SayHello;
OH\_JSVM\_CreateFunction(env, "func", JSVM\_AUTO\_LENGTH, &param, &value);
bool isConstructor = false;
OH\_JSVM\_IsConstructor(env, value, &isConstructor); // 这里isConstructor的值是true

判断传入的JS值是否为Map类型

JSVM\_Value value = nullptr;
OH\_JSVM\_CreateMap(env, &value);
bool isMap = false;
OH\_JSVM\_IsMap(env, value, &isMap); // 这里isMap的值是true

判断传入的JS值是否为Set类型

JSVM\_Value value;
OH\_JSVM\_CreateSet(env, &value);
bool isSet = false;
OH\_JSVM\_IsSet(env, value, &isSet); // 这里isSet的值是true

判断JS值是否为RegExp类型

JSVM\_Value value = nullptr;
const char testStr\[\] = "ab+c";
OH\_JSVM\_CreateStringUtf8(env, testStr, strlen(testStr), &value);
JSVM\_Value result = nullptr;
OH\_JSVM\_CreateRegExp(env, value, JSVM\_RegExpFlags::JSVM\_REGEXP\_GLOBAL, &result);
bool isRegExp = false;
OH\_JSVM\_IsRegExp(env, result, &isRegExp);

#### \[h2\]JS属性操作

**场景介绍**

JS对象属性的增加、删除、获取和判断。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_GetPropertyNames | 获取给定对象的所有可枚举属性名称, 结果变量将存储一个包含所有可枚举属性名称的JavaScript数组。 |
| OH\_JSVM\_GetAllPropertyNames | 获取给定对象的所有可用属性名称, 结果变量将存储一个包含所有可枚举属性名称的JavaScript数组。 |
| OH\_JSVM\_SetProperty | 为给定对象设置一个属性。 |
| OH\_JSVM\_GetProperty | 用给定的属性的名称，检索目标对象的属性。 |
| OH\_JSVM\_HasProperty | 用给定的属性的名称，查询目标对象是否有此属性。 |
| OH\_JSVM\_DeleteProperty | 用给定的属性的名称，删除目标对象属性。 |
| OH\_JSVM\_HasOwnProperty | 检查目标对象是否具有指定的自有属性。 |
| OH\_JSVM\_SetNamedProperty | 用给定的属性的名称为目标对象设置属性，此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM\_Value 调用 OH\_JSVM\_SetProperty。 |
| OH\_JSVM\_GetNamedProperty | 用给定的属性的名称，检索目标对象的属性，此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM\_Value 调用 OH\_JSVM\_GetProperty。 |
| OH\_JSVM\_HasNamedProperty | 用给定的属性的名称，查询目标对象是否有此属性，此方法等效于使用从作为 utf8Name 传入的字符串创建的 JSVM\_Value 调用 OH\_JSVM\_HasProperty。 |
| OH\_JSVM\_SetElement | 在给定对象的指定索引处设置元素。 |
| OH\_JSVM\_GetElement | 获取给定对象指定索引处的元素。 |
| OH\_JSVM\_HasElement | 若给定对象的指定索引处拥有属性，获取该元素。 |
| OH\_JSVM\_DeleteElement | 尝试删除给定对象的指定索引处的元素。 |
| OH\_JSVM\_DefineProperties | 批量的向给定对象中定义属性。 |
| OH\_JSVM\_ObjectFreeze | 冻结给定的对象,防止向其添加新属性，删除现有属性，防止更改现有属性的可枚举性、可配置性或可写性，并防止更改现有属性的值。 |
| OH\_JSVM\_ObjectSeal | 密封给定的对象。这可以防止向其添加新属性，以及将所有现有属性标记为不可配置。 |
| OH\_JSVM\_ObjectSetPrototypeOf | 为给定对象设置一个原型。 |
| OH\_JSVM\_ObjectGetPrototypeOf | 获取给定JavaScript对象的原型。 |

场景示例:

JS对象属性的增加、删除、获取和判断。

// 创建一个空对象
JSVM\_Value myObject = nullptr;
OH\_JSVM\_CreateObject(env, &myObject);

// 设置属性
const char \*testNameStr = "John Doe";
JSVM\_Value propValue = nullptr;
JSVM\_Value key = nullptr;
OH\_JSVM\_CreateStringUtf8(env, "name", JSVM\_AUTO\_LENGTH, &key);
OH\_JSVM\_CreateStringUtf8(env, testNameStr, strlen(testNameStr), &propValue);
OH\_JSVM\_SetProperty(env, myObject, key, propValue);

// 获取属性
JSVM\_Value propResult = nullptr;
OH\_JSVM\_GetProperty(env, myObject, key, &propResult);

// 检查属性是否存在
bool hasProperty = false;
OH\_JSVM\_HasNamedProperty(env, myObject, "name", &hasProperty);
    // 属性存在，做相应处理...
    if (hasProperty)
    {
        // 获取对象的所有属性名
        JSVM\_Value propNames = nullptr;
        OH\_JSVM\_GetPropertyNames(env, myObject, &propNames);

        bool isArray = false;
        OH\_JSVM\_IsArray(env, propNames, &isArray);

        uint32\_t arrayLength = 0;
        OH\_JSVM\_GetArrayLength(env, propNames, &arrayLength);
        // 遍历属性元素
        for (uint32\_t i = 0; i < arrayLength; i++)
        {
            bool hasElement = false;
            OH\_JSVM\_HasElement(env, propNames, i, &hasElement);

            JSVM\_Value propName = nullptr;
            OH\_JSVM\_GetElement(env, propNames, i, &propName);

            bool hasProp = false;
            OH\_JSVM\_HasProperty(env, myObject, propName, &hasProp);

            JSVM\_Value propValue = nullptr;
            OH\_JSVM\_GetProperty(env, myObject, propName, &propValue);
        }
    }

// 删除属性
OH\_JSVM\_DeleteProperty(env, myObject, key, &hasProperty);

// 设置对象原型
JSVM\_Value value;
OH\_JSVM\_CreateSet(env, &value);
OH\_JSVM\_ObjectSetPrototypeOf(env, myObject, value);

// 获取对象原型
JSVM\_Value proto;
OH\_JSVM\_ObjectGetPrototypeOf(env, myObject, &proto);

#### \[h2\]JS函数操作

**场景介绍**

JS函数操作。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CallFunction | 在C/C++侧调用JS方法 |
| OH\_JSVM\_CreateFunction | 用于创建JavaScript函数,用于从JavaScript环境中调用C/C++代码中的函数 |
| OH\_JSVM\_GetCbInfo | 从给定的callback info中获取有关调用的详细信息，如参数和this指针 |
| OH\_JSVM\_GetNewTarget | 获取构造函数调用的new.target |
| OH\_JSVM\_NewInstance | 通过给定的构造函数，构建一个实例 |
| OH\_JSVM\_CreateFunctionWithScript | 根据传入的函数体和函数参数列表，创建一个新的 JavaScript Function对象 |

场景示例:

创建JavaScript函数操作。

JSVM\_Value SayHello(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    printf("Hello\\n");
    JSVM\_Value ret;
    OH\_JSVM\_CreateInt32(env, 2, &ret);
    return ret;
}

static JSVM\_Value JsvmCreateFunction(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    JSVM\_CallbackStruct param;
    param.data = nullptr;
    param.callback = SayHello;

    JSVM\_Value funcValue = nullptr;
    JSVM\_Status status = OH\_JSVM\_CreateFunction(env, "func", JSVM\_AUTO\_LENGTH, &param, &funcValue);
    return funcValue;
}

在C/C++侧调用JS方法。

static JSVM\_Value CallFunction(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    size\_t argc = 1;
    JSVM\_Value args\[1\];
    JSVM\_CALL(OH\_JSVM\_GetCbInfo(env, info, &argc, args, NULL, NULL));
    if (argc < 1) {
        OH\_LOG\_ERROR(LOG\_APP, "Wrong number of arguments");
        return nullptr;
    }

    JSVM\_ValueType valuetype;
    JSVM\_CALL(OH\_JSVM\_Typeof(env, args\[0\], &valuetype));
    if (valuetype != JSVM\_ValueType::JSVM\_FUNCTION) {
        OH\_LOG\_ERROR(LOG\_APP, "Wrong type of argument. Expects a function.");
        return nullptr;
    }

    JSVM\_Value global;
    JSVM\_CALL(OH\_JSVM\_GetGlobal(env, &global));

    JSVM\_Value ret;
    JSVM\_CALL(OH\_JSVM\_CallFunction(env, global, args\[0\], 0, nullptr, &ret));
    return ret;
}

创建JavaScript函数:

JSVM\_Value script;
OH\_JSVM\_CreateStringUtf8(env, "return a + b;", JSVM\_AUTO\_LENGTH, &script);
JSVM\_Value param1;
JSVM\_Value param2;
OH\_JSVM\_CreateStringUtf8(env, "a", JSVM\_AUTO\_LENGTH, &param1);
OH\_JSVM\_CreateStringUtf8(env, "b", JSVM\_AUTO\_LENGTH, &param2);
JSVM\_Value argus\[\] = {param1, param2};
JSVM\_Value func;
OH\_JSVM\_CreateFunctionWithScript(env, "add", JSVM\_AUTO\_LENGTH, 2, argus, script, &func);

#### \[h2\]对象绑定操作

**场景介绍**

对象绑定操作。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_DefineClass | 用于在JavaScript中定义一个类，并与对应的C类进行封装和交互。它提供了创建类的构造函数、定义属性和方法的能力，以及在C和JavaScript之间进行数据交互的支持。 |
| OH\_JSVM\_Wrap | 在 JavaScript 对象中封装原生实例。稍后可以使用 OH\_JSVM\_Unwrap() 检索原生实例。 |
| OH\_JSVM\_Unwrap | 使用 OH\_JSVM\_Wrap() 检索先前封装在 JavaScript 对象中的原生实例。 |
| OH\_JSVM\_RemoveWrap | 检索先前封装在 JavaScript 对象中的原生实例并移除封装。 |
| OH\_JSVM\_TypeTagObject | 将 type\_tag 指针的值与 JavaScript 对象或外部对象相关联。 |
| OH\_JSVM\_CheckObjectTypeTag | 检查给定的类型标签是否与对象上的类型标签匹配。 |
| OH\_JSVM\_AddFinalizer | 为对象添加 JSVM\_Finalize 回调，以便在 JavaScript 对象被垃圾回收时调用来释放原生对象。 |
| OH\_JSVM\_DefineClassWithPropertyHandler | 定义一个具有给定类名、构造函数、属性和回调处理程序的JavaScript类，并作为函数回调进行调用。属性操作包括getter、setter、deleter、enumerator等。 |
| OH\_JSVM\_DefineClassWithOptions | 定义一个具有给定类名、构造函数、属性和回调处理程序、父类的JavaScript类，并根据传入了DefineClassOptions来决定是否需要为所定义的Class设置属性代理、预留internal-field槽位、为class作为函数进行调用时设置函数回调。 |

场景示例：

对象绑定操作。

static int aa = 0;

static JSVM\_Value AssertEqual(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    size\_t argc = 2;
    JSVM\_Value args\[2\];
    JSVM\_CALL(OH\_JSVM\_GetCbInfo(env, info, &argc, args, NULL, NULL));

    bool isStrictEquals = false;
    OH\_JSVM\_StrictEquals(env, args\[0\], args\[1\], &isStrictEquals);
    return nullptr;
}

static napi\_value TestWrap(napi\_env env1, napi\_callback\_info info)
{
    OH\_LOG\_ERROR(LOG\_APP, "testWrap start");
    JSVM\_InitOptions init\_options;
    memset(&init\_options, 0, sizeof(init\_options));
    if (aa == 0) {
        OH\_JSVM\_Init(&init\_options);
        aa++;
    }
    JSVM\_VM vm;
    JSVM\_CreateVMOptions options;
    memset(&options, 0, sizeof(options));
    OH\_JSVM\_CreateVM(&options, &vm);
    JSVM\_VMScope vm\_scope;
    OH\_JSVM\_OpenVMScope(vm, &vm\_scope);
    JSVM\_Env env;
    JSVM\_CallbackStruct param\[1\];
    param\[0\].data = nullptr;
    param\[0\].callback = AssertEqual;
    JSVM\_PropertyDescriptor descriptor\[\] = {
        {"assertEqual", NULL, &param\[0\], NULL, NULL, NULL, JSVM\_DEFAULT},
    };
    OH\_JSVM\_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor\[0\]), descriptor, &env);
    JSVM\_EnvScope envScope;
    OH\_JSVM\_OpenEnvScope(env, &envScope);
    JSVM\_HandleScope handlescope;
    OH\_JSVM\_OpenHandleScope(env, &handlescope);
    JSVM\_Value testClass = nullptr;
    JSVM\_CallbackStruct param1;
    param1.data = nullptr;
    param1.callback = \[\](JSVM\_Env env, JSVM\_CallbackInfo info) -> JSVM\_Value {
        JSVM\_Value thisVar = nullptr;
        OH\_JSVM\_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr);

        return thisVar;
    };
    OH\_JSVM\_DefineClass(env, "TestClass", JSVM\_AUTO\_LENGTH, &param1, 0, nullptr, &testClass);

    JSVM\_Value instanceValue = nullptr;
    OH\_JSVM\_NewInstance(env, testClass, 0, nullptr, &instanceValue);

    const char \*testStr = "test";
    OH\_JSVM\_Wrap(
        env, instanceValue, (void \*)testStr, \[\](JSVM\_Env env, void \*data, void \*hint) {}, nullptr, nullptr);
    const char \*tmpTestStr = nullptr;
    OH\_JSVM\_Unwrap(env, instanceValue, (void \*\*)&tmpTestStr);
    const char \*tmpTestStr1 = nullptr;
    OH\_JSVM\_RemoveWrap(env, instanceValue, (void \*\*)&tmpTestStr1);
    OH\_JSVM\_Unwrap(env, instanceValue, (void \*\*)&tmpTestStr1);
    OH\_JSVM\_CloseHandleScope(env, handlescope);
    OH\_JSVM\_CloseEnvScope(env, envScope);
    OH\_JSVM\_DestroyEnv(env);
    OH\_JSVM\_CloseVMScope(vm, vm\_scope);
    OH\_JSVM\_DestroyVM(vm);
    OH\_LOG\_ERROR(LOG\_APP, "testWrap pass");
    return nullptr;
}

场景示例：

对象绑定及监听拦截属性操作。

static int aa = 0;
static JSVM\_Value hello(JSVM\_Env env, JSVM\_CallbackInfo info) {
    JSVM\_Value output;
    void \*data = nullptr;
    OH\_JSVM\_GetCbInfo(env, info, nullptr, nullptr, nullptr, &data);
    OH\_JSVM\_CreateStringUtf8(env, (char \*)data, strlen((char \*)data), &output);
    return output;
}

static JSVM\_CallbackStruct hello\_cb = {hello, (void \*)"Hello"};
static intptr\_t externals\[\] = {
    (intptr\_t)&hello\_cb,
    0,
};

static void test1() { OH\_LOG\_INFO(LOG\_APP, "test1 called"); }

struct Test {
    void \*ptr1;
    void \*ptr2;
};

static JSVM\_Value assertEqual(JSVM\_Env env, JSVM\_CallbackInfo info) {
    size\_t argc = 2;
    JSVM\_Value args\[2\];
    JSVM\_CALL(OH\_JSVM\_GetCbInfo(env, info, &argc, args, NULL, NULL));

    bool isStrictEquals = false;
    OH\_JSVM\_StrictEquals(env, args\[0\], args\[1\], &isStrictEquals);
    return nullptr;
}

static JSVM\_Value GetPropertyCbInfo(JSVM\_Env env, JSVM\_Value name, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由对象上的获取请求触发的
    char strValue\[100\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, name, strValue, 300, &size);
    JSVM\_Value newResult = nullptr;
    char newStr\[\] = "new return value hahaha from name listening";
    OH\_JSVM\_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "GetPropertyCbInfo wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value SetPropertyCbInfo(JSVM\_Env env, JSVM\_Value name, JSVM\_Value property, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由对象上的设置请求触发的
    char strValue\[100\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, name, strValue, 300, &size);
    JSVM\_Value newResult = nullptr;
    char newStr\[\] = "new return value hahaha from name listening";
    OH\_JSVM\_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "SetPropertyCbInfo wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value DeleterPropertyCbInfo(JSVM\_Env env, JSVM\_Value name, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由对象上的删除请求触发的
    char strValue\[100\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, name, strValue, 300, &size);
    JSVM\_Value newResult = nullptr;
    bool returnValue = false;
    OH\_JSVM\_GetBoolean(env, returnValue, &newResult);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "DeleterPropertyCbInfo wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value EnumeratorPropertyCbInfo(JSVM\_Env env, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由获取对象上的所有属性请求触发的
    JSVM\_Value testArray = nullptr;
    OH\_JSVM\_CreateArrayWithLength(env, 2, &testArray);
    JSVM\_Value name1 = nullptr;
    char newStr1\[\] = "hahaha";
    OH\_JSVM\_CreateStringUtf8(env, newStr1, strlen(newStr1), &name1);
    JSVM\_Value name2 = nullptr;
    char newStr2\[\] = "heheheh";
    OH\_JSVM\_CreateStringUtf8(env, newStr2, strlen(newStr2), &name2);

    OH\_JSVM\_SetElement(env, testArray, 0, name1);
    OH\_JSVM\_SetElement(env, testArray, 1, name2);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "EnumeratorPropertyCbInfo wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value IndexedPropertyGet(JSVM\_Env env, JSVM\_Value index, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由获取实例对象的索引属性触发的
    uint32\_t value = 0;
    OH\_JSVM\_GetValueUint32(env, index, &value);

    JSVM\_Value newResult = nullptr;
    char newStr\[\] = "new return value hahaha from index listening";
    OH\_JSVM\_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "IndexedPropertyGet wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value IndexedPropertySet(JSVM\_Env env, JSVM\_Value index, JSVM\_Value property, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由设置实例对象的索引属性触发的
    uint32\_t value = 0;
    OH\_JSVM\_GetValueUint32(env, index, &value);
    char str\[100\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, property, str, 100, &size);
    JSVM\_Value newResult = nullptr;
    char newStr\[\] = "new return value hahaha from name listening";
    OH\_JSVM\_CreateStringUtf8(env, newStr, strlen(newStr), &newResult);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "IndexedPropertySet wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value IndexedPropertyDeleter(JSVM\_Env env, JSVM\_Value index, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由删除实例对象的索引属性触发的
    uint32\_t value = 0;
    OH\_JSVM\_GetValueUint32(env, index, &value);
    JSVM\_Value newResult = nullptr;
    bool returnValue = false;
    OH\_JSVM\_GetBoolean(env, returnValue, &newResult);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static JSVM\_Value IndexedPropertyEnumerator(JSVM\_Env env, JSVM\_Value thisArg, JSVM\_Value data) {
    // 该回调是由获取对象上的所有索引属性请求触发的
    JSVM\_Value testArray = nullptr;
    OH\_JSVM\_CreateArrayWithLength(env, 2, &testArray);
    JSVM\_Value index1 = nullptr;
    OH\_JSVM\_CreateUint32(env, 1, &index1);
    JSVM\_Value index2 = nullptr;
    OH\_JSVM\_CreateUint32(env, 2, &index2);
    OH\_JSVM\_SetElement(env, testArray, 0, index1);
    OH\_JSVM\_SetElement(env, testArray, 1, index2);
    int signBit = 0;
    size\_t wordCount = 2;
    uint64\_t wordsOut\[2\] = {0ULL, 0ULL};
    JSVM\_Status status = OH\_JSVM\_GetValueBigintWords(env, data, &signBit, &wordCount, wordsOut);
    if (status == JSVM\_OK) {
        OH\_LOG\_INFO(LOG\_APP, "IndexedPropertyDeleter wordCount is %{public}zu", wordCount);
        auto test = reinterpret\_cast<Test \*>(wordsOut);
        typedef void (\*callTest1)();
        callTest1 callTe = reinterpret\_cast<callTest1>(test->ptr1);
        callTe();
    }
    return nullptr;
}

static napi\_value TestDefineClassWithProperty(napi\_env env1, napi\_callback\_info info) {
    OH\_LOG\_ERROR(LOG\_APP, "TestDefineClassWithProperty start");
    JSVM\_InitOptions init\_options;
    memset(&init\_options, 0, sizeof(init\_options));
    init\_options.externalReferences = externals;
    if (aa == 0) {
        OH\_JSVM\_Init(&init\_options);
        aa++;
    }
    JSVM\_VM vm;
    JSVM\_CreateVMOptions options;
    memset(&options, 0, sizeof(options));
    OH\_JSVM\_CreateVM(&options, &vm);
    JSVM\_VMScope vm\_scope;
    OH\_JSVM\_OpenVMScope(vm, &vm\_scope);
    JSVM\_Env env;
    JSVM\_CallbackStruct param\[1\];
    param\[0\].data = nullptr;
    param\[0\].callback = assertEqual;
    JSVM\_PropertyDescriptor descriptor\[\] = {
        {"assertEqual", NULL, &param\[0\], NULL, NULL, NULL, JSVM\_DEFAULT},
    };
    OH\_JSVM\_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor\[0\]), descriptor, &env);
    JSVM\_EnvScope envScope;
    OH\_JSVM\_OpenEnvScope(env, &envScope);
    JSVM\_HandleScope handlescope;
    OH\_JSVM\_OpenHandleScope(env, &handlescope);


    JSVM\_CallbackStruct param1;
    param1.callback = \[\](JSVM\_Env env, JSVM\_CallbackInfo info) -> JSVM\_Value {
        JSVM\_Value thisVar = nullptr;
        OH\_JSVM\_GetCbInfo(env, info, nullptr, nullptr, &thisVar, nullptr);
        return thisVar;
    };
    param1.data = nullptr;

    JSVM\_Value res = nullptr;
    Test \*test = new Test();
    test->ptr1 = (void \*)test1;
    test->ptr2 = (void \*)test1;
    OH\_LOG\_INFO(LOG\_APP, "OH\_JSVM\_CreateBigintWords 111 word count %{public}d",
                sizeof(\*test) / sizeof(uint64\_t));
    JSVM\_Status status = OH\_JSVM\_CreateBigintWords(env, 1, 2, reinterpret\_cast<const uint64\_t \*>(test), &res);

    // 初始化propertyCfg
    JSVM\_PropertyHandlerConfigurationStruct propertyCfg;
    propertyCfg.genericNamedPropertyGetterCallback = GetPropertyCbInfo;
    propertyCfg.genericNamedPropertySetterCallback = SetPropertyCbInfo;
    propertyCfg.genericNamedPropertyDeleterCallback = DeleterPropertyCbInfo;
    propertyCfg.genericNamedPropertyEnumeratorCallback = EnumeratorPropertyCbInfo;
    propertyCfg.genericIndexedPropertyGetterCallback = IndexedPropertyGet;
    propertyCfg.genericIndexedPropertySetterCallback = IndexedPropertySet;
    propertyCfg.genericIndexedPropertyDeleterCallback = IndexedPropertyDeleter;
    propertyCfg.genericIndexedPropertyEnumeratorCallback = IndexedPropertyEnumerator;
    propertyCfg.namedPropertyData = res;
    propertyCfg.indexedPropertyData = res;

    JSVM\_CallbackStruct callbackStruct;
    callbackStruct.callback = \[\](JSVM\_Env env, JSVM\_CallbackInfo info) -> JSVM\_Value {
        OH\_LOG\_INFO(LOG\_APP, "call as a function called");
        JSVM\_Value thisVar = nullptr;
        void \*innerData;
        size\_t argc = 1;
        JSVM\_Value args\[1\];
        OH\_JSVM\_GetCbInfo(env, info, &argc, args, &thisVar, &innerData);
        OH\_LOG\_INFO(LOG\_APP, "function call as function result is %{public}s", reinterpret\_cast<char \*>(innerData));
        uint32\_t ret = 0;
        OH\_JSVM\_GetValueUint32(env, args\[0\], &ret);
        const char testStr\[\] = "hello world 111111";
        JSVM\_Value setvalueName = nullptr;
        JSVM\_CALL(OH\_JSVM\_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName));
        return setvalueName;
    };
    char data\[100\] = "1111 hello world";
    callbackStruct.data = data;
    JSVM\_Value testWrapClass = nullptr;

    // 将属性的访问监听注册在propertyCfg中
    OH\_JSVM\_DefineClassWithPropertyHandler(env, "TestWrapClass", NAPI\_AUTO\_LENGTH, &param1, 0, nullptr, &propertyCfg,
                                           &callbackStruct, &testWrapClass);
    JSVM\_Value instanceValue = nullptr;
    OH\_JSVM\_NewInstance(env, testWrapClass, 0, nullptr, &instanceValue);
    const char testStr\[\] = "hello world";
    JSVM\_Value setvalueName = nullptr;
    OH\_JSVM\_CreateStringUtf8(env, testStr, strlen(testStr), &setvalueName);

    // 1. 名称属性回调
    // 设置属性
    OH\_JSVM\_SetNamedProperty(env, instanceValue, "str11", setvalueName);
    OH\_JSVM\_SetNamedProperty(env, instanceValue, "str123", setvalueName);

    // 获取属性
    JSVM\_Value valueName = nullptr;
    OH\_JSVM\_GetNamedProperty(env, instanceValue, "str11", &valueName);
    char str\[100\];
    size\_t size = 0;
    OH\_JSVM\_GetValueStringUtf8(env, valueName, str, 100, &size);

    // 获取所有属性的名称
    JSVM\_Value allPropertyNames = nullptr;
    OH\_JSVM\_GetAllPropertyNames(env, instanceValue, JSVM\_KEY\_OWN\_ONLY,
                                static\_cast<JSVM\_KeyFilter>(JSVM\_KEY\_ENUMERABLE | JSVM\_KEY\_SKIP\_SYMBOLS),
                                JSVM\_KEY\_NUMBERS\_TO\_STRINGS, &allPropertyNames);
    uint32\_t nameSize = 0;
    OH\_JSVM\_GetArrayLength(env, allPropertyNames, &nameSize);
    JSVM\_Value propertyName = nullptr;
    for (uint32\_t i = 0; i < nameSize; ++i) {
        OH\_JSVM\_GetElement(env, allPropertyNames, i, &propertyName);
        char str\[100\];
        size\_t size = 0;
        OH\_JSVM\_GetValueStringUtf8(env, propertyName, str, 100, &size);
    }

    // 删除属性
    bool result = false;
    propertyName = nullptr;
    char propertyChar\[\] = "str11";
    OH\_JSVM\_CreateStringUtf8(env, propertyChar, strlen(propertyChar), &propertyName);
    OH\_JSVM\_DeleteProperty(env, instanceValue, propertyName, &result);

    // 2. 索引属性回调
    // 设置属性
    JSVM\_Value jsIndex = nullptr;
    uint32\_t index = 0;
    OH\_JSVM\_CreateUint32(env, index, &jsIndex);
    OH\_JSVM\_SetProperty(env, instanceValue, jsIndex, setvalueName);
    JSVM\_Value jsIndex1 = nullptr;
    index = 1;
    OH\_JSVM\_CreateUint32(env, index, &jsIndex1);
    OH\_JSVM\_SetProperty(env, instanceValue, jsIndex1, setvalueName);

    // 获取属性
    JSVM\_Value valueName1 = nullptr;
    OH\_JSVM\_GetProperty(env, instanceValue, jsIndex, &valueName1);
    char str1\[100\];
    size\_t size1 = 0;
    OH\_JSVM\_GetValueStringUtf8(env, valueName1, str1, 100, &size1);

    // 获取所有属性的名称
    JSVM\_Value allPropertyNames1 = nullptr;
    OH\_JSVM\_GetAllPropertyNames(env, instanceValue, JSVM\_KEY\_OWN\_ONLY,
                                static\_cast<JSVM\_KeyFilter>(JSVM\_KEY\_ENUMERABLE | JSVM\_KEY\_SKIP\_SYMBOLS),
                                JSVM\_KEY\_NUMBERS\_TO\_STRINGS, &allPropertyNames1);
    uint32\_t nameSize1 = 0;
    OH\_JSVM\_GetArrayLength(env, allPropertyNames1, &nameSize1);
    JSVM\_Value propertyName1 = nullptr;
    for (uint32\_t i = 0; i < nameSize1; ++i) {
        OH\_JSVM\_GetElement(env, allPropertyNames1, i, &propertyName1);
        char str\[100\];
        size\_t size = 0;
        OH\_JSVM\_GetValueStringUtf8(env, propertyName1, str, 100, &size);
    }

    // 删除属性
    bool result1 = false;
    OH\_JSVM\_DeleteProperty(env, instanceValue, jsIndex, &result1);

    // 3. 作为函数的回调
    JSVM\_Value globalObj = nullptr;
    OH\_JSVM\_GetGlobal(env, &globalObj);
    OH\_JSVM\_SetNamedProperty(env, globalObj, "myTestInstance", instanceValue);
    OH\_LOG\_INFO(LOG\_APP, "set property on global object");
    std::string innerSourcecodestr = R"(
    {
        let res = myTestInstance(12);
    })";
    JSVM\_Value innerSourcecodevalue;
    OH\_JSVM\_CreateStringUtf8(env, innerSourcecodestr.c\_str(), innerSourcecodestr.size(), &innerSourcecodevalue);
    JSVM\_Script innerscript;
    OH\_JSVM\_CompileScript(env, innerSourcecodevalue, nullptr, 0, true, nullptr, &innerscript);
    JSVM\_Value innerResult;
    OH\_JSVM\_RunScript(env, innerscript, &innerResult);

    OH\_JSVM\_CloseHandleScope(env, handlescope);
    OH\_JSVM\_CloseEnvScope(env, envScope);
    OH\_JSVM\_DestroyEnv(env);
    OH\_JSVM\_CloseVMScope(vm, vm\_scope);
    OH\_JSVM\_DestroyVM(vm);
    OH\_LOG\_ERROR(LOG\_APP, "TestDefineClassWithProperty pass");
    return nullptr;
}

场景示例：设置父类并通过DefineClassOptions设置监听拦截属性操作

具体示例参考[使用JSVM-API接口进行class相关开发](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-about-class)。

#### \[h2\]版本管理

**场景介绍**

获取当前版本信息。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_GetVersion | 返回JSVM运行时支持的最高JSVM API版本 |
| OH\_JSVM\_GetVMInfo | 返回虚拟机的信息 |

场景示例：

获取当前版本信息。

JSVM\_VMInfo result;
OH\_JSVM\_GetVMInfo(&result);
uint32\_t versionId = 0;
OH\_JSVM\_GetVersion(env, &versionId);

#### \[h2\]内存管理

**场景介绍**

内存管理。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_AdjustExternalMemory | 将因JavaScript对象而保持活跃的外部分配的内存大小及时通知给底层虚拟机，虚拟机后续触发GC时，就会综合内外内存状态来判断是否进行全局GC。即增大外部内存分配，则会增大触发全局GC的概率；反之减少。 |
| OH\_JSVM\_MemoryPressureNotification | 通知虚拟机系统内存压力层级，并有选择地触发垃圾回收。 |
| OH\_JSVM\_AllocateArrayBufferBackingStoreData | 申请一块 BackingStore 内存。 |
| OH\_JSVM\_FreeArrayBufferBackingStoreData | 释放 BackingStore 内存。 |
| OH\_JSVM\_CreateArrayBufferFromBackingStoreData | 基于申请的 BackingStore 内存创建 array buffer。 |

使用 BackingStore 属于高危操作，使用者需确保内存使用正确。请参考下方正确示例，谨慎操作。

场景示例：

内存管理。

// 分别在调用OH\_JSVM\_AdjustExternalMemory前后来查看底层虚拟机视角下外部分配的内存大小
int64\_t result = 0;
OH\_JSVM\_AdjustExternalMemory(env, 0, &result); // 假设外部分配内存的变化不变
OH\_LOG\_INFO(LOG\_APP, "Before AdjustExternalMemory: %{public}lld\\n", result); // 得到调整前的数值
// 调整外部分配的内存大小通知给底层虚拟机（此示例假设内存使用量增加）
int64\_t memoryIncrease = 1024 \* 1024; // 增加 1 MB
OH\_JSVM\_AdjustExternalMemory(env, memoryIncrease, &result);
OH\_LOG\_INFO(LOG\_APP, "After AdjustExternalMemory: %{public}lld\\n", result); // 得到调整后的数值

// 打开一个Handle scope，在scope范围内申请大量内存来测试函数功能；
// 分别在“完成申请后”、“关闭scope后”和“调用OH\_JSVM\_MemoryPressureNotification后”三个节点查看内存状态
JSVM\_HandleScope tmpscope = nullptr;
OH\_JSVM\_OpenHandleScope(env, &tmpscope);
for (int i = 0; i < 1000000; ++i) {
    JSVM\_Value obj;
    OH\_JSVM\_CreateObject(env, &obj);
}
JSVM\_HeapStatistics mem;
OH\_JSVM\_GetHeapStatistics(vm, &mem); // 获取虚拟机堆的统计数据
OH\_LOG\_INFO(LOG\_APP, "%{public}zu\\n", mem.usedHeapSize); // 申请完成后，内存处于最大状态
OH\_JSVM\_CloseHandleScope(env, tmpscope); // 关闭Handle scope

OH\_JSVM\_GetHeapStatistics(vm, &mem);
OH\_LOG\_INFO(LOG\_APP, "%{public}zu\\n", mem.usedHeapSize); // 关闭scope后，GC并没有立即回收

// 通知虚拟机系统内存压力层级，并有选择地触发垃圾回收
OH\_JSVM\_MemoryPressureNotification(env, JSVM\_MEMORY\_PRESSURE\_LEVEL\_CRITICAL); // 假设内存压力处于临界状态

OH\_JSVM\_GetHeapStatistics(vm, &mem);
OH\_LOG\_INFO(LOG\_APP, "%{public}zu\\n", mem.usedHeapSize); // 触发垃圾回收后

BackingStore 正确使用示例

void \*backingStore;
JSVM\_Value arrayBuffer;

// 申请一块大小为 100 字节的 BackingStore 内存
OH\_JSVM\_AllocateArrayBufferBackingStoreData(100, JSVM\_ZERO\_INITIALIZED, &backingStore);

// 在之前申请的 BackingStore 上创建一个 ArrayBuffer，位置为距离 BackingStore 起始地址加 30 字节处，大小为 20 字节
OH\_JSVM\_CreateArrayBufferFromBackingStoreData(env, backingStore, 100, 30, 20, &arrayBuffer);

// 在 JS 中使用创建的 ArrayBuffer
JSVM\_Value js\_global;
JSVM\_Value name;
OH\_JSVM\_GetGlobal(env, &js\_global);
OH\_JSVM\_CreateStringUtf8(env, "buffer", JSVM\_AUTO\_LENGTH, &name);
OH\_JSVM\_SetProperty(env, js\_global, name, arrayBuffer);

JSVM\_Script script;
JSVM\_Value scriptString;
JSVM\_Value result;
const char \*src = R"JS(
function writeBuffer(data) {
  let view = new Uint8Array(data);
  // Write some values to the ArrayBuffer
  for (let i = 0; i < view.length; i++) {
    view\[i\] = i % 256;
  }
}
writeBuffer(buffer)
)JS";
OH\_JSVM\_CreateStringUtf8(env, src, JSVM\_AUTO\_LENGTH, &scriptString);
OH\_JSVM\_CompileScriptWithOptions(env, scriptString, 0, nullptr, &script);
OH\_JSVM\_RunScript(env, script, &result);

// 检查 ArrayBuffer 的内容
uint8\_t \*array = static\_cast<uint8\_t\*>(backingStore);
for (auto i = 0; i < 100; ++i) {
  if (array\[i\] != i % 256) {
    return false;
  }
}

// 释放 array buffer. 注意对于这种方式创建的 ArrayBuffer, 在释放对应的 BackingStore 之前,
// 务必使用 OH\_JSVM\_DetachArraybuffer 将所有使用当前的 BackingStore 创建的 ArrayBuffer 释放
// 否则可能产生不可预测的内存问题，请谨慎使用
OH\_JSVM\_DetachArraybuffer(env, arrayBuffer);

// 释放申请的 backing store 内存
OH\_JSVM\_FreeArrayBufferBackingStoreData(backingStore);

#### \[h2\]Promise操作

**场景介绍**

Promise相关操作。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CreatePromise | 创建一个延迟对象和一个JavaScript promise |
| OH\_JSVM\_ResolveDeferred | 通过与之关联的延迟对象来解析JavaScript promise |
| OH\_JSVM\_RejectDeferred | 通过与之关联的延迟对象来拒绝JavaScript Promise |
| OH\_JSVM\_IsPromise | 查询Promise是否为原生Promise对象 |

场景示例：

Promise相关操作。

JSVM\_Deferred deferred;
JSVM\_Value promise;
OH\_JSVM\_CreatePromise(env, &deferred, &promise);

// 模拟异步操作
int result = 42;
bool success = true;
if (success)
{
    // 解析Promise，并传递结果
    JSVM\_Value value;
    OH\_JSVM\_CreateInt32(env, result, &value);
    OH\_JSVM\_ResolveDeferred(env, deferred, value);
} else {
    // 拒绝Promise，并传递错误信息
    JSVM\_Value code = nullptr;
    JSVM\_Value message = nullptr;
    OH\_JSVM\_CreateStringUtf8(env, "600", JSVM\_AUTO\_LENGTH, &code);
    OH\_JSVM\_CreateStringUtf8(env, "Async operation failed", JSVM\_AUTO\_LENGTH, &message);
    JSVM\_Value error = nullptr;
    OH\_JSVM\_CreateError(env, code, message, &error);
    OH\_JSVM\_RejectDeferred(env, deferred, error);
}

#### \[h2\]JSON操作

**场景介绍**

JSON操作。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_JsonParse | 解析JSON字符串，并返回成功解析的值 |
| OH\_JSVM\_JsonStringify | 将对象字符串化，并返回成功转换后的字符串 |

场景示例：

解析JSON操作。

std::string sourcecodestr = "{\\"name\\": \\"John\\", \\"age\\": 30, \\"city\\": \\"New York\\"}" ;
JSVM\_Value jsonString;
OH\_JSVM\_CreateStringUtf8(env, sourcecodestr.c\_str(), sourcecodestr.size(), &jsonString);
JSVM\_Value result;
OH\_JSVM\_JsonParse(env, jsonString, &result);

#### \[h2\]创建和使用虚拟机的启动快照

**场景介绍**

创建和使用虚拟机的启动快照。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_CreateSnapshot | 用于创建虚拟机的启动快照 |
| OH\_JSVM\_CreateEnvFromSnapshot | 基于启动快照创建jsvm环境 |

场景示例：

[创建和使用虚拟机的启动快照。](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-create-snapshot)

#### \[h2\]检查传入的值是否可调用

**场景介绍**

检查传入的值是否可调用。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_IsCallable | 检查传入的值是否可调用 |

场景示例：

检查传入的值是否可调用。

static JSVM\_Value NapiIsCallable(JSVM\_Env env, JSVM\_CallbackInfo info) {
    JSVM\_Value value, rst;
    size\_t argc = 1;
    bool isCallable = false;
    JSVM\_CALL(OH\_JSVM\_GetCbInfo(env, info, &argc, &value, NULL, NULL));
    JSVM\_CALL(OH\_JSVM\_IsCallable(env, value, &isCallable));
    OH\_JSVM\_GetBoolean(env, isCallable, &rst);
    return rst;
}

static napi\_value MyJSVMDemo(\[\[maybe\_unused\]\] napi\_env \_env, \[\[maybe\_unused\]\] napi\_callback\_info \_info) {
    std::thread t(\[\]() {
        // create vm, and open vm scope
        JSVM\_VM vm;
        JSVM\_CreateVMOptions options;
        memset(&options, 0, sizeof(options));
        OH\_JSVM\_CreateVM(&options, &vm);
        JSVM\_VMScope vmScope;
        OH\_JSVM\_OpenVMScope(vm, &vmScope);
        JSVM\_CallbackStruct param\[\] = {
            {.data = nullptr, .callback = NapiIsCallable},
        };
        JSVM\_PropertyDescriptor descriptor\[\] = {
            {"napiIsCallable", NULL, &param\[0\], NULL, NULL, NULL, JSVM\_DEFAULT},
        };
        // create env, register native method, and open env scope
        JSVM\_Env env;
        OH\_JSVM\_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor\[0\]), descriptor, &env);
        JSVM\_EnvScope envScope;
        OH\_JSVM\_OpenEnvScope(env, &envScope);
        // open handle scope
        JSVM\_HandleScope handleScope;
        OH\_JSVM\_OpenHandleScope(env, &handleScope);
        std::string sourceCodeStr = R"JS(
        function addNumbers(num1, num2)
        {
            var rst= num1 + num2;
            return rst;
        }
        let rst = napiIsCallable(addNumbers);
        )JS";
        // compile js script
        JSVM\_Value sourceCodeValue;
        OH\_JSVM\_CreateStringUtf8(env, sourceCodeStr.c\_str(), sourceCodeStr.size(), &sourceCodeValue);
        JSVM\_Script script;
        OH\_JSVM\_CompileScript(env, sourceCodeValue, nullptr, 0, true, nullptr, &script);
        JSVM\_Value result;
        // run js script
        OH\_JSVM\_RunScript(env, script, &result);
        JSVM\_ValueType type;
        OH\_JSVM\_Typeof(env, result, &type);
        OH\_LOG\_INFO(LOG\_APP, "JSVM API TEST type: %{public}d", type);
        // exit vm and clean memory
        OH\_JSVM\_CloseHandleScope(env, handleScope);
        OH\_JSVM\_CloseEnvScope(env, envScope);
        OH\_JSVM\_DestroyEnv(env);
        OH\_JSVM\_CloseVMScope(vm, vmScope);
        OH\_JSVM\_DestroyVM(vm);
    });
    t.detach();
    return nullptr;
}

#### \[h2\]Lock操作

**场景介绍**

Lock操作。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_IsLocked | 判断当前线程是否持有指定环境的锁 |
| OH\_JSVM\_AcquireLock | 获取指定环境的锁 |
| OH\_JSVM\_ReleaseLock | 释放指定环境的锁 |

场景示例：

加锁解锁操作。

class LockWrapper {
 public:
  LockWrapper(JSVM\_Env env) : env(env) {
    OH\_JSVM\_IsLocked(env, &isLocked);
    if (!isLocked) {
      OH\_JSVM\_AcquireLock(env);
      OH\_JSVM\_GetVM(env, &vm);
      OH\_JSVM\_OpenVMScope(vm, &vmScope);
      OH\_JSVM\_OpenEnvScope(env, &envScope);
    }
  }

  ~LockWrapper() {
    if (!isLocked) {
      OH\_JSVM\_CloseEnvScope(env, envScope);
      OH\_JSVM\_CloseVMScope(vm, vmScope);
      OH\_JSVM\_ReleaseLock(env);
    }
  }

  LockWrapper(const LockWrapper&) = delete;
  LockWrapper& operator=(const LockWrapper&) = delete;
  LockWrapper(LockWrapper&&) = delete;
  void\* operator new(size\_t) = delete;
  void\* operator new\[\](size\_t) = delete;

 private:
  JSVM\_Env env;
  JSVM\_EnvScope envScope;
  JSVM\_VMScope vmScope;
  JSVM\_VM vm;
  bool isLocked;
};

static int aa = 0;

static napi\_value Add(\[\[maybe\_unused\]\] napi\_env \_env, \[\[maybe\_unused\]\] napi\_callback\_info \_info) {
    static JSVM\_VM vm;
    static JSVM\_Env env;
    if (aa == 0) {
        OH\_JSVM\_Init(nullptr);
        aa++;
        // create vm
        JSVM\_CreateVMOptions options;
        memset(&options, 0, sizeof(options));
        OH\_JSVM\_CreateVM(&options, &vm);
        // create env
        OH\_JSVM\_CreateEnv(vm, 0, nullptr, &env);
    }

    std::thread t1(\[\]() {
        LockWrapper lock(env);
        JSVM\_HandleScope handleScope;
        OH\_JSVM\_OpenHandleScope(env, &handleScope);
        JSVM\_Value value;
        JSVM\_Status rst = OH\_JSVM\_CreateInt32(env, 32, &value); // 32: numerical value
        if (rst == JSVM\_OK) {
            OH\_LOG\_INFO(LOG\_APP, "JSVM:t1 OH\_JSVM\_CreateInt32 suc");
        } else {
            OH\_LOG\_ERROR(LOG\_APP, "JSVM:t1 OH\_JSVM\_CreateInt32 fail");
        }
        int32\_t num1 = 0;
        OH\_JSVM\_GetValueInt32(env, value, &num1);
        OH\_LOG\_INFO(LOG\_APP, "JSVM:t1 num1 = %{public}d", num1);
        OH\_JSVM\_CloseHandleScope(env, handleScope);
    });
    std::thread t2(\[\]() {
        LockWrapper lock(env);
        JSVM\_HandleScope handleScope;
        OH\_JSVM\_OpenHandleScope(env, &handleScope);
        JSVM\_Value value;
        JSVM\_Status rst = OH\_JSVM\_CreateInt32(env, 32, &value); // 32: numerical value
        if (rst == JSVM\_OK) {
            OH\_LOG\_INFO(LOG\_APP, "JSVM:t2 OH\_JSVM\_CreateInt32 suc");
        } else {
            OH\_LOG\_ERROR(LOG\_APP, "JSVM:t2 OH\_JSVM\_CreateInt32 fail");
        }
        int32\_t num1 = 0;
        OH\_JSVM\_GetValueInt32(env, value, &num1);
        OH\_LOG\_INFO(LOG\_APP, "JSVM:t2 num1 = %{public}d", num1);
        OH\_JSVM\_CloseHandleScope(env, handleScope);
    });
    t1.detach();
    t2.detach();
    return nullptr;
}

#### \[h2\]设置与获取和当前运行的JSVM环境相关联的数据

**场景介绍**

调用OH\_JSVM\_SetInstanceData接口，设置与当前运行的JSVM环境相关联的数据。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_SetInstanceData | 设置与当前运行的JSVM环境相关联的数据 |
| OH\_JSVM\_GetInstanceData | 获取与当前运行的JSVM环境相关联的数据 |

场景示例：

设置并获取与当前运行的JSVM环境相关联的数据。

JSVM\_VM vm;
JSVM\_CreateVMOptions options;
JSVM\_VMScope vm\_scope;
JSVM\_Env env;
JSVM\_EnvScope envScope;
JSVM\_HandleScope handlescope;

static int aa = 0;
struct InstanceData {
    int32\_t value;
};

// 初始化虚拟机，创建JSVM运行环境
void init\_JSVM\_environment(){
    JSVM\_InitOptions init\_options;
    memset(&init\_options, 0, sizeof(init\_options));
    if (aa == 0) {
        OH\_JSVM\_Init(&init\_options);
        aa++;
    }
    memset(&options, 0, sizeof(options));
    OH\_JSVM\_CreateVM(&options, &vm);
    OH\_JSVM\_OpenVMScope(vm, &vm\_scope);
    OH\_JSVM\_CreateEnv(vm, 0, nullptr, &env);
    OH\_JSVM\_OpenEnvScope(env, &envScope);
    OH\_JSVM\_OpenHandleScope(env, &handlescope);
}

// 退出虚拟机，释放对应的环境
napi\_value close\_JSVM\_environment(napi\_env env1, napi\_callback\_info info)
{
    OH\_JSVM\_CloseHandleScope(env, handlescope);
    OH\_JSVM\_CloseEnvScope(env, envScope);
    OH\_JSVM\_DestroyEnv(env);
    OH\_JSVM\_CloseVMScope(vm, vm\_scope);
    OH\_JSVM\_DestroyVM(vm);
    napi\_value result;
    char\* s = "ok";
    napi\_create\_string\_latin1(env1, s, strlen(s), &result);
    return result;
}

// 清除和释放与实例相关联的内存资源
void InstanceFinalizeCallback(JSVM\_Env env, void \*finalizeData, void \*finalizeHint)
{
    if (finalizeData) {
        InstanceData \*data = reinterpret\_cast<InstanceData \*>(finalizeData);
        free(data);
        \*(InstanceData \*\*)finalizeData = nullptr;
    }
}

static napi\_value GetInstanceData(napi\_env env1, napi\_callback\_info info)
{
    InstanceData \*instanceData = reinterpret\_cast<InstanceData \*>(malloc(sizeof(InstanceData)));
    if (instanceData == nullptr) {
        printf("Memory allocation failed!\\n");
        return nullptr;
    }
    size\_t argc = 1;
    napi\_value args\[1\] = {nullptr};
    // 用于获取回调函数参数
    napi\_get\_cb\_info(env1, info, &argc, args , nullptr, nullptr);
    napi\_valuetype valuetype0;
    napi\_typeof(env1, args\[0\], &valuetype0);
    int32\_t tmp = 0;
    napi\_get\_value\_int32(env1, args\[0\], &tmp);
    instanceData->value = tmp;
    // 将获得的参数与当前运行的JSVM环境关联起来
    OH\_JSVM\_SetInstanceData(env, instanceData, InstanceFinalizeCallback, nullptr);
    InstanceData \*resData = nullptr;
    // 获取与当前运行的JSVM环境相关联的数据
    OH\_JSVM\_GetInstanceData(env, (void \*\*)&resData);
    napi\_value result;
    napi\_create\_uint32(env1, resData->value, &result);
    return result;
}

#### \[h2\]任务队列

**场景介绍**

在虚拟机内部启动任务队列的运行，检查队列中是否有待处理的微任务。任务队列可由外部事件循环执行。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_PumpMessageLoop | 启动任务队列的运行 |
| OH\_JSVM\_PerformMicrotaskCheckpoint | 执行任务队列里的微任务 |

场景示例：

[使用JSVM-API接口进行任务队列相关开发](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-execute_tasks)

#### \[h2\]后台反序列化

**场景介绍**

后台反序列化允许在后台线程中异步反序列化代码缓存，通过减少同步反序列化时间提升应用启动性能。

**接口说明**

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_BackgroundDeserialize | 在线程池中反序列化 JSVM\_CodeCache，通过 OH\_JSVM\_ReleaseDeserializeResult 接口释放 JSVM\_DeserializeResult。 |
| OH\_JSVM\_ReleaseDeserializeResult | 当 JSVM\_DeserializeResult 不再被使用时进行释放。 |