jsbind/
prelude.rs

1pub use emlite::Console;
2pub use emlite::FromVal;
3
4pub use crate::any::{Any, AnyHandle};
5pub use crate::array::{
6    Array, ArrayBuffer, DataView, Endian, Float32Array, Float64Array, FrozenArray, Int8Array,
7    Int32Array, ObservableArray, TypedArray, Uint8Array, Uint32Array,
8};
9pub use crate::date::Date;
10pub use crate::error::*;
11pub use crate::function::{Closure, Function};
12pub use crate::json::JSON;
13pub use crate::map::*;
14pub use crate::math::Math;
15pub use crate::null::Null;
16pub use crate::object::Object;
17pub use crate::promise::Promise;
18pub use crate::record::Record;
19pub use crate::reflect::Reflect;
20pub use crate::response::{fetch, fetch_val};
21pub use crate::sequence::Sequence;
22pub use crate::set::*;
23pub use crate::string::{ByteString, CSSOMString, DOMString, USVString};
24pub use crate::text::{TextDecoder, TextEncoder};
25pub use crate::time::*;
26pub use crate::undefined::Undefined;
27pub use crate::url::URL;
28
29/// Parse `src` with an optional `radix`.  Mirrors `parseInt(str, radix)`.
30pub fn parse_int(src: &str, radix: Option<i32>) -> i32 {
31    let g = emlite::Val::global("parseInt");
32    match radix {
33        Some(r) => g.invoke(&[src.into(), r.into()]).as_::<i32>(),
34        None => g.invoke(&[src.into()]).as_::<i32>(),
35    }
36}
37
38/// Parse a floating-point value – identical to JS `parseFloat(str)`.
39pub fn parse_float(src: &str) -> f64 {
40    emlite::Val::global("parseFloat")
41        .invoke(&[src.into()])
42        .as_::<f64>()
43}
44
45/// Trait analogous to `wasm-bindgen::JsCast`.
46///
47/// Automatically available on every wrapper that is:
48/// * holds a single `emlite::Val`
49/// * implements `AsRef<Val>` and `Into<Val>`
50pub trait DynCast
51where
52    Self: AsRef<emlite::Val> + Into<emlite::Val>,
53{
54    fn has_type<T>(&self) -> bool
55    where
56        T: DynCast,
57    {
58        T::is_type_of(self.as_ref())
59    }
60
61    fn dyn_into<T>(self) -> Result<T, Self>
62    where
63        T: DynCast,
64    {
65        if self.has_type::<T>() {
66            Ok(self.unchecked_into())
67        } else {
68            Err(self)
69        }
70    }
71
72    fn dyn_ref<T>(&self) -> Option<&T>
73    where
74        T: DynCast,
75    {
76        if self.has_type::<T>() {
77            Some(self.unchecked_ref())
78        } else {
79            None
80        }
81    }
82
83    fn unchecked_into<T>(self) -> T
84    where
85        T: DynCast,
86    {
87        T::unchecked_from_val(self.into())
88    }
89
90    fn unchecked_ref<T>(&self) -> &T
91    where
92        T: DynCast,
93    {
94        T::unchecked_from_val_ref(self.as_ref())
95    }
96
97    fn is_instance_of<T>(&self) -> bool
98    where
99        T: DynCast,
100    {
101        T::instanceof(self.as_ref())
102    }
103
104    /// Implementation of `val instanceof ThisType`.
105    fn instanceof(val: &emlite::Val) -> bool;
106
107    /// Customisable brand check – defaults to `instanceof`.
108    fn is_type_of(val: &emlite::Val) -> bool {
109        Self::instanceof(val)
110    }
111
112    /// Zero-cost unchecked conversion from `Val` into `Self`.
113    fn unchecked_from_val(v: emlite::Val) -> Self;
114
115    /// Zero-cost unchecked conversion from `&Val` into `&Self`.
116    fn unchecked_from_val_ref(v: &emlite::Val) -> &Self;
117}
118
119/// Throws a JS exception.
120#[cold]
121#[inline(never)]
122pub fn throw_str(s: &str) -> ! {
123    throw_val(s.into())
124}
125
126/// Throws a JS exception
127#[cold]
128#[inline(never)]
129pub fn throw_val(s: Any) -> ! {
130    unsafe {
131        let handle = s.as_handle();
132        core::mem::forget(s);
133        emlite::env::emlite_val_throw(handle)
134    }
135}
136
137// Implementations copied from wasm-bindgen
138pub trait UnwrapThrowExt<T>: Sized {
139    fn unwrap_throw(self) -> T {
140        let loc = core::panic::Location::caller();
141        let msg = alloc::format!(
142            "called `{}::unwrap_throw()` ({}:{}:{})",
143            core::any::type_name::<Self>(),
144            loc.file(),
145            loc.line(),
146            loc.column()
147        );
148        self.expect_throw(&msg)
149    }
150
151    fn expect_throw(self, message: &str) -> T;
152}
153
154// Implementations copied from wasm-bindgen
155impl<T> UnwrapThrowExt<T> for Option<T> {
156    fn unwrap_throw(self) -> T {
157        const MSG: &str = "called `Option::unwrap_throw()` on a `None` value";
158        if let Some(val) = self {
159            val
160        } else if cfg!(debug_assertions) {
161            let loc = core::panic::Location::caller();
162            let msg = alloc::format!("{} ({}:{}:{})", MSG, loc.file(), loc.line(), loc.column(),);
163
164            throw_str(&msg)
165        } else {
166            throw_str(MSG)
167        }
168    }
169
170    fn expect_throw(self, message: &str) -> T {
171        if let Some(val) = self {
172            val
173        } else if cfg!(debug_assertions) {
174            let loc = core::panic::Location::caller();
175            let msg = alloc::format!(
176                "{} ({}:{}:{})",
177                message,
178                loc.file(),
179                loc.line(),
180                loc.column(),
181            );
182
183            throw_str(&msg)
184        } else {
185            throw_str(message)
186        }
187    }
188}
189
190// Implementations copied from wasm-bindgen
191impl<T, E> UnwrapThrowExt<T> for Result<T, E>
192where
193    E: core::fmt::Debug,
194{
195    fn unwrap_throw(self) -> T {
196        const MSG: &str = "called `Result::unwrap_throw()` on an `Err` value";
197        match self {
198            Ok(val) => val,
199            Err(err) => {
200                if cfg!(debug_assertions) {
201                    let loc = core::panic::Location::caller();
202                    let msg = alloc::format!(
203                        "{} ({}:{}:{}): {:?}",
204                        MSG,
205                        loc.file(),
206                        loc.line(),
207                        loc.column(),
208                        err
209                    );
210
211                    throw_str(&msg)
212                } else {
213                    throw_str(MSG)
214                }
215            }
216        }
217    }
218
219    fn expect_throw(self, message: &str) -> T {
220        match self {
221            Ok(val) => val,
222            Err(err) => {
223                if cfg!(debug_assertions) {
224                    let loc = core::panic::Location::caller();
225                    let msg = alloc::format!(
226                        "{} ({}:{}:{}): {:?}",
227                        message,
228                        loc.file(),
229                        loc.line(),
230                        loc.column(),
231                        err
232                    );
233
234                    throw_str(&msg)
235                } else {
236                    throw_str(message)
237                }
238            }
239        }
240    }
241}