quickjs-rusty icon indicating copy to clipboard operation
quickjs-rusty copied to clipboard

Implement timeout feature

Open Gioppix opened this issue 7 months ago • 0 comments

As per this issue in the old repo.

I tested the solution and it works (the example evaluates a list of expressions given an Object as global):

pub fn execute_js_isolated_new(
    input_data: Value,
    js_code: &[String],
) -> Result<Vec<ExecutionResult>, String> {
    let context = Context::builder()
        .memory_limit(1024 * 1024)
        .build()
        .unwrap();

    context
        .set_global(
            "input",
            to_js(unsafe { context.context_raw() }, &input_data).unwrap(),
        )
        .unwrap();

    let timeout = Box::new(SystemTime::now() + Duration::from_millis(TIMEOUT_MS));
    let ptr = Box::into_raw(timeout);

    extern "C" fn timeout_interrupt(
        _rt: *mut q::JSRuntime,
        opaque: *mut std::ffi::c_void,
    ) -> ::std::os::raw::c_int {
        let ts: SystemTime = unsafe { std::ptr::read(opaque as *const SystemTime) };
        if SystemTime::now().gt(&ts) { 1 } else { 0 }
    }

    let runtime = unsafe { q::JS_GetRuntime(context.context_raw()) };

    unsafe {
        q::JS_SetInterruptHandler(
            runtime,
            Some(timeout_interrupt),
            ptr as *mut std::ffi::c_void,
        );
    }

    let mut values = Vec::new();
    for s in js_code {
        let maybe_eval_res = context.eval(
            &format!(
                r#"
                        let __result;
                        try {{
                            __result = {{ success: {} }};
                        }} catch (e) {{
                            __result = {{ error: e.toString() }};
                        }}

                        JSON.stringify(__result);
                    "#,
                s
            ),
            true,
        );

        let final_val = match maybe_eval_res {
            Ok(r) => {
                let result_str = r.to_string().map_err(|e| e.to_string())?;
                serde_json::from_str(&result_str).map_err(|e| e.to_string())?
            }
            Err(e) => ExecutionResult::Error(e.to_string()),
        };

        values.push(final_val);
    }

    Ok(values)
}

Gioppix avatar May 08 '25 11:05 Gioppix