• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用JSVM-API接口进行任务队列相关开发
2<!--Kit: NDK Development-->
3<!--Subsystem: arkcompiler-->
4<!--Owner: @yuanxiaogou; @string_sz-->
5<!--Designer: @knightaoko-->
6<!--Tester: @test_lzz-->
7<!--Adviser: @fang-jinxu-->
8
9## 简介
10
11在虚拟机内启动任务队列,检查队列中是否有待处理的微任务。任务队列可由外部事件循环执行。
12
13## 基本概念
14
15- **任务队列**:用于管理异步任务的调度和执行,确保任务按顺序处理。
16- **微任务**:微任务是一种任务调度机制,主要用于处理那些需要尽快执行的较小任务,它们通常具有较高的优先级。
17
18## 接口说明
19
20| 接口 | 功能说明 |
21| -------- | -------- |
22|OH_JSVM_PumpMessageLoop| 启动任务队列的运行 |
23|OH_JSVM_PerformMicrotaskCheckpoint| 执行任务队列里的微任务 |
24| OH_JSVM_SetMicrotaskPolicy | 设置微任务执行策略 |
25
26## 使用示例
27
28JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](use-jsvm-process.md),本文仅展示接口对应的C++相关代码。
29权限要求:Wasm字节码需要应用拥有JIT权限才能执行,可参考[JSVM 申请JIT权限指导](jsvm-apply-jit-profile.md)申请对应权限。
30运行限制:当前 JSVM 版本在坚盾守护模式下将禁用 WebAssembly 全部功能模块。开发者需针对此限制进行应用兼容性评估,具体技术规范详见[JSVM 坚盾守护模式](jsvm-secure-shield-mode.md)。
31### OH_JSVM_PumpMessageLoop & OH_JSVM_PerformMicrotaskCheckpoint
32
33启动任务队列,执行任务。
34
35cpp部分代码:
36
37```cpp
38#include <chrono>
39#include <string.h>
40
41static int g_aa = 0;
42
43// 待执行的js代码
44static const char *STR_TASK = R"JS(
45    // wasm 字节码 (以add 模块为例)
46    // 以下 wasmBuffer 对应的 wasm 字节码文本格式如下所示,只包含了一个函数 add
47    // (module
48    //   (func $add (param $lhs i32) (param $rhs i32) (result i32)
49    //     local.get $lhs
50    //     local.get $rhs
51    //     i32.add
52    //   )
53    //   (export "add" (func $add))
54    // )
55    var wasmBytes = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
56                                       0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
57                                       0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
58                                       0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b]);
59
60    var p = WebAssembly.instantiate(wasmBytes, {});
61    p.then((result) => {
62        consoleinfo("Called with instance " + result);
63    });
64    p.finally(() => {
65       consoleinfo("Called Finally");
66    });
67)JS";
68
69// 保证js代码中的打印信息可以正常输出
70static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) {
71    size_t argc = 1;
72    JSVM_Value args[1];
73    char log[256] = "";
74    size_t logLength = 0;
75    JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL));
76
77    OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength);
78    log[255] = 0;
79    OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log);
80    return nullptr;
81}
82
83// 注册consoleinfo的方法
84JSVM_CallbackStruct param[] = {
85    {.data = nullptr, .callback = ConsoleInfo},
86};
87JSVM_PropertyDescriptor descriptor[] = {
88    {"consoleinfo", NULL, &param[0], NULL, NULL, NULL, JSVM_DEFAULT},
89};
90
91static int32_t TestJSVM() {
92    JSVM_InitOptions init_options;
93    memset(&init_options, 0, sizeof(init_options));
94    if (g_aa == 0) {
95        OH_JSVM_Init(&init_options);
96        g_aa++;
97    }
98    // 创建JavaScript虚拟机实例,打开虚拟机作用域
99    JSVM_VM vm;
100    JSVM_CreateVMOptions options;
101    memset(&options, 0, sizeof(options));
102    CHECK(OH_JSVM_CreateVM(&options, &vm));
103    JSVM_VMScope vm_scope;
104    CHECK(OH_JSVM_OpenVMScope(vm, &vm_scope));
105
106    JSVM_Env env;
107    CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env));
108    JSVM_EnvScope envScope;
109    CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
110    JSVM_HandleScope handlescope;
111    CHECK_RET(OH_JSVM_OpenHandleScope(env, &handlescope));
112    JSVM_Value sourcecodevalue;
113    CHECK_RET(OH_JSVM_CreateStringUtf8(env, STR_TASK, strlen(STR_TASK), &sourcecodevalue));
114    JSVM_Script script;
115    CHECK_RET(OH_JSVM_CompileScript(env, sourcecodevalue, nullptr, 0, true, nullptr, &script));
116    JSVM_Value result;
117    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
118    bool rst = false;
119    auto start = std::chrono::system_clock::now();
120    while (true) {
121        // 如果任务队列中没有任务启动,则rst设置为false
122        CHECK_RET(OH_JSVM_PumpMessageLoop(vm, &rst));
123        CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm));
124        // 定时退出
125        auto now = std::chrono::system_clock::now();
126        auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
127        if (cost > 100) {
128            break;
129        }
130    }
131
132    // 关闭并销毁环境和虚拟机
133    CHECK_RET(OH_JSVM_CloseHandleScope(env, handlescope));
134    CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
135    CHECK(OH_JSVM_DestroyEnv(env));
136    CHECK(OH_JSVM_CloseVMScope(vm, vm_scope));
137    CHECK(OH_JSVM_DestroyVM(vm));
138    return 0;
139}
140
141```
142<!-- @[oh_jsvm_pump_message_loop_and_perform_microtask_checkpoint](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/JSVMAPI/JsvmUsageGuide/UsageInstructionsOne/pumpmessageloop/src/main/cpp/hello.cpp) -->
143预期输出结果:
144```
145JSVM API TEST: Called with instance [object Object]
146JSVM API TEST: Called Finally
147```
148### OH_JSVM_SetMicrotaskPolicy
149修改微任务执行策略,通过该接口,用户可以将策略设置为 JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT 或 JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO。默认模式下,微任务的执行策略为 JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO。
150
151微任务策略:
152- JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT : 微任务在用户调用 OH_JSVM_PerformMicrotaskCheckpoint 后执行
153- JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO: 微任务在 JS 调用栈为空时自动执行
154
155cpp 部分代码
156
157```cpp
158// OH_JSVM_SetMicrotaskPolicy的样例方法
159static int SetMicrotaskPolicy(JSVM_VM vm, JSVM_Env env) {
160    // 默认或将策略设置为 JSVM_MICROTASK_AUTO 的行为
161    const char *scriptEvalMicrotask = R"JS(
162        evaluateMicrotask = false;
163        Promise.resolve().then(()=>{
164            evaluateMicrotask = true;
165        });
166    )JS";
167    JSVM_Script script;
168    JSVM_Value jsSrc;
169    JSVM_Value result;
170    CHECK_RET(OH_JSVM_CreateStringUtf8(env, scriptEvalMicrotask, JSVM_AUTO_LENGTH, &jsSrc));
171    CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script));
172    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
173    JSVM_Value global;
174    CHECK_RET(OH_JSVM_GetGlobal(env, &global));
175    JSVM_Value hasEvaluateMicrotask;
176    CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask));
177    bool val = false;
178    CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val));
179
180    OH_LOG_INFO(LOG_APP, "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask : %{public}d", val);
181
182    // 策略设置为 JSVM_MICROTASK_EXPLICIT 的行为
183    CHECK_RET(OH_JSVM_SetMicrotaskPolicy(vm, JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT));
184    CHECK_RET(OH_JSVM_RunScript(env, script, &result));
185    CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask));
186    CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val));
187    OH_LOG_INFO(
188        LOG_APP,
189        "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask before calling OH_JSVM_PerformMicrotaskCheckpoint: %{public}d",
190        val);
191
192    CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm));
193    CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask));
194    CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val));
195    OH_LOG_INFO(
196        LOG_APP,
197        "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask after calling OH_JSVM_PerformMicrotaskCheckpoint: %{public}d",
198        val);
199
200    return 0;
201}
202
203static void RunDemo(JSVM_VM vm, JSVM_Env env) {
204    if (SetMicrotaskPolicy(vm, env) != 0) {
205        OH_LOG_INFO(LOG_APP, "Run Microtask Policy failed");
206    }
207}
208
209static int32_t TestJSVM() {
210    JSVM_InitOptions initOptions = {0};
211    JSVM_VM vm;
212    JSVM_Env env = nullptr;
213    JSVM_VMScope vmScope;
214    JSVM_EnvScope envScope;
215    JSVM_HandleScope handleScope;
216    JSVM_Value result;
217    // 初始化JavaScript引擎实例
218    if (g_aa == 0) {
219        g_aa++;
220        CHECK(OH_JSVM_Init(&initOptions));
221    }
222    // 创建JSVM环境
223    CHECK(OH_JSVM_CreateVM(nullptr, &vm));
224    CHECK(OH_JSVM_CreateEnv(vm, 0, nullptr, &env));
225    CHECK(OH_JSVM_OpenVMScope(vm, &vmScope));
226    CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope));
227    CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope));
228
229    // 通过script调用测试函数
230    RunDemo(vm, env);
231
232    // 销毁JSVM环境
233    CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope));
234    CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope));
235    CHECK(OH_JSVM_CloseVMScope(vm, vmScope));
236    CHECK(OH_JSVM_DestroyEnv(env));
237    CHECK(OH_JSVM_DestroyVM(vm));
238    return 0;
239}
240```
241
242预期输出结果:
243```
244Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask : 1
245Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask before calling OH_JSVM_PerformMicrotaskCheckpoint: 0
246Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask after calling OH_JSVM_PerformMicrotaskCheckpoint: 1
247```
248