1pub mod env;
2use crate::env::*;
3use std::ffi::CStr;
4
5#[repr(u32)]
6pub enum EmlitePredefHandles {
7 Null = 0,
8 Undefined,
9 False,
10 True,
11 GlobalThis,
12 Console,
13 Reserved,
14}
15
16#[macro_export]
18macro_rules! eval {
19 ($src: literal) => {{
20 $crate::Val::global("eval").invoke(&[$crate::Val::from($src)])
21 }};
22 ($src: literal $(, $arg:expr)* $(,)?) => {{
23 $crate::Val::global("eval").invoke(
24 &[$crate::Val::from(&format!($src, $( $arg ),*)) ]
25 )
26 }};
27}
28
29#[macro_export]
31macro_rules! argv {
32 ($($rest:expr),*) => {{
33 [$($crate::Val::from($rest)),*]
34 }};
35}
36
37#[derive(Debug)]
39pub struct Val {
40 inner: Handle,
41}
42
43impl Val {
44 pub const fn global_this() -> Val {
46 Val { inner: EmlitePredefHandles::GlobalThis as _ }
47 }
48
49 pub fn get<T: Into<Val>>(&self, prop: T) -> Val {
51 let h = unsafe { emlite_val_get(self.as_handle(), prop.into().as_handle()) };
52 Val::take_ownership(h)
53 }
54
55 pub fn global(name: &str) -> Val {
57 Val::global_this().get(name)
58 }
59
60 pub const fn null() -> Val {
62 Val { inner: EmlitePredefHandles::Null as _ }
63 }
64
65 pub const fn undefined() -> Val {
67 Val { inner: EmlitePredefHandles::Undefined as _ }
68 }
69
70 pub fn object() -> Val {
72 Val::take_ownership(unsafe { emlite_val_new_object() })
73 }
74
75 pub fn array() -> Val {
77 Val::take_ownership(unsafe { emlite_val_new_array() })
78 }
79
80 pub fn set<K: Into<Val>, V: Into<Val>>(&self, prop: K, val: V) {
82 unsafe {
83 emlite_val_set(
84 self.as_handle(),
85 prop.into().as_handle(),
86 val.into().as_handle(),
87 )
88 };
89 }
90
91 pub fn has<T: Into<Val>>(&self, prop: T) -> bool {
93 unsafe { emlite_val_has(self.as_handle(), prop.into().as_handle()) }
94 }
95
96 pub fn has_own_property(&self, prop: &str) -> bool {
98 unsafe { emlite_val_obj_has_own_prop(self.as_handle(), prop.as_ptr() as _, prop.len()) }
99 }
100
101 pub fn type_of(&self) -> String {
103 unsafe {
104 let ptr = emlite_val_typeof(self.as_handle());
105 String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string()
106 }
107 }
108
109 pub fn at<T: Into<Val>>(&self, idx: T) -> Val {
111 Val::take_ownership(unsafe { emlite_val_get(self.as_handle(), idx.into().as_handle()) })
112 }
113
114 pub fn to_vec<V: FromVal>(&self) -> Vec<V> {
116 let len = self.get("length").as_::<usize>();
117 let mut v: Vec<V> = Vec::with_capacity(len);
118 for i in 0..len {
119 v.push(self.at::<i32>(i as _).as_::<V>());
120 }
121 v
122 }
123
124 pub fn call(&self, f: &str, args: &[Val]) -> Val {
126 unsafe {
127 let arr = Val::take_ownership(emlite_val_new_array());
128 for arg in args {
129 emlite_val_push(arr.as_handle(), arg.as_handle());
130 }
131 Val::take_ownership(emlite_val_obj_call(
132 self.as_handle(),
133 f.as_ptr() as _,
134 f.len(),
135 arr.as_handle(),
136 ))
137 }
138 }
139
140 pub fn new(&self, args: &[Val]) -> Val {
142 unsafe {
143 let arr = Val::take_ownership(emlite_val_new_array());
144 for arg in args {
145 emlite_val_push(arr.as_handle(), arg.as_handle());
146 }
147 Val::take_ownership(emlite_val_construct_new(self.as_handle(), arr.as_handle()))
148 }
149 }
150
151 pub fn invoke(&self, args: &[Val]) -> Val {
153 unsafe {
154 let arr = Val::take_ownership(emlite_val_new_array());
155 for arg in args {
156 emlite_val_push(arr.as_handle(), arg.as_handle());
157 }
158 Val::take_ownership(emlite_val_func_call(self.as_handle(), arr.as_handle()))
159 }
160 }
161
162 pub fn make_fn_raw(f: fn(Handle, Handle) -> Handle, data: Handle) -> Val {
164 let idx: u32 = f as usize as u32;
165 unsafe { Val::take_ownership(emlite_val_make_callback(idx, data)) }
166 }
167
168 pub fn make_fn<F: FnMut(&[Val]) -> Val>(cb: F) -> Val {
170 fn shim(args: Handle, data: Handle) -> Handle {
171 let v = Val::take_ownership(args);
172 let vals: Vec<Val> = v.to_vec();
173 let func0 = Val::take_ownership(data);
174 let a = func0.as_::<i32>() as usize as *mut Box<dyn FnMut(&[Val]) -> Val>;
175 let f: &mut (dyn FnMut(&[Val]) -> Val) = unsafe { &mut **a };
176 std::mem::forget(func0);
177 f(&vals).as_handle()
178 }
179 #[allow(clippy::type_complexity)]
180 let a: *mut Box<dyn FnMut(&[Val]) -> Val> = Box::into_raw(Box::new(Box::new(cb)));
181 let data = Val::from(a as Handle);
182 unsafe {
183 emlite_val_inc_ref(data.as_handle());
184 }
185 Self::make_fn_raw(shim, data.as_handle())
186 }
187
188 pub fn await_(&self) -> Val {
190 eval!(
191 r#"
192 (async () => {{
193 let obj = EMLITE_VALMAP.toValue({});
194 let ret = await obj;
195 return EMLITE_VALMAP.toHandle(ret);
196 }})()
197 "#,
198 self.as_handle()
199 )
200 }
201
202 pub fn delete(v: Val) {
204 unsafe {
205 emlite_val_dec_ref(v.as_handle());
206 }
207 }
208
209 pub fn throw(v: Val) {
211 unsafe {
212 emlite_val_throw(v.as_handle());
213 }
214 }
215
216 pub fn instanceof(&self, v: Val) -> bool {
218 unsafe { emlite_val_instanceof(self.as_handle(), v.as_handle()) }
219 }
220
221 #[inline(always)]
222 pub fn as_<T>(&self) -> T
223 where
224 T: FromVal,
225 {
226 T::from_val(self)
227 }
228}
229
230impl From<bool> for Val {
231 fn from(v: bool) -> Self {
232 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
233 }
234}
235
236impl From<i8> for Val {
237 fn from(v: i8) -> Self {
238 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
239 }
240}
241
242impl From<u8> for Val {
243 fn from(v: u8) -> Self {
244 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
245 }
246}
247
248impl From<i16> for Val {
249 fn from(v: i16) -> Self {
250 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
251 }
252}
253
254impl From<u16> for Val {
255 fn from(v: u16) -> Self {
256 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
257 }
258}
259
260impl From<i32> for Val {
261 fn from(v: i32) -> Self {
262 Val::take_ownership(unsafe { emlite_val_make_int(v) })
263 }
264}
265
266impl From<u32> for Val {
267 fn from(v: u32) -> Self {
268 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
269 }
270}
271
272impl From<i64> for Val {
273 fn from(v: i64) -> Self {
274 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
275 }
276}
277
278impl From<u64> for Val {
279 fn from(v: u64) -> Self {
280 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
281 }
282}
283
284impl From<usize> for Val {
285 fn from(v: usize) -> Self {
286 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
287 }
288}
289
290impl From<isize> for Val {
291 fn from(v: isize) -> Self {
292 Val::take_ownership(unsafe { emlite_val_make_int(v as _) })
293 }
294}
295
296impl From<f32> for Val {
297 fn from(v: f32) -> Self {
298 Val::take_ownership(unsafe { emlite_val_make_double(v as _) })
299 }
300}
301
302impl From<f64> for Val {
303 fn from(v: f64) -> Self {
304 Val::take_ownership(unsafe { emlite_val_make_double(v) })
305 }
306}
307
308impl From<()> for Val {
309 fn from(_: ()) -> Self {
310 Val::undefined()
311 }
312}
313
314impl From<&str> for Val {
315 fn from(s: &str) -> Self {
316 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
317 }
318}
319
320impl From<String> for Val {
321 fn from(s: String) -> Self {
322 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
323 }
324}
325
326impl From<&String> for Val {
327 fn from(s: &String) -> Self {
328 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
329 }
330}
331
332impl Drop for Val {
333 fn drop(&mut self) {
334 unsafe { emlite_val_dec_ref(self.as_handle()) }
335 }
336}
337
338impl Clone for Val {
339 fn clone(&self) -> Val {
340 unsafe {
341 emlite_val_inc_ref(self.as_handle());
342 }
343 Val::take_ownership(self.as_handle())
344 }
345}
346
347use std::ops::{Deref, DerefMut};
348
349#[derive(Clone, Debug)]
351pub struct Console {
352 val: Val,
353}
354
355impl Console {
356 pub const fn get() -> Console {
358 Console {
359 val: Val {
360 inner: EmlitePredefHandles::Console as _,
361 },
362 }
363 }
364
365 pub fn log(&self, args: &[Val]) {
367 self.val.call("log", args);
368 }
369
370 pub fn warn(&self, args: &[Val]) {
372 self.val.call("warn", args);
373 }
374
375 pub fn info(&self, args: &[Val]) {
377 self.val.call("info", args);
378 }
379
380 pub fn as_handle(&self) -> Handle {
382 self.val.as_handle()
383 }
384}
385
386impl Deref for Console {
387 type Target = Val;
388
389 fn deref(&self) -> &Self::Target {
390 &self.val
391 }
392}
393
394impl DerefMut for Console {
395 fn deref_mut(&mut self) -> &mut Self::Target {
396 &mut self.val
397 }
398}
399
400impl From<Console> for Val {
401 fn from(val: Console) -> Self {
402 Val::take_ownership(val.inner)
403 }
404}
405
406use std::cmp::Ordering;
407use std::ops::Not;
408
409impl PartialEq for Val {
410 fn eq(&self, other: &Val) -> bool {
411 unsafe { emlite_val_strictly_equals(self.as_handle(), other.as_handle()) }
412 }
413}
414
415impl PartialOrd for Val {
416 fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
417 unsafe {
418 if emlite_val_strictly_equals(self.as_handle(), other.as_handle()) {
419 Some(Ordering::Equal)
420 } else if emlite_val_gt(self.as_handle(), other.as_handle()) {
421 Some(Ordering::Greater)
422 } else if emlite_val_lt(self.as_handle(), other.as_handle()) {
423 Some(Ordering::Less)
424 } else {
425 None
426 }
427 }
428 }
429}
430
431impl Not for Val {
432 type Output = bool;
433
434 fn not(self) -> Self::Output {
435 unsafe { emlite_val_not(self.as_handle()) }
436 }
437}
438
439pub trait FromVal: Sized {
440 fn from_val(v: &Val) -> Self;
442 fn take_ownership(v: Handle) -> Self;
444 fn as_handle(&self) -> Handle;
446}
447
448impl FromVal for Val {
449 fn from_val(v: &Val) -> Self {
450 unsafe {
451 emlite_val_inc_ref(v.inner);
452 }
453 Val {
454 inner: v.as_handle(),
455 }
456 }
457 fn take_ownership(v: Handle) -> Self {
458 Val { inner: v }
459 }
460 #[inline(always)]
461 fn as_handle(&self) -> Handle {
462 self.inner
463 }
464}
465
466impl FromVal for bool {
467 fn from_val(v: &Val) -> Self {
468 v.as_handle() > EmlitePredefHandles::False as u32
469 }
470 fn take_ownership(v: Handle) -> Self {
471 Self::from_val(&Val::take_ownership(v))
472 }
473 fn as_handle(&self) -> Handle {
474 EmlitePredefHandles::False as u32
475 }
476}
477
478macro_rules! impl_int {
479 ($($t:ty),*) => {$(
480 impl FromVal for $t {
481 fn from_val(v: &Val) -> Self {
482 unsafe {
483 emlite_val_get_value_int(v.as_handle()) as Self
484 }
485 }
486 fn take_ownership(v: Handle) -> Self {
487 unsafe { emlite_val_get_value_int(v) as Self }
488 }
489 fn as_handle(&self) -> Handle {
490 0
491 }
492 }
493 )*}
494}
495
496impl_int!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
497
498macro_rules! impl_float {
499 ($($t:ty),*) => {$(
500 impl FromVal for $t {
501 fn from_val(v: &Val) -> Self {
502 unsafe { emlite_val_get_value_double(v.as_handle()) as Self }
503 }
504 fn take_ownership(v: Handle) -> Self {
505 unsafe { emlite_val_get_value_double(v) as Self }
506 }
507 fn as_handle(&self) -> Handle {
508 0
509 }
510 }
511 )*}
512}
513
514impl_float!(f32, f64);
515
516impl FromVal for String {
517 fn from_val(v: &Val) -> Self {
518 unsafe {
519 let ptr = emlite_val_get_value_string(v.as_handle());
520 CStr::from_ptr(ptr).to_string_lossy().into_owned()
521 }
522 }
523 fn take_ownership(v: Handle) -> Self {
524 unsafe {
525 let ptr = emlite_val_get_value_string(v);
526 CStr::from_ptr(ptr).to_string_lossy().into_owned()
527 }
528 }
529 fn as_handle(&self) -> Handle {
530 0
531 }
532}
533
534
535impl FromVal for &str {
536 fn from_val(v: &Val) -> Self {
537 unsafe {
538 let ptr = emlite_val_get_value_string(v.as_handle());
539 CStr::from_ptr(ptr).to_str().unwrap()
540 }
541 }
542 fn take_ownership(v: Handle) -> Self {
543 unsafe {
544 let ptr = emlite_val_get_value_string(v);
545 CStr::from_ptr(ptr).to_str().unwrap()
546 }
547 }
548 fn as_handle(&self) -> Handle {
549 0
550 }
551}