quickjs-emscripten
quickjs-emscripten copied to clipboard
Issue with getting a result from an async function call
Hey,
first of all - thanks for this great library.
Now - I'm having slight issues with getting a result from an async function call.
Full code example below (I took https://github.com/justjake/quickjs-emscripten#promises as a reference example).
I tried to write proper comments in the code, but to sum-up
- I'm creating an instance of the QJS context
- I'm evaluating the script with the definition of the "handle" function - a function that is than supposed to be called many times with different params
- I'm calling the "handle" function
- the "handle" is being logged in the console
- The "Result1" is being logged in the console
- The "Result2" (i.e. the result from "handle" function call) is NEVER logged in the console..
The full result from the console is:
❯ node tools/quickjs.mjs
QuickJS: handle
Result1
It works fine when the handle
is not defined as async
.
Now - am I'm doing here sth wrong - or is such usecase simply not yet supported by the library?
import {getQuickJS} from 'quickjs-emscripten';
// the example smart contract code loaded from Arweave blockchain
const code = `
(() => {
async function handle(state, action) {
// this is being logged
console.log('handle');
return 1;
}
return handle;
})();
`.trim();
async function main() {
// 1. creating the QJS context
const QuickJS = await getQuickJS();
const vm = QuickJS.newContext();
// 2. registering "console.log" API
const logHandle = vm.newFunction("log", (...args) => {
const nativeArgs = args.map(vm.dump)
console.log("QuickJS:", ...nativeArgs)
});
const consoleHandle = vm.newObject();
vm.setProp(consoleHandle, "log", logHandle);
vm.setProp(vm.global, "console", consoleHandle);
consoleHandle.dispose();
logHandle.dispose();
// 3. registering the "handle" function in a global scope
const handle = vm.evalCode(code);
vm.setProp(vm.global, 'handle', handle.value);
// 4. calling the "handle" function
const result = vm.evalCode(`(async () => {
return await handle();
})()`);
// execute pending jobs - is it necessary here?
vm.runtime.executePendingJobs();
if (result.error) {
console.log('Execution failed:', vm.dump(result.error));
result.error.dispose();
} else {
const promiseHandle = vm.unwrapResult(result)
// the below is being logged
console.log("Result1");
const resolvedResult = await vm.resolvePromise(promiseHandle)
promiseHandle.dispose();
const resolvedHandle = vm.unwrapResult(resolvedResult);
// the below is NEVER logged
console.log("Result2:", vm.getNumber(resolvedHandle));
}
vm.dispose();
}
main().finally();
Perhaps we need executePendingJobs after resolvePromise?
Perhaps we need executePendingJobs after resolvePromise?
I've missed your answer. Unfortunatelly this didn't help.. :-(
I've also tried sth stupid like:
const code = `
async function handle(state, action) {
// this is being logged
console.log('handle');
return 1;
}
`.trim();
const executePendingJobsHandle = vm.newFunction("epj", (...args) => {
console.log("inside executePendingJobsHandle");
vm.runtime.executePendingJobs();
});
const consoleHandle = vm.newObject();
vm.setProp(consoleHandle, "log", logHandle);
vm.setProp(consoleHandle, "epj", executePendingJobsHandle);
vm.setProp(vm.global, "console", consoleHandle);
consoleHandle.dispose();
logHandle.dispose();
executePendingJobsHandle.dispose();
const result = vm.evalCode(`(async () => {
${code}
return handle().then(() => {
console.log('inside then');
console.epj();
});
})()`);
if (result.error) {
console.log('Execution failed:', vm.dump(result.error));
result.error.dispose();
} else {
const promiseHandle = vm.unwrapResult(result);
// the below is being logged
console.log("Result1");
vm.runtime.executePendingJobs();
const resolvedResult = await vm.resolvePromise(promiseHandle)
promiseHandle.dispose();
const resolvedHandle = vm.unwrapResult(resolvedResult);
vm.runtime.executePendingJobs();
// the below is NEVER logged
console.log("Result2:", vm.getNumber(resolvedHandle));
}
It is logging:
QuickJS: handle
Result1
QuickJS: inside then
inside executePendingJobsHandle
I suppose it only works with promises created via vm.newPromise()
?