1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "demo_javascript_class.h" 17 18#include "napi/native_api.h" 19#include "napi/native_node_api.h" 20 21/* 22 * Sync callback 23 */ 24static napi_value Add(napi_env env, napi_callback_info info) 25{ 26 size_t requireArgc = 2; 27 size_t argc = 2; 28 napi_value args[2] = { nullptr }; 29 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); 30 31 NAPI_ASSERT(env, argc >= requireArgc, "Wrong number of arguments"); 32 33 napi_valuetype valuetype0; 34 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); 35 36 napi_valuetype valuetype1; 37 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); 38 39 NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected."); 40 41 double value0; 42 NAPI_CALL(env, napi_get_value_double(env, args[0], &value0)); 43 44 double value1; 45 NAPI_CALL(env, napi_get_value_double(env, args[1], &value1)); 46 47 napi_value sum; 48 NAPI_CALL(env, napi_create_double(env, value0 + value1, &sum)); 49 50 return sum; 51} 52 53struct AsyncCallbackInfo { 54 napi_async_work asyncWork = nullptr; 55 napi_deferred deferred = nullptr; 56 napi_ref callback[2] = { 0 }; 57}; 58 59/** 60 * Promise 61 */ 62static napi_value TestPromise(napi_env env, napi_callback_info) 63{ 64 napi_deferred deferred = nullptr; 65 napi_value promise = nullptr; 66 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); 67 68 auto asyncCallbackInfo = new AsyncCallbackInfo { 69 .asyncWork = nullptr, 70 .deferred = deferred, 71 }; 72 73 napi_value resourceName = nullptr; 74 napi_create_string_latin1(env, "TestPromise", NAPI_AUTO_LENGTH, &resourceName); 75 napi_create_async_work( 76 env, nullptr, resourceName, [](napi_env env, void* data) {}, 77 [](napi_env env, napi_status status, void* data) { 78 AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data; 79 napi_value result = nullptr; 80 napi_create_string_utf8(env, "TestPromise", NAPI_AUTO_LENGTH, &result); 81 napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); 82 napi_delete_async_work(env, asyncCallbackInfo->asyncWork); 83 delete asyncCallbackInfo; 84 }, 85 (void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork); 86 napi_queue_async_work(env, asyncCallbackInfo->asyncWork); 87 return promise; 88} 89 90/* 91 * Promise or async callback 92 */ 93void NapiCreateAsyncWork(napi_env env, napi_value resourceName, AsyncCallbackInfo* asyncCallbackInfo) 94{ 95 napi_create_async_work( 96 env, nullptr, resourceName, [](napi_env env, void* data) {}, 97 [](napi_env env, napi_status status, void* data) { 98 AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data; 99 100 napi_value callback = nullptr; 101 napi_value undefined = nullptr; 102 napi_value result = nullptr; 103 napi_value callbackResult = nullptr; 104 napi_create_string_utf8(env, "TestPromiseOrAsyncCallback", NAPI_AUTO_LENGTH, &result); 105 napi_get_undefined(env, &undefined); 106 107 if (true) { 108 napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback); 109 napi_call_function(env, undefined, callback, 1, &result, &callbackResult); 110 } else { 111 if (asyncCallbackInfo->callback[1]) { 112 napi_get_reference_value(env, asyncCallbackInfo->callback[1], &callback); 113 napi_call_function(env, undefined, callback, 1, &result, &callbackResult); 114 } else { 115 napi_throw_error(env, "error", "foo"); 116 } 117 } 118 119 if (asyncCallbackInfo->callback[0] != nullptr) { 120 napi_delete_reference(env, asyncCallbackInfo->callback[0]); 121 } 122 if (asyncCallbackInfo->callback[1] != nullptr) { 123 napi_delete_reference(env, asyncCallbackInfo->callback[1]); 124 } 125 napi_delete_async_work(env, asyncCallbackInfo->asyncWork); 126 delete asyncCallbackInfo; 127 }, 128 (void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork); 129} 130 131static napi_value TestPromiseOrAsyncCallback(napi_env env, napi_callback_info info) 132{ 133 size_t argc = 2; 134 napi_value args[2] = { 0 }; 135 napi_value thisArg = nullptr; 136 void* data = nullptr; 137 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, &data)); 138 139 auto asyncCallbackInfo = new AsyncCallbackInfo { 140 .asyncWork = nullptr, 141 .deferred = nullptr, 142 }; 143 144 if (argc != 0) { 145 napi_value resourceName = nullptr; 146 napi_create_string_latin1(env, "TestPromiseOrAsyncCallback1", NAPI_AUTO_LENGTH, &resourceName); 147 148 for (size_t i = 0; i < argc; i++) { 149 napi_valuetype valuetype = napi_undefined; 150 NAPI_CALL(env, napi_typeof(env, args[i], &valuetype)); 151 NAPI_ASSERT(env, valuetype == napi_function, "Wrong argument type. Function expected."); 152 napi_create_reference(env, args[i], 1, &asyncCallbackInfo->callback[i]); 153 } 154 155 NapiCreateAsyncWork(env, resourceName, asyncCallbackInfo); 156 NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork)); 157 return nullptr; 158 } else { 159 napi_value resourceName = nullptr; 160 napi_create_string_latin1(env, "TestPromiseOrAsyncCallback2", NAPI_AUTO_LENGTH, &resourceName); 161 napi_deferred deferred = nullptr; 162 napi_value promise = nullptr; 163 NAPI_CALL(env, napi_create_promise(env, &deferred, &promise)); 164 asyncCallbackInfo->deferred = deferred; 165 166 napi_create_async_work( 167 env, nullptr, resourceName, [](napi_env env, void* data) {}, 168 [](napi_env env, napi_status status, void* data) { 169 AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data; 170 171 napi_value result = nullptr; 172 napi_create_string_utf8(env, "TestPromiseOrAsyncCallback", NAPI_AUTO_LENGTH, &result); 173 if (true) { 174 napi_resolve_deferred(env, asyncCallbackInfo->deferred, result); 175 } else { 176 napi_reject_deferred(env, asyncCallbackInfo->deferred, result); 177 } 178 179 napi_delete_async_work(env, asyncCallbackInfo->asyncWork); 180 delete asyncCallbackInfo; 181 }, 182 (void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork); 183 napi_queue_async_work(env, asyncCallbackInfo->asyncWork); 184 return promise; 185 } 186} 187 188EXTERN_C_START 189/* 190 * function for module exports 191 */ 192static napi_value Init(napi_env env, napi_value exports) 193{ 194 /* 195 * Properties define 196 */ 197 napi_property_descriptor desc[] = { 198 DECLARE_NAPI_FUNCTION("add", Add), 199 DECLARE_NAPI_FUNCTION("TestPromise", TestPromise), 200 DECLARE_NAPI_FUNCTION("TestPromiseOrAsyncCallback", TestPromiseOrAsyncCallback), 201 }; 202 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); 203 204 DemoJavascriptClassInit(env, exports); 205 206 return exports; 207} 208EXTERN_C_END 209 210/* 211 * Module define 212 */ 213static napi_module demoModule = { 214 .nm_version = 1, 215 .nm_flags = 0, 216 .nm_filename = nullptr, 217 .nm_register_func = Init, 218 .nm_modname = "demo", 219 .nm_priv = ((void*)0), 220 .reserved = { 0 }, 221}; 222/* 223 * Module register function 224 */ 225extern "C" __attribute__((constructor)) void RegisterModule(void) 226{ 227 napi_module_register(&demoModule); 228} 229