use crate::{qjs, Context, Result, Runtime};
use std::marker::PhantomData;
pub trait Intrinsic {
unsafe fn add_intrinsic(ctx: *mut qjs::JSContext);
}
pub struct ContextBuilder<I>(PhantomData<I>);
macro_rules! intrinsic_impls {
(@builtin: $($(#[$meta:meta])* $name:ident $func:ident $(($($args:expr),*))*,)*) => {
$(
$(#[$meta])*
pub struct $name;
impl Intrinsic for $name {
unsafe fn add_intrinsic(ctx: *mut qjs::JSContext) {
qjs::$func(ctx $(, $($args),*)*);
}
}
)*
};
(@tuple: $($($name:ident)*,)*) => {
$(
impl<$($name,)*> Intrinsic for ($($name,)*)
where
$($name: Intrinsic,)*
{
unsafe fn add_intrinsic(_ctx: *mut qjs::JSContext) {
$($name::add_intrinsic(_ctx);)*
}
}
)*
}
}
pub mod intrinsic {
use super::{qjs, Intrinsic};
intrinsic_impls! {
@builtin:
BaseObjects JS_AddIntrinsicBaseObjects,
Date JS_AddIntrinsicDate,
Eval JS_AddIntrinsicEval,
StringNormalize JS_AddIntrinsicStringNormalize,
RegExpCompiler JS_AddIntrinsicRegExpCompiler,
RegExp JS_AddIntrinsicRegExp,
Json JS_AddIntrinsicJSON,
Proxy JS_AddIntrinsicProxy,
MapSet JS_AddIntrinsicMapSet,
TypedArrays JS_AddIntrinsicTypedArrays,
Promise JS_AddIntrinsicPromise,
BigInt JS_AddIntrinsicBigInt,
BigFloat JS_AddIntrinsicBigFloat,
BigDecimal JS_AddIntrinsicBigDecimal,
Operators JS_AddIntrinsicOperators,
BignumExt JS_EnableBignumExt (1),
}
pub type Base = BaseObjects;
pub type None = ();
pub type All = (
Base,
Date,
Eval,
StringNormalize,
RegExpCompiler,
RegExp,
Json,
Proxy,
MapSet,
TypedArrays,
Promise,
BigInt,
BigFloat,
BigDecimal,
Operators,
BignumExt,
);
}
intrinsic_impls! {
@tuple:
,
A,
A B,
A B C,
A B C D,
A B C D E,
A B C D E F,
A B C D E F G,
A B C D E F G H,
A B C D E F G H I,
A B C D E F G H I J,
A B C D E F G H I J K,
A B C D E F G H I J K L,
A B C D E F G H I J K L M,
A B C D E F G H I J K L M N,
A B C D E F G H I J K L M N O,
A B C D E F G H I J K L M N O P,
A B C D E F G H I J K L M N O P R,
}
impl Default for ContextBuilder<()> {
fn default() -> Self {
ContextBuilder(PhantomData)
}
}
impl<I: Intrinsic> ContextBuilder<I> {
pub fn with<J: Intrinsic>(self) -> ContextBuilder<(I, J)> {
ContextBuilder(PhantomData)
}
pub fn build(self, runtime: &Runtime) -> Result<Context> {
Context::custom::<I>(runtime)
}
}