ion/function/
mod.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::any::Any;
8use std::mem::forget;
9use std::thread::Result;
10
11pub use arguments::{Accessor, Arguments, FromArgument};
12pub use closure::{Closure, ClosureOnce};
13pub use function::{Function, NativeFunction};
14use mozjs::conversions::ConversionBehavior;
15
16use crate::conversions::{FromValue, ToValue as _};
17use crate::{Context, Error, Object, ResultExc, ThrowException as _, Value};
18
19mod arguments;
20mod closure;
21mod function;
22
23#[doc(hidden)]
24pub fn __handle_native_function_result(cx: &Context, result: Result<ResultExc<()>>) -> bool {
25	match result {
26		Ok(Ok(_)) => true,
27		Ok(Err(error)) => {
28			error.throw(cx);
29			false
30		}
31		Err(unwind_error) => handle_unwind_error(cx, unwind_error),
32	}
33}
34
35#[doc(hidden)]
36pub fn __handle_native_constructor_result(
37	cx: &Context, result: Result<ResultExc<()>>, this: &Object, rval: &mut Value,
38) -> bool {
39	match result {
40		Ok(Ok(_)) => {
41			this.to_value(cx, rval);
42			true
43		}
44		Ok(Err(error)) => {
45			error.throw(cx);
46			false
47		}
48		Err(unwind_error) => handle_unwind_error(cx, unwind_error),
49	}
50}
51
52fn handle_unwind_error(cx: &Context, unwind_error: Box<dyn Any + Send>) -> bool {
53	match unwind_error.downcast::<String>() {
54		Ok(unwind) => Error::new(*unwind, None).throw(cx),
55		Err(unwind_error) => {
56			if let Some(unwind) = unwind_error.downcast_ref::<&'static str>() {
57				Error::new(*unwind, None).throw(cx);
58			} else {
59				Error::new("Unknown Panic Occurred", None).throw(cx);
60				forget(unwind_error);
61			}
62		}
63	}
64	false
65}
66
67/// Helper type for optional arguments.
68pub struct Opt<T>(pub Option<T>);
69
70/// Helper type for rest/spread/variable arguments.
71pub struct Rest<T>(pub Box<[T]>);
72
73pub type VarArgs<T> = Rest<T>;
74
75/// Helper type for strict arguments.
76pub struct Strict<T>(pub T);
77
78impl<'cx, T: FromValue<'cx>> FromValue<'cx> for Strict<T> {
79	type Config = T::Config;
80
81	fn from_value(cx: &'cx Context, value: &Value, _: bool, config: Self::Config) -> crate::Result<Strict<T>> {
82		T::from_value(cx, value, true, config).map(Strict)
83	}
84}
85
86/// Helper type for integer arguments that wraps.
87#[derive(Clone, Copy, Debug, Default)]
88pub struct Wrap<T>(pub T);
89
90impl<'cx, T: FromValue<'cx, Config = ConversionBehavior>> FromValue<'cx> for Wrap<T> {
91	type Config = ();
92
93	fn from_value(cx: &'cx Context, value: &Value, strict: bool, _: ()) -> crate::Result<Wrap<T>> {
94		T::from_value(cx, value, strict, ConversionBehavior::Default).map(Wrap)
95	}
96}
97
98/// Helper type for integer arguments that enforces the range.
99#[derive(Clone, Copy, Debug, Default)]
100pub struct Enforce<T>(pub T);
101
102impl<'cx, T: FromValue<'cx, Config = ConversionBehavior>> FromValue<'cx> for Enforce<T> {
103	type Config = ();
104
105	fn from_value(cx: &'cx Context, value: &Value, strict: bool, _: ()) -> crate::Result<Enforce<T>> {
106		T::from_value(cx, value, strict, ConversionBehavior::EnforceRange).map(Enforce)
107	}
108}
109
110/// Helper type for integer arguments that clamps.
111#[derive(Clone, Copy, Debug, Default)]
112pub struct Clamp<T>(pub T);
113
114impl<'cx, T: FromValue<'cx, Config = ConversionBehavior>> FromValue<'cx> for Clamp<T> {
115	type Config = ();
116
117	fn from_value(cx: &'cx Context, value: &Value, strict: bool, _: ()) -> crate::Result<Clamp<T>> {
118		T::from_value(cx, value, strict, ConversionBehavior::Clamp).map(Clamp)
119	}
120}