use super::*;
pub(super) fn register_host(ctx: &mut Context) -> JsResult<()> {
let source = ObjectInitializer::new(ctx)
.function(NativeFunction::from_fn_ptr(js_put), js_string!("put"), 2)
.function(NativeFunction::from_fn_ptr(js_get), js_string!("get"), 1)
.function(
NativeFunction::from_fn_ptr(js_get_variable),
js_string!("getVariable"),
0,
)
.function(
NativeFunction::from_fn_ptr(js_put_variable),
js_string!("putVariable"),
1,
)
.function(
NativeFunction::from_fn_ptr(js_put_login_header),
js_string!("putLoginHeader"),
1,
)
.function(
NativeFunction::from_fn_ptr(js_get_login_header),
js_string!("getLoginHeader"),
0,
)
.function(
NativeFunction::from_fn_ptr(js_get_login_header_map),
js_string!("getLoginHeaderMap"),
0,
)
.function(
NativeFunction::from_fn_ptr(js_remove_login_header),
js_string!("removeLoginHeader"),
0,
)
.function(
NativeFunction::from_fn_ptr(js_put_login_info),
js_string!("putLoginInfo"),
1,
)
.function(
NativeFunction::from_fn_ptr(js_get_login_info),
js_string!("getLoginInfo"),
0,
)
.function(
NativeFunction::from_fn_ptr(js_get_login_info_map),
js_string!("getLoginInfoMap"),
0,
)
.build();
ctx.register_global_property(js_string!("source"), source, Attribute::all())?;
let net = ObjectInitializer::new(ctx)
.function(NativeFunction::from_fn_ptr(js_ajax), js_string!("ajax"), 1)
.function(
NativeFunction::from_fn_ptr(js_connect),
js_string!("connect"),
1,
)
.function(NativeFunction::from_fn_ptr(js_post), js_string!("post"), 2)
.function(
NativeFunction::from_fn_ptr(js_get_cookie),
js_string!("getCookie"),
2,
)
.build();
ctx.register_global_property(js_string!("net"), net, Attribute::all())?;
Ok(())
}
fn js_put(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let key = arg(args, 0, ctx)?;
let value = arg(args, 1, ctx)?;
if let Some(host) = active_host() {
let mut h = host.borrow_mut();
h.state.kv.insert(key, value.clone());
h.dirty = true;
}
Ok(js_string!(value.as_str()).into())
}
fn js_get(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let key = arg(args, 0, ctx)?;
let v = active_host()
.map(|h| h.borrow().state.kv.get(&key).cloned().unwrap_or_default())
.unwrap_or_default();
Ok(js_string!(v.as_str()).into())
}
fn js_get_variable(_t: &JsValue, _args: &[JsValue], _ctx: &mut Context) -> JsResult<JsValue> {
let v = active_host()
.map(|h| h.borrow().state.variable.clone())
.unwrap_or_default();
Ok(js_string!(v.as_str()).into())
}
fn js_put_variable(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let value = arg(args, 0, ctx)?;
if let Some(host) = active_host() {
let mut h = host.borrow_mut();
h.state.variable = value.clone();
h.dirty = true;
}
Ok(js_string!(value.as_str()).into())
}
fn map_to_js_object(map: &BTreeMap<String, String>, ctx: &mut Context) -> JsObject {
let mut init = ObjectInitializer::new(ctx);
for (k, v) in map {
init.property(
js_string!(k.as_str()),
js_string!(v.as_str()),
Attribute::all(),
);
}
init.build()
}
fn js_put_login_header(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let json = arg(args, 0, ctx)?;
let r = json_to_string_map(&json).map(|map| {
if let Some(host) = active_host() {
host.borrow_mut().set_login_header(map);
}
json.clone()
});
yield_js(r)
}
fn js_get_login_header(_t: &JsValue, _args: &[JsValue], _ctx: &mut Context) -> JsResult<JsValue> {
let s = active_host()
.map(|h| {
let h = h.borrow();
if h.state.login_header.is_empty() {
String::new()
} else {
serde_json::to_string(&h.state.login_header).unwrap_or_default()
}
})
.unwrap_or_default();
Ok(js_string!(s.as_str()).into())
}
fn js_get_login_header_map(
_t: &JsValue,
_args: &[JsValue],
ctx: &mut Context,
) -> JsResult<JsValue> {
let map = active_host()
.map(|h| h.borrow().state.login_header.clone())
.unwrap_or_default();
Ok(map_to_js_object(&map, ctx).into())
}
fn js_remove_login_header(
_t: &JsValue,
_args: &[JsValue],
_ctx: &mut Context,
) -> JsResult<JsValue> {
if let Some(host) = active_host() {
let mut h = host.borrow_mut();
if !h.state.login_header.is_empty() {
h.state.login_header.clear();
h.dirty = true;
}
}
Ok(JsValue::undefined())
}
fn js_put_login_info(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let plain = arg(args, 0, ctx)?;
let r = match active_host() {
Some(host) => host
.borrow_mut()
.store_login_info(&plain)
.map(|_| plain.clone()),
None => Ok(plain.clone()),
};
yield_js(r)
}
fn js_get_login_info(_t: &JsValue, _args: &[JsValue], _ctx: &mut Context) -> JsResult<JsValue> {
let r = match active_host() {
Some(host) => host
.borrow()
.state
.get_login_info()
.map(Option::unwrap_or_default),
None => Ok(String::new()),
};
yield_js(r)
}
fn js_get_login_info_map(_t: &JsValue, _args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let plain = match active_host() {
Some(host) => match host.borrow().state.get_login_info() {
Ok(o) => o.unwrap_or_default(),
Err(e) => return Err(JsNativeError::typ().with_message(e.to_string()).into()),
},
None => String::new(),
};
if plain.is_empty() {
return Ok(ObjectInitializer::new(ctx).build().into());
}
let map =
json_to_string_map(&plain).map_err(|e| JsNativeError::typ().with_message(e.to_string()))?;
Ok(map_to_js_object(&map, ctx).into())
}
fn opt_extra_arg(args: &[JsValue], i: usize, ctx: &mut Context) -> JsResult<Option<String>> {
let extra = arg(args, i, ctx)?;
Ok((!extra.is_empty() && extra != "[object Object]").then_some(extra))
}
fn yield_response(r: Result<FetchResponse, EvalError>, ctx: &mut Context) -> JsResult<JsValue> {
match r {
Ok(resp) => Ok(response_to_js(&resp, ctx).into()),
Err(e) => Err(JsNativeError::typ().with_message(e.to_string()).into()),
}
}
fn js_ajax(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let url = arg(args, 0, ctx)?;
let r = match active_host() {
Some(host) => host.borrow_mut().ajax(&url),
None => Err(EvalError::Host("no active host".into())),
};
yield_js(r)
}
fn js_connect(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let url = arg(args, 0, ctx)?;
let extra = opt_extra_arg(args, 1, ctx)?;
let r = match active_host() {
Some(host) => host.borrow_mut().connect(&url, extra.as_deref()),
None => Err(EvalError::Host("no active host".into())),
};
yield_response(r, ctx)
}
fn js_post(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let url = arg(args, 0, ctx)?;
let body = arg(args, 1, ctx)?;
let extra = opt_extra_arg(args, 2, ctx)?;
let r = match active_host() {
Some(host) => host.borrow_mut().post(&url, &body, extra.as_deref()),
None => Err(EvalError::Host("no active host".into())),
};
yield_response(r, ctx)
}
fn response_to_js(resp: &FetchResponse, ctx: &mut Context) -> JsObject {
let headers: BTreeMap<String, String> = resp
.headers
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
let headers_obj = map_to_js_object(&headers, ctx);
ObjectInitializer::new(ctx)
.property(
js_string!("body"),
js_string!(resp.body.as_str()),
Attribute::all(),
)
.property(
js_string!("code"),
JsValue::from(i32::from(resp.status)),
Attribute::all(),
)
.property(js_string!("headers"), headers_obj, Attribute::all())
.build()
}
fn js_get_cookie(_t: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult<JsValue> {
let domain = arg(args, 0, ctx)?;
let key = arg(args, 1, ctx)?;
let v = active_host()
.map(|h| {
h.borrow()
.get_cookie(&domain, (!key.is_empty()).then_some(key.as_str()))
})
.unwrap_or_default();
Ok(js_string!(v.as_str()).into())
}