rquickjs_core/context/
builder.rs1use core::{marker::PhantomData, ptr::NonNull};
2
3#[cfg(feature = "futures")]
4use crate::{context::AsyncContext, runtime::AsyncRuntime};
5use crate::{qjs, util::Sealed, Context, Result, Runtime};
6
7pub trait Intrinsic: Sealed {
9 unsafe fn add_intrinsic(ctx: NonNull<qjs::JSContext>);
12}
13
14pub struct ContextBuilder<I>(PhantomData<I>);
16
17macro_rules! intrinsic_impls {
18 (@builtin: $($(#[$meta:meta])* $name:ident $func:ident $(($($args:expr),*))*,)*) => {
19 $(
20 $(#[$meta])*
21 pub struct $name;
22 impl crate::util::Sealed for $name { }
23
24 impl Intrinsic for $name {
25 unsafe fn add_intrinsic(ctx: NonNull<qjs::JSContext>) {
26 qjs::$func(ctx.as_ptr() $(, $($args),*)*);
27 }
28 }
29 )*
30 };
31
32 (@tuple: $($($name:ident)*,)*) => {
33 $(
34 impl<$($name,)*> crate::util::Sealed for ($($name,)*) { }
35
36 impl<$($name,)*> Intrinsic for ($($name,)*)
37 where
38 $($name: Intrinsic,)*
39 {
40 unsafe fn add_intrinsic(_ctx: NonNull<qjs::JSContext>) {
41 $($name::add_intrinsic(_ctx);)*
42 }
43 }
44 )*
45 }
46}
47
48pub mod intrinsic {
52 use super::{qjs, Intrinsic, NonNull};
53
54 intrinsic_impls! {
55 @builtin:
56 Date JS_AddIntrinsicDate,
58 Eval JS_AddIntrinsicEval,
60 RegExpCompiler JS_AddIntrinsicRegExpCompiler,
62 RegExp JS_AddIntrinsicRegExp,
64 Json JS_AddIntrinsicJSON,
66 Proxy JS_AddIntrinsicProxy,
68 MapSet JS_AddIntrinsicMapSet,
70 TypedArrays JS_AddIntrinsicTypedArrays,
72 Promise JS_AddIntrinsicPromise,
74 Performance JS_AddPerformance,
76 WeakRef JS_AddIntrinsicWeakRef,
78 }
79
80 pub type None = ();
82
83 pub type All = (
85 Date,
86 Eval,
87 RegExpCompiler,
88 RegExp,
89 Json,
90 Proxy,
91 MapSet,
92 TypedArrays,
93 Promise,
94 Performance,
95 WeakRef,
96 );
97}
98
99intrinsic_impls! {
100 @tuple:
101 ,
102 A,
103 A B,
104 A B C,
105 A B C D,
106 A B C D E,
107 A B C D E F,
108 A B C D E F G,
109 A B C D E F G H,
110 A B C D E F G H I,
111 A B C D E F G H I J,
112 A B C D E F G H I J K,
113 A B C D E F G H I J K L,
114 A B C D E F G H I J K L M,
115 A B C D E F G H I J K L M N,
116 A B C D E F G H I J K L M N O,
117 A B C D E F G H I J K L M N O P,
118 A B C D E F G H I J K L M N O P R,
119}
120
121impl Default for ContextBuilder<()> {
122 fn default() -> Self {
123 ContextBuilder(PhantomData)
124 }
125}
126
127impl<I: Intrinsic> ContextBuilder<I> {
128 pub fn with<J: Intrinsic>(self) -> ContextBuilder<(I, J)> {
129 ContextBuilder(PhantomData)
130 }
131
132 pub fn build(self, runtime: &Runtime) -> Result<Context> {
133 Context::custom::<I>(runtime)
134 }
135
136 #[cfg(feature = "futures")]
137 pub async fn build_async(self, runtime: &AsyncRuntime) -> Result<AsyncContext> {
138 AsyncContext::custom::<I>(runtime).await
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[test]
147 fn all_intrinsinces() {
148 let rt = crate::Runtime::new().unwrap();
149 let ctx = Context::builder()
150 .with::<intrinsic::All>()
151 .build(&rt)
152 .unwrap();
153 let result: usize = ctx.with(|ctx| ctx.eval("1+1")).unwrap();
154 assert_eq!(result, 2);
155 }
156}