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