1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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")
}
}
}