next.js/turbopack/crates/turbopack-core/src/loader.rs
loader.rs85 lines2.4 KB
use std::hash::{Hash, Hasher};

use bincode::{Decode, Encode};
use serde::{Deserialize, Serialize};
use turbo_tasks::{NonLocalValue, OperationValue, TaskInput, trace::TraceRawVcs};
use turbo_tasks_fs::FileSystemPath;

#[derive(
    Clone,
    PartialEq,
    Eq,
    Debug,
    TraceRawVcs,
    Serialize,
    Deserialize,
    NonLocalValue,
    OperationValue,
    Encode,
    Decode,
)]
pub struct WebpackLoaderItem {
    pub loader: turbo_rcstr::RcStr,
    #[serde(default)]
    #[bincode(with = "turbo_bincode::serde_self_describing")]
    pub options: serde_json::Map<String, serde_json::Value>,
}

impl Hash for WebpackLoaderItem {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.loader.hash(state);
        // serde_json::Map doesn't implement Hash, so hash the canonical JSON string.
        // serde_json::Map preserves insertion order, and our maps are built
        // deterministically from AST traversal, so this is stable.
        let options_str = serde_json::to_string(&self.options).unwrap_or_default();
        options_str.hash(state);
    }
}

impl TaskInput for WebpackLoaderItem {
    fn is_transient(&self) -> bool {
        false
    }
}

/// Like `WebpackLoaderItem`, but with the loader path already resolved to a `FileSystemPath`.
#[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, NonLocalValue, Encode, Decode)]
pub struct ResolvedWebpackLoaderItem {
    pub loader: FileSystemPath,
    #[bincode(with = "turbo_bincode::serde_self_describing")]
    pub options: serde_json::Map<String, serde_json::Value>,
}

impl Hash for ResolvedWebpackLoaderItem {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.loader.hash(state);
        let options_str = serde_json::to_string(&self.options).unwrap_or_default();
        options_str.hash(state);
    }
}

impl TaskInput for ResolvedWebpackLoaderItem {
    fn is_transient(&self) -> bool {
        false
    }
}

#[derive(Debug, Clone)]
#[turbo_tasks::value(shared, transparent)]
pub struct WebpackLoaderItems(pub Vec<WebpackLoaderItem>);

impl std::fmt::Display for WebpackLoaderItems {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut iter = self.0.iter();

        if let Some(first) = iter.next() {
            write!(f, "{}", first.loader)?;
            for remaining in iter {
                write!(f, ", {}", remaining.loader)?;
            }
        }

        Ok(())
    }
}
Quest for Codev2.0.0
/
SIGN IN