1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use crate::Ctx;
#[cfg(feature = "exports")]
use crate::{Atom, Value};
use rquickjs_sys as qjs;
use std::ffi::c_void;
#[cfg(feature = "exports")]
pub struct ExportList<'js> {
m: Module<'js>,
max: i32,
cur: i32,
}
#[cfg(feature = "exports")]
impl<'js> Iterator for ExportList<'js> {
type Item = (Atom<'js>, Value<'js>);
fn next(&mut self) -> Option<Self::Item> {
if self.cur == self.max {
return None;
}
let ptr = self.m.ptr as *mut qjs::JSModuleDef;
let atom = unsafe {
let atom_val = qjs::JS_GetModuleExportEntryName(self.m.ctx.ctx, ptr, self.cur);
Atom::from_atom_val(self.m.ctx, atom_val)
};
let val = unsafe {
let js_val = qjs::JS_GetModuleExportEntry(self.m.ctx.ctx, ptr, self.cur);
Value::from_js_value(self.m.ctx, js_val).unwrap()
};
self.cur += 1;
Some((atom, val))
}
}
#[derive(Debug, Clone)]
pub struct Module<'js> {
ptr: *mut qjs::JSModuleDef,
ctx: Ctx<'js>,
}
impl<'js> PartialEq<Module<'js>> for Module<'js> {
fn eq(&self, other: &Module<'js>) -> bool {
self.ptr == other.ptr
}
}
impl<'js> Module<'js> {
pub(crate) unsafe fn from_js_value(ctx: Ctx<'js>, js_val: qjs::JSValue) -> Self {
debug_assert_eq!(js_val.tag, qjs::JS_TAG_MODULE as i64);
let ptr = js_val.u.ptr;
Module {
ptr: ptr as *mut qjs::JSModuleDef,
ctx,
}
}
#[allow(dead_code)]
pub(crate) fn as_js_value(&self) -> qjs::JSValue {
qjs::JSValue {
u: qjs::JSValueUnion {
ptr: self.ptr as *mut c_void,
},
tag: qjs::JS_TAG_MODULE as i64,
}
}
pub fn name(&self) -> Atom<'js> {
unsafe { Atom::from_atom_val(self.ctx, qjs::JS_GetModuleName(self.ctx.ctx, self.ptr)) }
}
#[cfg(feature = "exports")]
pub fn export_list(&self) -> ExportList<'js> {
ExportList {
m: self.clone(),
max: unsafe { qjs::JS_GetModuleExportEntriesCount(self.ptr) },
cur: 0,
}
}
#[doc(hidden)]
#[cfg(feature = "exports")]
pub unsafe fn dump_exports(&self) {
let ptr = self.ptr;
let count = qjs::JS_GetModuleExportEntriesCount(ptr);
for i in 0..count {
let atom_name = Atom::from_atom_val(
self.ctx,
qjs::JS_GetModuleExportEntryName(self.ctx.ctx, ptr, i),
);
println!("{}", atom_name.to_string().unwrap());
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::*;
#[test]
fn from_javascript() {
let rt = Runtime::new().unwrap();
let ctx = Context::full(&rt).unwrap();
ctx.with(|ctx| {
let val: Module = ctx
.compile(
"Test",
r#"
export var a = 2;
export function foo(){ return "bar"}
export class Baz{
quel = 3;
constructor(){
}
}
"#,
)
.unwrap();
assert_eq!(val.name().to_string().unwrap(), "Test".to_string());
let mut iter = val.export_list();
assert_eq!(iter.next().unwrap().0.to_string().unwrap(), "a".to_string());
assert_eq!(
iter.next().unwrap().0.to_string().unwrap(),
"foo".to_string()
);
assert_eq!(
iter.next().unwrap().0.to_string().unwrap(),
"Baz".to_string()
);
});
}
}