use std::{env, sync::Arc};
use anyhow::{Context, Error};
use parking_lot::Mutex;
use swc_common::{plugin::metadata::TransformPluginMetadataContext, SourceMap};
use wasmer::{ChainableNamedResolver, Instance};
use wasmer_wasi::{is_wasi_module, WasiState};
use crate::imported_fn::build_import_object;
#[tracing::instrument(level = "info", skip_all)]
pub fn load_plugin(
plugin_path: &std::path::Path,
cache: &once_cell::sync::Lazy<crate::cache::PluginModuleCache>,
source_map: &Arc<SourceMap>,
metadata_context: &Arc<TransformPluginMetadataContext>,
plugin_config: Option<serde_json::Value>,
transform_result_buffer: &Arc<Mutex<Vec<u8>>>,
core_diag_buffer: &Arc<Mutex<Vec<u8>>>,
) -> Result<Instance, Error> {
let module = cache.load_module(plugin_path)?;
let import_object = build_import_object(
&module,
source_map.clone(),
metadata_context.clone(),
plugin_config,
transform_result_buffer,
core_diag_buffer,
);
let instance = if is_wasi_module(&module) {
let mut wasi_env = WasiState::new(
plugin_path
.file_name()
.and_then(|f| f.to_str())
.expect("Plugin path missing file name"),
);
let wasi_env = if let Ok(cwd) = env::current_dir() {
wasi_env.map_dir("/cwd", cwd)?
} else {
&mut wasi_env
};
let mut wasi_env = wasi_env.finalize()?;
let wasi_env_import_object = wasi_env.import_object(&module)?;
let chained_resolver = import_object.chain_front(wasi_env_import_object);
Instance::new(&module, &chained_resolver)
} else {
Instance::new(&module, &import_object)
};
instance.context("Failed to create plugin instance")
}