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