Skip to main content

turbopack_core/
loader.rs

1use std::hash::{Hash, Hasher};
2
3use bincode::{Decode, Encode};
4use serde::{Deserialize, Serialize};
5use turbo_tasks::{NonLocalValue, OperationValue, TaskInput, trace::TraceRawVcs};
6use turbo_tasks_fs::FileSystemPath;
7
8#[derive(
9    Clone,
10    PartialEq,
11    Eq,
12    Debug,
13    TraceRawVcs,
14    Serialize,
15    Deserialize,
16    NonLocalValue,
17    OperationValue,
18    Encode,
19    Decode,
20)]
21pub struct WebpackLoaderItem {
22    pub loader: turbo_rcstr::RcStr,
23    #[serde(default)]
24    #[bincode(with = "turbo_bincode::serde_self_describing")]
25    pub options: serde_json::Map<String, serde_json::Value>,
26}
27
28impl Hash for WebpackLoaderItem {
29    fn hash<H: Hasher>(&self, state: &mut H) {
30        self.loader.hash(state);
31        // serde_json::Map doesn't implement Hash, so hash the canonical JSON string.
32        // serde_json::Map preserves insertion order, and our maps are built
33        // deterministically from AST traversal, so this is stable.
34        let options_str = serde_json::to_string(&self.options).unwrap_or_default();
35        options_str.hash(state);
36    }
37}
38
39impl TaskInput for WebpackLoaderItem {
40    fn is_transient(&self) -> bool {
41        false
42    }
43}
44
45/// Like `WebpackLoaderItem`, but with the loader path already resolved to a `FileSystemPath`.
46#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, NonLocalValue, Encode, Decode)]
47pub struct ResolvedWebpackLoaderItem {
48    pub loader: FileSystemPath,
49    #[bincode(with = "turbo_bincode::serde_self_describing")]
50    pub options: serde_json::Map<String, serde_json::Value>,
51}
52
53impl Hash for ResolvedWebpackLoaderItem {
54    fn hash<H: Hasher>(&self, state: &mut H) {
55        self.loader.hash(state);
56        let options_str = serde_json::to_string(&self.options).unwrap_or_default();
57        options_str.hash(state);
58    }
59}
60
61impl TaskInput for ResolvedWebpackLoaderItem {
62    fn is_transient(&self) -> bool {
63        false
64    }
65}
66
67#[derive(Debug, Clone)]
68#[turbo_tasks::value(shared, transparent)]
69pub struct WebpackLoaderItems(pub Vec<WebpackLoaderItem>);
70
71impl std::fmt::Display for WebpackLoaderItems {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        let mut iter = self.0.iter();
74
75        if let Some(first) = iter.next() {
76            write!(f, "{}", first.loader)?;
77            for remaining in iter {
78                write!(f, ", {}", remaining.loader)?;
79            }
80        }
81
82        Ok(())
83    }
84}