green_copper_runtime/features/js_fetch/mod.rs
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157
//! runtime agnostic fetch implementation
use crate::features::js_fetch::spec::{do_fetch, FetchInit};
use quickjs_runtime::builder::QuickJsRuntimeBuilder;
use quickjs_runtime::facades::QuickJsRuntimeFacade;
use quickjs_runtime::jsutils::{JsError, JsValueType};
use quickjs_runtime::quickjsrealmadapter::QuickJsRealmAdapter;
mod proxies;
pub mod spec;
pub fn init(builder: QuickJsRuntimeBuilder) -> QuickJsRuntimeBuilder {
builder.runtime_facade_init_hook(impl_for_rt)
}
pub fn impl_for_rt(runtime: &QuickJsRuntimeFacade) -> Result<(), JsError> {
runtime.loop_sync_mut(|rta| rta.add_realm_init_hook(|_rt, realm| impl_for(realm)))
}
pub fn impl_for(realm: &QuickJsRealmAdapter) -> Result<(), JsError> {
realm.install_function(
&[],
"fetch",
|_rt, realm, _this_obj, args| {
//
// convert vals to fetch options here, make fetch options Send
//arg0 = url: String
//arg1 = data: Object
//if arg0 is not a string the returned promise will reject
let url: Option<String> =
if !args.is_empty() && args[0].get_js_type() == JsValueType::String {
Some(args[0].to_string()?)
} else {
None
};
let fetch_init: FetchInit = FetchInit::from_js_object(realm, args.get(1))?;
realm.create_resolving_promise_async(
//
// do request here and return result as fetch objects
do_fetch(url, fetch_init),
|realm, res| {
// convert result fetch objects to JsValueAdapter here
res.to_js_value(realm)
},
)
},
2,
)?;
proxies::impl_for(realm)
}
#[cfg(test)]
pub mod tests {
use crate::features::js_fetch::impl_for_rt;
use crate::tests::init_test_greco_rt;
use futures::executor::block_on;
use quickjs_runtime::jsutils::Script;
use quickjs_runtime::values::JsValueFacade;
#[test]
fn test_fetch_generic() {
let rt = init_test_greco_rt();
#[allow(clippy::ok_expect)]
impl_for_rt(&rt).ok().expect("init failed");
let fetch_fut = rt.eval(
None,
Script::new("test_fetch_gen.js", "let testFunc = async function() {console.log(1); let fetchRes = await fetch('https://httpbin.org/anything', {headers: {myHeader: ['a', 'b']}}); let text = await fetchRes.text(); return text;}; testFunc()"),
);
let res = block_on(fetch_fut);
match res {
Ok(val) => match val {
JsValueFacade::JsPromise { cached_promise } => {
let res_fut = cached_promise.get_promise_result();
let fetch_res = block_on(res_fut);
match fetch_res {
Ok(v) => match v {
Ok(resolved) => {
//assert_eq!(resolved.js_get_value_type(), JsValueType::String);
println!("resolved to string: {}", resolved.stringify());
}
Err(rejected) => {
panic!("promise was rejected: {}", rejected.stringify());
}
},
Err(e) => {
panic!("fetch failed {}", e)
}
}
}
_ => {
panic!("result was not a promise")
}
},
Err(e) => {
panic!("script failed: {}", e);
}
}
}
/*#[test]
fn test_chart() {
let rt = init_test_greco_rt();
impl_for_rt(&rt).ok().expect("init failed");
let fetch_fut = rt.eval(
None,
Script::new("test_fetch_gen.js", r#"
let testFunc = async function() {
console.log(1);
let body = {
"chart": {
"chartOptions": {"as": "svg"}
}
};
let fetchRes = await fetch('http://192.168.10.43:8055/charts/line', {body: JSON.stringify(body), headers: {"Content-Type": ['application/json']}});
let text = await fetchRes.text();
return text;
};
testFunc()
"#),
);
let res = block_on(fetch_fut);
match res {
Ok(val) => match val {
JsValueFacade::JsPromise { cached_promise } => {
let res_fut = cached_promise.get_promise_result();
let fetch_res = block_on(res_fut);
match fetch_res {
Ok(v) => match v {
Ok(resolved) => {
//assert_eq!(resolved.js_get_value_type(), JsValueType::String);
println!("resolved to string: {}", resolved.stringify());
}
Err(rejected) => {
panic!("promise was rejected: {}", rejected.stringify());
}
},
Err(e) => {
panic!("fetch failed {}", e)
}
}
}
_ => {
panic!("result was not a promise")
}
},
Err(e) => {
panic!("script failed: {}", e);
}
}
}*/
}