Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Cancellable or interruptible setTimeout in javy #650

Open
redoC-A2k opened this issue May 25, 2024 · 5 comments
Open

Implement Cancellable or interruptible setTimeout in javy #650

redoC-A2k opened this issue May 25, 2024 · 5 comments
Labels
question Further information is requested

Comments

@redoC-A2k
Copy link

How can I implement Implement Cancellable or interruptible timeout in javy ?
I am right now polyfilling setTimeout like below -

fn set_timeout_api() -> impl FnMut(&JSContextRef, JSValueRef, &[JSValueRef]) -> Result<JSValue> {
    move |context: &JSContextRef, _this: JSValueRef, args: &[JSValueRef]| {
        let callback = args.get(0).unwrap();
        let default = to_qjs_value(context, &JSValue::Int(0)).unwrap();
        let timeout = args.get(1).unwrap_or(&default);
        thread::sleep(Duration::from_millis(
            timeout
                .as_f64()
                .expect("Unable to convert timeout to milliseconds") as u64,
        ));
        println!("timeout reached");
        if callback.is_function() {
            let mut argsvec: Vec<JSValueRef> = vec![];
            if args.len() > 2 {
                for i in 2..args.len() {
                    argsvec.push(args.get(i).unwrap().to_owned())
                }
            }
            let res = callback.call(
                &to_qjs_value(context.to_owned(), &JSValue::Undefined).unwrap(),
                &argsvec,
            );
        }
        Ok(JSValue::Undefined)
    }
}

But it is not cancellable it will only be cleared after timeout .

@redoC-A2k redoC-A2k added the question Further information is requested label May 25, 2024
@redoC-A2k
Copy link
Author

Please could you guys help ?

@saulecabrera
Copy link
Member

According to the setTimeout API, order to make the timeout cancellable, you'd need to use the clearTimeout API. So, roughly, you'd need to return an id from your implementation that can be later passed to clearTimeout. Have you tried this approach? Or is it something different what you're trying to achieve?

Regarding the snippet above, it's also worth noting that there's still work to be done when it comes to Wasm atomics/threads.

@jeffcharles
Copy link
Collaborator

You may want to consider using a different implementation than thread::sleep. thread::sleep will block the JS event queue which will make canceling it from within JS impossible. You could have something on the host side cancel it.

@redoC-A2k
Copy link
Author

redoC-A2k commented May 27, 2024

@jeffcharles I was considering exposing a async function from host to guest ... but again wrap_callback takes a synchronous closure as argument , so I won't be able to call that async function asynchronously from guest wasm in setTimeout polyfill method .
Could you please tell me more what I should do ? Or suggest me some alternatives .... I am fine with any implementation for polyfilling setTimeout , all I want is it to be cancellable .

@jeffcharles
Copy link
Collaborator

You could take a look at how QuickJS implemented setTimeout in https://github.com/bellard/quickjs/blob/d378a9f3a583cb787c390456e27276d0ee377d23/quickjs-libc.c#L2034. You can see they have a recurring check for each timer in a poll function that's run inside of a loop to see if any timers have expired in https://github.com/bellard/quickjs/blob/d378a9f3a583cb787c390456e27276d0ee377d23/quickjs-libc.c#L2326.

We've also switched off of quickjs-wasm-rs and on to rquickjs in #618 for Javy. So it may be worth investigating if there's an API in rquickjs like Ctx.spawn that you can use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants