rong_jscore 0.4.0

JavaScriptCore backend for RongJS
use crate::{JSCContext, JSCValue, jsc};
use rong_core::{JSEngine, JSRuntimeImpl};

pub struct JSCRuntime {
    raw: *const jsc::OpaqueJSContextGroup,
}

impl JSRuntimeImpl for JSCRuntime {
    type RawRuntime = *const jsc::OpaqueJSContextGroup;
    type Context = JSCContext;

    fn new() -> Self {
        // On the source/JSCOnly backend, force JSC's one-time global init before
        // the first JSC API call. `JSContextGroupCreate` is the earliest VM touch
        // (earlier than `JSCContext::new`), so the guard belongs here. Idempotent
        // and thread-safe; a no-op on the system framework, which runs this from
        // the dylib's static initializers.
        #[cfg(jsc_source)]
        jsc::ensure_initialized();
        Self {
            raw: unsafe { jsc::JSContextGroupCreate() },
        }
    }

    fn to_raw(&self) -> Self::RawRuntime {
        self.raw
    }

    // JavaScriptCore  GC works on Conext level, not runtime
    fn run_gc(&self) {}
}

impl Drop for JSCRuntime {
    fn drop(&mut self) {
        unsafe {
            jsc::JSContextGroupRelease(self.raw);
        }
    }
}

pub struct JavaScriptCore;

impl JSEngine for JavaScriptCore {
    type Value = JSCValue;
    type Context = JSCContext;
    type Runtime = JSCRuntime;

    fn name() -> &'static str {
        // Distinguish the source-built JSCOnly backend from the system
        // JavaScriptCore.framework so the active engine is identifiable at runtime.
        #[cfg(jsc_source)]
        {
            "JavaScriptCore (source)"
        }
        #[cfg(not(jsc_source))]
        {
            "JavaScriptCore"
        }
    }

    fn version() -> String {
        #[cfg(jsc_source)]
        {
            String::from("JSCOnly (source build)")
        }
        #[cfg(not(jsc_source))]
        {
            String::from("system framework")
        }
    }
}