rquickjs_core/context/
builder.rs1use std::{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 BigInt JS_AddIntrinsicBigInt,
76 Performance JS_AddPerformance,
78 WeakRef JS_AddIntrinsicWeakRef,
80 }
81
82 pub type None = ();
84
85 pub type All = (
87 Date,
88 Eval,
89 RegExpCompiler,
90 RegExp,
91 Json,
92 Proxy,
93 MapSet,
94 TypedArrays,
95 Promise,
96 BigInt,
97 Performance,
98 WeakRef,
99 );
100}
101
102intrinsic_impls! {
103 @tuple:
104 ,
105 A,
106 A B,
107 A B C,
108 A B C D,
109 A B C D E,
110 A B C D E F,
111 A B C D E F G,
112 A B C D E F G H,
113 A B C D E F G H I,
114 A B C D E F G H I J,
115 A B C D E F G H I J K,
116 A B C D E F G H I J K L,
117 A B C D E F G H I J K L M,
118 A B C D E F G H I J K L M N,
119 A B C D E F G H I J K L M N O,
120 A B C D E F G H I J K L M N O P,
121 A B C D E F G H I J K L M N O P R,
122}
123
124impl Default for ContextBuilder<()> {
125 fn default() -> Self {
126 ContextBuilder(PhantomData)
127 }
128}
129
130impl<I: Intrinsic> ContextBuilder<I> {
131 pub fn with<J: Intrinsic>(self) -> ContextBuilder<(I, J)> {
132 ContextBuilder(PhantomData)
133 }
134
135 pub fn build(self, runtime: &Runtime) -> Result<Context> {
136 Context::custom::<I>(runtime)
137 }
138
139 #[cfg(feature = "futures")]
140 pub async fn build_async(self, runtime: &AsyncRuntime) -> Result<AsyncContext> {
141 AsyncContext::custom::<I>(runtime).await
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn all_intrinsinces() {
151 let rt = crate::Runtime::new().unwrap();
152 let ctx = Context::builder()
153 .with::<intrinsic::All>()
154 .build(&rt)
155 .unwrap();
156 let result: usize = ctx.with(|ctx| ctx.eval("1+1")).unwrap();
157 assert_eq!(result, 2);
158 }
159}