1# Working with Tasks Using JSVM-API 2 3## Introduction 4 5JSVM-API provides APIs for processing and dispatching the tasks that are queued up for execution. You can use the APIs to start the running of a task queue in a JSVM and check whether there are micro tasks waiting in the queue. The task queue can be executed cyclically by external events. 6 7## Basic Concepts 8 9- Task queue: a mechanism used to manage the scheduling and execution of asynchronous tasks to ensure that tasks are processed in sequence. 10- Micro task: a small task that needs to be executed as soon as possible. Micro tasks usually have a higher priority. 11 12## Available APIs 13 14| API| Description| 15| -------- | -------- | 16|OH_JSVM_PumpMessageLoop| Starts running a task queue.| 17|OH_JSVM_PerformMicrotaskCheckpoint| Executes micro tasks in a task queue.| 18| OH_JSVM_SetMicrotaskPolicy | Sets the execution policy for micro tasks.| 19 20## Example 21 22If you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following demonstrates only the C++ code involved in task queue development. 23> **NOTE**<br>To run the WebAssembly (Wasm) bytecode, the application must have the JIT permission. For details about how to apply for the permission, see [Requesting the JIT Permission](jsvm-apply-jit-profile.md). 24### OH_JSVM_PumpMessageLoop and OH_JSVM_PerformMicrotaskCheckpoint 25 26Call **OH_JSVM_PumpMessageLoop** to start running a task queue. 27 28CPP code: 29 30```cpp 31#include <chrono> 32#include <string.h> 33 34 35// JS code to be executed. 36static const char *STR_TASK = R"JS( 37 // Wasm bytecode (using the add module as an example) 38 // The following is the text format of the Wasm bytecode corresponding to wasmBuffer, which contains only the add function. 39 // (module 40 // (func $add (param $lhs i32) (param $rhs i32) (result i32) 41 // local.get $lhs 42 // local.get $rhs 43 // i32.add 44 // ) 45 // (export "add" (func $add)) 46 // ) 47 var wasmBytes = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 48 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 49 0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01, 50 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b]); 51 52 var p = WebAssembly.instantiate(wasmBytes, {}); 53 p.then((result) => { 54 consoleinfo("Called with instance " + result); 55 }); 56 p.finally(() => { 57 consoleinfo("Called Finally"); 58 }); 59)JS"; 60 61// Ensure normal printing of the JS code information. 62static JSVM_Value ConsoleInfo(JSVM_Env env, JSVM_CallbackInfo info) { 63 size_t argc = 1; 64 JSVM_Value args[1]; 65 char log[256] = ""; 66 size_t logLength; 67 JSVM_CALL(OH_JSVM_GetCbInfo(env, info, &argc, args, NULL, NULL)); 68 69 OH_JSVM_GetValueStringUtf8(env, args[0], log, 255, &logLength); 70 log[255] = 0; 71 OH_LOG_INFO(LOG_APP, "JSVM API TEST: %{public}s", log); 72 return nullptr; 73} 74 75// Register the consoleinfo callback. 76JSVM_CallbackStruct param[] = { 77 {.data = nullptr, .callback = ConsoleInfo}, 78}; 79JSVM_PropertyDescriptor descriptor[] = { 80 {"consoleinfo", NULL, ¶m[0], NULL, NULL, NULL, JSVM_DEFAULT}, 81}; 82 83static int32_t TestJSVM() { 84 JSVM_InitOptions init_options; 85 memset(&init_options, 0, sizeof(init_options)); 86 if (g_aa == 0) { 87 OH_JSVM_Init(&init_options); 88 g_aa++; 89 } 90 // Create a JSVM instance and open the VM scope. 91 JSVM_VM vm; 92 JSVM_CreateVMOptions options; 93 memset(&options, 0, sizeof(options)); 94 CHECK(OH_JSVM_CreateVM(&options, &vm)); 95 JSVM_VMScope vm_scope; 96 CHECK(OH_JSVM_OpenVMScope(vm, &vm_scope)); 97 98 JSVM_Env env; 99 CHECK(OH_JSVM_CreateEnv(vm, sizeof(descriptor) / sizeof(descriptor[0]), descriptor, &env)); 100 JSVM_EnvScope envScope; 101 CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope)); 102 JSVM_HandleScope handlescope; 103 CHECK_RET(OH_JSVM_OpenHandleScope(env, &handlescope)); 104 JSVM_Value sourcecodevalue; 105 CHECK_RET(OH_JSVM_CreateStringUtf8(env, STR_TASK, strlen(STR_TASK), &sourcecodevalue)); 106 JSVM_Script script; 107 CHECK_RET(OH_JSVM_CompileScript(env, sourcecodevalue, nullptr, 0, true, nullptr, &script)); 108 JSVM_Value result; 109 CHECK_RET(OH_JSVM_RunScript(env, script, &result)); 110 bool rst = false; 111 auto start = std::chrono::system_clock::now(); 112 while (true) { 113 // If no task is started in the task queue, set rst to false. 114 CHECK_RET(OH_JSVM_PumpMessageLoop(vm, &rst)); 115 CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm)); 116 // Exit at the scheduled time. 117 auto now = std::chrono::system_clock::now(); 118 auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count(); 119 if (cost > 100) { 120 break; 121 } 122 } 123 124 // Close and destroy the environment and the VM. 125 CHECK_RET(OH_JSVM_CloseHandleScope(env, handlescope)); 126 CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope)); 127 CHECK(OH_JSVM_DestroyEnv(env)); 128 CHECK(OH_JSVM_CloseVMScope(vm, vm_scope)); 129 CHECK(OH_JSVM_DestroyVM(vm)); 130 return 0; 131} 132 133``` 134Expected result: 135``` 136JSVM API TEST: Called with instance [object Object] 137JSVM API TEST: Called Finally 138``` 139### OH_JSVM_SetMicrotaskPolicy 140Call **OH_JSVM_SetMicrotaskPolicy** to set the execution policy for micro tasks. 141 142The execution policy can be any of the following: 143- **JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT**: executes micro tasks after **OH_JSVM_PerformMicrotaskCheckpoint** is called. 144- **JSVM_MicrotaskPolicy::JSVM_MICROTASK_AUTO** (default): executes micro tasks automatically when the JS call stack is empty. 145 146CPP code: 147 148``` 149// Define OH_JSVM_SetMicrotaskPolicy. 150static int SetMicrotaskPolicy(JSVM_VM vm, JSVM_Env env) { 151 // Use the default policy or set the policy to JSVM_MICROTASK_AUTO. 152 const char *scriptEvalMicrotask = R"JS( 153 evaluateMicrotask = false; 154 Promise.resolve().then(()=>{ 155 evaluateMicrotask = true; 156 }); 157 )JS"; 158 JSVM_Script script; 159 JSVM_Value jsSrc; 160 JSVM_Value result; 161 CHECK_RET(OH_JSVM_CreateStringUtf8(env, scriptEvalMicrotask, JSVM_AUTO_LENGTH, &jsSrc)); 162 CHECK_RET(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script)); 163 CHECK_RET(OH_JSVM_RunScript(env, script, &result)); 164 JSVM_Value global; 165 CHECK_RET(OH_JSVM_GetGlobal(env, &global)); 166 JSVM_Value hasEvaluateMicrotask; 167 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask)); 168 bool val; 169 CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val)); 170 171 OH_LOG_INFO(LOG_APP, "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask : %{public}d", val); 172 173 // Set the policy to JSVM_MICROTASK_EXPLICIT. 174 CHECK_RET(OH_JSVM_SetMicrotaskPolicy(vm, JSVM_MicrotaskPolicy::JSVM_MICROTASK_EXPLICIT)); 175 CHECK_RET(OH_JSVM_RunScript(env, script, &result)); 176 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask)); 177 CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val)); 178 OH_LOG_INFO( 179 LOG_APP, 180 "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask before calling OH_JSVM_PerformMicrotaskCheckpoint: %{public}d", 181 val); 182 183 CHECK_RET(OH_JSVM_PerformMicrotaskCheckpoint(vm)); 184 CHECK_RET(OH_JSVM_GetNamedProperty(env, global, "evaluateMicrotask", &hasEvaluateMicrotask)); 185 CHECK_RET(OH_JSVM_GetValueBool(env, hasEvaluateMicrotask, &val)); 186 OH_LOG_INFO( 187 LOG_APP, 188 "Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask after calling OH_JSVM_PerformMicrotaskCheckpoint: %{public}d", 189 val); 190 191 return 0; 192} 193 194static void RunDemo(JSVM_VM vm, JSVM_Env env) { 195 if (SetMicrotaskPolicy(vm, env) != 0) { 196 OH_LOG_INFO(LOG_APP, "Run Microtask Policy failed"); 197 } 198} 199 200static int32_t TestJSVM() { 201 JSVM_InitOptions initOptions = {0}; 202 JSVM_VM vm; 203 JSVM_Env env = nullptr; 204 JSVM_VMScope vmScope; 205 JSVM_EnvScope envScope; 206 JSVM_HandleScope handleScope; 207 JSVM_Value result; 208 // Initialize the JSVM instance. 209 if (g_aa == 0) { 210 g_aa++; 211 CHECK(OH_JSVM_Init(&initOptions)); 212 } 213 // Create a JSVM environment. 214 CHECK(OH_JSVM_CreateVM(nullptr, &vm)); 215 CHECK(OH_JSVM_CreateEnv(vm, 0, nullptr, &env)); 216 CHECK(OH_JSVM_OpenVMScope(vm, &vmScope)); 217 CHECK_RET(OH_JSVM_OpenEnvScope(env, &envScope)); 218 CHECK_RET(OH_JSVM_OpenHandleScope(env, &handleScope)); 219 220 // Call the demo function using the script. 221 RunDemo(vm, env); 222 223 // Destroy the JSVM environment. 224 CHECK_RET(OH_JSVM_CloseHandleScope(env, handleScope)); 225 CHECK_RET(OH_JSVM_CloseEnvScope(env, envScope)); 226 CHECK(OH_JSVM_CloseVMScope(vm, vmScope)); 227 CHECK(OH_JSVM_DestroyEnv(env)); 228 CHECK(OH_JSVM_DestroyVM(vm)); 229 return 0; 230} 231``` 232 233Expected result: 234``` 235Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask : 1 236Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask before calling OH_JSVM_PerformMicrotaskCheckpoint: 0 237Policy :JSVM_MICROTASK_AUTO, evaluateMicrotask after calling OH_JSVM_PerformMicrotaskCheckpoint: 1 238``` 239