使用JSVM-API接口进行debug操作
=====================

#### 简介

JSVM-API中提供接口，可以启用/禁用特定JSVM\_Env下的指定debug选项。目前支持的debug选项有JSVM\_SCOPE\_CHECK。

#### debug选项介绍

debug选项皆为JSVM\_DebugOption类型。

#### \[h2\]JSVM\_SCOPE\_CHECK

*   开发者在开发时，可能会出现在HandleScope结束后，调用上一次HandleScope内的JSVM\_Value类型变量，导致程序崩溃。JSVM\_SCOPE\_CHECK为scope校验手段，校验当前调用的JSVM\_Value类型变量是否超出HandleScope作用域，如果超出，则抛出错误“Run in wrong HandleScope”。
*   开启该debug选项后，若JSVM-API创建了JSVM\_Value，则在hilog中有“ADD\_VAL\_TO\_SCOPE\_CHECK in function: \[函数名\]”输出，例如“ADD\_VAL\_TO\_SCOPE\_CHECK in function: OH\_JSVM\_GetBoolean”。若JSVM-API使用了JSVM\_Value，则在hilog中有“CHECK\_SCOPE in function: \[函数名\]”输出，表示对使用的JSVM\_Value进行了HandleScope校验，例如“CHECK\_SCOPE in function: OH\_JSVM\_IsBoolean”。

#### 接口说明

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_SetDebugOption | 启用/禁用特定JSVM\_Env的指定debug选项。传入的debug选项参数debugOption必须为JSVM\_DebugOption类型，布尔值参数isEnabled用于控制是否开启该debug选项。此API仅供debug时使用，开启后可能会带来性能下降。 |

#### 使用示例

JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-process)，本文仅对接口对应C++相关代码进行展示。

#### \[h2\]JSVM\_DebugOption

仅需替换[使用JSVM-API实现JS与C/C++语言交互开发流程](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-process)示例代码中的“TestJSVM()”函数即可运行。

*   在正确的HandleScope内调用JSVM\_Value类型变量。

static int32\_t TestJSVM()
{
    JSVM\_InitOptions initOptions = {0};
    JSVM\_VM vm;
    JSVM\_Env env = nullptr;
    JSVM\_VMScope vmScope;
    JSVM\_EnvScope envScope;
    JSVM\_HandleScope handleScope;

    // 初始化JavaScript引擎实例
    if (g\_aa == 0) {
        g\_aa++;
        CHECK(OH\_JSVM\_Init(&initOptions));
    }
    // 创建JSVM环境
    CHECK(OH\_JSVM\_CreateVM(nullptr, &vm));
    CHECK(OH\_JSVM\_OpenVMScope(vm, &vmScope));
    CHECK(OH\_JSVM\_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor\[0\]), descriptor, &env));
    // 打开JSVM\_SCOPE\_CHECK校验选项
    CHECK(OH\_JSVM\_SetDebugOption(env, JSVM\_SCOPE\_CHECK, true));
    CHECK\_RET(OH\_JSVM\_OpenEnvScope(env, &envScope));
    // 打开HandleScope
    CHECK\_RET(OH\_JSVM\_OpenHandleScope(env, &handleScope));

    // 通过script调用测试函数
    JSVM\_Script script;
    JSVM\_Value jsSrc, result;
    CHECK\_RET(OH\_JSVM\_CreateStringUtf8(env, srcCallNative, JSVM\_AUTO\_LENGTH, &jsSrc));
    CHECK\_RET(OH\_JSVM\_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
    CHECK\_RET(OH\_JSVM\_RunScript(env, script, &result));

    bool boolResult = true;
    // OH\_JSVM\_IsBoolean接口调用JSVM\_Value类型变量result
    JSVM\_Status status = OH\_JSVM\_IsBoolean(env, result, &boolResult);
    if (status != JSVM\_OK) {
        OH\_LOG\_ERROR(LOG\_APP, "JSVM OH\_JSVM\_IsBoolean: failed");
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM OH\_JSVM\_IsBoolean: success: %{public}d", boolResult);
    }

    // 销毁JSVM环境
    // 关闭HandleScope
    CHECK\_RET(OH\_JSVM\_CloseHandleScope(env, handleScope));
    CHECK\_RET(OH\_JSVM\_CloseEnvScope(env, envScope));
    // 关闭JSVM\_SCOPE\_CHECK校验选项
    CHECK(OH\_JSVM\_SetDebugOption(env, JSVM\_SCOPE\_CHECK, false));
    CHECK(OH\_JSVM\_DestroyEnv(env));
    CHECK(OH\_JSVM\_CloseVMScope(vm, vmScope));
    CHECK(OH\_JSVM\_DestroyVM(vm));
    return 0;
}

