[Question/Bug] Closing a popup won't stop its running scripts

I have a popup to confirm if the user wants to download a report. When it’s confirmed, the button calls a script to do the job. It works fine, but if the user decides to cancel it, e.g. it’s taking too long, even if they close the popup, the code keeps running. So, I cancel the popup and seconds later the file is downloaded normally.
Shouldn’t it cancel the execution?
Or is there a way to check if the popup is still open so I can abort the execution via code?

Well, it's not documented to cancel it, so I would say no. The running script basically holds a reference to the component it started from (via the event object) that prevents the popup from being destroyed, even if no longer visible. Consider not running slow tasks in event routines -- use system.util.invokeAsynchronous to run them in the background.

To clarify - is this a popup in Perspective, or Vision?
If the former - then you’ll have an ever harder time than Phil already explained - because scripting in Perspective is by necessity asynchronous from the actual browser/UI layer.

It is in Perspective.

Coming back to this - currently, there's no way to know whether a popup is open or closed at the time of script execution. We're planning to add more functions to allow for dynamic things like this, but there's still an inherent timing issue in Perspective - scripts execute on the gateway, so there will always be some amount of latency between UI changes from the user and scripts actually firing.

So far we haven't had any critical issues with this, the only problem is that if the user tries to cancel the processing, he will receive the file anyways.
Since the event object has a property "cancelable", shouldn't it be the case?

{"type":"click","eventPhase":3,"bubbles":true,"cancelable":true,"timeStamp":595558.5000000428,"defaultPrevented":false,"isTrusted":true,"detail":1,"screenX":584,"screenY":510,"clientX":217,"clientY":432,"pageX":217,"pageY":432,"ctrlKey":false,"shiftKey":false,"altKey":false,"metaKey":false,"button":0,"buttons":0,"movementX":0,"movementY":0}

The cancelable property is a (doubly-read-only) reflection of the cancelable property of the JS Event interface. It’s read only at the actual JS level, and it’s copied directly into the Python wrapper we put around the event object when actually sending it to your scripts.

It doesn’t really help with what you’re trying to do here.