use boa_engine::{Context, JsResult, JsString, JsValue}; use boa_engine::object::ObjectInitializer; use boa_engine::property::Attribute; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; wit_bindgen_rust::export!("../exports.wit"); wit_bindgen_rust::import!("../container.wit"); struct Exports; impl exports::Exports for Exports { fn eval_javascript(script: String) -> String { let mut ctx = Context::default(); ctx.register_global_function("fetch", 0, do_fetch); let console = ObjectInitializer::new(&mut ctx) .function(console_info, "log", 0) .build(); ctx.register_global_property("console", console, Attribute::empty()); let o = match ctx.eval(&script) { JsResult::Ok(o) => o, JsResult::Err(o) => o, }; format!("{}", o.to_json(&mut ctx).expect("To JSON error")) } } fn console_info(_this: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult { let mut msg = String::new(); if args.len() == 0 { msg.push_str(""); } else { for (i, a) in args.iter().enumerate() { if i > 0 { msg.push_str(", "); } let a = a.to_string(ctx); msg.push_str(&a.map(|s| s.to_string()).unwrap_or_else(|e| format!("", e))); } } container::log("INFO", &msg); Ok(JsValue::undefined()) } #[derive(Clone, Debug, Serialize, Deserialize)] struct FetchResult { error: Option, result: Option, } fn do_fetch(_this: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult { if args.is_empty() { return JsResult::Err(JsValue::String(JsString::from("Requires at least one argument"))); } let mut fetch_params_map = Map::new(); fetch_params_map.insert("url".to_string(), args[0].to_json(ctx).expect("error")); if args.len() > 1 { fetch_params_map.insert("options".to_string(), args[1].to_json(ctx).expect("error")); } let fetch_params = format!("{}", Value::Object(fetch_params_map)); let fetch_result_string = container::fetch(&fetch_params); let fetch_result: FetchResult = serde_json::from_str(&fetch_result_string).expect("from str error"); if let Some(result) = fetch_result.result { let r: Value = serde_json::from_str(&result).expect("result from str error"); let v = JsValue::from_json(&r, ctx).unwrap(); return JsResult::Ok(v); } JsResult::Err(JsValue::String(JsString::from(format!("Invoke fetch error: {}", fetch_result.error.unwrap_or("".to_string()))))) }