[quickjs-devel] Re: Suspending and Resuming the VM

  • From: Atif Ali <atif@xxxxxxxxxxxxx>
  • To: quickjs-devel@xxxxxxxxxxxxx
  • Date: Wed, 1 Jul 2020 19:22:41 -0400

Thanks for your reply Chris.

I looked into those 3 options as per your suggestion, but it turns out they
won't work for my use case:

1. Asyncify: this looked to be the most promising initially. However, this
technique requires that you compile in the async'ed functions in the
QuickJS code itself. But these async functions are not at the VM-level,
they are at the user-script level. This would mean that I would have to
know all the JS sandboxed API that needs to be async'ed before-hand, and
detect right before execution in the VM that API in order to redirect
towards the async'ed version. It brings the userland API into the VM. I
would have gone this route but the issue here is that I need to inject
different API for different contexts (the API is dependent on runtime
user-defined and external-systems-defined variables itself). So this is
kind of a no-go.

2. The next option was to turn all JS API return promises. However, this
would unnecessarily really complicate the end-user experience (for example,
imagine if you had to write in Excel the formula "await sum(E1,E2)" instead
of "sum(E1,E2)" ... and it gets really weird with nested/chained functions.

I should mention that I also tried just parsing the user code with acorn
and augmenting awaits. However, things become weird because of JS' dynamic
nature. For example, it is easy to augment `this.someFunc()` to become
`await this.someFunc()` but how do you reliably detect `this["someFunc"]()`
or worse `this[someCalculatedVar]()`.

3. SharedArrayBuffer was the last promising thing. But it's inability to
run in anything except Chrome right now is a no go.

I did find another JS interpreter, aptly named JS-Interpreter, that has the
suspend functionality that I was looking for. See
https://neil.fraser.name/software/JS-Interpreter/ and more specifically the
end goal I wished to achieve in
https://neil.fraser.name/software/JS-Interpreter/docs.html ;(search page for
"Asynchronous API functions"). But QuickJS is more stable and I would
switch back instantly if there was a way for the VM itself to
suspend/resume its execution of its interpreter itself.



On Sat, Jun 27, 2020 at 5:55 PM Chris Cowan <agentme49@xxxxxxxxx> wrote:

WebAssembly in web browsers doesn't provide a direct way to suspend with
an active stack.

I think there's several possible strategies you can do:

A. You can use Emscripten's asyncify feature to rewrite the entire
WebAssembly binary so that it can be suspended and resumed during function
calls. This can impact performance throughout the whole thing though.
https://emscripten.org/docs/porting/asyncify.html

B. Make it so any JS functions running in quickjs that need to do an async
operation are also async, and make the getter functions in quickjs return
promises. This strategy has the benefit of making the cost of the operation
more obvious, and allows the sandboxed code to do other things in the
meantime.

C. If you're comfortable with depending on SharedArrayBuffer (which is
currently not supported in some browsers like Firefox while they figure out
spectre mitigations), then you can use it to accomplish synchronous message
passing to a web worker. This will allow you to communicate with the host
page within a synchronous function call.


On Thu, Jun 25, 2020, 2:47 PM Atif Ali <atif@xxxxxxxxxxxxx> wrote:

I am using QuickJS compiled to webassembly inside a web page to allow for
user-defined scripts.

Specifically, I have been defining the props so that I lazily add data
into the VM as needed by the code. This works great, however, if I am to
run the VM inside a web worker, then the getter/functions needs to work
asynchronously (i.e. return promises -- not desired as user code will be
laden with async/awaits then).

I am wondering if there is a way to suspend / pause the VM so that when a
getter is called? Then, I can pause the VM, go fetch the value
asynchronously from the main thread, then resume the VM once I have the
value in the web worker.

I suspect the suspend/pause functionality will also be really helpful for
adding debugging capabilities later.

- Atif



-- 



Atif Ali
*CEO, President*
*Apployees Inc.*

p: +1-613-262-2556
w: www.apployees.com
e: atif@xxxxxxxxxxxxx
<https://www.facebook.com/Apployees/>
<https://twitter.com/i/notifications>
<https://www.linkedin.com/company/apployees/>

Other related posts: