如何通过v8或deno_core将JavaScript模块成员导出到Rust并调用?
解决deno_core调用ES模块导出函数的问题
你之前的代码找不到sum函数,核心原因是ES模块的导出不会挂载到全局对象,而是保存在模块自身的命名空间对象里。直接从global里查找自然拿不到目标函数。
修正步骤
- 模块评估完成后,
result.await?会返回模块的命名空间对象,需要保留这个对象 - 从模块命名空间中获取导出的
sum函数,而非全局对象
修正后的完整代码
use deno_core::{error::Error, JsRuntime, RuntimeOptions, FsModuleLoader}; use std::rc::Rc; use tokio; use anyhow::Context; fn main() -> Result<(), Error> { let mut js_runtime = JsRuntime::new(RuntimeOptions { module_loader: Some(Rc::new(FsModuleLoader)), ..Default::default() }); let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() .build()?; let main_module = deno_core::resolve_path( "./module.js", &std::env::current_dir().context("Unable to get CWD")?, )?; let future = async move { let mod_id = js_runtime.load_main_module(&main_module, None).await?; // 评估模块并获取其命名空间对象 let module_namespace = js_runtime.mod_evaluate(mod_id).await?; js_runtime.run_event_loop(false).await?; let context = js_runtime.global_context(); let scope = &mut js_runtime.handle_scope(); // 将模块命名空间转换为v8可操作的Value let ns_value = module_namespace.open(scope); let func_key = v8::String::new(scope, "sum").unwrap(); let func = ns_value.get(scope, func_key.into()).unwrap(); if func.is_function() { println!("func is a function"); // 可选:调用sum函数示例 let args = [ v8::Number::new(scope, 2.0).into(), v8::Number::new(scope, 3.0).into(), ]; let result = func.call_as_function(scope, ns_value, &args).unwrap(); let result_num = result.to_rust_string_lossy(scope); println!("sum(2,3) = {}", result_num); } else { println!("func is not a function but {:?}", func.type_of(scope)); } Ok(()) }; runtime.block_on(future) }
补充说明
- 确保你的
module.js内容正确:export function sum(a, b) { return a + b; } - 若使用自定义
FsModuleLoader,需确保它能正确加载本地模块;使用默认的deno_core::FsModuleLoader则需确认依赖配置正确 - 模块评估后需调用
run_event_loop处理完异步任务(如果存在),false参数表示处理完当前待处理任务后退出事件循环
内容的提问来源于stack exchange,提问作者CGessinger
相关产品推荐
相关产品推荐