**执行结果**

hilog中有以下结果输出：

ADD\_VAL\_TO\_SCOPE\_CHECK in function: NewString
CHECK\_SCOPE in function: OH\_JSVM\_CompileScript
ADD\_VAL\_TO\_SCOPE\_CHECK in function: OH\_JSVM\_GetCbInfo
ADD\_VAL\_TO\_SCOPE\_CHECK in function: OH\_JSVM\_GetCbInfo
ADD\_VAL\_TO\_SCOPE\_CHECK in function: OH\_JSVM\_GetCbInfo
CHECK\_SCOPE in function: OH\_JSVM\_StrictEquals
CHECK\_SCOPE in function: OH\_JSVM\_StrictEquals
JSVM OH\_JSVM\_StrictEquals: success: 0
ADD\_VAL\_TO\_SCOPE\_CHECK in function: OH\_JSVM\_GetBoolean
ADD\_VAL\_TO\_SCOPE\_CHECK in function: OH\_JSVM\_RunScript
CHECK\_SCOPE in function: OH\_JSVM\_IsBoolean
JSVM OH\_JSVM\_IsBoolean: success: 1

*   在错误的HandleScope内调用JSVM\_Value类型变量。

static int32\_t TestJSVM()
{
    JSVM\_InitOptions initOptions = {0};
    JSVM\_VM vm;
    JSVM\_Env env = nullptr;
    JSVM\_VMScope vmScope;
    JSVM\_EnvScope envScope;
    JSVM\_HandleScope handleScope;

    // 初始化JavaScript引擎实例
    if (g\_aa == 0) {
        g\_aa++;
        CHECK(OH\_JSVM\_Init(&initOptions));
    }
    // 创建JSVM环境
    CHECK(OH\_JSVM\_CreateVM(nullptr, &vm));
    CHECK(OH\_JSVM\_OpenVMScope(vm, &vmScope));
    CHECK(OH\_JSVM\_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor\[0\]), descriptor, &env));
    // 打开JSVM\_SCOPE\_CHECK校验选项
    CHECK(OH\_JSVM\_SetDebugOption(env, JSVM\_SCOPE\_CHECK, true));
    CHECK\_RET(OH\_JSVM\_OpenEnvScope(env, &envScope));
    // 打开HandleScope
    CHECK\_RET(OH\_JSVM\_OpenHandleScope(env, &handleScope));

    // 通过script调用测试函数
    JSVM\_Script script;
    JSVM\_Value jsSrc, result;
    CHECK\_RET(OH\_JSVM\_CreateStringUtf8(env, srcCallNative, JSVM\_AUTO\_LENGTH, &jsSrc));
    CHECK\_RET(OH\_JSVM\_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
    CHECK\_RET(OH\_JSVM\_RunScript(env, script, &result));

    bool boolResult = true;

    // 销毁JSVM环境
    // 关闭HandleScope
    CHECK\_RET(OH\_JSVM\_CloseHandleScope(env, handleScope));
    // OH\_JSVM\_IsBoolean接口在错误的HandleScope调用JSVM\_Value类型变量result
    JSVM\_Status status = OH\_JSVM\_IsBoolean(env, result, &boolResult);
    CHECK\_RET(OH\_JSVM\_CloseEnvScope(env, envScope));
    // 关闭JSVM\_SCOPE\_CHECK校验选项
    CHECK(OH\_JSVM\_SetDebugOption(env, JSVM\_SCOPE\_CHECK, false));
    CHECK(OH\_JSVM\_DestroyEnv(env));
    CHECK(OH\_JSVM\_CloseVMScope(vm, vmScope));
    CHECK(OH\_JSVM\_DestroyVM(vm));
    return 0;
}

**执行结果**

程序崩溃，有cppcrash日志生成，在hilog中可以检索到类似以下的信息：

JSVM Fatal Error Position : "../../../../../../../arkcompiler/jsvm/src/js\_native\_api\_v8.cpp":4537
JSVM Fatal Error Message : "Run in wrong HandleScope"