Skip to content

Commit b449af9

Browse files
working on promises/modules/eventqueue
1 parent 9453575 commit b449af9

9 files changed

+137
-10
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ categories = ["development-tools"]
1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1515

1616
[dependencies]
17-
quick-js = "0.3.3"
17+
#quick-js = "0.3.3"
18+
quick-js = {path = "../quickjs-rs"}
1819
lazy_static = "1.4.0"
1920
log = "0.4.11"
2021
simple-logging = "2.0.2"

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
# quick_es_runtime
1+
# quick_es_runtime
2+
3+
Same goals as es_runtime but with using quickjs
4+
5+
so
6+
* slower js
7+
* smaller footprint
8+
* much faster compilation
9+

src/esruntime.rs

+90-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::esscript::EsScript;
44
use crate::quickjsruntime::QuickJsRuntime;
55
use quick_js::{ExecutionError, JsValue};
66
use std::sync::Arc;
7+
use log::error;
78

89
pub struct EsRuntime {
910
event_queue: Arc<EsEventQueue>,
@@ -38,9 +39,19 @@ impl EsRuntime {
3839

3940
pub fn gc_sync() {}
4041

41-
pub fn load_module() {}
42+
pub fn eval_module(&self, script: EsScript) {
43+
self.add_to_event_queue(|qjs_rt| {
44+
let res = qjs_rt.eval_module(script);
45+
match res {
46+
Ok(_) => {}
47+
Err(e) => log::error!("error in async eval {}", e),
48+
}
49+
});
50+
}
4251

43-
pub fn load_module_sync() {}
52+
pub fn eval_module_sync(&self, script: EsScript) -> Result<JsValue, ExecutionError> {
53+
self.add_to_event_queue_sync(|qjs_rt| qjs_rt.eval_module(script))
54+
}
4455

4556
pub fn new_class_builder() {}
4657

@@ -50,27 +61,49 @@ impl EsRuntime {
5061
{
5162
self.event_queue
5263
.add_task(|| QuickJsRuntime::do_with(consumer));
64+
self._add_job_run_task();
5365
}
5466

5567
pub fn add_to_event_queue_sync<C, R>(&self, consumer: C) -> R
5668
where
5769
C: FnOnce(&QuickJsRuntime) -> R + Send + 'static,
5870
R: Send + 'static,
5971
{
60-
self.event_queue
61-
.exe_task(|| QuickJsRuntime::do_with(consumer))
72+
let res = self.event_queue
73+
.exe_task(|| QuickJsRuntime::do_with(consumer));
74+
self._add_job_run_task();
75+
res
6276
}
6377

6478
pub fn add_helper_task() {}
79+
80+
fn _add_job_run_task(&self) {
81+
self.event_queue.add_task(|| {
82+
QuickJsRuntime::do_with(|quick_js_rt| {
83+
while quick_js_rt.has_pending_jobs() {
84+
85+
let res = quick_js_rt.run_pending_job();
86+
match res {
87+
Ok(_) => {},
88+
Err(e) => {
89+
error!("job run failed: {}", e);
90+
},
91+
}
92+
93+
}
94+
})
95+
});
96+
}
6597
}
6698

6799
#[cfg(test)]
68100
pub mod tests {
69101
use crate::esruntime::EsRuntime;
70102
use crate::esscript::EsScript;
71103
use log::LevelFilter;
72-
use quick_js::JsValue;
104+
use quick_js::{JsValue, ExecutionError};
73105
use std::sync::Arc;
106+
use::log::debug;
74107

75108
lazy_static! {
76109
pub static ref TEST_ESRT: Arc<EsRuntime> = init();
@@ -83,13 +116,17 @@ pub mod tests {
83116
EsRuntime::builder().build()
84117
}
85118

119+
120+
86121
#[test]
87122
fn test_eval_sync() {
88123
let rt = &TEST_ESRT;
89-
rt.eval(EsScript::new(
124+
rt.eval_sync(EsScript::new(
90125
"test.es".to_string(),
91126
"console.log('foo bar');".to_string(),
92-
));
127+
)).ok().expect("eval script failed");
128+
129+
93130

94131
let res = rt
95132
.eval_sync(EsScript::new("test.es".to_string(), "(2 * 7);".to_string()))
@@ -98,4 +135,50 @@ pub mod tests {
98135

99136
assert_eq!(res, JsValue::Int(14));
100137
}
138+
139+
#[test]
140+
fn test_promise(){
141+
let rt = &TEST_ESRT;
142+
143+
rt.eval_sync(EsScript::new(
144+
"testp2.es".to_string(),
145+
"let r = {a: 1};console.log('setting up prom');let p = new Promise((res, rej) => {console.log('before res');res(123);console.log('after res');return 456;}).then((a) => {r.a = 2;console.log('prom ressed to ' + a);}).catch((x) => {console.log('p.ca ex=' + x);});".to_string(),
146+
)).ok().expect("eval script failed");
147+
148+
rt.eval_sync(EsScript::new(
149+
"testp2.es".to_string(),
150+
"console.log('r.a = ' + r.a + ' p= ' + p);".to_string(),
151+
)).ok().expect("eval script failed");
152+
}
153+
154+
#[test]
155+
fn test_module_sync() {
156+
let rt = &TEST_ESRT;
157+
debug!("test static import");
158+
let res: Result<JsValue, ExecutionError> = rt.eval_module_sync(EsScript::new(
159+
"test.es".to_string(),
160+
"import {some} from 'test_module.mes';\n console.log(some.foo);".to_string(),
161+
));
162+
163+
match res {
164+
Ok(_) => {},
165+
Err(e) => {
166+
log::error!("static import failed: {}", e);
167+
},
168+
}
169+
170+
debug!("test dynamic import");
171+
let res: Result<JsValue, ExecutionError> = rt.eval_module_sync(EsScript::new(
172+
"test.es".to_string(),
173+
"console.log('about to load dynamic module');import('test_module.mes').then((some) => {console.log('after dyn ' + some);console.log(some.mltpl(1, 2));}).catch((x) => {console.log('imp.cat x=' + x);});".to_string(),
174+
));
175+
176+
match res {
177+
Ok(_) => {},
178+
Err(e) => {
179+
log::error!("dynamic import failed: {}", e);
180+
},
181+
}
182+
183+
}
101184
}

src/esruntimebuilder.rs

+6
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ impl EsRuntimeBuilder {
1111
Self {}
1212
}
1313
}
14+
15+
impl Default for EsRuntimeBuilder {
16+
fn default() -> Self {
17+
EsRuntimeBuilder::new()
18+
}
19+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[allow(unused_imports)]
12
#[macro_use]
23
extern crate lazy_static;
34

src/quickjsruntime.rs

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::esscript::EsScript;
44
use crate::quickjsconsole::QuickJsConsole;
55
use quick_js::{Context, ExecutionError, JsValue};
66
use std::cell::RefCell;
7+
use log::trace;
78

89
thread_local! {
910
/// the thread-local SpiderMonkeyRuntime
@@ -29,6 +30,10 @@ impl QuickJsRuntime {
2930
self.context.eval(script.get_code())
3031
}
3132

33+
pub fn eval_module(&self, script: EsScript) -> Result<JsValue, ExecutionError> {
34+
self.context.eval_module(script.get_path(), script.get_code())
35+
}
36+
3237
pub(crate) fn do_with<C, R>(task: C) -> R
3338
where
3439
C: FnOnce(&QuickJsRuntime) -> R + Send + 'static,
@@ -39,4 +44,19 @@ impl QuickJsRuntime {
3944
task(qjs_rt)
4045
})
4146
}
47+
48+
pub fn has_pending_jobs(&self) -> bool {
49+
50+
let res = self.context.has_pending_jobs();
51+
trace!("QuickJSRuntime::has_pending_jobs = {}", res);
52+
res
53+
54+
}
55+
56+
pub fn run_pending_job(&self) -> Result<(), ExecutionError>{
57+
let res = self.context.run_pending_job();
58+
trace!("QuickJSRuntime::run_pending_job ok = {}", res.is_ok());
59+
res
60+
}
61+
4262
}

src/taskmanager.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ mod tests {
6161

6262
assert_eq!(s, "res");
6363

64-
for _x in 0..1000 {
64+
for _x in 0..5 {
6565
let s = tm.run_task_blocking(|| "res");
6666

6767
assert_eq!(s, "res");

test.mes

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import {mltpl} from "test_module.mes";
2+
3+
console.info("hello world from test.mes, 5 * 6 = %s", mltpl(5, 6));
4+
5+

test_module.mes

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function mltpl(a, b) {
2+
return a * b;
3+
}

0 commit comments

Comments
 (0)