use rolldown_common::ModuleId;
use rolldown_common::side_effects::{DeterminedSideEffects, HookSideEffects};
use rolldown_error::{BuildDiagnostic, BuildResult};
use rustc_hash::FxHashMap;
use crate::ecmascript::ecma_module_view_factory::normalize_side_effects;
use crate::module_loader::module_loader::VisitState;
use crate::{SharedOptions, stages::scan_stage::NormalizedScanStageOutput};
pub async fn defer_sync_scan_data(
options: &SharedOptions,
module_id_to_idx: &FxHashMap<ModuleId, VisitState>,
scan_stage_output: &mut NormalizedScanStageOutput,
) -> BuildResult<()> {
let Some(ref func) = options.defer_sync_scan_data else {
return Ok(());
};
let result = func.exec().await?;
let mut errors: Vec<BuildDiagnostic> = vec![];
for data in result {
let source_id = ModuleId::new(data.id.as_str());
let Some(state) = module_id_to_idx.get(&source_id) else {
continue;
};
let module_idx = state.idx();
let Some(module) = scan_stage_output.module_table.modules.get_mut(module_idx) else {
continue;
};
let Some(normal) = module.as_normal_mut() else {
continue;
};
let side_effects = match data.side_effects {
Some(HookSideEffects::False) => DeterminedSideEffects::UserDefined(false),
Some(HookSideEffects::NoTreeshake) => DeterminedSideEffects::NoTreeshake,
_ => {
match normalize_side_effects(
options,
&normal.originative_resolved_id,
Some(&scan_stage_output.stmt_infos[module_idx]),
data.side_effects,
)
.await
{
Ok(side_effects) => side_effects,
Err(error) => {
errors.extend(error.into_vec());
continue;
}
}
}
};
normal.ecma_view.side_effects = side_effects;
}
if errors.is_empty() { Ok(()) } else { Err(errors.into()) }
}