use deno_core::{OpState, ResourceId, op2};
use deno_core::{RuntimeOptions, extension, v8::CreateParams};
use deno_error::JsErrorBox;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
pub fn runtime_options() -> RuntimeOptions {
RuntimeOptions {
extensions: vec![
deno_webidl::deno_webidl::init(),
deno_web::deno_web::init(Default::default()),
deno_fetch::deno_fetch::init(Default::default()),
bootstrap::init(),
request_response_extension::init(),
],
create_params: Some(CreateParams::default()),
..Default::default()
}
}
extension!(
bootstrap,
esm_entry_point = "ext:bootstrap/bootstrap.js",
esm = ["bootstrap.js", "run.js"],
);
pub struct RequestParts {
pub url: String,
pub method: String,
pub headers: Vec<(String, String)>,
pub rid: Option<ResourceId>,
}
pub struct ResponseParts {
pub status: u16,
pub headers: HashMap<String, String>,
pub rid: Option<ResourceId>,
}
#[derive(Default)]
pub struct SlotMap {
pub requests: HashMap<u32, RequestParts>,
pub responses: HashMap<u32, ResponseParts>,
}
type OpGetRequestParts = (String, String, Vec<(String, String)>, Option<ResourceId>);
#[op2]
#[serde]
fn op_take_request_parts(
state: &mut OpState,
#[smi] id: u32,
) -> Result<OpGetRequestParts, JsErrorBox> {
let slot_map = state
.try_borrow_mut::<SlotMap>()
.ok_or_else(|| JsErrorBox::generic("slot map missing"))?;
let parts = slot_map
.requests
.remove(&id)
.ok_or_else(|| JsErrorBox::generic(format!("request {id} not found")))?;
Ok((parts.url, parts.method, parts.headers, parts.rid))
}
#[op2(async(lazy))]
async fn op_respond(
state: Rc<RefCell<OpState>>,
#[smi] id: u32,
#[smi] status: u16,
#[serde] headers: Vec<(String, String)>,
#[smi] rid: Option<ResourceId>,
) -> Result<(), JsErrorBox> {
let headers_map = headers.into_iter().collect::<HashMap<String, String>>();
let parts = ResponseParts {
status,
headers: headers_map,
rid,
};
let mut state = state.borrow_mut();
let slot_map = state
.try_borrow_mut::<SlotMap>()
.ok_or_else(|| JsErrorBox::generic("slot map missing"))?;
slot_map.responses.insert(id, parts);
Ok(())
}
deno_core::extension!(
request_response_extension,
ops = [op_take_request_parts, op_respond],
state = |s| {
s.put(SlotMap::default());
},
);