PetterS / quickjs

Thin Python wrapper of https://bellard.org/quickjs/
https://github.com/bellard/QuickJS
MIT License
177 stars 19 forks source link

Fix #66: Fetch and store Python exceptions while in JS code #67

Closed qwenger closed 2 years ago

qwenger commented 2 years ago

Fix #63, fix #66.

In contrast to JS, Python exceptions are global. So to support the case where an exception is raised in an asynchronous segment, one needs to store away the exception and unset the error indicator.

This stored exception can then be raised if it is returned on the JS side, or as part of a HostPromiseRejectionTracker.

Note: that mechanism is also needed to properly handle nested Python -> JS -> Python -> JS -> Python cases:

import quickjs
ctx = quickjs.Context()

def testa():
    ctx.eval("testb()")

def testb():
    raise Exception

ctx.add_callable("testa", testa)
ctx.add_callable("testb", testb)
ctx.eval("testa()")

This also supersedes #64.

PetterS commented 2 years ago

Thanks for this patch! Let me see if I have time to review it this weekend....

(I no longer work on this small library as part of my day-to-day work)

In the meantime, could you also add. a unit test demonstrating the bug?

qwenger commented 2 years ago

I added a unit test.

Please note that this PR and #65 step on each other's toes, so once you merge one of them (assuming you do :) ) I'll update the other one to make it mergeable.

Also, I'm a little bit rusty when it comes to the C-API, so my implementation may be a bit lacking stylistically - suggestions for improvement are welcome.

Once both PRs are merged, I'll probably submit a PR for implementing a host promise rejection tracker.

qwenger commented 2 years ago

Are you able to run the check_memory script to check whether all of the reference counting is correct?

I'm not really sure about what to look for in the memory logs...

qwenger commented 2 years ago

Ok. Now I've more or less understood how check_memory.py works and I have proposed a couple enhancements (#75, #76, #78).

I also agree that the current implementation based on the error string is not ideal. Furthermore, saving the error globally in the context does not seem good either. Better would be - if doable - to encapsulate the Python error in the JS error, using a new JS error type (a subclass of InternalError?).

I'll rework this PR once the other ones (#65 plus the aforementioned ones about memory leaks) are integrated.

PetterS commented 2 years ago

Sounds good! Thanks for the improvements to the memory script.

qwenger commented 2 years ago

Superseded by #79 .