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, ¶m[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