// This example implements a custom module handler which mimics // the require/module.exports pattern use boa_engine::{prelude::JsObject, property::Attribute, Context, JsResult, JsValue}; use std::fs::read_to_string; fn main() { let js_file_path = "./scripts/calctest.js"; let buffer = read_to_string(js_file_path); if buffer.is_err() { println!("Error: {}", buffer.unwrap_err()); return; } // Creating the execution context let mut ctx = Context::default(); // Adding custom implementation that mimics 'require' ctx.register_global_function("require", 0, require); // Adding custom object that mimics 'module.exports' let moduleobj = JsObject::default(); moduleobj .set("exports", JsValue::from(" "), false, &mut ctx) .unwrap(); ctx.register_global_property("module", JsValue::from(moduleobj), Attribute::default()); // Instantiating the engine with the execution context // Loading, parsing and executing the JS code from the source file ctx.eval(&buffer.unwrap()).unwrap(); } // Custom implementation that mimics the 'require' module loader fn require(_: &JsValue, args: &[JsValue], ctx: &mut Context) -> JsResult { let arg = args.get(0).unwrap(); // BUG: Dev branch seems to be passing string arguments along with quotes let libfile = arg .to_string(ctx) .expect("Failed to convert to string") .to_std_string_escaped(); // Read the module source file println!("Loading: {}", libfile); let buffer = read_to_string(libfile); if let Err(..) = buffer { println!("Error: {}", buffer.unwrap_err()); Ok(JsValue::Rational(-1.0)) } else { // Load and parse the module source ctx.eval(&buffer.unwrap()).unwrap(); // Access module.exports and return as ResultValue let global_obj = ctx.global_object().to_owned(); let module = global_obj.get("module", ctx).unwrap(); module.as_object().unwrap().get("exports", ctx) } }