boa_engine 0.21.1

Boa is a Javascript lexer, parser and compiler written in Rust. Currently, it has support for some of the language.
Documentation
use std::{rc::Rc, time::Duration};

use crate::{
    Context, JsValue,
    builtins::atomics::Atomics,
    js_string,
    module::IdleModuleLoader,
    object::{JsInt32Array, JsPromise, JsSharedArrayBuffer},
    value::TryFromJs,
};

#[test]
fn waiterlist_block_indexedposition_wake() {
    const NUMAGENT: i32 = 2;
    const RUNNING: i32 = 4;

    let context = &mut Context::builder()
        .can_block(true)
        .module_loader(Rc::new(IdleModuleLoader))
        .build()
        .unwrap();
    let buffer = JsSharedArrayBuffer::new(size_of::<i32>() * 5, context).unwrap();
    let inner_buffer = buffer.inner();
    let i32a = JsInt32Array::from_shared_array_buffer(buffer.clone(), context).unwrap();

    std::thread::scope(|s| {
        let mut threads = Vec::new();
        for idx in [2, 0] {
            let buffer = inner_buffer.clone();
            let handle = s.spawn(move || {
                let context = &mut Context::builder()
                    .can_block(true)
                    .module_loader(Rc::new(IdleModuleLoader))
                    .build()
                    .unwrap();
                let buffer = JsSharedArrayBuffer::from_buffer(buffer, context);
                let i32a = JsInt32Array::from_shared_array_buffer(buffer, context).unwrap();

                Atomics::add(
                    &JsValue::undefined(),
                    &[i32a.clone().into(), RUNNING.into(), 1.into()],
                    context,
                )
                .unwrap();

                let promise = JsPromise::try_from_js(
                    &Atomics::wait::<true>(
                        &JsValue::undefined(),
                        &[
                            i32a.clone().into(),
                            idx.into(),
                            0.into(),
                            f64::INFINITY.into(),
                        ],
                        context,
                    )
                    .unwrap()
                    .as_object()
                    .unwrap()
                    .get(js_string!("value"), context)
                    .unwrap(),
                    context,
                )
                .unwrap();

                assert_eq!(
                    promise
                        .await_blocking(context)
                        .unwrap()
                        .to_string(context)
                        .unwrap()
                        .to_std_string_lossy(),
                    "ok"
                );
            });
            threads.push(handle);
        }

        while Atomics::load(
            &JsValue::undefined(),
            &[i32a.clone().into(), RUNNING.into()],
            context,
        )
        .unwrap()
        .to_i32(context)
        .unwrap()
            != NUMAGENT
        {}

        std::thread::sleep(Duration::from_millis(100));

        assert_eq!(
            Atomics::load(
                &JsValue::undefined(),
                &[i32a.clone().into(), RUNNING.into()],
                context,
            )
            .unwrap()
            .to_i32(context)
            .unwrap(),
            NUMAGENT
        );

        for missing in [1, 3] {
            assert_eq!(
                Atomics::notify(
                    &JsValue::undefined(),
                    &[i32a.clone().into(), missing.into()],
                    context
                )
                .unwrap()
                .to_i32(context)
                .unwrap(),
                0
            );
        }

        for exists in [2, 0] {
            assert_eq!(
                Atomics::notify(
                    &JsValue::undefined(),
                    &[i32a.clone().into(), exists.into()],
                    context
                )
                .unwrap()
                .to_i32(context)
                .unwrap(),
                1
            );
        }
    });
}