use crate::error::JsError;
use crate::interpreter::Interpreter;
use crate::value::{CheapClone, ExoticObject, Guarded, JsValue};
use crate::{InternalModule, Order, OrderId, RuntimeValue};
pub fn create_eval_internal_module() -> InternalModule {
InternalModule::native("tsrun:host")
.with_function("order", order_syscall, 1)
.with_function("__cancelOrder__", cancel_order_syscall, 1)
.with_function("__getOrderId__", get_order_id_syscall, 0)
.build()
}
fn order_syscall(
interp: &mut Interpreter,
_this: JsValue,
args: &[JsValue],
) -> Result<Guarded, JsError> {
let payload = args.first().cloned().unwrap_or(JsValue::Undefined);
let id = OrderId(interp.next_order_id);
interp.next_order_id += 1;
let payload_rv = if let JsValue::Object(ref obj) = payload {
let payload_guard = interp.heap.create_guard();
payload_guard.guard(obj.cheap_clone());
RuntimeValue::with_guard(payload, payload_guard)
} else {
RuntimeValue::unguarded(payload)
};
interp.pending_orders.push(Order {
id,
payload: payload_rv,
});
let marker_guard = interp.heap.create_guard();
let marker = marker_guard.alloc();
marker.borrow_mut().exotic = ExoticObject::PendingOrder { id: id.0 };
Ok(Guarded::with_guard(JsValue::Object(marker), marker_guard))
}
fn cancel_order_syscall(
interp: &mut Interpreter,
_this: JsValue,
args: &[JsValue],
) -> Result<Guarded, JsError> {
let id = match args.first() {
Some(JsValue::Number(n)) => OrderId(*n as u64),
_ => return Err(JsError::type_error("__cancelOrder__ requires order ID")),
};
interp.cancelled_orders.push(id);
interp.pending_orders.retain(|o| o.id != id);
interp.order_responses.remove(&id);
Ok(Guarded::unguarded(JsValue::Undefined))
}
fn get_order_id_syscall(
interp: &mut Interpreter,
_this: JsValue,
_args: &[JsValue],
) -> Result<Guarded, JsError> {
let id = interp.next_order_id;
interp.next_order_id += 1;
Ok(Guarded::unguarded(JsValue::Number(id as f64)))
}