• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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