1/** 2 * Copyright (c) 2021-2025 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 16let testSuccess = false; 17// resolver: (value) => {} 18let resolver = undefined; 19 20let PROMISE_RESOLVE_VALUE = 'JS_PROMISE_RESULT'; 21 22// let LOG_LEVEL = 5 23let LOG_LEVEL = 1; 24let FATAL = 0; 25let ERROR = 1; 26let INFO = 2; 27function msg(s, lvl) { 28 if (LOG_LEVEL >= lvl) { 29 print(s); 30 } 31} 32 33const helper = requireNapiPreview('libinterop_test_helper.so', false); 34 35function init() { 36 const gtestAbcPath = helper.getEnvironmentVar('ARK_ETS_INTEROP_JS_GTEST_ABC_PATH'); 37 const stdlibPath = helper.getEnvironmentVar('ARK_ETS_STDLIB_PATH'); 38 39 let etsVm = requireNapiPreview('ets_interop_js_napi.so', false); 40 const etsOpts = { 41 'panda-files': gtestAbcPath, 42 'boot-panda-files': `${stdlibPath}:${gtestAbcPath}`, 43 'gc-trigger-type': 'heap-trigger', 44 'load-runtimes': 'ets', 45 'compiler-enable-jit': 'false', 46 'run-gc-in-place': 'true', 47 'coroutine-impl': 'stackful', 48 'xgc-trigger-type': 'never' 49 // 'log-debug': 'coroutines' 50 }; 51 const createRes = etsVm.createRuntime(etsOpts); 52 if (!createRes) { 53 throw Error('Cannot create ETS runtime'); 54 } 55 return etsVm; 56} 57 58async function doAwait(pr) { 59 msg('Await func: start', INFO); 60 let value = await pr; 61 msg('Await func: await returned: ' + value, INFO); 62 if (value === 'Panda') { 63 testSuccess = true; 64 msg('Await func: value from await is correct!', INFO); 65 } 66 msg('Await func: end', INFO); 67} 68 69function createPendingPromise() { 70 let p = new Promise((res, rej) => { 71 resolver = res; 72 }); 73 return p; 74} 75 76function createResolvedPromise() { 77 let p = new Promise((res, rej) => { 78 res(PROMISE_RESOLVE_VALUE); 79 }); 80 return p; 81} 82 83function runAwaitTest(name, promiseCreator, promiseResolver) { 84 msg('Running test ' + name, INFO); 85 let etsVm = init(); 86 let promise = promiseCreator(); 87 // similar to async JS function call. Returns a Promise instance 88 let packageName = ''; 89 if (helper.getEnvironmentVar('PACKAGE_NAME')) { 90 packageName = helper.getEnvironmentVar('PACKAGE_NAME') + '/'; 91 } else { 92 throw Error('PACKAGE_NAME not set'); 93 } 94 const testAwaitJsPromise = etsVm.getFunction('L' + packageName + 'ETSGLOBAL;', 'testAwaitJsPromise'); 95 let res = testAwaitJsPromise(promise); 96 msg('Called testAwaitJsPromise OK, result:', INFO); 97 msg(res, INFO); 98 if (typeof res !== 'object') { 99 throw Error('Result is not an object'); 100 } 101 if (res.constructor.name !== 'Promise') { 102 throw Error("Expect result type 'Promise' but get '" + res.constructor.name + "'"); 103 } 104 let anotherRes = doAwait(res); 105 msg('Called doAwait OK, res: ', INFO); 106 msg(anotherRes, INFO); 107 setTimeout(() => { 108 if (testSuccess) { 109 throw Error('Promise must not be resolved until JS resolves the passed one'); 110 } 111 // resolve the passed promise if necessary 112 promiseResolver(PROMISE_RESOLVE_VALUE); 113 // after Q is processed, the test should pass 114 setTimeout(async () => { 115 msg('Starting await of doAwait() result, its state is:', INFO); 116 msg(anotherRes, INFO); 117 await anotherRes; 118 if (!testSuccess) { 119 throw Error('Promise is not resolved or value is wrong'); 120 } else { 121 msg('Test PASSED', INFO); 122 } 123 }, 0); 124 }, 0); 125} 126 127function runAwaitPendingTest() { 128 runAwaitTest('AwaitPendingTest', createPendingPromise, (v) => { 129 resolver(v); 130 }); 131} 132 133function runAwaitResolvedTest() { 134 runAwaitTest('AwaitResolvedTest', createResolvedPromise, (v) => {}); 135} 136 137function runTest(test) { 138 if (test === 'pending') { 139 runAwaitPendingTest(); 140 } else if (test === 'resolved') { 141 runAwaitResolvedTest(); 142 } else { 143 throw Error('No such test'); 144 } 145} 146 147let args = helper.getArgv(); 148if (args.length !== 6) { 149 throw Error('Expected test name'); 150} 151runTest(args[5]); 152