1pub mod env;
2use crate::env::*;
3use std::ffi::CStr;
4
5#[macro_export]
7macro_rules! eval {
8 ($src: literal) => {{
9 $crate::Val::global("eval").invoke(&[$crate::Val::from_str($src)])
10 }};
11 ($src: literal $(, $arg:expr)* $(,)?) => {{
12 $crate::Val::global("eval").invoke(
13 &[$crate::Val::from_str(&format!($src, $( $arg ),*)) ]
14 )
15 }};
16}
17
18#[macro_export]
20macro_rules! argv {
21 ($($rest:expr),*) => {{
22 [$($crate::Val::from($rest)),*]
23 }};
24}
25
26#[derive(Debug)]
28pub struct Val {
29 inner: Handle,
30}
31
32impl Val {
33 pub fn take_ownership(handle: Handle) -> Val {
35 Val {
36 inner: handle,
37 }
38 }
39
40 pub fn from_val(v: Val) -> Self {
42 unsafe {
43 emlite_val_inc_ref(v.inner);
44 }
45 Val {
46 inner: v.inner,
47 }
48 }
49
50 pub fn global_this() -> Val {
52 Val::take_ownership(unsafe { emlite_val_global_this() })
53 }
54
55 pub fn get<T: Into<Val>>(&self, prop: T) -> Val {
57 let h = unsafe { emlite_val_get(self.as_handle(), prop.into().as_handle()) };
58 Val::take_ownership(h)
59 }
60
61 pub fn global(name: &str) -> Val {
63 Val::global_this().get(name)
64 }
65
66 pub fn null() -> Val {
68 Val::take_ownership(unsafe { emlite_val_null() })
69 }
70
71 pub fn undefined() -> Val {
73 Val::take_ownership(unsafe { emlite_val_undefined() })
74 }
75
76 pub fn object() -> Val {
78 Val::take_ownership(unsafe { emlite_val_new_object() })
79 }
80
81 pub fn array() -> Val {
83 Val::take_ownership(unsafe { emlite_val_new_array() })
84 }
85
86 pub fn from_i32(i: i32) -> Val {
88 Val::take_ownership(unsafe { emlite_val_make_int(i) })
89 }
90
91 pub fn from_f64(f: f64) -> Val {
93 Val::take_ownership(unsafe { emlite_val_make_double(f) })
94 }
95
96 #[allow(clippy::should_implement_trait)]
98 pub fn from_str(s: &str) -> Val {
99 Val::take_ownership(unsafe { emlite_val_make_str(s.as_ptr() as _, s.len()) })
100 }
101
102 #[inline(always)]
104 pub fn as_handle(&self) -> Handle {
105 self.inner
106 }
107
108 pub fn set<K: Into<Val>, V: Into<Val>>(&self, prop: K, val: V) {
110 unsafe {
111 emlite_val_set(
112 self.as_handle(),
113 prop.into().as_handle(),
114 val.into().as_handle(),
115 )
116 };
117 }
118
119 pub fn has<T: Into<Val>>(&self, prop: T) -> bool {
121 unsafe { emlite_val_has(self.as_handle(), prop.into().as_handle()) }
122 }
123
124 pub fn has_own_property(&self, prop: &str) -> bool {
126 unsafe { emlite_val_obj_has_own_prop(self.as_handle(), prop.as_ptr() as _, prop.len()) }
127 }
128
129 pub fn type_of(&self) -> String {
131 unsafe {
132 let ptr = emlite_val_typeof(self.as_handle());
133 String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string()
134 }
135 }
136
137 pub fn at<T: Into<Val>>(&self, idx: T) -> Val {
139 Val::take_ownership(unsafe { emlite_val_get(self.as_handle(), idx.into().as_handle()) })
140 }
141
142 pub fn as_i32(&self) -> i32 {
144 unsafe { emlite_val_get_value_int(self.as_handle()) as i32 }
145 }
146
147 pub fn as_bool(&self) -> bool {
149 self.as_handle() > 3
150 }
151
152 pub fn as_f64(&self) -> f64 {
154 unsafe { emlite_val_get_value_double(self.as_handle()) as _ }
155 }
156
157 pub fn as_string(&self) -> String {
159 unsafe {
160 let ptr = emlite_val_get_value_string(self.as_handle());
161 String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).to_string()
162 }
163 }
164
165 pub fn to_vec_i32(&self) -> Vec<i32> {
167 let len = self.get("length").as_i32();
168 let mut v: Vec<i32> = vec![];
169 for i in 0..len {
170 v.push(self.at::<i32>(i as _).as_i32());
171 }
172 v
173 }
174
175 pub fn to_vec_f64(&self) -> Vec<f64> {
177 let len = self.get("length").as_i32();
178 let mut v: Vec<f64> = vec![];
179 for i in 0..len {
180 v.push(self.at::<f64>(i as _).as_f64());
181 }
182 v
183 }
184
185 pub fn call(&self, f: &str, args: &[Val]) -> Val {
187 unsafe {
188 let arr = Val::take_ownership(emlite_val_new_array());
189 for arg in args {
190 emlite_val_push(arr.as_handle(), arg.as_handle());
191 }
192 Val::take_ownership(emlite_val_obj_call(
193 self.as_handle(),
194 f.as_ptr() as _,
195 f.len(),
196 arr.as_handle(),
197 ))
198 }
199 }
200
201 pub fn new(&self, args: &[Val]) -> Val {
203 unsafe {
204 let arr = Val::take_ownership(emlite_val_new_array());
205 for arg in args {
206 emlite_val_push(arr.as_handle(), arg.as_handle());
207 }
208 Val::take_ownership(emlite_val_construct_new(self.as_handle(), arr.as_handle()))
209 }
210 }
211
212 pub fn invoke(&self, args: &[Val]) -> Val {
214 unsafe {
215 let arr = Val::take_ownership(emlite_val_new_array());
216 for arg in args {
217 emlite_val_push(arr.as_handle(), arg.as_handle());
218 }
219 Val::take_ownership(emlite_val_func_call(self.as_handle(), arr.as_handle()))
220 }
221 }
222
223 pub fn make_fn_raw(f: fn(Handle, Handle) -> Handle, data: Handle) -> Val {
225 let idx: u32 = f as usize as u32;
226 unsafe { Val::take_ownership(emlite_val_make_callback(idx, data)) }
227 }
228
229 pub fn make_fn<F: FnMut(&[Val]) -> Val>(cb: F) -> Val {
231 fn shim(args: Handle, data: Handle) -> Handle {
232 let v = Val::take_ownership(args);
233 let sz = v.get("length").as_i32() as usize;
234 let mut vals: Vec<Val> = Vec::with_capacity(sz);
235 for i in 0..sz {
236 vals.push(v.at(i as i32));
237 }
238 let func0 = Val::take_ownership(data);
239 let a = func0.as_i32() as usize as *mut Box<dyn FnMut(&[Val]) -> Val>;
240 let f: &mut (dyn FnMut(&[Val]) -> Val) = unsafe { &mut **a };
241 std::mem::forget(func0);
242 f(&vals).as_handle()
243 }
244 let a: *mut Box<dyn FnMut(&[Val]) -> Val> = Box::into_raw(Box::new(Box::new(cb)));
245 let data = Val::from_i32(a as Handle as _);
246 unsafe {
247 emlite_val_inc_ref(data.as_handle());
248 }
249 Self::make_fn_raw(shim, data.as_handle())
250 }
251
252 pub fn await_(&self) -> Val {
254 eval!(
255 r#"
256 (async () => {{
257 let obj = EMLITE_VALMAP.toValue({});
258 let ret = await obj;
259 return EMLITE_VALMAP.toHandle(ret);
260 }})()
261 "#,
262 self.as_handle()
263 )
264 }
265
266 pub fn delete(v: Val) {
268 unsafe {
269 emlite_val_dec_ref(v.as_handle());
270 }
271 }
272
273 pub fn throw(v: Val) {
275 unsafe {
276 emlite_val_throw(v.as_handle());
277 }
278 }
279
280 pub fn instanceof(&self, v: Val) -> bool {
282 unsafe { emlite_val_instanceof(self.as_handle(), v.as_handle()) }
283 }
284}
285
286impl From<i32> for Val {
287 fn from(v: i32) -> Self {
288 Val::from_i32(v)
289 }
290}
291
292impl From<f64> for Val {
293 fn from(v: f64) -> Self {
294 Val::from_f64(v)
295 }
296}
297
298impl From<()> for Val {
299 fn from(_: ()) -> Self {
300 Val::undefined()
301 }
302}
303
304impl From<&str> for Val {
305 fn from(item: &str) -> Self {
306 Val::from_str(item)
307 }
308}
309
310impl From<String> for Val {
311 fn from(item: String) -> Self {
312 Val::from_str(&item)
313 }
314}
315
316impl Drop for Val {
317 fn drop(&mut self) {
318 unsafe { emlite_val_dec_ref(self.as_handle()) }
319 }
320}
321
322impl Clone for Val {
323 fn clone(&self) -> Val {
324 unsafe { emlite_val_inc_ref(self.as_handle()); }
325 Val::take_ownership(self.as_handle())
326 }
327}
328
329use std::ops::{Deref, DerefMut};
330
331#[derive(Clone, Debug)]
333pub struct Console {
334 val: Val,
335}
336
337impl Console {
338 pub fn get() -> Console {
340 Console {
341 val: Val::global("console"),
342 }
343 }
344
345 pub fn log(&self, args: &[Val]) {
347 self.val.call("log", args);
348 }
349
350 pub fn warn(&self, args: &[Val]) {
352 self.val.call("warn", args);
353 }
354
355 pub fn info(&self, args: &[Val]) {
357 self.val.call("info", args);
358 }
359
360 pub fn as_handle(&self) -> Handle {
362 self.val.as_handle()
363 }
364}
365
366impl Deref for Console {
367 type Target = Val;
368
369 fn deref(&self) -> &Self::Target {
370 &self.val
371 }
372}
373
374impl DerefMut for Console {
375 fn deref_mut(&mut self) -> &mut Self::Target {
376 &mut self.val
377 }
378}
379
380impl Into<Val> for Console {
381 fn into(self) -> Val {
382 Val::take_ownership(self.inner)
383 }
384}
385
386use std::cmp::Ordering;
387use std::ops::Not;
388
389impl PartialEq for Val {
390 fn eq(&self, other: &Val) -> bool {
391 unsafe { emlite_val_strictly_equals(self.as_handle(), other.as_handle()) }
392 }
393}
394
395impl PartialOrd for Val {
396 fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
397 unsafe {
398 if emlite_val_strictly_equals(self.as_handle(), other.as_handle()) {
399 Some(Ordering::Equal)
400 } else if emlite_val_gt(self.as_handle(), other.as_handle()) {
401 Some(Ordering::Greater)
402 } else if emlite_val_lt(self.as_handle(), other.as_handle()) {
403 Some(Ordering::Less)
404 } else {
405 None
406 }
407 }
408 }
409}
410
411impl Not for Val {
412 type Output = bool;
413
414 fn not(self) -> Self::Output {
415 unsafe { emlite_val_not(self.as_handle()) }
416 }
417}