diff --git a/.cargo/config.toml b/.cargo/config.toml index 1480f604c77438..a03957d798f0a0 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,10 @@ [env] CARGO_WORKSPACE_DIR = { value = "", relative = true } +[build] +rustflags = ["--cfg", "tokio_unstable"] +rustdocflags = ["-Znormalize-docs"] + [target.x86_64-pc-windows-msvc] linker = "rust-lld" diff --git a/Cargo.lock b/Cargo.lock index 639178f6f28496..5145347dea429d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8625,6 +8625,7 @@ name = "turbo-tasks" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "auto-hash-map", "concurrent-queue", "dashmap", diff --git a/Cargo.toml b/Cargo.toml index 5ade55d2ec04c7..06bc0f3697c050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ default-members = [ "crates/turbo-tasks-fetch", "crates/turbo-tasks-fs", "crates/turbo-tasks-hash", - "crates/turbo-tasks-macros", "crates/turbo-tasks-macros-shared", "crates/turbo-tasks-macros-tests", "crates/turbo-tasks-malloc", diff --git a/crates/node-file-trace/src/lib.rs b/crates/node-file-trace/src/lib.rs index aed9b901d4c38a..b25d4ba230df35 100644 --- a/crates/node-file-trace/src/lib.rs +++ b/crates/node-file-trace/src/lib.rs @@ -1,4 +1,6 @@ #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] mod nft_json; @@ -17,41 +19,38 @@ use anyhow::{anyhow, Context, Result}; #[cfg(feature = "cli")] use clap::Parser; #[cfg(feature = "node-api")] -use serde::{Deserialize, Serialize}; +use serde::Deserialize; +#[cfg(feature = "node-api")] +use serde::Serialize; use tokio::sync::mpsc::channel; use turbo_tasks::{ - backend::Backend, - primitives::{OptionStringVc, StringsVc}, - util::FormatDuration, - NothingVc, TaskId, TransientInstance, TransientValue, TurboTasks, TurboTasksBackendApi, - UpdateInfo, Value, + backend::Backend, unit, util::FormatDuration, TaskId, TransientInstance, TransientValue, + TurboTasks, TurboTasksBackendApi, UpdateInfo, Value, Vc, }; use turbo_tasks_fs::{ - glob::GlobVc, DirectoryEntry, DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc, - ReadGlobResultVc, + glob::Glob, DirectoryEntry, DiskFileSystem, FileSystem, FileSystemPath, ReadGlobResult, }; use turbo_tasks_memory::{ stats::{ReferenceType, Stats}, viz, MemoryBackend, }; use turbopack::{ - emit_asset, emit_with_completion, module_options::ModuleOptionsContext, rebase::RebasedAssetVc, - resolve_options_context::ResolveOptionsContext, transition::TransitionsByNameVc, - ModuleAssetContextVc, + emit_asset, emit_with_completion, module_options::ModuleOptionsContext, rebase::RebasedAsset, + resolve_options_context::ResolveOptionsContext, ModuleAssetContext, }; -use turbopack_cli_utils::issue::{ConsoleUiVc, IssueSeverityCliOption, LogOptions}; +use turbopack_cli_utils::issue::{ConsoleUi, IssueSeverityCliOption, LogOptions}; use turbopack_core::{ - asset::{Asset, AssetVc, AssetsVc}, + asset::{Asset, Assets}, compile_time_info::CompileTimeInfo, - context::{AssetContext, AssetContextVc}, - environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, - issue::{IssueContextExt, IssueReporter, IssueSeverity, IssueVc}, + context::AssetContext, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, + issue::{IssueContextExt, IssueReporter, IssueSeverity}, reference::all_assets, resolve::options::{ImportMapping, ResolvedMap}, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; -use crate::nft_json::NftJsonAssetVc; +use crate::nft_json::NftJsonAsset; #[cfg(feature = "persistent_cache")] #[cfg_attr(feature = "cli", derive(clap::Args))] @@ -195,25 +194,25 @@ impl Args { } } -async fn create_fs(name: &str, context: &str, watch: bool) -> Result { - let fs = DiskFileSystemVc::new(name.to_string(), context.to_string()); +async fn create_fs(name: &str, context: &str, watch: bool) -> Result>> { + let fs = DiskFileSystem::new(name.to_string(), context.to_string()); if watch { fs.await?.start_watching()?; } else { fs.await?.invalidate(); } - Ok(fs.into()) + Ok(Vc::upcast(fs)) } async fn add_glob_results( - context: AssetContextVc, - result: ReadGlobResultVc, - list: &mut Vec, + context: Vc>, + result: Vc, + list: &mut Vec>>, ) -> Result<()> { let result = result.await?; for entry in result.results.values() { if let DirectoryEntry::File(path) = entry { - let source = SourceAssetVc::new(*path).into(); + let source = Vc::upcast(SourceAsset::new(*path)); list.push(context.process( source, Value::new(turbopack_core::reference_type::ReferenceType::Undefined), @@ -222,9 +221,9 @@ async fn add_glob_results( } for result in result.inner.values() { fn recurse<'a>( - context: AssetContextVc, - result: ReadGlobResultVc, - list: &'a mut Vec, + context: Vc>, + result: Vc, + list: &'a mut Vec>>, ) -> Pin> + Send + 'a>> { Box::pin(add_glob_results(context, result, list)) } @@ -235,37 +234,41 @@ async fn add_glob_results( } #[turbo_tasks::function] -async fn input_to_modules<'a>( - fs: FileSystemVc, +async fn input_to_modules( + fs: Vc>, input: Vec, exact: bool, process_cwd: Option, context: String, module_options: TransientInstance, resolve_options: TransientInstance, -) -> Result { +) -> Result> { let root = fs.root(); let process_cwd = process_cwd .clone() .map(|p| p.trim_start_matches(&context).to_owned()); - let context: AssetContextVc = - create_module_asset(root, process_cwd, module_options, resolve_options).into(); + let context: Vc> = Vc::upcast(create_module_asset( + root, + process_cwd, + module_options, + resolve_options, + )); let mut list = Vec::new(); - for input in input.iter() { + for input in input { if exact { - let source = SourceAssetVc::new(root.join(input)).into(); + let source = Vc::upcast(SourceAsset::new(root.join(input))); list.push(context.process( source, Value::new(turbopack_core::reference_type::ReferenceType::Undefined), )); } else { - let glob = GlobVc::new(input); + let glob = Glob::new(input); add_glob_results(context, root.read_glob(glob, false), &mut list).await?; }; } - Ok(AssetsVc::cell(list)) + Ok(Vc::cell(list)) } fn process_context(dir: &Path, context_directory: Option<&String>) -> Result { @@ -492,15 +495,15 @@ async fn run>( resolve_options, ); - let source = TransientValue::new(output.into()); - let issues = IssueVc::peek_issues_with_path(output) + let source = TransientValue::new(output.node); + let issues = output + .peek_issues_with_path() .await? .strongly_consistent() .await?; - let console_ui = ConsoleUiVc::new(log_options); - console_ui - .as_issue_reporter() + let console_ui = ConsoleUi::new(log_options); + Vc::upcast::>(console_ui) .report_issues(TransientInstance::new(issues), source); if has_return_value { @@ -509,7 +512,7 @@ async fn run>( sender.send(output_iter.collect::>()).await?; drop(sender); } - Ok(NothingVc::new().into()) + Ok(unit().node) }) }); finish(tt, task).await?; @@ -527,7 +530,7 @@ async fn main_operation( args: TransientInstance, module_options: TransientInstance, resolve_options: TransientInstance, -) -> Result { +) -> Result>> { let dir = current_dir.into_value(); let args = &*args; let &CommonArgs { @@ -565,7 +568,7 @@ async fn main_operation( } } - return Ok(StringsVc::cell(result.into_iter().collect::>())); + return Ok(Vc::cell(result.into_iter().collect::>())); } Args::Annotate { common: _ } => { let input = process_input(&dir, &context, input).unwrap(); @@ -583,16 +586,16 @@ async fn main_operation( .await? .iter() { - let nft_asset = NftJsonAssetVc::new(*module); + let nft_asset = NftJsonAsset::new(*module); let path = nft_asset.ident().path().await?.path.clone(); output_nft_assets.push(path); - emits.push(emit_asset(nft_asset.into())); + emits.push(emit_asset(Vc::upcast(nft_asset))); } // Wait for all files to be emitted for emit in emits { emit.await?; } - return Ok(StringsVc::cell(output_nft_assets)); + return Ok(Vc::cell(output_nft_assets)); } Args::Build { ref output_directory, @@ -616,7 +619,7 @@ async fn main_operation( .await? .iter() { - let rebased = RebasedAssetVc::new(*module, input_dir, output_dir).into(); + let rebased = Vc::upcast(RebasedAsset::new(*module, input_dir, output_dir)); emits.push(emit_with_completion(rebased, output_dir)); } // Wait for all files to be emitted @@ -626,20 +629,20 @@ async fn main_operation( } Args::Size { common: _ } => todo!(), } - Ok(StringsVc::cell(Vec::new())) + Ok(Vc::cell(Vec::new())) } #[turbo_tasks::function] async fn create_module_asset( - root: FileSystemPathVc, + root: Vc, process_cwd: Option, module_options: TransientInstance, resolve_options: TransientInstance, -) -> Result { - let env = EnvironmentVc::new( +) -> Result> { + let env = Environment::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment { - cwd: OptionStringVc::cell(process_cwd), + cwd: Vc::cell(process_cwd), ..Default::default() } .into(), @@ -650,12 +653,12 @@ async fn create_module_asset( let glob_mappings = vec![ ( root, - GlobVc::new("**/*/next/dist/server/next.js"), + Glob::new("**/*/next/dist/server/next.js".to_string()), ImportMapping::Ignore.into(), ), ( root, - GlobVc::new("**/*/next/dist/bin/next"), + Glob::new("**/*/next/dist/bin/next".to_string()), ImportMapping::Ignore.into(), ), ]; @@ -672,8 +675,8 @@ async fn create_module_asset( ); } - Ok(ModuleAssetContextVc::new( - TransitionsByNameVc::cell(HashMap::new()), + Ok(ModuleAssetContext::new( + Vc::cell(HashMap::new()), compile_time_info, ModuleOptionsContext::clone(&*module_options).cell(), resolve_options.cell(), diff --git a/crates/node-file-trace/src/nft_json.rs b/crates/node-file-trace/src/nft_json.rs index 38d88d0d2132f7..a85211034902a4 100644 --- a/crates/node-file-trace/src/nft_json.rs +++ b/crates/node-file-trace/src/nft_json.rs @@ -1,21 +1,22 @@ use anyhow::Result; use serde_json::json; +use turbo_tasks::Vc; use turbo_tasks_fs::{File, FileSystem}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, reference::all_assets, }; #[turbo_tasks::value(shared)] pub struct NftJsonAsset { - entry: AssetVc, + entry: Vc>, } #[turbo_tasks::value_impl] -impl NftJsonAssetVc { +impl NftJsonAsset { #[turbo_tasks::function] - pub fn new(entry: AssetVc) -> Self { + pub fn new(entry: Vc>) -> Vc { Self::cell(NftJsonAsset { entry }) } } @@ -23,15 +24,15 @@ impl NftJsonAssetVc { #[turbo_tasks::value_impl] impl Asset for NftJsonAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { let path = self.entry.ident().path().await?; - Ok(AssetIdentVc::from_path( - path.fs.root().join(&format!("{}.nft.json", path.path)), + Ok(AssetIdent::from_path( + path.fs.root().join(format!("{}.nft.json", path.path)), )) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let context = self.entry.ident().path().parent().await?; // For clippy -- This explicit deref is necessary let entry_path = &*self.entry.ident().path().await?; @@ -54,6 +55,6 @@ impl Asset for NftJsonAsset { "files": result }); - Ok(File::from(json.to_string()).into()) + Ok(AssetContent::file(File::from(json.to_string()).into())) } } diff --git a/crates/turbo-tasks-build/src/lib.rs b/crates/turbo-tasks-build/src/lib.rs index c9375f21183e96..dd83adf84ffe8c 100644 --- a/crates/turbo-tasks-build/src/lib.rs +++ b/crates/turbo-tasks-build/src/lib.rs @@ -1,6 +1,8 @@ use std::{ collections::{HashMap, HashSet}, - env::{self, current_dir}, + env::{ + current_dir, {self}, + }, fmt::{Display, Write}, fs::read_dir, path::{PathBuf, MAIN_SEPARATOR as PATH_SEP}, @@ -9,13 +11,14 @@ use std::{ use anyhow::{Context, Result}; use glob::glob; use syn::{ - Attribute, Ident, Item, ItemEnum, ItemFn, ItemImpl, ItemMod, ItemStruct, ItemTrait, Path, - PathArguments, PathSegment, TraitItem, TraitItemMethod, Type, TypePath, + parse_quote, Attribute, Ident, Item, ItemEnum, ItemFn, ItemImpl, ItemMacro, ItemMod, + ItemStruct, ItemTrait, TraitItem, TraitItemMethod, }; use turbo_tasks_macros_shared::{ - get_function_ident, get_impl_function_ident, get_ref_ident, get_register_trait_methods_ident, - get_register_value_type_ident, get_trait_default_impl_function_ident, - get_trait_impl_function_ident, get_trait_type_ident, ValueTraitArguments, + get_impl_function_ident, get_native_function_ident, get_path_ident, + get_register_trait_methods_ident, get_register_value_type_ident, + get_trait_default_impl_function_ident, get_trait_impl_function_ident, get_trait_type_ident, + get_type_ident, PrimitiveInput, ValueTraitArguments, }; pub fn generate_register() { @@ -201,6 +204,7 @@ impl<'a> RegisterContext<'a> { Item::Mod(mod_item) => self.process_mod(mod_item), Item::Struct(struct_item) => self.process_struct(struct_item), Item::Trait(trait_item) => self.process_trait(trait_item), + Item::Macro(macro_item) => self.process_macro(macro_item), _ => Ok(()), } } @@ -215,7 +219,7 @@ impl<'a> RegisterContext<'a> { fn process_fn(&mut self, fn_item: ItemFn) -> Result<()> { if has_attribute(&fn_item.attrs, "function") { let ident = &fn_item.sig.ident; - let type_ident = get_function_ident(ident); + let type_ident = get_native_function_ident(ident); self.register(type_ident, self.get_global_name(&[ident]))?; } @@ -224,51 +228,36 @@ impl<'a> RegisterContext<'a> { fn process_impl(&mut self, impl_item: ItemImpl) -> Result<()> { if has_attribute(&impl_item.attrs, "value_impl") { - if let Type::Path(TypePath { - qself: None, - path: Path { segments, .. }, - }) = &*impl_item.self_ty - { - if segments.len() == 1 { - if let Some(PathSegment { - arguments: PathArguments::None, - ident: struct_ident, - }) = segments.first() - { - let trait_ident = - impl_item.trait_.as_ref().and_then(|(_, trait_path, _)| { - trait_path.segments.last().map(|s| &s.ident) - }); - if let Some(trait_ident) = trait_ident { - self.add_value_trait(struct_ident, trait_ident); - } - - for item in impl_item.items { - if let syn::ImplItem::Method(method_item) = item { - // TODO: if method_item.attrs.iter().any(|a| - // is_attribute(a, - // "function")) { - let method_ident = &method_item.sig.ident; - let function_type_ident = if let Some(trait_ident) = trait_ident { - get_trait_impl_function_ident( - struct_ident, - trait_ident, - method_ident, - ) - } else { - get_impl_function_ident(struct_ident, method_ident) - }; - - let global_name = if let Some(trait_ident) = trait_ident { - self.get_global_name(&[struct_ident, trait_ident, method_ident]) - } else { - self.get_global_name(&[struct_ident, method_ident]) - }; - - self.register(function_type_ident, global_name)?; - } - } - } + let struct_ident = get_type_ident(&impl_item.self_ty).unwrap(); + + let trait_ident = impl_item + .trait_ + .as_ref() + .map(|(_, trait_path, _)| get_path_ident(trait_path)); + + if let Some(trait_ident) = &trait_ident { + self.add_value_trait(&struct_ident, trait_ident); + } + + for item in impl_item.items { + if let syn::ImplItem::Method(method_item) = item { + // TODO: if method_item.attrs.iter().any(|a| + // is_attribute(a, + // "function")) { + let method_ident = &method_item.sig.ident; + let function_type_ident = if let Some(trait_ident) = &trait_ident { + get_trait_impl_function_ident(&struct_ident, trait_ident, method_ident) + } else { + get_impl_function_ident(&struct_ident, method_ident) + }; + + let global_name = if let Some(trait_ident) = &trait_ident { + self.get_global_name(&[&struct_ident, trait_ident, method_ident]) + } else { + self.get_global_name(&[&struct_ident, method_ident]) + }; + + self.register(function_type_ident, global_name)?; } } } @@ -332,12 +321,36 @@ impl<'a> RegisterContext<'a> { let trait_args: ValueTraitArguments = parse_attr_args(attr)?.unwrap_or_default(); if trait_args.debug { - let ref_ident = get_ref_ident(trait_ident); - self.register_debug_impl(&ref_ident, DebugType::Trait)?; + self.register_debug_impl( + &get_type_ident(&parse_quote! { + Box + }) + .unwrap(), + )?; } } Ok(()) } + + fn process_macro(&mut self, macro_item: ItemMacro) -> Result<()> { + if macro_item + .mac + .path + .is_ident("__turbo_tasks_internal_primitive") + { + let input = macro_item.mac.tokens; + let input = syn::parse2::(input).unwrap(); + + let ty = input.ty; + let Some(ident) = get_type_ident(&ty) else { + return Ok(()); + }; + + self.add_value(&ident); + } + + Ok(()) + } } impl<'a> RegisterContext<'a> { @@ -365,8 +378,14 @@ impl<'a> RegisterContext<'a> { ); // register default debug impl generated by proc macro - self.register_debug_impl(ident, DebugType::Value).unwrap(); - self.add_value_trait(ident, &Ident::new("ValueDebug", ident.span())); + self.register_debug_impl(ident).unwrap(); + self.add_value_trait( + ident, + &get_type_ident(&parse_quote! { + turbo_tasks::debug::ValueDebug + }) + .unwrap(), + ); } fn add_value_trait(&mut self, ident: &Ident, trait_ident: &Ident) { @@ -398,23 +417,18 @@ impl<'a> RegisterContext<'a> { } /// Declares the default derive of the `ValueDebug` trait. - fn register_debug_impl(&mut self, ident: &Ident, dbg_ty: DebugType) -> std::fmt::Result { + fn register_debug_impl(&mut self, ident: &Ident) -> std::fmt::Result { for fn_name in ["dbg", "dbg_depth"] { let fn_ident = Ident::new(fn_name, ident.span()); + let trait_ident = get_type_ident(&parse_quote! { + turbo_tasks::debug::ValueDebug + }) + .unwrap(); - let (impl_fn_ident, global_name) = match dbg_ty { - DebugType::Value => { - let trait_ident = Ident::new("ValueDebug", ident.span()); - ( - get_trait_impl_function_ident(ident, &trait_ident, &fn_ident), - self.get_global_name(&[ident, &trait_ident, &fn_ident]), - ) - } - DebugType::Trait => ( - get_impl_function_ident(ident, &fn_ident), - self.get_global_name(&[ident, &fn_ident]), - ), - }; + let (impl_fn_ident, global_name) = ( + get_trait_impl_function_ident(ident, &trait_ident, &fn_ident), + self.get_global_name(&[ident, &trait_ident, &fn_ident]), + ); self.register(impl_fn_ident, global_name)?; } @@ -423,14 +437,6 @@ impl<'a> RegisterContext<'a> { } } -// FIXME: traits currently don't implement the trait directly because -// `turbo_tasks::value_impl` would try to wrap the TraitVc in another Vc -// (TraitVcVc). -enum DebugType { - Value, - Trait, -} - fn has_attribute(attrs: &[Attribute], name: &str) -> bool { attrs.iter().any(|a| is_attribute(a, name)) } diff --git a/crates/turbo-tasks-bytes/src/lib.rs b/crates/turbo-tasks-bytes/src/lib.rs index 3ea6822c8cc5bb..8e995b64648850 100644 --- a/crates/turbo-tasks-bytes/src/lib.rs +++ b/crates/turbo-tasks-bytes/src/lib.rs @@ -1,8 +1,11 @@ +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] + pub mod bytes; pub mod stream; pub use crate::{ - bytes::{Bytes, BytesVc}, + bytes::Bytes, stream::{Stream, StreamRead}, }; diff --git a/crates/turbo-tasks-env/src/command_line.rs b/crates/turbo-tasks-env/src/command_line.rs index 0eec95c40621f2..6f98b514dcd7f5 100644 --- a/crates/turbo-tasks-env/src/command_line.rs +++ b/crates/turbo-tasks-env/src/command_line.rs @@ -1,17 +1,18 @@ use std::env; use indexmap::IndexMap; +use turbo_tasks::Vc; -use crate::{EnvMapVc, ProcessEnv, ProcessEnvVc, GLOBAL_ENV_LOCK}; +use crate::{EnvMap, ProcessEnv, GLOBAL_ENV_LOCK}; /// Load the environment variables defined via command line. #[turbo_tasks::value] pub struct CommandLineProcessEnv; #[turbo_tasks::value_impl] -impl CommandLineProcessEnvVc { +impl CommandLineProcessEnv { #[turbo_tasks::function] - pub fn new() -> Self { + pub fn new() -> Vc { CommandLineProcessEnv.cell() } } @@ -25,7 +26,7 @@ fn env_snapshot() -> IndexMap { #[turbo_tasks::value_impl] impl ProcessEnv for CommandLineProcessEnv { #[turbo_tasks::function] - fn read_all(&self) -> EnvMapVc { - EnvMapVc::cell(env_snapshot()) + fn read_all(&self) -> Vc { + Vc::cell(env_snapshot()) } } diff --git a/crates/turbo-tasks-env/src/custom.rs b/crates/turbo-tasks-env/src/custom.rs index 5c6400705210b5..f24f63e499fadc 100644 --- a/crates/turbo-tasks-env/src/custom.rs +++ b/crates/turbo-tasks-env/src/custom.rs @@ -1,20 +1,20 @@ use anyhow::Result; -use turbo_tasks::primitives::OptionStringVc; +use turbo_tasks::Vc; -use crate::{case_insensitive_read, EnvMapVc, ProcessEnv, ProcessEnvVc}; +use crate::{case_insensitive_read, EnvMap, ProcessEnv}; /// Allows providing any custom env values that you'd like, deferring the prior /// envs if a key is not overridden. #[turbo_tasks::value] pub struct CustomProcessEnv { - prior: ProcessEnvVc, - custom: EnvMapVc, + prior: Vc>, + custom: Vc, } #[turbo_tasks::value_impl] -impl CustomProcessEnvVc { +impl CustomProcessEnv { #[turbo_tasks::function] - pub fn new(prior: ProcessEnvVc, custom: EnvMapVc) -> Self { + pub fn new(prior: Vc>, custom: Vc) -> Vc { CustomProcessEnv { prior, custom }.cell() } } @@ -22,18 +22,18 @@ impl CustomProcessEnvVc { #[turbo_tasks::value_impl] impl ProcessEnv for CustomProcessEnv { #[turbo_tasks::function] - async fn read_all(&self) -> Result { + async fn read_all(&self) -> Result> { let prior = self.prior.read_all().await?; let custom = self.custom.await?; let mut extended = prior.clone_value(); extended.extend(custom.clone_value()); - Ok(EnvMapVc::cell(extended)) + Ok(Vc::cell(extended)) } #[turbo_tasks::function] - async fn read(&self, name: &str) -> Result { - let custom = case_insensitive_read(self.custom, name); + async fn read(&self, name: String) -> Result>> { + let custom = case_insensitive_read(self.custom, name.clone()); match &*custom.await? { Some(_) => Ok(custom), None => Ok(self.prior.read(name)), diff --git a/crates/turbo-tasks-env/src/dotenv.rs b/crates/turbo-tasks-env/src/dotenv.rs index 11516d1b61d487..03dd71e9da5caa 100644 --- a/crates/turbo-tasks-env/src/dotenv.rs +++ b/crates/turbo-tasks-env/src/dotenv.rs @@ -2,38 +2,38 @@ use std::{env, sync::MutexGuard}; use anyhow::{anyhow, Context, Result}; use indexmap::IndexMap; -use turbo_tasks::ValueToString; -use turbo_tasks_fs::{FileContent, FileSystemPathVc}; +use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks_fs::{FileContent, FileSystemPath}; -use crate::{EnvMapVc, ProcessEnv, ProcessEnvVc, GLOBAL_ENV_LOCK}; +use crate::{EnvMap, ProcessEnv, GLOBAL_ENV_LOCK}; /// Load the environment variables defined via a dotenv file, with an /// optional prior state that we can lookup already defined variables /// from. #[turbo_tasks::value] pub struct DotenvProcessEnv { - prior: Option, - path: FileSystemPathVc, + prior: Option>>, + path: Vc, } #[turbo_tasks::value_impl] -impl DotenvProcessEnvVc { +impl DotenvProcessEnv { #[turbo_tasks::function] - pub fn new(prior: Option, path: FileSystemPathVc) -> Self { + pub fn new(prior: Option>>, path: Vc) -> Vc { DotenvProcessEnv { prior, path }.cell() } #[turbo_tasks::function] - pub async fn read_prior(self) -> Result { + pub async fn read_prior(self: Vc) -> Result> { let this = self.await?; match this.prior { - None => Ok(EnvMapVc::empty()), + None => Ok(EnvMap::empty()), Some(p) => Ok(p.read_all()), } } #[turbo_tasks::function] - pub async fn read_all_with_prior(self, prior: EnvMapVc) -> Result { + pub async fn read_all_with_prior(self: Vc, prior: Vc) -> Result> { let this = self.await?; let prior = prior.await?; @@ -67,9 +67,9 @@ impl DotenvProcessEnvVc { )); } - Ok(EnvMapVc::cell(vars)) + Ok(Vc::cell(vars)) } else { - Ok(EnvMapVc::cell(prior.clone_value())) + Ok(Vc::cell(prior.clone_value())) } } } @@ -77,9 +77,9 @@ impl DotenvProcessEnvVc { #[turbo_tasks::value_impl] impl ProcessEnv for DotenvProcessEnv { #[turbo_tasks::function] - async fn read_all(self_vc: DotenvProcessEnvVc) -> Result { - let prior = self_vc.read_prior(); - Ok(self_vc.read_all_with_prior(prior)) + async fn read_all(self: Vc) -> Result> { + let prior = self.read_prior(); + Ok(self.read_all_with_prior(prior)) } } diff --git a/crates/turbo-tasks-env/src/filter.rs b/crates/turbo-tasks-env/src/filter.rs index 16fd71edb64fa0..bd8fb1f86abe80 100644 --- a/crates/turbo-tasks-env/src/filter.rs +++ b/crates/turbo-tasks-env/src/filter.rs @@ -1,21 +1,21 @@ use anyhow::Result; use indexmap::IndexMap; -use turbo_tasks::primitives::OptionStringVc; +use turbo_tasks::Vc; -use crate::{EnvMapVc, ProcessEnv, ProcessEnvVc}; +use crate::{EnvMap, ProcessEnv}; /// Filters env variables by some prefix. Casing of the env vars is ignored for /// filtering. #[turbo_tasks::value] pub struct FilterProcessEnv { - prior: ProcessEnvVc, + prior: Vc>, filters: Vec, } #[turbo_tasks::value_impl] -impl FilterProcessEnvVc { +impl FilterProcessEnv { #[turbo_tasks::function] - pub fn new(prior: ProcessEnvVc, filters: Vec) -> Self { + pub fn new(prior: Vc>, filters: Vec) -> Vc { FilterProcessEnv { prior, filters: filters.into_iter().map(|f| f.to_uppercase()).collect(), @@ -27,7 +27,7 @@ impl FilterProcessEnvVc { #[turbo_tasks::value_impl] impl ProcessEnv for FilterProcessEnv { #[turbo_tasks::function] - async fn read_all(&self) -> Result { + async fn read_all(&self) -> Result> { let prior = self.prior.read_all().await?; let mut filtered = IndexMap::new(); for (key, value) in &*prior { @@ -39,16 +39,16 @@ impl ProcessEnv for FilterProcessEnv { } } } - Ok(EnvMapVc::cell(filtered)) + Ok(Vc::cell(filtered)) } #[turbo_tasks::function] - fn read(&self, name: &str) -> OptionStringVc { + fn read(&self, name: String) -> Vc> { for filter in &self.filters { if name.to_uppercase().starts_with(filter) { return self.prior.read(name); } } - OptionStringVc::cell(None) + Vc::cell(None) } } diff --git a/crates/turbo-tasks-env/src/lib.rs b/crates/turbo-tasks-env/src/lib.rs index fbe06368e75f6a..f793ed06436d9a 100644 --- a/crates/turbo-tasks-env/src/lib.rs +++ b/crates/turbo-tasks-env/src/lib.rs @@ -1,4 +1,5 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] mod command_line; mod custom; @@ -9,20 +10,20 @@ use std::{env, sync::Mutex}; use anyhow::Result; use indexmap::IndexMap; -use turbo_tasks::primitives::OptionStringVc; +use turbo_tasks::Vc; pub use self::{ - command_line::CommandLineProcessEnvVc, custom::CustomProcessEnvVc, dotenv::DotenvProcessEnvVc, - filter::FilterProcessEnvVc, + command_line::CommandLineProcessEnv, custom::CustomProcessEnv, dotenv::DotenvProcessEnv, + filter::FilterProcessEnv, }; #[turbo_tasks::value(transparent)] pub struct EnvMap(#[turbo_tasks(trace_ignore)] IndexMap); #[turbo_tasks::value_impl] -impl EnvMapVc { +impl EnvMap { #[turbo_tasks::function] - pub fn empty() -> Self { + pub fn empty() -> Vc { EnvMap(IndexMap::new()).cell() } } @@ -30,13 +31,13 @@ impl EnvMapVc { #[turbo_tasks::value_impl] impl ProcessEnv for EnvMap { #[turbo_tasks::function] - async fn read_all(self_vc: EnvMapVc) -> Result { - Ok(self_vc) + async fn read_all(self: Vc) -> Result> { + Ok(self) } #[turbo_tasks::function] - async fn read(self_vc: EnvMapVc, name: &str) -> OptionStringVc { - case_insensitive_read(self_vc, name) + async fn read(self: Vc, name: String) -> Vc> { + case_insensitive_read(self, name) } } @@ -48,17 +49,17 @@ pub trait ProcessEnv { // Instead we should use only `read_prefix` to read all env vars with a specific // prefix. /// Reads all env variables into a Map - fn read_all(&self) -> EnvMapVc; + fn read_all(self: Vc) -> Vc; /// Reads a single env variable. Ignores casing. - fn read(&self, name: &str) -> OptionStringVc { + fn read(self: Vc, name: String) -> Vc> { case_insensitive_read(self.read_all(), name) } } #[turbo_tasks::function] -pub async fn case_insensitive_read(map: EnvMapVc, name: &str) -> Result { - Ok(OptionStringVc::cell( +pub async fn case_insensitive_read(map: Vc, name: String) -> Result>> { + Ok(Vc::cell( to_uppercase_map(map) .await? .get(&name.to_uppercase()) @@ -67,13 +68,13 @@ pub async fn case_insensitive_read(map: EnvMapVc, name: &str) -> Result Result { +async fn to_uppercase_map(map: Vc) -> Result> { let map = &*map.await?; let mut new = IndexMap::with_capacity(map.len()); for (k, v) in map { new.insert(k.to_uppercase(), v.clone()); } - Ok(EnvMapVc::cell(new)) + Ok(Vc::cell(new)) } pub static GLOBAL_ENV_LOCK: Mutex<()> = Mutex::new(()); diff --git a/crates/turbo-tasks-fetch/src/lib.rs b/crates/turbo-tasks-fetch/src/lib.rs index 4c7cf1d0c83b16..70b089256f233a 100644 --- a/crates/turbo-tasks-fetch/src/lib.rs +++ b/crates/turbo-tasks-fetch/src/lib.rs @@ -1,9 +1,11 @@ #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use anyhow::Result; -use turbo_tasks::primitives::{OptionStringVc, StringVc}; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::issue::{Issue, IssueSeverityVc, IssueVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueSeverity}; pub fn register() { turbo_tasks::register(); @@ -13,13 +15,13 @@ pub fn register() { } #[turbo_tasks::value(transparent)] -pub struct FetchResult(Result); +pub struct FetchResult(Result, Vc>); #[turbo_tasks::value(shared)] #[derive(Debug)] pub struct HttpResponse { pub status: u16, - pub body: HttpResponseBodyVc, + pub body: Vc, } #[turbo_tasks::value(shared)] @@ -27,16 +29,16 @@ pub struct HttpResponse { pub struct HttpResponseBody(pub Vec); #[turbo_tasks::value_impl] -impl HttpResponseBodyVc { +impl HttpResponseBody { #[turbo_tasks::function] - pub async fn to_string(self) -> Result { + pub async fn to_string(self: Vc) -> Result> { let this = &*self.await?; - Ok(StringVc::cell(std::str::from_utf8(&this.0)?.to_owned())) + Ok(Vc::cell(std::str::from_utf8(&this.0)?.to_owned())) } } #[turbo_tasks::function] -pub async fn fetch(url: StringVc, user_agent: OptionStringVc) -> Result { +pub async fn fetch(url: Vc, user_agent: Vc>) -> Result> { let url = &*url.await?; let user_agent = &*user_agent.await?; let client = reqwest::Client::new(); @@ -52,16 +54,15 @@ pub async fn fetch(url: StringVc, user_agent: OptionStringVc) -> Result Ok(FetchResultVc::cell(Err(FetchError::from_reqwest_error( - &err, url, - ) - .cell()))), + Err(err) => Ok(Vc::cell(Err( + FetchError::from_reqwest_error(&err, url).cell() + ))), } } @@ -76,9 +77,9 @@ pub enum FetchErrorKind { #[turbo_tasks::value(shared)] pub struct FetchError { - pub url: StringVc, - pub kind: FetchErrorKindVc, - pub detail: StringVc, + pub url: Vc, + pub kind: Vc, + pub detail: Vc, } impl FetchError { @@ -94,21 +95,21 @@ impl FetchError { }; FetchError { - detail: StringVc::cell(error.to_string()), - url: StringVc::cell(url.to_owned()), + detail: Vc::cell(error.to_string()), + url: Vc::cell(url.to_owned()), kind: kind.into(), } } } #[turbo_tasks::value_impl] -impl FetchErrorVc { +impl FetchError { #[turbo_tasks::function] pub async fn to_issue( - self, - severity: IssueSeverityVc, - context: FileSystemPathVc, - ) -> Result { + self: Vc, + severity: Vc, + context: Vc, + ) -> Result> { let this = &*self.await?; Ok(FetchIssue { context, @@ -123,41 +124,41 @@ impl FetchErrorVc { #[turbo_tasks::value(shared)] pub struct FetchIssue { - pub context: FileSystemPathVc, - pub severity: IssueSeverityVc, - pub url: StringVc, - pub kind: FetchErrorKindVc, - pub detail: StringVc, + pub context: Vc, + pub severity: Vc, + pub url: Vc, + pub kind: Vc, + pub detail: Vc, } #[turbo_tasks::value_impl] impl Issue for FetchIssue { #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Error while requesting resource".to_string()) + fn title(&self) -> Vc { + Vc::cell("Error while requesting resource".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("fetch".to_string()) + fn category(&self) -> Vc { + Vc::cell("fetch".to_string()) } #[turbo_tasks::function] - async fn description(&self) -> Result { + async fn description(&self) -> Result> { let url = &*self.url.await?; let kind = &*self.kind.await?; - Ok(StringVc::cell(match kind { + Ok(Vc::cell(match kind { FetchErrorKind::Connect => format!( "There was an issue establishing a connection while requesting {}.", url @@ -174,7 +175,7 @@ impl Issue for FetchIssue { } #[turbo_tasks::function] - fn detail(&self) -> StringVc { + fn detail(&self) -> Vc { self.detail } } diff --git a/crates/turbo-tasks-fetch/tests/fetch.rs b/crates/turbo-tasks-fetch/tests/fetch.rs index 5ae4427ebcfa2f..69d880e3e67512 100644 --- a/crates/turbo-tasks-fetch/tests/fetch.rs +++ b/crates/turbo-tasks-fetch/tests/fetch.rs @@ -1,8 +1,8 @@ #![cfg(test)] -use turbo_tasks::primitives::{OptionStringVc, StringVc}; +use turbo_tasks::Vc; use turbo_tasks_fetch::{fetch, register, FetchErrorKind}; -use turbo_tasks_fs::{DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath}; use turbo_tasks_testing::{register, run}; use turbopack_core::issue::{Issue, IssueSeverity}; @@ -21,7 +21,7 @@ async fn basic_get() { }); - let result = &*fetch(StringVc::cell(server.url("/foo.woff")), OptionStringVc::cell(None)).await?; + let result = &*fetch(Vc::cell(server.url("/foo.woff")), Vc::cell(None)).await?; resource_mock.assert(); match result { @@ -47,7 +47,7 @@ async fn sends_user_agent() { .body("responsebody"); }); - let result = &*fetch(StringVc::cell(server.url("/foo.woff")), OptionStringVc::cell(Some("foo".to_owned()))).await?; + let result = &*fetch(Vc::cell(server.url("/foo.woff")), Vc::cell(Some("foo".to_owned()))).await?; resource_mock.assert(); let Ok(response) = result else { @@ -74,8 +74,8 @@ async fn invalidation_does_not_invalidate() { .body("responsebody"); }); - let url = StringVc::cell(server.url("/foo.woff")); - let user_agent = OptionStringVc::cell(Some("foo".to_owned())); + let url = Vc::cell(server.url("/foo.woff")); + let user_agent = Vc::cell(Some("foo".to_owned())); let result = &*fetch(url, user_agent).await?; resource_mock.assert(); @@ -104,7 +104,7 @@ async fn errors_on_failed_connection() { register(); let url = "https://doesnotexist/foo.woff"; - let result = &*fetch(StringVc::cell(url.to_owned()), OptionStringVc::cell(None)).await?; + let result = &*fetch(Vc::cell(url.to_owned()), Vc::cell(None)).await?; let Err(err_vc) = result else { panic!() }; @@ -126,7 +126,7 @@ async fn errors_on_404() { let server = httpmock::MockServer::start(); let resource_url = server.url("/"); - let result = &*fetch(StringVc::cell(resource_url.clone()), OptionStringVc::cell(None)).await?; + let result = &*fetch(Vc::cell(resource_url.clone()), Vc::cell(None)).await?; let Err(err_vc) = result else { panic!() }; @@ -141,10 +141,6 @@ async fn errors_on_404() { } } -fn get_issue_context() -> FileSystemPathVc { - std::convert::Into::::into(DiskFileSystemVc::new( - "root".to_owned(), - "/".to_owned(), - )) - .root() +fn get_issue_context() -> Vc { + DiskFileSystem::new("root".to_owned(), "/".to_owned()).root() } diff --git a/crates/turbo-tasks-fs/examples/hash_directory.rs b/crates/turbo-tasks-fs/examples/hash_directory.rs index c1b24e0d783a6c..2ba48edb227aa8 100644 --- a/crates/turbo-tasks-fs/examples/hash_directory.rs +++ b/crates/turbo-tasks-fs/examples/hash_directory.rs @@ -1,6 +1,4 @@ #![feature(trivial_bounds)] -#![feature(once_cell)] -#![feature(min_specialization)] use std::{ collections::BTreeMap, @@ -11,10 +9,10 @@ use std::{ use anyhow::Result; use sha2::{Digest, Sha256}; -use turbo_tasks::{primitives::StringVc, util::FormatDuration, NothingVc, TurboTasks, UpdateInfo}; +use turbo_tasks::{unit, util::FormatDuration, TurboTasks, UpdateInfo, Vc}; use turbo_tasks_fs::{ - register, DirectoryContent, DirectoryEntry, DiskFileSystemVc, FileContent, FileSystem, - FileSystemPathVc, FileSystemVc, + register, DirectoryContent, DirectoryEntry, DiskFileSystem, FileContent, FileSystem, + FileSystemPath, }; use turbo_tasks_memory::MemoryBackend; @@ -32,15 +30,15 @@ async fn main() -> Result<()> { let task = tt.spawn_root_task(|| { Box::pin(async { let root = current_dir().unwrap().to_str().unwrap().to_string(); - let disk_fs = DiskFileSystemVc::new("project".to_string(), root); + let disk_fs = DiskFileSystem::new("project".to_string(), root); disk_fs.await?.start_watching()?; // Smart Pointer cast - let fs: FileSystemVc = disk_fs.into(); - let input = fs.root().join("demo"); + let fs: Vc> = Vc::upcast(disk_fs); + let input = fs.root().join("demo".to_string()); let dir_hash = hash_directory(input); print_hash(dir_hash); - Ok(NothingVc::new().into()) + Ok(unit().node) }) }); tt.wait_task_completion(task, true).await.unwrap(); @@ -57,17 +55,17 @@ async fn main() -> Result<()> { } #[turbo_tasks::function] -async fn print_hash(dir_hash: StringVc) -> Result<()> { +async fn print_hash(dir_hash: Vc) -> Result<()> { println!("DIR HASH: {}", dir_hash.await?.as_str()); Ok(()) } -async fn filename(path: FileSystemPathVc) -> Result { +async fn filename(path: Vc) -> Result { Ok(path.await?.path.split('/').last().unwrap().to_string()) } #[turbo_tasks::function] -async fn hash_directory(directory: FileSystemPathVc) -> Result { +async fn hash_directory(directory: Vc) -> Result> { let dir_path = &directory.await?.path; let content = directory.read_dir(); let mut hashes = BTreeMap::new(); @@ -103,18 +101,18 @@ async fn hash_directory(directory: FileSystemPathVc) -> Result { } #[turbo_tasks::function] -async fn hash_file(file_path: FileSystemPathVc) -> Result { +async fn hash_file(file_path: Vc) -> Result> { let content = file_path.read().await?; Ok(match &*content { FileContent::Content(file) => hash_content(&mut file.read()), FileContent::NotFound => { // report error - StringVc::cell("".to_string()) + Vc::cell("".to_string()) } }) } -fn hash_content(content: &mut R) -> StringVc { +fn hash_content(content: &mut R) -> Vc { let mut hasher = Sha256::new(); let mut buf = [0; 1024]; while let Ok(size) = content.read(&mut buf) { @@ -122,5 +120,5 @@ fn hash_content(content: &mut R) -> StringVc { } let result = format!("{:x}", hasher.finalize()); - StringVc::cell(result) + Vc::cell(result) } diff --git a/crates/turbo-tasks-fs/examples/hash_glob.rs b/crates/turbo-tasks-fs/examples/hash_glob.rs index 0ca597ed150511..00d6f784871eaa 100644 --- a/crates/turbo-tasks-fs/examples/hash_glob.rs +++ b/crates/turbo-tasks-fs/examples/hash_glob.rs @@ -1,6 +1,4 @@ #![feature(trivial_bounds)] -#![feature(once_cell)] -#![feature(min_specialization)] use std::{ collections::BTreeMap, @@ -11,10 +9,10 @@ use std::{ use anyhow::Result; use sha2::{Digest, Sha256}; -use turbo_tasks::{primitives::StringVc, util::FormatDuration, NothingVc, TurboTasks, UpdateInfo}; +use turbo_tasks::{unit, util::FormatDuration, TurboTasks, UpdateInfo, Vc}; use turbo_tasks_fs::{ - glob::GlobVc, register, DirectoryEntry, DiskFileSystemVc, FileContent, FileSystem, - FileSystemPathVc, FileSystemVc, ReadGlobResultVc, + glob::Glob, register, DirectoryEntry, DiskFileSystem, FileContent, FileSystem, FileSystemPath, + ReadGlobResult, }; use turbo_tasks_memory::MemoryBackend; @@ -29,17 +27,17 @@ async fn main() -> Result<()> { let task = tt.spawn_root_task(|| { Box::pin(async { let root = current_dir().unwrap().to_str().unwrap().to_string(); - let disk_fs = DiskFileSystemVc::new("project".to_string(), root); + let disk_fs = DiskFileSystem::new("project".to_string(), root); disk_fs.await?.start_watching()?; // Smart Pointer cast - let fs: FileSystemVc = disk_fs.into(); - let input = fs.root().join("crates"); - let glob = GlobVc::new("**/*.rs"); + let fs: Vc> = Vc::upcast(disk_fs); + let input = fs.root().join("crates".to_string()); + let glob = Glob::new("**/*.rs".to_string()); let glob_result = input.read_glob(glob, true); let dir_hash = hash_glob_result(glob_result); print_hash(dir_hash); - Ok(NothingVc::new().into()) + Ok(unit().node) }) }); tt.wait_task_completion(task, true).await.unwrap(); @@ -56,18 +54,18 @@ async fn main() -> Result<()> { } #[turbo_tasks::function] -pub fn empty_string() -> StringVc { - StringVc::cell("".to_string()) +pub fn empty_string() -> Vc { + Vc::cell("".to_string()) } #[turbo_tasks::function] -async fn print_hash(dir_hash: StringVc) -> Result<()> { +async fn print_hash(dir_hash: Vc) -> Result<()> { println!("DIR HASH: {}", dir_hash.await?.as_str()); Ok(()) } #[turbo_tasks::function] -async fn hash_glob_result(result: ReadGlobResultVc) -> Result { +async fn hash_glob_result(result: Vc) -> Result> { let result = result.await?; let mut hashes = BTreeMap::new(); for (name, entry) in result.results.iter() { @@ -95,18 +93,18 @@ async fn hash_glob_result(result: ReadGlobResultVc) -> Result { } #[turbo_tasks::function] -async fn hash_file(file_path: FileSystemPathVc) -> Result { +async fn hash_file(file_path: Vc) -> Result> { let content = file_path.read().await?; Ok(match &*content { FileContent::Content(file) => hash_content(&mut file.read()), FileContent::NotFound => { // report error - StringVc::cell("".to_string()) + Vc::cell("".to_string()) } }) } -fn hash_content(content: &mut R) -> StringVc { +fn hash_content(content: &mut R) -> Vc { let mut hasher = Sha256::new(); let mut buf = [0; 1024]; while let Ok(size) = content.read(&mut buf) { @@ -114,5 +112,5 @@ fn hash_content(content: &mut R) -> StringVc { } let result = format!("{:x}", hasher.finalize()); - StringVc::cell(result) + Vc::cell(result) } diff --git a/crates/turbo-tasks-fs/src/attach.rs b/crates/turbo-tasks-fs/src/attach.rs index 4c9dda72ba6f4c..7ae3ba07b5cc12 100644 --- a/crates/turbo-tasks-fs/src/attach.rs +++ b/crates/turbo-tasks-fs/src/attach.rs @@ -1,10 +1,10 @@ use anyhow::{bail, Result}; use auto_hash_map::AutoMap; -use turbo_tasks::{primitives::StringVc, CompletionVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{Completion, ValueToString, Vc}; use crate::{ - DirectoryContent, DirectoryContentVc, DirectoryEntry, FileContentVc, FileMetaVc, FileSystem, - FileSystemPathVc, FileSystemVc, LinkContentVc, + DirectoryContent, DirectoryEntry, FileContent, FileMeta, FileSystem, FileSystemPath, + LinkContent, }; /// A wrapper [FileSystem] which attaches a child [FileSystem] as a @@ -13,19 +13,22 @@ use crate::{ /// Caveat: The `child_path` itself is not visible as a directory entry. #[turbo_tasks::value] pub struct AttachedFileSystem { - root_fs: FileSystemVc, + root_fs: Vc>, // we turn this into a string because creating a FileSystemPath requires the filesystem which // we are creating (circular reference) child_path: String, - child_fs: FileSystemVc, + child_fs: Vc>, } #[turbo_tasks::value_impl] -impl AttachedFileSystemVc { +impl AttachedFileSystem { /// Create a new [AttachedFileSystem] which will have the `child_fs` as /// an invisible subdirectory of the `child_path` #[turbo_tasks::function] - pub async fn new(child_path: FileSystemPathVc, child_fs: FileSystemVc) -> Result { + pub async fn new( + child_path: Vc, + child_fs: Vc>, + ) -> Result> { let child_path = child_path.await?; Ok(AttachedFileSystem { @@ -36,30 +39,34 @@ impl AttachedFileSystemVc { .cell()) } - /// Converts the given [FileSystemPathVc] to a path in this [FileSystem]. + /// Converts the given [Vc] to a path in this [FileSystem]. /// /// The given path has to be inside of the root [FileSystem], the child /// [FileSystem] or this [AttachedFileSystem]. #[turbo_tasks::function] pub async fn convert_path( - self, - contained_path_vc: FileSystemPathVc, - ) -> Result { + self: Vc, + contained_path_vc: Vc, + ) -> Result> { let contained_path = contained_path_vc.await?; - let self_fs: FileSystemVc = self.into(); + let self_fs: Vc> = Vc::upcast(self); let this = self.await?; match contained_path.fs { // already on this filesystem fs if fs == self_fs => Ok(contained_path_vc), // in the root filesystem, just need to rebase on this filesystem - fs if fs == this.root_fs => Ok(self.root().resolve().await?.join(&contained_path.path)), + fs if fs == this.root_fs => Ok(self + .root() + .resolve() + .await? + .join(contained_path.path.clone())), // in the child filesystem, so we expand to the full path by appending to child_path fs if fs == this.child_fs => Ok(self .child_path() .resolve() .await? - .join(&contained_path.path)), + .join(contained_path.path.clone())), _ => bail!( "path {} not part of self, the root fs or the child fs", contained_path_vc.to_string().await? @@ -67,20 +74,27 @@ impl AttachedFileSystemVc { } } - /// Constructs a [FileSystemPathVc] of the attachment point referencing this - /// [AttachedFileSystem] + /// Constructs a [Vc] of the attachment point referencing + /// this [AttachedFileSystem] #[turbo_tasks::function] - async fn child_path(self) -> Result { - Ok(self.root().resolve().await?.join(&self.await?.child_path)) + async fn child_path(self: Vc) -> Result> { + Ok(self + .root() + .resolve() + .await? + .join(self.await?.child_path.clone())) } /// Resolves the local path of the root or child filesystem from a path /// on the [AttachedFileSystem] #[turbo_tasks::function] - pub async fn get_inner_fs_path(self, path: FileSystemPathVc) -> Result { + pub async fn get_inner_fs_path( + self: Vc, + path: Vc, + ) -> Result> { let this = self.await?; let path = path.await?; - let self_fs: FileSystemVc = self.into(); + let self_fs: Vc> = Vc::upcast(self); if path.fs != self_fs { bail!( @@ -92,9 +106,13 @@ impl AttachedFileSystemVc { let child_path = self.child_path().await?; Ok(if let Some(inner_path) = child_path.get_path_to(&path) { - this.child_fs.root().resolve().await?.join(inner_path) + this.child_fs + .root() + .resolve() + .await? + .join(inner_path.to_string()) } else { - this.root_fs.root().resolve().await?.join(&path.path) + this.root_fs.root().resolve().await?.join(path.path.clone()) }) } } @@ -102,24 +120,21 @@ impl AttachedFileSystemVc { #[turbo_tasks::value_impl] impl FileSystem for AttachedFileSystem { #[turbo_tasks::function] - fn read(self_vc: AttachedFileSystemVc, path: FileSystemPathVc) -> FileContentVc { - self_vc.get_inner_fs_path(path).read() + fn read(self: Vc, path: Vc) -> Vc { + self.get_inner_fs_path(path).read() } #[turbo_tasks::function] - fn read_link(self_vc: AttachedFileSystemVc, path: FileSystemPathVc) -> LinkContentVc { - self_vc.get_inner_fs_path(path).read_link() + fn read_link(self: Vc, path: Vc) -> Vc { + self.get_inner_fs_path(path).read_link() } #[turbo_tasks::function] - async fn read_dir( - self_vc: AttachedFileSystemVc, - path: FileSystemPathVc, - ) -> Result { - let dir_content = self_vc.get_inner_fs_path(path).read_dir().await?; + async fn read_dir(self: Vc, path: Vc) -> Result> { + let dir_content = self.get_inner_fs_path(path).read_dir().await?; let entries = match &*dir_content { DirectoryContent::Entries(e) => e, - DirectoryContent::NotFound => return Ok(DirectoryContentVc::not_found()), + DirectoryContent::NotFound => return Ok(DirectoryContent::not_found()), }; let mut converted_entries = AutoMap::with_capacity(entries.len()); @@ -127,53 +142,49 @@ impl FileSystem for AttachedFileSystem { use DirectoryEntry::*; let entry = match *entry { - File(path) => File(self_vc.convert_path(path)), - Directory(path) => Directory(self_vc.convert_path(path)), - Symlink(path) => Symlink(self_vc.convert_path(path)), - Other(path) => Other(self_vc.convert_path(path)), + File(path) => File(self.convert_path(path)), + Directory(path) => Directory(self.convert_path(path)), + Symlink(path) => Symlink(self.convert_path(path)), + Other(path) => Other(self.convert_path(path)), Error => Error, }; converted_entries.insert(name.clone(), entry); } - Ok(DirectoryContentVc::new(converted_entries)) + Ok(DirectoryContent::new(converted_entries)) } #[turbo_tasks::function] - fn track(self_vc: AttachedFileSystemVc, path: FileSystemPathVc) -> CompletionVc { - self_vc.get_inner_fs_path(path).track() + fn track(self: Vc, path: Vc) -> Vc { + self.get_inner_fs_path(path).track() } #[turbo_tasks::function] - fn write( - self_vc: AttachedFileSystemVc, - path: FileSystemPathVc, - content: FileContentVc, - ) -> CompletionVc { - self_vc.get_inner_fs_path(path).write(content) + fn write(self: Vc, path: Vc, content: Vc) -> Vc { + self.get_inner_fs_path(path).write(content) } #[turbo_tasks::function] fn write_link( - self_vc: AttachedFileSystemVc, - path: FileSystemPathVc, - target: LinkContentVc, - ) -> CompletionVc { - self_vc.get_inner_fs_path(path).write_link(target) + self: Vc, + path: Vc, + target: Vc, + ) -> Vc { + self.get_inner_fs_path(path).write_link(target) } #[turbo_tasks::function] - fn metadata(self_vc: AttachedFileSystemVc, path: FileSystemPathVc) -> FileMetaVc { - self_vc.get_inner_fs_path(path).metadata() + fn metadata(self: Vc, path: Vc) -> Vc { + self.get_inner_fs_path(path).metadata() } } #[turbo_tasks::value_impl] impl ValueToString for AttachedFileSystem { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "{}-with-{}", self.root_fs.to_string().await?, self.child_fs.to_string().await? diff --git a/crates/turbo-tasks-fs/src/embed/dir.rs b/crates/turbo-tasks-fs/src/embed/dir.rs index 690dbe04da8719..840719c05f3335 100644 --- a/crates/turbo-tasks-fs/src/embed/dir.rs +++ b/crates/turbo-tasks-fs/src/embed/dir.rs @@ -1,32 +1,37 @@ -pub use ::include_dir::{self, include_dir}; +pub use ::include_dir::{ + include_dir, {self}, +}; use anyhow::Result; -use turbo_tasks::TransientInstance; +use turbo_tasks::{TransientInstance, Vc}; -use crate::{embed::EmbeddedFileSystemVc, DiskFileSystemVc, FileSystemVc}; +use crate::{embed::EmbeddedFileSystem, DiskFileSystem, FileSystem}; #[turbo_tasks::function] -pub async fn directory_from_relative_path(name: &str, path: String) -> Result { - let disk_fs = DiskFileSystemVc::new(name.to_string(), path); +pub async fn directory_from_relative_path( + name: String, + path: String, +) -> Result>> { + let disk_fs = DiskFileSystem::new(name, path); disk_fs.await?.start_watching()?; - Ok(disk_fs.into()) + Ok(Vc::upcast(disk_fs)) } #[turbo_tasks::function] pub async fn directory_from_include_dir( - name: &str, + name: String, dir: TransientInstance<&'static include_dir::Dir<'static>>, -) -> Result { - Ok(EmbeddedFileSystemVc::new(name.to_string(), dir).into()) +) -> Result>> { + Ok(Vc::upcast(EmbeddedFileSystem::new(name, dir))) } -/// Returns an embedded [FileSystemVc] for the given path. +/// Returns an embedded [Vc>] for the given path. /// /// This will embed a directory's content into the binary and -/// create an [EmbeddedFileSystemVc]. +/// create an [Vc]. /// /// If you enable the `dynamic_embed_contents` feature, calling -/// the macro will return a [DiskFileSystemVc]. +/// the macro will return a [Vc]. /// /// This enables dynamic linking (and hot reloading) of embedded files/dirs. /// A binary built with `dynamic_embed_contents` enabled is **is not portable**, @@ -52,7 +57,7 @@ macro_rules! embed_directory_internal { let path = $path.replace("$CARGO_MANIFEST_DIR", env!("CARGO_MANIFEST_DIR")); - turbo_tasks_fs::embed::directory_from_relative_path($name, path) + turbo_tasks_fs::embed::directory_from_relative_path($name.to_string(), path) }}; } @@ -67,7 +72,7 @@ macro_rules! embed_directory_internal { static dir: include_dir::Dir<'static> = turbo_tasks_fs::embed::include_dir!($path); turbo_tasks_fs::embed::directory_from_include_dir( - $name, + $name.to_string(), turbo_tasks::TransientInstance::new(&dir), ) }}; diff --git a/crates/turbo-tasks-fs/src/embed/file.rs b/crates/turbo-tasks-fs/src/embed/file.rs index ad51fc6aad3595..1e48fa7b5921a3 100644 --- a/crates/turbo-tasks-fs/src/embed/file.rs +++ b/crates/turbo-tasks-fs/src/embed/file.rs @@ -2,11 +2,15 @@ use std::path::PathBuf; use anyhow::{Context, Result}; use dunce::canonicalize; +use turbo_tasks::Vc; -use crate::{DiskFileSystemVc, File, FileContentVc, FileSystem}; +use crate::{DiskFileSystem, File, FileContent, FileSystem}; #[turbo_tasks::function] -pub async fn content_from_relative_path(package_path: &str, path: &str) -> Result { +pub async fn content_from_relative_path( + package_path: String, + path: String, +) -> Result> { let package_path = PathBuf::from(package_path); let resolved_path = package_path.join(path); let resolved_path = @@ -14,18 +18,18 @@ pub async fn content_from_relative_path(package_path: &str, path: &str) -> Resul let root_path = resolved_path.parent().unwrap(); let path = resolved_path.file_name().unwrap().to_str().unwrap(); - let disk_fs = DiskFileSystemVc::new( + let disk_fs = DiskFileSystem::new( root_path.to_string_lossy().to_string(), root_path.to_string_lossy().to_string(), ); disk_fs.await?.start_watching()?; - let fs_path = disk_fs.root().join(path); + let fs_path = disk_fs.root().join(path.to_string()); Ok(fs_path.read()) } #[turbo_tasks::function] -pub async fn content_from_str(string: &str) -> Result { +pub async fn content_from_str(string: String) -> Result> { Ok(File::from(string).into()) } @@ -48,10 +52,8 @@ macro_rules! embed_file { #[macro_export] macro_rules! embed_file { ($path:expr) => { - turbo_tasks_fs::embed::content_from_str(include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/", - $path - ))) + turbo_tasks_fs::embed::content_from_str( + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/", $path)).to_string(), + ) }; } diff --git a/crates/turbo-tasks-fs/src/embed/fs.rs b/crates/turbo-tasks-fs/src/embed/fs.rs index 37e484201d209b..7e5862a71427b7 100644 --- a/crates/turbo-tasks-fs/src/embed/fs.rs +++ b/crates/turbo-tasks-fs/src/embed/fs.rs @@ -1,12 +1,10 @@ use anyhow::{bail, Result}; use include_dir::{Dir, DirEntry}; -use turbo_tasks::{ - primitives::StringVc, CompletionVc, TransientInstance, ValueToString, ValueToStringVc, -}; +use turbo_tasks::{Completion, TransientInstance, ValueToString, Vc}; use crate::{ - DirectoryContent, DirectoryContentVc, DirectoryEntry, File, FileContent, FileContentVc, - FileMeta, FileMetaVc, FileSystem, FileSystemPathVc, FileSystemVc, LinkContent, LinkContentVc, + DirectoryContent, DirectoryEntry, File, FileContent, FileMeta, FileSystem, FileSystemPath, + LinkContent, }; #[turbo_tasks::value(serialization = "none")] @@ -17,12 +15,12 @@ pub struct EmbeddedFileSystem { } #[turbo_tasks::value_impl] -impl EmbeddedFileSystemVc { +impl EmbeddedFileSystem { #[turbo_tasks::function] pub(super) fn new( name: String, dir: TransientInstance<&'static Dir<'static>>, - ) -> EmbeddedFileSystemVc { + ) -> Vc { EmbeddedFileSystem { name, dir }.cell() } } @@ -30,7 +28,7 @@ impl EmbeddedFileSystemVc { #[turbo_tasks::value_impl] impl FileSystem for EmbeddedFileSystem { #[turbo_tasks::function] - async fn read(&self, path: FileSystemPathVc) -> Result { + async fn read(&self, path: Vc) -> Result> { let file = match self.dir.get_file(&path.await?.path) { Some(file) => file, None => return Ok(FileContent::NotFound.cell()), @@ -40,12 +38,12 @@ impl FileSystem for EmbeddedFileSystem { } #[turbo_tasks::function] - fn read_link(&self, _path: FileSystemPathVc) -> LinkContentVc { + fn read_link(&self, _path: Vc) -> Vc { LinkContent::NotFound.cell() } #[turbo_tasks::function] - async fn read_dir(&self, path: FileSystemPathVc) -> Result { + async fn read_dir(&self, path: Vc) -> Result> { let path_str = &path.await?.path; let dir = match (path_str.as_str(), self.dir.get_dir(path_str)) { ("", _) => *self.dir, @@ -58,7 +56,7 @@ impl FileSystem for EmbeddedFileSystem { .iter() .map(|e| { let entry_name = e.path().file_name().unwrap_or_default().to_string_lossy(); - let entry_path = path.join(&entry_name); + let entry_path = path.join(entry_name.to_string()); ( entry_name.to_string(), @@ -70,26 +68,34 @@ impl FileSystem for EmbeddedFileSystem { }) .collect(); - Ok(DirectoryContentVc::new(entries)) + Ok(DirectoryContent::new(entries)) } #[turbo_tasks::function] - fn track(&self, _path: FileSystemPathVc) -> CompletionVc { - CompletionVc::immutable() + fn track(&self, _path: Vc) -> Vc { + Completion::immutable() } #[turbo_tasks::function] - fn write(&self, _path: FileSystemPathVc, _content: FileContentVc) -> Result { + fn write( + &self, + _path: Vc, + _content: Vc, + ) -> Result> { bail!("Writing is not possible to the embedded filesystem") } #[turbo_tasks::function] - fn write_link(&self, _path: FileSystemPathVc, _target: LinkContentVc) -> Result { + fn write_link( + &self, + _path: Vc, + _target: Vc, + ) -> Result> { bail!("Writing is not possible to the embedded filesystem") } #[turbo_tasks::function] - async fn metadata(&self, path: FileSystemPathVc) -> Result { + async fn metadata(&self, path: Vc) -> Result> { if self.dir.get_entry(&path.await?.path).is_none() { bail!("path not found, can't read metadata"); } @@ -101,7 +107,7 @@ impl FileSystem for EmbeddedFileSystem { #[turbo_tasks::value_impl] impl ValueToString for EmbeddedFileSystem { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.name.clone()) + fn to_string(&self) -> Vc { + Vc::cell(self.name.clone()) } } diff --git a/crates/turbo-tasks-fs/src/glob.rs b/crates/turbo-tasks-fs/src/glob.rs index 461f6d2a81c097..0c7fe46a1c47c9 100644 --- a/crates/turbo-tasks-fs/src/glob.rs +++ b/crates/turbo-tasks-fs/src/glob.rs @@ -2,7 +2,7 @@ use std::mem::take; use anyhow::{anyhow, bail, Context, Result}; use serde::{Deserialize, Serialize}; -use turbo_tasks::trace::TraceRawVcs; +use turbo_tasks::{trace::TraceRawVcs, Vc}; #[derive(PartialEq, Eq, Debug, Clone, TraceRawVcs, Serialize, Deserialize)] enum GlobPart { @@ -353,10 +353,10 @@ impl TryFrom<&str> for Glob { } #[turbo_tasks::value_impl] -impl GlobVc { +impl Glob { #[turbo_tasks::function] - pub fn new(glob: &str) -> Result { - Ok(Self::cell(Glob::try_from(glob)?)) + pub fn new(glob: String) -> Result> { + Ok(Self::cell(Glob::try_from(glob.as_str())?)) } } diff --git a/crates/turbo-tasks-fs/src/lib.rs b/crates/turbo-tasks-fs/src/lib.rs index 03439bf2cf2d8b..b86faea627512e 100644 --- a/crates/turbo-tasks-fs/src/lib.rs +++ b/crates/turbo-tasks-fs/src/lib.rs @@ -1,9 +1,11 @@ #![feature(trivial_bounds)] -#![feature(hash_drain_filter)] +#![feature(hash_extract_if)] #![feature(min_specialization)] #![feature(iter_advance_by)] #![feature(io_error_more)] #![feature(round_char_boundary)] +#![feature(async_fn_in_trait)] +#![feature(arbitrary_self_types)] pub mod attach; pub mod embed; @@ -22,9 +24,13 @@ use std::{ borrow::Cow, cmp::min, collections::{HashMap, HashSet}, - fmt::{self, Debug, Display, Formatter}, + fmt::{ + Debug, Display, Formatter, {self}, + }, fs::FileType, - io::{self, BufRead, ErrorKind}, + io::{ + BufRead, ErrorKind, {self}, + }, mem::take, path::{Path, PathBuf, MAIN_SEPARATOR}, sync::{ @@ -38,13 +44,13 @@ use anyhow::{anyhow, bail, Context, Result}; use auto_hash_map::AutoMap; use bitflags::bitflags; use dunce::simplified; -use glob::GlobVc; +use glob::Glob; use invalidator_map::InvalidatorMap; use jsonc_parser::{parse_to_serde_value, ParseOptions}; use mime::Mime; use notify::{watcher, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use read_glob::read_glob; -pub use read_glob::{ReadGlobResult, ReadGlobResultVc}; +pub use read_glob::ReadGlobResult; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::{ @@ -53,36 +59,41 @@ use tokio::{ }; use tracing::{instrument, Level}; use turbo_tasks::{ - mark_stateful, - primitives::{BoolVc, StringReadRef, StringVc}, - spawn_thread, - trace::TraceRawVcs, - CompletionVc, InvalidationReason, Invalidator, ValueToString, ValueToStringVc, + mark_stateful, spawn_thread, trace::TraceRawVcs, Completion, InvalidationReason, Invalidator, + ReadRef, ValueToString, Vc, }; use turbo_tasks_hash::hash_xxh3_hash64; use util::{extract_disk_access, join_path, normalize_path, sys_to_unix, unix_to_sys}; use self::{invalidation::WatchStart, json::UnparseableJson, mutex_map::MutexMap}; use crate::{ - attach::AttachedFileSystemVc, + attach::AttachedFileSystem, invalidation::WatchChange, retry::{retry_blocking, retry_future}, - rope::{Rope, RopeReadRef, RopeReader}, + rope::{Rope, RopeReader}, }; #[turbo_tasks::value_trait] pub trait FileSystem: ValueToString { /// Returns the path to the root of the file system. - fn root(self_vc: FileSystemVc) -> FileSystemPathVc { - FileSystemPathVc::new_normalized(self_vc, String::new()) - } - fn read(&self, fs_path: FileSystemPathVc) -> FileContentVc; - fn read_link(&self, fs_path: FileSystemPathVc) -> LinkContentVc; - fn read_dir(&self, fs_path: FileSystemPathVc) -> DirectoryContentVc; - fn track(&self, fs_path: FileSystemPathVc) -> CompletionVc; - fn write(&self, fs_path: FileSystemPathVc, content: FileContentVc) -> CompletionVc; - fn write_link(&self, fs_path: FileSystemPathVc, target: LinkContentVc) -> CompletionVc; - fn metadata(&self, fs_path: FileSystemPathVc) -> FileMetaVc; + fn root(self: Vc) -> Vc { + FileSystemPath::new_normalized(self, String::new()) + } + fn read(self: Vc, fs_path: Vc) -> Vc; + fn read_link(self: Vc, fs_path: Vc) -> Vc; + fn read_dir(self: Vc, fs_path: Vc) -> Vc; + fn track(self: Vc, fs_path: Vc) -> Vc; + fn write( + self: Vc, + fs_path: Vc, + content: Vc, + ) -> Vc; + fn write_link( + self: Vc, + fs_path: Vc, + target: Vc, + ) -> Vc; + fn metadata(self: Vc, fs_path: Vc) -> Vc; } #[derive(Default)] @@ -393,7 +404,7 @@ impl DiskFileSystem { for path in paths { let path_key = path_to_key(&path); for (_, invalidators) in - invalidator_map.drain_filter(|key, _| key.starts_with(&path_key)) + invalidator_map.extract_if(|key, _| key.starts_with(&path_key)) { invalidators .into_iter() @@ -446,7 +457,7 @@ impl DiskFileSystem { } } - pub async fn to_sys_path(&self, fs_path: FileSystemPathVc) -> Result { + pub async fn to_sys_path(&self, fs_path: Vc) -> Result { // just in case there's a windows unc path prefix we remove it with `dunce` let path = self.root_path(); let fs_path = fs_path.await?; @@ -478,9 +489,9 @@ pub fn path_to_key(path: impl AsRef) -> String { } #[turbo_tasks::value_impl] -impl DiskFileSystemVc { +impl DiskFileSystem { #[turbo_tasks::function] - pub async fn new(name: String, root: String) -> Result { + pub async fn new(name: String, root: String) -> Result> { mark_stateful(); // create the directory for the filesystem on disk, if it doesn't exist fs::create_dir_all(&root).await?; @@ -507,7 +518,7 @@ impl Debug for DiskFileSystem { #[turbo_tasks::value_impl] impl FileSystem for DiskFileSystem { #[turbo_tasks::function] - async fn read(&self, fs_path: FileSystemPathVc) -> Result { + async fn read(&self, fs_path: Vc) -> Result> { let full_path = self.to_sys_path(fs_path).await?; self.register_invalidator(&full_path)?; @@ -523,7 +534,7 @@ impl FileSystem for DiskFileSystem { } #[turbo_tasks::function] - async fn read_dir(&self, fs_path: FileSystemPathVc) -> Result { + async fn read_dir(&self, fs_path: Vc) -> Result> { let full_path = self.to_sys_path(fs_path).await?; self.register_dir_invalidator(&full_path)?; let fs_path = fs_path.await?; @@ -537,7 +548,7 @@ impl FileSystem for DiskFileSystem { || e.kind() == ErrorKind::NotADirectory || e.kind() == ErrorKind::InvalidFilename => { - return Ok(DirectoryContentVc::not_found()) + return Ok(DirectoryContent::not_found()) } Err(e) => { bail!(anyhow!(e).context(format!("reading dir {}", full_path.display()))) @@ -557,8 +568,7 @@ impl FileSystem for DiskFileSystem { let file_name = path.file_name()?.to_str()?.to_string(); let path_to_root = sys_to_unix(path.strip_prefix(&self.root).ok()?.to_str()?); - let fs_path = - FileSystemPathVc::new_normalized(fs_path.fs, path_to_root.to_string()); + let fs_path = FileSystemPath::new_normalized(fs_path.fs, path_to_root.to_string()); let entry = match e.file_type() { Ok(t) if t.is_file() => DirectoryEntry::File(fs_path), @@ -573,11 +583,11 @@ impl FileSystem for DiskFileSystem { .collect::>() .with_context(|| format!("reading directory item in {}", full_path.display()))?; - Ok(DirectoryContentVc::new(entries)) + Ok(DirectoryContent::new(entries)) } #[turbo_tasks::function] - async fn read_link(&self, fs_path: FileSystemPathVc) -> Result { + async fn read_link(&self, fs_path: Vc) -> Result> { let full_path = self.to_sys_path(fs_path).await?; self.register_invalidator(&full_path)?; @@ -625,7 +635,7 @@ impl FileSystem for DiskFileSystem { let target_string = relative_to_root_path.to_string_lossy().to_string(); ( target_string.clone(), - FileSystemPathVc::new_normalized(fs_path.fs(), target_string) + FileSystemPath::new_normalized(fs_path.fs(), target_string) .get_type() .await?, ) @@ -636,7 +646,7 @@ impl FileSystem for DiskFileSystem { link_path_unix.to_string(), fs_path .parent() - .join(link_path_unix.as_ref()) + .join(link_path_unix.to_string()) .get_type() .await?, ) @@ -659,18 +669,18 @@ impl FileSystem for DiskFileSystem { } #[turbo_tasks::function] - async fn track(&self, fs_path: FileSystemPathVc) -> Result { + async fn track(&self, fs_path: Vc) -> Result> { let full_path = self.to_sys_path(fs_path).await?; self.register_invalidator(&full_path)?; - Ok(CompletionVc::new()) + Ok(Completion::new()) } #[turbo_tasks::function] async fn write( &self, - fs_path: FileSystemPathVc, - content: FileContentVc, - ) -> Result { + fs_path: Vc, + content: Vc, + ) -> Result> { let full_path = self.to_sys_path(fs_path).await?; let content = content.await?; @@ -680,13 +690,13 @@ impl FileSystem for DiskFileSystem { let _lock = self.mutex_map.lock(full_path.clone()).await; // We perform an untracked comparison here, so that this write is not dependent - // on a read's FileContentVc (and the memory it holds). Our untracked read can + // on a read's Vc (and the memory it holds). Our untracked read can // be freed immediately. Given this is an output file, it's unlikely any Turbo - // code will need to read the file from disk into a FileContentVc, so we're not - // wasting cycles. + // code will need to read the file from disk into a Vc, so we're + // not wasting cycles. let compare = content.streaming_compare(full_path.clone()).await?; if compare == FileComparison::Equal { - return Ok(CompletionVc::unchanged()); + return Ok(Completion::unchanged()); } let create_directory = compare == FileComparison::Create; @@ -733,15 +743,15 @@ impl FileSystem for DiskFileSystem { } } - Ok(CompletionVc::new()) + Ok(Completion::new()) } #[turbo_tasks::function] async fn write_link( &self, - fs_path: FileSystemPathVc, - target: LinkContentVc, - ) -> Result { + fs_path: Vc, + target: Vc, + ) -> Result> { let full_path = self.to_sys_path(fs_path).await?; let old_content = fs_path .read_link() @@ -749,7 +759,7 @@ impl FileSystem for DiskFileSystem { .with_context(|| format!("reading old symlink target of {}", full_path.display()))?; let target_link = target.await?; if target_link == old_content { - return Ok(CompletionVc::unchanged()); + return Ok(Completion::unchanged()); } let file_type = &*fs_path.get_type().await?; let create_directory = file_type == &FileSystemEntryType::NotFound; @@ -810,11 +820,11 @@ impl FileSystem for DiskFileSystem { .with_context(|| anyhow!("removing {} failed", full_path.display()))?; } } - Ok(CompletionVc::new()) + Ok(Completion::new()) } #[turbo_tasks::function] - async fn metadata(&self, fs_path: FileSystemPathVc) -> Result { + async fn metadata(&self, fs_path: Vc) -> Result> { let full_path = self.to_sys_path(fs_path).await?; self.register_invalidator(&full_path)?; @@ -823,27 +833,27 @@ impl FileSystem for DiskFileSystem { .await .with_context(|| format!("reading metadata for {}", full_path.display()))?; - Ok(FileMetaVc::cell(meta.into())) + Ok(FileMeta::cell(meta.into())) } } #[turbo_tasks::value_impl] impl ValueToString for DiskFileSystem { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.name.clone()) + fn to_string(&self) -> Vc { + Vc::cell(self.name.clone()) } } #[turbo_tasks::value] #[derive(Debug, Clone)] pub struct FileSystemPath { - pub fs: FileSystemVc, + pub fs: Vc>, pub path: String, } impl FileSystemPath { - pub fn is_inside(&self, context: &FileSystemPath) -> bool { + pub fn is_inside_ref(&self, context: &FileSystemPath) -> bool { if self.fs == context.fs && self.path.starts_with(&context.path) { if context.path.is_empty() { true @@ -855,7 +865,7 @@ impl FileSystemPath { } } - pub fn is_inside_or_equal(&self, context: &FileSystemPath) -> bool { + pub fn is_inside_or_equal_ref(&self, context: &FileSystemPath) -> bool { if self.fs == context.fs && self.path.starts_with(&context.path) { if context.path.is_empty() { true @@ -932,7 +942,7 @@ impl FileSystemPath { self.path.rsplit('/').next().unwrap() } - pub fn extension(&self) -> Option<&str> { + pub fn extension_ref(&self) -> Option<&str> { if let Some((_, ext)) = self.path.rsplit_once('.') { if !ext.contains('/') { return Some(ext); @@ -943,15 +953,15 @@ impl FileSystemPath { } #[turbo_tasks::value(transparent)] -pub struct FileSystemPathOption(Option); +pub struct FileSystemPathOption(Option>); #[turbo_tasks::value_impl] -impl FileSystemPathVc { - /// Create a new FileSystemPathVc from a path withing a FileSystem. The +impl FileSystemPath { + /// Create a new Vc from a path withing a FileSystem. The /// /-separated path is expected to be already normalized (this is asserted /// in dev mode). #[turbo_tasks::function] - fn new_normalized(fs: FileSystemVc, path: String) -> Self { + fn new_normalized(fs: Vc>, path: String) -> Vc { // On Windows, the path must be converted to a unix path before creating. But on // Unix, backslashes are a valid char in file names, and the path can be // provided by the user, so we allow it. @@ -972,13 +982,13 @@ impl FileSystemPathVc { /// contain ".." or "." seqments, but it must not leave the root of the /// filesystem. #[turbo_tasks::function] - pub async fn join(self, path: &str) -> Result { + pub async fn join(self: Vc, path: String) -> Result> { let this = self.await?; - if let Some(path) = join_path(&this.path, path) { + if let Some(path) = join_path(&this.path, &path) { Ok(Self::new_normalized(this.fs, path)) } else { bail!( - "FileSystemPathVc(\"{}\").join(\"{}\") leaves the filesystem root", + "Vc(\"{}\").join(\"{}\") leaves the filesystem root", this.path, path ); @@ -987,11 +997,11 @@ impl FileSystemPathVc { /// Adds a suffix to the filename. [path] must not contain `/`. #[turbo_tasks::function] - pub async fn append(self, path: &str) -> Result { + pub async fn append(self: Vc, path: String) -> Result> { let this = self.await?; if path.contains('/') { bail!( - "FileSystemPathVc(\"{}\").append(\"{}\") must not append '/'", + "Vc(\"{}\").append(\"{}\") must not append '/'", this.path, path ) @@ -1005,11 +1015,11 @@ impl FileSystemPathVc { /// Adds a suffix to the basename of the filename. [appending] must not /// contain `/`. Extension will stay intact. #[turbo_tasks::function] - pub async fn append_to_stem(self, appending: &str) -> Result { + pub async fn append_to_stem(self: Vc, appending: String) -> Result> { let this = self.await?; if appending.contains('/') { bail!( - "FileSystemPathVc(\"{}\").append_to_stem(\"{}\") must not append '/'", + "Vc(\"{}\").append_to_stem(\"{}\") must not append '/'", this.path, appending ) @@ -1030,64 +1040,68 @@ impl FileSystemPathVc { )) } - /// Similar to [FileSystemPathVc::join], but returns an Option that will be + /// Similar to [FileSystemPath::join], but returns an Option that will be /// None when the joined path would leave the filesystem root. #[turbo_tasks::function] - pub async fn try_join(self, path: &str) -> Result { + pub async fn try_join(self: Vc, path: String) -> Result> { let this = self.await?; - if let Some(path) = join_path(&this.path, path) { - Ok(FileSystemPathOptionVc::cell(Some( + if let Some(path) = join_path(&this.path, &path) { + Ok(Vc::cell(Some( Self::new_normalized(this.fs, path).resolve().await?, ))) } else { - Ok(FileSystemPathOptionVc::cell(None)) + Ok(Vc::cell(None)) } } - /// Similar to [FileSystemPathVc::join], but returns an Option that will be + /// Similar to [FileSystemPath::join], but returns an Option that will be /// None when the joined path would leave the current path. #[turbo_tasks::function] - pub async fn try_join_inside(self, path: &str) -> Result { + pub async fn try_join_inside(self: Vc, path: String) -> Result> { let this = self.await?; - if let Some(path) = join_path(&this.path, path) { + if let Some(path) = join_path(&this.path, &path) { if path.starts_with(&this.path) { - return Ok(FileSystemPathOptionVc::cell(Some( + return Ok(Vc::cell(Some( Self::new_normalized(this.fs, path).resolve().await?, ))); } } - Ok(FileSystemPathOptionVc::cell(None)) + Ok(Vc::cell(None)) } #[turbo_tasks::function] - pub async fn read_glob(self, glob: GlobVc, include_dot_files: bool) -> ReadGlobResultVc { + pub async fn read_glob( + self: Vc, + glob: Vc, + include_dot_files: bool, + ) -> Vc { read_glob(self, glob, include_dot_files) } #[turbo_tasks::function] - pub fn root(self) -> Self { + pub fn root(self: Vc) -> Vc { self.fs().root() } #[turbo_tasks::function] - pub async fn fs(self) -> Result { + pub async fn fs(self: Vc) -> Result>> { Ok(self.await?.fs) } #[turbo_tasks::function] - pub async fn extension(self) -> Result { + pub async fn extension(self: Vc) -> Result> { let this = self.await?; - Ok(StringVc::cell(this.extension().unwrap_or("").to_string())) + Ok(Vc::cell(this.extension_ref().unwrap_or("").to_string())) } #[turbo_tasks::function] - pub async fn is_inside(self, other: FileSystemPathVc) -> Result { - Ok(BoolVc::cell(self.await?.is_inside(&*other.await?))) + pub async fn is_inside(self: Vc, other: Vc) -> Result> { + Ok(Vc::cell(self.await?.is_inside_ref(&*other.await?))) } #[turbo_tasks::function] - pub async fn is_inside_or_equal(self, other: FileSystemPathVc) -> Result { - Ok(BoolVc::cell(self.await?.is_inside_or_equal(&*other.await?))) + pub async fn is_inside_or_equal(self: Vc, other: Vc) -> Result> { + Ok(Vc::cell(self.await?.is_inside_or_equal_ref(&*other.await?))) } } @@ -1099,10 +1113,10 @@ impl Display for FileSystemPath { #[turbo_tasks::function] pub async fn rebase( - fs_path: FileSystemPathVc, - old_base: FileSystemPathVc, - new_base: FileSystemPathVc, -) -> Result { + fs_path: Vc, + old_base: Vc, + new_base: Vc, +) -> Result> { let fs_path = &*fs_path.await?; let old_base = &*old_base.await?; let new_base = &*new_base.await?; @@ -1129,23 +1143,23 @@ pub async fn rebase( new_path = [new_base.path.as_str(), &fs_path.path[old_base.path.len()..]].concat(); } } - Ok(new_base.fs.root().join(&new_path)) + Ok(new_base.fs.root().join(new_path)) } #[turbo_tasks::value_impl] -impl FileSystemPathVc { +impl FileSystemPath { #[turbo_tasks::function] - pub async fn read(self) -> FileContentVc { + pub async fn read(self: Vc) -> Vc { self.fs().read(self) } #[turbo_tasks::function] - pub async fn read_link(self) -> LinkContentVc { + pub async fn read_link(self: Vc) -> Vc { self.fs().read_link(self) } #[turbo_tasks::function] - pub fn read_json(self) -> FileJsonContentVc { + pub fn read_json(self: Vc) -> Vc { self.fs().read(self).parse_json() } @@ -1154,27 +1168,27 @@ impl FileSystemPathVc { /// DETERMINISM: Result is in random order. Either sort result or do not /// depend on the order. #[turbo_tasks::function] - pub async fn read_dir(self) -> DirectoryContentVc { + pub async fn read_dir(self: Vc) -> Vc { self.fs().read_dir(self) } #[turbo_tasks::function] - pub async fn track(self) -> CompletionVc { + pub async fn track(self: Vc) -> Vc { self.fs().track(self) } #[turbo_tasks::function] - pub fn write(self, content: FileContentVc) -> CompletionVc { + pub fn write(self: Vc, content: Vc) -> Vc { self.fs().write(self, content) } #[turbo_tasks::function] - pub fn write_link(self, target: LinkContentVc) -> CompletionVc { + pub fn write_link(self: Vc, target: Vc) -> Vc { self.fs().write_link(self, target) } #[turbo_tasks::function] - pub async fn parent(self) -> Result { + pub async fn parent(self: Vc) -> Result> { let this = self.await?; let path = &this.path; if path.is_empty() { @@ -1184,11 +1198,11 @@ impl FileSystemPathVc { Some(index) => path[..index].to_string(), None => "".to_string(), }; - Ok(FileSystemPathVc::new_normalized(this.fs, p)) + Ok(FileSystemPath::new_normalized(this.fs, p)) } #[turbo_tasks::function] - pub fn metadata(self) -> FileMetaVc { + pub fn metadata(self: Vc) -> Vc { self.fs().metadata(self) } @@ -1201,16 +1215,16 @@ impl FileSystemPathVc { // case-insenstive filesystems, while read_dir gives you the "correct" // casing. We want to enforce "correct" casing to avoid broken builds on // Vercel deployments (case-sensitive). - pub async fn get_type(self) -> Result { + pub async fn get_type(self: Vc) -> Result> { let this = self.await?; if this.is_root() { - return Ok(FileSystemEntryTypeVc::cell(FileSystemEntryType::Directory)); + return Ok(FileSystemEntryType::cell(FileSystemEntryType::Directory)); } let parent = self.parent().resolve().await?; let dir_content = parent.read_dir().await?; match &*dir_content { DirectoryContent::NotFound => { - Ok(FileSystemEntryTypeVc::cell(FileSystemEntryType::NotFound)) + Ok(FileSystemEntryType::cell(FileSystemEntryType::NotFound)) } DirectoryContent::Entries(entries) => { let basename = if let Some((_, basename)) = this.path.rsplit_once('/') { @@ -1219,21 +1233,21 @@ impl FileSystemPathVc { &this.path }; if let Some(entry) = entries.get(basename) { - Ok(FileSystemEntryTypeVc::cell(entry.into())) + Ok(FileSystemEntryType::cell(entry.into())) } else { - Ok(FileSystemEntryTypeVc::cell(FileSystemEntryType::NotFound)) + Ok(FileSystemEntryType::cell(FileSystemEntryType::NotFound)) } } } } #[turbo_tasks::function] - pub fn realpath(self) -> FileSystemPathVc { + pub fn realpath(self: Vc) -> Vc { self.realpath_with_links().path() } #[turbo_tasks::function] - pub async fn realpath_with_links(self) -> Result { + pub async fn realpath_with_links(self: Vc) -> Result> { let this = self.await?; if this.is_root() { return Ok(RealPathResult { @@ -1246,7 +1260,7 @@ impl FileSystemPathVc { let mut current = self.root().resolve().await?; let mut symlinks = Vec::new(); for segment in segments { - current = current.join(segment).resolve().await?; + current = current.join(segment.to_string()).resolve().await?; while let FileSystemEntryType::Symlink = &*current.get_type().await? { if let LinkContent::Link { target, link_type } = &*current.read_link().await? { symlinks.push(current.resolve().await?); @@ -1255,7 +1269,7 @@ impl FileSystemPathVc { } else { current.parent().resolve().await? } - .join(target) + .join(target.to_string()) .resolve() .await?; } else { @@ -1278,12 +1292,12 @@ impl FileSystemPathVc { } } -impl FileSystemPathVc { +impl FileSystemPath { pub fn rebase( - fs_path: FileSystemPathVc, - old_base: FileSystemPathVc, - new_base: FileSystemPathVc, - ) -> FileSystemPathVc { + fs_path: Vc, + old_base: Vc, + new_base: Vc, + ) -> Vc { rebase(fs_path, old_base, new_base) } } @@ -1291,8 +1305,8 @@ impl FileSystemPathVc { #[turbo_tasks::value_impl] impl ValueToString for FileSystemPath { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "[{}]/{}", self.fs.to_string().await?, self.path @@ -1303,14 +1317,14 @@ impl ValueToString for FileSystemPath { #[derive(Clone, Debug)] #[turbo_tasks::value(shared)] pub struct RealPathResult { - pub path: FileSystemPathVc, - pub symlinks: Vec, + pub path: Vc, + pub symlinks: Vec>, } #[turbo_tasks::value_impl] -impl RealPathResultVc { +impl RealPathResult { #[turbo_tasks::function] - pub async fn path(self) -> Result { + pub async fn path(self: Vc) -> Result> { Ok(self.await?.path) } } @@ -1380,7 +1394,7 @@ impl From for FileContent { } } -impl From for FileContentVc { +impl From for Vc { fn from(file: File) -> Self { FileContent::Content(file).cell() } @@ -1463,7 +1477,7 @@ bitflags! { pub enum LinkContent { // for the relative link, the target is raw value read from the link // for the absolute link, the target is stripped of the root path while reading - // We don't use the `FileSystemPathVc` here for now, because the `FileSystemPath` is always + // We don't use the `Vc` here for now, because the `FileSystemPath` is always // normalized, which means in `fn write_link` we couldn't restore the raw value of the file // link because there is only **dist** path in `fn write_link`, and we need the raw path if // we want to restore the link value in `fn write_link` @@ -1542,8 +1556,8 @@ impl From for File { } } -impl From for File { - fn from(s: StringReadRef) -> Self { +impl From> for File { + fn from(s: ReadRef) -> Self { File::from_bytes(s.as_bytes().to_vec()) } } @@ -1566,8 +1580,8 @@ impl From<&[u8]> for File { } } -impl From for File { - fn from(rope: RopeReadRef) -> Self { +impl From> for File { + fn from(rope: ReadRef) -> Self { File::from_rope(rope.clone_value()) } } @@ -1681,7 +1695,7 @@ impl FileContent { } } - pub fn parse_json(&self) -> FileJsonContent { + pub fn parse_json_ref(&self) -> FileJsonContent { match self { FileContent::Content(file) => { let de = &mut serde_json::Deserializer::from_reader(file.read()); @@ -1696,7 +1710,7 @@ impl FileContent { } } - pub fn parse_json_with_comments(&self) -> FileJsonContent { + pub fn parse_json_with_comments_ref(&self) -> FileJsonContent { match self { FileContent::Content(file) => match file.content.to_str() { Ok(string) => match parse_to_serde_value( @@ -1723,7 +1737,7 @@ impl FileContent { } } - pub fn lines(&self) -> FileLinesContent { + pub fn lines_ref(&self) -> FileLinesContent { match self { FileContent::Content(file) => match file.content.to_str() { Ok(string) => { @@ -1750,21 +1764,21 @@ impl FileContent { } #[turbo_tasks::value_impl] -impl FileContentVc { +impl FileContent { #[turbo_tasks::function] - pub async fn parse_json(self) -> Result { + pub async fn parse_json(self: Vc) -> Result> { let this = self.await?; - Ok(this.parse_json().into()) + Ok(this.parse_json_ref().into()) } #[turbo_tasks::function] - pub async fn parse_json_with_comments(self) -> Result { + pub async fn parse_json_with_comments(self: Vc) -> Result> { let this = self.await?; - Ok(this.parse_json_with_comments().into()) + Ok(this.parse_json_with_comments_ref().into()) } #[turbo_tasks::function] - pub async fn lines(self) -> Result { + pub async fn lines(self: Vc) -> Result> { let this = self.await?; - Ok(this.lines().into()) + Ok(this.lines_ref().into()) } } @@ -1783,9 +1797,9 @@ impl ValueToString for FileJsonContent { /// This operation will only succeed if the file contents are a valid JSON /// value. #[turbo_tasks::function] - async fn to_string(&self) -> Result { + async fn to_string(&self) -> Result> { match self { - FileJsonContent::Content(json) => Ok(StringVc::cell(json.to_string())), + FileJsonContent::Content(json) => Ok(Vc::cell(json.to_string())), FileJsonContent::Unparseable(e) => Err(anyhow!("File is not valid JSON: {}", e)), FileJsonContent::NotFound => Err(anyhow!("File not found")), } @@ -1827,10 +1841,10 @@ pub enum FileLinesContent { #[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, TraceRawVcs, Serialize, Deserialize)] pub enum DirectoryEntry { - File(FileSystemPathVc), - Directory(FileSystemPathVc), - Symlink(FileSystemPathVc), - Other(FileSystemPathVc), + File(Vc), + Directory(Vc), + Symlink(Vc), + Other(Vc), Error, } @@ -1881,12 +1895,12 @@ pub enum DirectoryContent { NotFound, } -impl DirectoryContentVc { - pub fn new(entries: AutoMap) -> Self { +impl DirectoryContent { + pub fn new(entries: AutoMap) -> Vc { Self::cell(DirectoryContent::Entries(entries)) } - pub fn not_found() -> Self { + pub fn not_found() -> Vc { Self::cell(DirectoryContent::NotFound) } } @@ -1897,37 +1911,37 @@ pub struct NullFileSystem; #[turbo_tasks::value_impl] impl FileSystem for NullFileSystem { #[turbo_tasks::function] - fn read(&self, _fs_path: FileSystemPathVc) -> FileContentVc { + fn read(&self, _fs_path: Vc) -> Vc { FileContent::NotFound.cell() } #[turbo_tasks::function] - fn read_link(&self, _fs_path: FileSystemPathVc) -> LinkContentVc { + fn read_link(&self, _fs_path: Vc) -> Vc { LinkContent::NotFound.into() } #[turbo_tasks::function] - fn read_dir(&self, _fs_path: FileSystemPathVc) -> DirectoryContentVc { - DirectoryContentVc::not_found() + fn read_dir(&self, _fs_path: Vc) -> Vc { + DirectoryContent::not_found() } #[turbo_tasks::function] - fn track(&self, _fs_path: FileSystemPathVc) -> CompletionVc { - CompletionVc::immutable() + fn track(&self, _fs_path: Vc) -> Vc { + Completion::immutable() } #[turbo_tasks::function] - fn write(&self, _fs_path: FileSystemPathVc, _content: FileContentVc) -> CompletionVc { - CompletionVc::new() + fn write(&self, _fs_path: Vc, _content: Vc) -> Vc { + Completion::new() } #[turbo_tasks::function] - fn write_link(&self, _fs_path: FileSystemPathVc, _target: LinkContentVc) -> CompletionVc { - CompletionVc::new() + fn write_link(&self, _fs_path: Vc, _target: Vc) -> Vc { + Completion::new() } #[turbo_tasks::function] - fn metadata(&self, _fs_path: FileSystemPathVc) -> FileMetaVc { + fn metadata(&self, _fs_path: Vc) -> Vc { FileMeta::default().cell() } } @@ -1935,19 +1949,19 @@ impl FileSystem for NullFileSystem { #[turbo_tasks::value_impl] impl ValueToString for NullFileSystem { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(String::from("null")) + fn to_string(&self) -> Vc { + Vc::cell(String::from("null")) } } -pub async fn to_sys_path(mut path: FileSystemPathVc) -> Result> { +pub async fn to_sys_path(mut path: Vc) -> Result> { loop { - if let Some(fs) = AttachedFileSystemVc::resolve_from(path.fs()).await? { + if let Some(fs) = Vc::try_resolve_downcast_type::(path.fs()).await? { path = fs.get_inner_fs_path(path); continue; } - if let Some(fs) = DiskFileSystemVc::resolve_from(path.fs()).await? { + if let Some(fs) = Vc::try_resolve_downcast_type::(path.fs()).await? { let sys_path = fs.await?.to_sys_path(path).await?; return Ok(Some(sys_path)); } diff --git a/crates/turbo-tasks-fs/src/read_glob.rs b/crates/turbo-tasks-fs/src/read_glob.rs index 194e56b22e8acd..35bffa372dc0a4 100644 --- a/crates/turbo-tasks-fs/src/read_glob.rs +++ b/crates/turbo-tasks-fs/src/read_glob.rs @@ -1,14 +1,15 @@ use std::collections::HashMap; use anyhow::Result; +use turbo_tasks::Vc; -use crate::{glob::GlobVc, DirectoryContent, DirectoryEntry, FileSystemPathVc}; +use crate::{glob::Glob, DirectoryContent, DirectoryEntry, FileSystemPath}; #[turbo_tasks::value] #[derive(Default, Debug)] pub struct ReadGlobResult { pub results: HashMap, - pub inner: HashMap, + pub inner: HashMap>, } /// Reads matches of a glob pattern. @@ -17,29 +18,29 @@ pub struct ReadGlobResult { /// on the order. #[turbo_tasks::function] pub async fn read_glob( - directory: FileSystemPathVc, - glob: GlobVc, + directory: Vc, + glob: Vc, include_dot_files: bool, -) -> Result { +) -> Result> { read_glob_internal("", directory, glob, include_dot_files).await } #[turbo_tasks::function] async fn read_glob_inner( prefix: String, - directory: FileSystemPathVc, - glob: GlobVc, + directory: Vc, + glob: Vc, include_dot_files: bool, -) -> Result { +) -> Result> { read_glob_internal(&prefix, directory, glob, include_dot_files).await } async fn read_glob_internal( prefix: &str, - directory: FileSystemPathVc, - glob: GlobVc, + directory: Vc, + glob: Vc, include_dot_files: bool, -) -> Result { +) -> Result> { let dir = directory.read_dir().await?; let mut result = ReadGlobResult::default(); let glob_value = glob.await?; @@ -73,5 +74,5 @@ async fn read_glob_internal( } DirectoryContent::NotFound => {} } - Ok(ReadGlobResultVc::cell(result)) + Ok(ReadGlobResult::cell(result)) } diff --git a/crates/turbo-tasks-macros-shared/src/ident.rs b/crates/turbo-tasks-macros-shared/src/ident.rs index 3700ed5f22d43d..332a4812c456bc 100644 --- a/crates/turbo-tasks-macros-shared/src/ident.rs +++ b/crates/turbo-tasks-macros-shared/src/ident.rs @@ -1,4 +1,5 @@ -use syn::Ident; +use quote::ToTokens; +use syn::{spanned::Spanned, GenericArgument, Ident, Path, PathArguments, Type, TypeParamBound}; pub fn get_register_value_type_ident(struct_ident: &Ident) -> Ident { Ident::new( @@ -14,13 +15,20 @@ pub fn get_register_trait_methods_ident(trait_ident: &Ident, struct_ident: &Iden ) } -pub fn get_function_ident(ident: &Ident) -> Ident { +pub fn get_native_function_ident(ident: &Ident) -> Ident { Ident::new( &format!("{}_FUNCTION", ident.to_string().to_uppercase()), ident.span(), ) } +pub fn get_native_function_id_ident(ident: &Ident) -> Ident { + Ident::new( + &format!("{}_FUNCTION_ID", ident.to_string().to_uppercase()), + ident.span(), + ) +} + pub fn get_trait_type_ident(ident: &Ident) -> Ident { Ident::new( &format!("{}_TRAIT_TYPE", ident.to_string().to_uppercase()), @@ -39,6 +47,28 @@ pub fn get_impl_function_ident(struct_ident: &Ident, ident: &Ident) -> Ident { ) } +pub fn get_inherent_impl_function_ident(ty_ident: &Ident, fn_ident: &Ident) -> Ident { + Ident::new( + &format!( + "{}_IMPL_{}_FUNCTION", + ty_ident.to_string().to_uppercase(), + fn_ident.to_string().to_uppercase() + ), + fn_ident.span(), + ) +} + +pub fn get_inherent_impl_function_id_ident(ty_ident: &Ident, fn_ident: &Ident) -> Ident { + Ident::new( + &format!( + "{}_IMPL_{}_FUNCTION_ID", + ty_ident.to_string().to_uppercase(), + fn_ident.to_string().to_uppercase() + ), + fn_ident.span(), + ) +} + pub fn get_trait_impl_function_ident( struct_ident: &Ident, trait_ident: &Ident, @@ -55,8 +85,106 @@ pub fn get_trait_impl_function_ident( ) } -pub fn get_ref_ident(ident: &Ident) -> Ident { - Ident::new(&(ident.to_string() + "Vc"), ident.span()) +pub fn get_trait_impl_function_id_ident( + struct_ident: &Ident, + trait_ident: &Ident, + ident: &Ident, +) -> Ident { + Ident::new( + &format!( + "{}_IMPL_TRAIT_{}_{}_FUNCTION_ID", + struct_ident.to_string().to_uppercase(), + trait_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_internal_trait_impl_function_ident(trait_ident: &Ident, ident: &Ident) -> Ident { + Ident::new( + &format!("__trait_call_{trait_ident}_{ident}"), + trait_ident.span(), + ) +} + +pub fn get_path_ident(path: &Path) -> Ident { + let mut result = String::new(); + + for (i, segment) in path.segments.iter().enumerate() { + let ident = segment.ident.to_string(); + + if i > 0 { + result.push('_'); + } + + result.push_str(&ident); + + match &segment.arguments { + PathArguments::AngleBracketed(args) => { + for arg in &args.args { + match arg { + GenericArgument::Type(ty) => { + if let Type::Path(type_path) = ty { + let type_ident = get_path_ident(&type_path.path); + result.push('_'); + result.push_str(&type_ident.to_string()); + } else if let Type::TraitObject(trait_obj) = ty { + for bound in &trait_obj.bounds { + if let TypeParamBound::Trait(bound_trait) = bound { + let bound_ident = get_path_ident(&bound_trait.path); + result.push_str("_dyn_"); + result.push_str(&bound_ident.to_string()); + } + } + } else { + arg.span() + .unwrap() + .error( + "#[turbo_tasks::value_impl] does not support this type \ + argument", + ) + .emit(); + } + } + _ => arg + .span() + .unwrap() + .error("#[turbo_tasks::value_impl] does not support this type argument") + .emit(), + } + } + } + PathArguments::None => {} + _ => { + segment + .span() + .unwrap() + .error("#[turbo_tasks::value_impl] does not support this type argument") + .emit(); + } + } + } + + Ident::new(&result, path.span()) +} + +pub fn get_type_ident(ty: &Type) -> Option { + match ty { + Type::Path(path) => Some(get_path_ident(&path.path)), + Type::Tuple(tuple) => Some(Ident::new("unit", tuple.span())), + _ => { + ty.span() + .unwrap() + .error(format!( + "#[turbo_tasks::value_impl] does not support the type {}, expected T or \ + Box", + ty.to_token_stream() + )) + .emit(); + None + } + } } pub fn get_read_ref_ident(ident: &Ident) -> Ident { @@ -77,3 +205,42 @@ pub fn get_trait_default_impl_function_ident(trait_ident: &Ident, ident: &Ident) ident.span(), ) } + +pub fn get_trait_type_id_ident(ident: &Ident) -> Ident { + Ident::new( + &format!("{}_TRAIT_TYPE_ID", ident.to_string().to_uppercase()), + ident.span(), + ) +} + +pub fn get_trait_default_impl_function_id_ident(trait_ident: &Ident, ident: &Ident) -> Ident { + Ident::new( + &format!( + "{}_DEFAULT_IMPL_{}_FUNCTION_ID", + trait_ident.to_string().to_uppercase(), + ident.to_string().to_uppercase() + ), + ident.span(), + ) +} + +pub fn get_value_type_ident(ident: &Ident) -> Ident { + Ident::new( + &format!("{}_VALUE_TYPE", ident.to_string().to_uppercase()), + ident.span(), + ) +} + +pub fn get_value_type_id_ident(ident: &Ident) -> Ident { + Ident::new( + &format!("{}_VALUE_TYPE_ID", ident.to_string().to_uppercase()), + ident.span(), + ) +} + +pub fn get_value_type_init_ident(ident: &Ident) -> Ident { + Ident::new( + &format!("{}_VALUE_TYPE_INIT", ident.to_string().to_uppercase()), + ident.span(), + ) +} diff --git a/crates/turbo-tasks-macros-shared/src/lib.rs b/crates/turbo-tasks-macros-shared/src/lib.rs index 2c3e3052976e2e..4b0c1189dcaf03 100644 --- a/crates/turbo-tasks-macros-shared/src/lib.rs +++ b/crates/turbo-tasks-macros-shared/src/lib.rs @@ -1,9 +1,12 @@ #![feature(proc_macro_diagnostic)] +#![feature(box_patterns)] mod expand; mod ident; +mod primitive_input; mod value_trait_arguments; pub use expand::*; pub use ident::*; +pub use primitive_input::PrimitiveInput; pub use value_trait_arguments::ValueTraitArguments; diff --git a/crates/turbo-tasks-macros-shared/src/primitive_input.rs b/crates/turbo-tasks-macros-shared/src/primitive_input.rs new file mode 100644 index 00000000000000..de4eb533986421 --- /dev/null +++ b/crates/turbo-tasks-macros-shared/src/primitive_input.rs @@ -0,0 +1,16 @@ +use syn::{ + parse::{Parse, ParseStream}, + Result, Type, +}; + +#[derive(Debug)] +pub struct PrimitiveInput { + pub ty: Type, +} + +impl Parse for PrimitiveInput { + fn parse(input: ParseStream) -> Result { + let ty: Type = input.parse()?; + Ok(PrimitiveInput { ty }) + } +} diff --git a/crates/turbo-tasks-macros-tests/tests/task_input.rs b/crates/turbo-tasks-macros-tests/tests/task_input.rs index 52cfba5be482cb..7eabe06e522472 100644 --- a/crates/turbo-tasks-macros-tests/tests/task_input.rs +++ b/crates/turbo-tasks-macros-tests/tests/task_input.rs @@ -2,8 +2,7 @@ //! However, we keep one test here as an integration test between the derive //! macro and the `#[turbo_tasks::function]` macro. -use anyhow::Result; -use turbo_tasks::{CompletionVc, TaskInput}; +use turbo_tasks::{Completion, TaskInput, Vc}; use turbo_tasks_testing::{register, run}; register!(); @@ -12,9 +11,9 @@ register!(); struct OneUnnamedField(u32); #[turbo_tasks::function] -async fn one_unnamed_field(input: OneUnnamedField) -> CompletionVc { +async fn one_unnamed_field(input: OneUnnamedField) -> Vc { assert_eq!(input.0, 42); - CompletionVc::immutable() + Completion::immutable() } #[tokio::test] diff --git a/crates/turbo-tasks-macros/src/derive/task_input_macro.rs b/crates/turbo-tasks-macros/src/derive/task_input_macro.rs index 144f2b39fe1694..04c60ee76389a3 100644 --- a/crates/turbo-tasks-macros/src/derive/task_input_macro.rs +++ b/crates/turbo-tasks-macros/src/derive/task_input_macro.rs @@ -107,11 +107,11 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream { ( quote! { match value { - turbo_tasks::TaskInput::List(value) => { + turbo_tasks::ConcreteTaskInput::List(value) => { let mut #inputs_list_ident = value.iter(); let discriminant = #inputs_list_ident.next().ok_or_else(|| anyhow::anyhow!(concat!("missing discriminant for ", stringify!(#ident))))?; - let discriminant: #repr = turbo_tasks::FromTaskInput::try_from(discriminant)?; + let discriminant: #repr = turbo_tasks::TaskInput::try_from_concrete(discriminant)?; Ok(match discriminant { #( @@ -127,15 +127,15 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream { } }, quote! { - match value { + match self { #( #ident::#variants_idents #variants_fields_destructuring => { let mut #inputs_list_ident = Vec::with_capacity(1 + #variants_fields_len); let discriminant: #repr = #variants_discriminants; - let discriminant: turbo_tasks::TaskInput = discriminant.into(); + let discriminant = discriminant.into_concrete(); #inputs_list_ident.push(discriminant); #variants_from_expansion - turbo_tasks::TaskInput::List(#inputs_list_ident) + turbo_tasks::ConcreteTaskInput::List(#inputs_list_ident) } )* } @@ -150,7 +150,7 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream { ( quote! { match value { - turbo_tasks::TaskInput::List(value) => { + turbo_tasks::ConcreteTaskInput::List(value) => { let mut #inputs_list_ident = value.iter(); #try_from_expansion Ok(#ident #destructuring) @@ -160,9 +160,9 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream { }, quote! { let mut #inputs_list_ident = Vec::with_capacity(#fields_len); - let #ident #destructuring = value; + let #ident #destructuring = self; #from_expansion - turbo_tasks::TaskInput::List(#inputs_list_ident) + turbo_tasks::ConcreteTaskInput::List(#inputs_list_ident) }, ) } @@ -190,35 +190,19 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream { .collect(); quote! { - impl - < - 'a, - #( - #generic_params: - turbo_tasks::FromTaskInput< - 'a, - // NOTE(alexkirsz) Couldn't find a way to accept any error type here. - // Tried with a `#generic_params::Error: std::error::Error + Send + Sync + 'static` bound but - // it clashes with `anyhow::Error` not implementing `std::error::Error`. - Error = turbo_tasks::Error, - > - , - )* - > - turbo_tasks::FromTaskInput<'a> for #ident #generics { - type Error = turbo_tasks::Error; - + impl #generics turbo_tasks::TaskInput for #ident #generics + where + #(#generic_params: turbo_tasks::TaskInput,)* + { #[allow(non_snake_case)] #[allow(unreachable_code)] // This can occur for enums with no variants. - fn try_from(value: &'a turbo_tasks::TaskInput) -> Result { + fn try_from_concrete(value: &turbo_tasks::ConcreteTaskInput) -> turbo_tasks::Result { #try_from_impl } - } - impl<#(#generic_params: Into,)*> From<#ident #generics> for turbo_tasks::TaskInput { #[allow(non_snake_case)] #[allow(unreachable_code)] // This can occur for enums with no variants. - fn from(value: #ident #generics) -> Self { + fn into_concrete(self) -> turbo_tasks::ConcreteTaskInput { #from_impl } } @@ -237,12 +221,12 @@ fn expand_named( quote! { #( let #fields_idents = #inputs_list_ident.next().ok_or_else(|| anyhow::anyhow!(concat!("missing element for ", stringify!(#fields_idents))))?; - let #fields_idents = turbo_tasks::FromTaskInput::try_from(#fields_idents)?; + let #fields_idents = turbo_tasks::TaskInput::try_from_concrete(#fields_idents)?; )* }, quote! { #( - let #fields_idents: turbo_tasks::TaskInput = #fields_idents.into(); + let #fields_idents = #fields_idents.into_concrete(); #inputs_list_ident.push(#fields_idents); )* }, @@ -260,12 +244,12 @@ fn expand_unnamed( quote! { #( let #fields_idents = #inputs_list_ident.next().ok_or_else(|| anyhow::anyhow!(concat!("missing element for ", stringify!(#fields_idents))))?; - let #fields_idents = turbo_tasks::FromTaskInput::try_from(#fields_idents)?; + let #fields_idents = turbo_tasks::TaskInput::try_from_concrete(#fields_idents)?; )* }, quote! { #( - let #fields_idents: turbo_tasks::TaskInput = #fields_idents.into(); + let #fields_idents = #fields_idents.into_concrete(); #inputs_list_ident.push(#fields_idents); )* }, diff --git a/crates/turbo-tasks-macros/src/derive/value_debug_format_macro.rs b/crates/turbo-tasks-macros/src/derive/value_debug_format_macro.rs index 29cf401506477c..5612261de365f6 100644 --- a/crates/turbo-tasks-macros/src/derive/value_debug_format_macro.rs +++ b/crates/turbo-tasks-macros/src/derive/value_debug_format_macro.rs @@ -25,17 +25,18 @@ pub fn derive_value_debug_format(input: TokenStream) -> TokenStream { let value_debug_format_ident = get_value_debug_format_ident(ident); quote! { + #[doc(hidden)] impl #ident { #[doc(hidden)] #[allow(non_snake_case)] - async fn #value_debug_format_ident(&self, depth: usize) -> anyhow::Result { + async fn #value_debug_format_ident(&self, depth: usize) -> anyhow::Result> { if depth == 0 { - return Ok(turbo_tasks::debug::ValueDebugStringVc::new(stringify!(#ident).to_string())); + return Ok(turbo_tasks::debug::ValueDebugString::new(stringify!(#ident).to_string())); } use turbo_tasks::debug::internal::*; use turbo_tasks::debug::ValueDebugFormat; - Ok(turbo_tasks::debug::ValueDebugStringVc::new(format!("{:#?}", #formatting_logic))) + Ok(turbo_tasks::debug::ValueDebugString::new(format!("{:#?}", #formatting_logic))) } } diff --git a/crates/turbo-tasks-macros/src/derive/value_debug_macro.rs b/crates/turbo-tasks-macros/src/derive/value_debug_macro.rs index 3af4143ab28b50..7e9fc975040da2 100644 --- a/crates/turbo-tasks-macros/src/derive/value_debug_macro.rs +++ b/crates/turbo-tasks-macros/src/derive/value_debug_macro.rs @@ -16,12 +16,12 @@ pub fn derive_value_debug(input: TokenStream) -> TokenStream { #[turbo_tasks::value_impl] impl turbo_tasks::debug::ValueDebug for #ident { #[turbo_tasks::function] - async fn dbg(&self) -> anyhow::Result { + async fn dbg(&self) -> anyhow::Result> { self.#value_debug_format_ident(usize::MAX).await } #[turbo_tasks::function] - async fn dbg_depth(&self, depth: usize) -> anyhow::Result { + async fn dbg_depth(&self, depth: usize) -> anyhow::Result> { self.#value_debug_format_ident(depth).await } } diff --git a/crates/turbo-tasks-macros/src/derive/value_macro.rs b/crates/turbo-tasks-macros/src/derive/value_macro.rs new file mode 100644 index 00000000000000..8b137891791fe9 --- /dev/null +++ b/crates/turbo-tasks-macros/src/derive/value_macro.rs @@ -0,0 +1 @@ + diff --git a/crates/turbo-tasks-macros/src/func.rs b/crates/turbo-tasks-macros/src/func.rs index 8d59a163906236..6afda74a7bad8c 100644 --- a/crates/turbo-tasks-macros/src/func.rs +++ b/crates/turbo-tasks-macros/src/func.rs @@ -1,251 +1,397 @@ -use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; -use proc_macro_error::abort; -use quote::quote; +use proc_macro2::Ident; use syn::{ - punctuated::Punctuated, spanned::Spanned, FnArg, Pat, PatIdent, PatType, Receiver, ReturnType, - Signature, Token, Type, TypePath, TypeReference, + parse_quote, punctuated::Punctuated, spanned::Spanned, Block, Expr, ExprPath, FnArg, Pat, + PatIdent, PatType, Path, Receiver, ReturnType, Signature, Token, Type, }; -use crate::util::*; +#[derive(Debug)] +pub struct TurboFn { + // signature: Signature, + // block: Block, + ident: Ident, + output: Type, + inputs: Vec, +} -/// The underlying type of the `self` identifier. -pub enum SelfType<'a> { - Value(&'a Ident), - Ref, - ValueTrait, +#[derive(Debug)] +pub struct Input { + pub ident: Ident, + pub ty: Type, } -pub fn gen_native_function_code( - name_code: TokenStream2, - original_function: TokenStream2, - function_ident: &Ident, - function_id_ident: &Ident, - async_function: bool, - inputs: &Punctuated, - output_type: &Type, - self_ref_type: Option<(&Ident, SelfType<'_>)>, -) -> (TokenStream2, Vec) { - let mut input_extraction = Vec::new(); - let mut input_convert = Vec::new(); - let mut input_clone = Vec::new(); - let mut input_final = Vec::new(); - let mut input_arguments = Vec::new(); - let mut input_raw_vc_arguments = Vec::new(); - - let mut index: i32 = 1; - - for input in inputs { - match input { - FnArg::Receiver(Receiver { mutability, .. }) => { - if mutability.is_some() { - input - .span() - .unwrap() - .error( - "mutable self is not supported in turbo_task traits (nodes are \ - immutable)", - ) - .emit(); - } +impl TurboFn { + pub fn new( + original_signature: &Signature, + definition_context: DefinitionContext, + ) -> Option { + if !original_signature.generics.params.is_empty() { + original_signature + .generics + .span() + .unwrap() + .error(format!( + "{} do not support generic parameters", + definition_context.function_type(), + )) + .emit(); + return None; + } + + if original_signature.generics.where_clause.is_some() { + original_signature + .generics + .where_clause + .span() + .unwrap() + .error(format!( + "{} do not support where clauses", + definition_context.function_type(), + )) + .emit(); + return None; + } - let (self_ref_ident, self_type) = match self_ref_type.as_ref() { - Some(self_ref_type) => self_ref_type, - None => { - abort!(input.span(), "unexpected receiver argument"); + let mut raw_inputs = original_signature.inputs.iter(); + let mut inputs = Vec::with_capacity(raw_inputs.len()); + + if let Some(possibly_receiver) = raw_inputs.next() { + match possibly_receiver { + FnArg::Receiver( + receiver @ Receiver { + attrs, + self_token, + reference, + mutability, + }, + ) => { + if !attrs.is_empty() { + receiver + .span() + .unwrap() + .error(format!( + "{} do not support attributes on arguments", + definition_context.function_type(), + )) + .emit(); + return None; } - }; - input_extraction.push(quote! { - let Some(__self) = __iter.next() else { - anyhow::bail!("{}() self argument missing", #name_code); + + // tt::functions in tt::value_impl can either take self as a typed `self: + // Vc`, or as immutable references `&self`. We must validate against any + // other forms of self. + + let definition_context = match &definition_context { + DefinitionContext::NakedFn { .. } => return None, + _ => &definition_context, }; - }); - input_convert.push(quote! { - let __self: #self_ref_ident = turbo_tasks::FromTaskInput::try_from(__self)?; - }); - input_clone.push(quote! { - let __self = std::clone::Clone::clone(&__self); - }); - match self_type { - SelfType::Value(self_ident) => { - // We can't use `IntoFuture` directly here because we want to retain - // transparent wrapper types. Otherwise calling trait methods on transparent - // types would fail. - input_final.push(quote! { - let __self = __self.node.into_read::<#self_ident>().await?; - }); - input_arguments.push(quote! { - &*__self - }); + + if !attrs.is_empty() { + receiver + .span() + .unwrap() + .error(format!( + "{} do not support attributes on self", + definition_context.function_type(), + )) + .emit(); + return None; } - SelfType::Ref => { - input_arguments.push(quote! { - __self - }); + + if mutability.is_some() { + receiver + .span() + .unwrap() + .error(format!( + "{} cannot take self by mutable reference, use &self or self: \ + Vc instead", + definition_context.function_type(), + )) + .emit(); + return None; } - SelfType::ValueTrait => { - input_arguments.push(quote! { - &__self - }); + + match &reference { + None => { + receiver + .span() + .unwrap() + .error(format!( + "{} cannot take self by value, use &self or self: Vc \ + instead", + definition_context.function_type(), + )) + .emit(); + return None; + } + Some((_, Some(lifetime))) => { + lifetime + .span() + .unwrap() + .error(format!( + "{} cannot take self by reference with a custom lifetime, use \ + &self or self: Vc instead", + definition_context.function_type(), + )) + .emit(); + return None; + } + _ => {} } + + inputs.push(Input { + ident: Ident::new("self", self_token.span()), + ty: parse_quote! { turbo_tasks::Vc }, + }); } - input_raw_vc_arguments.push(quote! { - self.into() - }); - } - FnArg::Typed(PatType { pat, ty, .. }) => { - input_extraction.push(quote! { - let Some(#pat) = __iter.next() else { - anyhow::bail!(concat!("{}() argument ", stringify!(#index), " (", stringify!(#pat), ") missing"), #name_code); - }; - }); - input_final.push(quote! {}); - if let Type::Reference(TypeReference { - and_token, - lifetime: _, - mutability, - elem, - }) = &**ty - { - let ty = if let Type::Path(TypePath { qself: None, path }) = &**elem { - if path.is_ident("str") { - quote! { String } + FnArg::Typed(typed) => { + if !typed.attrs.is_empty() { + typed + .span() + .unwrap() + .error(format!( + "{} does not support attributes on arguments", + definition_context.function_type(), + )) + .emit(); + return None; + } + + let ident = if let Pat::Ident(ident) = &*typed.pat { + if ident.ident == "self" { + if let DefinitionContext::NakedFn { .. } = definition_context { + // The function is not associated. The compiler will emit an error + // on its own. + return None; + }; + + // We don't validate that the user provided a valid + // `turbo_tasks::Vc` here. + // We'll rely on the compiler to emit an error + // if the user provided an invalid receiver type + // when + // calling `into_concrete`. } else { - quote! { #elem } + match definition_context { + DefinitionContext::NakedFn { .. } + | DefinitionContext::ValueInherentImpl { .. } => {} + DefinitionContext::ValueTraitImpl { .. } + | DefinitionContext::ValueTrait { .. } => { + typed + .span() + .unwrap() + .error(format!( + "{} must accept &self or self: Vc as the first \ + argument", + definition_context.function_type(), + )) + .emit(); + return None; + } + } } + + ident.ident.clone() } else { - quote! { #elem } + // We can't support destructuring patterns (or other kinds of patterns). + Ident::new("arg1", typed.pat.span()) }; - input_convert.push(quote! { - let #pat: #ty = turbo_tasks::FromTaskInput::try_from(#pat)?; - }); - input_clone.push(quote! { - let #pat = std::clone::Clone::clone(&#pat); - }); - input_arguments.push(quote! { - #and_token #mutability #pat - }); - } else { - input_convert.push(quote! { - let #pat: #ty = turbo_tasks::FromTaskInput::try_from(#pat)?; - }); - input_clone.push(quote! { - let #pat = std::clone::Clone::clone(&#pat); - }); - input_arguments.push(quote! { - #pat + + inputs.push(Input { + ident, + ty: (*typed.ty).clone(), }); } - let custom_self_type = if let Pat::Ident(PatIdent { ident, .. }) = &**pat { - ident == "self_vc" - } else { - false - }; - if custom_self_type { - input_raw_vc_arguments.push(quote! { - self.into() - }); - } else { - input_raw_vc_arguments.push(quote! { - #pat.into() + } + } + + for (i, input) in raw_inputs.enumerate() { + match input { + FnArg::Receiver(_) => { + // The compiler will emit an error on its own. + return None; + } + FnArg::Typed(typed) => { + let ident = if let Pat::Ident(ident) = &*typed.pat { + ident.ident.clone() + } else { + Ident::new(&format!("arg{}", i + 2), typed.pat.span()) + }; + + inputs.push(Input { + ident, + ty: (*typed.ty).clone(), }); } - index += 1; + } + } + + let output = return_type_to_type(&original_signature.output); + + Some(TurboFn { + ident: original_signature.ident.clone(), + output, + inputs, + }) + } + + /// The signature of the exposed function. This is the original signature + /// converted to a standard turbo_tasks function signature. + pub fn signature(&self) -> Signature { + let exposed_inputs: Punctuated<_, Token![,]> = self + .inputs + .iter() + .map(|input| { + FnArg::Typed(PatType { + attrs: Default::default(), + ty: Box::new(input.ty.clone()), + pat: Box::new(Pat::Ident(PatIdent { + attrs: Default::default(), + by_ref: None, + mutability: None, + ident: input.ident.clone(), + subpat: None, + })), + colon_token: Default::default(), + }) + }) + .collect(); + + let ident = &self.ident; + let output = &self.output; + + parse_quote! { + fn #ident(#exposed_inputs) -> <#output as turbo_tasks::task::TaskOutput>::Return + } + } + + pub fn trait_signature(&self) -> Signature { + let signature = self.signature(); + + parse_quote! { + #signature where Self: Sized + } + } + + fn converted_inputs(&self) -> Punctuated { + self.inputs + .iter() + .map(|Input { ty, ident }| -> Expr { + parse_quote! { + <#ty as turbo_tasks::task::TaskInput>::into_concrete(#ident) + } + }) + .collect() + } + + /// The block of the exposed function for a dynamic dispatch call to the + /// given trait. + pub fn dynamic_block(&self, trait_type_id_ident: &Ident) -> Block { + let ident = &self.ident; + let output = &self.output; + let converted_inputs = self.converted_inputs(); + parse_quote! { + { + <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( + turbo_tasks::trait_call( + *#trait_type_id_ident, + std::borrow::Cow::Borrowed(stringify!(#ident)), + vec![#converted_inputs], + ) + ) } } } - let original_call_code = if async_function { - quote! { #original_function(#(#input_arguments),*).await } - } else { - quote! { #original_function(#(#input_arguments),*) } - }; - let (raw_output_type, is_result) = unwrap_result_type(output_type); - let original_call_code = match (is_result, is_empty_type(raw_output_type)) { - (true, true) => quote! { - (#original_call_code).map(|_| turbo_tasks::NothingVc::new().into()) - }, - (true, false) => quote! { #original_call_code.map(|v| v.into()) }, - (false, true) => quote! { + + /// The block of the exposed function for a static dispatch call to the + /// given native function. + pub fn static_block(&self, native_function_id_ident: &Ident) -> Block { + let output = &self.output; + let converted_inputs = self.converted_inputs(); + parse_quote! { { - #original_call_code; - Ok(turbo_tasks::NothingVc::new().into()) + <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( + turbo_tasks::dynamic_call( + *#native_function_id_ident, + vec![#converted_inputs], + ) + ) } - }, - (false, false) => quote! { Ok(#original_call_code.into()) }, - }; - ( - quote! { - #[doc(hidden)] - pub(crate) static #function_ident: turbo_tasks::macro_helpers::Lazy = - turbo_tasks::macro_helpers::Lazy::new(|| { - turbo_tasks::NativeFunction::new(#name_code.to_owned(), Box::new(|inputs| { - let mut __iter = inputs.iter(); - #(#input_extraction)* - if __iter.next().is_some() { - return Err(anyhow::anyhow!("{}() called with too many arguments", #name_code)); - } - #(#input_convert)* - Ok(Box::new(move || { - #(#input_clone)* - Box::pin(turbo_tasks::macro_helpers::tracing::Instrument::instrument(async move { - #(#input_final)* - let turbo_tasks_result = #original_call_code; - turbo_tasks::macro_helpers::notify_scheduled_tasks(); - turbo_tasks_result - }, turbo_tasks::macro_helpers::tracing::trace_span!(#name_code))) - })) - })) - }); - - #[doc(hidden)] - pub(crate) static #function_id_ident: turbo_tasks::macro_helpers::Lazy = - turbo_tasks::macro_helpers::Lazy::new(|| { - turbo_tasks::registry::get_function_id(&#function_ident) - }); - }, - input_raw_vc_arguments, - ) + } + } } -pub fn split_signature(sig: &Signature) -> (Signature, Signature, Type, TokenStream2) { - let output_type = get_return_type(&sig.output); - let inline_ident = get_internal_function_ident(&sig.ident); - let mut inline_sig = sig.clone(); - inline_sig.ident = inline_ident; - - let mut external_sig = sig.clone(); - external_sig.asyncness = None; - - let (raw_output_type, _) = unwrap_result_type(&output_type); - - let convert_result_code = if is_empty_type(raw_output_type) { - external_sig.output = ReturnType::Default; - quote! {} - } else { - external_sig.output = ReturnType::Type( - Token![->](raw_output_type.span()), - Box::new(raw_output_type.clone()), - ); - quote! { std::convert::From::::from(result) } - }; - - let custom_self_type = if let Some(FnArg::Typed(PatType { - pat: box Pat::Ident(PatIdent { ident, .. }), - .. - })) = sig.inputs.first() - { - ident == "self_vc" - } else { - false - }; - if custom_self_type { - let external_self = external_sig.inputs.first_mut().unwrap(); - *external_self = FnArg::Receiver(Receiver { - attrs: Vec::new(), - reference: Some((Token![&](Span::call_site()), None)), - mutability: None, - self_token: Token![self](Span::call_site()), - }); +fn return_type_to_type(return_type: &ReturnType) -> Type { + match return_type { + ReturnType::Default => parse_quote! { () }, + ReturnType::Type(_, ref return_type) => (**return_type).clone(), } +} - (external_sig, inline_sig, output_type, convert_result_code) +/// The context in which the function is being defined. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum DefinitionContext { + // The function is defined as a naked #[turbo_tasks::function]. + NakedFn, + // The function is defined as a #[turbo_tasks::value_impl] inherent implementation method. + ValueInherentImpl, + // The function is defined as a #[turbo_tasks::value_impl] trait implementation method. + ValueTraitImpl, + // The function is defined as a #[turbo_tasks::value_trait] default method. + ValueTrait, +} + +impl DefinitionContext { + pub fn function_type(&self) -> &'static str { + match self { + DefinitionContext::NakedFn => "#[turbo_tasks::function] naked functions", + DefinitionContext::ValueInherentImpl => "#[turbo_tasks::value_impl] inherent methods", + DefinitionContext::ValueTraitImpl => "#[turbo_tasks::value_impl] trait methods", + DefinitionContext::ValueTrait => "#[turbo_tasks::value_trait] methods", + } + } +} + +#[derive(Debug)] +pub struct NativeFn { + function_path_string: String, + function_path: ExprPath, +} + +impl NativeFn { + pub fn new(function_path_string: &str, function_path: &ExprPath) -> NativeFn { + NativeFn { + function_path_string: function_path_string.to_owned(), + function_path: function_path.clone(), + } + } + + pub fn ty(&self) -> Type { + parse_quote! { turbo_tasks::macro_helpers::Lazy } + } + + pub fn definition(&self) -> Expr { + let Self { + function_path_string, + function_path, + } = self; + + parse_quote! { + turbo_tasks::macro_helpers::Lazy::new(|| { + #[allow(deprecated)] + turbo_tasks::NativeFunction::new(#function_path_string.to_owned(), #function_path) + }) + } + } + + pub fn id_ty(&self) -> Type { + parse_quote! { turbo_tasks::macro_helpers::Lazy } + } + + pub fn id_definition(&self, native_function_id_path: &Path) -> Expr { + parse_quote! { + turbo_tasks::macro_helpers::Lazy::new(|| { + turbo_tasks::registry::get_function_id(&*#native_function_id_path) + }) + } + } } diff --git a/crates/turbo-tasks-macros/src/function_macro.rs b/crates/turbo-tasks-macros/src/function_macro.rs index 983f1d3c64a798..726ca56ecbb345 100644 --- a/crates/turbo-tasks-macros/src/function_macro.rs +++ b/crates/turbo-tasks-macros/src/function_macro.rs @@ -1,54 +1,59 @@ use proc_macro::TokenStream; use proc_macro2::Ident; use quote::quote; -use syn::{parse_macro_input, ItemFn}; -use turbo_tasks_macros_shared::get_function_ident; +use syn::{parse_macro_input, parse_quote, ExprPath, ItemFn}; +use turbo_tasks_macros_shared::{get_native_function_id_ident, get_native_function_ident}; -use crate::func::{gen_native_function_code, split_signature}; - -fn get_function_id_ident(ident: &Ident) -> Ident { - Ident::new( - &(ident.to_string().to_uppercase() + "_FUNCTION_ID"), - ident.span(), - ) -} +use crate::func::{DefinitionContext, NativeFn, TurboFn}; pub fn function(_args: TokenStream, input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as ItemFn); + let ItemFn { attrs, vis, sig, block, } = &item; - let (external_sig, inline_sig, output_type, convert_result_code) = split_signature(sig); + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::NakedFn) else { + return quote! { + // An error occurred while parsing the function signature. + }.into(); + }; + let ident = &sig.ident; - let function_ident = get_function_ident(ident); - let function_id_ident = get_function_id_ident(ident); - let inline_ident = &inline_sig.ident; - - let (native_function_code, input_raw_vc_arguments) = gen_native_function_code( - quote! { stringify!(#ident) }, - quote! { #inline_ident }, - &function_ident, - &function_id_ident, - sig.asyncness.is_some(), - &sig.inputs, - &output_type, - None, - ); + + let inline_function_ident = Ident::new(&format!("{ident}_inline_function"), ident.span()); + let inline_function_path: ExprPath = parse_quote! { #inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let native_fn = NativeFn::new(&ident.to_string(), &inline_function_path); + let native_function_ident = get_native_function_ident(ident); + let native_function_ty = native_fn.ty(); + let native_function_def = native_fn.definition(); + + let native_function_id_ident = get_native_function_id_ident(ident); + let native_function_id_ty = native_fn.id_ty(); + let native_function_id_def = native_fn.id_definition(&native_function_ident.clone().into()); + + let exposed_signature = turbo_fn.signature(); + let exposed_block = turbo_fn.static_block(&native_function_id_ident); quote! { #(#attrs)* - #vis #external_sig { - let result = turbo_tasks::dynamic_call(*#function_id_ident, vec![#(#input_raw_vc_arguments),*]); - #convert_result_code - } + #vis #exposed_signature #exposed_block #(#attrs)* - #vis #inline_sig #block + #[doc(hidden)] + #inline_signature #block + + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = #native_function_def; - #native_function_code + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = #native_function_id_def; } .into() } diff --git a/crates/turbo-tasks-macros/src/lib.rs b/crates/turbo-tasks-macros/src/lib.rs index d3362ed2431062..1b51ffd1d323f0 100644 --- a/crates/turbo-tasks-macros/src/lib.rs +++ b/crates/turbo-tasks-macros/src/lib.rs @@ -6,7 +6,7 @@ mod derive; mod func; mod function_macro; -mod util; +mod primitive_macro; mod value_impl_macro; mod value_macro; mod value_trait_macro; @@ -41,16 +41,16 @@ pub fn derive_task_input(input: TokenStream) -> TokenStream { derive::derive_task_input(input) } -/// Creates a ValueVc struct for a `struct` or `enum` that represent +/// Creates a Vc struct for a `struct` or `enum` that represent /// that type placed into a cell in a Task. /// -/// That ValueVc object can be `.await?`ed to get a readonly reference +/// That Vc object can be `.await?`ed to get a readonly reference /// to the original value. /// /// `into` argument (`#[turbo_tasks::value(into: xxx)]`) /// -/// When provided the ValueVc implement `From` to allow to convert -/// a Value to a ValueVc by placing it into a cell in a Task. +/// When provided the Vc implement `From` to allow to convert +/// a Value to a Vc by placing it into a cell in a Task. /// /// `into: new`: Always overrides the value in the cell. Invalidating all /// dependent tasks. @@ -86,3 +86,10 @@ pub fn function(args: TokenStream, input: TokenStream) -> TokenStream { pub fn value_impl(args: TokenStream, input: TokenStream) -> TokenStream { value_impl_macro::value_impl(args, input) } + +#[allow_internal_unstable(min_specialization, into_future, trivial_bounds)] +#[proc_macro_error] +#[proc_macro] +pub fn primitive(input: TokenStream) -> TokenStream { + primitive_macro::primitive(input) +} diff --git a/crates/turbo-tasks-macros/src/primitive_macro.rs b/crates/turbo-tasks-macros/src/primitive_macro.rs new file mode 100644 index 00000000000000..243120c0e38e79 --- /dev/null +++ b/crates/turbo-tasks-macros/src/primitive_macro.rs @@ -0,0 +1,55 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::parse_macro_input; +use turbo_tasks_macros_shared::{get_type_ident, PrimitiveInput}; + +use crate::value_macro::value_type_and_register; + +pub fn primitive(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as PrimitiveInput); + + let ty = input.ty; + let Some(ident) = get_type_ident(&ty) else { + return quote! { + // An error occurred while parsing the ident. + }.into(); + }; + + let value_debug_impl = quote! { + #[turbo_tasks::value_impl] + impl turbo_tasks::debug::ValueDebug for #ty { + #[turbo_tasks::function] + async fn dbg(&self) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + self.value_debug_format(usize::MAX).try_to_value_debug_string().await + } + + #[turbo_tasks::function] + async fn dbg_depth(&self, depth: usize) -> anyhow::Result> { + use turbo_tasks::debug::ValueDebugFormat; + self.value_debug_format(depth).try_to_value_debug_string().await + } + } + }; + + let value_type_and_register = value_type_and_register( + &ident, + quote! { #ty }, + quote! { + turbo_tasks::VcTransparentRead<#ty, #ty> + }, + quote! { + turbo_tasks::VcCellSharedMode<#ty> + }, + quote! { + turbo_tasks::ValueType::new_with_any_serialization::<#ty>() + }, + ); + + quote! { + #value_type_and_register + + #value_debug_impl + } + .into() +} diff --git a/crates/turbo-tasks-macros/src/util.rs b/crates/turbo-tasks-macros/src/util.rs deleted file mode 100644 index 16d7960d5bbab8..00000000000000 --- a/crates/turbo-tasks-macros/src/util.rs +++ /dev/null @@ -1,90 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::{ - punctuated::Punctuated, token::Paren, AngleBracketedGenericArguments, GenericArgument, Ident, - Path, PathArguments, PathSegment, ReturnType, Type, TypePath, TypeTuple, -}; -use turbo_tasks_macros_shared::get_ref_ident; - -pub fn unwrap_result_type(ty: &Type) -> (&Type, bool) { - if let Type::Path(TypePath { - qself: None, - path: Path { segments, .. }, - }) = ty - { - if let Some(PathSegment { - ident, - arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }), - }) = segments.last() - { - if &ident.to_string() == "Result" { - if let Some(GenericArgument::Type(ty)) = args.first() { - return (ty, true); - } - } - } - } - (ty, false) -} - -pub fn is_empty_type(ty: &Type) -> bool { - if let Type::Tuple(TypeTuple { elems, .. }) = ty { - if elems.is_empty() { - return true; - } - } - false -} - -pub fn get_return_type(output: &ReturnType) -> Type { - match output { - ReturnType::Default => Type::Tuple(TypeTuple { - paren_token: Paren::default(), - elems: Punctuated::new(), - }), - ReturnType::Type(_, ref output_type) => (**output_type).clone(), - } -} - -pub fn get_internal_function_ident(ident: &Ident) -> Ident { - Ident::new(&format!("{ident}_inline"), ident.span()) -} - -pub fn get_as_super_ident(ident: &Ident) -> Ident { - use convert_case::{Case, Casing}; - Ident::new( - &format!("as_{}", ident.to_string().to_case(Case::Snake)), - ident.span(), - ) -} - -pub fn get_ref_path(path: &Path) -> Path { - let mut path = path.clone(); - if let Some(last_segment) = path.segments.last_mut() { - last_segment.ident = get_ref_ident(&last_segment.ident); - } - path -} - -pub fn strongly_consistent_doccomment() -> TokenStream { - quote! { - /// The invalidation of tasks due to changes is eventually consistent by default. - /// Tasks will execute as early as any of their children has changed, even while - /// other children or grandchildren are still computing (and may or may not result - /// in a future invalidation). Tasks may execute multiple times until the graph - /// reaches the end state. Partial applied changes might be visible to the user. - /// But changes are available as fast as possible and won't be blocked by some - /// slower parts of the graph (e. g. recomputation of blurred images, linting, - /// etc). - /// - /// When you read a task with `.strongly_consistent()` it will make that one read - /// operation strongly consistent. That means it will only return a result when all - /// children and grandchildren in that graph have been settled. This means your - /// current task will recompute less often, but it might also need to wait for - /// slower operations in the graph and can't continue with partial applied changes. - /// - /// Reading strongly consistent is also far more expensive compared to normal - /// reading, so it should be used with care. - /// - } -} diff --git a/crates/turbo-tasks-macros/src/value_impl_macro.rs b/crates/turbo-tasks-macros/src/value_impl_macro.rs index bdb589a90c824a..246b353b07eae5 100644 --- a/crates/turbo-tasks-macros/src/value_impl_macro.rs +++ b/crates/turbo-tasks-macros/src/value_impl_macro.rs @@ -1,53 +1,21 @@ use proc_macro::TokenStream; -use proc_macro2::{Ident, Literal, Span, TokenStream as TokenStream2}; -use quote::quote; +use proc_macro2::{Ident, TokenStream as TokenStream2}; +use quote::{quote, ToTokens}; use syn::{ - parse_macro_input, spanned::Spanned, Attribute, FnArg, ImplItem, ImplItemMethod, ItemImpl, - Path, Receiver, ReturnType, Signature, Token, Type, TypePath, + parse::{Parse, ParseStream}, + parse_macro_input, parse_quote, + punctuated::Punctuated, + spanned::Spanned, + Attribute, Error, ExprPath, ImplItem, ImplItemMethod, ItemImpl, Lit, LitStr, Meta, + MetaNameValue, Path, Result, Token, Type, }; use turbo_tasks_macros_shared::{ - get_impl_function_ident, get_ref_ident, get_register_trait_methods_ident, - get_trait_impl_function_ident, + get_inherent_impl_function_id_ident, get_inherent_impl_function_ident, get_path_ident, + get_register_trait_methods_ident, get_trait_impl_function_id_ident, + get_trait_impl_function_ident, get_type_ident, }; -use crate::{ - func::{gen_native_function_code, split_signature, SelfType}, - util::*, -}; - -fn get_internal_trait_impl_function_ident(trait_ident: &Ident, ident: &Ident) -> Ident { - Ident::new( - &format!("__trait_call_{trait_ident}_{ident}"), - trait_ident.span(), - ) -} - -fn get_impl_function_id_ident(struct_ident: &Ident, ident: &Ident) -> Ident { - Ident::new( - &format!( - "{}_IMPL_{}_FUNCTION_ID", - struct_ident.to_string().to_uppercase(), - ident.to_string().to_uppercase() - ), - ident.span(), - ) -} - -fn get_trait_impl_function_id_ident( - struct_ident: &Ident, - trait_ident: &Ident, - ident: &Ident, -) -> Ident { - Ident::new( - &format!( - "{}_IMPL_TRAIT_{}_{}_FUNCTION_ID", - struct_ident.to_string().to_uppercase(), - trait_ident.to_string().to_uppercase(), - ident.to_string().to_uppercase() - ), - ident.span(), - ) -} +use crate::func::{DefinitionContext, NativeFn, TurboFn}; fn is_attribute(attr: &Attribute, name: &str) -> bool { let path = &attr.path; @@ -64,9 +32,64 @@ fn is_attribute(attr: &Attribute, name: &str) -> bool { } } -pub fn value_impl(_args: TokenStream, input: TokenStream) -> TokenStream { - fn generate_for_vc_impl(vc_ident: &Ident, items: &[ImplItem]) -> TokenStream2 { - let mut functions = Vec::new(); +fn strip_function_attribute<'a>(item: &'a ImplItem, attrs: &'a [Attribute]) -> Vec<&'a Attribute> { + let (function_attrs, attrs): (Vec<_>, Vec<_>) = attrs + .iter() + // TODO(alexkirsz) Replace this with function + .partition(|attr| is_attribute(attr, "function")); + if function_attrs.is_empty() { + item.span() + .unwrap() + .error("#[turbo_tasks::function] attribute missing") + .emit(); + } + attrs +} + +struct ValueImplArguments { + ident: Option, +} + +impl Parse for ValueImplArguments { + fn parse(input: ParseStream) -> Result { + let mut result = ValueImplArguments { ident: None }; + let punctuated: Punctuated = input.parse_terminated(Meta::parse)?; + for meta in punctuated { + match ( + meta.path() + .get_ident() + .map(ToString::to_string) + .as_deref() + .unwrap_or_default(), + meta, + ) { + ( + "ident", + Meta::NameValue(MetaNameValue { + lit: Lit::Str(lit), .. + }), + ) => { + result.ident = Some(lit); + } + (_, meta) => { + return Err(Error::new_spanned( + &meta, + format!("unexpected {:?}, expected \"ident\"", meta), + )) + } + } + } + + Ok(result) + } +} + +pub fn value_impl(args: TokenStream, input: TokenStream) -> TokenStream { + let ValueImplArguments { ident } = parse_macro_input!(args as ValueImplArguments); + + fn inherent_value_impl(ty: &Type, ty_ident: &Ident, items: &[ImplItem]) -> TokenStream2 { + let mut all_definitions = Vec::new(); + let mut exposed_impl_items = Vec::new(); for item in items.iter() { if let ImplItem::Method(ImplItemMethod { @@ -77,225 +100,228 @@ pub fn value_impl(_args: TokenStream, input: TokenStream) -> TokenStream { block, }) = item { - let function_attr = attrs.iter().find(|attr| is_attribute(attr, "function")); - let attrs = if function_attr.is_none() { - item.span() - .unwrap() - .error("#[turbo_tasks::function] attribute missing") - .emit(); - attrs.clone() - } else { - attrs - .iter() - .filter(|attr| !is_attribute(attr, "function")) - .cloned() - .collect() + let attrs = strip_function_attribute(item, attrs); + + let ident = &sig.ident; + + // TODO(alexkirsz) These should go into their own utilities. + let inline_function_ident: Ident = + Ident::new(&format!("{}_inline", ident), ident.span()); + let inline_function_path: ExprPath = parse_quote! { <#ty>::#inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::ValueInherentImpl) else { + return quote! { + // An error occurred while parsing the function signature. + }; }; - let Signature { ident, .. } = sig; - - let (external_sig, inline_sig, output_type, convert_result_code) = - split_signature(sig); - - let inline_ident = &inline_sig.ident; - let function_ident = get_impl_function_ident(vc_ident, ident); - let function_id_ident = get_impl_function_id_ident(vc_ident, ident); - - let (native_function_code, input_raw_vc_arguments) = gen_native_function_code( - // use const string - quote! { concat!(stringify!(#vc_ident), "::", stringify!(#ident)) }, - quote! { #vc_ident::#inline_ident }, - &function_ident, - &function_id_ident, - sig.asyncness.is_some(), - &sig.inputs, - &output_type, - Some((vc_ident, SelfType::Ref)), + + let native_fn = NativeFn::new( + &format!("{ty}::{ident}", ty = ty.to_token_stream()), + &inline_function_path, ); - functions.push(quote! { - impl #vc_ident { - #(#attrs)* - #vis #external_sig { - let result = turbo_tasks::dynamic_call(*#function_id_ident, vec![#(#input_raw_vc_arguments),*]); - #convert_result_code - } + let native_function_ident = get_inherent_impl_function_ident(ty_ident, ident); + let native_function_ty = native_fn.ty(); + let native_function_def = native_fn.definition(); + let native_function_id_ident = get_inherent_impl_function_id_ident(ty_ident, ident); + let native_function_id_ty = native_fn.id_ty(); + let native_function_id_def = native_fn.id_definition(&parse_quote! { + #native_function_ident + }); + + let turbo_signature = turbo_fn.signature(); + let turbo_block = turbo_fn.static_block(&native_function_id_ident); + exposed_impl_items.push(quote! { + #(#attrs)* + #vis #turbo_signature #turbo_block + }); + + all_definitions.push(quote! { + #[doc(hidden)] + impl #ty { + // By declaring the native function's body within an `impl` block, we ensure that `Self` refers + // to `#ty`. This is necessary because the function's body is originally declared within an + // `impl` block already. + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_ident: #native_function_ty = #native_function_def; + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_id_ident: #native_function_id_ty = #native_function_id_def; #(#attrs)* #[doc(hidden)] - #vis #inline_sig #block + #[deprecated(note = "This function is only exposed for use in macros. Do not call it directly.")] + pub(self) #inline_signature #block } - #native_function_code + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = #ty::#native_function_ident; + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = #ty::#native_function_id_ident; }) } } quote! { - #(#functions)* + impl #ty { + #(#exposed_impl_items)* + } + + #(#all_definitions)* } } - fn generate_for_trait_impl( + fn trait_value_impl( + ty: &Type, + ty_ident: &Ident, trait_path: &Path, - struct_ident: &Ident, items: &[ImplItem], ) -> TokenStream2 { - let trait_ident = &trait_path.segments.last().unwrap().ident; - let register = get_register_trait_methods_ident(trait_ident, struct_ident); - let ref_ident = get_ref_ident(struct_ident); - let trait_ref_path = get_ref_path(trait_path); - let as_trait_method = get_as_super_ident(trait_ident); + let trait_ident = get_path_ident(trait_path); + + let register = get_register_trait_methods_ident(&trait_ident, ty_ident); let mut trait_registers = Vec::new(); - let mut impl_functions = Vec::new(); - let mut trait_functions = Vec::new(); + let mut trait_functions = Vec::with_capacity(items.len()); + let mut all_definitions = Vec::with_capacity(items.len()); + for item in items.iter() { if let ImplItem::Method(ImplItemMethod { sig, attrs, block, .. }) = item { - let function_attr = attrs.iter().find(|attr| is_attribute(attr, "function")); - let attrs = if function_attr.is_none() { - item.span() - .unwrap() - .error("#[turbo_tasks::function] attribute missing") - .emit(); - attrs.clone() - } else { - attrs - .iter() - .filter(|attr| !is_attribute(attr, "function")) - .cloned() - .collect() + let ident = &sig.ident; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::ValueTraitImpl) else { + return quote! { + // An error occurred while parsing the function signature. + }; }; - let Signature { - ident, - inputs, - output, - asyncness, - .. - } = sig; - let output_type = get_return_type(output); - let function_ident = - get_trait_impl_function_ident(struct_ident, trait_ident, ident); - let function_id_ident = - get_trait_impl_function_id_ident(struct_ident, trait_ident, ident); - let internal_function_ident = - get_internal_trait_impl_function_ident(trait_ident, ident); - trait_registers.push(quote! { - value.register_trait_method(<#trait_ref_path as turbo_tasks::ValueTraitVc>::get_trait_type_id(), stringify!(#ident).into(), *#function_id_ident); - }); - let name = Literal::string(&(struct_ident.to_string() + "::" + &ident.to_string())); - let (native_function_code, mut input_raw_vc_arguments) = gen_native_function_code( - quote! { #name }, - quote! { #struct_ident::#internal_function_ident }, - &function_ident, - &function_id_ident, - asyncness.is_some(), - inputs, - &output_type, - Some((&ref_ident, SelfType::Value(struct_ident))), + + let attrs = strip_function_attribute(item, attrs); + + // TODO(alexkirsz) These should go into their own utilities. + let inline_function_ident: Ident = + Ident::new(&format!("{}_inline", ident), ident.span()); + let inline_extension_trait_ident = Ident::new( + &format!("{}_{}_{}_inline", ty_ident, trait_ident, ident), + ident.span(), + ); + let inline_function_path: ExprPath = + parse_quote! { <#ty as #inline_extension_trait_ident>::#inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let native_fn = NativeFn::new( + &format!( + "<{ty} as {trait_path}>::{ident}", + ty = ty.to_token_stream(), + trait_path = trait_path.to_token_stream() + ), + &inline_function_path, ); - let mut new_sig = sig.clone(); - new_sig.ident = internal_function_ident; - let mut external_sig = sig.clone(); - external_sig.asyncness = None; - let external_self = external_sig.inputs.first_mut().unwrap(); - let custom_self_type = matches!(sig.inputs.first().unwrap(), FnArg::Typed(..)); - if custom_self_type { - *external_self = FnArg::Receiver(Receiver { - attrs: Vec::new(), - reference: Some((Token![&](Span::call_site()), None)), - mutability: None, - self_token: Token![self](Span::call_site()), - }); - input_raw_vc_arguments[0] = quote! { self.into() }; - } - impl_functions.push(quote! { - impl #struct_ident { - #(#attrs)* - #[allow(non_snake_case)] - #[doc(hidden)] - #new_sig #block - } - #native_function_code + let native_function_ident = + get_trait_impl_function_ident(ty_ident, &trait_ident, ident); + + let native_function_ty = native_fn.ty(); + let native_function_def = native_fn.definition(); + let native_function_id_ident = + get_trait_impl_function_id_ident(ty_ident, &trait_ident, ident); + let native_function_id_ty = native_fn.id_ty(); + let native_function_id_def = native_fn.id_definition(&parse_quote! { + #native_function_ident }); - let (raw_output_type, _) = unwrap_result_type(&output_type); - let convert_result_code = if is_empty_type(raw_output_type) { - external_sig.output = ReturnType::Default; - quote! {} - } else { - external_sig.output = ReturnType::Type( - Token![->](raw_output_type.span()), - Box::new(raw_output_type.clone()), - ); - quote! { std::convert::From::::from(result) } - }; + let turbo_signature = turbo_fn.signature(); + let turbo_block = turbo_fn.static_block(&native_function_id_ident); - trait_functions.push(quote!{ + trait_functions.push(quote! { #(#attrs)* - #external_sig { - let result = turbo_tasks::dynamic_call(*#function_id_ident, vec![#(#input_raw_vc_arguments),*]); - #convert_result_code + #turbo_signature #turbo_block + }); + + all_definitions.push(quote! { + #[doc(hidden)] + #[allow(non_camel_case_types)] + // #[turbo_tasks::async_trait] + trait #inline_extension_trait_ident { + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_ident: #native_function_ty; + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_id_ident: #native_function_id_ty; + + #(#attrs)* + #[doc(hidden)] + #inline_signature; + } + + #[doc(hidden)] + // #[turbo_tasks::async_trait] + impl #inline_extension_trait_ident for #ty { + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_ident: #native_function_ty = #native_function_def; + #[allow(declare_interior_mutable_const)] + #[doc(hidden)] + const #native_function_id_ident: #native_function_id_ty = #native_function_id_def; + + #(#attrs)* + #[doc(hidden)] + #[deprecated(note = "This function is only exposed for use in macros. Do not call it directly.")] + #inline_signature #block } + + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = <#ty as #inline_extension_trait_ident>::#native_function_ident; + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = <#ty as #inline_extension_trait_ident>::#native_function_id_ident; + }); + + trait_registers.push(quote! { + value.register_trait_method( as turbo_tasks::VcValueTrait>::get_trait_type_id(), stringify!(#ident).into(), *#native_function_id_ident); }); } } + quote! { #[doc(hidden)] #[allow(non_snake_case)] pub(crate) fn #register(value: &mut turbo_tasks::ValueType) { - value.register_trait(<#trait_ref_path as turbo_tasks::ValueTraitVc>::get_trait_type_id()); + value.register_trait( as turbo_tasks::VcValueTrait>::get_trait_type_id()); #(#trait_registers)* } - #(#impl_functions)* - - impl #ref_ident { - pub fn #as_trait_method(self) -> #trait_ref_path { - self.into() - } - } - - impl From<#ref_ident> for #trait_ref_path { - fn from(node_ref: #ref_ident) -> Self { - node_ref.node.into() - } - } + // NOTE(alexkirsz) We can't have a general `turbo_tasks::Upcast> for T where T: Trait` because + // rustc complains: error[E0210]: type parameter `T` must be covered by another type when it appears before + // the first local type (`dyn Trait`). + unsafe impl turbo_tasks::Upcast> for #ty {} - impl #trait_path for #ref_ident { + impl #trait_path for #ty { #(#trait_functions)* } + + #(#all_definitions)* } } let item = parse_macro_input!(input as ItemImpl); - if let Type::Path(TypePath { qself: None, path }) = &*item.self_ty { - if let Some(ident) = path.get_ident() { - match &item.trait_ { - None => { - let code = generate_for_vc_impl(ident, &item.items); - return quote! { - #code - } - .into(); - } - Some((_, trait_path, _)) => { - let code = generate_for_trait_impl(trait_path, ident, &item.items); - return quote! { - #code - } - .into(); - } - } + let Some(ty_ident) = ident.map(|ident| Ident::new(&ident.value(), ident.span())).or_else(|| get_type_ident(&item.self_ty)) else { + return quote! { + // An error occurred while parsing the type. + }.into(); + }; + + match &item.trait_ { + None => inherent_value_impl(&item.self_ty, &ty_ident, &item.items).into(), + Some((_, trait_path, _)) => { + trait_value_impl(&item.self_ty, &ty_ident, trait_path, &item.items).into() } } - item.span().unwrap().error("unsupported syntax").emit(); - quote! { - #item - } - .into() } diff --git a/crates/turbo-tasks-macros/src/value_macro.rs b/crates/turbo-tasks-macros/src/value_macro.rs index b2b16463c3f8a3..2ddb9f5eaab787 100644 --- a/crates/turbo-tasks-macros/src/value_macro.rs +++ b/crates/turbo-tasks-macros/src/value_macro.rs @@ -9,34 +9,10 @@ use syn::{ Error, Fields, FieldsUnnamed, Item, ItemEnum, ItemStruct, Lit, LitStr, Meta, MetaNameValue, Result, Token, }; -use turbo_tasks_macros_shared::{get_ref_ident, get_register_value_type_ident}; - -use crate::util::strongly_consistent_doccomment; - -fn get_read_ref_ident(ident: &Ident) -> Ident { - Ident::new(&(ident.to_string() + "ReadRef"), ident.span()) -} - -fn get_value_type_ident(ident: &Ident) -> Ident { - Ident::new( - &format!("{}_VALUE_TYPE", ident.to_string().to_uppercase()), - ident.span(), - ) -} - -fn get_value_type_id_ident(ident: &Ident) -> Ident { - Ident::new( - &format!("{}_VALUE_TYPE_ID", ident.to_string().to_uppercase()), - ident.span(), - ) -} - -fn get_value_type_init_ident(ident: &Ident) -> Ident { - Ident::new( - &format!("{}_VALUE_TYPE_INIT", ident.to_string().to_uppercase()), - ident.span(), - ) -} +use turbo_tasks_macros_shared::{ + get_register_value_type_ident, get_value_type_id_ident, get_value_type_ident, + get_value_type_init_ident, +}; enum IntoMode { None, @@ -222,9 +198,9 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { transparent, } = parse_macro_input!(args as ValueArguments); - let (vis, ident) = match &item { - Item::Enum(ItemEnum { vis, ident, .. }) => (vis, ident), - Item::Struct(ItemStruct { vis, ident, .. }) => (vis, ident), + let ident = match &item { + Item::Enum(ItemEnum { ident, .. }) => ident, + Item::Struct(ItemStruct { ident, .. }) => ident, _ => { item.span().unwrap().error("unsupported syntax").emit(); @@ -235,13 +211,6 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { } }; - let ref_ident = get_ref_ident(ident); - let read_ref_ident = get_read_ref_ident(ident); - let value_type_init_ident = get_value_type_init_ident(ident); - let value_type_ident = get_value_type_ident(ident); - let value_type_id_ident = get_value_type_id_ident(ident); - let register_value_type_ident = get_register_value_type_ident(ident); - let mut inner_type = None; if transparent { if let Item::Struct(ItemStruct { @@ -256,94 +225,59 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { } } - let into_update_op = match into_mode { - IntoMode::None => None, - IntoMode::New => Some(quote! { - cell.update_shared(content); - }), - IntoMode::Shared => Some(quote! { - // TODO we could offer a From<&#ident> when #ident implemented Clone - cell.compare_and_update_shared(content); - }), - }; - - let into = if let Some(update_op) = into_update_op { - quote! { - impl From<#ident> for turbo_tasks::RawVc { - fn from(content: #ident) -> Self { - let cell = turbo_tasks::macro_helpers::find_cell_by_type(*#value_type_id_ident); - #update_op - cell.into() - } - } - - impl From<#ident> for #ref_ident { - fn from(content: #ident) -> Self { - let cell = turbo_tasks::macro_helpers::find_cell_by_type(*#value_type_id_ident); - #update_op - Self { node: cell.into() } - } - } - } - } else { - quote! {} - }; - - let cell_update_op = match cell_mode { + let cell_mode = match cell_mode { CellMode::New => quote! { - cell.update_shared(content); + turbo_tasks::VcCellNewMode<#ident> }, CellMode::Shared => quote! { - // TODO we could offer a From<&#ident> when #ident implemented Clone - cell.compare_and_update_shared(content); + turbo_tasks::VcCellSharedMode<#ident> }, }; - let (cell_prefix, cell_arg_type, cell_convert_content, cell_access_content) = - if let Some(inner_type) = inner_type { - ( - quote! { pub }, - quote! { #inner_type }, - quote! { - let content = #ident(content); - }, - quote! { - content.0 - }, - ) - } else { - ( - if let IntoMode::New | IntoMode::Shared = into_mode { - quote! { pub } - } else { - quote! {} - }, - quote! { #ident }, - quote! {}, - quote! { content }, - ) - }; - - let cell = quote! { - /// Places a value in a cell of the current task. - /// - /// Cell is selected based on the value type and call order of `cell`. - #cell_prefix fn cell(content: #cell_arg_type) -> #ref_ident { - let cell = turbo_tasks::macro_helpers::find_cell_by_type(*#value_type_id_ident); - #cell_convert_content - #cell_update_op - #ref_ident { node: cell.into() } - } + let (cell_prefix, cell_access_content, read) = if let Some(inner_type) = inner_type { + ( + quote! { pub }, + quote! { + content.0 + }, + quote! { + turbo_tasks::VcTransparentRead::<#ident, #inner_type> + }, + ) + } else { + ( + if let IntoMode::New | IntoMode::Shared = into_mode { + quote! { pub } + } else { + quote! {} + }, + quote! { content }, + quote! { + turbo_tasks::VcDefaultRead::<#ident> + }, + ) }; let cell_struct = quote! { /// Places a value in a cell of the current task. /// /// Cell is selected based on the value type and call order of `cell`. - #cell_prefix fn cell(self) -> #ref_ident { + #cell_prefix fn cell(self) -> turbo_tasks::Vc { let content = self; - #ref_ident::cell(#cell_access_content) + turbo_tasks::Vc::cell_private(#cell_access_content) + } + }; + + let into = if let IntoMode::New | IntoMode::Shared = into_mode { + quote! { + impl Into> for #ident { + fn into(self) -> turbo_tasks::Vc<#ident> { + self.cell() + } + } } + } else { + quote! {} }; let derive = match serialization_mode { @@ -397,77 +331,6 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { }, }; - let future_type = if let Some(inner_type) = inner_type { - quote! { - turbo_tasks::ReadRawVcFuture> - } - } else { - quote! { - turbo_tasks::ReadRawVcFuture> - } - }; - - let into_future = if let Some(inner_type) = inner_type { - quote! { - impl std::future::IntoFuture for #ref_ident { - type Output = turbo_tasks::Result<#read_ref_ident>; - type IntoFuture = #future_type; - fn into_future(self) -> Self::IntoFuture { - /// SAFETY: Types are binary identical via #[repr(transparent)] - unsafe { self.node.into_transparent_read::<#ident, #inner_type>() } - } - } - - impl std::future::IntoFuture for &#ref_ident { - type Output = turbo_tasks::Result<#read_ref_ident>; - type IntoFuture = #future_type; - fn into_future(self) -> Self::IntoFuture { - /// SAFETY: Types are binary identical via #[repr(transparent)] - unsafe { self.node.into_transparent_read::<#ident, #inner_type>() } - } - } - } - } else { - quote! { - impl std::future::IntoFuture for #ref_ident { - type Output = turbo_tasks::Result<#read_ref_ident>; - type IntoFuture = #future_type; - fn into_future(self) -> Self::IntoFuture { - self.node.into_read::<#ident>() - } - } - - impl std::future::IntoFuture for &#ref_ident { - type Output = turbo_tasks::Result<#read_ref_ident>; - type IntoFuture = #future_type; - fn into_future(self) -> Self::IntoFuture { - self.node.into_read::<#ident>() - } - } - } - }; - - let strongly_consistent = { - let read = if let Some(inner_type) = inner_type { - quote! { - /// SAFETY: Types are binary identical via #[repr(transparent)] - unsafe { self.node.into_transparent_strongly_consistent_read::<#ident, #inner_type>() } - } - } else { - quote! { - self.node.into_strongly_consistent_read::<#ident>() - } - }; - let doc = strongly_consistent_doccomment(); - quote! { - #doc - #[must_use] - pub fn strongly_consistent(self) -> #future_type { - #read - } - } - }; - let value_debug_impl = if inner_type.is_some() { // For transparent values, we defer directly to the inner type's `ValueDebug` // implementation. @@ -475,13 +338,13 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { #[turbo_tasks::value_impl] impl turbo_tasks::debug::ValueDebug for #ident { #[turbo_tasks::function] - async fn dbg(&self) -> anyhow::Result { + async fn dbg(&self) -> anyhow::Result> { use turbo_tasks::debug::ValueDebugFormat; (&self.0).value_debug_format(usize::MAX).try_to_value_debug_string().await } #[turbo_tasks::function] - async fn dbg_depth(&self, depth: usize) -> anyhow::Result { + async fn dbg_depth(&self, depth: usize) -> anyhow::Result> { use turbo_tasks::debug::ValueDebugFormat; (&self.0).value_debug_format(depth).try_to_value_debug_string().await } @@ -491,37 +354,8 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { quote! {} }; - let read_ref = if let Some(inner_type) = inner_type { - quote! { - turbo_tasks::ReadRef<#ident, #inner_type> - } - } else { - quote! { - turbo_tasks::ReadRef<#ident, #ident> - } - }; - let read_ref = quote! { - /// see [turbo_tasks::ReadRef] - #vis type #read_ref_ident = #read_ref; - }; - - let value_debug_format_impl = quote! { - impl turbo_tasks::debug::ValueDebugFormat for #ref_ident { - fn value_debug_format(&self, depth: usize) -> turbo_tasks::debug::ValueDebugFormatString { - turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move { - Ok(if let Some(value_debug) = turbo_tasks::debug::ValueDebugVc::resolve_from(self).await? { - turbo_tasks::debug::ValueDebug::dbg_depth(&value_debug, depth).await?.to_string() - } else { - // This case means `SelfVc` does not implement `ValueDebugVc`, which is not possible - // if this implementation exists. - unreachable!() - }) - })) - } - } - }; - - let doc_msg_refer_to_ident = format!(" Vc for [`{ident}`]"); + let value_type_and_register_code = + value_type_and_register(ident, quote! { #ident }, read, cell_mode, new_value_type); let expanded = quote! { #derive @@ -533,6 +367,31 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { #cell_struct } + #into + + #value_type_and_register_code + + #for_input_marker + + #value_debug_impl + }; + + expanded.into() +} + +pub fn value_type_and_register( + ident: &Ident, + ty: proc_macro2::TokenStream, + read: proc_macro2::TokenStream, + cell_mode: proc_macro2::TokenStream, + new_value_type: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + let value_type_init_ident = get_value_type_init_ident(ident); + let value_type_ident = get_value_type_ident(ident); + let value_type_id_ident = get_value_type_id_ident(ident); + let register_value_type_ident = get_register_value_type_ident(ident); + + quote! { #[doc(hidden)] static #value_type_init_ident: turbo_tasks::macro_helpers::OnceCell< turbo_tasks::ValueType, @@ -554,6 +413,8 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { turbo_tasks::macro_helpers::Lazy::new(|| { turbo_tasks::registry::get_value_type_id(*#value_type_ident) }); + + #[doc(hidden)] #[allow(non_snake_case)] pub(crate) fn #register_value_type_ident( @@ -567,128 +428,13 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { }).register(global_name); } - impl turbo_tasks::Typed for #ident { - type Vc = #ref_ident; - - fn get_value_type_id() -> turbo_tasks::ValueTypeId { - *#value_type_id_ident - } - } - #for_input_marker - - #[doc = #doc_msg_refer_to_ident] - /// - /// A reference to a value created by a turbo-tasks function. - /// The type can either point to a cell in a [`turbo_tasks::Task`] or to the output of - /// a [`turbo_tasks::Task`], which then transitively points to a cell again, or - /// to an fatal execution error. - /// - /// [`Self::resolve`]`().await?` can be used to resolve it until it points to a cell. - /// This is useful when storing the reference somewhere or when comparing it with other references. - /// - /// A reference is equal to another reference when it points to the same thing. No resolving is applied on comparison. - #[derive(Clone, Copy, Debug, std::cmp::PartialOrd, std::cmp::Ord, std::hash::Hash, std::cmp::Eq, std::cmp::PartialEq, serde::Serialize, serde::Deserialize)] - #vis struct #ref_ident { - node: turbo_tasks::RawVc, - } - - #read_ref - - impl #ref_ident { - #cell - - /// see [turbo_tasks::RawVc::resolve] - pub async fn resolve(self) -> turbo_tasks::Result { - Ok(Self { node: self.node.resolve().await? }) - } - - /// see [turbo_tasks::RawVc::resolve_strongly_consistent] - pub async fn resolve_strongly_consistent(self) -> turbo_tasks::Result { - Ok(Self { node: self.node.resolve_strongly_consistent().await? }) - } - - pub async fn resolve_from(super_trait_vc: impl std::convert::Into) -> Result, turbo_tasks::ResolveTypeError> { - let raw_vc: turbo_tasks::RawVc = super_trait_vc.into(); - let raw_vc = raw_vc.resolve_value(*#value_type_id_ident).await?; - Ok(raw_vc.map(|raw_vc| #ref_ident { node: raw_vc })) - } - - #strongly_consistent - } - - impl turbo_tasks::CollectiblesSource for #ref_ident { - fn take_collectibles(self) -> turbo_tasks::CollectiblesFuture { - self.node.take_collectibles() - } + unsafe impl turbo_tasks::VcValueType for #ty { + type Read = #read; + type CellMode = #cell_mode; - fn peek_collectibles(self) -> turbo_tasks::CollectiblesFuture { - self.node.peek_collectibles() - } - } - - impl turbo_tasks::ValueVc for #ref_ident { - #[inline] fn get_value_type_id() -> turbo_tasks::ValueTypeId { *#value_type_id_ident } - - #[inline] - fn get_trait_type_ids() -> Box> { - Box::new(#value_type_ident.traits_iter()) - } - } - - #into_future - - impl turbo_tasks::FromTaskInput<'_> for #ref_ident { - type Error = turbo_tasks::Error; - - fn try_from(value: &turbo_tasks::TaskInput) -> Result { - Ok(Self { node: value.try_into()? }) - } } - - impl From for #ref_ident { - fn from(node: turbo_tasks::RawVc) -> Self { - Self { node } - } - } - - impl From<#ref_ident> for turbo_tasks::RawVc { - fn from(node_ref: #ref_ident) -> Self { - node_ref.node - } - } - - impl From<&#ref_ident> for turbo_tasks::RawVc { - fn from(node_ref: &#ref_ident) -> Self { - node_ref.node.clone() - } - } - - impl From<#ref_ident> for turbo_tasks::TaskInput { - fn from(node_ref: #ref_ident) -> Self { - node_ref.node.into() - } - } - - impl From<&#ref_ident> for turbo_tasks::TaskInput { - fn from(node_ref: &#ref_ident) -> Self { - node_ref.node.clone().into() - } - } - - #into - - impl turbo_tasks::trace::TraceRawVcs for #ref_ident { - fn trace_raw_vcs(&self, context: &mut turbo_tasks::trace::TraceRawVcsContext) { - turbo_tasks::trace::TraceRawVcs::trace_raw_vcs(&self.node, context); - } - } - - #value_debug_format_impl - #value_debug_impl - }; - - expanded.into() + } } diff --git a/crates/turbo-tasks-macros/src/value_trait_macro.rs b/crates/turbo-tasks-macros/src/value_trait_macro.rs index 53459a7b9a9e1a..99506996373957 100644 --- a/crates/turbo-tasks-macros/src/value_trait_macro.rs +++ b/crates/turbo-tasks-macros/src/value_trait_macro.rs @@ -2,216 +2,180 @@ use proc_macro::TokenStream; use proc_macro2::{Ident, TokenStream as TokenStream2}; use quote::quote; use syn::{ - parse_macro_input, parse_quote, ItemTrait, Path, PathSegment, Signature, TraitBound, TraitItem, - TraitItemMethod, TypeParamBound, + parse_macro_input, parse_quote, spanned::Spanned, ExprPath, ItemTrait, TraitItem, + TraitItemMethod, }; use turbo_tasks_macros_shared::{ - get_ref_ident, get_trait_default_impl_function_ident, get_trait_ref_ident, - get_trait_type_ident, ValueTraitArguments, + get_trait_default_impl_function_id_ident, get_trait_default_impl_function_ident, + get_trait_type_id_ident, get_trait_type_ident, ValueTraitArguments, }; -use crate::{ - func::{gen_native_function_code, split_signature, SelfType}, - util::*, -}; - -fn get_trait_type_id_ident(ident: &Ident) -> Ident { - Ident::new( - &format!("{}_TRAIT_TYPE_ID", ident.to_string().to_uppercase()), - ident.span(), - ) -} - -fn get_trait_default_impl_function_id_ident(trait_ident: &Ident, ident: &Ident) -> Ident { - Ident::new( - &format!( - "{}_DEFAULT_IMPL_{}_FUNCTION_ID", - trait_ident.to_string().to_uppercase(), - ident.to_string().to_uppercase() - ), - ident.span(), - ) -} +use crate::func::{DefinitionContext, NativeFn, TurboFn}; pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream { let ValueTraitArguments { debug } = parse_macro_input!(args as ValueTraitArguments); - let mut item = parse_macro_input!(input as ItemTrait); + let item = parse_macro_input!(input as ItemTrait); let ItemTrait { vis, - ident, - items, + ident: trait_ident, + items: raw_items, supertraits, attrs, trait_token, - colon_token, - .. - } = &mut item; + colon_token: _, + unsafety, + auto_token, + generics, + brace_token: _, + } = &item; + + if unsafety.is_some() { + item.span() + .unwrap() + .error("unsafe traits are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + if auto_token.is_some() { + item.span() + .unwrap() + .error("auto traits are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + if !generics.params.is_empty() { + item.span() + .unwrap() + .error("generic traits are not supported in #[turbo_tasks::value_trait]") + .emit(); + } + + if generics.where_clause.is_some() { + item.span() + .unwrap() + .error("where clauses are not supported in #[turbo_tasks::value_trait]") + .emit(); + } let supertraits = supertraits.into_iter().collect::>(); - let supertrait_refs: Vec<_> = supertraits - .iter() - .filter_map(|ident| { - if let TypeParamBound::Trait(TraitBound { - path: Path { segments, .. }, - .. - }) = ident - { - let PathSegment { ident, .. } = segments.iter().next()?; - Some(get_ref_ident(ident)) - } else { - None - } - }) - .collect(); - - let as_supertrait_methods: Vec<_> = supertraits - .iter() - .filter_map(|ident| { - if let TypeParamBound::Trait(TraitBound { - path: Path { segments, .. }, - .. - }) = ident - { - let PathSegment { ident, .. } = segments.iter().next()?; - Some(get_as_super_ident(ident)) - } else { - None - } - }) - .collect(); - - let ref_ident = get_ref_ident(ident); - let trait_ref_ident = get_trait_ref_ident(ident); - let trait_type_ident = get_trait_type_ident(ident); - let trait_type_id_ident = get_trait_type_id_ident(ident); - let mut trait_fns = Vec::new(); + let trait_type_ident = get_trait_type_ident(trait_ident); + let trait_type_id_ident = get_trait_type_id_ident(trait_ident); + let mut dynamic_trait_fns = Vec::new(); let mut default_method_registers: Vec = Vec::new(); let mut native_functions = Vec::new(); + let mut items = Vec::with_capacity(raw_items.len()); - for item in items.iter_mut() { - if let TraitItem::Method(TraitItemMethod { sig, default, .. }) = item { - let Signature { - ident: method_ident, - inputs, - .. - } = &*sig; - - let (external_sig, _inline_sig, output_type, convert_result_code) = - split_signature(sig); - let function_ident = get_trait_default_impl_function_ident(ident, method_ident); - let function_id_ident = get_trait_default_impl_function_id_ident(ident, method_ident); - let inline_ident = get_internal_function_ident(method_ident); - - let mut inline_sig = sig.clone(); - inline_sig.ident = inline_ident.clone(); - - let (native_function_code, input_raw_vc_arguments) = gen_native_function_code( - quote! { concat!(stringify!(#ref_ident), "::", stringify!(#method_ident)) }, - quote! { #ref_ident::#inline_ident }, - &function_ident, - &function_id_ident, - sig.asyncness.is_some(), - inputs, - &output_type, - Some((&ref_ident, SelfType::ValueTrait)), - ); - - trait_fns.push(quote! { - #external_sig { - let result = turbo_tasks::trait_call(*#trait_type_id_ident, std::borrow::Cow::Borrowed(stringify!(#method_ident)), vec![#(#input_raw_vc_arguments),*]); - #convert_result_code - } + for item in raw_items.iter() { + let TraitItem::Method(TraitItemMethod { sig, default, attrs, semi_token: _ }) = item else { + item.span().unwrap().error("only methods are allowed in a #[turbo_tasks::value_trait] trait").emit(); + continue; + }; + + let ident = &sig.ident; + + let Some(turbo_fn) = TurboFn::new(sig, DefinitionContext::ValueTrait) else { + return quote! { + // An error occurred while parsing the function signature. + }.into(); + }; + + let turbo_signature = turbo_fn.signature(); + let dynamic_block = turbo_fn.dynamic_block(&trait_type_id_ident); + dynamic_trait_fns.push(quote! { + #turbo_signature #dynamic_block + }); + + let default = if let Some(block) = default { + // TODO(alexkirsz) These should go into their own utilities. + let inline_function_ident: Ident = + Ident::new(&format!("{}_inline", ident), ident.span()); + let inline_extension_trait_ident = + Ident::new(&format!("{}_{}_inline", trait_ident, ident), ident.span()); + let inline_function_path: ExprPath = parse_quote! { as #inline_extension_trait_ident>::#inline_function_ident }; + let mut inline_signature = sig.clone(); + inline_signature.ident = inline_function_ident; + + let native_function = NativeFn::new(&ident.to_string(), &inline_function_path); + + let native_function_ident = get_trait_default_impl_function_ident(trait_ident, ident); + let native_function_ty = native_function.ty(); + let native_function_def = native_function.definition(); + let native_function_id_ident = + get_trait_default_impl_function_id_ident(trait_ident, ident); + let native_function_id_ty = native_function.id_ty(); + let native_function_id_def = native_function.id_definition(&parse_quote! { + #native_function_ident }); - if let Some(block) = default.take() { - default_method_registers.push(quote! { - trait_type.register_default_trait_method(stringify!(#method_ident).into(), *#function_id_ident); - }); - native_functions.push(quote! { - impl #ref_ident { - #(#attrs)* - #vis #inline_sig #block - } - - #native_function_code - }); - - *sig = external_sig; - *default = Some(parse_quote! {{ - let result = turbo_tasks::dynamic_call(*#function_id_ident, vec![#(#input_raw_vc_arguments),*]); - #convert_result_code - }}); - } - } - } + default_method_registers.push(quote! { + trait_type.register_default_trait_method(stringify!(#ident).into(), *#native_function_id_ident); + }); - let future_type = quote! { - turbo_tasks::ReadRawVcFuture> - }; + native_functions.push(quote! { + #[doc(hidden)] + #[allow(non_camel_case_types)] + // #[turbo_tasks::async_trait] + trait #inline_extension_trait_ident { + #[allow(declare_interior_mutable_const)] + const #native_function_ident: #native_function_ty; + #[allow(declare_interior_mutable_const)] + const #native_function_id_ident: #native_function_id_ty; + + #(#attrs)* + #inline_signature; + } - let into_trait_ref = quote! { - impl turbo_tasks::IntoTraitRef for #ref_ident { - type TraitVc = #ref_ident; - type Future = #future_type; - fn into_trait_ref(self) -> Self::Future { - self.node.into_trait_read::<#ref_ident>() - } - } + #[doc(hidden)] + // #[turbo_tasks::async_trait] + // Needs to be explicit 'static here, otherwise we can get a lifetime error + // in the inline signature. + impl #inline_extension_trait_ident for Box { + #[allow(declare_interior_mutable_const)] + const #native_function_ident: #native_function_ty = #native_function_def; + #[allow(declare_interior_mutable_const)] + const #native_function_id_ident: #native_function_id_ty = #native_function_id_def; + + #(#attrs)* + #inline_signature #block + } - impl turbo_tasks::IntoTraitRef for &#ref_ident { - type TraitVc = #ref_ident; - type Future = #future_type; - fn into_trait_ref(self) -> Self::Future { - self.node.into_trait_read::<#ref_ident>() - } - } - }; + #[doc(hidden)] + pub(crate) static #native_function_ident: #native_function_ty = as #inline_extension_trait_ident>::#native_function_ident; + #[doc(hidden)] + pub(crate) static #native_function_id_ident: #native_function_id_ty = as #inline_extension_trait_ident>::#native_function_id_ident; + }); - let strongly_consistent = { - let read = quote! { - self.node.into_strongly_consistent_trait_read::<#ref_ident>() + Some(turbo_fn.static_block(&native_function_id_ident)) + } else { + None }; - let doc = strongly_consistent_doccomment(); - quote! { - #doc - #[must_use] - pub fn strongly_consistent(self) -> #future_type { - #read - } - } - }; - let trait_ref = quote! { - turbo_tasks::TraitRef<#ref_ident> - }; - let trait_ref = quote! { - /// see [turbo_tasks::TraitRef] - #vis type #trait_ref_ident = #trait_ref; - }; + items.push(TraitItem::Method(TraitItemMethod { + sig: turbo_fn.trait_signature(), + default, + attrs: attrs.clone(), + semi_token: Default::default(), + })); + } let value_debug_impl = if debug { quote! { #[turbo_tasks::value_impl] - impl #ref_ident { + impl turbo_tasks::debug::ValueDebug for Box { #[turbo_tasks::function] - pub async fn dbg(self) -> anyhow::Result { - use turbo_tasks::debug::ValueDebugFormat; - self.value_debug_format(usize::MAX).try_to_value_debug_string().await + pub fn dbg(self: turbo_tasks::Vc) -> turbo_tasks::Vc { + use turbo_tasks::debug::ValueDebug; + self.dbg_depth(usize::MAX) } #[turbo_tasks::function] - pub async fn dbg_depth(self, depth: usize) -> anyhow::Result { + pub async fn dbg_depth(self: turbo_tasks::Vc, depth: usize) -> anyhow::Result> { use turbo_tasks::debug::ValueDebugFormat; - self.value_debug_format(depth).try_to_value_debug_string().await - } - } - - impl turbo_tasks::FromSubTrait<#ref_ident> for turbo_tasks::debug::ValueDebugVc { - fn from_sub_trait(node_ref: #ref_ident) -> Self { - node_ref.node.into() + let string = self.value_debug_format(depth).try_to_value_debug_string().await?.await?; + Ok(turbo_tasks::debug::ValueDebugString::new(format!(concat!(stringify!(#trait_ident), "({})"), string))) } } } @@ -219,33 +183,10 @@ pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream { quote! {} }; - let value_debug_format_impl = quote! { - impl turbo_tasks::debug::ValueDebugFormat for #ref_ident { - fn value_debug_format(&self, depth: usize) -> turbo_tasks::debug::ValueDebugFormatString { - turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move { - Ok(if let Some(value_debug) = turbo_tasks::debug::ValueDebugVc::resolve_from(self).await? { - format!(concat!(stringify!(#ident), "({})"), turbo_tasks::debug::ValueDebug::dbg_depth(&value_debug, depth).await?.as_str()) - } else { - // This case means the `Vc` pointed to by this `Vc` does not implement `ValueDebug`. - // This could happen if we provide a way to opt-out of the default `ValueDebug` derive, - // or if we make the derive opt-in. However, we can still print useful information - // like the resolved type. - "".to_string() - }) - })) - } - } - }; - - let where_clause = if !default_method_registers.is_empty() || !supertraits.is_empty() { - Some(quote! { where turbo_tasks::TaskInput: for<'a> std::convert::From<&'a Self> }) - } else { - None - }; - let expanded = quote! { #(#attrs)* - #vis #trait_token #ident #colon_token #(#supertraits)+* #where_clause { + #vis #trait_token #trait_ident: #(#supertraits)+* + { #(#items)* } @@ -254,7 +195,7 @@ pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream { #[doc(hidden)] pub(crate) static #trait_type_ident: turbo_tasks::macro_helpers::Lazy = turbo_tasks::macro_helpers::Lazy::new(|| { - let mut trait_type = turbo_tasks::TraitType::new(std::any::type_name::<#ref_ident>().to_string());; + let mut trait_type = turbo_tasks::TraitType::new(std::any::type_name::>>().to_string());; #(#default_method_registers)* trait_type }); @@ -264,132 +205,30 @@ pub fn value_trait(args: TokenStream, input: TokenStream) -> TokenStream { turbo_tasks::registry::get_trait_type_id(&#trait_type_ident) }); - #[derive(Clone, Copy, Debug, std::cmp::PartialOrd, std::cmp::Ord, std::hash::Hash, std::cmp::Eq, std::cmp::PartialEq, serde::Serialize, serde::Deserialize)] - #vis struct #ref_ident { - node: turbo_tasks::RawVc, - } - - #trait_ref - - impl #ref_ident { - /// see [turbo_tasks::RawVc::resolve] - pub async fn resolve(self) -> turbo_tasks::Result { - Ok(Self { node: self.node.resolve().await? }) - } - - /// see [turbo_tasks::RawVc::resolve_strongly_consistent] - pub async fn resolve_strongly_consistent(self) -> turbo_tasks::Result { - Ok(Self { node: self.node.resolve_strongly_consistent().await? }) - } - - pub async fn resolve_from(super_trait_vc: impl std::convert::Into) -> Result, turbo_tasks::ResolveTypeError> { - let raw_vc: turbo_tasks::RawVc = super_trait_vc.into(); - let raw_vc = raw_vc.resolve_trait(*#trait_type_id_ident).await?; - Ok(raw_vc.map(|raw_vc| #ref_ident { node: raw_vc })) - } - - pub fn cast_from(super_trait_vc: impl std::convert::Into) -> Self { - let raw_vc: turbo_tasks::RawVc = super_trait_vc.into(); - #ref_ident { node: raw_vc } - } - - #strongly_consistent - } - - impl turbo_tasks::CollectiblesSource for #ref_ident { - fn take_collectibles(self) -> turbo_tasks::CollectiblesFuture { - self.node.take_collectibles() - } - - fn peek_collectibles(self) -> turbo_tasks::CollectiblesFuture { - self.node.peek_collectibles() - } - } - - impl turbo_tasks::ValueTraitVc for #ref_ident { - #[inline] + impl turbo_tasks::VcValueTrait for Box { fn get_trait_type_id() -> turbo_tasks::TraitTypeId { *#trait_type_id_ident } } - #into_trait_ref + unsafe impl turbo_tasks::Dynamic> for Box {} + // TODO(alexkirsz) It would be great to have the following identity. However, I run into an ICE when I attempt this, + // so tabling it for now. + unsafe impl turbo_tasks::Upcast> for Box {} - impl #ident for T + impl #trait_ident for T where - T: turbo_tasks::ValueTraitVc, - #ref_ident: turbo_tasks::FromSubTrait, - turbo_tasks::TaskInput: for<'a> std::convert::From<&'a T> - #(, #supertrait_refs: turbo_tasks::FromSubTrait)* { - #(#trait_fns)* + T: turbo_tasks::Dynamic> #(+ #supertraits)*, + { + #(#dynamic_trait_fns)* } #( - impl From<#ref_ident> for #supertrait_refs { - fn from(node_ref: #ref_ident) -> Self { - node_ref.node.into() - } - } - - impl turbo_tasks::FromSubTrait<#ref_ident> for #supertrait_refs { - fn from_sub_trait(node_ref: #ref_ident) -> Self { - node_ref.node.into() - } - } - - impl #ref_ident { - pub fn #as_supertrait_methods(self) -> #supertrait_refs { - self.node.into() - } - } + unsafe impl turbo_tasks::Dynamic> for Box {} + unsafe impl turbo_tasks::Upcast> for Box {} )* - impl turbo_tasks::FromTaskInput<'_> for #ref_ident { - type Error = turbo_tasks::Error; - - fn try_from(value: &turbo_tasks::TaskInput) -> Result { - Ok(Self { node: std::convert::TryFrom::try_from(value)? }) - } - } - - impl From for #ref_ident { - fn from(node: turbo_tasks::RawVc) -> Self { - Self { node } - } - } - - impl From<#ref_ident> for turbo_tasks::RawVc { - fn from(node_ref: #ref_ident) -> Self { - node_ref.node - } - } - - impl From<&#ref_ident> for turbo_tasks::RawVc { - fn from(node_ref: &#ref_ident) -> Self { - node_ref.node.clone() - } - } - - impl From<#ref_ident> for turbo_tasks::TaskInput { - fn from(node_ref: #ref_ident) -> Self { - node_ref.node.into() - } - } - - impl From<&#ref_ident> for turbo_tasks::TaskInput { - fn from(node_ref: &#ref_ident) -> Self { - node_ref.node.clone().into() - } - } - - impl turbo_tasks::trace::TraceRawVcs for #ref_ident { - fn trace_raw_vcs(&self, context: &mut turbo_tasks::trace::TraceRawVcsContext) { - turbo_tasks::trace::TraceRawVcs::trace_raw_vcs(&self.node, context); - } - } - #value_debug_impl - #value_debug_format_impl }; expanded.into() } diff --git a/crates/turbo-tasks-memory/benches/mod.rs b/crates/turbo-tasks-memory/benches/mod.rs index 2b914d70ea4c60..c3fd0d6dff2601 100644 --- a/crates/turbo-tasks-memory/benches/mod.rs +++ b/crates/turbo-tasks-memory/benches/mod.rs @@ -1,4 +1,5 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use criterion::{criterion_group, criterion_main, Criterion}; diff --git a/crates/turbo-tasks-memory/benches/scope_stress.rs b/crates/turbo-tasks-memory/benches/scope_stress.rs index 0ba54699b49ceb..f589a0a8da39ef 100644 --- a/crates/turbo-tasks-memory/benches/scope_stress.rs +++ b/crates/turbo-tasks-memory/benches/scope_stress.rs @@ -1,6 +1,6 @@ use anyhow::Result; use criterion::{BenchmarkId, Criterion}; -use turbo_tasks::{CompletionVc, NothingVc, TryJoinIterExt, TurboTasks}; +use turbo_tasks::{unit, Completion, TryJoinIterExt, TurboTasks, Vc}; use turbo_tasks_memory::MemoryBackend; use super::register; @@ -47,7 +47,7 @@ pub fn scope_stress(c: &mut Criterion) { async move { let task = tt.spawn_once_task(async move { rectangle(a, b).strongly_consistent().await?; - Ok(NothingVc::new().into()) + Ok(unit().node) }); tt.wait_task_completion(task, false).await } @@ -67,12 +67,12 @@ pub fn scope_stress(c: &mut Criterion) { /// This fills a rectagle from (0, 0) to (a, b) by /// first filling (0, 0) to (a - 1, b) and then (0, 0) to (a, b - 1) recursively #[turbo_tasks::function] -async fn rectangle(a: u32, b: u32) -> Result { +async fn rectangle(a: u32, b: u32) -> Result> { if a > 0 { rectangle(a - 1, b).await?; } if b > 0 { rectangle(a, b - 1).await?; } - Ok(CompletionVc::new()) + Ok(Completion::new()) } diff --git a/crates/turbo-tasks-memory/benches/stress.rs b/crates/turbo-tasks-memory/benches/stress.rs index af883c83a67aef..5ba22e0a81c729 100644 --- a/crates/turbo-tasks-memory/benches/stress.rs +++ b/crates/turbo-tasks-memory/benches/stress.rs @@ -1,6 +1,6 @@ use anyhow::Result; use criterion::{BenchmarkId, Criterion}; -use turbo_tasks::{NothingVc, TryJoinIterExt, TurboTasks}; +use turbo_tasks::{unit, TryJoinIterExt, TurboTasks, Vc}; use turbo_tasks_memory::MemoryBackend; use super::register; @@ -41,7 +41,7 @@ pub fn fibonacci(c: &mut Criterion) { // size >= 1 => + fib(0) = 1 // size >= 2 => + fib(1) = 2 (0..size).map(|i| fib(i, i)).try_join().await?; - Ok(NothingVc::new().into()) + Ok(unit().node) }); tt.wait_task_completion(task, false).await.unwrap(); tt @@ -65,7 +65,7 @@ struct FibResult(u64); /// This function also has a `key` parameter to allow forcing it to separate /// cache entries by using different keys. #[turbo_tasks::function] -async fn fib(i: u32, key: u32) -> Result { +async fn fib(i: u32, key: u32) -> Result> { Ok(match i { 0 => FibResult(1).cell(), 1 => fib(0, key), diff --git a/crates/turbo-tasks-memory/src/lib.rs b/crates/turbo-tasks-memory/src/lib.rs index 72080c065b3a12..7f71d8b7114d51 100644 --- a/crates/turbo-tasks-memory/src/lib.rs +++ b/crates/turbo-tasks-memory/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(hash_drain_filter)] +#![feature(hash_extract_if)] #![feature(option_get_or_insert_default)] #![feature(type_alias_impl_trait)] #![feature(lint_reasons)] diff --git a/crates/turbo-tasks-memory/src/memory_backend.rs b/crates/turbo-tasks-memory/src/memory_backend.rs index e0be9f90ed2175..7c9bb1d81e5bc6 100644 --- a/crates/turbo-tasks-memory/src/memory_backend.rs +++ b/crates/turbo-tasks-memory/src/memory_backend.rs @@ -26,9 +26,8 @@ use turbo_tasks::{ TransientTaskType, }, event::EventListener, - primitives::RawVcSetVc, util::{IdFactory, NoMoveVec}, - CellId, RawVc, TaskId, TraitTypeId, TurboTasksBackendApi, Unused, + CellId, RawVc, TaskId, TraitTypeId, TurboTasksBackendApi, Unused, Vc, }; use crate::{ @@ -584,7 +583,7 @@ impl Backend for MemoryBackend { trait_id: TraitTypeId, reader: TaskId, turbo_tasks: &dyn TurboTasksBackendApi, - ) -> RawVcSetVc { + ) -> Vc> { self.with_task(id, |task| { task.read_task_collectibles(reader, trait_id, self, turbo_tasks) }) diff --git a/crates/turbo-tasks-memory/src/memory_backend_with_pg.rs b/crates/turbo-tasks-memory/src/memory_backend_with_pg.rs index 4d8e5bb158d099..8aa8a1d8b9077a 100644 --- a/crates/turbo-tasks-memory/src/memory_backend_with_pg.rs +++ b/crates/turbo-tasks-memory/src/memory_backend_with_pg.rs @@ -27,9 +27,8 @@ use turbo_tasks::{ ActivateResult, DeactivateResult, PersistResult, PersistTaskState, PersistedGraph, PersistedGraphApi, ReadTaskState, TaskCell, TaskData, }, - primitives::RawVcSetVc, util::{IdFactory, NoMoveVec, SharedError}, - CellId, RawVc, TaskId, TraitTypeId, TurboTasksBackendApi, Unused, + CellId, RawVc, TaskId, TraitTypeId, TurboTasksBackendApi, Unused, Vc, }; type RootTaskFn = @@ -1434,7 +1433,7 @@ impl Backend for MemoryBackendWithPersistedGraph

{ _trait_id: TraitTypeId, _reader: TaskId, _turbo_tasks: &dyn TurboTasksBackendApi>, - ) -> RawVcSetVc { + ) -> Vc> { todo!() } diff --git a/crates/turbo-tasks-memory/src/stats.rs b/crates/turbo-tasks-memory/src/stats.rs index a62853736b38d0..a2f2c7c3ec8ddc 100644 --- a/crates/turbo-tasks-memory/src/stats.rs +++ b/crates/turbo-tasks-memory/src/stats.rs @@ -199,7 +199,7 @@ impl Stats { pub fn merge(&mut self, mut select: impl FnMut(&StatsTaskType, &ExportedTaskStats) -> bool) { let merged: HashMap<_, _> = self .tasks - .drain_filter(|ty, stats| select(ty, stats)) + .extract_if(|ty, stats| select(ty, stats)) .collect(); for stats in self.tasks.values_mut() { diff --git a/crates/turbo-tasks-memory/src/task.rs b/crates/turbo-tasks-memory/src/task.rs index 98f6486c6013b6..692dba68204bab 100644 --- a/crates/turbo-tasks-memory/src/task.rs +++ b/crates/turbo-tasks-memory/src/task.rs @@ -24,10 +24,8 @@ use tokio::task_local; use turbo_tasks::{ backend::{PersistentTaskType, TaskExecutionSpec}, event::{Event, EventListener}, - get_invalidator, - primitives::{RawVcSet, RawVcSetVc}, - registry, CellId, Invalidator, RawVc, StatsType, TaskId, TraitTypeId, TryJoinIterExt, - TurboTasksBackendApi, ValueTypeId, + get_invalidator, registry, CellId, Invalidator, RawVc, StatsType, TaskId, TraitTypeId, + TryJoinIterExt, TurboTasksBackendApi, ValueTypeId, Vc, }; use crate::{ @@ -2265,11 +2263,7 @@ impl Task { read_task_id, &*turbo_tasks, ); - // Safety: RawVcSet is a transparent value - unsafe { - RawVc::TaskOutput(task) - .into_transparent_read::>() - } + RawVc::TaskOutput(task).into_read::>() }) }) }) @@ -2280,7 +2274,7 @@ impl Task { current.add(*v); } } - Ok(RawVcSetVc::cell(current.iter().copied().collect()).into()) + Ok(Vc::>::cell(current.iter().copied().collect()).node) } pub(crate) fn read_task_collectibles( @@ -2289,7 +2283,7 @@ impl Task { trait_id: TraitTypeId, backend: &MemoryBackend, turbo_tasks: &dyn TurboTasksBackendApi, - ) -> RawVcSetVc { + ) -> Vc> { let task = backend.get_or_create_read_task_collectibles_task( self.id, trait_id, diff --git a/crates/turbo-tasks-memory/src/task/meta_state.rs b/crates/turbo-tasks-memory/src/task/meta_state.rs index 548bcc5441b497..349adf333856a8 100644 --- a/crates/turbo-tasks-memory/src/task/meta_state.rs +++ b/crates/turbo-tasks-memory/src/task/meta_state.rs @@ -85,12 +85,14 @@ impl TaskMetaState { // These need to be impl types since there is no way to reference the zero-sized // function item type -type TaskMetaStateAsFull = impl Fn(&TaskMetaState) -> Option<&TaskState>; -type TaskMetaStateAsPartial = impl Fn(&TaskMetaState) -> Option<&PartialTaskState>; -type TaskMetaStateAsUnloaded = impl Fn(&TaskMetaState) -> Option<&UnloadedTaskState>; -type TaskMetaStateAsFullMut = impl Fn(&mut TaskMetaState) -> Option<&mut TaskState>; -type TaskMetaStateAsPartialMut = impl Fn(&mut TaskMetaState) -> Option<&mut PartialTaskState>; -type TaskMetaStateAsUnloadedMut = impl Fn(&mut TaskMetaState) -> Option<&mut UnloadedTaskState>; +pub(super) type TaskMetaStateAsFull = impl Fn(&TaskMetaState) -> Option<&TaskState>; +pub(super) type TaskMetaStateAsPartial = impl Fn(&TaskMetaState) -> Option<&PartialTaskState>; +pub(super) type TaskMetaStateAsUnloaded = impl Fn(&TaskMetaState) -> Option<&UnloadedTaskState>; +pub(super) type TaskMetaStateAsFullMut = impl Fn(&mut TaskMetaState) -> Option<&mut TaskState>; +pub(super) type TaskMetaStateAsPartialMut = + impl Fn(&mut TaskMetaState) -> Option<&mut PartialTaskState>; +pub(super) type TaskMetaStateAsUnloadedMut = + impl Fn(&mut TaskMetaState) -> Option<&mut UnloadedTaskState>; pub(super) enum TaskMetaStateReadGuard<'a> { Full(ReadGuard<'a, TaskMetaState, TaskState, TaskMetaStateAsFull>), diff --git a/crates/turbo-tasks-memory/tests/all_in_one.rs b/crates/turbo-tasks-memory/tests/all_in_one.rs index 372b0eeac1e108..4f65d323047258 100644 --- a/crates/turbo-tasks-memory/tests/all_in_one.rs +++ b/crates/turbo-tasks-memory/tests/all_in_one.rs @@ -1,7 +1,8 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use anyhow::{anyhow, Result}; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbo_tasks_testing::{register, run}; register!(); @@ -9,15 +10,18 @@ register!(); #[tokio::test] async fn all_in_one() { run! { - let a = MyTransparentValueVc::cell(4242); + let a: Vc = Vc::cell(4242); assert_eq!(*a.await?, 4242); - let b = MyEnumValueVc::cell(MyEnumValue::More(MyEnumValue::Yeah(42).into())); + let a: Vc = Vc::cell(4242); + assert_eq!(*a.await?, 4242); + + let b = MyEnumValue::cell(MyEnumValue::More(MyEnumValue::Yeah(42).into())); assert_eq!(*b.to_string().await?, "42"); let c = MyStructValue { value: 42, - next: Some(MyStructValueVc::new(a)), + next: Some(MyStructValue::new(a)), } .into(); @@ -38,13 +42,13 @@ struct MyTransparentValue(u32); enum MyEnumValue { Yeah(u32), Nah, - More(MyEnumValueVc), + More(Vc), } #[turbo_tasks::value_impl] -impl MyEnumValueVc { +impl MyEnumValue { #[turbo_tasks::function] - pub async fn get_last(self) -> Result { + pub async fn get_last(self: Vc) -> Result> { let mut current = self; while let MyEnumValue::More(more) = &*current.await? { current = *more; @@ -56,10 +60,10 @@ impl MyEnumValueVc { #[turbo_tasks::value_impl] impl ValueToString for MyEnumValue { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { + fn to_string(&self) -> Vc { match self { - MyEnumValue::Yeah(value) => StringVc::cell(value.to_string()), - MyEnumValue::Nah => StringVc::cell("nah".to_string()), + MyEnumValue::Yeah(value) => Vc::cell(value.to_string()), + MyEnumValue::Nah => Vc::cell("nah".to_string()), MyEnumValue::More(more) => more.to_string(), } } @@ -68,13 +72,13 @@ impl ValueToString for MyEnumValue { #[turbo_tasks::value(shared)] struct MyStructValue { value: u32, - next: Option, + next: Option>, } #[turbo_tasks::value_impl] -impl MyStructValueVc { +impl MyStructValue { #[turbo_tasks::function] - pub async fn new(value: MyTransparentValueVc) -> Result { + pub async fn new(value: Vc) -> Result> { Ok(Self::cell(MyStructValue { value: *value.await?, next: None, @@ -85,50 +89,50 @@ impl MyStructValueVc { #[turbo_tasks::value_impl] impl ValueToString for MyStructValue { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.value.to_string()) + fn to_string(&self) -> Vc { + Vc::cell(self.value.to_string()) } } #[turbo_tasks::value_impl] impl MyTrait for MyStructValue { #[turbo_tasks::function] - fn my_trait_function2(self_vc: MyStructValueVc) -> StringVc { - self_vc.to_string() + fn my_trait_function2(self: Vc) -> Vc { + self.to_string() } #[turbo_tasks::function] - async fn my_trait_function3(&self) -> Result { + async fn my_trait_function3(&self) -> Result> { if let Some(next) = self.next { return Ok(next.my_trait_function3()); } - Ok(StringVc::cell(self.value.to_string())) + Ok(Vc::cell(self.value.to_string())) } } #[turbo_tasks::value_trait] trait MyTrait: ValueToString { // TODO #[turbo_tasks::function] - async fn my_trait_function(self_vc: MyTraitVc) -> Result { - if *self_vc.to_string().await? != "42" { + async fn my_trait_function(self: Vc) -> Result> { + if *self.to_string().await? != "42" { return Err(anyhow!( "my_trait_function must only be called with 42 as value" )); } // Calling a function twice - Ok(self_vc.to_string()) + Ok(self.to_string()) } - fn my_trait_function2(&self) -> StringVc; - fn my_trait_function3(&self) -> StringVc; + fn my_trait_function2(&self) -> Vc; + fn my_trait_function3(&self) -> Vc; } #[turbo_tasks::function] async fn my_function( - a: MyTransparentValueVc, - b: MyEnumValueVc, - c: MyStructValueVc, + a: Vc, + b: Vc, + c: Vc, d: Value, -) -> Result { +) -> Result> { assert_eq!(*a.await?, 4242); assert_eq!(*b.await?, MyEnumValue::Yeah(42)); assert_eq!(c.await?.value, 42); diff --git a/crates/turbo-tasks-memory/tests/collectibles.rs b/crates/turbo-tasks-memory/tests/collectibles.rs index c4223ee3072e44..044d10d22a16f5 100644 --- a/crates/turbo-tasks-memory/tests/collectibles.rs +++ b/crates/turbo-tasks-memory/tests/collectibles.rs @@ -1,35 +1,24 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] -use std::{collections::HashSet, time::Duration}; +use std::collections::HashSet; -use anyhow::{bail, Result}; -use tokio::time::sleep; -use turbo_tasks::{emit, primitives::StringVc, CollectiblesSource, ValueToString, ValueToStringVc}; +use anyhow::Result; +use turbo_tasks::{emit, CollectiblesSource, ValueToString, Vc}; use turbo_tasks_testing::{register, run}; register!(); -#[tokio::test] -async fn emitting() { - run! { - let result = my_emitting_function_with_result(""); - let list = result.peek_collectibles::().strongly_consistent().await?; - assert_eq!(list.len(), 1); - assert_eq!(list.into_iter().next().unwrap().to_string().await?.as_str(), "123"); - assert_eq!(result.strongly_consistent().await?.0, 42); - } -} - #[tokio::test] async fn transitive_emitting() { run! { - let result = my_transitive_emitting_function("", ""); - let list = result.peek_collectibles::().strongly_consistent().await?; + let result = my_transitive_emitting_function("".to_string(), "".to_string()); + let list = result.peek_collectibles::>().await?; assert_eq!(list.len(), 2); let mut expected = ["123", "42"].into_iter().collect::>(); for collectible in list { assert!(expected.remove(collectible.to_string().await?.as_str())) } - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); } } @@ -37,13 +26,13 @@ async fn transitive_emitting() { async fn multi_emitting() { run! { let result = my_multi_emitting_function(); - let list = result.peek_collectibles::().strongly_consistent().await?; + let list = result.peek_collectibles::>().await?; assert_eq!(list.len(), 2); let mut expected = ["123", "42"].into_iter().collect::>(); for collectible in list { assert!(expected.remove(collectible.to_string().await?.as_str())) } - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); } } @@ -51,11 +40,11 @@ async fn multi_emitting() { async fn taking_collectibles() { run! { let result = my_collecting_function(); - let list = result.take_collectibles::().strongly_consistent().await?; + let list = result.take_collectibles::>().await?; // my_collecting_function already processed the collectibles so the list should // be empty assert!(list.is_empty()); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); } } @@ -63,114 +52,99 @@ async fn taking_collectibles() { async fn taking_collectibles_extra_layer() { run! { let result = my_collecting_function_indirect(); - let list = result.take_collectibles::().strongly_consistent().await?; + let list = result.take_collectibles::>().await?; // my_collecting_function already processed the collectibles so the list should // be empty assert!(list.is_empty()); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); } } #[tokio::test] async fn taking_collectibles_parallel() { run! { - let result = my_transitive_emitting_function("", "a"); - let list = result.take_collectibles::().strongly_consistent().await?; + let result = my_transitive_emitting_function("".to_string(), "a".to_string()); + let list = result.take_collectibles::>().await?; assert_eq!(list.len(), 2); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); - let result = my_transitive_emitting_function("", "b"); - let list = result.take_collectibles::().strongly_consistent().await?; + let result = my_transitive_emitting_function("".to_string(), "b".to_string()); + let list = result.take_collectibles::>().await?; assert_eq!(list.len(), 2); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); - let result = my_transitive_emitting_function_with_child_scope("", "b", "1"); - let list = result.take_collectibles::().strongly_consistent().await?; + let result = my_transitive_emitting_function_with_child_scope("".to_string(), "b".to_string(), "1".to_string()); + let list = result.take_collectibles::>().await?; assert_eq!(list.len(), 2); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); - let result = my_transitive_emitting_function_with_child_scope("", "b", "2"); - let list = result.take_collectibles::().strongly_consistent().await?; + let result = my_transitive_emitting_function_with_child_scope("".to_string(), "b".to_string(), "2".to_string()); + let list = result.take_collectibles::>().await?; assert_eq!(list.len(), 2); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); - let result = my_transitive_emitting_function_with_child_scope("", "c", "3"); - let list = result.take_collectibles::().strongly_consistent().await?; + let result = my_transitive_emitting_function_with_child_scope("".to_string(), "c".to_string(), "3".to_string()); + let list = result.take_collectibles::>().await?; assert_eq!(list.len(), 2); - assert_eq!(result.strongly_consistent().await?.0, 0); + assert_eq!(result.await?.0, 0); } } #[turbo_tasks::function] -async fn my_collecting_function() -> Result { - let result = my_transitive_emitting_function("", ""); - let list = result.take_collectibles::().await?; - if list.len() != 2 { - bail!("Expected 2 collectibles, got {}", list.len()); - } +async fn my_collecting_function() -> Result> { + let result = my_transitive_emitting_function("".to_string(), "".to_string()); + result.take_collectibles::>().await?; Ok(result) } #[turbo_tasks::function] -async fn my_collecting_function_indirect() -> Result { +async fn my_collecting_function_indirect() -> Result> { let result = my_collecting_function(); - let list = result.peek_collectibles::().await?; + let list = result.peek_collectibles::>().await?; // my_collecting_function already processed the collectibles so the list should // be empty - if !list.is_empty() { - bail!("Expected 0 collectibles, got {}", list.len()); - } + assert!(list.is_empty()); Ok(result) } #[turbo_tasks::function] -fn my_multi_emitting_function() -> ThingVc { - my_transitive_emitting_function("", "a"); - my_transitive_emitting_function("", "b"); - my_emitting_function(""); - ThingVc::cell(Thing(0)) +fn my_multi_emitting_function() -> Vc { + my_transitive_emitting_function("".to_string(), "a".to_string()); + my_transitive_emitting_function("".to_string(), "b".to_string()); + my_emitting_function("".to_string()); + Thing::cell(Thing(0)) } #[turbo_tasks::function] -fn my_transitive_emitting_function(key: &str, _key2: &str) -> ThingVc { +fn my_transitive_emitting_function(key: String, _key2: String) -> Vc { my_emitting_function(key); - ThingVc::cell(Thing(0)) + Thing::cell(Thing(0)) } #[turbo_tasks::function] async fn my_transitive_emitting_function_with_child_scope( - key: &str, - key2: &str, - _key3: &str, -) -> Result { + key: String, + key2: String, + _key3: String, +) -> Result> { let thing = my_transitive_emitting_function(key, key2); - let list = thing.peek_collectibles::().await?; + let list = thing.peek_collectibles::>().await?; assert_eq!(list.len(), 2); Ok(thing) } #[turbo_tasks::function] -async fn my_emitting_function(_key: &str) -> Result<()> { - sleep(Duration::from_millis(100)).await; - emit(ThingVc::new(123).as_value_to_string()); - emit(ThingVc::new(42).as_value_to_string()); +async fn my_emitting_function(_key: String) -> Result<()> { + emit(Vc::upcast::>(Thing::new(123))); + emit(Vc::upcast::>(Thing::new(42))); Ok(()) } -#[turbo_tasks::function] -async fn my_emitting_function_with_result(_key: &str) -> Result { - sleep(Duration::from_millis(100)).await; - println!("emitting"); - emit(ThingVc::new(123).as_value_to_string()); - println!("emitted"); - Ok(ThingVc::new(42)) -} - #[turbo_tasks::value(shared)] struct Thing(u32); -impl ThingVc { - fn new(v: u32) -> Self { +impl Thing { + fn new(v: u32) -> Vc { Self::cell(Thing(v)) } } @@ -178,7 +152,7 @@ impl ThingVc { #[turbo_tasks::value_impl] impl ValueToString for Thing { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.0.to_string()) + fn to_string(&self) -> Vc { + Vc::cell(self.0.to_string()) } } diff --git a/crates/turbo-tasks-memory/tests/debug.rs b/crates/turbo-tasks-memory/tests/debug.rs index b62e7bf9a31660..e3671519b2bc01 100644 --- a/crates/turbo-tasks-memory/tests/debug.rs +++ b/crates/turbo-tasks-memory/tests/debug.rs @@ -1,17 +1,25 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use std::sync::Mutex; -use anyhow::Result; -use turbo_tasks::debug::ValueDebug; +use turbo_tasks::{debug::ValueDebug, Vc}; use turbo_tasks_testing::{register, run}; register!(); +#[tokio::test] +async fn primitive_debug() { + run! { + let a: Vc = Vc::cell(42); + assert_eq!(format!("{:?}", a.dbg().await?), "42"); + } +} + #[tokio::test] async fn transparent_debug() { run! { - let a: TransparentVc = Transparent(42).into(); + let a: Vc = Transparent(42).cell(); assert_eq!(format!("{:?}", a.dbg().await?), "42"); } } @@ -19,7 +27,7 @@ async fn transparent_debug() { #[tokio::test] async fn enum_none_debug() { run! { - let a: EnumVc = Enum::None.into(); + let a: Vc = Enum::None.cell(); assert_eq!(format!("{:?}", a.dbg().await?), "None"); } } @@ -27,7 +35,7 @@ async fn enum_none_debug() { #[tokio::test] async fn enum_transparent_debug() { run! { - let a: EnumVc = Enum::Transparent(Transparent(42).into()).into(); + let a: Vc = Enum::Transparent(Transparent(42).cell()).cell(); assert_eq!(format!("{:?}", a.dbg().await?), r#"Transparent( 42, )"#); @@ -37,7 +45,7 @@ async fn enum_transparent_debug() { #[tokio::test] async fn enum_inner_vc_debug() { run! { - let a: EnumVc = Enum::Enum(Enum::None.into()).into(); + let a: Vc = Enum::Enum(Enum::None.cell()).cell(); assert_eq!(format!("{:?}", a.dbg().await?), r#"Enum( None, )"#); @@ -47,7 +55,7 @@ async fn enum_inner_vc_debug() { #[tokio::test] async fn struct_unit_debug() { run! { - let a: StructUnitVc = StructUnit.into(); + let a: Vc = StructUnit.cell(); assert_eq!(format!("{:?}", a.dbg().await?), "StructUnit"); } } @@ -55,7 +63,7 @@ async fn struct_unit_debug() { #[tokio::test] async fn struct_transparent_debug() { run! { - let a: StructWithTransparentVc = StructWithTransparent { transparent: Transparent(42).into() }.into(); + let a: Vc = StructWithTransparent { transparent: Transparent(42).cell() }.cell(); assert_eq!(format!("{:?}", a.dbg().await?), r#"StructWithTransparent { transparent: 42, }"#); @@ -65,12 +73,12 @@ async fn struct_transparent_debug() { #[tokio::test] async fn struct_vec_debug() { run! { - let a: StructWithVecVc = StructWithVec { vec: vec![] }.into(); + let a: Vc = StructWithVec { vec: vec![] }.cell(); assert_eq!(format!("{:?}", a.dbg().await?), r#"StructWithVec { vec: [], }"#); - let b: StructWithVecVc = StructWithVec { vec: vec![Transparent(42).into()] }.into(); + let b: Vc = StructWithVec { vec: vec![Transparent(42).cell()] }.cell(); assert_eq!(format!("{:?}", b.dbg().await?), r#"StructWithVec { vec: [ 42, @@ -82,7 +90,7 @@ async fn struct_vec_debug() { #[tokio::test] async fn struct_ignore_debug() { run! { - let a: StructWithIgnoreVc = StructWithIgnore { dont_ignore: 42, ignore: Mutex::new(()) }.into(); + let a: Vc = StructWithIgnore { dont_ignore: 42, ignore: Mutex::new(()) }.cell(); assert_eq!(format!("{:?}", a.dbg().await?), r#"StructWithIgnore { dont_ignore: 42, }"#); @@ -95,8 +103,8 @@ struct Transparent(u32); #[turbo_tasks::value(shared)] enum Enum { None, - Transparent(TransparentVc), - Enum(EnumVc), + Transparent(Vc), + Enum(Vc), } #[turbo_tasks::value(shared)] @@ -104,17 +112,17 @@ struct StructUnit; #[turbo_tasks::value(shared)] struct StructWithTransparent { - transparent: TransparentVc, + transparent: Vc, } #[turbo_tasks::value(shared)] struct StructWithOption { - option: Option, + option: Option>, } #[turbo_tasks::value(shared)] struct StructWithVec { - vec: Vec, + vec: Vec>, } #[turbo_tasks::value(shared, eq = "manual")] diff --git a/crates/turbo-tasks-memory/tests/read_ref_cell.rs b/crates/turbo-tasks-memory/tests/read_ref_cell.rs index ade943eaff186a..1603a163393528 100644 --- a/crates/turbo-tasks-memory/tests/read_ref_cell.rs +++ b/crates/turbo-tasks-memory/tests/read_ref_cell.rs @@ -1,9 +1,10 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use std::sync::Mutex; use anyhow::Result; -use turbo_tasks::{get_invalidator, Invalidator, ReadRef}; +use turbo_tasks::{get_invalidator, Invalidator, ReadRef, Vc}; use turbo_tasks_testing::{register, run}; register!(); @@ -11,7 +12,7 @@ register!(); #[tokio::test] async fn read_ref() { run! { - let counter = CounterVc::cell(Counter { value: Mutex::new((0, None))}); + let counter = Counter::cell(Counter { value: Mutex::new((0, None))}); let counter_value = counter.get_value(); @@ -60,20 +61,19 @@ impl Counter { } #[turbo_tasks::value_impl] -impl CounterVc { +impl Counter { #[turbo_tasks::function] - async fn get_value(self) -> Result { - let this = self.await?; - let mut lock = this.value.lock().unwrap(); + async fn get_value(&self) -> Result> { + let mut lock = self.value.lock().unwrap(); lock.1 = Some(get_invalidator()); - Ok(CounterValueVc::cell(lock.0)) + Ok(Vc::cell(lock.0)) } } #[turbo_tasks::value_impl] -impl CounterValueVc { +impl CounterValue { #[turbo_tasks::function] - fn get_value(self) -> CounterValueVc { + fn get_value(self: Vc) -> Vc { self } } diff --git a/crates/turbo-tasks-memory/tests/trait_ref_cell.rs b/crates/turbo-tasks-memory/tests/trait_ref_cell.rs index 2c56706e87a460..b66dbd9a2ee7a8 100644 --- a/crates/turbo-tasks-memory/tests/trait_ref_cell.rs +++ b/crates/turbo-tasks-memory/tests/trait_ref_cell.rs @@ -1,9 +1,10 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use std::sync::Mutex; use anyhow::Result; -use turbo_tasks::{get_invalidator, IntoTraitRef, Invalidator, TraitRef}; +use turbo_tasks::{get_invalidator, IntoTraitRef, Invalidator, TraitRef, Vc}; use turbo_tasks_testing::{register, run}; register!(); @@ -11,7 +12,7 @@ register!(); #[tokio::test] async fn trait_ref() { run! { - let counter = CounterVc::cell(Counter { value: Mutex::new((0, None))}); + let counter = Counter::cell(Counter { value: Mutex::new((0, None))}); let counter_value = counter.get_value(); @@ -24,12 +25,12 @@ async fn trait_ref() { assert_eq!(*counter_value.strongly_consistent().await?, 1); // `ref_counter` will still point to the same `counter` instance as `counter`. - let ref_counter = TraitRef::cell(counter.as_counter_trait().into_trait_ref().await?); + let ref_counter = TraitRef::cell(Vc::upcast::>(counter).into_trait_ref().await?); let ref_counter_value = ref_counter.get_value(); // However, `local_counter_value` will point to the value of `counter_value` // at the time it was turned into a trait reference (just like a `ReadRef` would). - let local_counter_value = TraitRef::cell(counter_value.as_counter_value_trait().into_trait_ref().await?).get_value(); + let local_counter_value = TraitRef::cell(Vc::upcast::>(counter_value).into_trait_ref().await?).get_value(); counter.await?.incr(); @@ -61,28 +62,28 @@ impl Counter { #[turbo_tasks::value_trait] trait CounterTrait { - fn get_value(&self) -> CounterValueVc; + fn get_value(&self) -> Vc; } #[turbo_tasks::value_impl] impl CounterTrait for Counter { #[turbo_tasks::function] - async fn get_value(&self) -> Result { + async fn get_value(&self) -> Result> { let mut lock = self.value.lock().unwrap(); lock.1 = Some(get_invalidator()); - Ok(CounterValueVc::cell(lock.0)) + Ok(Vc::cell(lock.0)) } } #[turbo_tasks::value_trait] trait CounterValueTrait { - fn get_value(&self) -> CounterValueVc; + fn get_value(&self) -> Vc; } #[turbo_tasks::value_impl] impl CounterValueTrait for CounterValue { #[turbo_tasks::function] - fn get_value(self_vc: CounterValueVc) -> CounterValueVc { - self_vc + fn get_value(self: Vc) -> Vc { + self } } diff --git a/crates/turbo-tasks-testing/src/lib.rs b/crates/turbo-tasks-testing/src/lib.rs index 714fc4b5d0b2ab..10f4fb7c3e1fe7 100644 --- a/crates/turbo-tasks-testing/src/lib.rs +++ b/crates/turbo-tasks-testing/src/lib.rs @@ -16,11 +16,10 @@ use auto_hash_map::AutoSet; use turbo_tasks::{ backend::CellContent, event::{Event, EventListener}, - primitives::RawVcSetVc, registry, test_helpers::with_turbo_tasks_for_testing, util::StaticOrArc, - CellId, InvalidationReason, RawVc, TaskId, TraitTypeId, TurboTasksApi, TurboTasksCallApi, + CellId, InvalidationReason, RawVc, TaskId, TraitTypeId, TurboTasksApi, TurboTasksCallApi, Vc, }; enum Task { @@ -39,7 +38,7 @@ impl TurboTasksCallApi for VcStorage { fn dynamic_call( &self, func: turbo_tasks::FunctionId, - inputs: Vec, + inputs: Vec, ) -> RawVc { let this = self.this.upgrade().unwrap(); let func = registry::get_function(func).bind(&inputs); @@ -70,7 +69,7 @@ impl TurboTasksCallApi for VcStorage { fn native_call( &self, _func: turbo_tasks::FunctionId, - _inputs: Vec, + _inputs: Vec, ) -> RawVc { unreachable!() } @@ -79,7 +78,7 @@ impl TurboTasksCallApi for VcStorage { &self, _trait_type: turbo_tasks::TraitTypeId, _trait_fn_name: Cow<'static, str>, - _inputs: Vec, + _inputs: Vec, ) -> RawVc { unreachable!() } @@ -195,7 +194,7 @@ impl TurboTasksApi for VcStorage { unimplemented!() } - fn read_task_collectibles(&self, _task: TaskId, _trait_id: TraitTypeId) -> RawVcSetVc { + fn read_task_collectibles(&self, _task: TaskId, _trait_id: TraitTypeId) -> Vc> { unimplemented!() } diff --git a/crates/turbo-tasks/Cargo.toml b/crates/turbo-tasks/Cargo.toml index c52f3a330a4c86..bc16dc239ad6ad 100644 --- a/crates/turbo-tasks/Cargo.toml +++ b/crates/turbo-tasks/Cargo.toml @@ -17,6 +17,7 @@ hanging_detection = [] [dependencies] anyhow = { workspace = true } +async-trait = { workspace = true } auto-hash-map = { workspace = true } concurrent-queue = { workspace = true } dashmap = { workspace = true } diff --git a/crates/turbo-tasks/src/backend.rs b/crates/turbo-tasks/src/backend.rs index 6b7872cd054079..b3d889a8defe69 100644 --- a/crates/turbo-tasks/src/backend.rs +++ b/crates/turbo-tasks/src/backend.rs @@ -10,13 +10,14 @@ use std::{ }; use anyhow::{anyhow, bail, Result}; +use auto_hash_map::AutoSet; use serde::{Deserialize, Serialize}; pub use crate::id::BackendJobId; use crate::{ - event::EventListener, manager::TurboTasksBackendApi, primitives::RawVcSetVc, raw_vc::CellId, - registry, task_input::SharedReference, FunctionId, RawVc, ReadRef, TaskId, TaskIdProvider, - TaskInput, TraitRef, TraitTypeId, ValueTraitVc, + event::EventListener, manager::TurboTasksBackendApi, raw_vc::CellId, registry, + ConcreteTaskInput, FunctionId, RawVc, ReadRef, SharedReference, TaskId, TaskIdProvider, + TraitRef, TraitTypeId, Vc, VcValueTrait, VcValueType, }; pub enum TaskType { @@ -61,17 +62,17 @@ impl Debug for TransientTaskType { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub enum PersistentTaskType { /// A normal task execution a native (rust) function - Native(FunctionId, Vec), + Native(FunctionId, Vec), /// A resolve task, which resolves arguments and calls the function with /// resolve arguments. The inner function call will do a cache lookup. - ResolveNative(FunctionId, Vec), + ResolveNative(FunctionId, Vec), /// A trait method resolve task. It resolves the first (`self`) argument and /// looks up the trait method on that value. Then it calls that method. /// The method call will do a cache lookup and might resolve arguments /// before. - ResolveTrait(TraitTypeId, Cow<'static, str>, Vec), + ResolveTrait(TraitTypeId, Cow<'static, str>, Vec), } impl Display for PersistentTaskType { @@ -144,7 +145,7 @@ impl Display for CellContent { } impl CellContent { - pub fn cast(self) -> Result> { + pub fn cast(self) -> Result> { let data = self.0.ok_or_else(|| anyhow!("Cell is empty"))?; let data = data .downcast() @@ -152,24 +153,13 @@ impl CellContent { Ok(ReadRef::new(data)) } - /// # Safety - /// - /// T and U must be binary identical (#[repr(transparent)]) - pub unsafe fn cast_transparent(self) -> Result> { - let data = self.0.ok_or_else(|| anyhow!("Cell is empty"))?; - let data = data - .downcast() - .ok_or_else(|| anyhow!("Unexpected type in cell"))?; - Ok(unsafe { ReadRef::new_transparent(data) }) - } - /// # Safety /// /// The caller must ensure that the CellContent contains a vc that /// implements T. pub fn cast_trait(self) -> Result> where - T: ValueTraitVc, + T: VcValueTrait + ?Sized, { let shared_reference = self.0.ok_or_else(|| anyhow!("Cell is empty"))?; if shared_reference.0.is_none() { @@ -181,7 +171,7 @@ impl CellContent { ) } - pub fn try_cast(self) -> Option> { + pub fn try_cast(self) -> Option> { self.0 .and_then(|data| data.downcast().map(|data| ReadRef::new(data))) } @@ -298,7 +288,7 @@ pub trait Backend: Sync + Send { trait_id: TraitTypeId, reader: TaskId, turbo_tasks: &dyn TurboTasksBackendApi, - ) -> RawVcSetVc; + ) -> Vc>; fn emit_collectible( &self, @@ -356,7 +346,7 @@ pub trait Backend: Sync + Send { impl PersistentTaskType { pub async fn run_resolve_native( fn_id: FunctionId, - inputs: Vec, + inputs: Vec, turbo_tasks: Arc>, ) -> Result { let mut resolved_inputs = Vec::with_capacity(inputs.len()); @@ -369,7 +359,7 @@ impl PersistentTaskType { pub async fn run_resolve_trait( trait_type: TraitTypeId, name: Cow<'static, str>, - inputs: Vec, + inputs: Vec, turbo_tasks: Arc>, ) -> Result { let mut resolved_inputs = Vec::with_capacity(inputs.len()); diff --git a/crates/turbo-tasks/src/collectibles.rs b/crates/turbo-tasks/src/collectibles.rs index 841ab151061a26..cea8f11513fea7 100644 --- a/crates/turbo-tasks/src/collectibles.rs +++ b/crates/turbo-tasks/src/collectibles.rs @@ -1,6 +1,6 @@ -use crate::{self as turbo_tasks, CollectiblesFuture}; +use crate::{CollectiblesFuture, VcValueTrait}; pub trait CollectiblesSource { - fn take_collectibles(self) -> CollectiblesFuture; - fn peek_collectibles(self) -> CollectiblesFuture; + fn take_collectibles(self) -> CollectiblesFuture; + fn peek_collectibles(self) -> CollectiblesFuture; } diff --git a/crates/turbo-tasks/src/completion.rs b/crates/turbo-tasks/src/completion.rs index 2e887c61472400..1c37b15c44ad87 100644 --- a/crates/turbo-tasks/src/completion.rs +++ b/crates/turbo-tasks/src/completion.rs @@ -1,5 +1,4 @@ -use crate::{self as turbo_tasks, RawVc}; - +use crate::{self as turbo_tasks, RawVc, Vc}; /// Just an empty type, but it's never equal to itself. /// [CompletionVc] can be used as return value instead of `()` /// to have a concrete reference that can be awaited. @@ -8,34 +7,28 @@ use crate::{self as turbo_tasks, RawVc}; #[turbo_tasks::value(cell = "new")] pub struct Completion; -impl Default for CompletionVc { - fn default() -> Self { - Self::new() - } -} - #[turbo_tasks::value_impl] -impl CompletionVc { +impl Completion { /// This will always be the same and never invalidates the reading task. #[turbo_tasks::function] - pub fn immutable() -> Self { - CompletionVc::cell(Completion) + pub fn immutable() -> Vc { + Completion::cell(Completion) } } // no #[turbo_tasks::value_impl] to inline new into the caller task // this ensures it's re-created on each execution -impl CompletionVc { +impl Completion { /// This will always be a new completion and invalidates the reading task. - pub fn new() -> Self { - CompletionVc::cell(Completion) + pub fn new() -> Vc { + Completion::cell(Completion) } /// Uses the previous completion. Can be used to cancel without triggering a /// new invalidation. - pub fn unchanged() -> Self { + pub fn unchanged() -> Vc { // This is the same code that CompletionVc::cell uses except that it - // only updates the cell when it is empty (CompletionVc::cell opted-out of + // only updates the cell when it is empty (Completion::cell opted-out of // that via `#[turbo_tasks::value(cell = "new")]`) let cell = turbo_tasks::macro_helpers::find_cell_by_type(*COMPLETION_VALUE_TYPE_ID); cell.conditional_update_shared(|old| old.is_none().then_some(Completion)); @@ -45,26 +38,26 @@ impl CompletionVc { } #[turbo_tasks::value(transparent)] -pub struct Completions(Vec); +pub struct Completions(Vec>); #[turbo_tasks::value_impl] -impl CompletionsVc { +impl Completions { /// Merges multiple completions into one. The passed list will be part of /// the cache key, so this function should not be used with varying lists. /// /// Varying lists should use `CompletionsVc::cell(list).completed()` /// instead. #[turbo_tasks::function] - pub fn all(completions: Vec) -> CompletionVc { - CompletionsVc::cell(completions).completed() + pub fn all(completions: Vec>) -> Vc { + Vc::::cell(completions).completed() } /// Merges the list of completions into one. #[turbo_tasks::function] - pub async fn completed(self) -> anyhow::Result { + pub async fn completed(self: Vc) -> anyhow::Result> { for c in self.await?.iter() { c.await?; } - Ok(CompletionVc::new()) + Ok(Completion::new()) } } diff --git a/crates/turbo-tasks/src/debug/mod.rs b/crates/turbo-tasks/src/debug/mod.rs index dd768457dbd9e9..27666189fce88b 100644 --- a/crates/turbo-tasks/src/debug/mod.rs +++ b/crates/turbo-tasks/src/debug/mod.rs @@ -3,7 +3,7 @@ use std::fmt::{Debug, Display}; use auto_hash_map::{AutoMap, AutoSet}; pub use turbo_tasks_macros::ValueDebugFormat; -use crate::{self as turbo_tasks}; +use crate::{self as turbo_tasks, Vc}; #[doc(hidden)] pub mod internal; @@ -15,7 +15,6 @@ use internal::PassthroughDebug; /// /// We don't use `StringVc` directly because we don't want the `Debug`/`Display` /// representations to be escaped. -#[derive(Clone)] #[turbo_tasks::value] pub struct ValueDebugString(String); @@ -38,10 +37,10 @@ impl ValueDebugString { } } -impl ValueDebugStringVc { - /// Create a new `ValueDebugStringVc` from a string. - pub fn new(s: String) -> Self { - ValueDebugStringVc::cell(ValueDebugString(s)) +impl ValueDebugString { + /// Create a new `ValueDebugString` from a string. + pub fn new(s: String) -> Vc { + ValueDebugString::cell(ValueDebugString(s)) } } @@ -55,10 +54,10 @@ impl ValueDebugStringVc { /// ``` #[turbo_tasks::value_trait(no_debug)] pub trait ValueDebug { - fn dbg(&self) -> ValueDebugStringVc; + fn dbg(self: Vc) -> Vc; /// Like `dbg`, but with a depth limit. - fn dbg_depth(&self, depth: usize) -> ValueDebugStringVc; + fn dbg_depth(self: Vc, depth: usize) -> Vc; } /// Use [autoref specialization] to implement `ValueDebug` for `T: Debug`. @@ -311,7 +310,7 @@ impl<'a> ValueDebugFormatString<'a> { /// Convert the `ValueDebugFormatString` into a `ValueDebugStringVc`. /// /// This can fail when resolving `Vc` types. - pub async fn try_to_value_debug_string(self) -> anyhow::Result { - Ok(ValueDebugStringVc::new(self.try_to_string().await?)) + pub async fn try_to_value_debug_string(self) -> anyhow::Result> { + Ok(ValueDebugString::new(self.try_to_string().await?)) } } diff --git a/crates/turbo-tasks/src/display.rs b/crates/turbo-tasks/src/display.rs index 89163d7d1ce7d2..9b3f13c6872a21 100644 --- a/crates/turbo-tasks/src/display.rs +++ b/crates/turbo-tasks/src/display.rs @@ -1,7 +1,6 @@ -use crate as turbo_tasks; -use crate::primitives::StringVc; +use crate::{self as turbo_tasks, Vc}; #[turbo_tasks::value_trait] pub trait ValueToString { - fn to_string(&self) -> StringVc; + fn to_string(self: Vc) -> Vc; } diff --git a/crates/turbo-tasks/src/graph/graph_traversal.rs b/crates/turbo-tasks/src/graph/graph_traversal.rs index 6cf3046683ebc9..aed61ef9442db2 100644 --- a/crates/turbo-tasks/src/graph/graph_traversal.rs +++ b/crates/turbo-tasks/src/graph/graph_traversal.rs @@ -18,7 +18,7 @@ pub trait GraphTraversal: GraphStore + Sized { self, root_edges: RootEdgesIt, visit: VisitImpl, - ) -> GraphTraversalFuture + ) -> GraphTraversalFuture where VisitImpl: Visit, RootEdgesIt: IntoIterator; @@ -36,7 +36,7 @@ where mut self, root_edges: RootEdgesIt, mut visit: VisitImpl, - ) -> GraphTraversalFuture + ) -> GraphTraversalFuture where VisitImpl: Visit, RootEdgesIt: IntoIterator, @@ -65,6 +65,7 @@ where store: self, futures, visit, + _phantom: std::marker::PhantomData, }), } } @@ -76,36 +77,43 @@ where /// A future that resolves to a [`GraphStore`] containing the result of a graph /// traversal. -pub struct GraphTraversalFuture +pub struct GraphTraversalFuture where Store: GraphStore, VisitImpl: Visit, + EdgesFuture: Future, { - state: GraphTraversalState, + state: GraphTraversalState, } #[derive(Default)] -enum GraphTraversalState +enum GraphTraversalState where Store: GraphStore, VisitImpl: Visit, + EdgesFuture: Future, { #[default] Completed, Aborted { abort: Abort, }, - Running(GraphTraversalRunningState), + Running(GraphTraversalRunningState), } -struct GraphTraversalRunningState +struct GraphTraversalRunningState where Store: GraphStore, VisitImpl: Visit, + EdgesFuture: Future, { store: Store, - futures: FuturesUnordered>, + // This should be VisitImpl::EdgesFuture, but this causes a bug in the Rust + // compiler (see https://github.com/rust-lang/rust/issues/102211). + // Instead, we pass the associated type as an additional generic parameter. + futures: FuturesUnordered>, visit: VisitImpl, + _phantom: std::marker::PhantomData<(Abort, Impl)>, } pub enum GraphTraversalResult { @@ -122,10 +130,14 @@ impl GraphTraversalResult { } } -impl Future for GraphTraversalFuture +impl Future + for GraphTraversalFuture where Store: GraphStore, - VisitImpl: Visit, + // The EdgesFuture bound is necessary to avoid the compiler bug mentioned + // above. + VisitImpl: Visit, + EdgesFuture: Future>, { type Output = GraphTraversalResult, Abort>; diff --git a/crates/turbo-tasks/src/id.rs b/crates/turbo-tasks/src/id.rs index 5905e3fa928ca2..887c594f32ef0d 100644 --- a/crates/turbo-tasks/src/id.rs +++ b/crates/turbo-tasks/src/id.rs @@ -173,7 +173,7 @@ where pub fn without_task_id_mapping(func: impl FnOnce() -> T) -> T { TASK_ID_MAPPING.with(|cell| { - let old = std::mem::replace(&mut *cell.borrow_mut(), None); + let old = (*cell.borrow_mut()).take(); let _swap_guard = TemporarySwapGuard(cell, ManuallyDrop::new(old)); func() }) diff --git a/crates/turbo-tasks/src/lib.rs b/crates/turbo-tasks/src/lib.rs index ddfc873fb956be..31e6c19b9eefb7 100644 --- a/crates/turbo-tasks/src/lib.rs +++ b/crates/turbo-tasks/src/lib.rs @@ -25,12 +25,15 @@ #![feature(trivial_bounds)] #![feature(min_specialization)] #![feature(try_trait_v2)] -#![feature(hash_drain_filter)] +#![feature(hash_extract_if)] #![deny(unsafe_op_in_unsafe_fn)] #![feature(result_flattening)] #![feature(error_generic_member_access)] #![feature(provide_any)] #![feature(new_uninit)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] +#![feature(type_alias_impl_trait)] #![feature(never_type)] pub mod backend; @@ -51,7 +54,6 @@ mod magic_any; mod manager; mod native_function; mod no_move_vec; -mod nothing; mod once_map; pub mod persisted_graph; pub mod primitives; @@ -60,18 +62,20 @@ mod read_ref; pub mod registry; pub mod small_duration; mod state; -mod task_input; +pub mod task; mod timed_future; pub mod trace; mod trait_ref; +mod unit; pub mod util; mod value; mod value_type; +mod vc; pub use anyhow::{Error, Result}; pub use collectibles::CollectiblesSource; -pub use completion::{Completion, CompletionVc, CompletionsVc}; -pub use display::{ValueToString, ValueToStringVc}; +pub use completion::{Completion, Completions}; +pub use display::ValueToString; pub use id::{ with_task_id_mapping, without_task_id_mapping, FunctionId, IdMapping, TaskId, TraitTypeId, ValueTypeId, @@ -86,21 +90,22 @@ pub use manager::{ StatsType, TaskIdProvider, TurboTasks, TurboTasksApi, TurboTasksBackendApi, TurboTasksCallApi, Unused, UpdateInfo, }; -pub use native_function::{NativeFunction, NativeFunctionVc}; -pub use nothing::{Nothing, NothingVc}; -pub use raw_vc::{ - CellId, CollectiblesFuture, RawVc, ReadRawVcFuture, ResolveTypeError, TraitCast, - TransparentValueCast, ValueCast, -}; +pub use native_function::NativeFunction; +pub use raw_vc::{CellId, CollectiblesFuture, RawVc, ReadRawVcFuture, ResolveTypeError}; pub use read_ref::ReadRef; pub use state::State; -pub use task_input::{FromTaskInput, SharedReference, SharedValue, TaskInput}; +pub use task::{ + concrete_task_input::{ConcreteTaskInput, SharedReference, SharedValue}, + task_input::TaskInput, +}; pub use trait_ref::{IntoTraitRef, TraitRef}; pub use turbo_tasks_macros::{function, value, value_impl, value_trait, TaskInput}; +pub use unit::unit; pub use value::{TransientInstance, TransientValue, Value}; -pub use value_type::{ - FromSubTrait, IntoSuperTrait, TraitMethod, TraitType, Typed, TypedForInput, ValueTraitVc, - ValueType, ValueVc, +pub use value_type::{TraitMethod, TraitType, ValueType}; +pub use vc::{ + Dynamic, TypedForInput, Upcast, ValueDefault, Vc, VcCellNewMode, VcCellSharedMode, + VcDefaultRead, VcRead, VcTransparentRead, VcValueTrait, VcValueType, }; pub mod test_helpers { diff --git a/crates/turbo-tasks/src/manager.rs b/crates/turbo-tasks/src/manager.rs index 32efb4b6521d4f..dfd845b456a359 100644 --- a/crates/turbo-tasks/src/manager.rs +++ b/crates/turbo-tasks/src/manager.rs @@ -28,25 +28,23 @@ use crate::{ event::{Event, EventListener}, id::{BackendJobId, FunctionId, TraitTypeId}, id_factory::IdFactory, - invalidation::InvalidationReasonSet, - primitives::RawVcSetVc, raw_vc::{CellId, RawVc}, registry, - task_input::{SharedReference, TaskInput}, timed_future::{self, TimedFuture}, trace::TraceRawVcs, util::{FormatDuration, StaticOrArc}, - Completion, CompletionVc, InvalidationReason, TaskId, ValueTraitVc, ValueTypeId, + Completion, ConcreteTaskInput, InvalidationReason, InvalidationReasonSet, SharedReference, + TaskId, ValueTypeId, Vc, VcRead, VcValueTrait, VcValueType, }; pub trait TurboTasksCallApi: Sync + Send { - fn dynamic_call(&self, func: FunctionId, inputs: Vec) -> RawVc; - fn native_call(&self, func: FunctionId, inputs: Vec) -> RawVc; + fn dynamic_call(&self, func: FunctionId, inputs: Vec) -> RawVc; + fn native_call(&self, func: FunctionId, inputs: Vec) -> RawVc; fn trait_call( &self, trait_type: TraitTypeId, trait_fn_name: Cow<'static, str>, - inputs: Vec, + inputs: Vec, ) -> RawVc; fn run_once( @@ -100,7 +98,7 @@ pub trait TurboTasksApi: TurboTasksCallApi + Sync + Send { index: CellId, ) -> Result>; - fn read_task_collectibles(&self, task: TaskId, trait_id: TraitTypeId) -> RawVcSetVc; + fn read_task_collectibles(&self, task: TaskId, trait_id: TraitTypeId) -> Vc>; fn emit_collectible(&self, trait_type: TraitTypeId, collectible: RawVc); fn unemit_collectible(&self, trait_type: TraitTypeId, collectible: RawVc); @@ -375,7 +373,7 @@ impl TurboTasks { let result = future.await?; tx.send(result) .map_err(|_| anyhow!("unable to send result"))?; - Ok(CompletionVc::new().into()) + Ok(Completion::new().node) }); // INVALIDATION: A Once task will never invalidate, therefore we don't need to // track a dependency @@ -387,7 +385,7 @@ impl TurboTasks { /// Call a native function with arguments. /// All inputs must be resolved. - pub(crate) fn native_call(&self, func: FunctionId, inputs: Vec) -> RawVc { + pub(crate) fn native_call(&self, func: FunctionId, inputs: Vec) -> RawVc { RawVc::TaskOutput(self.backend.get_or_create_persistent_task( PersistentTaskType::Native(func, inputs), current_task("turbo_function calls"), @@ -397,7 +395,7 @@ impl TurboTasks { /// Calls a native function with arguments. Resolves arguments when needed /// with a wrapper [Task]. - pub fn dynamic_call(&self, func: FunctionId, inputs: Vec) -> RawVc { + pub fn dynamic_call(&self, func: FunctionId, inputs: Vec) -> RawVc { if inputs.iter().all(|i| i.is_resolved() && !i.is_nothing()) { self.native_call(func, inputs) } else { @@ -415,13 +413,13 @@ impl TurboTasks { &self, trait_type: TraitTypeId, mut trait_fn_name: Cow<'static, str>, - inputs: Vec, + inputs: Vec, ) -> RawVc { // avoid creating a wrapper task if self is already resolved // for resolved cells we already know the value type so we can lookup the // function let first_input = inputs.first().expect("trait call without self argument"); - if let &TaskInput::TaskCell(_, CellId { type_id, .. }) = first_input { + if let &ConcreteTaskInput::TaskCell(_, CellId { type_id, .. }) = first_input { let value_type = registry::get_value_type(type_id); let key = (trait_type, trait_fn_name); if let Some(native_fn) = value_type.get_trait_method(&key) { @@ -667,9 +665,7 @@ impl TurboTasks { } else { drop(start_listener); } - if timeout.is_zero() - || matches!(tokio::time::timeout(timeout, listener).await, Err(_)) - { + if timeout.is_zero() || tokio::time::timeout(timeout, listener).await.is_err() { // Timeout return None; } @@ -813,17 +809,17 @@ impl TurboTasks { } impl TurboTasksCallApi for TurboTasks { - fn dynamic_call(&self, func: FunctionId, inputs: Vec) -> RawVc { + fn dynamic_call(&self, func: FunctionId, inputs: Vec) -> RawVc { self.dynamic_call(func, inputs) } - fn native_call(&self, func: FunctionId, inputs: Vec) -> RawVc { + fn native_call(&self, func: FunctionId, inputs: Vec) -> RawVc { self.native_call(func, inputs) } fn trait_call( &self, trait_type: TraitTypeId, trait_fn_name: Cow<'static, str>, - inputs: Vec, + inputs: Vec, ) -> RawVc { self.trait_call(trait_type, trait_fn_name, inputs) } @@ -835,7 +831,7 @@ impl TurboTasksCallApi for TurboTasks { ) -> TaskId { self.spawn_once_task(async move { future.await?; - Ok(CompletionVc::new().into()) + Ok(Completion::new().node) }) } @@ -851,7 +847,7 @@ impl TurboTasksCallApi for TurboTasks { } self.spawn_once_task(async move { future.await?; - Ok(CompletionVc::new().into()) + Ok(Completion::new().node) }) } @@ -865,7 +861,7 @@ impl TurboTasksCallApi for TurboTasks { this.finish_primary_job(); future.await?; this.begin_primary_job(); - Ok(CompletionVc::new().into()) + Ok(Completion::new().node) }) } } @@ -946,7 +942,7 @@ impl TurboTasksApi for TurboTasks { .try_read_own_task_cell_untracked(current_task, index, self) } - fn read_task_collectibles(&self, task: TaskId, trait_id: TraitTypeId) -> RawVcSetVc { + fn read_task_collectibles(&self, task: TaskId, trait_id: TraitTypeId) -> Vc> { self.backend.read_task_collectibles( task, trait_id, @@ -1305,7 +1301,7 @@ pub async fn run_once_with_reason( } /// see [TurboTasks] `dynamic_call` -pub fn dynamic_call(func: FunctionId, inputs: Vec) -> RawVc { +pub fn dynamic_call(func: FunctionId, inputs: Vec) -> RawVc { with_turbo_tasks(|tt| tt.dynamic_call(func, inputs)) } @@ -1313,7 +1309,7 @@ pub fn dynamic_call(func: FunctionId, inputs: Vec) -> RawVc { pub fn trait_call( trait_type: TraitTypeId, trait_fn_name: Cow<'static, str>, - inputs: Vec, + inputs: Vec, ) -> RawVc { with_turbo_tasks(|tt| tt.trait_call(trait_type, trait_fn_name, inputs)) } @@ -1386,8 +1382,8 @@ pub fn notify_scheduled_tasks() { with_turbo_tasks(|tt| tt.notify_scheduled_tasks()) } -pub fn emit(collectible: T) { - with_turbo_tasks(|tt| tt.emit_collectible(T::get_trait_type_id(), collectible.into())) +pub fn emit(collectible: Vc) { + with_turbo_tasks(|tt| tt.emit_collectible(T::get_trait_type_id(), collectible.node)) } pub async fn spawn_blocking(func: impl FnOnce() -> T + Send + 'static) -> T { @@ -1480,7 +1476,7 @@ pub struct CurrentCellRef { impl CurrentCellRef { pub fn conditional_update_shared< - T: Send + Sync + 'static, + T: VcValueType + 'static, F: FnOnce(Option<&T>) -> Option, >( &self, @@ -1491,7 +1487,10 @@ impl CurrentCellRef { .read_own_task_cell(self.current_task, self.index) .ok() .and_then(|v| v.try_cast::()); - let update = functor(content.as_deref()); + let update = + functor(content.as_deref().map(|content| { + <::Read as VcRead>::target_to_value_ref(content) + })); if let Some(update) = update { tt.update_own_task_cell( self.current_task, @@ -1504,7 +1503,7 @@ impl CurrentCellRef { } } - pub fn compare_and_update_shared(&self, new_content: T) { + pub fn compare_and_update_shared(&self, new_content: T) { self.conditional_update_shared(|old_content| { if let Some(old_content) = old_content { if PartialEq::eq(&new_content, old_content) { @@ -1515,7 +1514,7 @@ impl CurrentCellRef { }); } - pub fn update_shared(&self, new_content: T) { + pub fn update_shared(&self, new_content: T) { let tt = turbo_tasks(); tt.update_own_task_cell( self.current_task, @@ -1547,16 +1546,16 @@ impl From for RawVc { } } -pub fn find_cell_by_type(type_id: ValueTypeId) -> CurrentCellRef { +pub fn find_cell_by_type(ty: ValueTypeId) -> CurrentCellRef { CELL_COUNTERS.with(|cell| { let current_task = current_task("celling turbo_tasks values"); let mut map = cell.borrow_mut(); - let current_index = map.entry(type_id).or_default(); + let current_index = map.entry(ty).or_default(); let index = *current_index; *current_index += 1; CurrentCellRef { current_task, - index: CellId { type_id, index }, + index: CellId { type_id: ty, index }, } }) } diff --git a/crates/turbo-tasks/src/native_function.rs b/crates/turbo-tasks/src/native_function.rs index ebd5259dde5c61..8db7c5cd756e53 100644 --- a/crates/turbo-tasks/src/native_function.rs +++ b/crates/turbo-tasks/src/native_function.rs @@ -1,23 +1,17 @@ use std::{ fmt::Debug, - future::Future, hash::Hash, - pin::Pin, sync::atomic::{AtomicUsize, Ordering}, }; -use anyhow::{Context, Result}; - use crate::{ - self as turbo_tasks, registry::register_function, task_input::TaskInput, util::SharedError, - RawVc, + self as turbo_tasks, + registry::register_function, + task::{function::NativeTaskFn, IntoTaskFn, TaskFn}, + util::SharedError, + ConcreteTaskInput, }; -type NativeTaskFuture = Pin> + Send>>; -type NativeTaskFn = Box NativeTaskFuture + Send + Sync>; -type BoundNativeTaskFn = - Box) -> Result) + Send + Sync + 'static>; - /// A native (rust) turbo-tasks function. It's used internally by /// `#[turbo_tasks::function]`. #[turbo_tasks::value(cell = "new", serialization = "none", eq = "manual")] @@ -27,7 +21,7 @@ pub struct NativeFunction { /// The functor that creates a functor from inputs. The inner functor /// handles the task execution. #[turbo_tasks(debug_ignore, trace_ignore)] - pub bind_fn: BoundNativeTaskFn, + pub implementation: Box, // TODO move to Task /// A counter that tracks total executions of that function #[turbo_tasks(debug_ignore, trace_ignore)] @@ -42,24 +36,23 @@ impl Debug for NativeFunction { } } -type BindFn = Box) -> Result) + Send + Sync + 'static>; - impl NativeFunction { - pub fn new(name: String, bind_fn: BindFn) -> Self { + pub fn new(name: String, implementation: I) -> Self + where + I: IntoTaskFn, + { Self { name, - bind_fn, + implementation: Box::new(implementation.into_task_fn()), executed_count: AtomicUsize::new(0), } } /// Creates a functor for execution from a fixed set of inputs. - pub fn bind(&'static self, inputs: &Vec) -> NativeTaskFn { - match (self.bind_fn)(inputs) - .with_context(|| format!("Error during argument binding of {}", self.name)) - { - Ok(native_fn) => Box::new(move || { - let r = native_fn(); + pub fn bind(&'static self, inputs: &[ConcreteTaskInput]) -> NativeTaskFn { + match (self.implementation).functor(&self.name, inputs) { + Ok(functor) => Box::new(move || { + let r = (functor)(); if cfg!(feature = "log_function_stats") { let count = self.executed_count.fetch_add(1, Ordering::Relaxed); if count > 0 && count % 100000 == 0 { diff --git a/crates/turbo-tasks/src/no_move_vec.rs b/crates/turbo-tasks/src/no_move_vec.rs index 333b753023472f..7fde0833bec021 100644 --- a/crates/turbo-tasks/src/no_move_vec.rs +++ b/crates/turbo-tasks/src/no_move_vec.rs @@ -121,20 +121,6 @@ impl NoMoveVec { NoMoveVec { buckets } } - pub fn capacity(&self) -> usize { - self.buckets - .iter() - .enumerate() - .map(|(i, (ptr, _))| { - if ptr.load(Ordering::Relaxed).is_null() { - 0 - } else { - get_bucket_size::(i as u32) - } - }) - .sum() - } - pub fn get(&self, idx: usize) -> Option<&T> { let bucket_idx = get_bucket_index::(idx); let bucket_ptr = unsafe { self.buckets.get_unchecked(bucket_idx as usize) } diff --git a/crates/turbo-tasks/src/nothing.rs b/crates/turbo-tasks/src/nothing.rs deleted file mode 100644 index ebe2ea59b77b19..00000000000000 --- a/crates/turbo-tasks/src/nothing.rs +++ /dev/null @@ -1,15 +0,0 @@ -use crate::{self as turbo_tasks}; - -/// Just an empty type. -/// [NothingVc] can be used as return value instead of `()` -/// to have a concrete reference that can be awaited. -#[turbo_tasks::value] -pub struct Nothing; - -#[turbo_tasks::value_impl] -impl NothingVc { - #[turbo_tasks::function] - pub fn new() -> Self { - NothingVc::cell(Nothing) - } -} diff --git a/crates/turbo-tasks/src/primitives.rs b/crates/turbo-tasks/src/primitives.rs index d631b90b17e7c9..0dd38d1c2fd87e 100644 --- a/crates/turbo-tasks/src/primitives.rs +++ b/crates/turbo-tasks/src/primitives.rs @@ -1,74 +1,61 @@ use std::ops::Deref; -use anyhow::Result; use auto_hash_map::AutoSet; -use turbo_tasks::debug::ValueDebugFormat; +// This specific macro identifier is detected by turbo-tasks-build. +use turbo_tasks_macros::primitive as __turbo_tasks_internal_primitive; -use crate::{self as turbo_tasks, RawVc, ValueToString, ValueToStringVc}; +use crate::{self as turbo_tasks, RawVc, Vc}; -#[turbo_tasks::value(transparent)] -pub struct String(std::string::String); +__turbo_tasks_internal_primitive!(()); +__turbo_tasks_internal_primitive!(String); -#[turbo_tasks::value_impl] -impl StringVc { - #[turbo_tasks::function] - pub fn empty() -> Self { - Self::cell("".to_string()) - } +#[turbo_tasks::function] +fn empty_string() -> Vc { + Vc::cell(String::new()) } -#[turbo_tasks::value(transparent)] -pub struct OptionU16(Option); - -#[turbo_tasks::value(transparent)] -pub struct U32(u32); - -#[turbo_tasks::value(transparent)] -pub struct U64(u64); - -#[turbo_tasks::value_impl] -impl ValueToString for U64 { - #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.0.to_string()) +impl Vc { + #[inline(always)] + pub fn empty() -> Vc { + empty_string() } } -#[turbo_tasks::value(transparent)] -pub struct OptionString(Option); - -#[turbo_tasks::value(transparent)] -pub struct Strings(Vec); +__turbo_tasks_internal_primitive!(Option); +__turbo_tasks_internal_primitive!(Vec); -#[turbo_tasks::value_impl] -impl StringsVc { - #[turbo_tasks::function] - pub fn empty() -> Self { - Self::cell(Vec::new()) - } +#[turbo_tasks::function] +fn empty_string_vec() -> Vc> { + Vc::cell(Vec::new()) } -#[turbo_tasks::value(transparent)] -pub struct Bool(bool); - -#[turbo_tasks::value(transparent)] -pub struct Usize(usize); - -#[turbo_tasks::value(transparent)] -pub struct RawVcSet(AutoSet); - -#[derive(ValueDebugFormat)] -#[turbo_tasks::value(transparent)] -pub struct JsonValue(pub serde_json::Value); - -#[turbo_tasks::value_impl] -impl ValueToString for JsonValue { - #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.0.to_string()) +impl Vc> { + #[inline(always)] + pub fn empty() -> Vc> { + empty_string_vec() } } +__turbo_tasks_internal_primitive!(Option); + +__turbo_tasks_internal_primitive!(bool); + +__turbo_tasks_internal_primitive!(u8); +__turbo_tasks_internal_primitive!(u16); +__turbo_tasks_internal_primitive!(u32); +__turbo_tasks_internal_primitive!(u64); +__turbo_tasks_internal_primitive!(u128); +__turbo_tasks_internal_primitive!(i8); +__turbo_tasks_internal_primitive!(i16); +__turbo_tasks_internal_primitive!(i32); +__turbo_tasks_internal_primitive!(i64); +__turbo_tasks_internal_primitive!(i128); +__turbo_tasks_internal_primitive!(usize); +__turbo_tasks_internal_primitive!(isize); +__turbo_tasks_internal_primitive!(AutoSet); +__turbo_tasks_internal_primitive!(serde_json::Value); +__turbo_tasks_internal_primitive!(Vec); + #[turbo_tasks::value(transparent, eq = "manual")] #[derive(Debug, Clone)] pub struct Regex( diff --git a/crates/turbo-tasks/src/raw_vc.rs b/crates/turbo-tasks/src/raw_vc.rs index 6b218b0e458e78..51fee39675c079 100644 --- a/crates/turbo-tasks/src/raw_vc.rs +++ b/crates/turbo-tasks/src/raw_vc.rs @@ -21,11 +21,11 @@ use crate::{ read_task_cell, read_task_cell_untracked, read_task_output, read_task_output_untracked, TurboTasksApi, }, - primitives::{RawVcSet, RawVcSetVc}, registry::{self, get_value_type}, turbo_tasks, - value_type::ValueTraitVc, - CollectiblesSource, ReadRef, SharedReference, TaskId, TraitRef, TraitTypeId, ValueTypeId, + vc::{cast::VcCast, Vc, VcValueTraitCast, VcValueTypeCast}, + CollectiblesSource, ReadRef, SharedReference, TaskId, TraitTypeId, ValueTypeId, VcValueTrait, + VcValueType, }; #[derive(Error, Debug)] @@ -64,62 +64,39 @@ pub enum RawVc { } impl RawVc { - pub fn into_read(self) -> ReadRawVcFuture> { + pub fn into_read(self) -> ReadRawVcFuture> { // returns a custom future to have something concrete and sized // this avoids boxing in IntoFuture ReadRawVcFuture::new(self) } - pub fn into_strongly_consistent_read( + pub fn into_strongly_consistent_read( self, - ) -> ReadRawVcFuture> { + ) -> ReadRawVcFuture> { // returns a custom future to have something concrete and sized // this avoids boxing in IntoFuture ReadRawVcFuture::new_strongly_consistent(self) } - /// # Safety - /// - /// T and U must be binary identical (#[repr(transparent)]) - pub unsafe fn into_transparent_read( + pub fn into_trait_read( self, - ) -> ReadRawVcFuture> { + ) -> ReadRawVcFuture> { // returns a custom future to have something concrete and sized // this avoids boxing in IntoFuture - unsafe { ReadRawVcFuture::new_transparent(self) } + ReadRawVcFuture::new(self) } - /// # Safety - /// - /// T and U must be binary identical (#[repr(transparent)]) - pub unsafe fn into_transparent_strongly_consistent_read< - T: Any + Send + Sync, - U: Any + Send + Sync, - >( + pub fn into_strongly_consistent_trait_read( self, - ) -> ReadRawVcFuture> { + ) -> ReadRawVcFuture> { // returns a custom future to have something concrete and sized // this avoids boxing in IntoFuture - unsafe { ReadRawVcFuture::new_transparent_strongly_consistent(self) } - } - - pub fn into_trait_read(self) -> ReadRawVcFuture> - where - T: ValueTraitVc, - { - ReadRawVcFuture::new_trait(self) - } - - pub fn into_strongly_consistent_trait_read(self) -> ReadRawVcFuture> - where - T: ValueTraitVc, - { - ReadRawVcFuture::new_trait_strongly_consistent(self) + ReadRawVcFuture::new_strongly_consistent(self) } /// INVALIDATION: Be careful with this, it will not track dependencies, so /// using it could break cache invalidation. - pub async fn into_read_untracked( + pub async fn into_read_untracked( self, turbo_tasks: &dyn TurboTasksApi, ) -> Result> { @@ -130,7 +107,7 @@ impl RawVc { /// INVALIDATION: Be careful with this, it will not track dependencies, so /// using it could break cache invalidation. - pub async fn into_strongly_consistent_read_untracked( + pub async fn into_strongly_consistent_read_untracked( self, turbo_tasks: &dyn TurboTasksApi, ) -> Result> { @@ -245,15 +222,7 @@ impl RawVc { } } - /// Resolve the reference until it points to a cell directly. - /// - /// Resolving will wait for task execution to be finished, so that the - /// returned Vc points to a cell that stores a value. - /// - /// Resolving is necessary to compare identities of Vcs. - /// - /// This is async and will rethrow any fatal error that happened during task - /// execution. + /// See [`crate::Vc::resolve`]. pub async fn resolve(self) -> Result { let tt = turbo_tasks(); let mut current = self; @@ -271,17 +240,7 @@ impl RawVc { } } } - - /// Resolve the reference until it points to a cell directly in a strongly - /// consistent way. - /// - /// Resolving will wait for task execution to be finished, so that the - /// returned Vc points to a cell that stores a value. - /// - /// Resolving is necessary to compare identities of Vcs. - /// - /// This is async and will rethrow any fatal error that happened during task - /// execution. + /// See [`crate::Vc::resolve_strongly_consistent`]. pub async fn resolve_strongly_consistent(self) -> Result { let tt = turbo_tasks(); let mut current = self; @@ -320,10 +279,11 @@ impl RawVc { } impl CollectiblesSource for RawVc { - fn peek_collectibles(self) -> CollectiblesFuture { + fn peek_collectibles(self) -> CollectiblesFuture { let tt = turbo_tasks(); tt.notify_scheduled_tasks(); - let set: RawVcSetVc = tt.read_task_collectibles(self.get_task_id(), T::get_trait_type_id()); + let set: Vc> = + tt.read_task_collectibles(self.get_task_id(), T::get_trait_type_id()); CollectiblesFuture { turbo_tasks: tt, inner: set.into_future(), @@ -332,10 +292,11 @@ impl CollectiblesSource for RawVc { } } - fn take_collectibles(self) -> CollectiblesFuture { + fn take_collectibles(self) -> CollectiblesFuture { let tt = turbo_tasks(); tt.notify_scheduled_tasks(); - let set: RawVcSetVc = tt.read_task_collectibles(self.get_task_id(), T::get_trait_type_id()); + let set: Vc> = + tt.read_task_collectibles(self.get_task_id(), T::get_trait_type_id()); CollectiblesFuture { turbo_tasks: tt, inner: set.into_future(), @@ -358,21 +319,16 @@ impl Display for RawVc { } } -pub struct ReadRawVcFuture -where - C: Cast, -{ +pub struct ReadRawVcFuture> { turbo_tasks: Arc, strongly_consistent: bool, current: RawVc, listener: Option, - _cast: C, + phantom_data: PhantomData>>, + _cast: PhantomData, } -impl ReadRawVcFuture> -where - T: Any + Send + Sync, -{ +impl ReadRawVcFuture { fn new(vc: RawVc) -> Self { let tt = turbo_tasks(); tt.notify_scheduled_tasks(); @@ -381,9 +337,8 @@ where strongly_consistent: false, current: vc, listener: None, - _cast: ValueCast { - _phantom: PhantomData, - }, + phantom_data: PhantomData, + _cast: PhantomData, } } @@ -395,90 +350,14 @@ where strongly_consistent: true, current: vc, listener: None, - _cast: ValueCast { - _phantom: PhantomData, - }, - } - } -} - -impl ReadRawVcFuture> -where - T: Any + Send + Sync, -{ - /// # Safety - /// - /// T and U must be binary identical (#[repr(transparent)]) - unsafe fn new_transparent(vc: RawVc) -> Self { - let tt = turbo_tasks(); - tt.notify_scheduled_tasks(); - ReadRawVcFuture { - turbo_tasks: tt, - strongly_consistent: false, - current: vc, - listener: None, - _cast: TransparentValueCast { - _phantom: PhantomData, - }, - } - } - - /// # Safety - /// - /// T and U must be binary identical (#[repr(transparent)]) - unsafe fn new_transparent_strongly_consistent(vc: RawVc) -> Self { - let tt = turbo_tasks(); - tt.notify_scheduled_tasks(); - ReadRawVcFuture { - turbo_tasks: tt, - strongly_consistent: true, - current: vc, - listener: None, - _cast: TransparentValueCast { - _phantom: PhantomData, - }, - } - } -} - -impl ReadRawVcFuture> -where - T: ValueTraitVc, -{ - fn new_trait(vc: RawVc) -> Self { - let tt = turbo_tasks(); - tt.notify_scheduled_tasks(); - ReadRawVcFuture { - turbo_tasks: tt, - strongly_consistent: false, - current: vc, - listener: None, - _cast: TraitCast { - _phantom: PhantomData, - }, - } - } - - fn new_trait_strongly_consistent(vc: RawVc) -> Self { - let tt = turbo_tasks(); - tt.notify_scheduled_tasks(); - ReadRawVcFuture { - turbo_tasks: tt, - strongly_consistent: true, - current: vc, - listener: None, - _cast: TraitCast { - _phantom: PhantomData, - }, + phantom_data: PhantomData, + _cast: PhantomData, } } } -impl Future for ReadRawVcFuture -where - C: Cast, -{ - type Output = Result; +impl Future for ReadRawVcFuture { + type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { self.turbo_tasks.notify_scheduled_tasks(); @@ -509,7 +388,8 @@ where RawVc::TaskCell(task, index) => { match this.turbo_tasks.try_read_task_cell(task, index) { Ok(Ok(content)) => { - return Poll::Ready(C::cast(content)); + // SAFETY: Constructor ensures that T and U are binary identical + return Poll::Ready(Cast::cast(content)); } Ok(Err(listener)) => listener, Err(err) => return Poll::Ready(Err(err)), @@ -528,60 +408,10 @@ where } } -/// Trait defined to share behavior between values and traits within -/// [`ReadRawVcFuture`]. See [`ValueCast`] and [`TraitCast`]. -/// -/// This should not be implemented by users. -pub trait Cast { - type Output; +unsafe impl Send for ReadRawVcFuture where T: ?Sized {} +unsafe impl Sync for ReadRawVcFuture where T: ?Sized {} - fn cast(content: CellContent) -> Result; -} - -/// Casts an arbitrary cell content into a [`ReadRef`]. -pub struct ValueCast { - _phantom: PhantomData, -} - -impl Cast for ValueCast { - type Output = ReadRef; - - fn cast(content: CellContent) -> Result { - content.cast::() - } -} - -/// Casts an arbitrary cell content into a [`ReadRef`]. -pub struct TransparentValueCast { - _phantom: PhantomData<(T, U)>, -} - -impl Cast for TransparentValueCast { - type Output = ReadRef; - - fn cast(content: CellContent) -> Result { - // Safety: Constructor ensures that T and U are binary identical - unsafe { content.cast_transparent::() } - } -} - -/// Casts an arbitrary cell content into a [`TraitRef`]. -pub struct TraitCast { - _phantom: PhantomData, -} - -impl Cast for TraitCast -where - T: ValueTraitVc, -{ - type Output = TraitRef; - - fn cast(content: CellContent) -> Result { - // Safety: Constructor ensures the cell content points to a value that - // implements T - content.cast_trait::() - } -} +impl Unpin for ReadRawVcFuture where T: ?Sized {} #[derive(Error, Debug)] #[error("Unable to read collectibles")] @@ -589,22 +419,22 @@ pub struct ReadCollectiblesError { source: anyhow::Error, } -pub struct CollectiblesFuture { +pub struct CollectiblesFuture { turbo_tasks: Arc, - inner: ReadRawVcFuture>>, + inner: ReadRawVcFuture>, take: bool, phantom: PhantomData T>, } -impl CollectiblesFuture { +impl CollectiblesFuture { pub fn strongly_consistent(mut self) -> Self { self.inner.strongly_consistent = true; self } } -impl Future for CollectiblesFuture { - type Output = Result>; +impl Future for CollectiblesFuture { + type Output = Result>>; fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { // SAFETY: we are not moving `this` diff --git a/crates/turbo-tasks/src/read_ref.rs b/crates/turbo-tasks/src/read_ref.rs index 5f6f50a76d2ea3..1328e7a968320b 100644 --- a/crates/turbo-tasks/src/read_ref.rs +++ b/crates/turbo-tasks/src/read_ref.rs @@ -1,10 +1,8 @@ use std::{ - borrow::Borrow, cmp::Ordering, fmt::{Debug, Display}, hash::Hash, marker::PhantomData, - mem::transmute, sync::Arc, }; @@ -13,9 +11,9 @@ use turbo_tasks_hash::DeterministicHash; use crate::{ debug::{ValueDebugFormat, ValueDebugFormatString}, - manager::find_cell_by_type, + macro_helpers::find_cell_by_type, trace::{TraceRawVcs, TraceRawVcsContext}, - RawVc, SharedReference, Typed, + SharedReference, Vc, VcRead, VcValueType, }; /// The read value of a value cell. The read value is immutable, while the cell @@ -23,95 +21,128 @@ use crate::{ /// certain point in time. /// /// Internally it stores a reference counted reference to a value on the heap. -/// -/// Invariant: T and U are binary identical (#[repr(transparent)]) -pub struct ReadRef(Arc, PhantomData>); +pub struct ReadRef(Arc); -impl Clone for ReadRef { +impl Clone for ReadRef { fn clone(&self) -> Self { - Self(self.0.clone(), PhantomData) + Self(self.0.clone()) } } -impl std::ops::Deref for ReadRef { - type Target = U; +impl std::ops::Deref for ReadRef +where + T: VcValueType, +{ + type Target = >::Target; fn deref(&self) -> &Self::Target { - let inner: &T = &self.0; - unsafe { transmute(inner) } + T::Read::value_to_target_ref(&self.0) } } -unsafe impl stable_deref_trait::StableDeref for ReadRef {} -unsafe impl stable_deref_trait::CloneStableDeref for ReadRef {} - -impl Display for ReadRef { +impl Display for ReadRef +where + T: VcValueType, + >::Target: Display, +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } } -impl Debug for ReadRef { +impl Debug for ReadRef +where + T: VcValueType, + >::Target: Debug, +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) } } -impl TraceRawVcs for ReadRef { +impl TraceRawVcs for ReadRef +where + T: VcValueType, + >::Target: TraceRawVcs, +{ fn trace_raw_vcs(&self, context: &mut TraceRawVcsContext) { (**self).trace_raw_vcs(context); } } -impl ValueDebugFormat for ReadRef { +impl ValueDebugFormat for ReadRef +where + T: VcValueType, + >::Target: ValueDebugFormat + 'static, +{ fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString { let value = &**self; value.value_debug_format(depth) } } -impl PartialEq for ReadRef { +impl PartialEq for ReadRef +where + T: VcValueType, + >::Target: PartialEq, +{ fn eq(&self, other: &Self) -> bool { PartialEq::eq(&**self, &**other) } } -impl Eq for ReadRef {} +impl Eq for ReadRef +where + T: VcValueType, + >::Target: Eq, +{ +} -impl PartialOrd for ReadRef { +impl PartialOrd for ReadRef +where + T: VcValueType, + >::Target: PartialOrd, +{ fn partial_cmp(&self, other: &Self) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } -impl Ord for ReadRef { +impl Ord for ReadRef +where + T: VcValueType, + >::Target: Ord, +{ fn cmp(&self, other: &Self) -> std::cmp::Ordering { Ord::cmp(&**self, &**other) } } -impl Hash for ReadRef { +impl Hash for ReadRef +where + T: VcValueType, + >::Target: Hash, +{ fn hash(&self, state: &mut H) { Hash::hash(&**self, state) } } -impl DeterministicHash for ReadRef { +impl DeterministicHash for ReadRef +where + T: VcValueType, + >::Target: DeterministicHash, +{ fn deterministic_hash(&self, state: &mut H) { let p = &**self; p.deterministic_hash(state); } } -impl Borrow for ReadRef { - fn borrow(&self) -> &U { - self - } -} - -impl<'a, T, U, I, J: Iterator> IntoIterator for &'a ReadRef +impl<'a, T, I, J: Iterator> IntoIterator for &'a ReadRef where - &'a U: IntoIterator, + T: VcValueType, + &'a >::Target: IntoIterator, { type Item = I; @@ -122,118 +153,71 @@ where } } -impl Serialize for ReadRef { +impl Serialize for ReadRef +where + T: VcValueType, + >::Target: Serialize, +{ fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - T::serialize(&self.0, serializer) + (**self).serialize(serializer) } } -impl<'de, T: Deserialize<'de>, U> Deserialize<'de> for ReadRef { +impl<'de, T> Deserialize<'de> for ReadRef +where + T: Deserialize<'de>, +{ fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let value = T::deserialize(deserializer)?; - Ok(Self(Arc::new(value), PhantomData)) + Ok(Self(Arc::new(value))) } } -impl ReadRef { +impl ReadRef { pub fn new(arc: Arc) -> Self { - Self(arc, PhantomData) - } -} - -impl ReadRef { - /// # Safety - /// - /// T and U must be binary identical (#[repr(transparent)]) - pub unsafe fn new_transparent(arc: Arc) -> Self { - Self(arc, PhantomData) + Self(arc) } - pub fn ptr_eq(&self, other: &ReadRef) -> bool { + pub fn ptr_eq(&self, other: &ReadRef) -> bool { Arc::ptr_eq(&self.0, &other.0) } - pub fn ptr_cmp(&self, other: &ReadRef) -> Ordering { + pub fn ptr_cmp(&self, other: &ReadRef) -> Ordering { Arc::as_ptr(&self.0).cmp(&Arc::as_ptr(&other.0)) } } -impl ReadRef +impl ReadRef where - T: Typed + Send + Sync + 'static, + T: VcValueType, { - /// Returns a new cell that points to a value that implements the value - /// trait `T`. - pub fn cell(trait_ref: ReadRef) -> T::Vc { - // See Safety clause above. + /// Returns a new cell that points to the same value as the given + /// reference. + pub fn cell(read_ref: ReadRef) -> Vc { let local_cell = find_cell_by_type(T::get_value_type_id()); local_cell - .update_shared_reference(SharedReference(Some(T::get_value_type_id()), trait_ref.0)); - let raw_vc: RawVc = local_cell.into(); - raw_vc.into() + .update_shared_reference(SharedReference(Some(T::get_value_type_id()), read_ref.0)); + Vc { + node: local_cell.into(), + _t: PhantomData, + } } } -impl ReadRef { +impl ReadRef +where + T: VcValueType, + >::Target: Clone, +{ /// This will clone the contained value instead of cloning the ReadRef. /// This clone is more expensive, but allows to get an mutable owned value. - pub fn clone_value(&self) -> U { + pub fn clone_value(&self) -> >::Target { (**self).clone() } } - -#[cfg(test)] -mod tests { - use std::sync::Arc; - - use serde::{Deserialize, Serialize}; - use serde_test::{assert_tokens, Token}; - - use super::ReadRef; - - #[test] - fn serde_transparent() { - #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] - struct Foo16(u16); - type Foo16ReadRef = ReadRef; - - let v = Foo16(123); - let v = unsafe { Foo16ReadRef::new_transparent(Arc::new(v)) }; - - assert_tokens( - &v, - &[Token::NewtypeStruct { name: "Foo16" }, Token::U16(123)], - ) - } - - #[test] - fn serde_non_transparent() { - #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] - struct Foo16 { - value: u16, - } - type Foo16ReadRef = ReadRef; - - let v = Foo16 { value: 123 }; - let v = Foo16ReadRef::new(Arc::new(v)); - - assert_tokens( - &v, - &[ - Token::Struct { - name: "Foo16", - len: 1, - }, - Token::Str("value"), - Token::U16(123), - Token::StructEnd, - ], - ) - } -} diff --git a/crates/turbo-tasks/src/registry.rs b/crates/turbo-tasks/src/registry.rs index 3df5d6a02c56f0..d722728dd9e0cc 100644 --- a/crates/turbo-tasks/src/registry.rs +++ b/crates/turbo-tasks/src/registry.rs @@ -52,8 +52,8 @@ fn register_thing< } fn get_thing_id< - K: From + Deref + Sync + Send + Copy, - V: Clone + Hash + Ord + Eq + Debug + Sync + Send, + K: From + Deref + Sync + Send + Copy + Debug, + V: Clone + Hash + Ord + Eq + Debug + Sync + Send + Debug, >( value: V, map_by_value: &DashMap, diff --git a/crates/turbo-tasks/src/state.rs b/crates/turbo-tasks/src/state.rs index 1adc34fce1d6a7..5f49d51511f695 100644 --- a/crates/turbo-tasks/src/state.rs +++ b/crates/turbo-tasks/src/state.rs @@ -1,8 +1,4 @@ -use std::{ - fmt::Debug, - mem::take, - ops::{Deref, DerefMut}, -}; +use std::{fmt::Debug, mem::take}; use auto_hash_map::AutoSet; use parking_lot::{Mutex, MutexGuard}; @@ -21,7 +17,6 @@ struct StateInner { pub struct StateRef<'a, T> { inner: MutexGuard<'a, StateInner>, - mutated: bool, } impl Debug for State { @@ -52,7 +47,7 @@ impl PartialEq for State { } impl Eq for State {} -impl Serialize for State { +impl Serialize for State { fn serialize(&self, _serializer: S) -> Result { // For this to work at all we need to do more. Changing the the state need to // invalidate the serialization of the task that contains the state. So we @@ -62,7 +57,7 @@ impl Serialize for State { } } -impl<'de, T> Deserialize<'de> for State { +impl<'de, T: Deserialize<'de>> Deserialize<'de> for State { fn deserialize>(_deserializer: D) -> Result { panic!("State serialization is not implemented yet"); } @@ -95,19 +90,7 @@ impl State { let invalidator = get_invalidator(); let mut inner = self.inner.lock(); inner.invalidators.insert(invalidator); - StateRef { - inner, - mutated: false, - } - } - - /// Gets the current value of the state. Untracked. - pub fn get_untracked(&self) -> StateRef<'_, T> { - let inner = self.inner.lock(); - StateRef { - inner, - mutated: false, - } + StateRef { inner } } /// Sets the current state without comparing it with the old value. This @@ -150,27 +133,10 @@ impl State { } } -impl<'a, T> Deref for StateRef<'a, T> { +impl<'a, T> std::ops::Deref for StateRef<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { &self.inner.value } } - -impl<'a, T> DerefMut for StateRef<'a, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.mutated = true; - &mut self.inner.value - } -} - -impl<'a, T> Drop for StateRef<'a, T> { - fn drop(&mut self) { - if self.mutated { - for invalidator in take(&mut self.inner.invalidators) { - invalidator.invalidate(); - } - } - } -} diff --git a/crates/turbo-tasks/src/task/concrete_task_input.rs b/crates/turbo-tasks/src/task/concrete_task_input.rs new file mode 100644 index 00000000000000..839e8e54b750dc --- /dev/null +++ b/crates/turbo-tasks/src/task/concrete_task_input.rs @@ -0,0 +1,523 @@ +use std::{ + any::Any, + borrow::Cow, + fmt::{Debug, Display}, + future::Future, + hash::Hash, + pin::Pin, + sync::Arc, +}; + +use anyhow::Result; +use serde::{ser::SerializeTuple, Deserialize, Serialize}; + +use crate::{ + backend::CellContent, + id::{FunctionId, TraitTypeId}, + magic_any::MagicAny, + manager::{read_task_cell, read_task_output}, + registry, turbo_tasks, CellId, RawVc, TaskId, TraitType, ValueTypeId, +}; + +#[derive(Clone)] +pub struct SharedReference(pub Option, pub Arc); + +impl SharedReference { + pub fn downcast(self) -> Option> { + match Arc::downcast(self.1) { + Ok(data) => Some(data), + Err(_) => None, + } + } +} + +impl Hash for SharedReference { + fn hash(&self, state: &mut H) { + Hash::hash(&(&*self.1 as *const (dyn Any + Send + Sync)), state) + } +} +impl PartialEq for SharedReference { + fn eq(&self, other: &Self) -> bool { + PartialEq::eq( + &(&*self.1 as *const (dyn Any + Send + Sync)), + &(&*other.1 as *const (dyn Any + Send + Sync)), + ) + } +} +impl Eq for SharedReference {} +impl PartialOrd for SharedReference { + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp( + &(&*self.1 as *const (dyn Any + Send + Sync)), + &(&*other.1 as *const (dyn Any + Send + Sync)), + ) + } +} +impl Ord for SharedReference { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + Ord::cmp( + &(&*self.1 as *const (dyn Any + Send + Sync)), + &(&*other.1 as *const (dyn Any + Send + Sync)), + ) + } +} +impl Debug for SharedReference { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("SharedReference") + .field(&self.0) + .field(&self.1) + .finish() + } +} + +impl Serialize for SharedReference { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if let SharedReference(Some(ty), arc) = self { + let value_type = registry::get_value_type(*ty); + if let Some(serializable) = value_type.any_as_serializable(arc) { + let mut t = serializer.serialize_tuple(2)?; + t.serialize_element(registry::get_value_type_global_name(*ty))?; + t.serialize_element(serializable)?; + t.end() + } else { + Err(serde::ser::Error::custom(format!( + "{:?} is not serializable", + arc + ))) + } + } else { + Err(serde::ser::Error::custom( + "untyped values are not serializable", + )) + } + } +} + +impl Display for SharedReference { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(ty) = self.0 { + write!(f, "value of type {}", registry::get_value_type(ty).name) + } else { + write!(f, "untyped value") + } + } +} + +impl<'de> Deserialize<'de> for SharedReference { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = SharedReference; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a serializable shared reference") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + if let Some(global_name) = seq.next_element()? { + if let Some(ty) = registry::get_value_type_id_by_global_name(global_name) { + if let Some(seed) = registry::get_value_type(ty).get_any_deserialize_seed() + { + if let Some(value) = seq.next_element_seed(seed)? { + Ok(SharedReference(Some(ty), value.into())) + } else { + Err(serde::de::Error::invalid_length( + 1, + &"tuple with type and value", + )) + } + } else { + Err(serde::de::Error::custom(format!( + "{ty} is not deserializable" + ))) + } + } else { + Err(serde::de::Error::unknown_variant(global_name, &[])) + } + } else { + Err(serde::de::Error::invalid_length( + 0, + &"tuple with type and value", + )) + } + } + } + + deserializer.deserialize_tuple(2, Visitor) + } +} + +#[derive(Debug, Clone, PartialOrd, Ord)] +pub struct TransientSharedValue(pub Arc); + +impl TransientSharedValue { + pub fn downcast(self) -> Option> { + match Arc::downcast(self.0.magic_any_arc()) { + Ok(data) => Some(data), + Err(_) => None, + } + } +} + +impl Hash for TransientSharedValue { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl PartialEq for TransientSharedValue { + #[allow(clippy::op_ref)] + fn eq(&self, other: &Self) -> bool { + &self.0 == &other.0 + } +} +impl Eq for TransientSharedValue {} +impl Serialize for TransientSharedValue { + fn serialize(&self, _serializer: S) -> Result + where + S: serde::Serializer, + { + Err(serde::ser::Error::custom( + "Transient values can't be serialized", + )) + } +} +impl<'de> Deserialize<'de> for TransientSharedValue { + fn deserialize(_deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + unreachable!("Transient values can't be serialized") + } +} + +#[derive(Debug, Clone, PartialOrd, Ord)] +pub struct SharedValue(pub Option, pub Arc); + +impl SharedValue { + pub fn downcast(self) -> Option> { + match Arc::downcast(self.1.magic_any_arc()) { + Ok(data) => Some(data), + Err(_) => None, + } + } +} + +impl PartialEq for SharedValue { + // this breaks without the ref + #[allow(clippy::op_ref)] + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 && &self.1 == &other.1 + } +} + +impl Eq for SharedValue {} + +impl Hash for SharedValue { + fn hash(&self, state: &mut H) { + self.0.hash(state); + self.1.hash(state); + } +} + +impl Display for SharedValue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(ty) = self.0 { + write!(f, "value of type {}", registry::get_value_type(ty).name) + } else { + write!(f, "untyped value") + } + } +} + +impl Serialize for SharedValue { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if let SharedValue(Some(ty), arc) = self { + let value_type = registry::get_value_type(*ty); + if let Some(serializable) = value_type.magic_as_serializable(arc) { + let mut t = serializer.serialize_tuple(2)?; + t.serialize_element(registry::get_value_type_global_name(*ty))?; + t.serialize_element(serializable)?; + t.end() + } else { + Err(serde::ser::Error::custom(format!( + "{:?} is not serializable", + arc + ))) + } + } else { + Err(serde::ser::Error::custom( + "untyped values are not serializable", + )) + } + } +} + +impl<'de> Deserialize<'de> for SharedValue { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = SharedValue; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a serializable shared value") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + if let Some(global_name) = seq.next_element()? { + if let Some(ty) = registry::get_value_type_id_by_global_name(global_name) { + if let Some(seed) = + registry::get_value_type(ty).get_magic_deserialize_seed() + { + if let Some(value) = seq.next_element_seed(seed)? { + Ok(SharedValue(Some(ty), value.into())) + } else { + Err(serde::de::Error::invalid_length( + 1, + &"tuple with type and value", + )) + } + } else { + Err(serde::de::Error::custom(format!( + "{ty} is not deserializable" + ))) + } + } else { + Err(serde::de::Error::unknown_variant(global_name, &[])) + } + } else { + Err(serde::de::Error::invalid_length( + 0, + &"tuple with type and value", + )) + } + } + } + + deserializer.deserialize_tuple(2, Visitor) + } +} + +#[allow(clippy::derived_hash_with_manual_eq)] +#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum ConcreteTaskInput { + TaskOutput(TaskId), + TaskCell(TaskId, CellId), + List(Vec), + String(String), + Bool(bool), + Usize(usize), + I8(i8), + U8(u8), + I16(i16), + U16(u16), + I32(i32), + U32(u32), + U64(u64), + Nothing, + SharedValue(SharedValue), + TransientSharedValue(TransientSharedValue), + SharedReference(SharedReference), +} + +impl ConcreteTaskInput { + pub async fn resolve_to_value(self) -> Result { + let tt = turbo_tasks(); + let mut current = self; + loop { + current = match current { + ConcreteTaskInput::TaskOutput(task_id) => { + read_task_output(&*tt, task_id, false).await?.into() + } + ConcreteTaskInput::TaskCell(task_id, index) => { + read_task_cell(&*tt, task_id, index).await?.into() + } + _ => return Ok(current), + } + } + } + + pub async fn resolve(self) -> Result { + let tt = turbo_tasks(); + let mut current = self; + loop { + current = match current { + ConcreteTaskInput::TaskOutput(task_id) => { + read_task_output(&*tt, task_id, false).await?.into() + } + ConcreteTaskInput::List(list) => { + if list.iter().all(|i| i.is_resolved()) { + return Ok(ConcreteTaskInput::List(list)); + } + fn resolve_all( + list: Vec, + ) -> Pin>> + Send>> + { + use crate::TryJoinIterExt; + Box::pin(list.into_iter().map(|i| i.resolve()).try_join()) + } + return Ok(ConcreteTaskInput::List(resolve_all(list).await?)); + } + _ => return Ok(current), + } + } + } + + pub fn get_task_id(&self) -> Option { + match self { + ConcreteTaskInput::TaskOutput(t) | ConcreteTaskInput::TaskCell(t, _) => Some(*t), + _ => None, + } + } + + pub fn get_trait_method( + &self, + trait_type: TraitTypeId, + name: Cow<'static, str>, + ) -> Result> { + match self { + ConcreteTaskInput::TaskOutput(_) | ConcreteTaskInput::TaskCell(_, _) => { + panic!("get_trait_method must be called on a resolved TaskInput") + } + ConcreteTaskInput::SharedValue(SharedValue(ty, _)) + | ConcreteTaskInput::SharedReference(SharedReference(ty, _)) => { + if let Some(ty) = *ty { + let key = (trait_type, name); + if let Some(func) = registry::get_value_type(ty).get_trait_method(&key) { + Ok(*func) + } else if let Some(func) = registry::get_trait(trait_type) + .default_trait_methods + .get(&key.1) + { + Ok(*func) + } else { + Err(key.1) + } + } else { + Err(name) + } + } + _ => Err(name), + } + } + + pub fn has_trait(&self, trait_type: TraitTypeId) -> bool { + match self { + ConcreteTaskInput::TaskOutput(_) | ConcreteTaskInput::TaskCell(_, _) => { + panic!("has_trait() must be called on a resolved TaskInput") + } + ConcreteTaskInput::SharedValue(SharedValue(ty, _)) + | ConcreteTaskInput::SharedReference(SharedReference(ty, _)) => { + if let Some(ty) = *ty { + registry::get_value_type(ty).has_trait(&trait_type) + } else { + false + } + } + _ => false, + } + } + + pub fn traits(&self) -> Vec<&'static TraitType> { + match self { + ConcreteTaskInput::TaskOutput(_) | ConcreteTaskInput::TaskCell(_, _) => { + panic!("traits() must be called on a resolved TaskInput") + } + ConcreteTaskInput::SharedValue(SharedValue(ty, _)) + | ConcreteTaskInput::SharedReference(SharedReference(ty, _)) => { + if let Some(ty) = *ty { + registry::get_value_type(ty) + .traits_iter() + .map(registry::get_trait) + .collect() + } else { + Vec::new() + } + } + _ => Vec::new(), + } + } + + pub fn is_resolved(&self) -> bool { + match self { + ConcreteTaskInput::TaskOutput(_) => false, + ConcreteTaskInput::List(list) => list.iter().all(|i| i.is_resolved()), + _ => true, + } + } + + pub fn is_nothing(&self) -> bool { + matches!(self, ConcreteTaskInput::Nothing) + } +} + +impl From for ConcreteTaskInput { + fn from(raw_vc: RawVc) -> Self { + match raw_vc { + RawVc::TaskOutput(task) => ConcreteTaskInput::TaskOutput(task), + RawVc::TaskCell(task, i) => ConcreteTaskInput::TaskCell(task, i), + } + } +} + +impl From for ConcreteTaskInput { + fn from(content: CellContent) -> Self { + match content { + CellContent(None) => ConcreteTaskInput::Nothing, + CellContent(Some(shared_ref)) => ConcreteTaskInput::SharedReference(shared_ref), + } + } +} + +impl Display for ConcreteTaskInput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConcreteTaskInput::TaskOutput(task) => write!(f, "task output {}", task), + ConcreteTaskInput::TaskCell(task, index) => write!(f, "cell {} in {}", index, task), + ConcreteTaskInput::List(list) => write!( + f, + "list {}", + list.iter() + .map(|i| i.to_string()) + .collect::>() + .join(", ") + ), + ConcreteTaskInput::String(s) => write!(f, "string {:?}", s), + ConcreteTaskInput::Bool(b) => write!(f, "bool {:?}", b), + ConcreteTaskInput::Usize(v) => write!(f, "usize {}", v), + ConcreteTaskInput::I8(v) => write!(f, "i8 {}", v), + ConcreteTaskInput::U8(v) => write!(f, "u8 {}", v), + ConcreteTaskInput::I16(v) => write!(f, "i16 {}", v), + ConcreteTaskInput::U16(v) => write!(f, "u16 {}", v), + ConcreteTaskInput::I32(v) => write!(f, "i32 {}", v), + ConcreteTaskInput::U32(v) => write!(f, "u32 {}", v), + ConcreteTaskInput::U64(v) => write!(f, "u64 {}", v), + ConcreteTaskInput::Nothing => write!(f, "nothing"), + ConcreteTaskInput::SharedValue(_) => write!(f, "any value"), + ConcreteTaskInput::TransientSharedValue(_) => write!(f, "any transient value"), + ConcreteTaskInput::SharedReference(data) => { + write!(f, "shared reference with {}", data) + } + } + } +} diff --git a/crates/turbo-tasks/src/task/function.rs b/crates/turbo-tasks/src/task/function.rs new file mode 100644 index 00000000000000..b86bd084c57d10 --- /dev/null +++ b/crates/turbo-tasks/src/task/function.rs @@ -0,0 +1,418 @@ +use std::{future::Future, marker::PhantomData, pin::Pin}; + +use anyhow::{bail, Context, Result}; + +use super::{TaskInput, TaskOutput}; +use crate::{macro_helpers, ConcreteTaskInput, RawVc, Vc, VcRead, VcValueType}; + +pub type NativeTaskFuture = Pin> + Send>>; +pub type NativeTaskFn = Box NativeTaskFuture + Send + Sync>; + +pub trait TaskFn: Send + Sync + 'static { + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result; +} + +pub trait IntoTaskFn { + type TaskFn: TaskFn; + + fn into_task_fn(self) -> Self::TaskFn; +} + +impl IntoTaskFn for F +where + F: TaskFnInputFunction, + Mode: TaskFnMode, + Inputs: TaskInputs, +{ + type TaskFn = FunctionTaskFn; + + fn into_task_fn(self) -> Self::TaskFn { + FunctionTaskFn { + task_fn: self, + mode: PhantomData, + inputs: PhantomData, + } + } +} + +pub struct FunctionTaskFn { + task_fn: F, + mode: PhantomData, + inputs: PhantomData, +} + +impl TaskFn for FunctionTaskFn +where + F: TaskFnInputFunction, + Mode: TaskFnMode, + Inputs: TaskInputs, +{ + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result { + TaskFnInputFunction::functor(&self.task_fn, name, inputs) + } +} + +trait TaskFnInputFunction: Send + Sync + Clone + 'static { + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result; +} + +pub trait TaskFnMode: Send + Sync + 'static {} + +pub trait TaskInputs: Send + Sync + 'static {} + +pub struct FunctionMode; +impl TaskFnMode for FunctionMode {} + +pub struct MethodMode; +impl TaskFnMode for MethodMode {} + +pub struct AsyncFunctionMode; +impl TaskFnMode for AsyncFunctionMode {} + +pub struct AsyncMethodMode; +impl TaskFnMode for AsyncMethodMode {} + +macro_rules! task_inputs_impl { + ( $( $arg:ident )* ) => { + impl<$($arg,)*> TaskInputs for ($($arg,)*) + where + $($arg: TaskInput + 'static,)* + {} + } +} + +macro_rules! task_fn_impl { + ( $async_fn_trait:ident , $( $arg:ident )* ) => { + impl TaskFnInputFunction for F + where + $($arg: TaskInput + 'static,)* + F: Fn($($arg,)*) -> Output + Send + Sync + Clone + 'static, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result { + let task_fn = self.clone(); + let mut iter = inputs.iter(); + + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(macro_helpers::tracing::Instrument::instrument(async move { + Output::try_into_raw_vc((task_fn)($($arg),*)) + }, macro_helpers::tracing::trace_span!("{}", name))) + })) + } + } + + impl TaskFnInputFunction for F + where + $($arg: TaskInput + 'static,)* + F: Fn($($arg,)*) -> FutureOutput + Send + Sync + Clone + 'static, + FutureOutput: Future + Send, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result { + let task_fn = self.clone(); + let mut iter = inputs.iter(); + + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(macro_helpers::tracing::Instrument::instrument(async move { + let result = Output::try_into_raw_vc((task_fn)($($arg),*).await); + macro_helpers::notify_scheduled_tasks(); + result + }, macro_helpers::tracing::trace_span!("{}", name))) + })) + } + } + + impl TaskFnInputFunction, $($arg,)*)> for F + where + Recv: VcValueType, + $($arg: TaskInput + 'static,)* + F: Fn(&Recv, $($arg,)*) -> Output + Send + Sync + Clone + 'static, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result { + let task_fn = self.clone(); + let mut iter = inputs.iter(); + + let recv = iter.next().context("task is missing receiver")?; + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + let recv = Vc::::try_from_concrete(recv)?; + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + let recv = recv.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(macro_helpers::tracing::Instrument::instrument(async move { + let recv = recv.await?; + let recv = <::Read as VcRead>::target_to_value_ref(&*recv); + let result = Output::try_into_raw_vc((task_fn)(recv, $($arg),*)); + macro_helpers::notify_scheduled_tasks(); + result + }, macro_helpers::tracing::trace_span!("{}", name))) + })) + } + } + + pub trait $async_fn_trait: Fn(A0, $($arg,)*) -> Self::OutputFuture { + type OutputFuture: Future>::Output> + Send; + type Output: TaskOutput; + } + + impl $async_fn_trait for F + where + F: Fn(A0, $($arg,)*) -> Fut, + Fut: Future + Send, + Fut::Output: TaskOutput + { + type OutputFuture = Fut; + type Output = Fut::Output; + } + + impl TaskFnInputFunction, $($arg,)*)> for F + where + Recv: VcValueType, + $($arg: TaskInput + 'static,)* + F: for<'a> $async_fn_trait<&'a Recv, $($arg,)*> + Clone + Send + Sync + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, name: &'static str, inputs: &[ConcreteTaskInput]) -> Result { + let task_fn = self.clone(); + let mut iter = inputs.iter(); + + let recv = iter.next().context("task is missing receiver")?; + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + let recv = Vc::::try_from_concrete(recv)?; + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let task_fn = task_fn.clone(); + let recv = recv.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(macro_helpers::tracing::Instrument::instrument(async move { + let recv = recv.await?; + let recv = <::Read as VcRead>::target_to_value_ref(&*recv); + let result = >::Output::try_into_raw_vc((task_fn)(recv, $($arg),*).await); + macro_helpers::notify_scheduled_tasks(); + result + }, macro_helpers::tracing::trace_span!("{}", name))) + })) + } + } + }; +} + +task_fn_impl! { AsyncFn0, } +task_fn_impl! { AsyncFn1, A1 } +task_fn_impl! { AsyncFn2, A1 A2 } +task_fn_impl! { AsyncFn3, A1 A2 A3 } +task_fn_impl! { AsyncFn4, A1 A2 A3 A4 } +task_fn_impl! { AsyncFn5, A1 A2 A3 A4 A5 } +task_fn_impl! { AsyncFn6, A1 A2 A3 A4 A5 A6 } +task_fn_impl! { AsyncFn7, A1 A2 A3 A4 A5 A6 A7 } +task_fn_impl! { AsyncFn8, A1 A2 A3 A4 A5 A6 A7 A8 } +task_fn_impl! { AsyncFn9, A1 A2 A3 A4 A5 A6 A7 A8 A9 } +task_fn_impl! { AsyncFn10, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 } +task_fn_impl! { AsyncFn11, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 } +task_fn_impl! { AsyncFn12, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 } +task_fn_impl! { AsyncFn13, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 } +task_fn_impl! { AsyncFn14, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 } +task_fn_impl! { AsyncFn15, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 } +task_fn_impl! { AsyncFn16, A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 } + +// There needs to be one more implementation than task_fn_impl to account for +// the receiver. +task_inputs_impl! {} +task_inputs_impl! { A1 } +task_inputs_impl! { A1 A2 } +task_inputs_impl! { A1 A2 A3 } +task_inputs_impl! { A1 A2 A3 A4 } +task_inputs_impl! { A1 A2 A3 A4 A5 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 } +task_inputs_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 A17 } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{VcCellNewMode, VcDefaultRead}; + + #[test] + fn test_task_fn() { + fn no_args() -> crate::Vc { + todo!() + } + + fn one_arg(_a: i32) -> crate::Vc { + todo!() + } + + async fn async_one_arg(_a: i32) -> crate::Vc { + todo!() + } + + fn with_recv(_a: &i32) -> crate::Vc { + todo!() + } + + async fn async_with_recv(_a: &i32) -> crate::Vc { + todo!() + } + + fn with_recv_and_str(_a: &i32, _s: String) -> crate::Vc { + todo!() + } + + async fn async_with_recv_and_str(_a: &i32, _s: String) -> crate::Vc { + todo!() + } + + async fn async_with_recv_and_str_and_result( + _a: &i32, + _s: String, + ) -> Result> { + todo!() + } + + async fn async_with_recv_and_str_and_lf(_a: &i32, _s: &str) -> crate::Vc { + todo!() + } + + fn accepts_task_fn(_task_fn: F) + where + F: TaskFn, + { + } + + struct Thing; + impl Thing { + async fn dbg(&self) {} + } + + unsafe impl VcValueType for Thing { + type Read = VcDefaultRead; + + type CellMode = VcCellNewMode; + + fn get_value_type_id() -> crate::ValueTypeId { + todo!() + } + } + + trait AsyncWhat { + async fn what(&self); + } + + impl AsyncWhat for Thing { + async fn what(&self) { + todo!() + } + } + + // #[async_trait::async_trait] + // trait What { + // async fn what(&self); + // } + + // #[async_trait::async_trait] + // impl What for Thing { + // async fn what(&self) { + // todo!() + // } + // } + + let _task_fn = no_args.into_task_fn(); + accepts_task_fn(no_args.into_task_fn()); + let _task_fn = one_arg.into_task_fn(); + accepts_task_fn(one_arg.into_task_fn()); + let _task_fn = async_one_arg.into_task_fn(); + accepts_task_fn(async_one_arg.into_task_fn()); + let task_fn = with_recv.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = async_with_recv.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = with_recv_and_str.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = async_with_recv_and_str.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = async_with_recv_and_str_and_result.into_task_fn(); + accepts_task_fn(task_fn); + let task_fn = ::what.into_task_fn(); + accepts_task_fn(task_fn); + // let task_fn = ::what.into_task_fn(); + // accepts_task_fn(task_fn); + let task_fn = Thing::dbg.into_task_fn(); + accepts_task_fn(task_fn); + // let task_fn = async_with_recv_and_str_and_lf.into_task_fn(); + // accepts_task_fn(task_fn); + } +} diff --git a/crates/turbo-tasks/src/task/function3.rs b/crates/turbo-tasks/src/task/function3.rs new file mode 100644 index 00000000000000..fbf5b754fe4a9e --- /dev/null +++ b/crates/turbo-tasks/src/task/function3.rs @@ -0,0 +1,249 @@ +use std::{future::Future, marker::PhantomData, pin::Pin}; + +use anyhow::{bail, Context, Result}; + +use super::{ConcreteTaskInput, TaskInput, TaskOutput}; +use crate::{RawVc, Vc, VcRead, VcValueType}; + +pub type NativeTaskFuture = Pin> + Send>>; +pub type NativeTaskFn = Box NativeTaskFuture + Send + Sync>; + +pub trait TaskFn: Send + Sync + 'static { + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result; +} + +pub struct AsFunction(pub F); + +pub struct AsAsyncFunction(pub F); +pub struct AsMethod(pub F); +pub struct AsAsyncMethod(pub F); + +macro_rules! task_fn_impl { + ( $( $arg:ident )* ) => { + impl<$($arg,)* Output> TaskFn for AsFunction Output> + where + $($arg: TaskInput + 'static,)* + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let this = self.0; + + let mut iter = inputs.iter(); + + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + Output::try_into_raw_vc((this)($($arg),*)) + }) + })) + } + } + + impl<$($arg,)* FutureOutput, Output> TaskFn for AsAsyncFunction FutureOutput> + where + $($arg: TaskInput + 'static,)* + FutureOutput: Future + Send + 'static, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let this = self.0; + + let mut iter = inputs.iter(); + + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + Output::try_into_raw_vc((this)($($arg),*).await) + }) + })) + } + } + + impl TaskFn for AsMethod Output> + where + Recv: VcValueType, + Vc: TaskInput + 'static, + $($arg: TaskInput + 'static,)* + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let this = self.0; + + let mut iter = inputs.iter(); + + let recv = iter.next().context("task is missing receiver")?; + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + let recv = Vc::::try_from_concrete(recv)?; + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let recv = recv.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(async move { + let recv = recv.await?; + let recv = <::Read as VcRead>::target_to_value_ref(&*recv); + Output::try_into_raw_vc((this)(recv, $($arg),*)) + }) + })) + } + } + + impl TaskFn for AsAsyncMethod FutureOutput> + where + Recv: VcValueType, + Vc: TaskInput + 'static, + <::Read as VcRead>::Target: Send + Sync, + $($arg: TaskInput + 'static,)* + FutureOutput: Future + Send + 'static, + Output: TaskOutput + 'static, + { + #[allow(non_snake_case)] + fn functor(&self, inputs: &[ConcreteTaskInput]) -> Result { + let this = self.0; + + let mut iter = inputs.iter(); + + let recv = iter.next().context("task is missing receiver")?; + $( + let $arg = iter.next().context(format!("task is missing argument {}", stringify!($arg)))?; + )* + + if iter.next().is_some() { + bail!("task was called with too many arguments"); + } + + let recv = Vc::::try_from_concrete(recv)?; + $( + let $arg = $arg::try_from_concrete($arg)?; + )* + + Ok(Box::new(move || { + let recv = recv.clone(); + $( + let $arg = $arg.clone(); + )* + + Box::pin(turbo_tasks::macro_helpers::tracing::Instrument::instrument(async move { + let recv = recv.await?; + let recv = <::Read as VcRead>::target_to_value_ref(&*recv); + Output::try_into_raw_vc((this)(recv, $($arg),*).await) + }, turbo_tasks::macro_helpers::tracing::trace_span!(#name_code))) + })) + } + } + }; +} + +task_fn_impl! {} +task_fn_impl! { A1 } +task_fn_impl! { A1 A2 } +task_fn_impl! { A1 A2 A3 } +task_fn_impl! { A1 A2 A3 A4 } +task_fn_impl! { A1 A2 A3 A4 A5 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 } +task_fn_impl! { A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15 A16 } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_task_fn() { + fn no_args() -> crate::Vc { + todo!() + } + + fn one_arg(_a: i32) -> crate::Vc { + todo!() + } + + fn with_recv(_a: &i32) -> crate::Vc { + todo!() + } + + fn with_recv_and_str(_a: &i32, s: String) -> crate::Vc { + todo!() + } + + async fn async_with_recv_and_str(_a: &i32, s: String) -> crate::Vc { + todo!() + } + + // fn accepts_task_fn(_task_fn: F) + // where + // F: TaskFn, + // { + // } + + // accepts_task_fn(AsFunction(no_args as fn() -> _)); + // accepts_task_fn(AsFunction(one_arg as fn(_) -> _)); + // accepts_task_fn(AsMethod(with_recv as fn(&'_ _) -> _)); + // accepts_task_fn(AsMethod(with_recv_and_str as fn(_, _) -> _)); + + fn accepts_task_fn(_task_fn: F) + where + F: TaskFn, + { + } + + accepts_task_fn(AsFunction(no_args as fn() -> _)); + accepts_task_fn(AsFunction(one_arg as fn(_) -> _)); + accepts_task_fn(AsMethod(with_recv as fn(_) -> _)); + accepts_task_fn(AsMethod(with_recv_and_str as fn(_, _) -> _)); + accepts_task_fn(AsAsyncMethod(async_with_recv_and_str as fn(_, _) -> _)); + } +} diff --git a/crates/turbo-tasks/src/task/mod.rs b/crates/turbo-tasks/src/task/mod.rs new file mode 100644 index 00000000000000..067a16429d9a0d --- /dev/null +++ b/crates/turbo-tasks/src/task/mod.rs @@ -0,0 +1,11 @@ +pub(crate) mod concrete_task_input; +pub(crate) mod function; +pub(crate) mod task_input; +pub(crate) mod task_output; + +pub use concrete_task_input::ConcreteTaskInput; +pub use function::{ + AsyncFunctionMode, AsyncMethodMode, FunctionMode, IntoTaskFn, MethodMode, NativeTaskFn, TaskFn, +}; +pub use task_input::TaskInput; +pub use task_output::TaskOutput; diff --git a/crates/turbo-tasks/src/task/task_input.rs b/crates/turbo-tasks/src/task/task_input.rs new file mode 100644 index 00000000000000..8dce9bb4abf401 --- /dev/null +++ b/crates/turbo-tasks/src/task/task_input.rs @@ -0,0 +1,481 @@ +use std::{ + any::{type_name, Any}, + marker::PhantomData, + sync::Arc, +}; + +use anyhow::{anyhow, bail, Result}; + +use super::concrete_task_input::TransientSharedValue; +use crate::{ + magic_any::MagicAny, ConcreteTaskInput, RawVc, SharedValue, TransientInstance, TransientValue, + TypedForInput, Value, Vc, VcValueType, +}; + +pub trait TaskInput: Send + Sync + Clone { + fn try_from_concrete(input: &ConcreteTaskInput) -> Result; + fn into_concrete(self) -> ConcreteTaskInput; +} + +impl TaskInput for String { + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::String(s) => Ok(s.clone()), + _ => bail!("invalid task input type, expected String"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::String(self) + } +} + +impl TaskInput for bool { + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::Bool(b) => Ok(*b), + _ => bail!("invalid task input type, expected Bool"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::Bool(self) + } +} + +impl TaskInput for Vec +where + T: TaskInput, +{ + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::List(list) => Ok(list + .iter() + .map(|i| ::try_from_concrete(i)) + .collect::, _>>()?), + _ => bail!("invalid task input type, expected List"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::List( + self.into_iter() + .map(|i| ::into_concrete(i)) + .collect::>(), + ) + } +} + +impl TaskInput for u8 { + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U8(value) => Ok(*value), + _ => bail!("invalid task input type, expected U8"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::U8(self) + } +} + +impl TaskInput for u16 { + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U16(value) => Ok(*value), + _ => bail!("invalid task input type, expected U16"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::U16(self) + } +} + +impl TaskInput for u32 { + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U32(value) => Ok(*value), + _ => bail!("invalid task input type, expected U32"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::U32(self) + } +} + +impl TaskInput for i32 { + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::I32(value) => Ok(*value), + _ => bail!("invalid task input type, expected I32"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::I32(self) + } +} + +impl TaskInput for u64 { + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::U64(value) => Ok(*value), + _ => bail!("invalid task input type, expected U64"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::U64(self) + } +} + +impl TaskInput for usize { + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::Usize(value) => Ok(*value), + _ => bail!("invalid task input type, expected Usize"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::Usize(self) + } +} + +impl TaskInput for Option +where + T: TaskInput, +{ + fn try_from_concrete(value: &ConcreteTaskInput) -> Result { + match value { + ConcreteTaskInput::Nothing => Ok(None), + _ => Ok(Some(::try_from_concrete(value)?)), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + match self { + None => ConcreteTaskInput::Nothing, + Some(value) => ::into_concrete(value), + } + } +} + +impl TaskInput for Vc { + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::TaskCell(task, index) => Ok(Vc { + node: RawVc::TaskCell(*task, *index), + _t: PhantomData, + }), + ConcreteTaskInput::TaskOutput(task) => Ok(Vc { + node: RawVc::TaskOutput(*task), + _t: PhantomData, + }), + _ => bail!("invalid task input type, expected RawVc"), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + match self.node { + RawVc::TaskCell(task, index) => ConcreteTaskInput::TaskCell(task, index), + RawVc::TaskOutput(task) => ConcreteTaskInput::TaskOutput(task), + } + } +} + +impl TaskInput for Value +where + T: Any + + std::fmt::Debug + + Clone + + std::hash::Hash + + Eq + + Ord + + Send + + Sync + + VcValueType + + TypedForInput + + 'static, +{ + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::SharedValue(value) => { + let v = value.1.downcast_ref::().ok_or_else(|| { + anyhow!( + "invalid task input type, expected {} got {:?}", + type_name::(), + value.1, + ) + })?; + Ok(Value::new(v.clone())) + } + _ => bail!("invalid task input type, expected {}", type_name::()), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + let raw_value: T = self.into_value(); + ConcreteTaskInput::SharedValue(SharedValue( + Some(T::get_value_type_id()), + Arc::new(raw_value), + )) + } +} + +impl TaskInput for TransientValue +where + T: MagicAny + Clone + 'static, +{ + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::TransientSharedValue(value) => { + let v = value.0.downcast_ref::().ok_or_else(|| { + anyhow!( + "invalid task input type, expected {} got {:?}", + type_name::(), + value.0, + ) + })?; + Ok(TransientValue::new(v.clone())) + } + _ => bail!("invalid task input type, expected {}", type_name::()), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + let raw_value: T = self.into_value(); + ConcreteTaskInput::TransientSharedValue(TransientSharedValue(Arc::new(raw_value))) + } +} + +impl TaskInput for TransientInstance +where + T: Send + Sync + 'static, +{ + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::SharedReference(reference) => { + if let Ok(i) = reference.clone().try_into() { + Ok(i) + } else { + bail!( + "invalid task input type, expected {} got {:?}", + type_name::(), + reference.0, + ) + } + } + _ => bail!("invalid task input type, expected {}", type_name::()), + } + } + + fn into_concrete(self) -> ConcreteTaskInput { + ConcreteTaskInput::SharedReference(self.into()) + } +} + +macro_rules! tuple_impls { + ( $( $name:ident )+ ) => { + impl<$($name: TaskInput),+> TaskInput for ($($name,)+) + { + #[allow(non_snake_case)] + fn try_from_concrete(input: &ConcreteTaskInput) -> Result { + match input { + ConcreteTaskInput::List(value) => { + let mut iter = value.iter(); + $( + let $name = iter.next().ok_or_else(|| anyhow!("missing tuple element"))?; + let $name = TaskInput::try_from_concrete($name)?; + )+ + Ok(($($name,)+)) + } + _ => bail!("invalid task input type, expected list"), + } + } + + #[allow(non_snake_case)] + fn into_concrete(self) -> ConcreteTaskInput { + let ($($name,)+) = self; + let ($($name,)+) = ($($name.into_concrete(),)+); + ConcreteTaskInput::List(vec![ $($name,)+ ]) + } + } + }; +} + +tuple_impls! { A } +tuple_impls! { A B } +tuple_impls! { A B C } +tuple_impls! { A B C D } +tuple_impls! { A B C D E } +tuple_impls! { A B C D E F } +tuple_impls! { A B C D E F G } +tuple_impls! { A B C D E F G H } +tuple_impls! { A B C D E F G H I } +tuple_impls! { A B C D E F G H I J } +tuple_impls! { A B C D E F G H I J K } +tuple_impls! { A B C D E F G H I J K L } + +#[cfg(test)] +mod tests { + use anyhow::Result; + use turbo_tasks_macros::TaskInput; + + use super::*; + // This is necessary for the derive macro to work, as its expansion refers to + // the crate name directly. + use crate as turbo_tasks; + + fn conversion(t: T) -> Result + where + T: TaskInput, + { + TaskInput::try_from_concrete(&TaskInput::into_concrete(t)) + } + + macro_rules! test_conversion { + ($input:expr) => { + assert_eq!(conversion($input)?, $input); + }; + } + + #[test] + fn test_no_fields() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct NoFields; + + test_conversion!(NoFields); + Ok(()) + } + + #[test] + fn test_one_unnamed_field() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct OneUnnamedField(u32); + + test_conversion!(OneUnnamedField(42)); + Ok(()) + } + + #[test] + fn test_multiple_unnamed_fields() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct MultipleUnnamedFields(u32, String); + + test_conversion!(MultipleUnnamedFields(42, "42".into())); + Ok(()) + } + + #[test] + fn test_one_named_field() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct OneNamedField { + named: u32, + } + + test_conversion!(OneNamedField { named: 42 }); + Ok(()) + } + + #[test] + fn test_multiple_named_fields() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct MultipleNamedFields { + named: u32, + other: String, + } + + test_conversion!(MultipleNamedFields { + named: 42, + other: "42".into() + }); + Ok(()) + } + + #[test] + fn test_generic_field() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + struct GenericField(T); + + test_conversion!(GenericField(42)); + test_conversion!(GenericField("42".to_string())); + Ok(()) + } + + #[test] + fn test_no_variant() -> Result<()> { + // This can't actually be tested at runtime because such an enum can't be + // constructed. However, the macro expansion is tested. + #[derive(Clone, TaskInput)] + enum NoVariants {} + Ok(()) + } + + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + enum OneVariant { + Variant, + } + + #[test] + fn test_one_variant() -> Result<()> { + test_conversion!(OneVariant::Variant); + Ok(()) + } + + #[test] + fn test_multiple_variants() -> Result<()> { + #[derive(Clone, TaskInput, PartialEq, Eq, Debug)] + enum MultipleVariants { + Variant1, + Variant2, + } + + test_conversion!(MultipleVariants::Variant2); + Ok(()) + } + + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + enum MultipleVariantsAndHeterogeneousFields { + Variant1, + Variant2(u32), + Variant3 { named: u32 }, + Variant4(u32, String), + Variant5 { named: u32, other: String }, + } + + #[test] + fn test_multiple_variants_and_heterogeneous_fields() -> Result<()> { + test_conversion!(MultipleVariantsAndHeterogeneousFields::Variant5 { + named: 42, + other: "42".into() + }); + Ok(()) + } + + #[test] + fn test_nested_variants() -> Result<()> { + #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] + enum NestedVariants { + Variant1, + Variant2(MultipleVariantsAndHeterogeneousFields), + Variant3 { named: OneVariant }, + Variant4(OneVariant, String), + Variant5 { named: OneVariant, other: String }, + } + + test_conversion!(NestedVariants::Variant5 { + named: OneVariant::Variant, + other: "42".into() + }); + test_conversion!(NestedVariants::Variant2( + MultipleVariantsAndHeterogeneousFields::Variant5 { + named: 42, + other: "42".into() + } + )); + Ok(()) + } +} diff --git a/crates/turbo-tasks/src/task/task_output.rs b/crates/turbo-tasks/src/task/task_output.rs new file mode 100644 index 00000000000000..3f452cdfa590b1 --- /dev/null +++ b/crates/turbo-tasks/src/task/task_output.rs @@ -0,0 +1,55 @@ +use std::marker::PhantomData; + +use anyhow::Result; + +use crate::{unit, RawVc, Vc}; + +pub trait TaskOutput { + type Return; + + fn try_from_raw_vc(raw_vc: RawVc) -> Self::Return; + fn try_into_raw_vc(self) -> Result; +} + +impl TaskOutput for Vc +where + T: ?Sized, +{ + type Return = Vc; + + fn try_from_raw_vc(raw_vc: RawVc) -> Self::Return { + Vc { + node: raw_vc, + _t: PhantomData, + } + } + + fn try_into_raw_vc(self) -> Result { + Ok(self.node) + } +} + +impl TaskOutput for () { + type Return = (); + + fn try_from_raw_vc(_raw_vc: RawVc) -> Self::Return {} + + fn try_into_raw_vc(self) -> Result { + Ok(unit().node) + } +} + +impl TaskOutput for Result +where + T: TaskOutput, +{ + type Return = T::Return; + + fn try_from_raw_vc(raw_vc: RawVc) -> Self::Return { + T::try_from_raw_vc(raw_vc) + } + + fn try_into_raw_vc(self) -> Result { + self?.try_into_raw_vc() + } +} diff --git a/crates/turbo-tasks/src/task_input.rs b/crates/turbo-tasks/src/task_input.rs deleted file mode 100644 index 8f28c87516822d..00000000000000 --- a/crates/turbo-tasks/src/task_input.rs +++ /dev/null @@ -1,1108 +0,0 @@ -use std::{ - any::{type_name, Any}, - borrow::Cow, - fmt::{Debug, Display}, - future::Future, - hash::Hash, - pin::Pin, - sync::Arc, -}; - -use anyhow::{anyhow, Result}; -use serde::{ser::SerializeTuple, Deserialize, Serialize}; - -use crate::{ - backend::CellContent, - id::{FunctionId, TraitTypeId}, - magic_any::MagicAny, - manager::{read_task_cell, read_task_output}, - registry, turbo_tasks, - value::{TransientInstance, TransientValue, Value}, - value_type::TypedForInput, - CellId, RawVc, TaskId, TraitType, Typed, ValueTypeId, -}; - -#[derive(Clone)] -pub struct SharedReference(pub Option, pub Arc); - -impl SharedReference { - pub fn downcast(self) -> Option> { - match Arc::downcast(self.1) { - Ok(data) => Some(data), - Err(_) => None, - } - } -} - -impl Hash for SharedReference { - fn hash(&self, state: &mut H) { - Hash::hash(&(&*self.1 as *const (dyn Any + Send + Sync)), state) - } -} -impl PartialEq for SharedReference { - fn eq(&self, other: &Self) -> bool { - PartialEq::eq( - &(&*self.1 as *const (dyn Any + Send + Sync)), - &(&*other.1 as *const (dyn Any + Send + Sync)), - ) - } -} -impl Eq for SharedReference {} -impl PartialOrd for SharedReference { - fn partial_cmp(&self, other: &Self) -> Option { - PartialOrd::partial_cmp( - &(&*self.1 as *const (dyn Any + Send + Sync)), - &(&*other.1 as *const (dyn Any + Send + Sync)), - ) - } -} -impl Ord for SharedReference { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - Ord::cmp( - &(&*self.1 as *const (dyn Any + Send + Sync)), - &(&*other.1 as *const (dyn Any + Send + Sync)), - ) - } -} -impl Debug for SharedReference { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("SharedReference") - .field(&self.0) - .field(&self.1) - .finish() - } -} - -impl Serialize for SharedReference { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - if let SharedReference(Some(ty), arc) = self { - let value_type = registry::get_value_type(*ty); - if let Some(serializable) = value_type.any_as_serializable(arc) { - let mut t = serializer.serialize_tuple(2)?; - t.serialize_element(registry::get_value_type_global_name(*ty))?; - t.serialize_element(serializable)?; - t.end() - } else { - Err(serde::ser::Error::custom(format!( - "{:?} is not serializable", - arc - ))) - } - } else { - Err(serde::ser::Error::custom( - "untyped values are not serializable", - )) - } - } -} - -impl Display for SharedReference { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(ty) = self.0 { - write!(f, "value of type {}", registry::get_value_type(ty).name) - } else { - write!(f, "untyped value") - } - } -} - -impl<'de> Deserialize<'de> for SharedReference { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct Visitor; - - impl<'de> serde::de::Visitor<'de> for Visitor { - type Value = SharedReference; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a serializable shared reference") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - if let Some(global_name) = seq.next_element()? { - if let Some(ty) = registry::get_value_type_id_by_global_name(global_name) { - if let Some(seed) = registry::get_value_type(ty).get_any_deserialize_seed() - { - if let Some(value) = seq.next_element_seed(seed)? { - Ok(SharedReference(Some(ty), value.into())) - } else { - Err(serde::de::Error::invalid_length( - 1, - &"tuple with type and value", - )) - } - } else { - Err(serde::de::Error::custom(format!( - "{ty} is not deserializable" - ))) - } - } else { - Err(serde::de::Error::unknown_variant(global_name, &[])) - } - } else { - Err(serde::de::Error::invalid_length( - 0, - &"tuple with type and value", - )) - } - } - } - - deserializer.deserialize_tuple(2, Visitor) - } -} - -#[derive(Debug, Clone, PartialOrd, Ord)] -pub struct TransientSharedValue(pub Arc); - -impl TransientSharedValue { - pub fn downcast(self) -> Option> { - match Arc::downcast(self.0.magic_any_arc()) { - Ok(data) => Some(data), - Err(_) => None, - } - } -} - -impl Hash for TransientSharedValue { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl PartialEq for TransientSharedValue { - #[allow(clippy::op_ref)] - fn eq(&self, other: &Self) -> bool { - &self.0 == &other.0 - } -} -impl Eq for TransientSharedValue {} -impl Serialize for TransientSharedValue { - fn serialize(&self, _serializer: S) -> Result - where - S: serde::Serializer, - { - Err(serde::ser::Error::custom( - "Transient values can't be serialized", - )) - } -} -impl<'de> Deserialize<'de> for TransientSharedValue { - fn deserialize(_deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - unreachable!("Transient values can't be serialized") - } -} - -#[derive(Debug, Clone, PartialOrd, Ord)] -pub struct SharedValue(pub Option, pub Arc); - -impl SharedValue { - pub fn downcast(self) -> Option> { - match Arc::downcast(self.1.magic_any_arc()) { - Ok(data) => Some(data), - Err(_) => None, - } - } -} - -impl PartialEq for SharedValue { - // this breaks without the ref - #[allow(clippy::op_ref)] - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 && &self.1 == &other.1 - } -} - -impl Eq for SharedValue {} - -impl Hash for SharedValue { - fn hash(&self, state: &mut H) { - self.0.hash(state); - self.1.hash(state); - } -} - -impl Display for SharedValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(ty) = self.0 { - write!(f, "value of type {}", registry::get_value_type(ty).name) - } else { - write!(f, "untyped value") - } - } -} - -impl Serialize for SharedValue { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - if let SharedValue(Some(ty), arc) = self { - let value_type = registry::get_value_type(*ty); - if let Some(serializable) = value_type.magic_as_serializable(arc) { - let mut t = serializer.serialize_tuple(2)?; - t.serialize_element(registry::get_value_type_global_name(*ty))?; - t.serialize_element(serializable)?; - t.end() - } else { - Err(serde::ser::Error::custom(format!( - "{:?} is not serializable", - arc - ))) - } - } else { - Err(serde::ser::Error::custom( - "untyped values are not serializable", - )) - } - } -} - -impl<'de> Deserialize<'de> for SharedValue { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - struct Visitor; - - impl<'de> serde::de::Visitor<'de> for Visitor { - type Value = SharedValue; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a serializable shared value") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - if let Some(global_name) = seq.next_element()? { - if let Some(ty) = registry::get_value_type_id_by_global_name(global_name) { - if let Some(seed) = - registry::get_value_type(ty).get_magic_deserialize_seed() - { - if let Some(value) = seq.next_element_seed(seed)? { - Ok(SharedValue(Some(ty), value.into())) - } else { - Err(serde::de::Error::invalid_length( - 1, - &"tuple with type and value", - )) - } - } else { - Err(serde::de::Error::custom(format!( - "{ty} is not deserializable" - ))) - } - } else { - Err(serde::de::Error::unknown_variant(global_name, &[])) - } - } else { - Err(serde::de::Error::invalid_length( - 0, - &"tuple with type and value", - )) - } - } - } - - deserializer.deserialize_tuple(2, Visitor) - } -} - -#[allow(clippy::derived_hash_with_manual_eq)] -#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum TaskInput { - TaskOutput(TaskId), - TaskCell(TaskId, CellId), - List(Vec), - String(String), - Bool(bool), - Usize(usize), - I8(i8), - U8(u8), - I16(i16), - U16(u16), - I32(i32), - U32(u32), - U64(u64), - Nothing, - SharedValue(SharedValue), - TransientSharedValue(TransientSharedValue), - SharedReference(SharedReference), -} - -impl TaskInput { - pub async fn resolve_to_value(self) -> Result { - let tt = turbo_tasks(); - let mut current = self; - loop { - current = match current { - TaskInput::TaskOutput(task_id) => { - read_task_output(&*tt, task_id, false).await?.into() - } - TaskInput::TaskCell(task_id, index) => { - read_task_cell(&*tt, task_id, index).await?.into() - } - _ => return Ok(current), - } - } - } - - pub async fn resolve(self) -> Result { - let tt = turbo_tasks(); - let mut current = self; - loop { - current = match current { - TaskInput::TaskOutput(task_id) => { - read_task_output(&*tt, task_id, false).await?.into() - } - TaskInput::List(list) => { - if list.iter().all(|i| i.is_resolved()) { - return Ok(TaskInput::List(list)); - } - fn resolve_all( - list: Vec, - ) -> Pin>> + Send>> - { - use crate::TryJoinIterExt; - Box::pin(list.into_iter().map(|i| i.resolve()).try_join()) - } - return Ok(TaskInput::List(resolve_all(list).await?)); - } - _ => return Ok(current), - } - } - } - - pub fn get_task_id(&self) -> Option { - match self { - TaskInput::TaskOutput(t) | TaskInput::TaskCell(t, _) => Some(*t), - _ => None, - } - } - - pub fn get_trait_method( - &self, - trait_type: TraitTypeId, - name: Cow<'static, str>, - ) -> Result> { - match self { - TaskInput::TaskOutput(_) | TaskInput::TaskCell(_, _) => { - panic!("get_trait_method must be called on a resolved TaskInput") - } - TaskInput::SharedValue(SharedValue(ty, _)) - | TaskInput::SharedReference(SharedReference(ty, _)) => { - if let Some(ty) = *ty { - let key = (trait_type, name); - if let Some(func) = registry::get_value_type(ty).get_trait_method(&key) { - Ok(*func) - } else if let Some(func) = registry::get_trait(trait_type) - .default_trait_methods - .get(&key.1) - { - Ok(*func) - } else { - Err(key.1) - } - } else { - Err(name) - } - } - _ => Err(name), - } - } - - pub fn has_trait(&self, trait_type: TraitTypeId) -> bool { - match self { - TaskInput::TaskOutput(_) | TaskInput::TaskCell(_, _) => { - panic!("has_trait() must be called on a resolved TaskInput") - } - TaskInput::SharedValue(SharedValue(ty, _)) - | TaskInput::SharedReference(SharedReference(ty, _)) => { - if let Some(ty) = *ty { - registry::get_value_type(ty).has_trait(&trait_type) - } else { - false - } - } - _ => false, - } - } - - pub fn traits(&self) -> Vec<&'static TraitType> { - match self { - TaskInput::TaskOutput(_) | TaskInput::TaskCell(_, _) => { - panic!("traits() must be called on a resolved TaskInput") - } - TaskInput::SharedValue(SharedValue(ty, _)) - | TaskInput::SharedReference(SharedReference(ty, _)) => { - if let Some(ty) = *ty { - registry::get_value_type(ty) - .traits_iter() - .map(registry::get_trait) - .collect() - } else { - Vec::new() - } - } - _ => Vec::new(), - } - } - - pub fn is_resolved(&self) -> bool { - match self { - TaskInput::TaskOutput(_) => false, - TaskInput::List(list) => list.iter().all(|i| i.is_resolved()), - _ => true, - } - } - - pub fn is_nothing(&self) -> bool { - matches!(self, TaskInput::Nothing) - } -} - -pub trait FromTaskInput<'a> -where - Self: Sized, -{ - type Error; - - fn try_from(value: &'a TaskInput) -> Result; -} - -impl From for TaskInput { - fn from(raw_vc: RawVc) -> Self { - match raw_vc { - RawVc::TaskOutput(task) => TaskInput::TaskOutput(task), - RawVc::TaskCell(task, i) => TaskInput::TaskCell(task, i), - } - } -} - -impl From for TaskInput { - fn from(content: CellContent) -> Self { - match content { - CellContent(None) => TaskInput::Nothing, - CellContent(Some(shared_ref)) => TaskInput::SharedReference(shared_ref), - } - } -} - -impl Display for TaskInput { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - TaskInput::TaskOutput(task) => write!(f, "task output {}", task), - TaskInput::TaskCell(task, index) => write!(f, "cell {} in {}", index, task), - TaskInput::List(list) => write!( - f, - "list {}", - list.iter() - .map(|i| i.to_string()) - .collect::>() - .join(", ") - ), - TaskInput::String(s) => write!(f, "string {:?}", s), - TaskInput::Bool(b) => write!(f, "bool {:?}", b), - TaskInput::Usize(v) => write!(f, "usize {}", v), - TaskInput::I8(v) => write!(f, "i8 {}", v), - TaskInput::U8(v) => write!(f, "u8 {}", v), - TaskInput::I16(v) => write!(f, "i16 {}", v), - TaskInput::U16(v) => write!(f, "u16 {}", v), - TaskInput::I32(v) => write!(f, "i32 {}", v), - TaskInput::U32(v) => write!(f, "u32 {}", v), - TaskInput::U64(v) => write!(f, "u64 {}", v), - TaskInput::Nothing => write!(f, "nothing"), - TaskInput::SharedValue(_) => write!(f, "any value"), - TaskInput::TransientSharedValue(_) => write!(f, "any transient value"), - TaskInput::SharedReference(data) => { - write!(f, "shared reference with {}", data) - } - } - } -} - -impl From for TaskInput { - fn from(s: String) -> Self { - TaskInput::String(s) - } -} - -impl From<&str> for TaskInput { - fn from(s: &str) -> Self { - TaskInput::String(s.to_string()) - } -} - -impl From for TaskInput { - fn from(b: bool) -> Self { - TaskInput::Bool(b) - } -} - -impl From for TaskInput { - fn from(v: i8) -> Self { - TaskInput::I8(v) - } -} - -impl From for TaskInput { - fn from(v: u8) -> Self { - TaskInput::U8(v) - } -} - -impl From for TaskInput { - fn from(v: i16) -> Self { - TaskInput::I16(v) - } -} - -impl From for TaskInput { - fn from(v: u16) -> Self { - TaskInput::U16(v) - } -} - -impl From for TaskInput { - fn from(v: i32) -> Self { - TaskInput::I32(v) - } -} - -impl From for TaskInput { - fn from(v: u32) -> Self { - TaskInput::U32(v) - } -} - -impl From for TaskInput { - fn from(v: u64) -> Self { - TaskInput::U64(v) - } -} - -impl From for TaskInput { - fn from(v: usize) -> Self { - TaskInput::Usize(v) - } -} - -impl From> for TaskInput -where - TaskInput: From, -{ - fn from(v: Option) -> Self { - match v { - None => TaskInput::Nothing, - Some(v) => { - let result = v.into(); - // Option> leads to problems with using Some(None) - debug_assert!(result != TaskInput::Nothing); - result - } - } - } -} - -impl - From> for TaskInput -where - T: Serialize, - for<'de2> T: Deserialize<'de2>, -{ - fn from(v: Value) -> Self { - let raw_value: T = v.into_value(); - TaskInput::SharedValue(SharedValue( - Some(T::get_value_type_id()), - Arc::new(raw_value), - )) - } -} - -impl From> for TaskInput { - fn from(v: TransientValue) -> Self { - let raw_value: T = v.into_value(); - TaskInput::TransientSharedValue(TransientSharedValue(Arc::new(raw_value))) - } -} - -impl From> for TaskInput { - fn from(v: TransientInstance) -> Self { - TaskInput::SharedReference(v.into()) - } -} - -impl> From> for TaskInput { - fn from(s: Vec) -> Self { - TaskInput::List(s.into_iter().map(|i| i.into()).collect()) - } -} - -impl FromTaskInput<'_> for RawVc { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::TaskCell(task, index) => Ok(RawVc::TaskCell(*task, *index)), - TaskInput::TaskOutput(task) => Ok(RawVc::TaskOutput(*task)), - _ => Err(anyhow!("invalid task input type, expected RawVc")), - } - } -} - -impl FromTaskInput<'_> for String { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::String(str) => Ok(str.to_string()), - _ => Err(anyhow!("invalid task input type, expected string")), - } - } -} - -impl<'a> FromTaskInput<'a> for &'a str { - type Error = anyhow::Error; - - fn try_from(value: &'a TaskInput) -> Result { - match value { - TaskInput::String(str) => Ok(str), - _ => Err(anyhow!("invalid task input type, expected string")), - } - } -} - -impl FromTaskInput<'_> for bool { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::Bool(b) => Ok(*b), - _ => Err(anyhow!("invalid task input type, expected bool")), - } - } -} - -impl<'a, T: FromTaskInput<'a, Error = anyhow::Error>> FromTaskInput<'a> for Vec { - type Error = anyhow::Error; - - fn try_from(value: &'a TaskInput) -> Result { - match value { - TaskInput::List(list) => Ok(list - .iter() - .map(|i| FromTaskInput::try_from(i)) - .collect::, _>>()?), - _ => Err(anyhow!("invalid task input type, expected list")), - } - } -} - -impl FromTaskInput<'_> for u8 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::U8(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected u8")), - } - } -} - -impl FromTaskInput<'_> for i8 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::I8(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected i8")), - } - } -} - -impl FromTaskInput<'_> for u16 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::U16(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected u16")), - } - } -} - -impl FromTaskInput<'_> for i16 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::I16(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected i16")), - } - } -} - -impl FromTaskInput<'_> for u32 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::U32(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected u32")), - } - } -} - -impl FromTaskInput<'_> for i32 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::I32(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected i32")), - } - } -} - -impl FromTaskInput<'_> for u64 { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::U64(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected u64")), - } - } -} - -impl FromTaskInput<'_> for usize { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::Usize(value) => Ok(*value), - _ => Err(anyhow!("invalid task input type, expected usize")), - } - } -} - -impl<'a, T> FromTaskInput<'a> for Option -where - T: FromTaskInput<'a>, -{ - type Error = T::Error; - - fn try_from(value: &'a TaskInput) -> Result { - match value { - TaskInput::Nothing => Ok(None), - _ => Ok(Some(FromTaskInput::try_from(value)?)), - } - } -} - -impl FromTaskInput<'_> - for Value -where - T: Serialize, - for<'de2> T: Deserialize<'de2>, -{ - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::SharedValue(value) => { - let v = value.1.downcast_ref::().ok_or_else(|| { - anyhow!( - "invalid task input type, expected {} got {:?}", - type_name::(), - value.1, - ) - })?; - Ok(Value::new(v.clone())) - } - _ => Err(anyhow!( - "invalid task input type, expected {}", - type_name::() - )), - } - } -} - -impl FromTaskInput<'_> for TransientValue { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::TransientSharedValue(value) => { - let v = value.0.downcast_ref::().ok_or_else(|| { - anyhow!( - "invalid task input type, expected {} got {:?}", - type_name::(), - value.0, - ) - })?; - Ok(TransientValue::new(v.clone())) - } - _ => Err(anyhow!( - "invalid task input type, expected {}", - type_name::() - )), - } - } -} - -impl FromTaskInput<'_> for TransientInstance { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::SharedReference(reference) => { - if let Ok(i) = reference.clone().try_into() { - Ok(i) - } else { - Err(anyhow!( - "invalid task input type, expected {} got {:?}", - type_name::(), - reference.0, - )) - } - } - _ => Err(anyhow!( - "invalid task input type, expected {}", - type_name::() - )), - } - } -} - -impl TryFrom<&TaskInput> for RawVc { - type Error = anyhow::Error; - - fn try_from(value: &TaskInput) -> Result { - match value { - TaskInput::TaskOutput(task) => Ok(RawVc::TaskOutput(*task)), - TaskInput::TaskCell(task, index) => Ok(RawVc::TaskCell(*task, *index)), - _ => Err(anyhow!("invalid task input type, expected cell ref")), - } - } -} - -macro_rules! tuple_impls { - ( $( $name:ident )+ ) => { - impl<$($name: Into),+> From<($($name,)+)> for TaskInput { - #[allow(non_snake_case)] - fn from(s: ($($name,)+)) -> Self { - let ($($name,)+) = s; - let ($($name,)+) = ($($name.into(),)+); - TaskInput::List(vec![ $($name,)+ ]) - } - } - - impl<'a, $($name: FromTaskInput<'a, Error = anyhow::Error>,)+> FromTaskInput<'a> for ($($name,)+) { - type Error = anyhow::Error; - - #[allow(non_snake_case)] - fn try_from(value: &'a TaskInput) -> Result { - match value { - TaskInput::List(value) => { - let mut iter = value.iter(); - $( - let $name = iter.next().ok_or_else(|| anyhow!("missing tuple element"))?; - let $name = FromTaskInput::try_from($name)?; - )+ - Ok(($($name,)+)) - }, - _ => Err(anyhow!("invalid task input type, expected list")), - } - } - } - }; - -} - -tuple_impls! { A } -tuple_impls! { A B } -tuple_impls! { A B C } -tuple_impls! { A B C D } -tuple_impls! { A B C D E } -tuple_impls! { A B C D E F } -tuple_impls! { A B C D E F G } -tuple_impls! { A B C D E F G H } -tuple_impls! { A B C D E F G H I } -tuple_impls! { A B C D E F G H I J } -tuple_impls! { A B C D E F G H I J K } -tuple_impls! { A B C D E F G H I J K L } - -#[cfg(test)] -mod tests { - use anyhow::Result; - use turbo_tasks_macros::TaskInput; - - use super::*; - // This is necessary for the derive macro to work, as its expansion refers to - // the crate name directly. - use crate as turbo_tasks; - - fn conversion(t: T) -> Result - where - T: for<'a> FromTaskInput<'a, Error = anyhow::Error>, - TaskInput: From, - { - FromTaskInput::try_from(&TaskInput::from(t)) - } - - macro_rules! test_conversion { - ($input:expr) => { - assert_eq!(conversion($input)?, $input); - }; - } - - #[test] - fn test_no_fields() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - struct NoFields; - - test_conversion!(NoFields); - Ok(()) - } - - #[test] - fn test_one_unnamed_field() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - struct OneUnnamedField(u32); - - test_conversion!(OneUnnamedField(42)); - Ok(()) - } - - #[test] - fn test_multiple_unnamed_fields() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - struct MultipleUnnamedFields(u32, String); - - test_conversion!(MultipleUnnamedFields(42, "42".into())); - Ok(()) - } - - #[test] - fn test_one_named_field() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - struct OneNamedField { - named: u32, - } - - test_conversion!(OneNamedField { named: 42 }); - Ok(()) - } - - #[test] - fn test_multiple_named_fields() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - struct MultipleNamedFields { - named: u32, - other: String, - } - - test_conversion!(MultipleNamedFields { - named: 42, - other: "42".into() - }); - Ok(()) - } - - #[test] - fn test_generic_field() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - struct GenericField(T); - - test_conversion!(GenericField(42)); - test_conversion!(GenericField("42".to_string())); - Ok(()) - } - - #[test] - fn test_no_variant() -> Result<()> { - // This can't actually be tested at runtime because such an enum can't be - // constructed. However, the macro expansion is tested. - #[derive(Clone, TaskInput)] - enum NoVariants {} - Ok(()) - } - - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - enum OneVariant { - Variant, - } - - #[test] - fn test_one_variant() -> Result<()> { - test_conversion!(OneVariant::Variant); - Ok(()) - } - - #[test] - fn test_multiple_variants() -> Result<()> { - #[derive(Clone, TaskInput, PartialEq, Eq, Debug)] - enum MultipleVariants { - Variant1, - Variant2, - } - - test_conversion!(MultipleVariants::Variant2); - Ok(()) - } - - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - enum MultipleVariantsAndHeterogeneousFields { - Variant1, - Variant2(u32), - Variant3 { named: u32 }, - Variant4(u32, String), - Variant5 { named: u32, other: String }, - } - - #[test] - fn test_multiple_variants_and_heterogeneous_fields() -> Result<()> { - test_conversion!(MultipleVariantsAndHeterogeneousFields::Variant5 { - named: 42, - other: "42".into() - }); - Ok(()) - } - - #[test] - fn test_nested_variants() -> Result<()> { - #[derive(Clone, TaskInput, Eq, PartialEq, Debug)] - enum NestedVariants { - Variant1, - Variant2(MultipleVariantsAndHeterogeneousFields), - Variant3 { named: OneVariant }, - Variant4(OneVariant, String), - Variant5 { named: OneVariant, other: String }, - } - - test_conversion!(NestedVariants::Variant5 { - named: OneVariant::Variant, - other: "42".into() - }); - test_conversion!(NestedVariants::Variant2( - MultipleVariantsAndHeterogeneousFields::Variant5 { - named: 42, - other: "42".into() - } - )); - Ok(()) - } -} diff --git a/crates/turbo-tasks/src/trait_ref.rs b/crates/turbo-tasks/src/trait_ref.rs index b39778d3485f3f..a6fd98f30673fa 100644 --- a/crates/turbo-tasks/src/trait_ref.rs +++ b/crates/turbo-tasks/src/trait_ref.rs @@ -1,25 +1,99 @@ -use std::{fmt::Debug, future::Future, marker::PhantomData, sync::Arc}; +use std::{fmt::Debug, future::Future, marker::PhantomData}; use anyhow::Result; use serde::{Deserialize, Serialize}; -use crate::{manager::find_cell_by_type, RawVc, SharedReference, ValueTraitVc}; +use crate::{ + manager::find_cell_by_type, + vc::{cast::VcCast, VcValueTraitCast}, + RawVc, ReadRawVcFuture, SharedReference, Vc, VcValueTrait, +}; /// Similar to a [`ReadRef`], but contains a value trait object instead. The /// only way to interact with a `TraitRef` is by passing it around or turning /// it back into a value trait vc by calling [`ReadRef::cell`]. /// /// Internally it stores a reference counted reference to a value on the heap. -#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct TraitRef where T: ?Sized, { shared_reference: SharedReference, - _t: PhantomData>, + _t: PhantomData, } -impl TraitRef { +impl Debug for TraitRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TraitRef") + .field("shared_reference", &self.shared_reference) + .finish() + } +} + +impl Clone for TraitRef { + fn clone(&self) -> Self { + Self { + shared_reference: self.shared_reference.clone(), + _t: PhantomData, + } + } +} + +impl PartialEq for TraitRef { + fn eq(&self, other: &Self) -> bool { + self.shared_reference == other.shared_reference + } +} + +impl Eq for TraitRef {} + +impl PartialOrd for TraitRef { + fn partial_cmp(&self, other: &Self) -> Option { + self.shared_reference.partial_cmp(&other.shared_reference) + } +} + +impl Ord for TraitRef { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.shared_reference.cmp(&other.shared_reference) + } +} + +impl std::hash::Hash for TraitRef { + fn hash(&self, state: &mut H) { + self.shared_reference.hash(state) + } +} + +impl Serialize for TraitRef { + fn serialize(&self, serializer: S) -> Result { + self.shared_reference.serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for TraitRef { + fn deserialize>(deserializer: D) -> Result { + Ok(Self { + shared_reference: SharedReference::deserialize(deserializer)?, + _t: PhantomData, + }) + } +} + +// Otherwise, TraitRef> would not be Sync. +// SAFETY: TraitRef doesn't actually contain a T. +unsafe impl Sync for TraitRef where T: ?Sized {} + +// Otherwise, TraitRef> would not be Send. +// SAFETY: TraitRef doesn't actually contain a T. +unsafe impl Send for TraitRef where T: ?Sized {} + +impl Unpin for TraitRef where T: ?Sized {} + +impl TraitRef +where + T: ?Sized, +{ pub(crate) fn new(shared_reference: SharedReference) -> Self { Self { shared_reference, @@ -30,11 +104,11 @@ impl TraitRef { impl TraitRef where - T: From, + T: VcValueTrait + ?Sized, { /// Returns a new cell that points to a value that implements the value /// trait `T`. - pub fn cell(trait_ref: TraitRef) -> T { + pub fn cell(trait_ref: TraitRef) -> Vc { // See Safety clause above. let SharedReference(ty, _) = trait_ref.shared_reference; let ty = ty.unwrap(); @@ -52,8 +126,21 @@ where /// refs. This behavior is rarely needed, so in most cases, `.await`ing a trait /// vc is a mistake. pub trait IntoTraitRef { - type TraitVc: ValueTraitVc; - type Future: Future>>; + type ValueTrait: VcValueTrait + ?Sized; + type Future: Future as VcCast>::Output>>; fn into_trait_ref(self) -> Self::Future; } + +impl IntoTraitRef for Vc +where + T: VcValueTrait + ?Sized, +{ + type ValueTrait = T; + + type Future = ReadRawVcFuture>; + + fn into_trait_ref(self) -> Self::Future { + self.node.into_trait_read::() + } +} diff --git a/crates/turbo-tasks/src/unit.rs b/crates/turbo-tasks/src/unit.rs new file mode 100644 index 00000000000000..6b1c81042f9ea2 --- /dev/null +++ b/crates/turbo-tasks/src/unit.rs @@ -0,0 +1,5 @@ +use crate::Vc; + +pub fn unit() -> Vc<()> { + Vc::cell(()) +} diff --git a/crates/turbo-tasks/src/util.rs b/crates/turbo-tasks/src/util.rs index 7df77c74a0ff3b..bd5bdf218bc9d4 100644 --- a/crates/turbo-tasks/src/util.rs +++ b/crates/turbo-tasks/src/util.rs @@ -25,8 +25,11 @@ pub struct SharedError { impl SharedError { pub fn new(err: Error) -> Self { - Self { - inner: Arc::new(err), + match err.downcast::() { + Ok(shared) => shared, + Err(plain) => Self { + inner: Arc::new(plain), + }, } } } @@ -37,7 +40,7 @@ impl StdError for SharedError { } fn provide<'a>(&'a self, req: &mut std::any::Demand<'a>) { - Provider::provide(&*self.inner, req); + self.inner.provide(req); } } @@ -235,7 +238,7 @@ pin_project! { } impl Fn(Pin<&mut F>, &mut Context<'a>) -> Poll> WrapFuture { - pub fn new(wrapper: W, future: F) -> Self { + pub fn new(future: F, wrapper: W) -> Self { Self { wrapper, future } } } diff --git a/crates/turbo-tasks/src/value.rs b/crates/turbo-tasks/src/value.rs index 1704598d592523..6f4a492b64ed95 100644 --- a/crates/turbo-tasks/src/value.rs +++ b/crates/turbo-tasks/src/value.rs @@ -1,16 +1,16 @@ use std::{fmt::Debug, marker::PhantomData, ops::Deref, sync::Arc}; -use crate::{SharedReference, Typed}; +use crate::SharedReference; /// Pass a value by value (`Value`) instead of by reference (`XxxVc`). /// /// Persistent, requires serialization. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] -pub struct Value { +pub struct Value { inner: T, } -impl Value { +impl Value { pub fn new(value: T) -> Self { Self { inner: value } } @@ -20,13 +20,7 @@ impl Value { } } -impl From for Value { - fn from(value: T) -> Self { - Value::new(value) - } -} - -impl Deref for Value { +impl Deref for Value { type Target = T; fn deref(&self) -> &Self::Target { @@ -34,9 +28,9 @@ impl Deref for Value { } } -impl Copy for Value {} +impl Copy for Value {} -impl Default for Value { +impl Default for Value { fn default() -> Self { Value::new(Default::default()) } diff --git a/crates/turbo-tasks/src/value_type.rs b/crates/turbo-tasks/src/value_type.rs index 84e961e1dd3e0b..2cd1382c617efe 100644 --- a/crates/turbo-tasks/src/value_type.rs +++ b/crates/turbo-tasks/src/value_type.rs @@ -7,94 +7,14 @@ use std::{ }; use auto_hash_map::{AutoMap, AutoSet}; -use nohash_hasher::BuildNoHashHasher; use serde::{Deserialize, Serialize}; use crate::{ id::{FunctionId, TraitTypeId}, magic_any::{AnyDeserializeSeed, MagicAny, MagicAnyDeserializeSeed}, registry::{register_trait_type, register_value_type}, - CollectiblesSource, RawVc, ValueTypeId, }; -pub trait Typed { - type Vc: From; - - fn get_value_type_id() -> ValueTypeId; -} - -pub trait ValueVc: - From - + Into - + CollectiblesSource - + Hash - + PartialEq - + Eq - + PartialOrd - + Ord - + Copy - + Clone -{ - fn get_value_type_id() -> ValueTypeId; - fn get_trait_type_ids() -> Box>; -} - -pub trait ValueTraitVc: - From - + Into - + CollectiblesSource - + Hash - + PartialEq - + Eq - + PartialOrd - + Ord - + Copy - + Clone -{ - fn get_trait_type_id() -> TraitTypeId; -} - -pub trait IntoSuperTrait: ValueTraitVc -where - T: ValueTraitVc, -{ - fn into_super_trait(self) -> T; -} - -pub trait FromSubTrait: ValueTraitVc -where - T: ValueTraitVc, -{ - fn from_sub_trait(t: T) -> Self; -} - -impl IntoSuperTrait for T -where - T: ValueTraitVc, - U: ValueTraitVc + FromSubTrait, -{ - fn into_super_trait(self) -> U { - U::from_sub_trait(self) - } -} - -impl FromSubTrait for T -where - T: ValueTraitVc, -{ - /// Returns the argument unchanged. - #[inline(always)] - fn from_sub_trait(t: T) -> T { - t - } -} - -/// Marker trait that a turbo_tasks::value is prepared for -/// serialization as Value<...> input. -/// Either use `#[turbo_tasks::value(serialization: auto_for_input)]` -/// or avoid Value<...> in favor of a real Vc -pub trait TypedForInput: Typed {} - type MagicSerializationFn = fn(&dyn MagicAny) -> &dyn erased_serde::Serialize; type AnySerializationFn = fn(&(dyn Any + Sync + Send)) -> &dyn erased_serde::Serialize; @@ -111,7 +31,7 @@ pub struct ValueType { /// A readable name of the type pub name: String, /// List of traits available - pub traits: AutoSet>, + pub traits: AutoSet, /// List of trait methods available pub trait_methods: AutoMap<(TraitTypeId, Cow<'static, str>), FunctionId>, @@ -173,7 +93,7 @@ impl ValueType { pub fn new() -> Self { Self { name: std::any::type_name::().to_string(), - traits: AutoSet::default(), + traits: AutoSet::new(), trait_methods: AutoMap::new(), magic_serialization: None, any_serialization: None, @@ -186,7 +106,7 @@ impl ValueType { >() -> Self { Self { name: std::any::type_name::().to_string(), - traits: AutoSet::default(), + traits: AutoSet::new(), trait_methods: AutoMap::new(), magic_serialization: Some(( ::as_serialize::, @@ -202,7 +122,7 @@ impl ValueType { >() -> Self { Self { name: std::any::type_name::().to_string(), - traits: AutoSet::default(), + traits: AutoSet::new(), trait_methods: AutoMap::new(), magic_serialization: None, any_serialization: Some((any_as_serialize::, AnyDeserializeSeed::new::())), diff --git a/crates/turbo-tasks/src/vc/cast.rs b/crates/turbo-tasks/src/vc/cast.rs new file mode 100644 index 00000000000000..7916089501fe4d --- /dev/null +++ b/crates/turbo-tasks/src/vc/cast.rs @@ -0,0 +1,52 @@ +use std::marker::PhantomData; + +use anyhow::Result; + +use crate::{backend::CellContent, ReadRef, TraitRef, VcValueTrait, VcValueType}; + +/// Trait defined to share behavior between values and traits within +/// [`ReadRawVcFuture`]. See [`ValueCast`] and [`TraitCast`]. +/// +/// This should not be implemented by users. +pub trait VcCast { + type Output; + + fn cast(content: CellContent) -> Result; +} + +/// Casts an arbitrary cell content into a [`ReadRef`]. +pub struct VcValueTypeCast { + _phantom: PhantomData, +} + +impl VcCast for VcValueTypeCast +where + T: VcValueType, +{ + type Output = ReadRef; + + fn cast(content: CellContent) -> Result { + content.cast::() + } +} + +/// Casts an arbitrary cell content into a [`TraitRef`]. +pub struct VcValueTraitCast +where + T: ?Sized, +{ + _phantom: PhantomData, +} + +impl VcCast for VcValueTraitCast +where + T: VcValueTrait + ?Sized, +{ + type Output = TraitRef; + + fn cast(content: CellContent) -> Result { + // Safety: Constructor ensures the cell content points to a value that + // implements T + content.cast_trait::() + } +} diff --git a/crates/turbo-tasks/src/vc/cell_mode.rs b/crates/turbo-tasks/src/vc/cell_mode.rs new file mode 100644 index 00000000000000..d3a81bdf4e216b --- /dev/null +++ b/crates/turbo-tasks/src/vc/cell_mode.rs @@ -0,0 +1,53 @@ +use std::marker::PhantomData; + +use super::{read::VcRead, traits::VcValueType, Vc}; +use crate::manager::find_cell_by_type; + +/// Trait that controls the behavior of `Vc::cell` on a value type basis. +/// +/// This trait must remain sealed within this crate. +pub trait VcCellMode +where + T: VcValueType, +{ + fn cell(value: >::Target) -> Vc; +} + +/// Mode that always updates the cell's content. +pub struct VcCellNewMode { + _phantom: PhantomData, +} + +impl VcCellMode for VcCellNewMode +where + T: VcValueType, +{ + fn cell(inner: >::Target) -> Vc { + let cell = find_cell_by_type(T::get_value_type_id()); + cell.update_shared(>::target_to_value(inner)); + Vc { + node: cell.into(), + _t: PhantomData, + } + } +} + +/// Mode that compares the cell's content with the new value and only updates +/// if the new value is different. +pub struct VcCellSharedMode { + _phantom: PhantomData, +} + +impl VcCellMode for VcCellSharedMode +where + T: VcValueType + PartialEq, +{ + fn cell(inner: >::Target) -> Vc { + let cell = find_cell_by_type(T::get_value_type_id()); + cell.compare_and_update_shared(>::target_to_value(inner)); + Vc { + node: cell.into(), + _t: PhantomData, + } + } +} diff --git a/crates/turbo-tasks/src/vc/default.rs b/crates/turbo-tasks/src/vc/default.rs new file mode 100644 index 00000000000000..9c3ae6dec94cd3 --- /dev/null +++ b/crates/turbo-tasks/src/vc/default.rs @@ -0,0 +1,7 @@ +use super::Vc; +use crate::{self as turbo_tasks}; + +#[turbo_tasks::value_trait] +pub trait ValueDefault { + fn value_default() -> Vc; +} diff --git a/crates/turbo-tasks/src/vc/mod.rs b/crates/turbo-tasks/src/vc/mod.rs new file mode 100644 index 00000000000000..f61ad49b6b06bc --- /dev/null +++ b/crates/turbo-tasks/src/vc/mod.rs @@ -0,0 +1,513 @@ +pub(crate) mod cast; +mod cell_mode; +pub(crate) mod default; +mod read; +mod traits; + +use std::{any::Any, marker::PhantomData, ops::Deref}; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; + +use self::cell_mode::VcCellMode; +pub use self::{ + cast::{VcValueTraitCast, VcValueTypeCast}, + cell_mode::{VcCellNewMode, VcCellSharedMode}, + default::ValueDefault, + read::{VcDefaultRead, VcRead, VcTransparentRead}, + traits::{Dynamic, TypedForInput, Upcast, VcValueTrait, VcValueType}, +}; +use crate::{ + debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString}, + trace::{TraceRawVcs, TraceRawVcsContext}, + CollectiblesFuture, CollectiblesSource, RawVc, ReadRawVcFuture, ResolveTypeError, +}; + +/// A Value Cell (`Vc` for short) is a reference to a memoized computation +/// result stored on the heap or in persistent cache, depending on the +/// Turbo Engine backend implementation. +/// +/// In order to get a reference to the pointed value, you need to `.await` the +/// [`Vc`] to get a [`ReadRef`]: +/// +/// ``` +/// let some_vc: Vc; +/// let some_ref: ReadRef = some_vc.await?; +/// some_ref.some_method_on_t(); +/// ``` +pub struct Vc +where + T: ?Sized, +{ + // TODO(alexkirsz) Should be private (or undocumented), but turbo-tasks-memory needs it to be + // accessible. + #[doc(hidden)] + pub node: RawVc, + pub(crate) _t: PhantomData, +} + +pub struct VcDeref +where + T: ?Sized, +{ + _t: PhantomData, +} + +trait Impossible {} + +macro_rules! do_not_use_or_you_will_be_fired { + ($($name:ident)*) => { + impl VcDeref + where + T: ?Sized, + { + $( + #[doc(hidden)] + #[allow(unused)] + #[allow(clippy::wrong_self_convention)] + #[deprecated = "This is not the method you are looking for."] + pub fn $name(self) {} + )* + } + }; +} + +// Hide raw pointer methods on `Vc`. This is an artifact of having +// implement `Deref` on `Vc` for `arbitrary_self_types` to +// do its thing. This can be removed once the `Receiver` trait no longer depends +// on `Deref`. +do_not_use_or_you_will_be_fired!( + add + addr + align_offset + as_mut + as_mut_ptr + as_ptr + as_ref + as_uninit_mut + as_uninit_ref + as_uninit_slice + as_uninit_slice_mut + byte_add + byte_offset + byte_offset_from + byte_sub + cast + cast_const + cast_mut + copy_from + copy_from_nonoverlapping + copy_to + copy_to_nonoverlapping + drop_in_place + expose_addr + from_bits + get_unchecked + get_unchecked_mut + guaranteed_eq + guaranteed_ne + is_aligned + is_aligned_to + is_empty + is_null + len + map_addr + mask + offset + offset_from + read + read_unaligned + read_volatile + replace + split_at_mut + split_at_mut_unchecked + sub + sub_ptr + swap + to_bits + to_raw_parts + with_addr + with_metadata_of + wrapping_add + wrapping_byte_add + wrapping_byte_offset + wrapping_byte_sub + wrapping_offset + wrapping_sub + write + write_bytes + write_unaligned + write_volatile +); + +// Call this macro for all the applicable methods above: + +#[doc(hidden)] +impl Deref for VcDeref +where + T: ?Sized, +{ + // `*const T` or `*mut T` would be enough here, but from an abundance of + // caution, we use `*const *mut *const T` to make sure there will never be an + // applicable method. + type Target = *const *mut *const T; + + fn deref(&self) -> &Self::Target { + extern "C" { + #[link_name = "\n\nERROR: you tried to dereference a `Vc`\n"] + fn trigger() -> !; + } + + unsafe { trigger() }; + } +} + +// This is the magic that makes `Vc` accept `self: Vc` methods through +// `arbitrary_self_types`, while not allowing any other receiver type: +// * `Vc` dereferences to `*const *mut *const T`, which means that it is +// valid under the `arbitrary_self_types` rules. +// * `*const *mut *const T` is not a valid receiver for any attribute access on +// `T`, which means that the only applicable items will be the methods +// declared on `self: Vc`. +// +// If we had used `type Target = T` instead, `vc_t.some_attr_defined_on_t` would +// have been accepted by the compiler. +#[doc(hidden)] +impl Deref for Vc +where + T: ?Sized, +{ + type Target = VcDeref; + + fn deref(&self) -> &Self::Target { + extern "C" { + #[link_name = "\n\nERROR: you tried to dereference a `Vc`\n"] + fn trigger() -> !; + } + + unsafe { trigger() }; + } +} + +impl Copy for Vc where T: ?Sized {} + +unsafe impl Send for Vc where T: ?Sized {} +unsafe impl Sync for Vc where T: ?Sized {} + +impl Clone for Vc +where + T: ?Sized, +{ + fn clone(&self) -> Self { + Self { + node: self.node, + _t: PhantomData, + } + } +} + +impl core::hash::Hash for Vc +where + T: ?Sized, +{ + fn hash(&self, state: &mut H) { + self.node.hash(state); + } +} + +impl PartialEq> for Vc +where + T: ?Sized, +{ + fn eq(&self, other: &Self) -> bool { + self.node == other.node + } +} + +impl Eq for Vc where T: ?Sized {} + +impl PartialOrd> for Vc +where + T: ?Sized, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.node.partial_cmp(&other.node) + } +} + +impl Ord for Vc +where + T: ?Sized, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.node.cmp(&other.node) + } +} + +impl Serialize for Vc +where + T: ?Sized, +{ + fn serialize(&self, serializer: S) -> Result { + self.node.serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for Vc +where + T: ?Sized, +{ + fn deserialize>(deserializer: D) -> Result { + Ok(Vc { + node: RawVc::deserialize(deserializer)?, + _t: PhantomData, + }) + } +} + +// TODO(alexkirsz) This should not be implemented for Vc. Instead, users should +// use the `ValueDebug` implementation to get a `D: Debug`. +impl std::fmt::Debug for Vc { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Vc").field("node", &self.node).finish() + } +} + +impl Vc +where + T: VcValueType, +{ + #[doc(hidden)] + pub fn cell_private(inner: >::Target) -> Self { + >::cell(inner) + } +} + +impl Vc +where + T: VcValueType>, + Inner: Any + Send + Sync, +{ + pub fn cell(inner: Inner) -> Self { + >::cell(inner) + } +} + +impl Vc +where + T: ?Sized, +{ + /// Upcasts the given `Vc` to a `Vc>`. + /// + /// This is also available as an `Into`/`From` conversion. + #[inline(always)] + pub fn upcast(vc: Self) -> Vc + where + T: Upcast, + K: VcValueTrait + ?Sized, + { + Vc { + node: vc.node, + _t: PhantomData, + } + } +} + +impl Vc +where + T: ?Sized, +{ + /// Resolve the reference until it points to a cell directly. + /// + /// Resolving will wait for task execution to be finished, so that the + /// returned `Vc` points to a cell that stores a value. + /// + /// Resolving is necessary to compare identities of `Vc`s. + /// + /// This is async and will rethrow any fatal error that happened during task + /// execution. + pub async fn resolve(self) -> Result { + Ok(Self { + node: self.node.resolve().await?, + _t: PhantomData, + }) + } + + /// Resolve the reference until it points to a cell directly in a strongly + /// consistent way. + /// + /// Resolving will wait for task execution to be finished, so that the + /// returned Vc points to a cell that stores a value. + /// + /// Resolving is necessary to compare identities of Vcs. + /// + /// This is async and will rethrow any fatal error that happened during task + /// execution. + pub async fn resolve_strongly_consistent(self) -> Result { + Ok(Self { + node: self.node.resolve_strongly_consistent().await?, + _t: PhantomData, + }) + } +} + +impl Vc +where + T: VcValueTrait + ?Sized, +{ + /// Attempts to sidecast the given `Vc>` to a `Vc>`. + /// This operation also resolves the `Vc`. + /// + /// Returns `None` if the underlying value type does not implement `K`. + /// + /// **Note:** if the trait T is required to implement K, use + /// `Vc::upcast(vc).resolve()` instead. This provides stronger guarantees, + /// removing the need for a `Result` return type. + pub async fn try_resolve_sidecast(vc: Self) -> Result>, ResolveTypeError> + where + K: VcValueTrait + ?Sized, + { + let raw_vc: RawVc = vc.node; + let raw_vc = raw_vc + .resolve_trait(::get_trait_type_id()) + .await?; + Ok(raw_vc.map(|raw_vc| Vc { + node: raw_vc, + _t: PhantomData, + })) + } + + /// Attempts to downcast the given `Vc>` to a `Vc`, where `K` + /// is of the form `Box`, and `L` is a value trait. + /// This operation also resolves the `Vc`. + /// + /// Returns `None` if the underlying value type is not a `K`. + pub async fn try_resolve_downcast(vc: Self) -> Result>, ResolveTypeError> + where + K: Upcast, + K: VcValueTrait + ?Sized, + { + let raw_vc: RawVc = vc.node; + let raw_vc = raw_vc + .resolve_trait(::get_trait_type_id()) + .await?; + Ok(raw_vc.map(|raw_vc| Vc { + node: raw_vc, + _t: PhantomData, + })) + } + + /// Attempts to downcast the given `Vc>` to a `Vc`, where `K` + /// is a value type. + /// This operation also resolves the `Vc`. + /// + /// Returns `None` if the underlying value type is not a `K`. + pub async fn try_resolve_downcast_type(vc: Self) -> Result>, ResolveTypeError> + where + K: Upcast, + K: VcValueType, + { + let raw_vc: RawVc = vc.node; + let raw_vc = raw_vc + .resolve_value(::get_value_type_id()) + .await?; + Ok(raw_vc.map(|raw_vc| Vc { + node: raw_vc, + _t: PhantomData, + })) + } +} + +impl CollectiblesSource for Vc +where + T: ?Sized, +{ + fn take_collectibles(self) -> CollectiblesFuture { + self.node.take_collectibles() + } + + fn peek_collectibles(self) -> CollectiblesFuture { + self.node.peek_collectibles() + } +} + +impl From for Vc +where + T: ?Sized, +{ + fn from(node: RawVc) -> Self { + Self { + node, + _t: PhantomData, + } + } +} + +impl TraceRawVcs for Vc +where + T: ?Sized, +{ + fn trace_raw_vcs(&self, context: &mut TraceRawVcsContext) { + TraceRawVcs::trace_raw_vcs(&self.node, context); + } +} + +impl ValueDebugFormat for Vc +where + T: ?Sized, + T: Upcast>, +{ + fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString { + ValueDebugFormatString::Async(Box::pin(async move { + Ok({ + let vc_value_debug = Vc::upcast::>(*self); + vc_value_debug.dbg_depth(depth).await?.to_string() + }) + })) + } +} + +impl std::future::IntoFuture for Vc +where + T: VcValueType, +{ + type Output = as std::future::Future>::Output; + type IntoFuture = ReadRawVcFuture; + fn into_future(self) -> Self::IntoFuture { + self.node.into_read::() + } +} + +impl std::future::IntoFuture for &Vc +where + T: VcValueType, +{ + type Output = as std::future::IntoFuture>::Output; + type IntoFuture = as std::future::IntoFuture>::IntoFuture; + fn into_future(self) -> Self::IntoFuture { + (*self).into_future() + } +} + +impl Vc +where + T: VcValueType, +{ + /// Returns a strongly consistent read of the value. This ensures that all + /// internal tasks are finished before the read is returned. + #[must_use] + pub fn strongly_consistent(self) -> ReadRawVcFuture { + self.node.into_strongly_consistent_read::() + } +} + +impl Unpin for Vc where T: ?Sized {} + +impl Default for Vc +where + T: ValueDefault, +{ + fn default() -> Self { + T::value_default() + } +} diff --git a/crates/turbo-tasks/src/vc/read.rs b/crates/turbo-tasks/src/vc/read.rs new file mode 100644 index 00000000000000..03b632300897ed --- /dev/null +++ b/crates/turbo-tasks/src/vc/read.rs @@ -0,0 +1,89 @@ +use std::{any::Any, marker::PhantomData, mem::ManuallyDrop}; + +use super::traits::VcValueType; + +/// Trait that controls [`Vc`]'s read representation. +/// +/// Has two implementations: +/// * [`VcDefaultRepr`] +/// * [`VcTransparentRepr`] +/// +/// This trait must remain sealed within this crate. +pub trait VcRead +where + T: VcValueType, +{ + /// The read target type. + type Target; + + /// Convert a reference to a value to a reference to the target type. + fn value_to_target_ref(value: &T) -> &Self::Target; + + /// Convert an target type to a value. + fn target_to_value(target: Self::Target) -> T; + + /// Convert a reference to an target type to a reference to a value. + fn target_to_value_ref(target: &Self::Target) -> &T; +} + +/// Representation for standard `#[turbo_tasks::value]`, where a read return a +/// reference to the value type[] +pub struct VcDefaultRead { + _phantom: PhantomData, +} + +impl VcRead for VcDefaultRead +where + T: VcValueType, +{ + type Target = T; + + fn value_to_target_ref(value: &T) -> &Self::Target { + value + } + + fn target_to_value(target: Self::Target) -> T { + target + } + fn target_to_value_ref(target: &Self::Target) -> &T { + target + } +} + +/// Representation for `#[turbo_tasks::value(transparent)]` types, where reads +/// return a reference to the target type. +pub struct VcTransparentRead { + _phantom: PhantomData<(T, Target)>, +} + +impl VcRead for VcTransparentRead +where + T: VcValueType, + Target: Any + Send + Sync, +{ + type Target = Target; + + fn value_to_target_ref(value: &T) -> &Self::Target { + // Safety: the `VcValueType` implementor must guarantee that both `T` and + // `Target` are #[repr(transparent)]. This is guaranteed by the + // `#[turbo_tasks::value(transparent)]` macro. + // We can't use `std::mem::transmute` here as it doesn't support generic types. + unsafe { + std::mem::transmute_copy::, &Self::Target>(&ManuallyDrop::new(value)) + } + } + + fn target_to_value(target: Self::Target) -> T { + // Safety: see `Self::value_to_target` above. + unsafe { + std::mem::transmute_copy::, T>(&ManuallyDrop::new(target)) + } + } + + fn target_to_value_ref(target: &Self::Target) -> &T { + // Safety: see `Self::value_to_target` above. + unsafe { + std::mem::transmute_copy::, &T>(&ManuallyDrop::new(target)) + } + } +} diff --git a/crates/turbo-tasks/src/vc/traits.rs b/crates/turbo-tasks/src/vc/traits.rs new file mode 100644 index 00000000000000..67e52e942924fb --- /dev/null +++ b/crates/turbo-tasks/src/vc/traits.rs @@ -0,0 +1,60 @@ +use super::{cell_mode::VcCellMode, read::VcRead}; +use crate::{TraitTypeId, ValueTypeId}; + +/// A trait implemented on all values types that can be put into a Value Cell +/// ([`Vc`]). +/// +/// # Safety +/// +/// The implementor of this trait must ensure that the read and cell mode +/// implementations are correct for the value type. Otherwise, it is possible to +/// generate invalid reads, for instance by using `VcTransparentRead` for a +/// value type that is not repr(transparent). +pub unsafe trait VcValueType: Sized + Send + Sync + 'static { + /// How to read the value. + type Read: VcRead; + + /// How to update cells of this value type. + type CellMode: VcCellMode; + + /// Returns the type id of the value type. + fn get_value_type_id() -> ValueTypeId; +} + +/// A trait implemented on all values trait object references that can be put +/// into a Value Cell ([`Vc<&dyn Trait>`]). +pub trait VcValueTrait { + fn get_trait_type_id() -> TraitTypeId; +} + +/// Marker trait that indicates that a [`Vc`] can be upcasted to a +/// [`Vc`]. +/// +/// # Safety +/// +/// The implementor of this trait must ensure that `Self` implements the +/// trait `T`. +pub unsafe trait Upcast +where + T: VcValueTrait + ?Sized, +{ +} + +/// Marker trait that indicates that a [`Vc`] can accept all methods +/// declared on a [`Vc`]. +/// +/// # Safety +/// +/// The implementor of this trait must ensure that `Self` implements the +/// trait `T`. +pub unsafe trait Dynamic +where + T: VcValueTrait + ?Sized, +{ +} + +/// Marker trait that a turbo_tasks::value is prepared for +/// serialization as Value<...> input. +/// Either use `#[turbo_tasks::value(serialization: auto_for_input)]` +/// or avoid Value<...> in favor of a real Vc +pub trait TypedForInput: VcValueType {} diff --git a/crates/turbopack-bench/src/bundlers/nextjs/mod.rs b/crates/turbopack-bench/src/bundlers/nextjs/mod.rs index 70cd9e6a231a36..7bea5c665c8fc8 100644 --- a/crates/turbopack-bench/src/bundlers/nextjs/mod.rs +++ b/crates/turbopack-bench/src/bundlers/nextjs/mod.rs @@ -12,7 +12,9 @@ use super::RenderType; use crate::{ bundlers::Bundler, util::{ - npm::{self, NpmPackage}, + npm::{ + NpmPackage, {self}, + }, wait_for_match, }, }; diff --git a/crates/turbopack-bench/src/bundlers/parcel.rs b/crates/turbopack-bench/src/bundlers/parcel.rs index d6ce56ab3ef5d0..308d0344248c0f 100644 --- a/crates/turbopack-bench/src/bundlers/parcel.rs +++ b/crates/turbopack-bench/src/bundlers/parcel.rs @@ -9,7 +9,9 @@ use regex::Regex; use crate::{ bundlers::Bundler, util::{ - npm::{self, NpmPackage}, + npm::{ + NpmPackage, {self}, + }, wait_for_match, }, }; diff --git a/crates/turbopack-bench/src/bundlers/rspack/mod.rs b/crates/turbopack-bench/src/bundlers/rspack/mod.rs index 18aed7e045dcf5..44a9f2204ece25 100644 --- a/crates/turbopack-bench/src/bundlers/rspack/mod.rs +++ b/crates/turbopack-bench/src/bundlers/rspack/mod.rs @@ -10,7 +10,9 @@ use regex::Regex; use crate::{ bundlers::Bundler, util::{ - npm::{self, NpmPackage}, + npm::{ + NpmPackage, {self}, + }, wait_for_match, }, }; diff --git a/crates/turbopack-bench/src/bundlers/vite/mod.rs b/crates/turbopack-bench/src/bundlers/vite/mod.rs index 7b22da4d36cdfa..fa998e529fa0dc 100644 --- a/crates/turbopack-bench/src/bundlers/vite/mod.rs +++ b/crates/turbopack-bench/src/bundlers/vite/mod.rs @@ -10,7 +10,9 @@ use regex::Regex; use crate::{ bundlers::Bundler, util::{ - npm::{self, NpmPackage}, + npm::{ + NpmPackage, {self}, + }, wait_for_match, }, }; diff --git a/crates/turbopack-bench/src/bundlers/webpack/mod.rs b/crates/turbopack-bench/src/bundlers/webpack/mod.rs index 400f4fcb1598d6..d4304b2172b6dd 100644 --- a/crates/turbopack-bench/src/bundlers/webpack/mod.rs +++ b/crates/turbopack-bench/src/bundlers/webpack/mod.rs @@ -10,7 +10,9 @@ use regex::Regex; use crate::{ bundlers::Bundler, util::{ - npm::{self, NpmPackage}, + npm::{ + NpmPackage, {self}, + }, wait_for_match, }, }; diff --git a/crates/turbopack-bench/src/util/mod.rs b/crates/turbopack-bench/src/util/mod.rs index 9b69b8f478e3f6..be077c334bfc40 100644 --- a/crates/turbopack-bench/src/util/mod.rs +++ b/crates/turbopack-bench/src/util/mod.rs @@ -1,5 +1,7 @@ use std::{ - io::{self, BufRead, BufReader, Read, Write}, + io::{ + BufRead, BufReader, Read, Write, {self}, + }, panic::UnwindSafe, process::Command, time::{Duration, Instant}, diff --git a/crates/turbopack-bench/src/util/npm.rs b/crates/turbopack-bench/src/util/npm.rs index 0e6ab8976b4433..b6e37de3864f27 100644 --- a/crates/turbopack-bench/src/util/npm.rs +++ b/crates/turbopack-bench/src/util/npm.rs @@ -1,6 +1,10 @@ use std::{ - fs::{self, File}, - io::{self, Write}, + fs::{ + File, {self}, + }, + io::{ + Write, {self}, + }, path::Path, }; diff --git a/crates/turbopack-build/src/chunking_context.rs b/crates/turbopack-build/src/chunking_context.rs index 65574e532ef86d..429314f5703149 100644 --- a/crates/turbopack-build/src/chunking_context.rs +++ b/crates/turbopack-build/src/chunking_context.rs @@ -2,31 +2,27 @@ use anyhow::Result; use indexmap::IndexSet; use turbo_tasks::{ graph::{GraphTraversal, ReverseTopological}, - primitives::{BoolVc, StringVc}, - TryJoinIterExt, Value, + TryJoinIterExt, Value, Vc, }; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetVc, AssetsVc}, - chunk::{ - Chunk, ChunkVc, ChunkableAsset, ChunkingContext, ChunkingContextVc, ChunksVc, - EvaluatableAssetsVc, - }, - environment::EnvironmentVc, - ident::AssetIdentVc, + asset::{Asset, Assets}, + chunk::{Chunk, ChunkableAsset, ChunkingContext, Chunks, EvaluatableAssets}, + environment::Environment, + ident::AssetIdent, }; -use turbopack_css::chunk::CssChunkVc; +use turbopack_css::chunk::CssChunk; use turbopack_ecmascript::{ - chunk::{EcmascriptChunkVc, EcmascriptChunkingContext, EcmascriptChunkingContextVc}, - EcmascriptModuleAssetVc, + chunk::{EcmascriptChunk, EcmascriptChunkingContext}, + EcmascriptModuleAsset, }; use turbopack_ecmascript_runtime::RuntimeType; use crate::ecmascript::node::{ - chunk::EcmascriptBuildNodeChunkVc, evaluate::chunk::EcmascriptBuildNodeEvaluateChunkVc, + chunk::EcmascriptBuildNodeChunk, evaluate::chunk::EcmascriptBuildNodeEvaluateChunk, }; -/// A builder for [`BuildChunkingContextVc`]. +/// A builder for [`Vc`]. pub struct BuildChunkingContextBuilder { context: BuildChunkingContext, } @@ -38,8 +34,8 @@ impl BuildChunkingContextBuilder { } /// Builds the chunking context. - pub fn build(self) -> BuildChunkingContextVc { - BuildChunkingContextVc::new(Value::new(self.context)) + pub fn build(self) -> Vc { + BuildChunkingContext::new(Value::new(self.context)) } } @@ -49,29 +45,29 @@ impl BuildChunkingContextBuilder { pub struct BuildChunkingContext { /// This path get stripped off of chunk paths before generating output asset /// paths. - context_path: FileSystemPathVc, + context_path: Vc, /// This path is used to compute the url to request chunks or assets from - output_root: FileSystemPathVc, + output_root: Vc, /// Chunks are placed at this path - chunk_root_path: FileSystemPathVc, + chunk_root_path: Vc, /// Static assets are placed at this path - asset_root_path: FileSystemPathVc, + asset_root_path: Vc, /// Layer name within this context layer: Option, /// The environment chunks will be evaluated in. - environment: EnvironmentVc, + environment: Vc, /// The kind of runtime to include in the output. runtime_type: RuntimeType, } -impl BuildChunkingContextVc { +impl BuildChunkingContext { /// Creates a new chunking context builder. pub fn builder( - context_path: FileSystemPathVc, - output_root: FileSystemPathVc, - chunk_root_path: FileSystemPathVc, - asset_root_path: FileSystemPathVc, - environment: EnvironmentVc, + context_path: Vc, + output_root: Vc, + chunk_root_path: Vc, + asset_root_path: Vc, + environment: Vc, ) -> BuildChunkingContextBuilder { BuildChunkingContextBuilder { context: BuildChunkingContext { @@ -98,28 +94,27 @@ impl BuildChunkingContext { } #[turbo_tasks::value_impl] -impl BuildChunkingContextVc { +impl BuildChunkingContext { #[turbo_tasks::function] - fn new(this: Value) -> Self { + fn new(this: Value) -> Vc { this.into_value().cell() } #[turbo_tasks::function] fn generate_evaluate_chunk( - self_vc: BuildChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, - exported_module: Option, - ) -> AssetVc { - EcmascriptBuildNodeEvaluateChunkVc::new( - self_vc, + self: Vc, + entry_chunk: Vc>, + other_chunks: Vc, + evaluatable_assets: Vc, + exported_module: Option>, + ) -> Vc> { + Vc::upcast(EcmascriptBuildNodeEvaluateChunk::new( + self, entry_chunk, other_chunks, evaluatable_assets, exported_module, - ) - .into() + )) } /// Generates an output chunk that: @@ -128,19 +123,19 @@ impl BuildChunkingContextVc { /// default export. #[turbo_tasks::function] pub async fn generate_exported_chunk( - self_vc: BuildChunkingContextVc, - module: EcmascriptModuleAssetVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> Result { - let entry_chunk = module.as_root_chunk(self_vc.into()); + self: Vc, + module: Vc, + evaluatable_assets: Vc, + ) -> Result>> { + let entry_chunk = module.as_root_chunk(Vc::upcast(self)); - let assets = self_vc + let assets = self .get_evaluate_chunk_assets(entry_chunk, evaluatable_assets) .await?; - let asset = self_vc.generate_evaluate_chunk( + let asset = self.generate_evaluate_chunk( entry_chunk, - AssetsVc::cell(assets), + Vc::cell(assets), evaluatable_assets, Some(module), ); @@ -149,30 +144,38 @@ impl BuildChunkingContextVc { } #[turbo_tasks::function] - async fn generate_chunk(self, chunk: ChunkVc) -> Result { + async fn generate_chunk( + self: Vc, + chunk: Vc>, + ) -> Result>> { Ok( - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { - EcmascriptBuildNodeChunkVc::new(self, ecmascript_chunk).into() + if let Some(ecmascript_chunk) = + Vc::try_resolve_downcast_type::(chunk).await? + { + Vc::upcast(EcmascriptBuildNodeChunk::new(self, ecmascript_chunk)) } else { - chunk.into() + Vc::upcast(chunk) }, ) } } -impl BuildChunkingContextVc { +impl BuildChunkingContext { async fn get_evaluate_chunk_assets( - self, - entry_chunk: ChunkVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> Result> { + self: Vc, + entry_chunk: Vc>, + evaluatable_assets: Vc, + ) -> Result>>> { let evaluatable_assets_ref = evaluatable_assets.await?; let mut chunks: IndexSet<_> = evaluatable_assets_ref .iter() .map({ move |evaluatable_asset| async move { - evaluatable_asset.as_root_chunk(self.into()).resolve().await + evaluatable_asset + .as_root_chunk(Vc::upcast(self)) + .resolve() + .await } }) .try_join() @@ -197,60 +200,68 @@ impl BuildChunkingContextVc { #[turbo_tasks::value_impl] impl ChunkingContext for BuildChunkingContext { #[turbo_tasks::function] - fn context_path(&self) -> FileSystemPathVc { + fn context_path(&self) -> Vc { self.context_path } #[turbo_tasks::function] - fn output_root(&self) -> FileSystemPathVc { + fn output_root(&self) -> Vc { self.output_root } #[turbo_tasks::function] - fn environment(&self) -> EnvironmentVc { + fn environment(&self) -> Vc { self.environment } #[turbo_tasks::function] - async fn chunk_path(&self, ident: AssetIdentVc, extension: &str) -> Result { + async fn chunk_path( + &self, + ident: Vc, + extension: String, + ) -> Result> { let root_path = self.chunk_root_path; let root_path = if let Some(layer) = self.layer.as_deref() { - root_path.join(layer) + root_path.join(layer.to_string()) } else { root_path }; let name = ident.output_name(self.context_path, extension).await?; - Ok(root_path.join(&name)) + Ok(root_path.join(name.clone_value())) } #[turbo_tasks::function] - fn reference_chunk_source_maps(&self, _chunk: AssetVc) -> BoolVc { - BoolVc::cell(true) + fn reference_chunk_source_maps(&self, _chunk: Vc>) -> Vc { + Vc::cell(true) } #[turbo_tasks::function] - async fn can_be_in_same_chunk(&self, asset_a: AssetVc, asset_b: AssetVc) -> Result { + async fn can_be_in_same_chunk( + &self, + asset_a: Vc>, + asset_b: Vc>, + ) -> Result> { let parent_dir = asset_a.ident().path().parent().await?; let path = asset_b.ident().path().await?; if let Some(rel_path) = parent_dir.get_path_to(&path) { if !rel_path.starts_with("node_modules/") && !rel_path.contains("/node_modules/") { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } - Ok(BoolVc::cell(false)) + Ok(Vc::cell(false)) } #[turbo_tasks::function] async fn asset_path( &self, - content_hash: &str, - original_asset_ident: AssetIdentVc, - ) -> Result { + content_hash: String, + original_asset_ident: Vc, + ) -> Result> { let source_path = original_asset_ident.path().await?; let basename = source_path.file_name(); - let asset_path = match source_path.extension() { + let asset_path = match source_path.extension_ref() { Some(ext) => format!( "{basename}.{content_hash}.{ext}", basename = &basename[..basename.len() - ext.len() - 1], @@ -261,70 +272,67 @@ impl ChunkingContext for BuildChunkingContext { content_hash = &content_hash[..8] ), }; - Ok(self.asset_root_path.join(&asset_path)) + Ok(self.asset_root_path.join(asset_path)) } #[turbo_tasks::function] - fn layer(&self) -> StringVc { - StringVc::cell(self.layer.clone().unwrap_or_default()) + fn layer(&self) -> Vc { + Vc::cell(self.layer.clone().unwrap_or_default()) } #[turbo_tasks::function] - async fn with_layer(self_vc: BuildChunkingContextVc, layer: &str) -> Result { - let mut context = self_vc.await?.clone_value(); + async fn with_layer(self: Vc, layer: String) -> Result>> { + let mut context = self.await?.clone_value(); context.layer = (!layer.is_empty()).then(|| layer.to_string()); - Ok(BuildChunkingContextVc::new(Value::new(context)).into()) + Ok(Vc::upcast(BuildChunkingContext::new(Value::new(context)))) } #[turbo_tasks::function] - async fn chunk_group( - self_vc: BuildChunkingContextVc, - entry_chunk: ChunkVc, - ) -> Result { + async fn chunk_group(self: Vc, entry_chunk: Vc>) -> Result> { let parallel_chunks = get_parallel_chunks([entry_chunk]).await?; let optimized_chunks = get_optimized_chunks(parallel_chunks).await?; - let assets: Vec = optimized_chunks + let assets: Vec>> = optimized_chunks .await? .iter() - .map(|chunk| self_vc.generate_chunk(*chunk)) + .map(|chunk| self.generate_chunk(*chunk)) .collect(); - Ok(AssetsVc::cell(assets)) + Ok(Vc::cell(assets)) } #[turbo_tasks::function] async fn evaluated_chunk_group( - self_vc: BuildChunkingContextVc, - entry_chunk: ChunkVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> Result { - let mut assets = self_vc + self: Vc, + entry_chunk: Vc>, + evaluatable_assets: Vc, + ) -> Result> { + let mut assets = self .get_evaluate_chunk_assets(entry_chunk, evaluatable_assets) .await?; - assets.push(self_vc.generate_evaluate_chunk( + assets.push(self.generate_evaluate_chunk( entry_chunk, - AssetsVc::cell(assets.clone()), + Vc::cell(assets.clone()), evaluatable_assets, None, )); - Ok(AssetsVc::cell(assets)) + Ok(Vc::cell(assets)) } } #[turbo_tasks::value_impl] impl EcmascriptChunkingContext for BuildChunkingContext {} -async fn get_parallel_chunks(entries: I) -> Result> +async fn get_parallel_chunks(entries: I) -> Result>>> where - I: IntoIterator, + I: IntoIterator>>, { Ok(ReverseTopological::new() .skip_duplicates() - .visit(entries, |chunk: ChunkVc| async move { + .visit(entries, |chunk: Vc>| async move { Ok(chunk .parallel_chunks() .await? @@ -339,18 +347,20 @@ where .into_iter()) } -async fn get_optimized_chunks(chunks: I) -> Result +async fn get_optimized_chunks(chunks: I) -> Result> where - I: IntoIterator, + I: IntoIterator>>, { let mut ecmascript_chunks = vec![]; let mut css_chunks = vec![]; let mut other_chunks = vec![]; for chunk in chunks.into_iter() { - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(&chunk).await? { + if let Some(ecmascript_chunk) = + Vc::try_resolve_downcast_type::(chunk).await? + { ecmascript_chunks.push(ecmascript_chunk); - } else if let Some(css_chunk) = CssChunkVc::resolve_from(&chunk).await? { + } else if let Some(css_chunk) = Vc::try_resolve_downcast_type::(chunk).await? { css_chunks.push(css_chunk); } else { other_chunks.push(chunk); @@ -362,10 +372,10 @@ where let chunks = ecmascript_chunks .iter() .copied() - .map(|chunk| chunk.as_chunk()) - .chain(css_chunks.iter().copied().map(|chunk| chunk.as_chunk())) + .map(|chunk| Vc::upcast(chunk)) + .chain(css_chunks.iter().copied().map(|chunk| Vc::upcast(chunk))) .chain(other_chunks.into_iter()) .collect(); - Ok(ChunksVc::cell(chunks)) + Ok(Vc::cell(chunks)) } diff --git a/crates/turbopack-build/src/ecmascript/node/chunk.rs b/crates/turbopack-build/src/ecmascript/node/chunk.rs index e677cdb465e480..961d9431c7960e 100644 --- a/crates/turbopack-build/src/ecmascript/node/chunk.rs +++ b/crates/turbopack-build/src/ecmascript/node/chunk.rs @@ -1,33 +1,31 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::ChunkingContext, - ident::AssetIdentVc, - introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}, - reference::AssetReferencesVc, - source_map::{ - GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, - }, + ident::AssetIdent, + introspect::{Introspectable, IntrospectableChildren}, + reference::AssetReferences, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAssetReference}, }; -use turbopack_ecmascript::chunk::EcmascriptChunkVc; +use turbopack_ecmascript::chunk::EcmascriptChunk; -use super::content::EcmascriptBuildNodeChunkContentVc; -use crate::BuildChunkingContextVc; +use super::content::EcmascriptBuildNodeChunkContent; +use crate::BuildChunkingContext; /// Production Ecmascript chunk targeting Node.js. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptBuildNodeChunk { - chunking_context: BuildChunkingContextVc, - chunk: EcmascriptChunkVc, + chunking_context: Vc, + chunk: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeChunkVc { - /// Creates a new [`EcmascriptBuildNodeChunkVc`]. +impl EcmascriptBuildNodeChunk { + /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub fn new(chunking_context: BuildChunkingContextVc, chunk: EcmascriptChunkVc) -> Self { + pub fn new(chunking_context: Vc, chunk: Vc) -> Vc { EcmascriptBuildNodeChunk { chunking_context, chunk, @@ -39,22 +37,22 @@ impl EcmascriptBuildNodeChunkVc { #[turbo_tasks::value_impl] impl ValueToString for EcmascriptBuildNodeChunk { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("Ecmascript Build Node Chunk".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Build Node Chunk".to_string())) } } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript build node chunk".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript build node chunk".to_string()) } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeChunkVc { +impl EcmascriptBuildNodeChunk { #[turbo_tasks::function] - async fn own_content(self) -> Result { + async fn own_content(self: Vc) -> Result> { let this = self.await?; - Ok(EcmascriptBuildNodeChunkContentVc::new( + Ok(EcmascriptBuildNodeChunkContent::new( this.chunking_context, self, this.chunk.chunk_content(), @@ -65,14 +63,14 @@ impl EcmascriptBuildNodeChunkVc { #[turbo_tasks::value_impl] impl Asset for EcmascriptBuildNodeChunk { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { let ident = self.chunk.ident().with_modifier(modifier()); - AssetIdentVc::from_path(self.chunking_context.chunk_path(ident, ".js")) + AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".to_string())) } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptBuildNodeChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let chunk_references = this.chunk.references().await?; let mut references = Vec::with_capacity(chunk_references.len() + 1); @@ -82,62 +80,63 @@ impl Asset for EcmascriptBuildNodeChunk { if *this .chunking_context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()); + references.push(Vc::upcast(SourceMapAssetReference::new(Vc::upcast(self)))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } #[turbo_tasks::function] - fn content(self_vc: EcmascriptBuildNodeChunkVc) -> AssetContentVc { - self_vc.own_content().content() + fn content(self: Vc) -> Vc { + self.own_content().content() } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptBuildNodeChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptBuildNodeChunkVc) -> OptionSourceMapVc { - self_vc.own_content().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.own_content().generate_source_map() } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("ecmascript build node chunk".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("ecmascript build node chunk".to_string()) } #[turbo_tasks::function] -fn introspectable_details() -> StringVc { - StringVc::cell("generates a production EcmaScript chunk targeting Node.js".to_string()) +fn introspectable_details() -> Vc { + Vc::cell("generates a production EcmaScript chunk targeting Node.js".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for EcmascriptBuildNodeChunk { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(self_vc: EcmascriptBuildNodeChunkVc) -> StringVc { - self_vc.ident().to_string() + fn title(self: Vc) -> Vc { + self.ident().to_string() } #[turbo_tasks::function] - fn details(&self) -> StringVc { + fn details(&self) -> Vc { introspectable_details() } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let mut children = IndexSet::new(); - if let Some(chunk) = IntrospectableVc::resolve_from(self.chunk).await? { - children.insert((StringVc::cell("chunk".to_string()), chunk)); - } - Ok(IntrospectableChildrenVc::cell(children)) + let introspectable_chunk = Vc::upcast::>(self.chunk) + .resolve() + .await?; + children.insert((Vc::cell("chunk".to_string()), introspectable_chunk)); + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-build/src/ecmascript/node/content.rs b/crates/turbopack-build/src/ecmascript/node/content.rs index a57776e15d7f23..c589e256627aef 100644 --- a/crates/turbopack-build/src/ecmascript/node/content.rs +++ b/crates/turbopack-build/src/ecmascript/node/content.rs @@ -2,33 +2,36 @@ use std::io::Write; use anyhow::Result; use indoc::writedoc; -use turbo_tasks::{TryJoinIterExt, Value}; +use turbo_tasks::{TryJoinIterExt, Value, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc}, - code_builder::{CodeBuilder, CodeVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, + asset::{Asset, AssetContent}, + code_builder::{Code, CodeBuilder}, + source_map::{GenerateSourceMap, OptionSourceMap}, +}; +use turbopack_ecmascript::{ + chunk::{EcmascriptChunkContent, EcmascriptChunkItemExt}, + utils::StringifyJs, }; -use turbopack_ecmascript::{chunk::EcmascriptChunkContentVc, utils::StringifyJs}; -use super::chunk::EcmascriptBuildNodeChunkVc; -use crate::BuildChunkingContextVc; +use super::chunk::EcmascriptBuildNodeChunk; +use crate::BuildChunkingContext; #[turbo_tasks::value] pub(super) struct EcmascriptBuildNodeChunkContent { - pub(super) content: EcmascriptChunkContentVc, - pub(super) chunking_context: BuildChunkingContextVc, - pub(super) chunk: EcmascriptBuildNodeChunkVc, + pub(super) content: Vc, + pub(super) chunking_context: Vc, + pub(super) chunk: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeChunkContentVc { +impl EcmascriptBuildNodeChunkContent { #[turbo_tasks::function] pub(crate) async fn new( - chunking_context: BuildChunkingContextVc, - chunk: EcmascriptBuildNodeChunkVc, - content: EcmascriptChunkContentVc, - ) -> Result { + chunking_context: Vc, + chunk: Vc, + content: Vc, + ) -> Result> { Ok(EcmascriptBuildNodeChunkContent { content, chunking_context, @@ -39,9 +42,9 @@ impl EcmascriptBuildNodeChunkContentVc { } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeChunkContentVc { +impl EcmascriptBuildNodeChunkContent { #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { let this = self.await?; let chunk_path = this.chunk.ident().path().await?; @@ -86,16 +89,18 @@ impl EcmascriptBuildNodeChunkContentVc { } #[turbo_tasks::function] - pub async fn content(self_vc: EcmascriptBuildNodeChunkContentVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + pub async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptBuildNodeChunkContent { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptBuildNodeChunkContentVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } } diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs b/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs index 72fb451378417a..7249e628ab5e14 100644 --- a/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs +++ b/crates/turbopack-build/src/ecmascript/node/evaluate/chunk.rs @@ -2,49 +2,47 @@ use std::io::Write; use anyhow::{bail, Result}; use indoc::writedoc; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ChunkVc, ChunkingContext, EvaluatableAssetsVc}, - code_builder::{CodeBuilder, CodeVc}, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, - source_map::{ - GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, - }, + asset::{Asset, AssetContent, Assets}, + chunk::{Chunk, ChunkingContext, EvaluatableAssets}, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAssetReference}, }; use turbopack_ecmascript::{ - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, + chunk::{EcmascriptChunkItemExt, EcmascriptChunkPlaceable}, utils::StringifyJs, - EcmascriptModuleAssetVc, + EcmascriptModuleAsset, }; -use super::runtime::EcmascriptBuildNodeRuntimeReferenceVc; -use crate::BuildChunkingContextVc; +use super::runtime::EcmascriptBuildNodeRuntimeReference; +use crate::BuildChunkingContext; /// An Ecmascript chunk that loads a list of parallel chunks, then instantiates /// runtime entries. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptBuildNodeEvaluateChunk { - chunking_context: BuildChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, - exported_module: Option, + chunking_context: Vc, + entry_chunk: Vc>, + other_chunks: Vc, + evaluatable_assets: Vc, + exported_module: Option>, } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeEvaluateChunkVc { - /// Creates a new [`EcmascriptBuildNodeEvaluateChunkVc`]. +impl EcmascriptBuildNodeEvaluateChunk { + /// Creates a new [`Vc`]. #[turbo_tasks::function] pub fn new( - chunking_context: BuildChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, - exported_module: Option, - ) -> Self { + chunking_context: Vc, + entry_chunk: Vc>, + other_chunks: Vc, + evaluatable_assets: Vc, + exported_module: Option>, + ) -> Vc { EcmascriptBuildNodeEvaluateChunk { chunking_context, entry_chunk, @@ -56,7 +54,7 @@ impl EcmascriptBuildNodeEvaluateChunkVc { } #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { let this = self.await?; let output_root = this.chunking_context.output_root().await?; @@ -119,10 +117,11 @@ impl EcmascriptBuildNodeEvaluateChunkVc { let evaluatable_assets = this.evaluatable_assets.await?; for evaluatable_asset in &*evaluatable_assets { if let Some(placeable) = - EcmascriptChunkPlaceableVc::resolve_from(evaluatable_asset).await? + Vc::try_resolve_sidecast::>(*evaluatable_asset) + .await? { let runtime_module_id = placeable - .as_chunk_item(this.chunking_context.into()) + .as_chunk_item(Vc::upcast(this.chunking_context)) .id() .await?; @@ -138,7 +137,7 @@ impl EcmascriptBuildNodeEvaluateChunkVc { if let Some(exported_module) = this.exported_module { let runtime_module_id = exported_module - .as_chunk_item(this.chunking_context.into()) + .as_chunk_item(Vc::upcast(this.chunking_context)) .id() .await?; @@ -151,13 +150,13 @@ impl EcmascriptBuildNodeEvaluateChunkVc { )?; } - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } #[turbo_tasks::function] - async fn runtime_reference(self) -> Result { + async fn runtime_reference(self: Vc) -> Result> { let this = self.await?; - Ok(EcmascriptBuildNodeRuntimeReferenceVc::new( + Ok(EcmascriptBuildNodeRuntimeReference::new( this.chunking_context, )) } @@ -166,27 +165,25 @@ impl EcmascriptBuildNodeEvaluateChunkVc { #[turbo_tasks::value_impl] impl ValueToString for EcmascriptBuildNodeEvaluateChunk { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell( - "Ecmascript Build Node Evaluate Chunk".to_string(), - )) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Build Node Evaluate Chunk".to_string())) } } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript build node evaluate chunk".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript build node evaluate chunk".to_string()) } #[turbo_tasks::function] -fn chunk_reference_description() -> StringVc { - StringVc::cell("chunk".to_string()) +fn chunk_reference_description() -> Vc { + Vc::cell("chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for EcmascriptBuildNodeEvaluateChunk { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { let mut ident = self.entry_chunk.ident().await?.clone_value(); ident.add_modifier(modifier()); @@ -202,46 +199,49 @@ impl Asset for EcmascriptBuildNodeEvaluateChunk { ident.add_modifier(chunk.ident().to_string()); } - let ident = AssetIdentVc::new(Value::new(ident)); - Ok(AssetIdentVc::from_path( - self.chunking_context.chunk_path(ident, ".js"), + let ident = AssetIdent::new(Value::new(ident)); + Ok(AssetIdent::from_path( + self.chunking_context.chunk_path(ident, ".js".to_string()), )) } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result { - let this = self_vc.await?; - let mut references = vec![self_vc.runtime_reference().into()]; + async fn references(self: Vc) -> Result> { + let this = self.await?; + let mut references = vec![Vc::upcast(self.runtime_reference())]; if *this .chunking_context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()) + references.push(Vc::upcast(SourceMapAssetReference::new(Vc::upcast(self)))) } let other_chunks = this.other_chunks.await?; for other_chunk in &*other_chunks { - references.push( - SingleAssetReferenceVc::new(*other_chunk, chunk_reference_description()).into(), - ); + references.push(Vc::upcast(SingleAssetReference::new( + *other_chunk, + chunk_reference_description(), + ))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } #[turbo_tasks::function] - async fn content(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptBuildNodeEvaluateChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } } diff --git a/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs b/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs index ed016523961f41..9452538e062037 100644 --- a/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs +++ b/crates/turbopack-build/src/ecmascript/node/evaluate/runtime.rs @@ -2,40 +2,38 @@ use std::io::Write; use anyhow::{bail, Result}; use indoc::writedoc; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::{File, FileSystem}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::ChunkingContext, - code_builder::{CodeBuilder, CodeVc}, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, - resolve::{ResolveResult, ResolveResultVc}, - source_map::{ - GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, - }, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + reference::{AssetReference, AssetReferences}, + resolve::ResolveResult, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAssetReference}, }; use turbopack_ecmascript::utils::StringifyJs; use turbopack_ecmascript_runtime::RuntimeType; -use crate::BuildChunkingContextVc; +use crate::BuildChunkingContext; /// An Ecmascript chunk that contains the Node.js runtime code. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptBuildNodeRuntimeChunk { - chunking_context: BuildChunkingContextVc, + chunking_context: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeRuntimeChunkVc { - /// Creates a new [`EcmascriptBuildNodeRuntimeChunkVc`]. +impl EcmascriptBuildNodeRuntimeChunk { + /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub fn new(chunking_context: BuildChunkingContextVc) -> Self { + pub fn new(chunking_context: Vc) -> Vc { EcmascriptBuildNodeRuntimeChunk { chunking_context }.cell() } #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { let this = self.await?; let output_root = this.chunking_context.output_root().await?; @@ -74,83 +72,81 @@ impl EcmascriptBuildNodeRuntimeChunkVc { } } - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } } #[turbo_tasks::value_impl] impl ValueToString for EcmascriptBuildNodeRuntimeChunk { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell( - "Ecmascript Build Node Runtime Chunk".to_string(), - )) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Build Node Runtime Chunk".to_string())) } } #[turbo_tasks::value_impl] impl Asset for EcmascriptBuildNodeRuntimeChunk { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - let ident = AssetIdentVc::from_path( + fn ident(&self) -> Vc { + let ident = AssetIdent::from_path( turbopack_ecmascript_runtime::embed_fs() .root() - .join("runtime.js"), + .join("runtime.js".to_string()), ); - AssetIdentVc::from_path(self.chunking_context.chunk_path(ident, ".js")) + AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".to_string())) } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptBuildNodeRuntimeChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let mut references = vec![]; if *this .chunking_context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()) + references.push(Vc::upcast(SourceMapAssetReference::new(Vc::upcast(self)))) } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } #[turbo_tasks::function] - async fn content(self_vc: EcmascriptBuildNodeRuntimeChunkVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptBuildNodeRuntimeChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptBuildNodeRuntimeChunkVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } } /// A reference to the runtime chunk. #[turbo_tasks::value] pub(crate) struct EcmascriptBuildNodeRuntimeReference { - chunking_context: BuildChunkingContextVc, + chunking_context: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptBuildNodeRuntimeReferenceVc { +impl EcmascriptBuildNodeRuntimeReference { #[turbo_tasks::function] - pub fn new(chunking_context: BuildChunkingContextVc) -> Self { + pub fn new(chunking_context: Vc) -> Vc { Self::cell(EcmascriptBuildNodeRuntimeReference { chunking_context }) } #[turbo_tasks::function] - pub async fn runtime_chunk( - self_vc: EcmascriptBuildNodeRuntimeReferenceVc, - ) -> Result { - Ok(EcmascriptBuildNodeRuntimeChunkVc::new( - self_vc.await?.chunking_context, + pub async fn runtime_chunk(self: Vc) -> Result> { + Ok(EcmascriptBuildNodeRuntimeChunk::new( + self.await?.chunking_context, )) } } @@ -158,18 +154,18 @@ impl EcmascriptBuildNodeRuntimeReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for EcmascriptBuildNodeRuntimeReference { #[turbo_tasks::function] - fn resolve_reference(self_vc: EcmascriptBuildNodeRuntimeReferenceVc) -> ResolveResultVc { - ResolveResult::asset(self_vc.runtime_chunk().into()).into() + fn resolve_reference(self: Vc) -> Vc { + ResolveResult::asset(Vc::upcast(self.runtime_chunk())).into() } } #[turbo_tasks::value_impl] impl ValueToString for EcmascriptBuildNodeRuntimeReference { #[turbo_tasks::function] - async fn to_string(self_vc: EcmascriptBuildNodeRuntimeReferenceVc) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(self: Vc) -> Result> { + Ok(Vc::cell(format!( "runtime chunk {}", - self_vc.runtime_chunk().ident().to_string().await? + self.runtime_chunk().ident().to_string().await? ))) } } diff --git a/crates/turbopack-build/src/lib.rs b/crates/turbopack-build/src/lib.rs index 9edc258a2881ff..0226b408aedb4b 100644 --- a/crates/turbopack-build/src/lib.rs +++ b/crates/turbopack-build/src/lib.rs @@ -1,12 +1,12 @@ #![feature(lint_reasons)] #![feature(iter_intersperse)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub(crate) mod chunking_context; pub(crate) mod ecmascript; -pub use chunking_context::{ - BuildChunkingContext, BuildChunkingContextBuilder, BuildChunkingContextVc, -}; +pub use chunking_context::{BuildChunkingContext, BuildChunkingContextBuilder}; pub fn register() { turbo_tasks::register(); diff --git a/crates/turbopack-cli-utils/src/issue.rs b/crates/turbopack-cli-utils/src/issue.rs index 97d2101ed7489e..06fd71e823bbfb 100644 --- a/crates/turbopack-cli-utils/src/issue.rs +++ b/crates/turbopack-cli-utils/src/issue.rs @@ -11,13 +11,11 @@ use std::{ use anyhow::{anyhow, Result}; use crossterm::style::{StyledContent, Stylize}; use owo_colors::{OwoColorize as _, Style}; -use turbo_tasks::{ - primitives::BoolVc, RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, -}; +use turbo_tasks::{RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, Vc}; use turbo_tasks_fs::{source_context::get_source_context, FileLinesContent}; use turbopack_core::issue::{ - CapturedIssues, IssueReporter, IssueReporterVc, IssueSeverity, PlainIssue, - PlainIssueProcessingPathItem, PlainIssueProcessingPathItemReadRef, PlainIssueSource, + CapturedIssues, Issue, IssueReporter, IssueSeverity, PlainIssue, PlainIssueProcessingPathItem, + PlainIssueSource, }; use crate::source_context::format_source_context_lines; @@ -80,7 +78,7 @@ fn severity_to_style(severity: IssueSeverity) -> Style { } fn format_source_content(source: &PlainIssueSource, formatted_issue: &mut String) { - if let FileLinesContent::Lines(lines) = source.asset.content.lines() { + if let FileLinesContent::Lines(lines) = source.asset.content.lines_ref() { let start_line = source.start.line; let end_line = source.end.line; let start_column = source.start.column; @@ -92,7 +90,7 @@ fn format_source_content(source: &PlainIssueSource, formatted_issue: &mut String } fn format_optional_path( - path: &Option>, + path: &Option>>, formatted_issue: &mut String, ) -> Result<()> { if let Some(path) = path { @@ -335,9 +333,9 @@ impl PartialEq for ConsoleUi { } #[turbo_tasks::value_impl] -impl ConsoleUiVc { +impl ConsoleUi { #[turbo_tasks::function] - pub fn new(options: TransientInstance) -> Self { + pub fn new(options: TransientInstance) -> Vc { ConsoleUi { options: (*options).clone(), seen: Arc::new(Mutex::new(SeenIssues::new())), @@ -353,7 +351,7 @@ impl IssueReporter for ConsoleUi { &self, issues: TransientInstance>, source: TransientValue, - ) -> Result { + ) -> Result> { let issues = &*issues; let LogOptions { ref current_dir, @@ -529,7 +527,7 @@ impl IssueReporter for ConsoleUi { } } - Ok(BoolVc::cell(has_fatal)) + Ok(Vc::cell(has_fatal)) } } diff --git a/crates/turbopack-cli-utils/src/lib.rs b/crates/turbopack-cli-utils/src/lib.rs index aeb93ad001cb61..2c2aaf26eccf78 100644 --- a/crates/turbopack-cli-utils/src/lib.rs +++ b/crates/turbopack-cli-utils/src/lib.rs @@ -2,6 +2,8 @@ #![feature(min_specialization)] #![feature(round_char_boundary)] #![feature(thread_id_value)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub mod exit; pub mod issue; diff --git a/crates/turbopack-cli-utils/src/runtime_entry.rs b/crates/turbopack-cli-utils/src/runtime_entry.rs index 4092bdffaf2851..1bc78d6ad6c224 100644 --- a/crates/turbopack-cli-utils/src/runtime_entry.rs +++ b/crates/turbopack-cli-utils/src/runtime_entry.rs @@ -1,40 +1,41 @@ use anyhow::{bail, Result}; -use turbo_tasks::ValueToString; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{EvaluatableAssetVc, EvaluatableAssetsVc}, - context::AssetContextVc, - issue::{IssueSeverity, OptionIssueSourceVc}, - resolve::{origin::PlainResolveOriginVc, parse::RequestVc}, + asset::Asset, + chunk::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets}, + context::AssetContext, + issue::{IssueSeverity, OptionIssueSource}, + resolve::{origin::PlainResolveOrigin, parse::Request}, }; use turbopack_ecmascript::resolve::cjs_resolve; #[turbo_tasks::value(shared)] pub enum RuntimeEntry { - Request(RequestVc, FileSystemPathVc), - Evaluatable(EvaluatableAssetVc), - Source(AssetVc), + Request(Vc, Vc), + Evaluatable(Vc>), + Source(Vc>), } #[turbo_tasks::value_impl] -impl RuntimeEntryVc { +impl RuntimeEntry { #[turbo_tasks::function] - pub async fn resolve_entry(self, context: AssetContextVc) -> Result { + pub async fn resolve_entry( + self: Vc, + context: Vc>, + ) -> Result> { let (request, path) = match *self.await? { - RuntimeEntry::Evaluatable(e) => return Ok(EvaluatableAssetsVc::one(e)), + RuntimeEntry::Evaluatable(e) => return Ok(EvaluatableAssets::one(e)), RuntimeEntry::Source(source) => { - return Ok(EvaluatableAssetsVc::one(EvaluatableAssetVc::from_asset( - source, context, - ))); + return Ok(EvaluatableAssets::one(source.to_evaluatable(context))); } RuntimeEntry::Request(r, path) => (r, path), }; let assets = cjs_resolve( - PlainResolveOriginVc::new(context, path).into(), + Vc::upcast(PlainResolveOrigin::new(context, path)), request, - OptionIssueSourceVc::none(), + OptionIssueSource::none(), IssueSeverity::Error.cell(), ) .primary_assets() @@ -42,7 +43,9 @@ impl RuntimeEntryVc { let mut runtime_entries = Vec::with_capacity(assets.len()); for asset in &assets { - if let Some(entry) = EvaluatableAssetVc::resolve_from(asset).await? { + if let Some(entry) = + Vc::try_resolve_sidecast::>(*asset).await? + { runtime_entries.push(entry); } else { bail!( @@ -52,17 +55,20 @@ impl RuntimeEntryVc { } } - Ok(EvaluatableAssetsVc::cell(runtime_entries)) + Ok(Vc::cell(runtime_entries)) } } #[turbo_tasks::value(transparent)] -pub struct RuntimeEntries(Vec); +pub struct RuntimeEntries(Vec>); #[turbo_tasks::value_impl] -impl RuntimeEntriesVc { +impl RuntimeEntries { #[turbo_tasks::function] - pub async fn resolve_entries(self, context: AssetContextVc) -> Result { + pub async fn resolve_entries( + self: Vc, + context: Vc>, + ) -> Result> { let mut runtime_entries = Vec::new(); for reference in &self.await? { @@ -70,6 +76,6 @@ impl RuntimeEntriesVc { runtime_entries.extend(resolved_entries.into_iter()); } - Ok(EvaluatableAssetsVc::cell(runtime_entries)) + Ok(Vc::cell(runtime_entries)) } } diff --git a/crates/turbopack-cli/benches/bundler.rs b/crates/turbopack-cli/benches/bundler.rs index 334ec9d04a40f5..0583b9207643dd 100644 --- a/crates/turbopack-cli/benches/bundler.rs +++ b/crates/turbopack-cli/benches/bundler.rs @@ -9,7 +9,9 @@ use regex::Regex; use turbopack_bench::{ bundlers::{Bundler, RenderType}, util::{ - npm::{self, NpmPackage}, + npm::{ + NpmPackage, {self}, + }, wait_for_match, }, }; diff --git a/crates/turbopack-cli/src/dev/mod.rs b/crates/turbopack-cli/src/dev/mod.rs index 3815b9b49061af..777f58c502233b 100644 --- a/crates/turbopack-cli/src/dev/mod.rs +++ b/crates/turbopack-cli/src/dev/mod.rs @@ -14,31 +14,31 @@ use dunce::canonicalize; use owo_colors::OwoColorize; use turbo_tasks::{ util::{FormatBytes, FormatDuration}, - StatsType, TransientInstance, TurboTasks, TurboTasksBackendApi, UpdateInfo, Value, + StatsType, TransientInstance, TurboTasks, TurboTasksBackendApi, UpdateInfo, Value, Vc, }; -use turbo_tasks_fs::{DiskFileSystemVc, FileSystem, FileSystemVc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem}; use turbo_tasks_malloc::TurboMalloc; use turbo_tasks_memory::MemoryBackend; use turbopack::evaluate_context::node_build_environment; -use turbopack_cli_utils::issue::{ConsoleUiVc, LogOptions}; +use turbopack_cli_utils::issue::{ConsoleUi, LogOptions}; use turbopack_core::{ environment::ServerAddr, - issue::{IssueReporterVc, IssueSeverity}, - resolve::{parse::RequestVc, pattern::QueryMapVc}, - server_fs::ServerFileSystemVc, + issue::{IssueReporter, IssueSeverity}, + resolve::{parse::Request, pattern::QueryMap}, + server_fs::ServerFileSystem, }; -use turbopack_dev::DevChunkingContextVc; +use turbopack_dev::DevChunkingContext; use turbopack_dev_server::{ introspect::IntrospectionSource, source::{ - combined::CombinedContentSourceVc, router::RouterContentSource, - source_maps::SourceMapContentSourceVc, static_assets::StaticAssetsContentSourceVc, - ContentSourceVc, + combined::CombinedContentSource, router::RouterContentSource, + source_maps::SourceMapContentSource, static_assets::StaticAssetsContentSource, + ContentSource, }, DevServer, DevServerBuilder, }; use turbopack_env::dotenv::load_env; -use turbopack_node::execution_context::ExecutionContextVc; +use turbopack_node::execution_context::ExecutionContext; use self::web_entry_source::create_web_entry_source; use crate::arguments::DevArguments; @@ -210,7 +210,7 @@ impl TurbopackDevServerBuilder { let tasks = turbo_tasks.clone(); let issue_provider = self.issue_reporter.unwrap_or_else(|| { // Initialize a ConsoleUi reporter if no custom reporter was provided - Box::new(move || ConsoleUiVc::new(log_args.clone().into()).into()) + Box::new(move || Vc::upcast(ConsoleUi::new(log_args.clone().into()))) }); let source = move || { @@ -230,17 +230,17 @@ impl TurbopackDevServerBuilder { } #[turbo_tasks::function] -async fn project_fs(project_dir: &str) -> Result { - let disk_fs = DiskFileSystemVc::new("project".to_string(), project_dir.to_string()); +async fn project_fs(project_dir: String) -> Result>> { + let disk_fs = DiskFileSystem::new("project".to_string(), project_dir.to_string()); disk_fs.await?.start_watching()?; - Ok(disk_fs.into()) + Ok(Vc::upcast(disk_fs)) } #[turbo_tasks::function] -async fn output_fs(project_dir: &str) -> Result { - let disk_fs = DiskFileSystemVc::new("output".to_string(), project_dir.to_string()); +async fn output_fs(project_dir: String) -> Result>> { + let disk_fs = DiskFileSystem::new("output".to_string(), project_dir.to_string()); disk_fs.await?.start_watching()?; - Ok(disk_fs.into()) + Ok(Vc::upcast(disk_fs)) } #[allow(clippy::too_many_arguments)] @@ -252,38 +252,39 @@ async fn source( eager_compile: bool, turbo_tasks: TransientInstance>, browserslist_query: String, -) -> Result { - let output_fs = output_fs(&project_dir); - let fs = project_fs(&root_dir); +) -> Result>> { let project_relative = project_dir.strip_prefix(&root_dir).unwrap(); let project_relative = project_relative .strip_prefix(MAIN_SEPARATOR) .unwrap_or(project_relative) .replace(MAIN_SEPARATOR, "/"); - let project_path = fs.root().join(&project_relative); + + let output_fs = output_fs(project_dir); + let fs = project_fs(root_dir); + let project_path: Vc = fs.root().join(project_relative); let env = load_env(project_path); - let build_output_root = output_fs.root().join(".turbopack/build"); + let build_output_root = output_fs.root().join(".turbopack/build".to_string()); - let build_chunking_context = DevChunkingContextVc::builder( + let build_chunking_context = DevChunkingContext::builder( project_path, build_output_root, - build_output_root.join("chunks"), - build_output_root.join("assets"), + build_output_root.join("chunks".to_string()), + build_output_root.join("assets".to_string()), node_build_environment(), ) .build(); - let execution_context = ExecutionContextVc::new(project_path, build_chunking_context, env); + let execution_context = ExecutionContext::new(project_path, build_chunking_context, env); - let server_fs = ServerFileSystemVc::new().as_file_system(); + let server_fs = Vc::upcast::>(ServerFileSystem::new()); let server_root = server_fs.root(); let entry_requests = entry_requests .iter() .map(|r| match r { - EntryRequest::Relative(p) => RequestVc::relative(Value::new(p.clone().into()), false), + EntryRequest::Relative(p) => Request::relative(Value::new(p.clone().into()), false), EntryRequest::Module(m, p) => { - RequestVc::module(m.clone(), Value::new(p.clone().into()), QueryMapVc::none()) + Request::module(m.clone(), Value::new(p.clone().into()), QueryMap::none()) } }) .collect(); @@ -295,33 +296,38 @@ async fn source( server_root, env, eager_compile, - &browserslist_query, + browserslist_query, + ); + let viz = Vc::upcast( + turbo_tasks_viz::TurboTasksSource { + turbo_tasks: turbo_tasks.into(), + } + .cell(), + ); + let static_source = Vc::upcast(StaticAssetsContentSource::new( + String::new(), + project_path.join("public".to_string()), + )); + let main_source = CombinedContentSource::new(vec![static_source, web_source]); + let introspect = Vc::upcast( + IntrospectionSource { + roots: HashSet::from([Vc::upcast(main_source)]), + } + .cell(), + ); + let main_source = Vc::upcast(main_source); + let source_maps = Vc::upcast(SourceMapContentSource::new(main_source)); + let source = Vc::upcast( + RouterContentSource { + routes: vec![ + ("__turbopack__/".to_string(), introspect), + ("__turbo_tasks__/".to_string(), viz), + ("__turbopack_sourcemap__/".to_string(), source_maps), + ], + fallback: main_source, + } + .cell(), ); - let viz = turbo_tasks_viz::TurboTasksSource { - turbo_tasks: turbo_tasks.into(), - } - .cell() - .into(); - let static_source = - StaticAssetsContentSourceVc::new(String::new(), project_path.join("public")).into(); - let main_source = CombinedContentSourceVc::new(vec![static_source, web_source]); - let introspect = IntrospectionSource { - roots: HashSet::from([main_source.into()]), - } - .cell() - .into(); - let main_source = main_source.into(); - let source_maps = SourceMapContentSourceVc::new(main_source).into(); - let source = RouterContentSource { - routes: vec![ - ("__turbopack__/".to_string(), introspect), - ("__turbo_tasks__/".to_string(), viz), - ("__turbopack_sourcemap__/".to_string(), source_maps), - ], - fallback: main_source, - } - .cell() - .into(); Ok(source) } @@ -524,14 +530,14 @@ fn profile_timeout( } pub trait IssueReporterProvider: Send + Sync + 'static { - fn get_issue_reporter(&self) -> IssueReporterVc; + fn get_issue_reporter(&self) -> Vc>; } impl IssueReporterProvider for T where - T: Fn() -> IssueReporterVc + Send + Sync + Clone + 'static, + T: Fn() -> Vc> + Send + Sync + Clone + 'static, { - fn get_issue_reporter(&self) -> IssueReporterVc { + fn get_issue_reporter(&self) -> Vc> { self() } } diff --git a/crates/turbopack-cli/src/dev/turbo_tasks_viz.rs b/crates/turbopack-cli/src/dev/turbo_tasks_viz.rs index 81b1ab09eb7687..aa2c635cd8da1d 100644 --- a/crates/turbopack-cli/src/dev/turbo_tasks_viz.rs +++ b/crates/turbopack-cli/src/dev/turbo_tasks_viz.rs @@ -2,16 +2,16 @@ use std::{sync::Arc, time::Duration}; use anyhow::Result; use mime::TEXT_HTML_UTF_8; -use turbo_tasks::{get_invalidator, TurboTasks, TurboTasksBackendApi, Value}; +use turbo_tasks::{get_invalidator, TurboTasks, TurboTasksBackendApi, Value, Vc}; use turbo_tasks_fs::File; use turbo_tasks_memory::{ stats::{ReferenceType, Stats}, viz, MemoryBackend, }; -use turbopack_core::asset::AssetContentVc; +use turbopack_core::{asset::AssetContent, version::VersionedContentExt}; use turbopack_dev_server::source::{ - ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceDataFilter, - ContentSourceDataVary, ContentSourceResultVc, ContentSourceVc, NeededData, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataFilter, + ContentSourceDataVary, ContentSourceResult, NeededData, }; #[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new", into = "new")] @@ -20,8 +20,9 @@ pub struct TurboTasksSource { pub turbo_tasks: Arc>, } -impl TurboTasksSourceVc { - pub fn new(turbo_tasks: Arc>) -> Self { +impl TurboTasksSource { + #[allow(unused)] + pub fn new(turbo_tasks: Arc>) -> Vc { Self::cell(TurboTasksSource { turbo_tasks }) } } @@ -32,11 +33,11 @@ const INVALIDATION_INTERVAL: Duration = Duration::from_secs(3); impl ContentSource for TurboTasksSource { #[turbo_tasks::function] async fn get( - self_vc: TurboTasksSourceVc, - path: &str, + self: Vc, + path: String, data: Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result> { + let this = self.await?; let tt = &this.turbo_tasks; let invalidator = get_invalidator(); tokio::spawn({ @@ -45,7 +46,7 @@ impl ContentSource for TurboTasksSource { invalidator.invalidate(); } }); - let html = match path { + let html = match path.as_str() { "graph" => { let mut stats = Stats::new(); let b = tt.backend(); @@ -86,8 +87,8 @@ impl ContentSource for TurboTasksSource { let table = viz::table::create_table(tree, tt.stats_type()); viz::table::wrap_html(&table) } else { - return Ok(ContentSourceResultVc::need_data(Value::new(NeededData { - source: self_vc.into(), + return Ok(ContentSourceResult::need_data(Value::new(NeededData { + source: Vc::upcast(self), path: path.to_string(), vary: ContentSourceDataVary { query: Some(ContentSourceDataFilter::All), @@ -103,13 +104,13 @@ impl ContentSource for TurboTasksSource { }); "Done".to_string() } - _ => return Ok(ContentSourceResultVc::not_found()), + _ => return Ok(ContentSourceResult::not_found()), }; - Ok(ContentSourceResultVc::exact( - ContentSourceContentVc::static_content( - AssetContentVc::from(File::from(html).with_content_type(TEXT_HTML_UTF_8)).into(), - ) - .into(), - )) + Ok(ContentSourceResult::exact(Vc::upcast( + ContentSourceContent::static_content( + AssetContent::file(File::from(html).with_content_type(TEXT_HTML_UTF_8).into()) + .versioned(), + ), + ))) } } diff --git a/crates/turbopack-cli/src/dev/web_entry_source.rs b/crates/turbopack-cli/src/dev/web_entry_source.rs index 76b689cfee08a4..b9e3d3ed4bbd7f 100644 --- a/crates/turbopack-cli/src/dev/web_entry_source.rs +++ b/crates/turbopack-cli/src/dev/web_entry_source.rs @@ -1,46 +1,42 @@ use std::collections::HashMap; use anyhow::{anyhow, Result}; -use turbo_tasks::{TryJoinIterExt, Value}; -use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::{FileSystem, FileSystemPathVc}; +use turbo_tasks::{TryJoinIterExt, Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{FileSystem, FileSystemPath}; use turbopack::{ condition::ContextCondition, - ecmascript::{EcmascriptModuleAssetVc, TransformPluginVc}, - module_options::{ - CustomEcmascriptTransformPlugins, CustomEcmascriptTransformPluginsVc, JsxTransformOptions, - ModuleOptionsContext, ModuleOptionsContextVc, - }, - resolve_options_context::{ResolveOptionsContext, ResolveOptionsContextVc}, - transition::TransitionsByNameVc, - ModuleAssetContextVc, + ecmascript::EcmascriptModuleAsset, + module_options::{CustomEcmascriptTransformPlugins, JsxTransformOptions, ModuleOptionsContext}, + resolve_options_context::ResolveOptionsContext, + ModuleAssetContext, }; -use turbopack_cli_utils::runtime_entry::{RuntimeEntriesVc, RuntimeEntry}; +use turbopack_cli_utils::runtime_entry::{RuntimeEntries, RuntimeEntry}; use turbopack_core::{ - chunk::{ChunkableAssetVc, ChunkingContextVc}, + chunk::{ChunkableAsset, ChunkingContext}, compile_time_defines, - compile_time_info::{CompileTimeDefinesVc, CompileTimeInfo, CompileTimeInfoVc}, - context::AssetContextVc, - environment::{BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment}, + compile_time_info::{CompileTimeDefines, CompileTimeInfo}, + context::AssetContext, + environment::{BrowserEnvironment, Environment, EnvironmentIntention, ExecutionEnvironment}, reference_type::{EntryReferenceSubType, ReferenceType}, resolve::{ - options::{ImportMap, ImportMapVc, ImportMapping}, - origin::PlainResolveOriginVc, - parse::RequestVc, + options::{ImportMap, ImportMapping}, + origin::{PlainResolveOrigin, ResolveOriginExt}, + parse::Request, }, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; -use turbopack_dev::{react_refresh::assert_can_resolve_react_refresh, DevChunkingContextVc}; +use turbopack_dev::{react_refresh::assert_can_resolve_react_refresh, DevChunkingContext}; use turbopack_dev_server::{ - html::DevHtmlAssetVc, - source::{asset_graph::AssetGraphContentSourceVc, ContentSourceVc}, + html::DevHtmlAsset, + source::{asset_graph::AssetGraphContentSource, ContentSource}, }; use turbopack_ecmascript_plugins::transform::{ emotion::{EmotionTransformConfig, EmotionTransformer}, styled_components::{StyledComponentsTransformConfig, StyledComponentsTransformer}, styled_jsx::StyledJsxTransformer, }; -use turbopack_node::execution_context::ExecutionContextVc; +use turbopack_node::execution_context::ExecutionContext; use crate::embed_js::embed_file_path; @@ -49,7 +45,7 @@ async fn foreign_code_context_condition() -> Result { } #[turbo_tasks::function] -pub async fn get_client_import_map(project_path: FileSystemPathVc) -> Result { +pub async fn get_client_import_map(project_path: Vc) -> Result> { let mut import_map = ImportMap::empty(); import_map.insert_singleton_alias("@swc/helpers", project_path); @@ -71,8 +67,8 @@ pub async fn get_client_import_map(project_path: FileSystemPathVc) -> Result Result { + project_path: Vc, +) -> Result> { let next_client_import_map = get_client_import_map(project_path); let module_options_context = ResolveOptionsContext { enable_node_modules: Some(project_path.root().resolve().await?), @@ -96,10 +92,10 @@ async fn get_client_resolve_options_context( #[turbo_tasks::function] async fn get_client_module_options_context( - project_path: FileSystemPathVc, - execution_context: ExecutionContextVc, - env: EnvironmentVc, -) -> Result { + project_path: Vc, + execution_context: Vc, + env: Vc, +) -> Result> { let module_options_context = ModuleOptionsContext { preset_env_versions: Some(env), execution_context: Some(execution_context), @@ -121,17 +117,17 @@ async fn get_client_module_options_context( .cell(), ); - let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell( + let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell( CustomEcmascriptTransformPlugins { source_transforms: vec![ - TransformPluginVc::cell(Box::new( + Vc::cell(Box::new( EmotionTransformer::new(&EmotionTransformConfig::default()) .expect("Should be able to create emotion transformer"), - )), - TransformPluginVc::cell(Box::new(StyledComponentsTransformer::new( + ) as _), + Vc::cell(Box::new(StyledComponentsTransformer::new( &StyledComponentsTransformConfig::default(), - ))), - TransformPluginVc::cell(Box::new(StyledJsxTransformer::new())), + )) as _), + Vc::cell(Box::new(StyledJsxTransformer::new()) as _), ], output_transforms: vec![], }, @@ -155,10 +151,10 @@ async fn get_client_module_options_context( #[turbo_tasks::function] fn get_client_asset_context( - project_path: FileSystemPathVc, - execution_context: ExecutionContextVc, - compile_time_info: CompileTimeInfoVc, -) -> AssetContextVc { + project_path: Vc, + execution_context: Vc, + compile_time_info: Vc, +) -> Vc> { let resolve_options_context = get_client_resolve_options_context(project_path); let module_options_context = get_client_module_options_context( project_path, @@ -166,18 +162,17 @@ fn get_client_asset_context( compile_time_info.environment(), ); - let context: AssetContextVc = ModuleAssetContextVc::new( - TransitionsByNameVc::cell(HashMap::new()), + let context: Vc> = Vc::upcast(ModuleAssetContext::new( + Vc::cell(HashMap::new()), compile_time_info, module_options_context, resolve_options_context, - ) - .into(); + )); context } -pub fn client_defines() -> CompileTimeDefinesVc { +pub fn client_defines() -> Vc { compile_time_defines!( process.turbopack = true, process.env.NODE_ENV = "development", @@ -186,14 +181,14 @@ pub fn client_defines() -> CompileTimeDefinesVc { } #[turbo_tasks::function] -pub fn get_client_compile_time_info(browserslist_query: &str) -> CompileTimeInfoVc { - CompileTimeInfo::builder(EnvironmentVc::new( +pub fn get_client_compile_time_info(browserslist_query: String) -> Vc { + CompileTimeInfo::builder(Environment::new( Value::new(ExecutionEnvironment::Browser( BrowserEnvironment { dom: true, web_worker: false, service_worker: false, - browserslist_query: browserslist_query.to_owned(), + browserslist_query, } .into(), )), @@ -205,15 +200,15 @@ pub fn get_client_compile_time_info(browserslist_query: &str) -> CompileTimeInfo #[turbo_tasks::function] pub fn get_client_chunking_context( - project_path: FileSystemPathVc, - server_root: FileSystemPathVc, - environment: EnvironmentVc, -) -> ChunkingContextVc { - DevChunkingContextVc::builder( + project_path: Vc, + server_root: Vc, + environment: Vc, +) -> Vc> { + DevChunkingContext::builder( project_path, server_root, - server_root.join("/_chunks"), - server_root.join("/_assets"), + server_root.join("/_chunks".to_string()), + server_root.join("/_assets".to_string()), environment, ) .hot_module_replacement() @@ -222,8 +217,8 @@ pub fn get_client_chunking_context( #[turbo_tasks::function] pub async fn get_client_runtime_entries( - project_path: FileSystemPathVc, -) -> Result { + project_path: Vc, +) -> Result> { let resolve_options_context = get_client_resolve_options_context(project_path); let mut runtime_entries = Vec::new(); @@ -236,27 +231,30 @@ pub async fn get_client_runtime_entries( // because the bootstrap contains JSX which requires Refresh's global // functions to be available. if let Some(request) = enable_react_refresh { - runtime_entries.push(RuntimeEntry::Request(request, project_path.join("_")).cell()) + runtime_entries + .push(RuntimeEntry::Request(request, project_path.join("_".to_string())).cell()) }; runtime_entries.push( - RuntimeEntry::Source(SourceAssetVc::new(embed_file_path("entry/bootstrap.ts")).into()) - .cell(), + RuntimeEntry::Source(Vc::upcast(SourceAsset::new(embed_file_path( + "entry/bootstrap.ts".to_string(), + )))) + .cell(), ); - Ok(RuntimeEntriesVc::cell(runtime_entries)) + Ok(Vc::cell(runtime_entries)) } #[turbo_tasks::function] pub async fn create_web_entry_source( - project_path: FileSystemPathVc, - execution_context: ExecutionContextVc, - entry_requests: Vec, - server_root: FileSystemPathVc, - _env: ProcessEnvVc, + project_path: Vc, + execution_context: Vc, + entry_requests: Vec>, + server_root: Vc, + _env: Vc>, eager_compile: bool, - browserslist_query: &str, -) -> Result { + browserslist_query: String, +) -> Result>> { let compile_time_info = get_client_compile_time_info(browserslist_query); let context = get_client_asset_context(project_path, execution_context, compile_time_info); let chunking_context = @@ -265,7 +263,7 @@ pub async fn create_web_entry_source( let runtime_entries = entries.resolve_entries(context); - let origin = PlainResolveOriginVc::new(context, project_path.join("_")).as_resolve_origin(); + let origin = PlainResolveOrigin::new(context, project_path.join("_".to_string())); let entries = entry_requests .into_iter() .map(|request| async move { @@ -284,13 +282,17 @@ pub async fn create_web_entry_source( .into_iter() .flatten() .map(|module| async move { - if let Some(ecmascript) = EcmascriptModuleAssetVc::resolve_from(module).await? { + if let Some(ecmascript) = + Vc::try_resolve_downcast_type::(module).await? + { Ok(( - ecmascript.into(), + Vc::upcast(ecmascript), chunking_context, - Some(runtime_entries.with_entry(ecmascript.into())), + Some(runtime_entries.with_entry(Vc::upcast(ecmascript))), )) - } else if let Some(chunkable) = ChunkableAssetVc::resolve_from(module).await? { + } else if let Some(chunkable) = + Vc::try_resolve_sidecast::>(module).await? + { // TODO this is missing runtime code, so it's probably broken and we should also // add an ecmascript chunk with the runtime code Ok((chunkable, chunking_context, None)) @@ -305,13 +307,15 @@ pub async fn create_web_entry_source( .try_join() .await?; - let entry_asset = DevHtmlAssetVc::new(server_root.join("index.html"), entries).into(); + let entry_asset = Vc::upcast(DevHtmlAsset::new( + server_root.join("index.html".to_string()), + entries, + )); - let graph = if eager_compile { - AssetGraphContentSourceVc::new_eager(server_root, entry_asset) + let graph = Vc::upcast(if eager_compile { + AssetGraphContentSource::new_eager(server_root, entry_asset) } else { - AssetGraphContentSourceVc::new_lazy(server_root, entry_asset) - } - .into(); + AssetGraphContentSource::new_lazy(server_root, entry_asset) + }); Ok(graph) } diff --git a/crates/turbopack-cli/src/embed_js.rs b/crates/turbopack-cli/src/embed_js.rs index 79eaba08dd5b68..793fe320013ae0 100644 --- a/crates/turbopack-cli/src/embed_js.rs +++ b/crates/turbopack-cli/src/embed_js.rs @@ -1,16 +1,17 @@ -use turbo_tasks_fs::{embed_directory, FileContentVc, FileSystem, FileSystemPathVc, FileSystemVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{embed_directory, FileContent, FileSystem, FileSystemPath}; #[turbo_tasks::function] -fn embed_fs() -> FileSystemVc { +fn embed_fs() -> Vc> { embed_directory!("turbopack-cli", "$CARGO_MANIFEST_DIR/js/src") } #[turbo_tasks::function] -pub(crate) fn embed_file(path: &str) -> FileContentVc { +pub(crate) fn embed_file(path: String) -> Vc { embed_fs().root().join(path).read() } #[turbo_tasks::function] -pub(crate) fn embed_file_path(path: &str) -> FileSystemPathVc { +pub(crate) fn embed_file_path(path: String) -> Vc { embed_fs().root().join(path) } diff --git a/crates/turbopack-cli/src/lib.rs b/crates/turbopack-cli/src/lib.rs index 93e5a63c3a38f1..7a7850615803be 100644 --- a/crates/turbopack-cli/src/lib.rs +++ b/crates/turbopack-cli/src/lib.rs @@ -1,5 +1,7 @@ #![feature(future_join)] #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub mod arguments; pub mod dev; diff --git a/crates/turbopack-core/src/asset.rs b/crates/turbopack-core/src/asset.rs index 3abc6b63d54c9b..b75785c906f625 100644 --- a/crates/turbopack-core/src/asset.rs +++ b/crates/turbopack-core/src/asset.rs @@ -1,32 +1,31 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::CompletionVc; +use turbo_tasks::{Completion, Vc}; use turbo_tasks_fs::{ - File, FileContent, FileContentVc, FileJsonContent, FileJsonContentVc, FileLinesContent, - FileLinesContentVc, FileSystemPathVc, LinkContent, LinkType, + FileContent, FileJsonContent, FileLinesContent, FileSystemPath, LinkContent, LinkType, }; use crate::{ - ident::AssetIdentVc, - reference::AssetReferencesVc, - version::{VersionedAssetContentVc, VersionedContentVc}, + ident::AssetIdent, + reference::AssetReferences, + version::{VersionedAssetContent, VersionedContent}, }; /// A list of [Asset]s #[turbo_tasks::value(transparent)] #[derive(Hash)] -pub struct Assets(Vec); +pub struct Assets(Vec>>); /// A set of [Asset]s #[turbo_tasks::value(transparent)] -pub struct AssetsSet(IndexSet); +pub struct AssetsSet(IndexSet>>); #[turbo_tasks::value_impl] -impl AssetsVc { +impl Assets { /// Creates an empty list of [Asset]s #[turbo_tasks::function] - pub fn empty() -> Self { - AssetsVc::cell(Vec::new()) + pub fn empty() -> Vc { + Vc::cell(Vec::new()) } } @@ -35,58 +34,45 @@ impl AssetsVc { pub trait Asset { /// The identifier of the [Asset]. It's expected to be unique and capture /// all properties of the [Asset]. - fn ident(&self) -> AssetIdentVc; + fn ident(self: Vc) -> Vc; /// The content of the [Asset]. - fn content(&self) -> AssetContentVc; + fn content(self: Vc) -> Vc; /// Other things (most likely [Asset]s) referenced from this [Asset]. - fn references(&self) -> AssetReferencesVc { - AssetReferencesVc::empty() + fn references(self: Vc) -> Vc { + AssetReferences::empty() } /// The content of the [Asset] alongside its version. - async fn versioned_content(&self) -> Result { - Ok(VersionedAssetContentVc::new(self.content()).into()) + async fn versioned_content(self: Vc) -> Result>> { + Ok(Vc::upcast(VersionedAssetContent::new(self.content()))) } } /// An optional [Asset] #[turbo_tasks::value(shared, transparent)] -pub struct AssetOption(Option); +pub struct AssetOption(Option>>); #[turbo_tasks::value(shared)] #[derive(Clone)] pub enum AssetContent { - File(FileContentVc), + File(Vc), // for the relative link, the target is raw value read from the link // for the absolute link, the target is stripped of the root path while reading // See [LinkContent::Link] for more details. Redirect { target: String, link_type: LinkType }, } -impl From for AssetContentVc { - fn from(content: FileContentVc) -> Self { - AssetContent::File(content).cell() - } -} - -impl From for AssetContentVc { - fn from(content: FileContent) -> Self { - AssetContent::File(content.cell()).cell() - } -} - -impl From for AssetContentVc { - fn from(file: File) -> Self { - AssetContent::File(file.into()).cell() +#[turbo_tasks::value_impl] +impl AssetContent { + #[turbo_tasks::function] + pub fn file(file: Vc) -> Vc { + AssetContent::File(file).cell() } -} -#[turbo_tasks::value_impl] -impl AssetContentVc { #[turbo_tasks::function] - pub async fn parse_json(self) -> Result { + pub async fn parse_json(self: Vc) -> Result> { let this = self.await?; match &*this { AssetContent::File(content) => Ok(content.parse_json()), @@ -97,7 +83,7 @@ impl AssetContentVc { } #[turbo_tasks::function] - pub async fn file_content(self) -> Result { + pub async fn file_content(self: Vc) -> Result> { let this = self.await?; match &*this { AssetContent::File(content) => Ok(*content), @@ -106,7 +92,7 @@ impl AssetContentVc { } #[turbo_tasks::function] - pub async fn lines(self) -> Result { + pub async fn lines(self: Vc) -> Result> { let this = self.await?; match &*this { AssetContent::File(content) => Ok(content.lines()), @@ -115,7 +101,7 @@ impl AssetContentVc { } #[turbo_tasks::function] - pub async fn parse_json_with_comments(self) -> Result { + pub async fn parse_json_with_comments(self: Vc) -> Result> { let this = self.await?; match &*this { AssetContent::File(content) => Ok(content.parse_json_with_comments()), @@ -126,7 +112,7 @@ impl AssetContentVc { } #[turbo_tasks::function] - pub async fn write(self, path: FileSystemPathVc) -> Result { + pub async fn write(self: Vc, path: Vc) -> Result> { let this = self.await?; Ok(match &*this { AssetContent::File(file) => path.write(*file), diff --git a/crates/turbopack-core/src/changed.rs b/crates/turbopack-core/src/changed.rs index e640f35de26315..785c6125961e36 100644 --- a/crates/turbopack-core/src/changed.rs +++ b/crates/turbopack-core/src/changed.rs @@ -1,15 +1,14 @@ use anyhow::Result; use turbo_tasks::{ graph::{GraphTraversal, NonDeterministic}, - CompletionVc, CompletionsVc, + Completion, Completions, Vc, }; -use crate::{ - asset::{Asset, AssetVc}, - reference::all_referenced_assets, -}; +use crate::{asset::Asset, reference::all_referenced_assets}; -async fn get_referenced_assets(parent: AssetVc) -> Result + Send> { +async fn get_referenced_assets( + parent: Vc>, +) -> Result>> + Send> { Ok(all_referenced_assets(parent) .await? .clone_value() @@ -19,7 +18,7 @@ async fn get_referenced_assets(parent: AssetVc) -> Result Result { +pub async fn any_content_changed(root: Vc>) -> Result> { let completions = NonDeterministic::new() .skip_duplicates() .visit([root], get_referenced_assets) @@ -30,14 +29,14 @@ pub async fn any_content_changed(root: AssetVc) -> Result { .map(content_changed) .collect(); - Ok(CompletionsVc::cell(completions).completed()) + Ok(Vc::::cell(completions).completed()) } /// Returns a completion that changes when the content of the given asset /// changes. #[turbo_tasks::function] -pub async fn content_changed(asset: AssetVc) -> Result { +pub async fn content_changed(asset: Vc>) -> Result> { // Reading the file content is enough to add as dependency asset.content().file_content().await?; - Ok(CompletionVc::new()) + Ok(Completion::new()) } diff --git a/crates/turbopack-core/src/chunk/availability_info.rs b/crates/turbopack-core/src/chunk/availability_info.rs index d0eed8999c3cfd..e073f2072874b6 100644 --- a/crates/turbopack-core/src/chunk/availability_info.rs +++ b/crates/turbopack-core/src/chunk/availability_info.rs @@ -1,21 +1,23 @@ -use super::available_assets::AvailableAssetsVc; -use crate::asset::AssetVc; +use turbo_tasks::Vc; + +use super::available_assets::AvailableAssets; +use crate::asset::Asset; #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(PartialOrd, Ord, Hash, Clone, Copy, Debug)] pub enum AvailabilityInfo { Untracked, Root { - current_availability_root: AssetVc, + current_availability_root: Vc>, }, Inner { - available_assets: AvailableAssetsVc, - current_availability_root: AssetVc, + available_assets: Vc, + current_availability_root: Vc>, }, } impl AvailabilityInfo { - pub fn current_availability_root(&self) -> Option { + pub fn current_availability_root(&self) -> Option>> { match self { Self::Untracked => None, Self::Root { @@ -28,7 +30,7 @@ impl AvailabilityInfo { } } - pub fn available_assets(&self) -> Option { + pub fn available_assets(&self) -> Option> { match self { Self::Untracked => None, Self::Root { .. } => None, diff --git a/crates/turbopack-core/src/chunk/available_assets.rs b/crates/turbopack-core/src/chunk/available_assets.rs index 624ddbe17a9978..1a3b8a7ff6ecfe 100644 --- a/crates/turbopack-core/src/chunk/available_assets.rs +++ b/crates/turbopack-core/src/chunk/available_assets.rs @@ -1,16 +1,15 @@ -use std::iter::once; +use std::{iter::once, marker::PhantomData}; use anyhow::Result; use turbo_tasks::{ graph::{GraphTraversal, ReverseTopological}, - primitives::{BoolVc, U64Vc}, - TryJoinIterExt, ValueToString, + TryJoinIterExt, ValueToString, Vc, }; use turbo_tasks_hash::Xxh3Hash64Hasher; -use super::{ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingType}; +use super::{ChunkableAssetReference, ChunkingType}; use crate::{ - asset::{Asset, AssetVc, AssetsSetVc}, + asset::{Asset, AssetsSet}, reference::AssetReference, }; @@ -19,24 +18,27 @@ use crate::{ /// `include` queries. #[turbo_tasks::value] pub struct AvailableAssets { - parent: Option, - roots: Vec, + parent: Option>, + roots: Vec>>, } #[turbo_tasks::value_impl] -impl AvailableAssetsVc { +impl AvailableAssets { #[turbo_tasks::function] - fn new_normalized(parent: Option, roots: Vec) -> Self { + fn new_normalized( + parent: Option>, + roots: Vec>>, + ) -> Vc { AvailableAssets { parent, roots }.cell() } #[turbo_tasks::function] - pub fn new(roots: Vec) -> Self { + pub fn new(roots: Vec>>) -> Vc { Self::new_normalized(None, roots) } #[turbo_tasks::function] - pub async fn with_roots(self, roots: Vec) -> Result { + pub async fn with_roots(self: Vc, roots: Vec>>) -> Result> { let roots = roots .into_iter() .map(|root| async move { Ok((self.includes(root).await?, root)) }) @@ -49,7 +51,7 @@ impl AvailableAssetsVc { } #[turbo_tasks::function] - pub async fn hash(self) -> Result { + pub async fn hash(self: Vc) -> Result> { let this = self.await?; let mut hasher = Xxh3Hash64Hasher::new(); if let Some(parent) = this.parent { @@ -60,34 +62,52 @@ impl AvailableAssetsVc { for root in &this.roots { hasher.write_value(root.ident().to_string().await?); } - Ok(U64Vc::cell(hasher.finish())) + Ok(Vc::cell(hasher.finish())) } #[turbo_tasks::function] - pub async fn includes(self, asset: AssetVc) -> Result { + pub async fn includes(self: Vc, asset: Vc>) -> Result> { let this = self.await?; if let Some(parent) = this.parent { if *parent.includes(asset).await? { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } for root in this.roots.iter() { if chunkable_assets_set(*root).await?.contains(&asset) { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } - Ok(BoolVc::cell(false)) + Ok(Vc::cell(false)) } } +trait What {} + +struct OkWhat; + +impl What for OkWhat {} + +struct Ptr +where + T: ?Sized, +{ + _t: PhantomData, +} + +unsafe impl Send for Ptr where T: ?Sized {} +unsafe impl Sync for Ptr where T: ?Sized {} + #[turbo_tasks::function] -async fn chunkable_assets_set(root: AssetVc) -> Result { +async fn chunkable_assets_set(root: Vc>) -> Result> { let assets = ReverseTopological::new() .skip_duplicates() - .visit(once(root), |&asset: &AssetVc| async move { + .visit(once(root), |&asset: &Vc>| async move { let mut results = Vec::new(); for reference in asset.references().await?.iter() { - if let Some(chunkable) = ChunkableAssetReferenceVc::resolve_from(reference).await? { + if let Some(chunkable) = + Vc::try_resolve_downcast::>(*reference).await? + { if matches!( &*chunkable.chunking_type().await?, Some( @@ -111,5 +131,5 @@ async fn chunkable_assets_set(root: AssetVc) -> Result { }) .await .completed()?; - Ok(AssetsSetVc::cell(assets.into_inner().into_iter().collect())) + Ok(Vc::cell(assets.into_inner().into_iter().collect())) } diff --git a/crates/turbopack-core/src/chunk/chunking_context.rs b/crates/turbopack-core/src/chunk/chunking_context.rs index 4eb5de3bca4575..a68215f4c02f30 100644 --- a/crates/turbopack-core/src/chunk/chunking_context.rs +++ b/crates/turbopack-core/src/chunk/chunking_context.rs @@ -1,59 +1,60 @@ -use std::fmt::Debug; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; -use anyhow::Result; -use turbo_tasks::primitives::{BoolVc, StringVc}; -use turbo_tasks_fs::FileSystemPathVc; - -use super::{ChunkVc, EvaluatableAssetsVc}; +use super::{Chunk, EvaluatableAssets}; use crate::{ - asset::{AssetVc, AssetsVc}, - environment::EnvironmentVc, - ident::AssetIdentVc, + asset::{Asset, Assets}, + environment::Environment, + ident::AssetIdent, }; /// A context for the chunking that influences the way chunks are created #[turbo_tasks::value_trait] pub trait ChunkingContext { - fn context_path(&self) -> FileSystemPathVc; - fn output_root(&self) -> FileSystemPathVc; + fn context_path(self: Vc) -> Vc; + fn output_root(self: Vc) -> Vc; // TODO remove this, a chunking context should not be bound to a specific // environment since this can change due to transitions in the module graph - fn environment(&self) -> EnvironmentVc; + fn environment(self: Vc) -> Vc; // TODO(alexkirsz) Remove this from the chunking context. This should be at the // discretion of chunking context implementors. However, we currently use this // in a couple of places in `turbopack-css`, so we need to remove that // dependency first. - fn chunk_path(&self, ident: AssetIdentVc, extension: &str) -> FileSystemPathVc; + fn chunk_path(self: Vc, ident: Vc, extension: String) -> Vc; // TODO(alexkirsz) Remove this from the chunking context. /// Reference Source Map Assets for chunks - fn reference_chunk_source_maps(&self, chunk: AssetVc) -> BoolVc; + fn reference_chunk_source_maps(self: Vc, chunk: Vc>) -> Vc; - fn can_be_in_same_chunk(&self, asset_a: AssetVc, asset_b: AssetVc) -> BoolVc; + fn can_be_in_same_chunk( + self: Vc, + asset_a: Vc>, + asset_b: Vc>, + ) -> Vc; fn asset_path( - &self, - content_hash: &str, - original_asset_ident: AssetIdentVc, - ) -> FileSystemPathVc; + self: Vc, + content_hash: String, + original_asset_ident: Vc, + ) -> Vc; - fn is_hot_module_replacement_enabled(&self) -> BoolVc { - BoolVc::cell(false) + fn is_hot_module_replacement_enabled(self: Vc) -> Vc { + Vc::cell(false) } - fn layer(&self) -> StringVc { - StringVc::cell("".to_string()) + fn layer(self: Vc) -> Vc { + Vc::cell("".to_string()) } - fn with_layer(&self, layer: &str) -> ChunkingContextVc; + fn with_layer(self: Vc, layer: String) -> Vc>; - fn chunk_group(&self, entry: ChunkVc) -> AssetsVc; + fn chunk_group(self: Vc, entry: Vc>) -> Vc; fn evaluated_chunk_group( - &self, - entry: ChunkVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> AssetsVc; + self: Vc, + entry: Vc>, + evaluatable_assets: Vc, + ) -> Vc; } diff --git a/crates/turbopack-core/src/chunk/data.rs b/crates/turbopack-core/src/chunk/data.rs index 9ff473c4369e9b..b740faba7612aa 100644 --- a/crates/turbopack-core/src/chunk/data.rs +++ b/crates/turbopack-core/src/chunk/data.rs @@ -1,61 +1,61 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::FileSystemPath; use crate::{ - asset::{Asset, AssetVc, AssetsVc}, - chunk::{ModuleIdReadRef, OutputChunk, OutputChunkRuntimeInfo, OutputChunkVc}, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, + asset::{Asset, Assets}, + chunk::{ModuleId, OutputChunk, OutputChunkRuntimeInfo}, + reference::{AssetReferences, SingleAssetReference}, }; #[turbo_tasks::value] pub struct ChunkData { pub path: String, - pub included: Vec, - pub excluded: Vec, + pub included: Vec>, + pub excluded: Vec>, pub module_chunks: Vec, - pub references: AssetReferencesVc, + pub references: Vc, } #[turbo_tasks::value(transparent)] -pub struct ChunkDataOption(Option); +pub struct ChunkDataOption(Option>); // NOTE(alexkirsz) Our convention for naming vector types is to add an "s" to // the end of the type name, but in this case it would be both gramatically // incorrect and clash with the variable names everywhere. // TODO(WEB-101) Should fix this. #[turbo_tasks::value(transparent)] -pub struct ChunksData(Vec); +pub struct ChunksData(Vec>); #[turbo_tasks::function] -fn module_chunk_reference_description() -> StringVc { - StringVc::cell("module chunk".to_string()) +fn module_chunk_reference_description() -> Vc { + Vc::cell("module chunk".to_string()) } #[turbo_tasks::value_impl] -impl ChunkDataVc { +impl ChunkData { #[turbo_tasks::function] pub async fn from_asset( - output_root: FileSystemPathVc, - chunk: AssetVc, - ) -> Result { + output_root: Vc, + chunk: Vc>, + ) -> Result> { let output_root = output_root.await?; let path = chunk.ident().path().await?; // The "path" in this case is the chunk's path, not the chunk item's path. // The difference is a chunk is a file served by the dev server, and an // item is one of several that are contained in that chunk file. let Some(path) = output_root.get_path_to(&path) else { - return Ok(ChunkDataOptionVc::cell(None)); + return Ok(Vc::cell(None)); }; let path = path.to_string(); - let Some(output_chunk) = OutputChunkVc::resolve_from(chunk).await? else { - return Ok(ChunkDataOptionVc::cell(Some(ChunkData { + let Some(output_chunk) = Vc::try_resolve_sidecast::>(chunk).await? else { + return Ok(Vc::cell(Some(ChunkData { path, included: Vec::new(), excluded: Vec::new(), module_chunks: Vec::new(), - references: AssetReferencesVc::empty(), + references: AssetReferences::empty(), }.cell()))); }; @@ -91,11 +91,10 @@ impl ChunkDataVc { Ok(output_root.get_path_to(&chunk_path).map(|path| { ( path.to_owned(), - SingleAssetReferenceVc::new( + Vc::upcast(SingleAssetReference::new( chunk, module_chunk_reference_description(), - ) - .as_asset_reference(), + )), ) })) } @@ -109,13 +108,13 @@ impl ChunkDataVc { (Vec::new(), Vec::new()) }; - Ok(ChunkDataOptionVc::cell(Some( + Ok(Vc::cell(Some( ChunkData { path, included, excluded, module_chunks, - references: AssetReferencesVc::cell(module_chunks_references), + references: Vc::cell(module_chunks_references), } .cell(), ))) @@ -123,14 +122,14 @@ impl ChunkDataVc { #[turbo_tasks::function] pub async fn from_assets( - output_root: FileSystemPathVc, - chunks: AssetsVc, - ) -> Result { - Ok(ChunksDataVc::cell( + output_root: Vc, + chunks: Vc, + ) -> Result> { + Ok(Vc::cell( chunks .await? .iter() - .map(|&chunk| ChunkDataVc::from_asset(output_root, chunk)) + .map(|&chunk| ChunkData::from_asset(output_root, chunk)) .try_join() .await? .into_iter() @@ -142,7 +141,7 @@ impl ChunkDataVc { /// Returns [`AssetReferences`] to the assets that this chunk data /// references. #[turbo_tasks::function] - pub async fn references(self) -> Result { + pub async fn references(self: Vc) -> Result> { Ok(self.await?.references) } } diff --git a/crates/turbopack-core/src/chunk/evaluate.rs b/crates/turbopack-core/src/chunk/evaluate.rs index aa16ab1836655d..189809cbe5eb90 100644 --- a/crates/turbopack-core/src/chunk/evaluate.rs +++ b/crates/turbopack-core/src/chunk/evaluate.rs @@ -1,10 +1,10 @@ use anyhow::{bail, Result}; -use turbo_tasks::{Value, ValueToString}; +use turbo_tasks::{Upcast, Value, ValueToString, Vc}; -use super::{ChunkableAsset, ChunkableAssetVc}; +use super::ChunkableAsset; use crate::{ - asset::{Asset, AssetVc}, - context::{AssetContext, AssetContextVc}, + asset::Asset, + context::AssetContext, reference_type::{EntryReferenceSubType, ReferenceType}, }; @@ -15,38 +15,60 @@ use crate::{ #[turbo_tasks::value_trait] pub trait EvaluatableAsset: Asset + ChunkableAsset {} -#[turbo_tasks::value_impl] -impl EvaluatableAssetVc { - #[turbo_tasks::function] - pub async fn from_asset(asset: AssetVc, context: AssetContextVc) -> Result { - let asset = context.process( - asset, - Value::new(ReferenceType::Entry(EntryReferenceSubType::Runtime)), - ); - let Some(entry) = EvaluatableAssetVc::resolve_from(asset).await? else { - bail!("{} is not a valid evaluated entry", asset.ident().to_string().await?) - }; - Ok(entry) +pub trait EvaluatableAssetExt { + fn to_evaluatable( + self: Vc, + context: Vc>, + ) -> Vc>; +} + +impl EvaluatableAssetExt for T +where + T: Upcast>, +{ + fn to_evaluatable( + self: Vc, + context: Vc>, + ) -> Vc> { + to_evaluatable(Vc::upcast(self), context) } } +#[turbo_tasks::function] +async fn to_evaluatable( + asset: Vc>, + context: Vc>, +) -> Result>> { + let asset = context.process( + asset, + Value::new(ReferenceType::Entry(EntryReferenceSubType::Runtime)), + ); + let Some(entry) = Vc::try_resolve_downcast::>(asset).await? else { + bail!("{} is not a valid evaluated entry", asset.ident().to_string().await?) + }; + Ok(entry) +} + #[turbo_tasks::value(transparent)] -pub struct EvaluatableAssets(Vec); +pub struct EvaluatableAssets(Vec>>); #[turbo_tasks::value_impl] -impl EvaluatableAssetsVc { +impl EvaluatableAssets { #[turbo_tasks::function] - pub fn empty() -> EvaluatableAssetsVc { + pub fn empty() -> Vc { EvaluatableAssets(vec![]).cell() } #[turbo_tasks::function] - pub fn one(entry: EvaluatableAssetVc) -> EvaluatableAssetsVc { + pub fn one(entry: Vc>) -> Vc { EvaluatableAssets(vec![entry]).cell() } #[turbo_tasks::function] - pub async fn with_entry(self, entry: EvaluatableAssetVc) -> Result { + pub async fn with_entry( + self: Vc, + entry: Vc>, + ) -> Result> { let mut entries = self.await?.clone_value(); entries.push(entry); Ok(EvaluatableAssets(entries).cell()) diff --git a/crates/turbopack-core/src/chunk/mod.rs b/crates/turbopack-core/src/chunk/mod.rs index 4b1fd67df36c32..534b5d2802d1e8 100644 --- a/crates/turbopack-core/src/chunk/mod.rs +++ b/crates/turbopack-core/src/chunk/mod.rs @@ -20,24 +20,23 @@ use tracing::{info_span, Span}; use turbo_tasks::{ debug::ValueDebugFormat, graph::{GraphTraversal, GraphTraversalResult, ReverseTopological, Visit, VisitControlFlow}, - primitives::{StringReadRef, StringVc}, trace::TraceRawVcs, - TryJoinIterExt, Value, ValueToString, ValueToStringVc, + ReadRef, TryJoinIterExt, Value, ValueToString, Vc, }; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::FileSystemPath; use turbo_tasks_hash::DeterministicHash; use self::availability_info::AvailabilityInfo; pub use self::{ - chunking_context::{ChunkingContext, ChunkingContextVc}, - data::{ChunkData, ChunkDataOption, ChunkDataOptionVc, ChunkDataVc, ChunksData, ChunksDataVc}, - evaluate::{EvaluatableAsset, EvaluatableAssetVc, EvaluatableAssets, EvaluatableAssetsVc}, + chunking_context::ChunkingContext, + data::{ChunkData, ChunkDataOption, ChunksData}, + evaluate::{EvaluatableAsset, EvaluatableAssetExt, EvaluatableAssets}, }; use crate::{ - asset::{Asset, AssetVc, AssetsVc}, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, - resolve::{PrimaryResolveResult, ResolveResult, ResolveResultVc}, + asset::{Asset, Assets}, + ident::AssetIdent, + reference::{AssetReference, AssetReferences}, + resolve::{PrimaryResolveResult, ResolveResult}, }; /// A module id, which can be a number or string @@ -61,8 +60,8 @@ impl Display for ModuleId { #[turbo_tasks::value_impl] impl ValueToString for ModuleId { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.to_string()) + fn to_string(&self) -> Vc { + Vc::cell(self.to_string()) } } @@ -77,36 +76,36 @@ impl ModuleId { /// A list of module ids. #[turbo_tasks::value(transparent, shared)] -pub struct ModuleIds(Vec); +pub struct ModuleIds(Vec>); /// An [Asset] that can be converted into a [Chunk]. #[turbo_tasks::value_trait] pub trait ChunkableAsset: Asset { fn as_chunk( - &self, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc; + ) -> Vc>; - fn as_root_chunk(self_vc: ChunkableAssetVc, context: ChunkingContextVc) -> ChunkVc { - self_vc.as_chunk( + fn as_root_chunk(self: Vc, context: Vc>) -> Vc> { + self.as_chunk( context, Value::new(AvailabilityInfo::Root { - current_availability_root: self_vc.into(), + current_availability_root: Vc::upcast(self), }), ) } } #[turbo_tasks::value(transparent)] -pub struct Chunks(Vec); +pub struct Chunks(Vec>>); #[turbo_tasks::value_impl] -impl ChunksVc { - /// Creates a new empty [ChunksVc]. +impl Chunks { + /// Creates a new empty [Vc]. #[turbo_tasks::function] - pub fn empty() -> ChunksVc { - Self::cell(vec![]) + pub fn empty() -> Vc { + Vc::cell(vec![]) } } @@ -114,18 +113,18 @@ impl ChunksVc { /// It usually contains multiple chunk items. #[turbo_tasks::value_trait] pub trait Chunk: Asset { - fn chunking_context(&self) -> ChunkingContextVc; + fn chunking_context(self: Vc) -> Vc>; // TODO Once output assets have their own trait, this path() method will move // into that trait and ident() will be removed from that. Assets on the // output-level only have a path and no complex ident. /// The path of the chunk. - fn path(&self) -> FileSystemPathVc { + fn path(self: Vc) -> Vc { self.ident().path() } /// Returns a list of chunks that should be loaded in parallel to this /// chunk. - fn parallel_chunks(&self) -> ChunksVc { - ChunksVc::empty() + fn parallel_chunks(self: Vc) -> Vc { + Chunks::empty() } } @@ -134,18 +133,18 @@ pub trait Chunk: Asset { #[turbo_tasks::value(shared)] #[derive(Default)] pub struct OutputChunkRuntimeInfo { - pub included_ids: Option, - pub excluded_ids: Option, + pub included_ids: Option>, + pub excluded_ids: Option>, /// List of paths of chunks containing individual modules that are part of /// this chunk. This is useful for selectively loading modules from a chunk /// without loading the whole chunk. - pub module_chunks: Option, + pub module_chunks: Option>, pub placeholder_for_future_extensions: (), } #[turbo_tasks::value_trait] pub trait OutputChunk: Asset { - fn runtime_info(&self) -> OutputChunkRuntimeInfoVc; + fn runtime_info(self: Vc) -> Vc; } /// Specifies how a chunk interacts with other chunks when building a chunk @@ -187,22 +186,25 @@ pub struct ChunkingTypeOption(Option); /// specific interface is implemented. #[turbo_tasks::value_trait] pub trait ChunkableAssetReference: AssetReference + ValueToString { - fn chunking_type(&self) -> ChunkingTypeOptionVc { - ChunkingTypeOptionVc::cell(Some(ChunkingType::default())) + fn chunking_type(self: Vc) -> Vc { + Vc::cell(Some(ChunkingType::default())) } } /// A reference to multiple chunks from a [ChunkGroup] #[turbo_tasks::value] pub struct ChunkGroupReference { - chunking_context: ChunkingContextVc, - entry: ChunkVc, + chunking_context: Vc>, + entry: Vc>, } #[turbo_tasks::value_impl] -impl ChunkGroupReferenceVc { +impl ChunkGroupReference { #[turbo_tasks::function] - pub fn new(chunking_context: ChunkingContextVc, entry: ChunkVc) -> Self { + pub fn new( + chunking_context: Vc>, + entry: Vc>, + ) -> Vc { Self::cell(ChunkGroupReference { chunking_context, entry, @@ -210,7 +212,7 @@ impl ChunkGroupReferenceVc { } #[turbo_tasks::function] - async fn chunks(self) -> Result { + async fn chunks(self: Vc) -> Result> { let this = self.await?; Ok(this.chunking_context.chunk_group(this.entry)) } @@ -219,8 +221,8 @@ impl ChunkGroupReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for ChunkGroupReference { #[turbo_tasks::function] - async fn resolve_reference(self_vc: ChunkGroupReferenceVc) -> Result { - let set = self_vc.chunks().await?.clone_value(); + async fn resolve_reference(self: Vc) -> Result> { + let set = self.chunks().await?.clone_value(); Ok(ResolveResult::assets(set).into()) } } @@ -228,8 +230,8 @@ impl AssetReference for ChunkGroupReference { #[turbo_tasks::value_impl] impl ValueToString for ChunkGroupReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "chunk group ({})", self.entry.ident().to_string().await? ))) @@ -238,30 +240,33 @@ impl ValueToString for ChunkGroupReference { pub struct ChunkContentResult { pub chunk_items: Vec, - pub chunks: Vec, - pub async_chunk_group_entries: Vec, - pub external_asset_references: Vec, + pub chunks: Vec>>, + pub async_chunk_group_entries: Vec>>, + pub external_asset_references: Vec>>, pub availability_info: AvailabilityInfo, } #[async_trait::async_trait] -pub trait FromChunkableAsset: ChunkItem + Sized + Debug { - async fn from_asset(context: ChunkingContextVc, asset: AssetVc) -> Result>; +pub trait FromChunkableAsset: ChunkItem { + async fn from_asset( + context: Vc>, + asset: Vc>, + ) -> Result>>; async fn from_async_asset( - context: ChunkingContextVc, - asset: ChunkableAssetVc, + context: Vc>, + asset: Vc>, availability_info: Value, - ) -> Result>; + ) -> Result>>; } pub async fn chunk_content_split( - context: ChunkingContextVc, - entry: AssetVc, - additional_entries: Option, + context: Vc>, + entry: Vc>, + additional_entries: Option>, availability_info: Value, -) -> Result> +) -> Result>> where - I: FromChunkableAsset + Eq + std::hash::Hash + Clone, + I: FromChunkableAsset, { chunk_content_internal_parallel(context, entry, additional_entries, availability_info, true) .await @@ -269,13 +274,13 @@ where } pub async fn chunk_content( - context: ChunkingContextVc, - entry: AssetVc, - additional_entries: Option, + context: Vc>, + entry: Vc>, + additional_entries: Option>, availability_info: Value, -) -> Result>> +) -> Result>>> where - I: FromChunkableAsset + Eq + std::hash::Hash + Clone, + I: FromChunkableAsset, { chunk_content_internal_parallel(context, entry, additional_entries, availability_info, false) .await @@ -284,33 +289,38 @@ where #[derive(Eq, PartialEq, Clone, Hash)] enum ChunkContentGraphNode { // Chunk items that are placed into the current chunk - ChunkItem { item: I, ident: StringReadRef }, + ChunkItem { item: I, ident: ReadRef }, // Asset that is already available and doesn't need to be included - AvailableAsset(AssetVc), + AvailableAsset(Vc>), // Chunks that are loaded in parallel to the current chunk - Chunk(ChunkVc), + Chunk(Vc>), // Chunk groups that are referenced from the current chunk, but // not loaded in parallel - AsyncChunkGroup { entry: ChunkVc }, - ExternalAssetReference(AssetReferenceVc), + AsyncChunkGroup { entry: Vc> }, + ExternalAssetReference(Vc>), } #[derive(Clone, Copy)] struct ChunkContentContext { - chunking_context: ChunkingContextVc, - entry: AssetVc, + chunking_context: Vc>, + entry: Vc>, availability_info: Value, split: bool, } async fn reference_to_graph_nodes( context: ChunkContentContext, - reference: AssetReferenceVc, -) -> Result, ChunkContentGraphNode)>> + reference: Vc>, +) -> Result< + Vec<( + Option<(Vc>, ChunkingType)>, + ChunkContentGraphNode>, + )>, +> where - I: FromChunkableAsset + Eq + std::hash::Hash + Clone, + I: FromChunkableAsset, { - let Some(chunkable_asset_reference) = ChunkableAssetReferenceVc::resolve_from(reference).await? else { + let Some(chunkable_asset_reference) = Vc::try_resolve_downcast::>(reference).await? else { return Ok(vec![(None, ChunkContentGraphNode::ExternalAssetReference(reference))]); }; @@ -342,15 +352,16 @@ where } } - let chunkable_asset = match ChunkableAssetVc::resolve_from(asset).await? { - Some(chunkable_asset) => chunkable_asset, - _ => { - return Ok(vec![( - None, - ChunkContentGraphNode::ExternalAssetReference(reference), - )]); - } - }; + let chunkable_asset = + match Vc::try_resolve_sidecast::>(asset).await? { + Some(chunkable_asset) => chunkable_asset, + _ => { + return Ok(vec![( + None, + ChunkContentGraphNode::ExternalAssetReference(reference), + )]); + } + }; match chunking_type { ChunkingType::Placed => { @@ -458,28 +469,38 @@ const MAX_CHUNK_ITEMS_COUNT: usize = 5000; struct ChunkContentVisit { context: ChunkContentContext, chunk_items_count: usize, - processed_assets: HashSet<(ChunkingType, AssetVc)>, + processed_assets: HashSet<(ChunkingType, Vc>)>, _phantom: PhantomData, } -type ChunkItemToGraphNodesEdges = - impl Iterator, ChunkContentGraphNode)>; +type ChunkItemToGraphNodesEdges = impl Iterator< + Item = ( + Option<(Vc>, ChunkingType)>, + ChunkContentGraphNode>, + ), +>; -type ChunkItemToGraphNodesFuture = +type ChunkItemToGraphNodesFuture = impl Future>>; -impl Visit, ()> for ChunkContentVisit +impl Visit>, ()> for ChunkContentVisit> where - I: FromChunkableAsset + Eq + std::hash::Hash + Clone, + I: FromChunkableAsset, { - type Edge = (Option<(AssetVc, ChunkingType)>, ChunkContentGraphNode); + type Edge = ( + Option<(Vc>, ChunkingType)>, + ChunkContentGraphNode>, + ); type EdgesIntoIter = ChunkItemToGraphNodesEdges; type EdgesFuture = ChunkItemToGraphNodesFuture; fn visit( &mut self, - (option_key, node): (Option<(AssetVc, ChunkingType)>, ChunkContentGraphNode), - ) -> VisitControlFlow, ()> { + (option_key, node): ( + Option<(Vc>, ChunkingType)>, + ChunkContentGraphNode>, + ), + ) -> VisitControlFlow>, ()> { let Some((asset, chunking_type)) = option_key else { return VisitControlFlow::Continue(node); }; @@ -503,12 +524,12 @@ where VisitControlFlow::Continue(node) } - fn edges(&mut self, node: &ChunkContentGraphNode) -> Self::EdgesFuture { + fn edges(&mut self, node: &ChunkContentGraphNode>) -> Self::EdgesFuture { let chunk_item = if let ChunkContentGraphNode::ChunkItem { item: chunk_item, .. } = node { - Some(chunk_item.clone()) + Some(*chunk_item) } else { None }; @@ -520,9 +541,9 @@ where return Ok(vec![].into_iter().flatten()); }; - Ok(chunk_item - .references() - .await? + let references = chunk_item.references().await?; + + Ok(references .into_iter() .map(|reference| reference_to_graph_nodes::(context, *reference)) .try_join() @@ -532,7 +553,7 @@ where } } - fn span(&mut self, node: &ChunkContentGraphNode) -> Span { + fn span(&mut self, node: &ChunkContentGraphNode>) -> Span { if let ChunkContentGraphNode::ChunkItem { ident, .. } = node { info_span!("module", name = display(ident)) } else { @@ -542,14 +563,14 @@ where } async fn chunk_content_internal_parallel( - chunking_context: ChunkingContextVc, - entry: AssetVc, - additional_entries: Option, + chunking_context: Vc>, + entry: Vc>, + additional_entries: Option>, availability_info: Value, split: bool, -) -> Result>> +) -> Result>>> where - I: FromChunkableAsset + Eq + std::hash::Hash + Clone, + I: FromChunkableAsset, { let additional_entries = if let Some(additional_entries) = additional_entries { additional_entries.await?.clone_value().into_iter() @@ -629,13 +650,13 @@ pub trait ChunkItem { /// The [AssetIdent] of the [Asset] that this [ChunkItem] was created from. /// For most chunk types this must uniquely identify the asset as it's the /// source of the module id used at runtime. - fn asset_ident(&self) -> AssetIdentVc; + fn asset_ident(self: Vc) -> Vc; /// A [ChunkItem] can describe different `references` than its original /// [Asset]. /// TODO(alexkirsz) This should have a default impl that returns empty /// references. - fn references(&self) -> AssetReferencesVc; + fn references(self: Vc) -> Vc; } #[turbo_tasks::value(transparent)] -pub struct ChunkItems(Vec); +pub struct ChunkItems(Vec>>); diff --git a/crates/turbopack-core/src/chunk/optimize.rs b/crates/turbopack-core/src/chunk/optimize.rs index fd5a242cb14a9f..d216b25174bb0d 100644 --- a/crates/turbopack-core/src/chunk/optimize.rs +++ b/crates/turbopack-core/src/chunk/optimize.rs @@ -4,16 +4,16 @@ //! their size and eliminating duplicates between them. use anyhow::Result; -use turbo_tasks::TryJoinIterExt; -use turbo_tasks_fs::{FileSystemPathOptionVc, FileSystemPathVc}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbo_tasks_fs::{FileSystemPath, FileSystemPathOption}; use crate::chunk::containment_tree::{ContainmentTree, ContainmentTreeKey}; #[derive(Debug, Clone, Eq, PartialEq, Hash)] -struct FileSystemPathKey(FileSystemPathVc); +struct FileSystemPathKey(Vc); impl FileSystemPathKey { - async fn new(path: FileSystemPathVc) -> Result { + async fn new(path: Vc) -> Result { Ok(Self(path.resolve().await?)) } } @@ -32,7 +32,7 @@ pub async fn optimize_by_common_parent( ) -> Result where T: Clone, - GetCommonParent: Fn(T) -> FileSystemPathOptionVc + Clone, + GetCommonParent: Fn(T) -> Vc + Clone, Optimize: Fn(Option>, Vec) -> Acc, { let tree = ContainmentTree::build( diff --git a/crates/turbopack-core/src/code_builder.rs b/crates/turbopack-core/src/code_builder.rs index 39062c30abb1ef..8c39858a74b1c7 100644 --- a/crates/turbopack-core/src/code_builder.rs +++ b/crates/turbopack-core/src/code_builder.rs @@ -5,26 +5,25 @@ use std::{ }; use anyhow::Result; -use turbo_tasks::primitives::U64Vc; +use turbo_tasks::Vc; use turbo_tasks_fs::rope::{Rope, RopeBuilder}; use turbo_tasks_hash::hash_xxh3_hash64; use crate::{ - source_map::{ - GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMap, SourceMapSection, - SourceMapVc, - }, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMap, SourceMapSection}, source_pos::SourcePos, }; +/// A mapping of byte-offset in the code string to an associated source map. +pub type Mapping = (usize, Option>>); + /// Code stores combined output code and the source map of that output code. #[turbo_tasks::value(shared)] #[derive(Debug, Clone)] pub struct Code { code: Rope, - /// A mapping of byte-offset in the code string to an associated source map. - mappings: Vec<(usize, Option)>, + mappings: Vec, } /// CodeBuilder provides a mutable container to append source code. @@ -32,8 +31,7 @@ pub struct Code { pub struct CodeBuilder { code: RopeBuilder, - /// A mapping of byte-offset in the code string to an associated source map. - mappings: Vec<(usize, Option)>, + mappings: Vec, } impl Code { @@ -59,7 +57,7 @@ impl CodeBuilder { /// Pushes original user code with an optional source map if one is /// available. If it's not, this is no different than pushing Synthetic /// code. - pub fn push_source(&mut self, code: &Rope, map: Option) { + pub fn push_source(&mut self, code: &Rope, map: Option>>) { self.push_map(map); self.code += code; } @@ -94,7 +92,7 @@ impl CodeBuilder { /// original code section. By inserting an empty source map when reaching a /// synthetic section directly after an original section, we tell Chrome /// that the previous map ended at this point. - fn push_map(&mut self, map: Option) { + fn push_map(&mut self, map: Option>>) { if map.is_none() && matches!(self.mappings.last(), None | Some((_, None))) { // No reason to push an empty map directly after an empty map return; @@ -154,7 +152,7 @@ impl GenerateSourceMap for Code { /// far the simplest way to concatenate the source maps of the multiple /// chunk items into a single map file. #[turbo_tasks::function] - pub async fn generate_source_map(&self) -> Result { + pub async fn generate_source_map(&self) -> Result> { let mut pos = SourcePos::new(); let mut last_byte_pos = 0; @@ -175,9 +173,9 @@ impl GenerateSourceMap for Code { last_byte_pos = *byte_pos; let encoded = match map { - None => SourceMapVc::empty(), + None => SourceMap::empty(), Some(map) => match *map.generate_source_map().await? { - None => SourceMapVc::empty(), + None => SourceMap::empty(), Some(map) => map, }, }; @@ -185,19 +183,17 @@ impl GenerateSourceMap for Code { sections.push(SourceMapSection::new(pos, encoded)) } - Ok(OptionSourceMapVc::cell(Some( - SourceMap::new_sectioned(sections).cell(), - ))) + Ok(Vc::cell(Some(SourceMap::new_sectioned(sections).cell()))) } } #[turbo_tasks::value_impl] -impl CodeVc { +impl Code { /// Returns the hash of the source code of this Code. #[turbo_tasks::function] - pub async fn source_code_hash(self) -> Result { + pub async fn source_code_hash(self: Vc) -> Result> { let code = self.await?; let hash = hash_xxh3_hash64(code.source_code()); - Ok(U64Vc::cell(hash)) + Ok(Vc::cell(hash)) } } diff --git a/crates/turbopack-core/src/compile_time_info.rs b/crates/turbopack-core/src/compile_time_info.rs index fce0dc11aeebbe..d0c85658d12a50 100644 --- a/crates/turbopack-core/src/compile_time_info.rs +++ b/crates/turbopack-core/src/compile_time_info.rs @@ -1,8 +1,9 @@ use anyhow::Result; use indexmap::IndexMap; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; -use crate::environment::EnvironmentVc; +use crate::environment::Environment; // TODO stringify split map collect could be optimized with a marco #[macro_export] @@ -109,10 +110,10 @@ impl IntoIterator for CompileTimeDefines { } #[turbo_tasks::value_impl] -impl CompileTimeDefinesVc { +impl CompileTimeDefines { #[turbo_tasks::function] - pub fn empty() -> Self { - Self::cell(IndexMap::new()) + pub fn empty() -> Vc { + Vc::cell(IndexMap::new()) } } @@ -121,7 +122,7 @@ impl CompileTimeDefinesVc { pub enum FreeVarReference { EcmaScriptModule { request: String, - context: Option, + context: Option>, export: Option, }, Value(CompileTimeDefineValue), @@ -155,22 +156,22 @@ impl From for FreeVarReference { pub struct FreeVarReferences(pub IndexMap, FreeVarReference>); #[turbo_tasks::value_impl] -impl FreeVarReferencesVc { +impl FreeVarReferences { #[turbo_tasks::function] - pub fn empty() -> Self { - Self::cell(IndexMap::new()) + pub fn empty() -> Vc { + Vc::cell(IndexMap::new()) } } #[turbo_tasks::value(shared)] pub struct CompileTimeInfo { - pub environment: EnvironmentVc, - pub defines: CompileTimeDefinesVc, - pub free_var_references: FreeVarReferencesVc, + pub environment: Vc, + pub defines: Vc, + pub free_var_references: Vc, } impl CompileTimeInfo { - pub fn builder(environment: EnvironmentVc) -> CompileTimeInfoBuilder { + pub fn builder(environment: Vc) -> CompileTimeInfoBuilder { CompileTimeInfoBuilder { environment, defines: None, @@ -180,36 +181,36 @@ impl CompileTimeInfo { } #[turbo_tasks::value_impl] -impl CompileTimeInfoVc { +impl CompileTimeInfo { #[turbo_tasks::function] - pub fn new(environment: EnvironmentVc) -> Self { + pub fn new(environment: Vc) -> Vc { CompileTimeInfo { environment, - defines: CompileTimeDefinesVc::empty(), - free_var_references: FreeVarReferencesVc::empty(), + defines: CompileTimeDefines::empty(), + free_var_references: FreeVarReferences::empty(), } .cell() } #[turbo_tasks::function] - pub async fn environment(self) -> Result { + pub async fn environment(self: Vc) -> Result> { Ok(self.await?.environment) } } pub struct CompileTimeInfoBuilder { - environment: EnvironmentVc, - defines: Option, - free_var_references: Option, + environment: Vc, + defines: Option>, + free_var_references: Option>, } impl CompileTimeInfoBuilder { - pub fn defines(mut self, defines: CompileTimeDefinesVc) -> Self { + pub fn defines(mut self, defines: Vc) -> Self { self.defines = Some(defines); self } - pub fn free_var_references(mut self, free_var_references: FreeVarReferencesVc) -> Self { + pub fn free_var_references(mut self, free_var_references: Vc) -> Self { self.free_var_references = Some(free_var_references); self } @@ -217,14 +218,14 @@ impl CompileTimeInfoBuilder { pub fn build(self) -> CompileTimeInfo { CompileTimeInfo { environment: self.environment, - defines: self.defines.unwrap_or_else(CompileTimeDefinesVc::empty), + defines: self.defines.unwrap_or_else(CompileTimeDefines::empty), free_var_references: self .free_var_references - .unwrap_or_else(FreeVarReferencesVc::empty), + .unwrap_or_else(FreeVarReferences::empty), } } - pub fn cell(self) -> CompileTimeInfoVc { + pub fn cell(self) -> Vc { self.build().cell() } } diff --git a/crates/turbopack-core/src/context.rs b/crates/turbopack-core/src/context.rs index 7c095f0bbbff6f..cd084b31f4eeee 100644 --- a/crates/turbopack-core/src/context.rs +++ b/crates/turbopack-core/src/context.rs @@ -1,12 +1,11 @@ -use anyhow::Result; -use turbo_tasks::Value; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; use crate::{ - asset::AssetVc, - compile_time_info::CompileTimeInfoVc, + asset::Asset, + compile_time_info::CompileTimeInfo, reference_type::ReferenceType, - resolve::{options::ResolveOptionsVc, parse::RequestVc, ResolveResultVc}, + resolve::{options::ResolveOptions, parse::Request, ResolveResult}, }; /// A context for building an asset graph. It's passed through the assets while @@ -14,24 +13,28 @@ use crate::{ /// type (e. g. from SourceAsset to ModuleAsset). #[turbo_tasks::value_trait] pub trait AssetContext { - fn compile_time_info(&self) -> CompileTimeInfoVc; + fn compile_time_info(self: Vc) -> Vc; fn resolve_options( - &self, - origin_path: FileSystemPathVc, + self: Vc, + origin_path: Vc, reference_type: Value, - ) -> ResolveOptionsVc; + ) -> Vc; fn resolve_asset( - &self, - origin_path: FileSystemPathVc, - request: RequestVc, - resolve_options: ResolveOptionsVc, + self: Vc, + origin_path: Vc, + request: Vc, + resolve_options: Vc, reference_type: Value, - ) -> ResolveResultVc; - fn process(&self, asset: AssetVc, reference_type: Value) -> AssetVc; + ) -> Vc; + fn process( + self: Vc, + asset: Vc>, + reference_type: Value, + ) -> Vc>; fn process_resolve_result( - &self, - result: ResolveResultVc, + self: Vc, + result: Vc, reference_type: Value, - ) -> ResolveResultVc; - fn with_transition(&self, transition: &str) -> AssetContextVc; + ) -> Vc; + fn with_transition(self: Vc, transition: String) -> Vc>; } diff --git a/crates/turbopack-core/src/environment.rs b/crates/turbopack-core/src/environment.rs index ac3f9acda677be..46fe495cd0b944 100644 --- a/crates/turbopack-core/src/environment.rs +++ b/crates/turbopack-core/src/environment.rs @@ -8,13 +8,10 @@ use std::{ use anyhow::{anyhow, bail, Context, Result}; use serde::{Deserialize, Serialize}; use swc_core::ecma::preset_env::{Version, Versions}; -use turbo_tasks::{ - primitives::{BoolVc, OptionStringVc, StringVc, StringsVc}, - Value, -}; -use turbo_tasks_env::{ProcessEnv, ProcessEnvVc}; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_env::ProcessEnv; -use crate::target::CompileTargetVc; +use crate::target::CompileTarget; static DEFAULT_NODEJS_VERSION: &str = "16.0.0"; @@ -66,9 +63,9 @@ impl ServerAddr { } #[turbo_tasks::value_impl] -impl ServerAddrVc { +impl ServerAddr { #[turbo_tasks::function] - pub fn empty() -> Self { + pub fn empty() -> Vc { ServerAddr(None).cell() } } @@ -135,7 +132,7 @@ pub enum Rendering { #[default] None, Client, - Server(ServerAddrVc), + Server(Vc), } impl Rendering { @@ -163,12 +160,12 @@ pub struct Environment { } #[turbo_tasks::value_impl] -impl EnvironmentVc { +impl Environment { #[turbo_tasks::function] pub fn new( execution: Value, intention: Value, - ) -> Self { + ) -> Vc { Self::cell(Environment { execution: execution.into_value(), intention: intention.into_value(), @@ -202,36 +199,36 @@ pub enum EnvironmentIntention { #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(PartialOrd, Ord, Debug, Hash, Clone, Copy)] pub enum ExecutionEnvironment { - NodeJsBuildTime(NodeJsEnvironmentVc), - NodeJsLambda(NodeJsEnvironmentVc), - EdgeWorker(EdgeWorkerEnvironmentVc), - Browser(BrowserEnvironmentVc), + NodeJsBuildTime(Vc), + NodeJsLambda(Vc), + EdgeWorker(Vc), + Browser(Vc), // TODO allow custom trait here Custom(u8), } #[turbo_tasks::value_impl] -impl EnvironmentVc { +impl Environment { #[turbo_tasks::function] - pub async fn compile_target(self) -> Result { + pub async fn compile_target(self: Vc) -> Result> { let this = self.await?; Ok(match this.execution { ExecutionEnvironment::NodeJsBuildTime(node_env, ..) | ExecutionEnvironment::NodeJsLambda(node_env) => node_env.await?.compile_target, - ExecutionEnvironment::Browser(_) => CompileTargetVc::unknown(), - ExecutionEnvironment::EdgeWorker(_) => CompileTargetVc::unknown(), + ExecutionEnvironment::Browser(_) => CompileTarget::unknown(), + ExecutionEnvironment::EdgeWorker(_) => CompileTarget::unknown(), ExecutionEnvironment::Custom(_) => todo!(), }) } #[turbo_tasks::function] - pub async fn runtime_versions(self) -> Result { + pub async fn runtime_versions(self: Vc) -> Result> { let this = self.await?; Ok(match this.execution { ExecutionEnvironment::NodeJsBuildTime(node_env, ..) | ExecutionEnvironment::NodeJsLambda(node_env) => node_env.runtime_versions(), ExecutionEnvironment::Browser(browser_env) => { - RuntimeVersionsVc::cell(Versions::parse_versions(browserslist::resolve( + Vc::cell(Versions::parse_versions(browserslist::resolve( browser_env.await?.browserslist_query.split(','), &browserslist::Opts::new(), )?)?) @@ -242,75 +239,75 @@ impl EnvironmentVc { } #[turbo_tasks::function] - pub async fn node_externals(self) -> Result { + pub async fn node_externals(self: Vc) -> Result> { let this = self.await?; Ok(match this.execution { ExecutionEnvironment::NodeJsBuildTime(..) | ExecutionEnvironment::NodeJsLambda(_) => { - BoolVc::cell(true) + Vc::cell(true) } - ExecutionEnvironment::Browser(_) => BoolVc::cell(false), - ExecutionEnvironment::EdgeWorker(_) => BoolVc::cell(false), + ExecutionEnvironment::Browser(_) => Vc::cell(false), + ExecutionEnvironment::EdgeWorker(_) => Vc::cell(false), ExecutionEnvironment::Custom(_) => todo!(), }) } #[turbo_tasks::function] - pub async fn resolve_extensions(self) -> Result { + pub async fn resolve_extensions(self: Vc) -> Result>> { let env = self.await?; Ok(match env.execution { ExecutionEnvironment::NodeJsBuildTime(..) | ExecutionEnvironment::NodeJsLambda(_) => { - StringsVc::cell(vec![ + Vc::cell(vec![ ".js".to_string(), ".node".to_string(), ".json".to_string(), ]) } ExecutionEnvironment::EdgeWorker(_) | ExecutionEnvironment::Browser(_) => { - StringsVc::empty() + Vc::>::empty() } ExecutionEnvironment::Custom(_) => todo!(), }) } #[turbo_tasks::function] - pub async fn resolve_node_modules(self) -> Result { + pub async fn resolve_node_modules(self: Vc) -> Result> { let env = self.await?; Ok(match env.execution { ExecutionEnvironment::NodeJsBuildTime(..) | ExecutionEnvironment::NodeJsLambda(_) => { - BoolVc::cell(true) + Vc::cell(true) } ExecutionEnvironment::EdgeWorker(_) | ExecutionEnvironment::Browser(_) => { - BoolVc::cell(false) + Vc::cell(false) } ExecutionEnvironment::Custom(_) => todo!(), }) } #[turbo_tasks::function] - pub async fn resolve_conditions(self) -> Result { + pub async fn resolve_conditions(self: Vc) -> Result>> { let env = self.await?; Ok(match env.execution { ExecutionEnvironment::NodeJsBuildTime(..) | ExecutionEnvironment::NodeJsLambda(_) => { - StringsVc::cell(vec!["node".to_string()]) + Vc::cell(vec!["node".to_string()]) } - ExecutionEnvironment::Browser(_) => StringsVc::empty(), - ExecutionEnvironment::EdgeWorker(_) => StringsVc::cell(vec!["edge-worker".to_string()]), + ExecutionEnvironment::Browser(_) => Vc::>::empty(), + ExecutionEnvironment::EdgeWorker(_) => Vc::cell(vec!["edge-worker".to_string()]), ExecutionEnvironment::Custom(_) => todo!(), }) } #[turbo_tasks::function] - pub async fn cwd(self) -> Result { + pub async fn cwd(self: Vc) -> Result>> { let env = self.await?; Ok(match env.execution { ExecutionEnvironment::NodeJsBuildTime(env) | ExecutionEnvironment::NodeJsLambda(env) => env.await?.cwd, - _ => OptionStringVc::cell(None), + _ => Vc::cell(None), }) } #[turbo_tasks::function] - pub async fn rendering(self) -> Result { + pub async fn rendering(self: Vc) -> Result> { let env = self.await?; Ok(match env.execution { ExecutionEnvironment::NodeJsBuildTime(env) @@ -326,7 +323,7 @@ impl EnvironmentVc { } #[turbo_tasks::function] - pub async fn chunk_loading(self) -> Result { + pub async fn chunk_loading(self: Vc) -> Result> { let env = self.await?; Ok(match env.execution { ExecutionEnvironment::NodeJsBuildTime(_) | ExecutionEnvironment::NodeJsLambda(_) => { @@ -345,35 +342,35 @@ pub enum NodeEnvironmentType { #[turbo_tasks::value(shared)] pub struct NodeJsEnvironment { - pub compile_target: CompileTargetVc, - pub node_version: NodeJsVersionVc, + pub compile_target: Vc, + pub node_version: Vc, // user specified process.cwd - pub cwd: OptionStringVc, - pub server_addr: ServerAddrVc, + pub cwd: Vc>, + pub server_addr: Vc, } impl Default for NodeJsEnvironment { fn default() -> Self { NodeJsEnvironment { - compile_target: CompileTargetVc::current(), - node_version: NodeJsVersionVc::default(), - cwd: OptionStringVc::cell(None), - server_addr: ServerAddrVc::empty(), + compile_target: CompileTarget::current(), + node_version: NodeJsVersion::default().cell(), + cwd: Vc::cell(None), + server_addr: ServerAddr::empty(), } } } #[turbo_tasks::value_impl] -impl NodeJsEnvironmentVc { +impl NodeJsEnvironment { #[turbo_tasks::function] - pub async fn runtime_versions(self) -> Result { + pub async fn runtime_versions(self: Vc) -> Result> { let str = match *self.await?.node_version.await? { NodeJsVersion::Current(process_env) => get_current_nodejs_version(process_env), NodeJsVersion::Static(version) => version, } .await?; - Ok(RuntimeVersionsVc::cell(Versions { + Ok(Vc::cell(Versions { node: Some( Version::from_str(&str).map_err(|_| anyhow!("Node.js version parse error"))?, ), @@ -382,11 +379,11 @@ impl NodeJsEnvironmentVc { } #[turbo_tasks::function] - pub fn current(process_env: ProcessEnvVc, server_addr: ServerAddrVc) -> Self { + pub fn current(process_env: Vc>, server_addr: Vc) -> Vc { Self::cell(NodeJsEnvironment { - compile_target: CompileTargetVc::current(), - node_version: NodeJsVersionVc::cell(NodeJsVersion::Current(process_env)), - cwd: OptionStringVc::cell(None), + compile_target: CompileTarget::current(), + node_version: NodeJsVersion::cell(NodeJsVersion::Current(process_env)), + cwd: Vc::cell(None), server_addr, }) } @@ -394,13 +391,13 @@ impl NodeJsEnvironmentVc { #[turbo_tasks::value(shared)] pub enum NodeJsVersion { - Current(ProcessEnvVc), - Static(StringVc), + Current(Vc>), + Static(Vc), } -impl Default for NodeJsVersionVc { +impl Default for NodeJsVersion { fn default() -> Self { - NodeJsVersion::Static(StringVc::cell(DEFAULT_NODEJS_VERSION.to_owned())).cell() + NodeJsVersion::Static(Vc::cell(DEFAULT_NODEJS_VERSION.to_owned())) } } @@ -414,15 +411,15 @@ pub struct BrowserEnvironment { #[turbo_tasks::value(shared)] pub struct EdgeWorkerEnvironment { - pub server_addr: ServerAddrVc, + pub server_addr: Vc, } #[turbo_tasks::value(transparent)] pub struct RuntimeVersions(#[turbo_tasks(trace_ignore)] pub Versions); #[turbo_tasks::function] -pub async fn get_current_nodejs_version(env: ProcessEnvVc) -> Result { - let path_read = env.read("PATH").await?; +pub async fn get_current_nodejs_version(env: Vc>) -> Result> { + let path_read = env.read("PATH".to_string()).await?; let path = path_read.as_ref().context("env must have PATH")?; let mut cmd = Command::new("node"); cmd.arg("--version"); @@ -431,7 +428,7 @@ pub async fn get_current_nodejs_version(env: ProcessEnvVc) -> Result { cmd.stdin(Stdio::piped()); cmd.stdout(Stdio::piped()); - Ok(StringVc::cell( + Ok(Vc::cell( String::from_utf8(cmd.output()?.stdout)? .strip_prefix('v') .context("Version must begin with v")? diff --git a/crates/turbopack-core/src/ident.rs b/crates/turbopack-core/src/ident.rs index 94d957aa6c5189..fce57a0ede2d0b 100644 --- a/crates/turbopack-core/src/ident.rs +++ b/crates/turbopack-core/src/ident.rs @@ -1,43 +1,43 @@ use std::fmt::Write; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbo_tasks_hash::{encode_hex, hash_xxh3_hash64, DeterministicHash, Xxh3Hash64Hasher}; -use crate::resolve::{ModulePart, ModulePartVc}; +use crate::resolve::ModulePart; #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(Clone, Debug, PartialOrd, Ord, Hash)] pub struct AssetIdent { /// The primary path of the asset - pub path: FileSystemPathVc, + pub path: Vc, /// The query string of the asset (e.g. `?foo=bar`) - pub query: Option, + pub query: Option>, /// The fragment of the asset (e.g. `#foo`) - pub fragment: Option, + pub fragment: Option>, /// The assets that are nested in this asset - pub assets: Vec<(StringVc, AssetIdentVc)>, + pub assets: Vec<(Vc, Vc)>, /// The modifiers of this asset (e.g. `client chunks`) - pub modifiers: Vec, + pub modifiers: Vec>, /// The part of the asset that is a (ECMAScript) module - pub part: Option, + pub part: Option>, } impl AssetIdent { - pub fn add_modifier(&mut self, modifier: StringVc) { + pub fn add_modifier(&mut self, modifier: Vc) { self.modifiers.push(modifier); } - pub fn add_asset(&mut self, key: StringVc, asset: AssetIdentVc) { + pub fn add_asset(&mut self, key: Vc, asset: Vc) { self.assets.push((key, asset)); } - pub async fn rename_as(&mut self, pattern: &str) -> Result<()> { + pub async fn rename_as_ref(&mut self, pattern: &str) -> Result<()> { let root = self.path.root(); let path = self.path.await?; self.path = root - .join(&pattern.replace('*', &path.path)) + .join(pattern.replace('*', &path.path)) .resolve() .await?; Ok(()) @@ -47,7 +47,7 @@ impl AssetIdent { #[turbo_tasks::value_impl] impl ValueToString for AssetIdent { #[turbo_tasks::function] - async fn to_string(&self) -> Result { + async fn to_string(&self) -> Result> { let mut s = self.path.to_string().await?.clone_value(); if let Some(query) = &self.query { write!(s, "?{}", query.await?)?; @@ -68,20 +68,20 @@ impl ValueToString for AssetIdent { } s.push(')'); } - Ok(StringVc::cell(s)) + Ok(Vc::cell(s)) } } #[turbo_tasks::value_impl] -impl AssetIdentVc { +impl AssetIdent { #[turbo_tasks::function] - pub fn new(ident: Value) -> Self { + pub fn new(ident: Value) -> Vc { ident.into_value().cell() } - /// Creates an [AssetIdent] from a [FileSystemPathVc] + /// Creates an [AssetIdent] from a [Vc] #[turbo_tasks::function] - pub fn from_path(path: FileSystemPathVc) -> Self { + pub fn from_path(path: Vc) -> Vc { Self::new(Value::new(AssetIdent { path, query: None, @@ -93,28 +93,28 @@ impl AssetIdentVc { } #[turbo_tasks::function] - pub async fn with_modifier(self, modifier: StringVc) -> Result { + pub async fn with_modifier(self: Vc, modifier: Vc) -> Result> { let mut this = self.await?.clone_value(); this.add_modifier(modifier); Ok(Self::new(Value::new(this))) } #[turbo_tasks::function] - pub async fn with_part(self, part: ModulePartVc) -> Result { + pub async fn with_part(self: Vc, part: Vc) -> Result> { let mut this = self.await?.clone_value(); this.part = Some(part); Ok(Self::new(Value::new(this))) } #[turbo_tasks::function] - pub async fn rename_as(self, pattern: &str) -> Result { + pub async fn rename_as(self: Vc, pattern: String) -> Result> { let mut this = self.await?.clone_value(); - this.rename_as(pattern).await?; + this.rename_as_ref(&pattern).await?; Ok(Self::new(Value::new(this))) } #[turbo_tasks::function] - pub async fn path(self) -> Result { + pub async fn path(self: Vc) -> Result> { Ok(self.await?.path) } @@ -124,10 +124,10 @@ impl AssetIdentVc { /// name generation logic. #[turbo_tasks::function] pub async fn output_name( - self, - context_path: FileSystemPathVc, - expected_extension: &str, - ) -> Result { + self: Vc, + context_path: Vc, + expected_extension: String, + ) -> Result> { let this = &*self.await?; // For clippy -- This explicit deref is necessary @@ -137,7 +137,7 @@ impl AssetIdentVc { } else { clean_separators(&this.path.to_string().await?) }; - let removed_extension = name.ends_with(expected_extension); + let removed_extension = name.ends_with(&expected_extension); if removed_extension { name.truncate(name.len() - expected_extension.len()); } @@ -146,7 +146,7 @@ impl AssetIdentVc { // Next.js). let mut name = clean_additional_extensions(&name); - let default_modifier = match expected_extension { + let default_modifier = match expected_extension.as_str() { ".js" => Some("ecmascript"), ".css" => Some("css"), _ => None, @@ -241,8 +241,8 @@ impl AssetIdentVc { if !removed_extension { name += "._"; } - name += expected_extension; - Ok(StringVc::cell(name)) + name += &expected_extension; + Ok(Vc::cell(name)) } } diff --git a/crates/turbopack-core/src/introspect/asset.rs b/crates/turbopack-core/src/introspect/asset.rs index 64a8b1f5d6b5aa..a57d72b88f6aa2 100644 --- a/crates/turbopack-core/src/introspect/asset.rs +++ b/crates/turbopack-core/src/introspect/asset.rs @@ -1,121 +1,123 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, ValueToString}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::FileContent; -use super::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}; +use super::{Introspectable, IntrospectableChildren}; use crate::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, - chunk::{ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingType}, - reference::{AssetReference, AssetReferencesVc}, + asset::{Asset, AssetContent}, + chunk::{ChunkableAssetReference, ChunkingType}, + reference::{AssetReference, AssetReferences}, resolve::PrimaryResolveResult, }; #[turbo_tasks::value] -pub struct IntrospectableAsset(AssetVc); +pub struct IntrospectableAsset(Vc>); #[turbo_tasks::value_impl] -impl IntrospectableAssetVc { +impl IntrospectableAsset { #[turbo_tasks::function] - pub async fn new(asset: AssetVc) -> Result { - Ok(IntrospectableVc::resolve_from(asset) + pub async fn new(asset: Vc>) -> Result>> { + Ok(Vc::try_resolve_sidecast::>(asset) .await? - .unwrap_or_else(|| IntrospectableAsset(asset).cell().into())) + .unwrap_or_else(|| Vc::upcast(IntrospectableAsset(asset).cell()))) } } #[turbo_tasks::function] -fn asset_ty() -> StringVc { - StringVc::cell("asset".to_string()) +fn asset_ty() -> Vc { + Vc::cell("asset".to_string()) } #[turbo_tasks::function] -fn reference_ty() -> StringVc { - StringVc::cell("reference".to_string()) +fn reference_ty() -> Vc { + Vc::cell("reference".to_string()) } #[turbo_tasks::function] -fn placed_or_parallel_reference_ty() -> StringVc { - StringVc::cell("placed/parallel reference".to_string()) +fn placed_or_parallel_reference_ty() -> Vc { + Vc::cell("placed/parallel reference".to_string()) } #[turbo_tasks::function] -fn placed_reference_ty() -> StringVc { - StringVc::cell("placed reference".to_string()) +fn placed_reference_ty() -> Vc { + Vc::cell("placed reference".to_string()) } #[turbo_tasks::function] -fn parallel_reference_ty() -> StringVc { - StringVc::cell("parallel reference".to_string()) +fn parallel_reference_ty() -> Vc { + Vc::cell("parallel reference".to_string()) } #[turbo_tasks::function] -fn isolated_parallel_reference_ty() -> StringVc { - StringVc::cell("isolated parallel reference".to_string()) +fn isolated_parallel_reference_ty() -> Vc { + Vc::cell("isolated parallel reference".to_string()) } #[turbo_tasks::function] -fn separate_reference_ty() -> StringVc { - StringVc::cell("separate reference".to_string()) +fn separate_reference_ty() -> Vc { + Vc::cell("separate reference".to_string()) } #[turbo_tasks::function] -fn async_reference_ty() -> StringVc { - StringVc::cell("async reference".to_string()) +fn async_reference_ty() -> Vc { + Vc::cell("async reference".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for IntrospectableAsset { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { asset_ty() } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { self.0.ident().to_string() } #[turbo_tasks::function] - fn details(&self) -> StringVc { + fn details(&self) -> Vc { content_to_details(self.0.content()) } #[turbo_tasks::function] - fn children(&self) -> IntrospectableChildrenVc { + fn children(&self) -> Vc { children_from_asset_references(self.0.references()) } } #[turbo_tasks::function] -pub async fn content_to_details(content: AssetContentVc) -> Result { +pub async fn content_to_details(content: Vc) -> Result> { Ok(match &*content.await? { AssetContent::File(file_content) => match &*file_content.await? { FileContent::Content(file) => { let content = file.content(); match content.to_str() { - Ok(str) => StringVc::cell(str.into_owned()), - Err(_) => StringVc::cell(format!("{} binary bytes", content.len())), + Ok(str) => Vc::cell(str.into_owned()), + Err(_) => Vc::cell(format!("{} binary bytes", content.len())), } } - FileContent::NotFound => StringVc::cell("not found".to_string()), + FileContent::NotFound => Vc::cell("not found".to_string()), }, AssetContent::Redirect { target, link_type } => { - StringVc::cell(format!("redirect to {target} with type {link_type:?}")) + Vc::cell(format!("redirect to {target} with type {link_type:?}")) } }) } #[turbo_tasks::function] pub async fn children_from_asset_references( - references: AssetReferencesVc, -) -> Result { + references: Vc, +) -> Result> { let key = reference_ty(); let mut children = IndexSet::new(); let references = references.await?; for reference in &*references { let mut key = key; - if let Some(chunkable) = ChunkableAssetReferenceVc::resolve_from(reference).await? { + if let Some(chunkable) = + Vc::try_resolve_downcast::>(*reference).await? + { match &*chunkable.chunking_type().await? { None => {} Some(ChunkingType::Placed) => key = placed_reference_ty(), @@ -129,9 +131,9 @@ pub async fn children_from_asset_references( for result in reference.resolve_reference().await?.primary.iter() { if let PrimaryResolveResult::Asset(asset) = result { - children.insert((key, IntrospectableAssetVc::new(*asset))); + children.insert((key, IntrospectableAsset::new(*asset))); } } } - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } diff --git a/crates/turbopack-core/src/introspect/mod.rs b/crates/turbopack-core/src/introspect/mod.rs index bbe95c0f11945c..0275dde422b4dc 100644 --- a/crates/turbopack-core/src/introspect/mod.rs +++ b/crates/turbopack-core/src/introspect/mod.rs @@ -1,21 +1,23 @@ pub mod asset; use indexmap::IndexSet; -use turbo_tasks::primitives::StringVc; +use turbo_tasks::Vc; + +type VcDynIntrospectable = Vc>; #[turbo_tasks::value(transparent)] -pub struct IntrospectableChildren(IndexSet<(StringVc, IntrospectableVc)>); +pub struct IntrospectableChildren(IndexSet<(Vc, VcDynIntrospectable)>); #[turbo_tasks::value_trait] pub trait Introspectable { - fn ty(&self) -> StringVc; - fn title(&self) -> StringVc { - StringVc::empty() + fn ty(self: Vc) -> Vc; + fn title(self: Vc) -> Vc { + Vc::::empty() } - fn details(&self) -> StringVc { - StringVc::empty() + fn details(self: Vc) -> Vc { + Vc::::empty() } - fn children(&self) -> IntrospectableChildrenVc { - IntrospectableChildrenVc::cell(IndexSet::new()) + fn children(self: Vc) -> Vc { + Vc::cell(IndexSet::new()) } } diff --git a/crates/turbopack-core/src/issue/analyze.rs b/crates/turbopack-core/src/issue/analyze.rs index 26b62cb4b2a443..32ee5c97c33877 100644 --- a/crates/turbopack-core/src/issue/analyze.rs +++ b/crates/turbopack-core/src/issue/analyze.rs @@ -1,54 +1,54 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; -use super::{Issue, IssueSeverityVc, IssueSourceVc, IssueVc, OptionIssueSourceVc}; -use crate::ident::AssetIdentVc; +use super::{Issue, IssueSeverity, IssueSource, OptionIssueSource}; +use crate::ident::AssetIdent; #[turbo_tasks::value(shared)] pub struct AnalyzeIssue { - pub severity: IssueSeverityVc, - pub source_ident: AssetIdentVc, - pub title: StringVc, - pub message: StringVc, - pub category: StringVc, + pub severity: Vc, + pub source_ident: Vc, + pub title: Vc, + pub message: Vc, + pub category: Vc, pub code: Option, - pub source: Option, + pub source: Option>, } #[turbo_tasks::value_impl] impl Issue for AnalyzeIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - async fn title(&self) -> Result { + async fn title(&self) -> Result> { Ok(if let Some(code) = self.code.as_ref() { - StringVc::cell(format!("{code} {}", self.title.await?)) + Vc::cell(format!("{code} {}", self.title.await?)) } else { self.title }) } #[turbo_tasks::function] - fn category(&self) -> StringVc { + fn category(&self) -> Vc { self.category } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.source_ident.path() } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.message } #[turbo_tasks::function] - fn source(&self) -> OptionIssueSourceVc { - OptionIssueSourceVc::cell(self.source) + fn source(&self) -> Vc { + Vc::cell(self.source) } } diff --git a/crates/turbopack-core/src/issue/code_gen.rs b/crates/turbopack-core/src/issue/code_gen.rs index e032aca697cb17..2059a17ad8f1eb 100644 --- a/crates/turbopack-core/src/issue/code_gen.rs +++ b/crates/turbopack-core/src/issue/code_gen.rs @@ -1,41 +1,40 @@ -use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; -use super::{Issue, IssueSeverityVc, IssueVc}; +use super::{Issue, IssueSeverity}; #[turbo_tasks::value(shared)] pub struct CodeGenerationIssue { - pub severity: IssueSeverityVc, - pub path: FileSystemPathVc, - pub title: StringVc, - pub message: StringVc, + pub severity: Vc, + pub path: Vc, + pub title: Vc, + pub message: Vc, } #[turbo_tasks::value_impl] impl Issue for CodeGenerationIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { self.title } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("code generation".to_string()) + fn category(&self) -> Vc { + Vc::cell("code generation".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.path } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.message } } diff --git a/crates/turbopack-core/src/issue/mod.rs b/crates/turbopack-core/src/issue/mod.rs index 4eff9783370f73..c8f6b918965a98 100644 --- a/crates/turbopack-core/src/issue/mod.rs +++ b/crates/turbopack-core/src/issue/mod.rs @@ -13,18 +13,14 @@ use anyhow::Result; use async_trait::async_trait; use auto_hash_map::AutoSet; use turbo_tasks::{ - emit, - primitives::{BoolVc, StringReadRef, StringVc, U64Vc}, - CollectiblesSource, RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, - ValueToString, ValueToStringVc, -}; -use turbo_tasks_fs::{ - FileContent, FileContentReadRef, FileLine, FileLinesContent, FileSystemPathVc, + emit, CollectiblesSource, RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, + Upcast, ValueToString, Vc, }; +use turbo_tasks_fs::{FileContent, FileLine, FileLinesContent, FileSystemPath}; use turbo_tasks_hash::{DeterministicHash, Xxh3Hash64Hasher}; use crate::{ - asset::{Asset, AssetContent, AssetVc}, + asset::{Asset, AssetContent}, source_pos::SourcePos, }; @@ -80,73 +76,109 @@ impl Display for IssueSeverity { pub trait Issue { /// Severity allows the user to filter out unimportant issues, with Bug /// being the highest priority and Info being the lowest. - fn severity(&self) -> IssueSeverityVc { + fn severity(self: Vc) -> Vc { IssueSeverity::Error.into() } /// The file path that generated the issue, displayed to the user as message /// header. - fn context(&self) -> FileSystemPathVc; + fn context(self: Vc) -> Vc; /// A short identifier of the type of error (eg "parse", "analyze", or /// "evaluate") displayed to the user as part of the message header. - fn category(&self) -> StringVc { - StringVc::empty() + fn category(self: Vc) -> Vc { + Vc::::empty() } /// The issue title should be descriptive of the issue, but should be a /// single line. This is displayed to the user directly under the issue /// header. - // TODO add StyledStringVc - fn title(&self) -> StringVc; + // TODO add Vc + fn title(self: Vc) -> Vc; /// A more verbose message of the issue, appropriate for providing multiline /// information of the issue. - // TODO add StyledStringVc - fn description(&self) -> StringVc; + // TODO add Vc + fn description(self: Vc) -> Vc; /// Full details of the issue, appropriate for providing debug level /// information. Only displayed if the user explicitly asks for detailed /// messages (not to be confused with severity). - fn detail(&self) -> StringVc { - StringVc::empty() + fn detail(self: Vc) -> Vc { + Vc::::empty() } /// A link to relevant documentation of the issue. Only displayed in console /// if the user explicitly asks for detailed messages. - fn documentation_link(&self) -> StringVc { - StringVc::empty() + fn documentation_link(self: Vc) -> Vc { + Vc::::empty() } /// The source location that caused the issue. Eg, for a parsing error it /// should point at the offending character. Displayed to the user alongside /// the title/description. - fn source(&self) -> OptionIssueSourceVc { - OptionIssueSourceVc::none() + fn source(self: Vc) -> Vc { + OptionIssueSource::none() + } + + fn sub_issues(self: Vc) -> Vc { + Vc::cell(Vec::new()) } - fn sub_issues(&self) -> IssuesVc { - IssuesVc::cell(Vec::new()) + async fn into_plain( + self: Vc, + processing_path: Vc, + ) -> Result> { + Ok(PlainIssue { + severity: *self.severity().await?, + context: self.context().to_string().await?.clone_value(), + category: self.category().await?.clone_value(), + title: self.title().await?.clone_value(), + description: self.description().await?.clone_value(), + detail: self.detail().await?.clone_value(), + documentation_link: self.documentation_link().await?.clone_value(), + source: { + if let Some(s) = *self.source().await? { + Some(s.into_plain().await?) + } else { + None + } + }, + sub_issues: self + .sub_issues() + .await? + .iter() + .map(|i| async move { + anyhow::Ok(i.into_plain(OptionIssueProcessingPathItems::none()).await?) + }) + .try_join() + .await?, + processing_path: processing_path.into_plain().await?, + } + .cell()) } } #[turbo_tasks::value_trait] trait IssueProcessingPath { - fn shortest_path(&self, issue: IssueVc) -> OptionIssueProcessingPathItemsVc; + fn shortest_path( + self: Vc, + issue: Vc>, + ) -> Vc; } #[turbo_tasks::value] pub struct IssueProcessingPathItem { - pub context: Option, - pub description: StringVc, + pub context: Option>, + pub description: Vc, } #[turbo_tasks::value_impl] impl ValueToString for IssueProcessingPathItem { #[turbo_tasks::function] - async fn to_string(&self) -> Result { + async fn to_string(&self) -> Result> { if let Some(context) = self.context { - Ok(StringVc::cell(format!( + Ok(Vc::cell(format!( "{} ({})", context.to_string().await?, self.description.await? @@ -158,9 +190,9 @@ impl ValueToString for IssueProcessingPathItem { } #[turbo_tasks::value_impl] -impl IssueProcessingPathItemVc { +impl IssueProcessingPathItem { #[turbo_tasks::function] - pub async fn into_plain(self) -> Result { + pub async fn into_plain(self: Vc) -> Result> { let this = self.await?; Ok(PlainIssueProcessingPathItem { context: if let Some(context) = this.context { @@ -175,59 +207,60 @@ impl IssueProcessingPathItemVc { } #[turbo_tasks::value(transparent)] -pub struct OptionIssueProcessingPathItems(Option>); +pub struct OptionIssueProcessingPathItems(Option>>); #[turbo_tasks::value_impl] -impl OptionIssueProcessingPathItemsVc { +impl OptionIssueProcessingPathItems { #[turbo_tasks::function] - pub fn none() -> Self { - OptionIssueProcessingPathItemsVc::cell(None) + pub fn none() -> Vc { + Vc::cell(None) } #[turbo_tasks::function] - pub async fn into_plain(self) -> Result { - Ok(PlainIssueProcessingPathVc::cell( - if let Some(items) = &*self.await? { - Some( - items - .iter() - .map(|item| item.into_plain()) - .try_join() - .await?, - ) - } else { - None - }, - )) + pub async fn into_plain(self: Vc) -> Result> { + Ok(Vc::cell(if let Some(items) = &*self.await? { + Some( + items + .iter() + .map(|item| item.into_plain()) + .try_join() + .await?, + ) + } else { + None + })) } } #[turbo_tasks::value] -struct RootIssueProcessingPath(IssueVc); +struct RootIssueProcessingPath(Vc>); #[turbo_tasks::value_impl] impl IssueProcessingPath for RootIssueProcessingPath { #[turbo_tasks::function] - fn shortest_path(&self, issue: IssueVc) -> OptionIssueProcessingPathItemsVc { + fn shortest_path(&self, issue: Vc>) -> Vc { if self.0 == issue { - OptionIssueProcessingPathItemsVc::cell(Some(Vec::new())) + Vc::cell(Some(Vec::new())) } else { - OptionIssueProcessingPathItemsVc::cell(None) + Vc::cell(None) } } } #[turbo_tasks::value] struct ItemIssueProcessingPath( - Option, - AutoSet, + Option>, + AutoSet>>, ); #[turbo_tasks::value_impl] impl IssueProcessingPath for ItemIssueProcessingPath { /// Returns the shortest path from the root issue to the given issue. #[turbo_tasks::function] - async fn shortest_path(&self, issue: IssueVc) -> Result { + async fn shortest_path( + &self, + issue: Vc>, + ) -> Result> { assert!(!self.1.is_empty()); let paths = self .1 @@ -262,129 +295,68 @@ impl IssueProcessingPath for ItemIssueProcessingPath { shortest = Some(path); } } - Ok(OptionIssueProcessingPathItemsVc::cell(shortest.map( - |path| { - if let Some(item) = self.0 { - std::iter::once(item).chain(path.iter().copied()).collect() - } else { - path.clone() - } - }, - ))) + Ok(Vc::cell(shortest.map(|path| { + if let Some(item) = self.0 { + std::iter::once(item).chain(path.iter().copied()).collect() + } else { + path.clone() + } + }))) } } -impl IssueVc { - pub fn emit(self) { - emit(self); - emit( - RootIssueProcessingPathVc::cell(RootIssueProcessingPath(self)) - .as_issue_processing_path(), - ) - } +pub trait IssueExt { + fn emit(self); } -impl IssueVc { - #[allow(unused_variables, reason = "behind feature flag")] - pub async fn attach_context( - context: impl Into> + Send, - description: impl Into + Send, - source: T, - ) -> Result { - #[cfg(feature = "issue_path")] - { - let children = source.take_collectibles().await?; - if !children.is_empty() { - emit( - ItemIssueProcessingPathVc::cell(ItemIssueProcessingPath( - Some(IssueProcessingPathItemVc::cell(IssueProcessingPathItem { - context: context.into(), - description: StringVc::cell(description.into()), - })), - children, - )) - .as_issue_processing_path(), - ); - } - } - Ok(source) - } - - #[allow(unused_variables, reason = "behind feature flag")] - pub async fn attach_description( - description: impl Into + Send, - source: T, - ) -> Result { - Self::attach_context(None, description, source).await - } - - /// Returns all issues from `source` in a list with their associated - /// processing path. - pub async fn peek_issues_with_path( - source: T, - ) -> Result { - Ok(CapturedIssuesVc::cell(CapturedIssues { - issues: source.peek_collectibles().strongly_consistent().await?, - #[cfg(feature = "issue_path")] - processing_path: ItemIssueProcessingPathVc::cell(ItemIssueProcessingPath( - None, - source.peek_collectibles().strongly_consistent().await?, - )), - })) - } - - /// Returns all issues from `source` in a list with their associated - /// processing path. - /// - /// This unemits the issues. They will not propagate up. - pub async fn take_issues_with_path( - source: T, - ) -> Result { - Ok(CapturedIssuesVc::cell(CapturedIssues { - issues: source.take_collectibles().strongly_consistent().await?, - #[cfg(feature = "issue_path")] - processing_path: ItemIssueProcessingPathVc::cell(ItemIssueProcessingPath( - None, - source.take_collectibles().strongly_consistent().await?, - )), - })) +impl IssueExt for Vc +where + T: Upcast>, +{ + fn emit(self) { + let issue = Vc::upcast::>(self); + emit(issue); + emit(Vc::upcast::>( + RootIssueProcessingPath::cell(RootIssueProcessingPath(issue)), + )) } } #[turbo_tasks::value(transparent)] -pub struct Issues(Vec); +pub struct Issues(Vec>>); -/// A list of issues captured with [`IssueVc::peek_issues_with_path`] and -/// [`IssueVc::take_issues_with_path`]. +/// A list of issues captured with [`Issue::peek_issues_with_path`] and +/// [`Issue::take_issues_with_path`]. #[derive(Debug)] #[turbo_tasks::value] pub struct CapturedIssues { - issues: AutoSet, + issues: AutoSet>>, #[cfg(feature = "issue_path")] - processing_path: ItemIssueProcessingPathVc, + processing_path: Vc, } #[turbo_tasks::value_impl] -impl CapturedIssuesVc { +impl CapturedIssues { #[turbo_tasks::function] - pub async fn is_empty(self) -> Result { - Ok(BoolVc::cell(self.await?.is_empty())) + pub async fn is_empty(self: Vc) -> Result> { + Ok(Vc::cell(self.await?.is_empty_ref())) } } impl CapturedIssues { /// Returns true if there are no issues. - pub fn is_empty(&self) -> bool { + pub fn is_empty_ref(&self) -> bool { self.issues.is_empty() } /// Returns the number of issues. + #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.issues.len() } /// Returns an iterator over the issues. - pub fn iter(&self) -> impl Iterator + '_ { + pub fn iter(&self) -> impl Iterator>> + '_ { self.issues.iter().copied() } @@ -392,17 +364,17 @@ impl CapturedIssues { /// issue to each issue. pub fn iter_with_shortest_path( &self, - ) -> impl Iterator + '_ { + ) -> impl Iterator>, Vc)> + '_ { self.issues.iter().map(|issue| { #[cfg(feature = "issue_path")] let path = self.processing_path.shortest_path(*issue); #[cfg(not(feature = "issue_path"))] - let path = OptionIssueProcessingPathItemsVc::none(); + let path = OptionIssueProcessingPathItems::none(); (*issue, path) }) } - pub async fn get_plain_issues(&self) -> Result> { + pub async fn get_plain_issues(&self) -> Result>> { let mut list = self .issues .iter() @@ -413,7 +385,7 @@ impl CapturedIssues { .await; #[cfg(not(feature = "issue_path"))] return issue - .into_plain(OptionIssueProcessingPathItemsVc::none()) + .into_plain(OptionIssueProcessingPathItems::none()) .await; }) .try_join() @@ -426,15 +398,19 @@ impl CapturedIssues { #[turbo_tasks::value] #[derive(Clone)] pub struct IssueSource { - pub asset: AssetVc, + pub asset: Vc>, pub start: SourcePos, pub end: SourcePos, } #[turbo_tasks::value_impl] -impl IssueSourceVc { +impl IssueSource { #[turbo_tasks::function] - pub async fn from_byte_offset(asset: AssetVc, start: usize, end: usize) -> Result { + pub async fn from_byte_offset( + asset: Vc>, + start: usize, + end: usize, + ) -> Result> { fn find_line_and_column(lines: &[FileLine], offset: usize) -> SourcePos { match lines.binary_search_by(|line| line.bytes_offset.cmp(&offset)) { Ok(i) => SourcePos { line: i, column: 0 }, @@ -470,18 +446,18 @@ impl IssueSourceVc { } #[turbo_tasks::value(transparent)] -pub struct OptionIssueSource(Option); +pub struct OptionIssueSource(Option>); #[turbo_tasks::value_impl] -impl OptionIssueSourceVc { +impl OptionIssueSource { #[turbo_tasks::function] - pub fn some(source: IssueSourceVc) -> Self { - OptionIssueSourceVc::cell(Some(source)) + pub fn some(source: Vc) -> Vc { + Vc::cell(Some(source)) } #[turbo_tasks::function] - pub fn none() -> Self { - OptionIssueSourceVc::cell(None) + pub fn none() -> Vc { + Vc::cell(None) } } @@ -497,9 +473,9 @@ pub struct PlainIssue { pub detail: String, pub documentation_link: String, - pub source: Option, - pub sub_issues: Vec, - pub processing_path: PlainIssueProcessingPathReadRef, + pub source: Option>, + pub sub_issues: Vec>, + pub processing_path: ReadRef, } fn hash_plain_issue(issue: &PlainIssue, hasher: &mut Xxh3Hash64Hasher, full: bool) { @@ -543,7 +519,7 @@ impl PlainIssue { /// useful for generating exact matching hashes, it's possible for the /// same issue to pass from multiple processing paths, making for overly /// verbose logging. - pub fn internal_hash(&self, full: bool) -> u64 { + pub fn internal_hash_ref(&self, full: bool) -> u64 { let mut hasher = Xxh3Hash64Hasher::new(); hash_plain_issue(self, &mut hasher, full); hasher.finish() @@ -551,7 +527,7 @@ impl PlainIssue { } #[turbo_tasks::value_impl] -impl PlainIssueVc { +impl PlainIssue { /// We need deduplicate issues that can come from unique paths, but /// represent the same underlying problem. Eg, a parse error for a file /// that is compiled in both client and server contexts. @@ -561,66 +537,26 @@ impl PlainIssueVc { /// same issue to pass from multiple processing paths, making for overly /// verbose logging. #[turbo_tasks::function] - pub async fn internal_hash(self, full: bool) -> Result { - Ok(U64Vc::cell(self.await?.internal_hash(full))) - } -} - -#[turbo_tasks::value_impl] -impl IssueVc { - #[turbo_tasks::function] - pub async fn into_plain( - self, - processing_path: OptionIssueProcessingPathItemsVc, - ) -> Result { - Ok(PlainIssue { - severity: *self.severity().await?, - context: self.context().to_string().await?.clone_value(), - category: self.category().await?.clone_value(), - title: self.title().await?.clone_value(), - description: self.description().await?.clone_value(), - detail: self.detail().await?.clone_value(), - documentation_link: self.documentation_link().await?.clone_value(), - source: { - if let Some(s) = *self.source().await? { - Some(s.into_plain().await?) - } else { - None - } - }, - sub_issues: self - .sub_issues() - .await? - .iter() - .map(|i| async move { - anyhow::Ok( - i.into_plain(OptionIssueProcessingPathItemsVc::none()) - .await?, - ) - }) - .try_join() - .await?, - processing_path: processing_path.into_plain().await?, - } - .cell()) + pub async fn internal_hash(self: Vc, full: bool) -> Result> { + Ok(Vc::cell(self.await?.internal_hash_ref(full))) } } #[turbo_tasks::value(serialization = "none")] #[derive(Clone, Debug)] pub struct PlainIssueSource { - pub asset: PlainAssetReadRef, + pub asset: ReadRef, pub start: SourcePos, pub end: SourcePos, } #[turbo_tasks::value_impl] -impl IssueSourceVc { +impl IssueSource { #[turbo_tasks::function] - pub async fn into_plain(self) -> Result { + pub async fn into_plain(self: Vc) -> Result> { let this = self.await?; Ok(PlainIssueSource { - asset: PlainAssetVc::from_asset(this.asset).await?, + asset: PlainAsset::from_asset(this.asset).await?, start: this.start, end: this.end, } @@ -631,15 +567,15 @@ impl IssueSourceVc { #[turbo_tasks::value(serialization = "none")] #[derive(Clone, Debug)] pub struct PlainAsset { - pub ident: StringReadRef, + pub ident: ReadRef, #[turbo_tasks(debug_ignore)] - pub content: FileContentReadRef, + pub content: ReadRef, } #[turbo_tasks::value_impl] -impl PlainAssetVc { +impl PlainAsset { #[turbo_tasks::function] - pub async fn from_asset(asset: AssetVc) -> Result { + pub async fn from_asset(asset: Vc>) -> Result> { let asset_content = asset.content().await?; let content = match *asset_content { AssetContent::File(file_content) => file_content.await?, @@ -656,22 +592,22 @@ impl PlainAssetVc { #[turbo_tasks::value(transparent, serialization = "none")] #[derive(Clone, Debug, DeterministicHash)] -pub struct PlainIssueProcessingPath(Option>); +pub struct PlainIssueProcessingPath(Option>>); #[turbo_tasks::value(serialization = "none")] #[derive(Clone, Debug, DeterministicHash)] pub struct PlainIssueProcessingPathItem { - pub context: Option, - pub description: StringReadRef, + pub context: Option>, + pub description: ReadRef, } #[turbo_tasks::value_trait] pub trait IssueReporter { fn report_issues( - &self, + self: Vc, issues: TransientInstance>, source: TransientValue, - ) -> BoolVc; + ) -> Vc; } #[async_trait] @@ -679,12 +615,32 @@ pub trait IssueContextExt where Self: Sized, { + #[allow(unused_variables, reason = "behind feature flag")] + async fn attach_context( + self, + context: impl Into>> + Send, + description: impl Into + Send, + ) -> Result; + + #[allow(unused_variables, reason = "behind feature flag")] + async fn attach_description(self, description: impl Into + Send) -> Result; + async fn issue_context( self, - context: impl Into> + Send, + context: impl Into>> + Send, description: impl Into + Send, ) -> Result; async fn issue_description(self, description: impl Into + Send) -> Result; + + /// Returns all issues from `source` in a list with their associated + /// processing path. + async fn peek_issues_with_path(self) -> Result>; + + /// Returns all issues from `source` in a list with their associated + /// processing path. + /// + /// This unemits the issues. They will not propagate up. + async fn take_issues_with_path(self) -> Result>; } #[async_trait] @@ -692,14 +648,86 @@ impl IssueContextExt for T where T: CollectiblesSource + Copy + Send, { + #[allow(unused_variables, reason = "behind feature flag")] + async fn attach_context( + self, + context: impl Into>> + Send, + description: impl Into + Send, + ) -> Result { + #[cfg(feature = "issue_path")] + { + let children = self.take_collectibles().await?; + if !children.is_empty() { + emit(Vc::upcast::>( + ItemIssueProcessingPath::cell(ItemIssueProcessingPath( + Some(IssueProcessingPathItem::cell(IssueProcessingPathItem { + context: context.into(), + description: Vc::cell(description.into()), + })), + children, + )), + )); + } + } + Ok(self) + } + + #[allow(unused_variables, reason = "behind feature flag")] + async fn attach_description(self, description: impl Into + Send) -> Result { + self.attach_context(None, description).await + } + async fn issue_context( self, - context: impl Into> + Send, + context: impl Into>> + Send, description: impl Into + Send, ) -> Result { - IssueVc::attach_context(context, description, self).await + #[cfg(feature = "issue_path")] + { + let children = self.take_collectibles().await?; + if !children.is_empty() { + emit(Vc::upcast::>( + ItemIssueProcessingPath::cell(ItemIssueProcessingPath( + Some(IssueProcessingPathItem::cell(IssueProcessingPathItem { + context: context.into(), + description: Vc::cell(description.into()), + })), + children, + )), + )); + } + } + #[cfg(not(feature = "issue_path"))] + { + let _ = context; + let _ = description; + } + Ok(self) } + async fn issue_description(self, description: impl Into + Send) -> Result { - IssueVc::attach_description(description, self).await + self.issue_context(None, description).await + } + + async fn peek_issues_with_path(self) -> Result> { + Ok(CapturedIssues::cell(CapturedIssues { + issues: self.peek_collectibles().strongly_consistent().await?, + #[cfg(feature = "issue_path")] + processing_path: ItemIssueProcessingPath::cell(ItemIssueProcessingPath( + None, + self.peek_collectibles().strongly_consistent().await?, + )), + })) + } + + async fn take_issues_with_path(self) -> Result> { + Ok(CapturedIssues::cell(CapturedIssues { + issues: self.take_collectibles().strongly_consistent().await?, + #[cfg(feature = "issue_path")] + processing_path: ItemIssueProcessingPath::cell(ItemIssueProcessingPath( + None, + self.take_collectibles().strongly_consistent().await?, + )), + })) } } diff --git a/crates/turbopack-core/src/issue/resolve.rs b/crates/turbopack-core/src/issue/resolve.rs index 002a751fe1d83e..04887710ec1828 100644 --- a/crates/turbopack-core/src/issue/resolve.rs +++ b/crates/turbopack-core/src/issue/resolve.rs @@ -1,62 +1,62 @@ use std::fmt::Write; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; -use super::{Issue, IssueVc}; +use super::Issue; use crate::{ error::PrettyPrintError, - issue::{IssueSeverityVc, OptionIssueSourceVc}, - resolve::{options::ResolveOptionsVc, parse::RequestVc}, + issue::{IssueSeverity, OptionIssueSource}, + resolve::{options::ResolveOptions, parse::Request}, }; #[turbo_tasks::value(shared)] pub struct ResolvingIssue { - pub severity: IssueSeverityVc, + pub severity: Vc, pub request_type: String, - pub request: RequestVc, - pub context: FileSystemPathVc, - pub resolve_options: ResolveOptionsVc, + pub request: Vc, + pub context: Vc, + pub resolve_options: Vc, pub error_message: Option, - pub source: OptionIssueSourceVc, + pub source: Vc, } #[turbo_tasks::value_impl] impl Issue for ResolvingIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell(format!( + fn title(&self) -> Vc { + Vc::cell(format!( "Error resolving {request_type}", request_type = self.request_type, )) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("resolve".to_string()) + fn category(&self) -> Vc { + Vc::cell("resolve".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - async fn description(&self) -> Result { - Ok(StringVc::cell(format!( + async fn description(&self) -> Result> { + Ok(Vc::cell(format!( "unable to resolve {module_name}", module_name = self.request.to_string().await? ))) } #[turbo_tasks::function] - async fn detail(&self) -> Result { + async fn detail(&self) -> Result> { let mut detail = String::new(); if let Some(error_message) = &self.error_message { @@ -94,11 +94,11 @@ impl Issue for ResolvingIssue { } } } - Ok(StringVc::cell(detail)) + Ok(Vc::cell(detail)) } #[turbo_tasks::function] - fn source(&self) -> OptionIssueSourceVc { + fn source(&self) -> Vc { self.source } diff --git a/crates/turbopack-core/src/issue/unsupported_module.rs b/crates/turbopack-core/src/issue/unsupported_module.rs index 1a2695344f57b9..62fa5d511b4d7e 100644 --- a/crates/turbopack-core/src/issue/unsupported_module.rs +++ b/crates/turbopack-core/src/issue/unsupported_module.rs @@ -1,12 +1,12 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; -use super::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}; +use super::{Issue, IssueSeverity}; #[turbo_tasks::value(shared)] pub struct UnsupportedModuleIssue { - pub context: FileSystemPathVc, + pub context: Vc, pub package: String, pub package_path: Option, } @@ -14,28 +14,28 @@ pub struct UnsupportedModuleIssue { #[turbo_tasks::value_impl] impl Issue for UnsupportedModuleIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("resolve".to_string()) + fn category(&self) -> Vc { + Vc::cell("resolve".to_string()) } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Unsupported module".into()) + fn title(&self) -> Vc { + Vc::cell("Unsupported module".into()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - async fn description(&self) -> Result { - Ok(StringVc::cell(match &self.package_path { + async fn description(&self) -> Result> { + Ok(Vc::cell(match &self.package_path { Some(path) => format!("The module {}{} is not yet supported", self.package, path), None => format!("The package {} is not yet supported", self.package), })) diff --git a/crates/turbopack-core/src/lib.rs b/crates/turbopack-core/src/lib.rs index 8bdf03d26ae0ae..47ccf149dd9ec8 100644 --- a/crates/turbopack-core/src/lib.rs +++ b/crates/turbopack-core/src/lib.rs @@ -4,6 +4,8 @@ #![feature(type_alias_impl_trait)] #![feature(assert_matches)] #![feature(lint_reasons)] +#![feature(async_fn_in_trait)] +#![feature(arbitrary_self_types)] pub mod asset; pub mod changed; diff --git a/crates/turbopack-core/src/package_json.rs b/crates/turbopack-core/src/package_json.rs index bc299002f27241..9783f00935d871 100644 --- a/crates/turbopack-core/src/package_json.rs +++ b/crates/turbopack-core/src/package_json.rs @@ -2,16 +2,17 @@ use std::{fmt::Write, ops::Deref}; use anyhow::Result; use serde_json::Value as JsonValue; -use turbo_tasks::{debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs}; -use turbo_tasks_fs::{FileContent, FileJsonContent, FileJsonContentReadRef, FileSystemPathVc}; +use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, ReadRef, Vc}; +use turbo_tasks_fs::{FileContent, FileJsonContent, FileSystemPath}; -use super::issue::{Issue, IssueVc}; +use super::issue::Issue; +use crate::issue::IssueExt; /// PackageJson wraps the parsed JSON content of a `package.json` file. The /// wrapper is necessary so that we can reference the [FileJsonContent]'s inner /// [serde_json::Value] without cloning it. #[derive(PartialEq, Eq, ValueDebugFormat, TraceRawVcs)] -pub struct PackageJson(FileJsonContentReadRef); +pub struct PackageJson(ReadRef); impl Deref for PackageJson { type Target = JsonValue; @@ -29,7 +30,7 @@ pub struct OptionPackageJson(Option); /// Reads a package.json file (if it exists). If the file is unparseable, it /// emits a useful [Issue] pointing to the invalid location. #[turbo_tasks::function] -pub async fn read_package_json(path: FileSystemPathVc) -> Result { +pub async fn read_package_json(path: Vc) -> Result> { let read = path.read_json().await?; match &*read { FileJsonContent::Content(_) => Ok(OptionPackageJson(Some(PackageJson(read))).cell()), @@ -47,7 +48,6 @@ pub async fn read_package_json(path: FileSystemPathVc) -> Result Result, pub error_message: String, } #[turbo_tasks::value_impl] impl Issue for PackageJsonIssue { #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Error parsing package.json file".to_string()) + fn title(&self) -> Vc { + Vc::cell("Error parsing package.json file".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("parse".to_string()) + fn category(&self) -> Vc { + Vc::cell("parse".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.path } #[turbo_tasks::function] - fn description(&self) -> StringVc { - StringVc::cell(self.error_message.clone()) + fn description(&self) -> Vc { + Vc::cell(self.error_message.clone()) } } diff --git a/crates/turbopack-core/src/plugin.rs b/crates/turbopack-core/src/plugin.rs index 352fd58bd6fbb8..22c64698fe4d05 100644 --- a/crates/turbopack-core/src/plugin.rs +++ b/crates/turbopack-core/src/plugin.rs @@ -1,11 +1,13 @@ -use crate::{asset::AssetVc, context::AssetContextVc, resolve::ModulePartVc}; +use turbo_tasks::Vc; + +use crate::{asset::Asset, context::AssetContext, resolve::ModulePart}; #[turbo_tasks::value_trait] pub trait CustomModuleType { fn create_module( - &self, - source: AssetVc, - context: AssetContextVc, - part: Option, - ) -> AssetVc; + self: Vc, + source: Vc>, + context: Vc>, + part: Option>, + ) -> Vc>; } diff --git a/crates/turbopack-core/src/proxied_asset.rs b/crates/turbopack-core/src/proxied_asset.rs index 7d7455e6fcba74..5a81da47f4c5e8 100644 --- a/crates/turbopack-core/src/proxied_asset.rs +++ b/crates/turbopack-core/src/proxied_asset.rs @@ -1,11 +1,11 @@ -use anyhow::Result; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; use crate::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, - reference::AssetReferencesVc, - version::VersionedContentVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, + reference::AssetReferences, + version::VersionedContent, }; /// An [`Asset`] with an overwritten path. This is helpful to expose an asset at @@ -14,15 +14,15 @@ use crate::{ /// Next.js apps. #[turbo_tasks::value] pub struct ProxiedAsset { - asset: AssetVc, - path: FileSystemPathVc, + asset: Vc>, + path: Vc, } #[turbo_tasks::value_impl] -impl ProxiedAssetVc { +impl ProxiedAsset { /// Creates a new [`ProxiedAsset`] from an [`Asset`] and a path. #[turbo_tasks::function] - pub fn new(asset: AssetVc, path: FileSystemPathVc) -> Self { + pub fn new(asset: Vc>, path: Vc) -> Vc { ProxiedAsset { asset, path }.cell() } } @@ -30,22 +30,22 @@ impl ProxiedAssetVc { #[turbo_tasks::value_impl] impl Asset for ProxiedAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - AssetIdentVc::from_path(self.path) + fn ident(&self) -> Vc { + AssetIdent::from_path(self.path) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.asset.content() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.asset.references() } #[turbo_tasks::function] - fn versioned_content(&self) -> VersionedContentVc { + fn versioned_content(&self) -> Vc> { self.asset.versioned_content() } } diff --git a/crates/turbopack-core/src/reference/mod.rs b/crates/turbopack-core/src/reference/mod.rs index e2819840ffefea..2052c7270016cb 100644 --- a/crates/turbopack-core/src/reference/mod.rs +++ b/crates/turbopack-core/src/reference/mod.rs @@ -1,16 +1,16 @@ use std::collections::{HashSet, VecDeque}; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, ValueToString, ValueToStringVc}; +use turbo_tasks::{TryJoinIterExt, ValueToString, Vc}; use crate::{ - asset::{Asset, AssetVc, AssetsVc}, + asset::{Asset, Assets}, issue::IssueContextExt, - resolve::{PrimaryResolveResult, ResolveResult, ResolveResultVc}, + resolve::{PrimaryResolveResult, ResolveResult}, }; pub mod source_map; -pub use source_map::SourceMapReferenceVc; +pub use source_map::SourceMapReference; /// A reference to one or multiple [Asset]s or other special things. /// There are a bunch of optional traits that can influence how these references @@ -20,34 +20,34 @@ pub use source_map::SourceMapReferenceVc; /// [ChunkableAssetReference]: crate::chunk::ChunkableAssetReference #[turbo_tasks::value_trait] pub trait AssetReference: ValueToString { - fn resolve_reference(&self) -> ResolveResultVc; + fn resolve_reference(self: Vc) -> Vc; // TODO think about different types - // fn kind(&self) -> AssetReferenceTypeVc; + // fn kind(&self) -> Vc; } /// Multiple [AssetReference]s #[turbo_tasks::value(transparent)] -pub struct AssetReferences(Vec); +pub struct AssetReferences(Vec>>); #[turbo_tasks::value_impl] -impl AssetReferencesVc { +impl AssetReferences { /// An empty list of [AssetReference]s #[turbo_tasks::function] - pub fn empty() -> Self { - AssetReferencesVc::cell(Vec::new()) + pub fn empty() -> Vc { + Vc::cell(Vec::new()) } } /// A reference that always resolves to a single asset. #[turbo_tasks::value] pub struct SingleAssetReference { - asset: AssetVc, - description: StringVc, + asset: Vc>, + description: Vc, } impl SingleAssetReference { /// Returns the asset that this reference resolves to. - pub fn asset(&self) -> AssetVc { + pub fn asset_ref(&self) -> Vc> { self.asset } } @@ -55,7 +55,7 @@ impl SingleAssetReference { #[turbo_tasks::value_impl] impl AssetReference for SingleAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { ResolveResult::asset(self.asset).cell() } } @@ -63,22 +63,23 @@ impl AssetReference for SingleAssetReference { #[turbo_tasks::value_impl] impl ValueToString for SingleAssetReference { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { + fn to_string(&self) -> Vc { self.description } } #[turbo_tasks::value_impl] -impl SingleAssetReferenceVc { - /// Create a new [SingleAssetReferenceVc] that resolves to the given asset. +impl SingleAssetReference { + /// Create a new [Vc] that resolves to the given + /// asset. #[turbo_tasks::function] - pub fn new(asset: AssetVc, description: StringVc) -> Self { + pub fn new(asset: Vc>, description: Vc) -> Vc { Self::cell(SingleAssetReference { asset, description }) } - /// The [AssetVc] that this reference resolves to. + /// The [Vc>] that this reference resolves to. #[turbo_tasks::function] - pub async fn asset(self) -> Result { + pub async fn asset(self: Vc) -> Result>> { Ok(self.await?.asset) } } @@ -89,7 +90,7 @@ impl SingleAssetReferenceVc { /// /// [Asset]: crate::asset::Asset #[turbo_tasks::function] -pub async fn all_referenced_assets(asset: AssetVc) -> Result { +pub async fn all_referenced_assets(asset: Vc>) -> Result> { let references_set = asset.references().await?; let mut assets = Vec::new(); let mut queue = VecDeque::with_capacity(32); @@ -113,7 +114,7 @@ pub async fn all_referenced_assets(asset: AssetVc) -> Result { queue.push_back(reference.resolve_reference()); } } - Ok(AssetsVc::cell(assets)) + Ok(Vc::cell(assets)) } /// Aggregates all primary [Asset]s referenced by an [Asset]. [AssetReference] @@ -122,7 +123,7 @@ pub async fn all_referenced_assets(asset: AssetVc) -> Result { /// /// [Asset]: crate::asset::Asset #[turbo_tasks::function] -pub async fn primary_referenced_assets(asset: AssetVc) -> Result { +pub async fn primary_referenced_assets(asset: Vc>) -> Result> { let assets = asset .references() .await? @@ -145,14 +146,14 @@ pub async fn primary_referenced_assets(asset: AssetVc) -> Result { .into_iter() .flatten() .collect(); - Ok(AssetsVc::cell(assets)) + Ok(Vc::cell(assets)) } /// Aggregates all [Asset]s referenced by an [Asset] including transitively /// referenced [Asset]s. This basically gives all [Asset]s in a subgraph /// starting from the passed [Asset]. #[turbo_tasks::function] -pub async fn all_assets(asset: AssetVc) -> Result { +pub async fn all_assets(asset: Vc>) -> Result> { // TODO need to track import path here let mut queue = VecDeque::with_capacity(32); queue.push_back((asset, all_referenced_assets(asset))); @@ -168,5 +169,5 @@ pub async fn all_assets(asset: AssetVc) -> Result { } } } - Ok(AssetsVc::cell(assets.into_iter().collect())) + Ok(Vc::cell(assets.into_iter().collect())) } diff --git a/crates/turbopack-core/src/reference/source_map.rs b/crates/turbopack-core/src/reference/source_map.rs index 0198ab4b03edcf..50ea1dd345e401 100644 --- a/crates/turbopack-core/src/reference/source_map.rs +++ b/crates/turbopack-core/src/reference/source_map.rs @@ -1,23 +1,20 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::{FileSystemEntryType, FileSystemPathVc}; +use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks_fs::{FileSystemEntryType, FileSystemPath}; -use super::{AssetReference, AssetReferenceVc}; -use crate::{ - resolve::{ResolveResult, ResolveResultVc}, - source_asset::SourceAssetVc, -}; +use super::AssetReference; +use crate::{resolve::ResolveResult, source_asset::SourceAsset}; #[turbo_tasks::value] pub struct SourceMapReference { - from: FileSystemPathVc, - file: FileSystemPathVc, + from: Vc, + file: Vc, } #[turbo_tasks::value_impl] -impl SourceMapReferenceVc { +impl SourceMapReference { #[turbo_tasks::function] - pub fn new(from: FileSystemPathVc, file: FileSystemPathVc) -> Self { + pub fn new(from: Vc, file: Vc) -> Vc { Self::cell(SourceMapReference { from, file }) } } @@ -25,11 +22,11 @@ impl SourceMapReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for SourceMapReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> ResolveResultVc { + async fn resolve_reference(&self) -> Vc { let file_type = self.file.get_type().await; if let Ok(file_type_result) = file_type.as_ref() { if let FileSystemEntryType::File = &**file_type_result { - return ResolveResult::asset(SourceAssetVc::new(self.file).into()).into(); + return ResolveResult::asset(Vc::upcast(SourceAsset::new(self.file))).into(); } } ResolveResult::unresolveable().into() @@ -39,8 +36,8 @@ impl AssetReference for SourceMapReference { #[turbo_tasks::value_impl] impl ValueToString for SourceMapReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "source map file is referenced by {}", self.from.to_string().await? ))) diff --git a/crates/turbopack-core/src/reference_type.rs b/crates/turbopack-core/src/reference_type.rs index 7b3d39bd3cb769..55beab768f2bbc 100644 --- a/crates/turbopack-core/src/reference_type.rs +++ b/crates/turbopack-core/src/reference_type.rs @@ -1,20 +1,21 @@ use std::fmt::Display; use indexmap::IndexMap; +use turbo_tasks::Vc; -use crate::{asset::AssetVc, resolve::ModulePartVc}; +use crate::{asset::Asset, resolve::ModulePart}; /// Named references to inner assets. Modules can used them to allow to /// per-module aliases of some requests to already created module assets. /// Name is usually in UPPER_CASE to make it clear that this is an inner asset. #[turbo_tasks::value(transparent)] -pub struct InnerAssets(IndexMap); +pub struct InnerAssets(IndexMap>>); #[turbo_tasks::value_impl] -impl InnerAssetsVc { +impl InnerAssets { #[turbo_tasks::function] - pub fn empty() -> Self { - InnerAssetsVc::cell(IndexMap::new()) + pub fn empty() -> Vc { + Vc::cell(IndexMap::new()) } } @@ -34,7 +35,7 @@ pub enum CommonJsReferenceSubType { #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(Debug, Default, Clone, PartialOrd, Ord, Hash)] pub enum EcmaScriptModulesReferenceSubType { - ImportPart(ModulePartVc), + ImportPart(Vc), Custom(u8), #[default] Undefined, @@ -88,7 +89,7 @@ pub enum ReferenceType { Url(UrlReferenceSubType), TypeScript(TypeScriptReferenceSubType), Entry(EntryReferenceSubType), - Internal(InnerAssetsVc), + Internal(Vc), Custom(u8), Undefined, } diff --git a/crates/turbopack-core/src/resolve/mod.rs b/crates/turbopack-core/src/resolve/mod.rs index 18cac86d753012..a930e74e4b185b 100644 --- a/crates/turbopack-core/src/resolve/mod.rs +++ b/crates/turbopack-core/src/resolve/mod.rs @@ -7,36 +7,32 @@ use std::{ use anyhow::{anyhow, bail, Result}; use serde_json::Value as JsonValue; -use turbo_tasks::{ - primitives::{BoolVc, StringVc, StringsVc}, - TryJoinIterExt, Value, ValueToString, ValueToStringVc, -}; +use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc}; use turbo_tasks_fs::{ util::{normalize_path, normalize_request}, - FileSystemEntryType, FileSystemPathVc, RealPathResult, + FileSystemEntryType, FileSystemPath, RealPathResult, }; use self::{ options::{ - resolve_modules_options, ImportMapResult, ResolveInPackage, ResolveIntoPackage, - ResolveModules, ResolveModulesOptionsVc, ResolveOptionsVc, + resolve_modules_options, ConditionValue, ImportMapResult, ResolveInPackage, + ResolveIntoPackage, ResolveModules, ResolveModulesOptions, ResolveOptions, }, - parse::{Request, RequestVc}, - pattern::QueryMapVc, + parse::Request, + pattern::{Pattern, QueryMap}, remap::{ExportsField, ImportsField}, }; use crate::{ - asset::{Asset, AssetOptionVc, AssetVc, AssetsVc}, - issue::resolve::{ResolvingIssue, ResolvingIssueVc}, - package_json::{read_package_json, PackageJsonIssue, PackageJsonIssueVc}, - reference::{AssetReference, AssetReferenceVc}, + asset::{Asset, AssetOption, Assets}, + issue::{resolve::ResolvingIssue, IssueExt}, + package_json::{read_package_json, PackageJsonIssue}, + reference::AssetReference, reference_type::ReferenceType, resolve::{ - options::{ConditionValue, ResolveOptions}, - pattern::{read_matches, Pattern, PatternMatch, PatternVc}, + pattern::{read_matches, PatternMatch}, plugin::ResolvePlugin, }, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; mod alias_map; @@ -51,14 +47,14 @@ pub(crate) mod remap; pub use alias_map::{ AliasMap, AliasMapIntoIter, AliasMapLookupIterator, AliasMatch, AliasPattern, AliasTemplate, }; -pub use remap::{ResolveAliasMap, ResolveAliasMapVc, SubpathValue}; +pub use remap::{ResolveAliasMap, SubpathValue}; -use crate::issue::{IssueSeverity, IssueSeverityVc, OptionIssueSourceVc}; +use crate::issue::{IssueSeverity, OptionIssueSource}; #[turbo_tasks::value(shared)] #[derive(Clone, Debug)] pub enum PrimaryResolveResult { - Asset(AssetVc), + Asset(Vc>), OriginalReferenceExternal, OriginalReferenceTypeExternal(String), Ignore, @@ -71,7 +67,7 @@ pub enum PrimaryResolveResult { #[derive(Clone, Debug)] pub struct ResolveResult { pub primary: Vec, - pub references: Vec, + pub references: Vec>>, } impl Default for ResolveResult { @@ -88,7 +84,9 @@ impl ResolveResult { } } - pub fn unresolveable_with_references(references: Vec) -> ResolveResult { + pub fn unresolveable_with_references( + references: Vec>>, + ) -> ResolveResult { ResolveResult { primary: Vec::new(), references, @@ -104,7 +102,7 @@ impl ResolveResult { pub fn primary_with_references( result: PrimaryResolveResult, - references: Vec, + references: Vec>>, ) -> ResolveResult { ResolveResult { primary: vec![result], @@ -112,7 +110,7 @@ impl ResolveResult { } } - pub fn asset(asset: AssetVc) -> ResolveResult { + pub fn asset(asset: Vc>) -> ResolveResult { ResolveResult { primary: vec![PrimaryResolveResult::Asset(asset)], references: Vec::new(), @@ -120,8 +118,8 @@ impl ResolveResult { } pub fn asset_with_references( - asset: AssetVc, - references: Vec, + asset: Vc>, + references: Vec>>, ) -> ResolveResult { ResolveResult { primary: vec![PrimaryResolveResult::Asset(asset)], @@ -129,7 +127,7 @@ impl ResolveResult { } } - pub fn assets(assets: Vec) -> ResolveResult { + pub fn assets(assets: Vec>>) -> ResolveResult { ResolveResult { primary: assets .into_iter() @@ -140,8 +138,8 @@ impl ResolveResult { } pub fn assets_with_references( - assets: Vec, - references: Vec, + assets: Vec>>, + references: Vec>>, ) -> ResolveResult { ResolveResult { primary: assets @@ -152,15 +150,15 @@ impl ResolveResult { } } - pub fn add_reference(&mut self, reference: AssetReferenceVc) { + pub fn add_reference_ref(&mut self, reference: Vc>) { self.references.push(reference); } - pub fn get_references(&self) -> &Vec { + pub fn get_references(&self) -> &Vec>> { &self.references } - fn clone_with_references(&self, references: Vec) -> ResolveResult { + fn clone_with_references(&self, references: Vec>>) -> ResolveResult { ResolveResult { primary: self.primary.clone(), references, @@ -172,16 +170,16 @@ impl ResolveResult { self.references.extend(other.references.iter().copied()); } - pub fn is_unresolveable(&self) -> bool { + pub fn is_unresolveable_ref(&self) -> bool { self.primary.is_empty() } pub async fn map(&self, asset_fn: A, reference_fn: R) -> Result where - A: Fn(AssetVc) -> AF, - AF: Future>, - R: Fn(AssetReferenceVc) -> RF, - RF: Future>, + A: Fn(Vc>) -> AF, + AF: Future>>>, + R: Fn(Vc>) -> RF, + RF: Future>>>, { Ok(Self { primary: self @@ -212,19 +210,25 @@ impl ResolveResult { } #[turbo_tasks::value_impl] -impl ResolveResultVc { +impl ResolveResult { #[turbo_tasks::function] - pub async fn add_reference(self, reference: AssetReferenceVc) -> Result { + pub async fn add_reference( + self: Vc, + reference: Vc>, + ) -> Result> { let mut this = self.await?.clone_value(); - this.add_reference(reference); + this.add_reference_ref(reference); Ok(this.into()) } #[turbo_tasks::function] - pub async fn add_references(self, references: Vec) -> Result { + pub async fn add_references( + self: Vc, + references: Vec>>, + ) -> Result> { let mut this = self.await?.clone_value(); for reference in references { - this.add_reference(reference); + this.add_reference_ref(reference); } Ok(this.into()) } @@ -233,14 +237,14 @@ impl ResolveResultVc { /// [ResolveResult::Unresolveable] in the given list, while keeping track /// of all the references in all the [ResolveResult]s. #[turbo_tasks::function] - pub async fn select_first(results: Vec) -> Result { + pub async fn select_first(results: Vec>) -> Result> { let mut references = vec![]; for result in &results { references.extend(result.await?.get_references()); } for result in results { let result_ref = result.await?; - if !result_ref.is_unresolveable() { + if !result_ref.is_unresolveable_ref() { return Ok(result_ref.clone_with_references(references).cell()); } } @@ -248,7 +252,7 @@ impl ResolveResultVc { } #[turbo_tasks::function] - pub async fn alternatives(results: Vec) -> Result { + pub async fn alternatives(results: Vec>) -> Result> { if results.len() == 1 { return Ok(results.into_iter().next().unwrap()); } @@ -268,11 +272,11 @@ impl ResolveResultVc { #[turbo_tasks::function] pub async fn alternatives_with_references( - results: Vec, - references: Vec, - ) -> Result { + results: Vec>, + references: Vec>>, + ) -> Result> { if references.is_empty() { - return Self::alternatives_inline(results).await; + return Ok(Self::alternatives(results)); } if results.len() == 1 { return Ok(results @@ -299,15 +303,15 @@ impl ResolveResultVc { } #[turbo_tasks::function] - pub async fn is_unresolveable(self) -> Result { + pub async fn is_unresolveable(self: Vc) -> Result> { let this = self.await?; - Ok(BoolVc::cell(this.is_unresolveable())) + Ok(Vc::cell(this.is_unresolveable_ref())) } #[turbo_tasks::function] - pub async fn first_asset(self) -> Result { + pub async fn first_asset(self: Vc) -> Result> { let this = self.await?; - Ok(AssetOptionVc::cell(this.primary.iter().find_map(|item| { + Ok(Vc::cell(this.primary.iter().find_map(|item| { if let PrimaryResolveResult::Asset(a) = item { Some(*a) } else { @@ -317,9 +321,9 @@ impl ResolveResultVc { } #[turbo_tasks::function] - pub async fn primary_assets(self) -> Result { + pub async fn primary_assets(self: Vc) -> Result> { let this = self.await?; - Ok(AssetsVc::cell( + Ok(Vc::cell( this.primary .iter() .filter_map(|item| { @@ -335,43 +339,43 @@ impl ResolveResultVc { } #[turbo_tasks::value(transparent)] -pub struct ResolveResultOption(Option); +pub struct ResolveResultOption(Option>); #[turbo_tasks::value_impl] -impl ResolveResultOptionVc { +impl ResolveResultOption { #[turbo_tasks::function] - pub fn some(result: ResolveResultVc) -> Self { + pub fn some(result: Vc) -> Vc { ResolveResultOption(Some(result)).cell() } #[turbo_tasks::function] - pub fn none() -> Self { + pub fn none() -> Vc { ResolveResultOption(None).cell() } } async fn exists( - fs_path: FileSystemPathVc, - refs: &mut Vec, -) -> Result> { + fs_path: Vc, + refs: &mut Vec>>, +) -> Result>> { type_exists(fs_path, FileSystemEntryType::File, refs).await } async fn dir_exists( - fs_path: FileSystemPathVc, - refs: &mut Vec, -) -> Result> { + fs_path: Vc, + refs: &mut Vec>>, +) -> Result>> { type_exists(fs_path, FileSystemEntryType::Directory, refs).await } async fn type_exists( - fs_path: FileSystemPathVc, + fs_path: Vc, ty: FileSystemEntryType, - refs: &mut Vec, -) -> Result> { + refs: &mut Vec>>, +) -> Result>> { let result = fs_path.resolve().await?.realpath_with_links().await?; for path in result.symlinks.iter() { - refs.push(AffectingResolvingAssetReferenceVc::new(*path).into()); + refs.push(Vc::upcast(AffectingResolvingAssetReference::new(*path))); } let path = result.path; Ok(if *path.get_type().await? == ty { @@ -390,7 +394,7 @@ enum ExportsFieldResult { /// Extracts the "exports" field out of the nearest package.json, parsing it /// into an appropriate [AliasMap] for lookups. #[turbo_tasks::function] -async fn exports_field(package_json_path: FileSystemPathVc) -> Result { +async fn exports_field(package_json_path: Vc) -> Result> { let read = read_package_json(package_json_path).await?; let package_json = match &*read { Some(json) => json, @@ -403,12 +407,12 @@ async fn exports_field(package_json_path: FileSystemPathVc) -> Result Ok(ExportsFieldResult::Some(exports).cell()), Err(err) => { - let issue: PackageJsonIssueVc = PackageJsonIssue { + PackageJsonIssue { path: package_json_path, error_message: err.to_string(), } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); Ok(ExportsFieldResult::None.cell()) } } @@ -418,7 +422,7 @@ async fn exports_field(package_json_path: FileSystemPathVc) -> Result, ), None, } @@ -426,7 +430,7 @@ enum ImportsFieldResult { /// Extracts the "imports" field out of the nearest package.json, parsing it /// into an appropriate [AliasMap] for lookups. #[turbo_tasks::function] -async fn imports_field(context: FileSystemPathVc) -> Result { +async fn imports_field(context: Vc) -> Result> { let package_json_context = find_context_file(context, package_json()).await?; let FindContextFileResult::Found(package_json_path, _refs) = &*package_json_context else { return Ok(ImportsFieldResult::None.cell()); @@ -444,37 +448,37 @@ async fn imports_field(context: FileSystemPathVc) -> Result Ok(ImportsFieldResult::Some(imports, *package_json_path).cell()), Err(err) => { - let issue: PackageJsonIssueVc = PackageJsonIssue { + PackageJsonIssue { path: *package_json_path, error_message: err.to_string(), } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); Ok(ImportsFieldResult::None.cell()) } } } #[turbo_tasks::function] -pub fn package_json() -> StringsVc { - StringsVc::cell(vec!["package.json".to_string()]) +pub fn package_json() -> Vc> { + Vc::cell(vec!["package.json".to_string()]) } #[turbo_tasks::value(shared)] pub enum FindContextFileResult { - Found(FileSystemPathVc, Vec), - NotFound(Vec), + Found(Vc, Vec>>), + NotFound(Vec>>), } #[turbo_tasks::function] pub async fn find_context_file( - context: FileSystemPathVc, - names: StringsVc, -) -> Result { + context: Vc, + names: Vc>, +) -> Result> { let mut refs = Vec::new(); let context_value = context.await?; for name in &*names.await? { - let fs_path = context.join(name); + let fs_path = context.join(name.clone()); if let Some(fs_path) = exists(fs_path, &mut refs).await? { return Ok(FindContextFileResult::Found(fs_path, refs).into()); } @@ -503,16 +507,16 @@ pub async fn find_context_file( #[turbo_tasks::value] struct FindPackageResult { - packages: Vec, - references: Vec, + packages: Vec>, + references: Vec>>, } #[turbo_tasks::function] async fn find_package( - context: FileSystemPathVc, + context: Vc, package_name: String, - options: ResolveModulesOptionsVc, -) -> Result { + options: Vc, +) -> Result> { let mut packages = vec![]; let mut references = vec![]; let options = options.await?; @@ -523,11 +527,11 @@ async fn find_package( let mut context_value = context.await?; // For clippy -- This explicit deref is necessary let root = &*root_vc.await?; - while context_value.is_inside(root) { + while context_value.is_inside_ref(root) { for name in names.iter() { - let fs_path = context.join(name); + let fs_path = context.join(name.clone()); if let Some(fs_path) = dir_exists(fs_path, &mut references).await? { - let fs_path = fs_path.join(&package_name); + let fs_path = fs_path.join(package_name.clone()); if let Some(fs_path) = dir_exists(fs_path, &mut references).await? { packages.push(fs_path); } @@ -542,7 +546,7 @@ async fn find_package( } } ResolveModules::Path(context) => { - let package_dir = context.join(&package_name); + let package_dir = context.join(package_name.clone()); if dir_exists(package_dir, &mut references).await?.is_some() { packages.push(package_dir.resolve().await?); } @@ -550,24 +554,24 @@ async fn find_package( ResolveModules::Registry(_, _) => todo!(), } } - Ok(FindPackageResultVc::cell(FindPackageResult { + Ok(FindPackageResult::cell(FindPackageResult { packages, references, })) } -fn merge_results(results: Vec) -> ResolveResultVc { +fn merge_results(results: Vec>) -> Vc { match results.len() { 0 => ResolveResult::unresolveable().into(), 1 => results.into_iter().next().unwrap(), - _ => ResolveResultVc::alternatives(results), + _ => ResolveResult::alternatives(results), } } fn merge_results_with_references( - results: Vec, - references: Vec, -) -> ResolveResultVc { + results: Vec>, + references: Vec>>, +) -> Vc { if references.is_empty() { return merge_results(results); } @@ -578,23 +582,23 @@ fn merge_results_with_references( .next() .unwrap() .add_references(references), - _ => ResolveResultVc::alternatives_with_references(results, references), + _ => ResolveResult::alternatives_with_references(results, references), } } #[turbo_tasks::function] pub async fn resolve_raw( - context: FileSystemPathVc, - path: PatternVc, + context: Vc, + path: Vc, force_in_context: bool, -) -> Result { - async fn to_result(path: FileSystemPathVc) -> Result { +) -> Result> { + async fn to_result(path: Vc) -> Result> { let RealPathResult { path, symlinks } = &*path.realpath_with_links().await?; Ok(ResolveResult::asset_with_references( - SourceAssetVc::new(*path).into(), + Vc::upcast(SourceAsset::new(*path)), symlinks .iter() - .map(|p| AffectingResolvingAssetReferenceVc::new(*p).into()) + .map(|p| Vc::upcast(AffectingResolvingAssetReference::new(*p))) .collect(), ) .into()) @@ -603,7 +607,7 @@ pub async fn resolve_raw( let pat = path.await?; if let Some(pat) = pat.filter_could_match("/ROOT/") { if let Some(pat) = pat.filter_could_not_match("/ROOT/fsd8nz8og54z") { - let path = PatternVc::new(pat); + let path = Pattern::new(pat); let matches = read_matches(context.root(), "/ROOT/".to_string(), true, path).await?; if matches.len() > 10000 { println!( @@ -642,10 +646,10 @@ pub async fn resolve_raw( #[turbo_tasks::function] pub async fn resolve( - context: FileSystemPathVc, - request: RequestVc, - options: ResolveOptionsVc, -) -> Result { + context: Vc, + request: Vc, + options: Vc, +) -> Result> { let raw_result = resolve_internal(context, request, options); let result = handle_resolve_plugins(context, request, options, raw_result); Ok(result) @@ -653,17 +657,17 @@ pub async fn resolve( #[turbo_tasks::function] async fn handle_resolve_plugins( - context: FileSystemPathVc, - request: RequestVc, - options: ResolveOptionsVc, - result: ResolveResultVc, -) -> Result { + context: Vc, + request: Vc, + options: Vc, + result: Vc, +) -> Result> { async fn apply_plugins_to_path( - path: FileSystemPathVc, - context: FileSystemPathVc, - request: RequestVc, - options: ResolveOptionsVc, - ) -> Result> { + path: Vc, + context: Vc, + request: Vc, + options: Vc, + ) -> Result>> { for plugin in &options.await?.plugins { if *plugin.after_resolve_condition().matches(path).await? { if let Some(result) = *plugin.after_resolve(path, context, request).await? { @@ -718,10 +722,10 @@ async fn handle_resolve_plugins( #[turbo_tasks::function] async fn resolve_internal( - context: FileSystemPathVc, - request: RequestVc, - options: ResolveOptionsVc, -) -> Result { + context: Vc, + request: Vc, + options: Vc, +) -> Result> { // This explicit deref of `options` is necessary #[allow(clippy::explicit_auto_deref)] let options_value: &ResolveOptions = &*options.await?; @@ -764,7 +768,7 @@ async fn resolve_internal( context, "".to_string(), *force_in_context, - PatternVc::new(path.clone()), + Pattern::new(path.clone()), ) .await?; for m in matches.iter() { @@ -798,7 +802,7 @@ async fn resolve_internal( for pattern in patterns { results.push(resolve_internal( context, - RequestVc::raw(Value::new(pattern), *force_in_context), + Request::raw(Value::new(pattern), *force_in_context), options, )); } @@ -813,9 +817,9 @@ async fn resolve_internal( Request::ServerRelative { path } => { let mut new_pat = path.clone(); new_pat.push_front(".".to_string().into()); - let relative = RequestVc::relative(Value::new(new_pat), true); + let relative = Request::relative(Value::new(new_pat), true); - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity: IssueSeverity::Error.cell(), request_type: "server relative import: not implemented yet".to_string(), request, @@ -826,25 +830,25 @@ async fn resolve_internal( relative to the file you are importing from." .to_string(), ), - source: OptionIssueSourceVc::none(), + source: OptionIssueSource::none(), } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); resolve_internal(context.root(), relative, options) } Request::Windows { path: _ } => { - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity: IssueSeverity::Error.cell(), request_type: "windows import: not implemented yet".to_string(), request, context, resolve_options: options, error_message: Some("windows imports are not implemented yet".to_string()), - source: OptionIssueSourceVc::none(), + source: OptionIssueSource::none(), } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); ResolveResult::unresolveable().into() } @@ -880,17 +884,17 @@ async fn resolve_internal( )) .into(), Request::Unknown { path } => { - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity: IssueSeverity::Error.cell(), request_type: format!("unknown import: `{}`", path), request, context, resolve_options: options, error_message: None, - source: OptionIssueSourceVc::none(), + source: OptionIssueSource::none(), } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); ResolveResult::unresolveable().into() } }; @@ -912,10 +916,10 @@ async fn resolve_internal( } async fn resolve_into_folder( - package_path: FileSystemPathVc, - options: ResolveOptionsVc, -) -> Result { - let package_json_path = package_path.join("package.json"); + package_path: Vc, + options: Vc, +) -> Result> { + let package_json_path = package_path.join("package.json".to_string()); let options_value = options.await?; for resolve_into_package in options_value.into_package.iter() { match resolve_into_package { @@ -927,23 +931,23 @@ async fn resolve_into_folder( escapes the current directory" ) })?; - let request = RequestVc::parse(Value::new(str.into())); + let request = Request::parse(Value::new(str.into())); return Ok(resolve_internal(package_path, request, options)); } ResolveIntoPackage::MainField(name) => { if let Some(package_json) = &*read_package_json(package_json_path).await? { if let Some(field_value) = package_json[name].as_str() { let request = - RequestVc::parse(Value::new(normalize_request(field_value).into())); + Request::parse(Value::new(normalize_request(field_value).into())); let result = &*resolve_internal(package_path, request, options).await?; // we are not that strict when a main field fails to resolve // we continue to try other alternatives - if !result.is_unresolveable() { + if !result.is_unresolveable_ref() { let mut result = result.clone(); - result.add_reference( - AffectingResolvingAssetReferenceVc::new(package_json_path).into(), - ); + result.add_reference_ref(Vc::upcast( + AffectingResolvingAssetReference::new(package_json_path), + )); return Ok(result.into()); } } @@ -974,13 +978,13 @@ async fn resolve_into_folder( } async fn resolve_module_request( - context: FileSystemPathVc, - options: ResolveOptionsVc, + context: Vc, + options: Vc, options_value: &ResolveOptions, module: &str, path: &Pattern, - _: &QueryMapVc, -) -> Result { + _: &Vc, +) -> Result> { // Check alias field for module aliases first for in_package in options_value.in_package.iter() { match in_package { @@ -1057,7 +1061,7 @@ async fn resolve_module_request( conditions, unspecified_conditions, } => { - let package_json_path = package_path.join("package.json"); + let package_json_path = package_path.join("package.json".to_string()); if let ExportsFieldResult::Some(exports_field) = &*exports_field(package_json_path).await? { @@ -1083,7 +1087,7 @@ async fn resolve_module_request( } let mut new_pat = path.clone(); new_pat.push_front(".".to_string().into()); - let relative = RequestVc::relative(Value::new(new_pat), true); + let relative = Request::relative(Value::new(new_pat), true); results.push(resolve_internal(*package_path, relative, options)); } } @@ -1096,11 +1100,11 @@ async fn resolve_module_request( async fn resolve_import_map_result( result: &ImportMapResult, - context: FileSystemPathVc, - original_context: FileSystemPathVc, - original_request: RequestVc, - options: ResolveOptionsVc, -) -> Result> { + context: Vc, + original_context: Vc, + original_request: Vc, + options: Vc, +) -> Result>> { Ok(match result { ImportMapResult::Result(result) => Some(*result), ImportMapResult::Alias(request, alias_context) => { @@ -1129,7 +1133,7 @@ async fn resolve_import_map_result( }) .try_join() .await?; - Some(ResolveResultVc::select_first( + Some(ResolveResult::select_first( results.into_iter().flatten().collect(), )) } @@ -1137,13 +1141,15 @@ async fn resolve_import_map_result( }) } +type ResolveImportMapResult = Result>>; + fn resolve_import_map_result_boxed<'a>( result: &'a ImportMapResult, - context: FileSystemPathVc, - original_context: FileSystemPathVc, - original_request: RequestVc, - options: ResolveOptionsVc, -) -> Pin>> + Send + 'a>> { + context: Vc, + original_context: Vc, + original_request: Vc, + options: Vc, +) -> Pin + Send + 'a>> { Box::pin(async move { resolve_import_map_result(result, context, original_context, original_request, options) .await @@ -1152,13 +1158,13 @@ fn resolve_import_map_result_boxed<'a>( async fn resolve_alias_field_result( result: &JsonValue, - refs: Vec, - package_path: FileSystemPathVc, - resolve_options: ResolveOptionsVc, - issue_context: FileSystemPathVc, + refs: Vec>>, + package_path: Vc, + resolve_options: Vc, + issue_context: Vc, issue_request: &str, field_name: &str, -) -> Result { +) -> Result> { if result.as_bool() == Some(false) { return Ok( ResolveResult::primary_with_references(PrimaryResolveResult::Ignore, refs).cell(), @@ -1167,36 +1173,36 @@ async fn resolve_alias_field_result( if let Some(value) = result.as_str() { return Ok(resolve_internal( package_path, - RequestVc::parse(Value::new(Pattern::Constant(value.to_string()))), + Request::parse(Value::new(Pattern::Constant(value.to_string()))), resolve_options, ) .add_references(refs)); } - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity: IssueSeverity::Error.cell(), context: issue_context, request_type: format!("alias field ({field_name})"), - request: RequestVc::parse(Value::new(Pattern::Constant(issue_request.to_string()))), + request: Request::parse(Value::new(Pattern::Constant(issue_request.to_string()))), resolve_options, error_message: Some(format!("invalid alias field value: {}", result)), - source: OptionIssueSourceVc::none(), + source: OptionIssueSource::none(), } - .cell(); - issue.as_issue().emit(); + .cell() + .emit(); Ok(ResolveResult::unresolveable_with_references(refs).cell()) } async fn resolved( - fs_path: FileSystemPathVc, - original_context: FileSystemPathVc, - original_request: RequestVc, + fs_path: Vc, + original_context: Vc, + original_request: Vc, ResolveOptions { resolved_map, in_package, .. }: &ResolveOptions, - options: ResolveOptionsVc, -) -> Result { + options: Vc, +) -> Result> { let RealPathResult { path, symlinks } = &*fs_path.realpath_with_links().await?; for in_package in in_package.iter() { match in_package { @@ -1253,24 +1259,24 @@ async fn resolved( } Ok(ResolveResult::asset_with_references( - SourceAssetVc::new(*path).into(), + Vc::upcast(SourceAsset::new(*path)), symlinks .iter() - .map(|p| AffectingResolvingAssetReferenceVc::new(*p).into()) + .map(|p| Vc::upcast(AffectingResolvingAssetReference::new(*p))) .collect(), ) .into()) } fn handle_exports_imports_field( - package_path: FileSystemPathVc, - package_json_path: FileSystemPathVc, - options: ResolveOptionsVc, + package_path: Vc, + package_json_path: Vc, + options: Vc, exports_imports_field: &AliasMap, path: &str, conditions: &BTreeMap, unspecified_conditions: &ConditionValue, -) -> Result { +) -> Result> { let mut results = Vec::new(); let mut conditions_state = HashMap::new(); let values = exports_imports_field @@ -1294,14 +1300,16 @@ fn handle_exports_imports_field( let mut resolved_results = Vec::new(); for path in results { if let Some(path) = normalize_path(path) { - let request = RequestVc::relative(Value::new(format!("./{}", path).into()), false); + let request = Request::relative(Value::new(format!("./{}", path).into()), false); resolved_results.push(resolve_internal(package_path, request, options)); } } // other options do not apply anymore when an exports field exist Ok(merge_results_with_references( resolved_results, - vec![AffectingResolvingAssetReferenceVc::new(package_json_path).into()], + vec![Vc::upcast(AffectingResolvingAssetReference::new( + package_json_path, + ))], )) } @@ -1310,29 +1318,29 @@ fn handle_exports_imports_field( /// static strings or conditions like `import` or `require` to handle ESM/CJS /// with differently compiled files. async fn resolve_package_internal_with_imports_field( - context: FileSystemPathVc, - request: RequestVc, - resolve_options: ResolveOptionsVc, + context: Vc, + request: Vc, + resolve_options: Vc, pattern: &Pattern, conditions: &BTreeMap, unspecified_conditions: &ConditionValue, -) -> Result { +) -> Result> { let Pattern::Constant(specifier) = pattern else { bail!("PackageInternal requests can only be Constant strings"); }; // https://github.com/nodejs/node/blob/1b177932/lib/internal/modules/esm/resolve.js#L615-L619 if specifier == "#" || specifier.starts_with("#/") || specifier.ends_with('/') { - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity: IssueSeverity::Error.cell(), context, request_type: format!("package imports request: `{specifier}`"), request, resolve_options, error_message: None, - source: OptionIssueSourceVc::none(), + source: OptionIssueSource::none(), } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); return Ok(ResolveResult::unresolveable().into()); } @@ -1355,13 +1363,13 @@ async fn resolve_package_internal_with_imports_field( #[turbo_tasks::value] pub struct AffectingResolvingAssetReference { - path: FileSystemPathVc, + path: Vc, } #[turbo_tasks::value_impl] -impl AffectingResolvingAssetReferenceVc { +impl AffectingResolvingAssetReference { #[turbo_tasks::function] - pub fn new(path: FileSystemPathVc) -> Self { + pub fn new(path: Vc) -> Vc { Self::cell(AffectingResolvingAssetReference { path }) } } @@ -1369,16 +1377,16 @@ impl AffectingResolvingAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for AffectingResolvingAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset(SourceAssetVc::new(self.path).into()).into() + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast(SourceAsset::new(self.path))).into() } } #[turbo_tasks::value_impl] impl ValueToString for AffectingResolvingAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "resolving is affected by {}", self.path.to_string().await? ))) @@ -1386,18 +1394,18 @@ impl ValueToString for AffectingResolvingAssetReference { } pub async fn handle_resolve_error( - result: ResolveResultVc, + result: Vc, reference_type: Value, - origin_path: FileSystemPathVc, - request: RequestVc, - resolve_options: ResolveOptionsVc, - source: OptionIssueSourceVc, - severity: IssueSeverityVc, -) -> Result { + origin_path: Vc, + request: Vc, + resolve_options: Vc, + source: Vc, + severity: Vc, +) -> Result> { Ok(match result.is_unresolveable().await { Ok(unresolveable) => { if *unresolveable { - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity, context: origin_path, request_type: format!("{} request", reference_type.into_value()), @@ -1406,13 +1414,13 @@ pub async fn handle_resolve_error( error_message: None, source, } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); } result } Err(err) => { - let issue: ResolvingIssueVc = ResolvingIssue { + ResolvingIssue { severity, context: origin_path, request_type: format!("{} request", reference_type.into_value()), @@ -1421,8 +1429,8 @@ pub async fn handle_resolve_error( error_message: Some(err.to_string()), source, } - .into(); - issue.as_issue().emit(); + .cell() + .emit(); ResolveResult::unresolveable().into() } }) @@ -1437,23 +1445,23 @@ pub enum ModulePart { /// all exports are unused. ModuleEvaluation, /// Represents an export of a module. - Export(StringVc), + Export(Vc), /// A pointer to a specific part. Internal(u32), } #[turbo_tasks::value_impl] -impl ModulePartVc { +impl ModulePart { #[turbo_tasks::function] - pub fn module_evaluation() -> Self { + pub fn module_evaluation() -> Vc { ModulePart::ModuleEvaluation.cell() } #[turbo_tasks::function] - pub fn export(export: String) -> Self { - ModulePart::Export(StringVc::cell(export)).cell() + pub fn export(export: String) -> Vc { + ModulePart::Export(Vc::cell(export)).cell() } #[turbo_tasks::function] - pub fn internal(id: u32) -> Self { + pub fn internal(id: u32) -> Vc { ModulePart::Internal(id).cell() } } diff --git a/crates/turbopack-core/src/resolve/node.rs b/crates/turbopack-core/src/resolve/node.rs index abcf3cc85b5e82..c36ec18e7ac546 100644 --- a/crates/turbopack-core/src/resolve/node.rs +++ b/crates/turbopack-core/src/resolve/node.rs @@ -1,12 +1,13 @@ -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; use super::options::{ ConditionValue, ResolutionConditions, ResolveInPackage, ResolveIntoPackage, ResolveModules, - ResolveOptions, ResolveOptionsVc, + ResolveOptions, }; #[turbo_tasks::function] -pub fn node_cjs_resolve_options(root: FileSystemPathVc) -> ResolveOptionsVc { +pub fn node_cjs_resolve_options(root: Vc) -> Vc { let conditions: ResolutionConditions = [ ("node".to_string(), ConditionValue::Set), ("require".to_string(), ConditionValue::Set), diff --git a/crates/turbopack-core/src/resolve/options.rs b/crates/turbopack-core/src/resolve/options.rs index f817561681c539..b13992c3873710 100644 --- a/crates/turbopack-core/src/resolve/options.rs +++ b/crates/turbopack-core/src/resolve/options.rs @@ -3,16 +3,15 @@ use std::{collections::BTreeMap, future::Future, pin::Pin}; use anyhow::Result; use serde::{Deserialize, Serialize}; use turbo_tasks::{ - debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs, TryJoinIterExt, Value, - ValueToString, ValueToStringVc, + debug::ValueDebugFormat, trace::TraceRawVcs, TryJoinIterExt, Value, ValueToString, Vc, }; -use turbo_tasks_fs::{glob::GlobVc, FileSystemPathVc}; +use turbo_tasks_fs::{glob::Glob, FileSystemPath}; use super::{ alias_map::{AliasMap, AliasTemplate}, - AliasPattern, PrimaryResolveResult, ResolveResult, ResolveResultVc, + AliasPattern, PrimaryResolveResult, ResolveResult, }; -use crate::resolve::{parse::RequestVc, plugin::ResolvePluginVc}; +use crate::resolve::{parse::Request, plugin::ResolvePlugin}; #[turbo_tasks::value(shared)] #[derive(Hash, Debug)] @@ -25,13 +24,13 @@ pub struct LockedVersions {} pub enum ResolveModules { /// when inside of path, use the list of directories to /// resolve inside these - Nested(FileSystemPathVc, Vec), + Nested(Vc, Vec), /// look into that directory - Path(FileSystemPathVc), + Path(Vc), /// lookup versions based on lockfile in the registry filesystem /// registry filesystem is assumed to have structure like /// @scope/module/version/ - Registry(FileSystemPathVc, LockedVersionsVc), + Registry(Vc, Vc), } #[derive(TraceRawVcs, Hash, PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)] @@ -92,21 +91,21 @@ pub enum ResolveInPackage { pub enum ImportMapping { External(Option), /// An already resolved result that will be returned directly. - Direct(ResolveResultVc), + Direct(Vc), /// A request alias that will be resolved first, and fall back to resolving /// the original request if it fails. Useful for the tsconfig.json /// `compilerOptions.paths` option and Next aliases. - PrimaryAlternative(String, Option), + PrimaryAlternative(String, Option>), Ignore, Empty, - Alternatives(Vec), - Dynamic(ImportMappingReplacementVc), + Alternatives(Vec>), + Dynamic(Vc>), } impl ImportMapping { pub fn primary_alternatives( list: Vec, - context: Option, + context: Option>, ) -> ImportMapping { if list.is_empty() { ImportMapping::Ignore @@ -122,8 +121,8 @@ impl ImportMapping { } } -impl AliasTemplate for ImportMappingVc { - type Output<'a> = Pin> + Send + 'a>>; +impl AliasTemplate for Vc { + type Output<'a> = Pin>> + Send + 'a>>; fn replace<'a>(&'a self, capture: &'a str) -> Self::Output<'a> { Box::pin(async move { @@ -150,7 +149,7 @@ impl AliasTemplate for ImportMappingVc { .await?, ), ImportMapping::Dynamic(replacement) => { - (*replacement.replace(capture).await?).clone() + (*replacement.replace(capture.to_string()).await?).clone() } } .cell()) @@ -161,12 +160,12 @@ impl AliasTemplate for ImportMappingVc { #[turbo_tasks::value(shared)] #[derive(Clone, Default)] pub struct ImportMap { - map: AliasMap, + map: AliasMap>, } impl ImportMap { /// Creates a new import map. - pub fn new(map: AliasMap) -> ImportMap { + pub fn new(map: AliasMap>) -> ImportMap { Self { map } } @@ -176,13 +175,13 @@ impl ImportMap { } /// Extends the import map with another import map. - pub fn extend(&mut self, other: &ImportMap) { + pub fn extend_ref(&mut self, other: &ImportMap) { let Self { map } = other.clone(); self.map.extend(map); } /// Inserts an alias into the import map. - pub fn insert_alias(&mut self, alias: AliasPattern, mapping: ImportMappingVc) { + pub fn insert_alias(&mut self, alias: AliasPattern, mapping: Vc) { self.map.insert(alias, mapping); } @@ -190,7 +189,7 @@ impl ImportMap { pub fn insert_exact_alias<'a>( &mut self, pattern: impl Into + 'a, - mapping: ImportMappingVc, + mapping: Vc, ) { self.map.insert(AliasPattern::exact(pattern), mapping); } @@ -199,7 +198,7 @@ impl ImportMap { pub fn insert_wildcard_alias<'a>( &mut self, prefix: impl Into + 'a, - mapping: ImportMappingVc, + mapping: Vc, ) { self.map.insert(AliasPattern::wildcard(prefix, ""), mapping); } @@ -209,7 +208,7 @@ impl ImportMap { &mut self, prefix: impl Into + 'p, suffix: impl Into + 's, - mapping: ImportMappingVc, + mapping: Vc, ) { self.map .insert(AliasPattern::wildcard(prefix, suffix), mapping); @@ -220,7 +219,7 @@ impl ImportMap { pub fn insert_singleton_alias<'a>( &mut self, prefix: impl Into + 'a, - context_path: FileSystemPathVc, + context_path: Vc, ) { let prefix = prefix.into(); let wildcard_prefix = prefix.clone() + "/"; @@ -237,12 +236,12 @@ impl ImportMap { } #[turbo_tasks::value_impl] -impl ImportMapVc { +impl ImportMap { /// Extends the underlying [ImportMap] with another [ImportMap]. #[turbo_tasks::function] - pub async fn extend(self, other: ImportMapVc) -> Result { + pub async fn extend(self: Vc, other: Vc) -> Result> { let mut import_map = self.await?.clone_value(); - import_map.extend(&*other.await?); + import_map.extend_ref(&*other.await?); Ok(import_map.cell()) } } @@ -250,22 +249,22 @@ impl ImportMapVc { #[turbo_tasks::value(shared)] #[derive(Clone, Default)] pub struct ResolvedMap { - pub by_glob: Vec<(FileSystemPathVc, GlobVc, ImportMappingVc)>, + pub by_glob: Vec<(Vc, Vc, Vc)>, } #[turbo_tasks::value(shared)] #[derive(Clone, Debug)] pub enum ImportMapResult { - Result(ResolveResultVc), - Alias(RequestVc, Option), + Result(Vc), + Alias(Vc, Option>), Alternatives(Vec), NoEntry, } async fn import_mapping_to_result( - mapping: ImportMappingVc, - context: FileSystemPathVc, - request: RequestVc, + mapping: Vc, + context: Vc, + request: Vc, ) -> Result { Ok(match &*mapping.await? { ImportMapping::Direct(result) => ImportMapResult::Result(*result), @@ -286,7 +285,7 @@ async fn import_mapping_to_result( ImportMapResult::Result(ResolveResult::primary(PrimaryResolveResult::Empty).into()) } ImportMapping::PrimaryAlternative(name, context) => { - let request = RequestVc::parse(Value::new(name.to_string().into())); + let request = Request::parse(Value::new(name.to_string().into())); ImportMapResult::Alias(request, *context) } @@ -305,9 +304,9 @@ async fn import_mapping_to_result( #[turbo_tasks::value_impl] impl ValueToString for ImportMapResult { #[turbo_tasks::function] - async fn to_string(&self) -> Result { + async fn to_string(&self) -> Result> { match self { - ImportMapResult::Result(_) => Ok(StringVc::cell("Resolved by import map".to_string())), + ImportMapResult::Result(_) => Ok(Vc::cell("Resolved by import map".to_string())), ImportMapResult::Alias(request, context) => { let s = if let Some(path) = context { format!( @@ -318,7 +317,7 @@ impl ValueToString for ImportMapResult { } else { format!("aliased to {}", request.to_string().await?) }; - Ok(StringVc::cell(s)) + Ok(Vc::cell(s)) } ImportMapResult::Alternatives(alternatives) => { let strings = alternatives @@ -330,9 +329,9 @@ impl ValueToString for ImportMapResult { .iter() .map(|string| string.as_str()) .collect::>(); - Ok(StringVc::cell(strings.join(" | "))) + Ok(Vc::cell(strings.join(" | "))) } - ImportMapResult::NoEntry => Ok(StringVc::cell("No import map entry".to_string())), + ImportMapResult::NoEntry => Ok(Vc::cell("No import map entry".to_string())), } } } @@ -342,21 +341,21 @@ impl ValueToString for ImportMapResult { // cycle detected when computing type of // `resolve::options::import_mapping_to_result::{opaque#0}` fn import_mapping_to_result_boxed( - mapping: ImportMappingVc, - context: FileSystemPathVc, - request: RequestVc, + mapping: Vc, + context: Vc, + request: Vc, ) -> Pin> + Send>> { Box::pin(async move { import_mapping_to_result(mapping, context, request).await }) } #[turbo_tasks::value_impl] -impl ImportMapVc { +impl ImportMap { #[turbo_tasks::function] pub async fn lookup( - self, - context: FileSystemPathVc, - request: RequestVc, - ) -> Result { + self: Vc, + context: Vc, + request: Vc, + ) -> Result> { let this = self.await?; // TODO lookup pattern if let Some(request_string) = request.await?.request() { @@ -375,14 +374,14 @@ impl ImportMapVc { } #[turbo_tasks::value_impl] -impl ResolvedMapVc { +impl ResolvedMap { #[turbo_tasks::function] pub async fn lookup( - self, - resolved: FileSystemPathVc, - context: FileSystemPathVc, - request: RequestVc, - ) -> Result { + self: Vc, + resolved: Vc, + context: Vc, + request: Vc, + ) -> Result> { let this = self.await?; let resolved = resolved.await?; for (root, glob, mapping) in this.by_glob.iter() { @@ -410,28 +409,31 @@ pub struct ResolveOptions { /// How to resolve in packages. pub in_package: Vec, /// An import map to use before resolving a request. - pub import_map: Option, + pub import_map: Option>, /// An import map to use when a request is otherwise unresolveable. - pub fallback_import_map: Option, - pub resolved_map: Option, - pub plugins: Vec, + pub fallback_import_map: Option>, + pub resolved_map: Option>, + pub plugins: Vec>>, pub placeholder_for_future_extensions: (), } #[turbo_tasks::value_impl] -impl ResolveOptionsVc { +impl ResolveOptions { #[turbo_tasks::function] - pub async fn modules(self) -> Result { + pub async fn modules(self: Vc) -> Result> { Ok(ResolveModulesOptions { modules: self.await?.modules.clone(), } .into()) } - /// Returns a new [ResolveOptionsVc] with its import map extended to include - /// the given import map. + /// Returns a new [Vc] with its import map extended to + /// include the given import map. #[turbo_tasks::function] - pub async fn with_extended_import_map(self, import_map: ImportMapVc) -> Result { + pub async fn with_extended_import_map( + self: Vc, + import_map: Vc, + ) -> Result> { let mut resolve_options = self.await?.clone_value(); resolve_options.import_map = Some( resolve_options @@ -442,10 +444,13 @@ impl ResolveOptionsVc { Ok(resolve_options.into()) } - /// Returns a new [ResolveOptionsVc] with its fallback import map extended + /// Returns a new [Vc] with its fallback import map extended /// to include the given import map. #[turbo_tasks::function] - pub async fn with_extended_fallback_import_map(self, import_map: ImportMapVc) -> Result { + pub async fn with_extended_fallback_import_map( + self: Vc, + import_map: Vc, + ) -> Result> { let mut resolve_options = self.await?.clone_value(); resolve_options.fallback_import_map = Some( resolve_options @@ -464,7 +469,9 @@ pub struct ResolveModulesOptions { } #[turbo_tasks::function] -pub async fn resolve_modules_options(options: ResolveOptionsVc) -> Result { +pub async fn resolve_modules_options( + options: Vc, +) -> Result> { Ok(ResolveModulesOptions { modules: options.await?.modules.clone(), } @@ -473,6 +480,10 @@ pub async fn resolve_modules_options(options: ResolveOptionsVc) -> Result ImportMappingVc; - fn result(&self, context: FileSystemPathVc, request: RequestVc) -> ImportMapResultVc; + fn replace(self: Vc, capture: String) -> Vc; + fn result( + self: Vc, + context: Vc, + request: Vc, + ) -> Vc; } diff --git a/crates/turbopack-core/src/resolve/origin.rs b/crates/turbopack-core/src/resolve/origin.rs index f6ab28e10cb10c..201c0be70972be 100644 --- a/crates/turbopack-core/src/resolve/origin.rs +++ b/crates/turbopack-core/src/resolve/origin.rs @@ -1,13 +1,9 @@ use anyhow::Result; -use turbo_tasks::Value; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Upcast, Value, Vc}; +use turbo_tasks_fs::FileSystemPath; -use super::{options::ResolveOptionsVc, parse::RequestVc, ResolveResult, ResolveResultVc}; -use crate::{ - asset::AssetOptionVc, - context::{AssetContext, AssetContextVc}, - reference_type::ReferenceType, -}; +use super::{options::ResolveOptions, parse::Request, ResolveResult}; +use crate::{asset::AssetOption, context::AssetContext, reference_type::ReferenceType}; /// A location where resolving can occur from. It carries some meta information /// that are needed for resolving from here. @@ -17,72 +13,97 @@ pub trait ResolveOrigin { /// since that might be needed to infer custom resolving options for that /// specific file. But usually only the directory is relevant for the real /// resolving. - fn origin_path(&self) -> FileSystemPathVc; + fn origin_path(self: Vc) -> Vc; /// The AssetContext that carries the configuration for building that /// subgraph. - fn context(&self) -> AssetContextVc; + fn context(self: Vc) -> Vc>; /// Get an inner asset form this origin that doesn't require resolving but /// is directly attached - fn get_inner_asset(&self, _request: RequestVc) -> AssetOptionVc { - AssetOptionVc::cell(None) + fn get_inner_asset(self: Vc, _request: Vc) -> Vc { + Vc::cell(None) } } -#[turbo_tasks::value_impl] -impl ResolveOriginVc { - // TODO it would be nice if these methods can be moved to the trait to allow - // overriding it, but currently this is not possible due to the way transitions - // work. Maybe transitions should be decorators on ResolveOrigin? - +// TODO it would be nice if these methods can be moved to the trait to allow +// overriding it, but currently we explicitly disallow it due to the way +// transitions work. Maybe transitions should be decorators on ResolveOrigin? +pub trait ResolveOriginExt { /// Resolve to an asset from that origin. Custom resolve options can be /// passed. Otherwise provide `origin.resolve_options()` unmodified. - #[turbo_tasks::function] - pub async fn resolve_asset( - self, - request: RequestVc, - options: ResolveOptionsVc, + fn resolve_asset( + self: Vc, + request: Vc, + options: Vc, reference_type: Value, - ) -> Result { - if let Some(asset) = *self.get_inner_asset(request).await? { - return Ok(ResolveResult::asset(asset).cell()); - } - Ok(self - .context() - .resolve_asset(self.origin_path(), request, options, reference_type)) - } + ) -> Vc; /// Get the resolve options that apply for this origin. - #[turbo_tasks::function] - pub fn resolve_options(self, reference_type: Value) -> ResolveOptionsVc { + fn resolve_options(self: Vc, reference_type: Value) -> Vc; + + /// Adds a transition that is used for resolved assets. + fn with_transition(self: Vc, transition: String) -> Vc>; +} + +impl ResolveOriginExt for T +where + T: ResolveOrigin + Upcast>, +{ + fn resolve_asset( + self: Vc, + request: Vc, + options: Vc, + reference_type: Value, + ) -> Vc { + resolve_asset(Vc::upcast(self), request, options, reference_type) + } + + fn resolve_options(self: Vc, reference_type: Value) -> Vc { self.context() .resolve_options(self.origin_path(), reference_type) } - /// Adds a transition that is used for resolved assets. - #[turbo_tasks::function] - pub fn with_transition(self, transition: &str) -> Self { - ResolveOriginWithTransition { - previous: self, - transition: transition.to_string(), - } - .cell() - .into() + fn with_transition(self: Vc, transition: String) -> Vc> { + Vc::upcast( + ResolveOriginWithTransition { + previous: Vc::upcast(self), + transition, + } + .cell(), + ) } } +#[turbo_tasks::function] +async fn resolve_asset( + resolve_origin: Vc>, + request: Vc, + options: Vc, + reference_type: Value, +) -> Result> { + if let Some(asset) = *resolve_origin.get_inner_asset(request).await? { + return Ok(ResolveResult::asset(asset).cell()); + } + Ok(resolve_origin.context().resolve_asset( + resolve_origin.origin_path(), + request, + options, + reference_type, + )) +} + /// A resolve origin for some path and context without additional modifications. #[turbo_tasks::value] pub struct PlainResolveOrigin { - context: AssetContextVc, - origin_path: FileSystemPathVc, + context: Vc>, + origin_path: Vc, } #[turbo_tasks::value_impl] -impl PlainResolveOriginVc { +impl PlainResolveOrigin { #[turbo_tasks::function] - pub fn new(context: AssetContextVc, origin_path: FileSystemPathVc) -> Self { + pub fn new(context: Vc>, origin_path: Vc) -> Vc { PlainResolveOrigin { context, origin_path, @@ -94,12 +115,12 @@ impl PlainResolveOriginVc { #[turbo_tasks::value_impl] impl ResolveOrigin for PlainResolveOrigin { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.origin_path } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { + fn context(&self) -> Vc> { self.context } } @@ -107,24 +128,26 @@ impl ResolveOrigin for PlainResolveOrigin { /// Wraps a ResolveOrigin to add a transition. #[turbo_tasks::value] struct ResolveOriginWithTransition { - previous: ResolveOriginVc, + previous: Vc>, transition: String, } #[turbo_tasks::value_impl] impl ResolveOrigin for ResolveOriginWithTransition { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.previous.origin_path() } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { - self.previous.context().with_transition(&self.transition) + fn context(&self) -> Vc> { + self.previous + .context() + .with_transition(self.transition.clone()) } #[turbo_tasks::function] - fn get_inner_asset(&self, request: RequestVc) -> AssetOptionVc { + fn get_inner_asset(&self, request: Vc) -> Vc { self.previous.get_inner_asset(request) } } diff --git a/crates/turbopack-core/src/resolve/parse.rs b/crates/turbopack-core/src/resolve/parse.rs index 6418f41a508567..3676a0ff39414d 100644 --- a/crates/turbopack-core/src/resolve/parse.rs +++ b/crates/turbopack-core/src/resolve/parse.rs @@ -2,9 +2,9 @@ use anyhow::Result; use indexmap::IndexMap; use lazy_static::lazy_static; use regex::Regex; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc}; -use super::pattern::{Pattern, QueryMapVc}; +use super::pattern::{Pattern, QueryMap}; #[turbo_tasks::value] #[derive(Hash, Clone, Debug)] @@ -20,7 +20,7 @@ pub enum Request { Module { module: String, path: Pattern, - query: QueryMapVc, + query: Vc, }, ServerRelative { path: Pattern, @@ -41,7 +41,7 @@ pub enum Request { }, Dynamic, Alternatives { - requests: Vec, + requests: Vec>, }, } @@ -82,7 +82,7 @@ impl Request { }) } - pub fn parse(mut request: Pattern) -> Self { + pub fn parse_ref(mut request: Pattern) -> Self { request.normalize(); match request { Pattern::Dynamic => Request::Dynamic, @@ -125,7 +125,7 @@ impl Request { return Request::Module { module: module.as_str().to_string(), path: path.as_str().to_string().into(), - query: QueryMapVc::cell(query.map(|q| { + query: Vc::cell(query.map(|q| { IndexMap::from_iter(qstring::QString::from(q.as_str())) })), }; @@ -137,7 +137,7 @@ impl Request { Pattern::Concatenation(list) => { let mut iter = list.into_iter(); if let Some(first) = iter.next() { - let mut result = Self::parse(first); + let mut result = Self::parse_ref(first); match &mut result { Request::Raw { path, .. } => { path.extend(iter); @@ -159,7 +159,7 @@ impl Request { path.extend(iter); } Request::Empty => { - result = Request::parse(Pattern::Concatenation(iter.collect())) + result = Request::parse_ref(Pattern::Concatenation(iter.collect())) } Request::PackageInternal { path } => { path.extend(iter); @@ -181,7 +181,7 @@ impl Request { Pattern::Alternatives(list) => Request::Alternatives { requests: list .into_iter() - .map(|p| RequestVc::parse(Value::new(p))) + .map(|p| Request::parse(Value::new(p))) .collect(), }, } @@ -189,19 +189,19 @@ impl Request { } #[turbo_tasks::value_impl] -impl RequestVc { +impl Request { #[turbo_tasks::function] - pub fn parse(request: Value) -> Self { - Self::cell(Request::parse(request.into_value())) + pub fn parse(request: Value) -> Vc { + Self::cell(Request::parse_ref(request.into_value())) } #[turbo_tasks::function] - pub fn parse_string(request: String) -> Self { - Self::cell(Request::parse(request.into())) + pub fn parse_string(request: String) -> Vc { + Self::cell(Request::parse_ref(request.into())) } #[turbo_tasks::function] - pub fn raw(request: Value, force_in_context: bool) -> Self { + pub fn raw(request: Value, force_in_context: bool) -> Vc { Self::cell(Request::Raw { path: request.into_value(), force_in_context, @@ -209,7 +209,7 @@ impl RequestVc { } #[turbo_tasks::function] - pub fn relative(request: Value, force_in_context: bool) -> Self { + pub fn relative(request: Value, force_in_context: bool) -> Vc { Self::cell(Request::Relative { path: request.into_value(), force_in_context, @@ -217,7 +217,7 @@ impl RequestVc { } #[turbo_tasks::function] - pub fn module(module: String, path: Value, query: QueryMapVc) -> Self { + pub fn module(module: String, path: Value, query: Vc) -> Vc { Self::cell(Request::Module { module, path: path.into_value(), @@ -226,7 +226,7 @@ impl RequestVc { } #[turbo_tasks::function] - pub async fn as_relative(self) -> Result { + pub async fn as_relative(self: Vc) -> Result> { let this = self.await?; Ok(match &*this { Request::Empty @@ -257,11 +257,7 @@ impl RequestVc { Self::parse(Value::new(pat)) } Request::Alternatives { requests } => { - let requests = requests - .iter() - .copied() - .map(RequestVc::as_relative) - .collect(); + let requests = requests.iter().copied().map(Request::as_relative).collect(); Request::Alternatives { requests }.cell() } }) @@ -271,8 +267,8 @@ impl RequestVc { #[turbo_tasks::value_impl] impl ValueToString for Request { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(match self { + async fn to_string(&self) -> Result> { + Ok(Vc::cell(match self { Request::Raw { path, force_in_context, diff --git a/crates/turbopack-core/src/resolve/pattern.rs b/crates/turbopack-core/src/resolve/pattern.rs index fca1fb43965c81..9617d2bdff7d96 100644 --- a/crates/turbopack-core/src/resolve/pattern.rs +++ b/crates/turbopack-core/src/resolve/pattern.rs @@ -5,21 +5,19 @@ use indexmap::IndexMap; use lazy_static::lazy_static; use regex::Regex; use serde::{Deserialize, Serialize}; -use turbo_tasks::{ - primitives::StringVc, trace::TraceRawVcs, Value, ValueToString, ValueToStringVc, -}; +use turbo_tasks::{trace::TraceRawVcs, Value, ValueToString, Vc}; use turbo_tasks_fs::{ - DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc, LinkContent, LinkType, + DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath, LinkContent, LinkType, }; #[turbo_tasks::value(transparent)] pub struct QueryMap(#[turbo_tasks(trace_ignore)] Option>); #[turbo_tasks::value_impl] -impl QueryMapVc { +impl QueryMap { #[turbo_tasks::function] - pub fn none() -> Self { - Self::cell(None) + pub fn none() -> Vc { + Vc::cell(None) } } @@ -525,16 +523,16 @@ impl Pattern { } } -impl PatternVc { - pub fn new(pattern: Pattern) -> Self { - PatternVc::new_internal(Value::new(pattern)) +impl Pattern { + pub fn new(pattern: Pattern) -> Vc { + Pattern::new_internal(Value::new(pattern)) } } #[turbo_tasks::value_impl] -impl PatternVc { +impl Pattern { #[turbo_tasks::function] - fn new_internal(pattern: Value) -> Self { + fn new_internal(pattern: Value) -> Vc { Self::cell(pattern.into_value()) } } @@ -630,15 +628,15 @@ impl Display for Pattern { #[turbo_tasks::value_impl] impl ValueToString for Pattern { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell(self.to_string()) + fn to_string(&self) -> Vc { + Vc::cell(self.to_string()) } } #[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, TraceRawVcs, Serialize, Deserialize)] pub enum PatternMatch { - File(String, FileSystemPathVc), - Directory(String, FileSystemPathVc), + File(String, Vc), + Directory(String, Vc), } // TODO this isn't super efficient @@ -655,11 +653,11 @@ pub struct PatternMatches(Vec); /// symlinks when they are interested in that. #[turbo_tasks::function] pub async fn read_matches( - context: FileSystemPathVc, + context: Vc, prefix: String, force_in_context: bool, - pattern: PatternVc, -) -> Result { + pattern: Vc, +) -> Result> { let mut prefix = prefix; let pat = pattern.await?; let mut results = Vec::new(); @@ -677,15 +675,15 @@ pub async fn read_matches( if until_end { if handled.insert(str) { if let Some(fs_path) = &*if force_in_context { - context.try_join_inside(str).await? + context.try_join_inside(str.to_string()).await? } else { - context.try_join(str).await? + context.try_join(str.to_string()).await? } { let fs_path = fs_path.resolve().await?; // This explicit deref of `context` is necessary #[allow(clippy::explicit_auto_deref)] let should_match = - !force_in_context || fs_path.await?.is_inside(&*context.await?); + !force_in_context || fs_path.await?.is_inside_ref(&*context.await?); if should_match { let len = prefix.len(); @@ -722,9 +720,9 @@ pub async fn read_matches( let subpath = &str[..=str.rfind('/').unwrap()]; if handled.insert(subpath) { if let Some(fs_path) = &*if force_in_context { - context.try_join_inside(subpath).await? + context.try_join_inside(subpath.to_string()).await? } else { - context.try_join(subpath).await? + context.try_join(subpath.to_string()).await? } { let fs_path = fs_path.resolve().await?; let len = prefix.len(); @@ -863,7 +861,7 @@ pub async fn read_matches( results.extend(nested.await?.iter().cloned()); } results.sort(); - Ok(PatternMatchesVc::cell(results)) + Ok(Vc::cell(results)) } } diff --git a/crates/turbopack-core/src/resolve/plugin.rs b/crates/turbopack-core/src/resolve/plugin.rs index 8902a19c6dc009..84eaaad6c5d6c5 100644 --- a/crates/turbopack-core/src/resolve/plugin.rs +++ b/crates/turbopack-core/src/resolve/plugin.rs @@ -1,25 +1,25 @@ use anyhow::Result; -use turbo_tasks::primitives::BoolVc; -use turbo_tasks_fs::{glob::GlobVc, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{glob::Glob, FileSystemPath}; -use crate::resolve::{parse::RequestVc, ResolveResultOptionVc}; +use crate::resolve::{parse::Request, ResolveResultOption}; /// A condition which determines if the hooks of a resolve plugin gets called. #[turbo_tasks::value] pub struct ResolvePluginCondition { - root: FileSystemPathVc, - glob: GlobVc, + root: Vc, + glob: Vc, } #[turbo_tasks::value_impl] -impl ResolvePluginConditionVc { +impl ResolvePluginCondition { #[turbo_tasks::function] - pub fn new(root: FileSystemPathVc, glob: GlobVc) -> Self { + pub fn new(root: Vc, glob: Vc) -> Vc { ResolvePluginCondition { root, glob }.cell() } #[turbo_tasks::function] - pub async fn matches(self, fs_path: FileSystemPathVc) -> Result { + pub async fn matches(self: Vc, fs_path: Vc) -> Result> { let this = self.await?; let root = this.root.await?; let glob = this.glob.await?; @@ -28,26 +28,26 @@ impl ResolvePluginConditionVc { if let Some(path) = root.get_path_to(&path) { if glob.execute(path) { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } - Ok(BoolVc::cell(false)) + Ok(Vc::cell(false)) } } #[turbo_tasks::value_trait] pub trait ResolvePlugin { /// A condition which determines if the hooks gets called. - fn after_resolve_condition(&self) -> ResolvePluginConditionVc; + fn after_resolve_condition(self: Vc) -> Vc; /// This hook gets called when a full filepath has been resolved and the /// condition matches. If a value is returned it replaces the resolve /// result. fn after_resolve( - &self, - fs_path: FileSystemPathVc, - context: FileSystemPathVc, - request: RequestVc, - ) -> ResolveResultOptionVc; + self: Vc, + fs_path: Vc, + context: Vc, + request: Vc, + ) -> Vc; } diff --git a/crates/turbopack-core/src/server_fs.rs b/crates/turbopack-core/src/server_fs.rs index 0855294b2e5700..b4dd139cc09b00 100644 --- a/crates/turbopack-core/src/server_fs.rs +++ b/crates/turbopack-core/src/server_fs.rs @@ -1,17 +1,16 @@ use anyhow::{bail, Result}; -use turbo_tasks::{primitives::StringVc, CompletionVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{Completion, ValueToString, Vc}; use turbo_tasks_fs::{ - DirectoryContentVc, FileContentVc, FileMetaVc, FileSystem, FileSystemPathVc, FileSystemVc, - LinkContentVc, + DirectoryContent, FileContent, FileMeta, FileSystem, FileSystemPath, LinkContent, }; #[turbo_tasks::value] pub struct ServerFileSystem {} #[turbo_tasks::value_impl] -impl ServerFileSystemVc { +impl ServerFileSystem { #[turbo_tasks::function] - pub fn new() -> Self { + pub fn new() -> Vc { Self::cell(ServerFileSystem {}) } } @@ -19,41 +18,45 @@ impl ServerFileSystemVc { #[turbo_tasks::value_impl] impl FileSystem for ServerFileSystem { #[turbo_tasks::function] - fn read(&self, _fs_path: FileSystemPathVc) -> Result { + fn read(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible from the marker filesystem for the server") } #[turbo_tasks::function] - fn read_link(&self, _fs_path: FileSystemPathVc) -> Result { + fn read_link(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible from the marker filesystem for the server") } #[turbo_tasks::function] - fn read_dir(&self, _fs_path: FileSystemPathVc) -> Result { + fn read_dir(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible from the marker filesystem for the server") } #[turbo_tasks::function] - fn track(&self, _fs_path: FileSystemPathVc) -> Result { + fn track(&self, _fs_path: Vc) -> Result> { bail!("Tracking is not possible to the marker filesystem for the server") } #[turbo_tasks::function] - fn write(&self, _fs_path: FileSystemPathVc, _content: FileContentVc) -> Result { + fn write( + &self, + _fs_path: Vc, + _content: Vc, + ) -> Result> { bail!("Writing is not possible to the marker filesystem for the server") } #[turbo_tasks::function] fn write_link( &self, - _fs_path: FileSystemPathVc, - _target: LinkContentVc, - ) -> Result { + _fs_path: Vc, + _target: Vc, + ) -> Result> { bail!("Writing is not possible to the marker filesystem for the server") } #[turbo_tasks::function] - fn metadata(&self, _fs_path: FileSystemPathVc) -> Result { + fn metadata(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible from the marker filesystem for the server") } } @@ -61,7 +64,7 @@ impl FileSystem for ServerFileSystem { #[turbo_tasks::value_impl] impl ValueToString for ServerFileSystem { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell("root of the server".to_string()) + fn to_string(&self) -> Vc { + Vc::cell("root of the server".to_string()) } } diff --git a/crates/turbopack-core/src/source_asset.rs b/crates/turbopack-core/src/source_asset.rs index d83c83af66ea5e..5eff624689beac 100644 --- a/crates/turbopack-core/src/source_asset.rs +++ b/crates/turbopack-core/src/source_asset.rs @@ -1,23 +1,24 @@ use anyhow::Result; -use turbo_tasks_fs::{FileContent, FileSystemEntryType, FileSystemPathVc, LinkContent}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{FileContent, FileSystemEntryType, FileSystemPath, LinkContent}; use crate::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, - ident::AssetIdentVc, - reference::AssetReferencesVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, + reference::AssetReferences, }; /// The raw [Asset]. It represents raw content from a path without any /// references to other [Asset]s. #[turbo_tasks::value] pub struct SourceAsset { - pub path: FileSystemPathVc, + pub path: Vc, } #[turbo_tasks::value_impl] -impl SourceAssetVc { +impl SourceAsset { #[turbo_tasks::function] - pub fn new(path: FileSystemPathVc) -> Self { + pub fn new(path: Vc) -> Vc { Self::cell(SourceAsset { path }) } } @@ -25,12 +26,12 @@ impl SourceAssetVc { #[turbo_tasks::value_impl] impl Asset for SourceAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - AssetIdentVc::from_path(self.path) + fn ident(&self) -> Vc { + AssetIdent::from_path(self.path) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let file_type = &*self.path.get_type().await?; match file_type { FileSystemEntryType::Symlink => match &*self.path.read_link().await? { @@ -50,9 +51,9 @@ impl Asset for SourceAsset { } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { // TODO: build input sourcemaps via language specific sourceMappingURL comment // or parse. - AssetReferencesVc::empty() + AssetReferences::empty() } } diff --git a/crates/turbopack-core/src/source_map/mod.rs b/crates/turbopack-core/src/source_map/mod.rs index 7f59ad45e79293..f00dd96c2b458f 100644 --- a/crates/turbopack-core/src/source_map/mod.rs +++ b/crates/turbopack-core/src/source_map/mod.rs @@ -4,24 +4,24 @@ use anyhow::Result; use indexmap::IndexMap; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use sourcemap::{SourceMap as CrateMap, SourceMapBuilder}; -use turbo_tasks::TryJoinIterExt; -use turbo_tasks_fs::rope::{Rope, RopeBuilder, RopeVc}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbo_tasks_fs::rope::{Rope, RopeBuilder}; use crate::source_pos::SourcePos; pub(crate) mod source_map_asset; -pub use source_map_asset::{SourceMapAssetReference, SourceMapAssetReferenceVc}; +pub use source_map_asset::SourceMapAssetReference; /// Allows callers to generate source maps. #[turbo_tasks::value_trait] pub trait GenerateSourceMap { /// Generates a usable source map, capable of both tracing and stringifying. - fn generate_source_map(&self) -> OptionSourceMapVc; + fn generate_source_map(self: Vc) -> Vc; /// Returns an individual section of the larger source map, if found. - fn by_section(&self, _section: &str) -> OptionSourceMapVc { - OptionSourceMapVc::cell(None) + fn by_section(self: Vc, _section: String) -> Vc { + Vc::cell(None) } } @@ -38,10 +38,10 @@ pub enum SourceMap { } #[turbo_tasks::value(transparent)] -pub struct SectionMapping(IndexMap); +pub struct SectionMapping(IndexMap>>); #[turbo_tasks::value(transparent)] -pub struct OptionSourceMap(Option); +pub struct OptionSourceMap(Option>); /// A token represents a mapping in a source map. It may either be Synthetic, /// meaning it was generated by some build tool and doesn't represent a location @@ -114,13 +114,13 @@ impl SourceMap { } #[turbo_tasks::value_impl] -impl SourceMapVc { +impl SourceMap { /// A source map that contains no actual source location information (no /// `sources`, no mappings that point into a source). This is used to tell /// Chrome that the generated code starting at a particular offset is no /// longer part of the previous section's mappings. #[turbo_tasks::function] - pub fn empty() -> Self { + pub fn empty() -> Vc { let mut builder = SourceMapBuilder::new(None); builder.add(0, 0, 0, 0, None, None); SourceMap::new_regular(builder.into_sourcemap()).cell() @@ -128,10 +128,10 @@ impl SourceMapVc { } #[turbo_tasks::value_impl] -impl SourceMapVc { +impl SourceMap { /// Stringifies the source map into JSON bytes. #[turbo_tasks::function] - pub async fn to_rope(self) -> Result { + pub async fn to_rope(self: Vc) -> Result> { let this = self.await?; let rope = match &*this { SourceMap::Regular(r) => { @@ -193,7 +193,11 @@ impl SourceMapVc { /// Traces a generated line/column into an mapping token representing either /// synthetic code or user-authored original code. #[turbo_tasks::function] - pub async fn lookup_token(self, line: usize, column: usize) -> Result { + pub async fn lookup_token( + self: Vc, + line: usize, + column: usize, + ) -> Result> { let token = match &*self.await? { SourceMap::Regular(map) => map .lookup_token(line as u32, column as u32) @@ -323,11 +327,11 @@ impl SectionedSourceMap { #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct SourceMapSection { offset: SourcePos, - map: SourceMapVc, + map: Vc, } impl SourceMapSection { - pub fn new(offset: SourcePos, map: SourceMapVc) -> Self { + pub fn new(offset: SourcePos, map: Vc) -> Self { Self { offset, map } } } diff --git a/crates/turbopack-core/src/source_map/source_map.rs b/crates/turbopack-core/src/source_map/source_map.rs index 494272f90f976d..e9e94514472aa6 100644 --- a/crates/turbopack-core/src/source_map/source_map.rs +++ b/crates/turbopack-core/src/source_map/source_map.rs @@ -4,8 +4,8 @@ use anyhow::Result; use indexmap::IndexMap; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use sourcemap::{SourceMap as CrateMap, SourceMapBuilder}; -use turbo_tasks::TryJoinIterExt; -use turbo_tasks_fs::rope::{Rope, RopeBuilder, RopeVc}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbo_tasks_fs::rope::{Rope, RopeBuilder}; use crate::source_pos::SourcePos; @@ -13,11 +13,11 @@ use crate::source_pos::SourcePos; #[turbo_tasks::value_trait] pub trait GenerateSourceMap { /// Generates a usable source map, capable of both tracing and stringifying. - fn generate_source_map(&self) -> OptionSourceMapVc; + fn generate_source_map(self: Vc) -> Vc; /// Returns an individual section of the larger source map, if found. - fn by_section(&self, _section: &str) -> OptionSourceMapVc { - OptionSourceMapVc::cell(None) + fn by_section(&self, _section: String) -> Vc { + Vc::cell(None) } } @@ -34,10 +34,10 @@ pub enum SourceMap { } #[turbo_tasks::value(transparent)] -pub struct SectionMapping(IndexMap); +pub struct SectionMapping(IndexMap>>); #[turbo_tasks::value(transparent)] -pub struct OptionSourceMap(Option); +pub struct OptionSourceMap(Option>); /// A token represents a mapping in a source map. It may either be Synthetic, /// meaning it was generated by some build tool and doesn't represent a location @@ -110,13 +110,13 @@ impl SourceMap { } #[turbo_tasks::value_impl] -impl SourceMapVc { +impl SourceMap { /// A source map that contains no actual source location information (no /// `sources`, no mappings that point into a source). This is used to tell /// Chrome that the generated code starting at a particular offset is no /// longer part of the previous section's mappings. #[turbo_tasks::function] - pub fn empty() -> Self { + pub fn empty() -> Vc { let mut builder = SourceMapBuilder::new(None); builder.add(0, 0, 0, 0, None, None); SourceMap::new_regular(builder.into_sourcemap()).cell() @@ -124,10 +124,10 @@ impl SourceMapVc { } #[turbo_tasks::value_impl] -impl SourceMapVc { +impl SourceMap { /// Stringifies the source map into JSON bytes. #[turbo_tasks::function] - pub async fn to_rope(self) -> Result { + pub async fn to_rope(self: Vc) -> Result> { let this = self.await?; let rope = match &*this { SourceMap::Regular(r) => { @@ -189,7 +189,11 @@ impl SourceMapVc { /// Traces a generated line/column into an mapping token representing either /// synthetic code or user-authored original code. #[turbo_tasks::function] - pub async fn lookup_token(self, line: usize, column: usize) -> Result { + pub async fn lookup_token( + self: Vc, + line: usize, + column: usize, + ) -> Result> { let token = match &*self.await? { SourceMap::Regular(map) => map .lookup_token(line as u32, column as u32) @@ -319,11 +323,11 @@ impl SectionedSourceMap { #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct SourceMapSection { offset: SourcePos, - map: SourceMapVc, + map: Vc, } impl SourceMapSection { - pub fn new(offset: SourcePos, map: SourceMapVc) -> Self { + pub fn new(offset: SourcePos, map: Vc) -> Self { Self { offset, map } } } diff --git a/crates/turbopack-core/src/source_map/source_map_asset.rs b/crates/turbopack-core/src/source_map/source_map_asset.rs index fa5b32b8491b4f..6f9306f95fc2b8 100644 --- a/crates/turbopack-core/src/source_map/source_map_asset.rs +++ b/crates/turbopack-core/src/source_map/source_map_asset.rs @@ -1,27 +1,27 @@ use anyhow::{bail, Result}; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::File; use crate::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, - introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}, - reference::{AssetReference, AssetReferenceVc}, - resolve::{ResolveResult, ResolveResultVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc, SourceMapVc}, + asset::{Asset, AssetContent}, + ident::AssetIdent, + introspect::{Introspectable, IntrospectableChildren}, + reference::AssetReference, + resolve::ResolveResult, + source_map::{GenerateSourceMap, SourceMap}, }; /// Represents the source map of an ecmascript asset. #[turbo_tasks::value] pub struct SourceMapAsset { - asset: AssetVc, + asset: Vc>, } #[turbo_tasks::value_impl] -impl SourceMapAssetVc { +impl SourceMapAsset { #[turbo_tasks::function] - pub fn new(asset: AssetVc) -> Self { + pub fn new(asset: Vc>) -> Vc { SourceMapAsset { asset }.cell() } } @@ -29,63 +29,64 @@ impl SourceMapAssetVc { #[turbo_tasks::value_impl] impl Asset for SourceMapAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { // NOTE(alexkirsz) We used to include the asset's version id in the path, // but this caused `all_assets_map` to be recomputed on every change. - Ok(AssetIdentVc::from_path( - self.asset.ident().path().append(".map"), + Ok(AssetIdent::from_path( + self.asset.ident().path().append(".map".to_string()), )) } #[turbo_tasks::function] - async fn content(&self) -> Result { - let Some(generate_source_map) = GenerateSourceMapVc::resolve_from(&self.asset).await? else { + async fn content(&self) -> Result> { + let Some(generate_source_map) = Vc::try_resolve_sidecast::>(self.asset).await? else { bail!("asset does not support generating source maps") }; let sm = if let Some(sm) = &*generate_source_map.generate_source_map().await? { *sm } else { - SourceMapVc::empty() + SourceMap::empty() }; let sm = sm.to_rope().await?; - Ok(File::from(sm).into()) + Ok(AssetContent::file(File::from(sm).into())) } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("source map".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("source map".to_string()) } #[turbo_tasks::function] -fn introspectable_details() -> StringVc { - StringVc::cell("source map of an asset".to_string()) +fn introspectable_details() -> Vc { + Vc::cell("source map of an asset".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for SourceMapAsset { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(self_vc: SourceMapAssetVc) -> StringVc { - self_vc.ident().to_string() + fn title(self: Vc) -> Vc { + self.ident().to_string() } #[turbo_tasks::function] - fn details(&self) -> StringVc { + fn details(&self) -> Vc { introspectable_details() } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let mut children = IndexSet::new(); - if let Some(asset) = IntrospectableVc::resolve_from(self.asset).await? { - children.insert((StringVc::cell("asset".to_string()), asset)); + if let Some(asset) = Vc::try_resolve_sidecast::>(self.asset).await? + { + children.insert((Vc::cell("asset".to_string()), asset)); } - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } } @@ -93,13 +94,13 @@ impl Introspectable for SourceMapAsset { /// server/build system of the presence of the source map #[turbo_tasks::value] pub struct SourceMapAssetReference { - asset: AssetVc, + asset: Vc>, } #[turbo_tasks::value_impl] -impl SourceMapAssetReferenceVc { +impl SourceMapAssetReference { #[turbo_tasks::function] - pub fn new(asset: AssetVc) -> Self { + pub fn new(asset: Vc>) -> Vc { SourceMapAssetReference { asset }.cell() } } @@ -107,8 +108,8 @@ impl SourceMapAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for SourceMapAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { - let asset = SourceMapAssetVc::new(self.asset).into(); + async fn resolve_reference(&self) -> Result> { + let asset = Vc::upcast(SourceMapAsset::new(self.asset)); Ok(ResolveResult::asset(asset).cell()) } } @@ -116,8 +117,8 @@ impl AssetReference for SourceMapAssetReference { #[turbo_tasks::value_impl] impl ValueToString for SourceMapAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "source map for {}", self.asset.ident().path().to_string().await? ))) diff --git a/crates/turbopack-core/src/source_transform.rs b/crates/turbopack-core/src/source_transform.rs index f13ce0a78905fe..a32bbe34da9034 100644 --- a/crates/turbopack-core/src/source_transform.rs +++ b/crates/turbopack-core/src/source_transform.rs @@ -1,19 +1,23 @@ use anyhow::Result; +use turbo_tasks::Vc; -use crate::asset::AssetVc; +use crate::asset::Asset; #[turbo_tasks::value_trait] pub trait SourceTransform { - fn transform(&self, source: AssetVc) -> AssetVc; + fn transform(self: Vc, source: Vc>) -> Vc>; } #[turbo_tasks::value(transparent)] -pub struct SourceTransforms(Vec); +pub struct SourceTransforms(Vec>>); #[turbo_tasks::value_impl] -impl SourceTransformsVc { +impl SourceTransforms { #[turbo_tasks::function] - pub async fn transform(self, source: AssetVc) -> Result { + pub async fn transform( + self: Vc, + source: Vc>, + ) -> Result>> { Ok(self .await? .iter() diff --git a/crates/turbopack-core/src/target.rs b/crates/turbopack-core/src/target.rs index bae621755dc7e0..2e51b5fb4a57d2 100644 --- a/crates/turbopack-core/src/target.rs +++ b/crates/turbopack-core/src/target.rs @@ -1,7 +1,7 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; -use turbo_tasks::trace::TraceRawVcs; +use turbo_tasks::{trace::TraceRawVcs, Vc}; #[turbo_tasks::value(shared, serialization = "auto_for_input")] #[derive(PartialOrd, Ord, Hash, Debug, Copy, Clone)] @@ -15,16 +15,10 @@ pub struct CompileTarget { pub libc: Libc, } -impl Default for CompileTargetVc { - fn default() -> Self { - Self::current() - } -} - #[turbo_tasks::value_impl] -impl CompileTargetVc { +impl CompileTarget { #[turbo_tasks::function] - pub fn current() -> Self { + pub fn current() -> Vc { Self::cell(CompileTarget { arch: CompileTarget::current_arch(), platform: CompileTarget::current_platform(), @@ -34,7 +28,7 @@ impl CompileTargetVc { } #[turbo_tasks::function] - pub fn unknown() -> Self { + pub fn unknown() -> Vc { Self::cell(CompileTarget { arch: Arch::Unknown, platform: Platform::Unknown, diff --git a/crates/turbopack-core/src/version.rs b/crates/turbopack-core/src/version.rs index bd9d2d63c1af71..2865d52a5bf45b 100644 --- a/crates/turbopack-core/src/version.rs +++ b/crates/turbopack-core/src/version.rs @@ -3,30 +3,30 @@ use std::sync::Arc; use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; use turbo_tasks::{ - debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs, IntoTraitRef, TraitRef, + debug::ValueDebugFormat, trace::TraceRawVcs, IntoTraitRef, ReadRef, TraitRef, Vc, }; -use turbo_tasks_fs::{FileContent, FileContentReadRef, LinkType}; +use turbo_tasks_fs::{FileContent, LinkType}; use turbo_tasks_hash::{encode_hex, hash_xxh3_hash64}; -use crate::asset::{AssetContent, AssetContentReadRef, AssetContentVc}; +use crate::asset::AssetContent; /// The content of an [Asset] alongside its version. #[turbo_tasks::value_trait] pub trait VersionedContent { /// The content of the [Asset]. - fn content(&self) -> AssetContentVc; + fn content(self: Vc) -> Vc; /// Get a [`Version`] implementor that contains enough information to /// identify and diff a future [`VersionedContent`] against it. - fn version(&self) -> VersionVc; + fn version(self: Vc) -> Vc>; /// Describes how to update the content from an earlier version to the /// latest available one. - async fn update(self_vc: VersionedContentVc, from: VersionVc) -> Result { + async fn update(self: Vc, from: Vc>) -> Result> { // By default, since we can't make any assumptions about the versioning // scheme of the content, we ask for a full invalidation, except in the // case where versions are the same. - let to = self_vc.version(); + let to = self.version(); let from_ref = from.into_trait_ref().await?; let to_ref = to.into_trait_ref().await?; @@ -35,9 +35,10 @@ pub trait VersionedContent { return Ok(Update::None.into()); } - // The fast path might not always work since `self_vc` might have been converted - // from a `ReadRef` or a `ReadRef`, in which case `self_vc.version()` would - // return a new `VersionVc`. In this case, we need to compare version ids. + // The fast path might not always work since `self` might have been converted + // from a `ReadRef` or a `ReadRef`, in which case `self.version()` would + // return a new `Vc>`. In this case, we need to compare + // version ids. let from_id = from.id(); let to_id = to.id(); let from_id = from_id.await?; @@ -53,66 +54,64 @@ pub trait VersionedContent { /// A versioned file content. #[turbo_tasks::value] pub struct VersionedAssetContent { - // We can't store a `FileContentVc` directly because we don't want - // `VersionedAssetContentVc` to invalidate when the content changes. + // We can't store a `Vc` directly because we don't want + // `Vc` to invalidate when the content changes. // Otherwise, reading `content` and `version` at two different instants in // time might return inconsistent values. - asset_content: AssetContentReadRef, + asset_content: ReadRef, } #[turbo_tasks::value] #[derive(Clone)] enum AssetContentSnapshot { - File(FileContentReadRef), + File(ReadRef), Redirect { target: String, link_type: LinkType }, } #[turbo_tasks::value_impl] impl VersionedContent for VersionedAssetContent { #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { (*self.asset_content).clone().cell() } #[turbo_tasks::function] - async fn version(&self) -> Result { - Ok(FileHashVersionVc::compute(&self.asset_content) - .await? - .into()) + async fn version(&self) -> Result>> { + Ok(Vc::upcast( + FileHashVersion::compute(&self.asset_content).await?, + )) } } #[turbo_tasks::value_impl] -impl VersionedAssetContentVc { +impl VersionedAssetContent { #[turbo_tasks::function] - /// Creates a new [VersionedAssetContentVc] from a [FileContentVc]. - pub async fn new(asset_content: AssetContentVc) -> Result { + /// Creates a new [Vc] from a [Vc]. + pub async fn new(asset_content: Vc) -> Result> { let asset_content = asset_content.strongly_consistent().await?; Ok(Self::cell(VersionedAssetContent { asset_content })) } } -impl From for VersionedAssetContentVc { +impl From for Vc { fn from(asset_content: AssetContent) -> Self { - VersionedAssetContentVc::new(asset_content.cell()) + VersionedAssetContent::new(asset_content.cell()) } } -impl From for VersionedAssetContentVc { - fn from(asset_content: AssetContentVc) -> Self { - VersionedAssetContentVc::new(asset_content) +impl From for Vc> { + fn from(asset_content: AssetContent) -> Self { + Vc::upcast(VersionedAssetContent::new(asset_content.cell())) } } -impl From for VersionedContentVc { - fn from(asset_content: AssetContent) -> Self { - VersionedAssetContentVc::new(asset_content.cell()).into() - } +pub trait VersionedContentExt { + fn versioned(self: Vc) -> Vc>; } -impl From for VersionedContentVc { - fn from(asset_content: AssetContentVc) -> Self { - VersionedAssetContentVc::new(asset_content).into() +impl VersionedContentExt for AssetContent { + fn versioned(self: Vc) -> Vc> { + Vc::upcast(VersionedAssetContent::new(self)) } } @@ -123,7 +122,7 @@ pub trait Version { /// Get a unique identifier of the version as a string. There is no way /// to convert an id back to its original `Version`, so the original object /// needs to be stored somewhere. - fn id(&self) -> StringVc; + fn id(self: Vc) -> Vc; } /// This trait allows multiple `VersionedContent` to declare which @@ -133,26 +132,26 @@ pub trait Version { /// together. #[turbo_tasks::value_trait] pub trait MergeableVersionedContent: VersionedContent { - fn get_merger(&self) -> VersionedContentMergerVc; + fn get_merger(self: Vc) -> Vc>; } /// A [`VersionedContentMerger`] merges multiple [`VersionedContent`] into a /// single one. #[turbo_tasks::value_trait] pub trait VersionedContentMerger { - fn merge(&self, contents: VersionedContentsVc) -> VersionedContentVc; + fn merge(self: Vc, contents: Vc) -> Vc>; } #[turbo_tasks::value(transparent)] -pub struct VersionedContents(Vec); +pub struct VersionedContents(Vec>>); #[turbo_tasks::value] pub struct NotFoundVersion; #[turbo_tasks::value_impl] -impl NotFoundVersionVc { +impl NotFoundVersion { #[turbo_tasks::function] - pub fn new() -> Self { + pub fn new() -> Vc { NotFoundVersion.cell() } } @@ -160,8 +159,8 @@ impl NotFoundVersionVc { #[turbo_tasks::value_impl] impl Version for NotFoundVersion { #[turbo_tasks::function] - fn id(&self) -> StringVc { - StringVc::empty() + fn id(&self) -> Vc { + Vc::cell("".to_string()) } } @@ -186,7 +185,7 @@ pub enum Update { pub struct TotalUpdate { /// The version this update will bring the object to. #[turbo_tasks(trace_ignore)] - pub to: TraitRef, + pub to: TraitRef>, } /// A partial update to a versioned object. @@ -194,7 +193,7 @@ pub struct TotalUpdate { pub struct PartialUpdate { /// The version this update will bring the object to. #[turbo_tasks(trace_ignore)] - pub to: TraitRef, + pub to: TraitRef>, /// The instructions to be passed to a remote system in order to update the /// versioned object. #[turbo_tasks(trace_ignore)] @@ -209,9 +208,9 @@ pub struct FileHashVersion { hash: String, } -impl FileHashVersionVc { - /// Computes a new [`FileHashVersionVc`] from a path. - pub async fn compute(asset_content: &AssetContent) -> Result { +impl FileHashVersion { + /// Computes a new [`Vc`] from a path. + pub async fn compute(asset_content: &AssetContent) -> Result> { match asset_content { AssetContent::File(file_vc) => match &*file_vc.await? { FileContent::Content(file) => { @@ -229,7 +228,7 @@ impl FileHashVersionVc { #[turbo_tasks::value_impl] impl Version for FileHashVersion { #[turbo_tasks::function] - async fn id(&self) -> Result { - Ok(StringVc::cell(self.hash.clone())) + async fn id(&self) -> Result> { + Ok(Vc::cell(self.hash.clone())) } } diff --git a/crates/turbopack-core/src/virtual_asset.rs b/crates/turbopack-core/src/virtual_asset.rs index 1cfe394f36ba87..7235a8f1cd6679 100644 --- a/crates/turbopack-core/src/virtual_asset.rs +++ b/crates/turbopack-core/src/virtual_asset.rs @@ -1,30 +1,30 @@ -use anyhow::Result; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; use crate::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, }; /// An [Asset] that is created from some passed source code. #[turbo_tasks::value] pub struct VirtualAsset { - pub ident: AssetIdentVc, - pub content: AssetContentVc, + pub ident: Vc, + pub content: Vc, } #[turbo_tasks::value_impl] -impl VirtualAssetVc { +impl VirtualAsset { #[turbo_tasks::function] - pub fn new(path: FileSystemPathVc, content: AssetContentVc) -> Self { + pub fn new(path: Vc, content: Vc) -> Vc { Self::cell(VirtualAsset { - ident: AssetIdentVc::from_path(path), + ident: AssetIdent::from_path(path), content, }) } #[turbo_tasks::function] - pub fn new_with_ident(ident: AssetIdentVc, content: AssetContentVc) -> Self { + pub fn new_with_ident(ident: Vc, content: Vc) -> Vc { Self::cell(VirtualAsset { ident, content }) } } @@ -32,12 +32,12 @@ impl VirtualAssetVc { #[turbo_tasks::value_impl] impl Asset for VirtualAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.ident } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.content } } diff --git a/crates/turbopack-core/src/virtual_fs.rs b/crates/turbopack-core/src/virtual_fs.rs index f1f33fe01d4504..a84e4cd23df625 100644 --- a/crates/turbopack-core/src/virtual_fs.rs +++ b/crates/turbopack-core/src/virtual_fs.rs @@ -1,17 +1,16 @@ use anyhow::{bail, Result}; -use turbo_tasks::{primitives::StringVc, CompletionVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{Completion, ValueToString, Vc}; use turbo_tasks_fs::{ - DirectoryContentVc, FileContentVc, FileMetaVc, FileSystem, FileSystemPathVc, FileSystemVc, - LinkContentVc, + DirectoryContent, FileContent, FileMeta, FileSystem, FileSystemPath, LinkContent, }; #[turbo_tasks::value] pub struct VirtualFileSystem; #[turbo_tasks::value_impl] -impl VirtualFileSystemVc { +impl VirtualFileSystem { #[turbo_tasks::function] - pub fn new() -> Self { + pub fn new() -> Vc { Self::cell(VirtualFileSystem) } } @@ -19,41 +18,45 @@ impl VirtualFileSystemVc { #[turbo_tasks::value_impl] impl FileSystem for VirtualFileSystem { #[turbo_tasks::function] - fn read(&self, _fs_path: FileSystemPathVc) -> Result { + fn read(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible on the virtual file system") } #[turbo_tasks::function] - fn read_link(&self, _fs_path: FileSystemPathVc) -> Result { + fn read_link(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible on the virtual file system") } #[turbo_tasks::function] - fn read_dir(&self, _fs_path: FileSystemPathVc) -> Result { + fn read_dir(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible on the virtual file system") } #[turbo_tasks::function] - fn track(&self, _fs_path: FileSystemPathVc) -> Result { + fn track(&self, _fs_path: Vc) -> Result> { bail!("Tracking is not possible on the virtual file system") } #[turbo_tasks::function] - fn write(&self, _fs_path: FileSystemPathVc, _content: FileContentVc) -> Result { + fn write( + &self, + _fs_path: Vc, + _content: Vc, + ) -> Result> { bail!("Writing is not possible on the virtual file system") } #[turbo_tasks::function] fn write_link( &self, - _fs_path: FileSystemPathVc, - _target: LinkContentVc, - ) -> Result { + _fs_path: Vc, + _target: Vc, + ) -> Result> { bail!("Writing is not possible on the virtual file system") } #[turbo_tasks::function] - fn metadata(&self, _fs_path: FileSystemPathVc) -> Result { + fn metadata(&self, _fs_path: Vc) -> Result> { bail!("Reading is not possible on the virtual file system") } } @@ -61,7 +64,7 @@ impl FileSystem for VirtualFileSystem { #[turbo_tasks::value_impl] impl ValueToString for VirtualFileSystem { #[turbo_tasks::function] - fn to_string(&self) -> StringVc { - StringVc::cell("virtual file system".to_string()) + fn to_string(&self) -> Vc { + Vc::cell("virtual file system".to_string()) } } diff --git a/crates/turbopack-css/src/asset.rs b/crates/turbopack-css/src/asset.rs index fc986785a21466..2433a4d03b4b42 100644 --- a/crates/turbopack-css/src/asset.rs +++ b/crates/turbopack-css/src/asset.rs @@ -7,58 +7,54 @@ use swc_core::{ visit::{VisitMutWith, VisitMutWithPath}, }, }; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetVc, ChunkingContextVc, - }, - context::AssetContextVc, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferencesVc}, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - PrimaryResolveResult, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, ChunkingContext, }, + context::AssetContext, + ident::AssetIdent, + reference::{AssetReference, AssetReferences}, + resolve::{origin::ResolveOrigin, PrimaryResolveResult}, }; use crate::{ - chunk::{ - CssChunkItem, CssChunkItemContent, CssChunkItemContentVc, CssChunkItemVc, - CssChunkPlaceable, CssChunkPlaceableVc, CssChunkVc, CssImport, - }, - code_gen::{CodeGenerateable, CodeGenerateableVc}, - parse::{parse, ParseResult, ParseResultSourceMap, ParseResultVc}, + chunk::{CssChunk, CssChunkItem, CssChunkItemContent, CssChunkPlaceable, CssImport}, + code_gen::CodeGenerateable, + parse::{parse, ParseResult, ParseResultSourceMap}, path_visitor::ApplyVisitors, references::{ - analyze_css_stylesheet, compose::CssModuleComposeReferenceVc, - import::ImportAssetReferenceVc, + analyze_css_stylesheet, compose::CssModuleComposeReference, import::ImportAssetReference, }, - transform::CssInputTransformsVc, + transform::CssInputTransforms, CssModuleAssetType, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("css".to_string()) +fn modifier() -> Vc { + Vc::cell("css".to_string()) } #[turbo_tasks::value] #[derive(Clone)] pub struct CssModuleAsset { - pub source: AssetVc, - pub context: AssetContextVc, - pub transforms: CssInputTransformsVc, + pub source: Vc>, + pub context: Vc>, + pub transforms: Vc, pub ty: CssModuleAssetType, } #[turbo_tasks::value_impl] -impl CssModuleAssetVc { +impl CssModuleAsset { /// Creates a new CSS asset. The CSS is treated as global CSS. #[turbo_tasks::function] - pub fn new(source: AssetVc, context: AssetContextVc, transforms: CssInputTransformsVc) -> Self { + pub fn new( + source: Vc>, + context: Vc>, + transforms: Vc, + ) -> Vc { Self::cell(CssModuleAsset { source, context, @@ -70,10 +66,10 @@ impl CssModuleAssetVc { /// Creates a new CSS asset. The CSS is treated as CSS module. #[turbo_tasks::function] pub fn new_module( - source: AssetVc, - context: AssetContextVc, - transforms: CssInputTransformsVc, - ) -> Self { + source: Vc>, + context: Vc>, + transforms: Vc, + ) -> Vc { Self::cell(CssModuleAsset { source, context, @@ -84,14 +80,14 @@ impl CssModuleAssetVc { /// Returns the parsed css. #[turbo_tasks::function] - pub(crate) async fn parse(self) -> Result { + pub(crate) async fn parse(self: Vc) -> Result> { let this = self.await?; Ok(parse(this.source, Value::new(this.ty), this.transforms)) } /// Retrns the asset ident of the source without the "css" modifier #[turbo_tasks::function] - pub async fn source_ident(self) -> Result { + pub async fn source_ident(self: Vc) -> Result> { Ok(self.await?.source.ident()) } } @@ -99,22 +95,22 @@ impl CssModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for CssModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } #[turbo_tasks::function] - async fn references(self_vc: CssModuleAssetVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; // TODO: include CSS source map Ok(analyze_css_stylesheet( this.source, - self_vc.as_resolve_origin(), + Vc::upcast(self), Value::new(this.ty), this.transforms, )) @@ -125,54 +121,56 @@ impl Asset for CssModuleAsset { impl ChunkableAsset for CssModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: CssModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - CssChunkVc::new(context, self_vc.into(), availability_info).into() + ) -> Vc> { + Vc::upcast(CssChunk::new(context, Vc::upcast(self), availability_info)) } } #[turbo_tasks::value_impl] impl CssChunkPlaceable for CssModuleAsset { #[turbo_tasks::function] - fn as_chunk_item(self_vc: CssModuleAssetVc, context: ChunkingContextVc) -> CssChunkItemVc { - ModuleChunkItemVc::cell(ModuleChunkItem { - module: self_vc, + fn as_chunk_item( + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(ModuleChunkItem::cell(ModuleChunkItem { + module: self, context, - }) - .into() + })) } } #[turbo_tasks::value_impl] impl ResolveOrigin for CssModuleAsset { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.source.ident().path() } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { + fn context(&self) -> Vc> { self.context } } #[turbo_tasks::value] struct ModuleChunkItem { - module: CssModuleAssetVc, - context: ChunkingContextVc, + module: Vc, + context: Vc>, } #[turbo_tasks::value_impl] impl ChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.module.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.module.references() } } @@ -180,16 +178,20 @@ impl ChunkItem for ModuleChunkItem { #[turbo_tasks::value_impl] impl CssChunkItem for ModuleChunkItem { #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let references = &*self.module.references().await?; let mut imports = vec![]; let context = self.context; for reference in references.iter() { - if let Some(import_ref) = ImportAssetReferenceVc::resolve_from(reference).await? { + if let Some(import_ref) = + Vc::try_resolve_downcast_type::(*reference).await? + { for result in import_ref.resolve_reference().await?.primary.iter() { if let PrimaryResolveResult::Asset(asset) = result { - if let Some(placeable) = CssChunkPlaceableVc::resolve_from(asset).await? { + if let Some(placeable) = + Vc::try_resolve_sidecast::>(*asset).await? + { imports.push(CssImport::Internal( import_ref, placeable.as_chunk_item(context), @@ -198,11 +200,13 @@ impl CssChunkItem for ModuleChunkItem { } } } else if let Some(compose_ref) = - CssModuleComposeReferenceVc::resolve_from(reference).await? + Vc::try_resolve_downcast_type::(*reference).await? { for result in compose_ref.resolve_reference().await?.primary.iter() { if let PrimaryResolveResult::Asset(asset) = result { - if let Some(placeable) = CssChunkPlaceableVc::resolve_from(asset).await? { + if let Some(placeable) = + Vc::try_resolve_sidecast::>(*asset).await? + { imports.push(CssImport::Composes(placeable.as_chunk_item(context))); } } @@ -212,7 +216,9 @@ impl CssChunkItem for ModuleChunkItem { let mut code_gens = Vec::new(); for r in references.iter() { - if let Some(code_gen) = CodeGenerateableVc::resolve_from(r).await? { + if let Some(code_gen) = + Vc::try_resolve_sidecast::>(*r).await? + { code_gens.push(code_gen.code_generation(context)); } } @@ -303,7 +309,7 @@ impl CssChunkItem for ModuleChunkItem { } #[turbo_tasks::function] - fn chunking_context(&self) -> ChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } } diff --git a/crates/turbopack-css/src/chunk/mod.rs b/crates/turbopack-css/src/chunk/mod.rs index 3a2292472c0553..a3e1ea8f96641b 100644 --- a/crates/turbopack-css/src/chunk/mod.rs +++ b/crates/turbopack-css/src/chunk/mod.rs @@ -6,58 +6,56 @@ use std::fmt::Write; use anyhow::{anyhow, Result}; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString}; -use turbo_tasks_fs::{rope::Rope, File, FileSystemPathOptionVc}; +use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::{rope::Rope, File, FileSystemPathOption}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, + asset::{Asset, AssetContent}, chunk::{ availability_info::AvailabilityInfo, chunk_content, chunk_content_split, Chunk, - ChunkContentResult, ChunkGroupReferenceVc, ChunkItem, ChunkItemVc, ChunkVc, - ChunkableAssetVc, ChunkingContext, ChunkingContextVc, ChunksVc, FromChunkableAsset, - ModuleId, ModuleIdVc, ModuleIdsVc, OutputChunk, OutputChunkRuntimeInfo, - OutputChunkRuntimeInfoVc, OutputChunkVc, + ChunkContentResult, ChunkGroupReference, ChunkItem, ChunkableAsset, ChunkingContext, + Chunks, FromChunkableAsset, ModuleId, OutputChunk, OutputChunkRuntimeInfo, }, - code_builder::{CodeBuilder, CodeVc}, - ident::{AssetIdent, AssetIdentVc}, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, introspect::{ - asset::{children_from_asset_references, content_to_details, IntrospectableAssetVc}, - Introspectable, IntrospectableChildrenVc, IntrospectableVc, + asset::{children_from_asset_references, content_to_details, IntrospectableAsset}, + Introspectable, IntrospectableChildren, }, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, + reference::{AssetReference, AssetReferences}, resolve::PrimaryResolveResult, - source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, + source_map::{GenerateSourceMap, OptionSourceMap}, }; use writer::expand_imports; use self::{ - single_item_chunk::{chunk::SingleItemCssChunkVc, reference::SingleItemCssChunkReferenceVc}, - source_map::CssChunkSourceMapAssetReferenceVc, + single_item_chunk::{chunk::SingleItemCssChunk, reference::SingleItemCssChunkReference}, + source_map::CssChunkSourceMapAssetReference, }; use crate::{ - embed::{CssEmbed, CssEmbeddable, CssEmbeddableVc}, - parse::ParseResultSourceMapVc, + embed::{CssEmbed, CssEmbeddable}, + parse::ParseResultSourceMap, util::stringify_js, - ImportAssetReferenceVc, + ImportAssetReference, }; #[turbo_tasks::value] pub struct CssChunk { - pub context: ChunkingContextVc, - pub main_entries: CssChunkPlaceablesVc, + pub context: Vc>, + pub main_entries: Vc, pub availability_info: AvailabilityInfo, } #[turbo_tasks::value(transparent)] -pub struct CssChunks(Vec); +pub struct CssChunks(Vec>); #[turbo_tasks::value_impl] -impl CssChunkVc { +impl CssChunk { #[turbo_tasks::function] pub fn new_normalized( - context: ChunkingContextVc, - main_entries: CssChunkPlaceablesVc, + context: Vc>, + main_entries: Vc, availability_info: Value, - ) -> Self { + ) -> Vc { CssChunk { context, main_entries, @@ -68,21 +66,17 @@ impl CssChunkVc { #[turbo_tasks::function] pub fn new( - context: ChunkingContextVc, - entry: CssChunkPlaceableVc, + context: Vc>, + entry: Vc>, availability_info: Value, - ) -> Self { - Self::new_normalized( - context, - CssChunkPlaceablesVc::cell(vec![entry]), - availability_info, - ) + ) -> Vc { + Self::new_normalized(context, Vc::cell(vec![entry]), availability_info) } /// Return the most specific directory which contains all elements of the /// chunk. #[turbo_tasks::function] - pub async fn common_parent(self) -> Result { + pub async fn common_parent(self: Vc) -> Result> { let this = self.await?; let main_entries = this.main_entries.await?; let mut paths = main_entries @@ -97,40 +91,36 @@ impl CssChunkVc { while !*path.is_inside(current).await? { let parent = current.parent().resolve().await?; if parent == current { - return Ok(FileSystemPathOptionVc::cell(None)); + return Ok(Vc::cell(None)); } current = parent; } } - Ok(FileSystemPathOptionVc::cell(Some(current))) + Ok(Vc::cell(Some(current))) } #[turbo_tasks::function] - async fn chunk_content(self) -> Result { + async fn chunk_content(self: Vc) -> Result> { let this = self.await?; - Ok(CssChunkContentVc::new( - this.main_entries, - this.context, - self, - )) + Ok(CssChunkContent::new(this.main_entries, this.context, self)) } } #[turbo_tasks::value] struct CssChunkContent { - main_entries: CssChunkPlaceablesVc, - context: ChunkingContextVc, - chunk: CssChunkVc, + main_entries: Vc, + context: Vc>, + chunk: Vc, } #[turbo_tasks::value_impl] -impl CssChunkContentVc { +impl CssChunkContent { #[turbo_tasks::function] async fn new( - main_entries: CssChunkPlaceablesVc, - context: ChunkingContextVc, - chunk: CssChunkVc, - ) -> Result { + main_entries: Vc, + context: Vc>, + chunk: Vc, + ) -> Result> { Ok(CssChunkContent { main_entries, context, @@ -140,7 +130,7 @@ impl CssChunkContentVc { } #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { use std::io::Write; let this = self.await?; @@ -149,8 +139,7 @@ impl CssChunkContentVc { let mut body = CodeBuilder::default(); let mut external_imports = IndexSet::new(); for entry in this.main_entries.await?.iter() { - let entry_placeable = CssChunkPlaceableVc::cast_from(entry); - let entry_item = entry_placeable.as_chunk_item(this.context); + let entry_item = entry.as_chunk_item(this.context); for external_import in expand_imports(&mut body, entry_item).await? { external_imports.insert(external_import.await?.to_owned()); @@ -167,7 +156,7 @@ impl CssChunkContentVc { if *this .context - .reference_chunk_source_maps(this.chunk.into()) + .reference_chunk_source_maps(Vc::upcast(this.chunk)) .await? && code.has_source_map() { @@ -184,30 +173,32 @@ impl CssChunkContentVc { } #[turbo_tasks::function] - async fn content(self) -> Result { + async fn content(self: Vc) -> Result> { let code = self.code().await?; - Ok(File::from(code.source_code().clone()).into()) + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for CssChunkContent { #[turbo_tasks::function] - fn generate_source_map(self_vc: CssChunkContentVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } } #[turbo_tasks::value] pub struct CssChunkContentResult { - pub chunk_items: Vec, - pub chunks: Vec, - pub async_chunk_group_entries: Vec, - pub external_asset_references: Vec, + pub chunk_items: Vec>>, + pub chunks: Vec>>, + pub async_chunk_group_entries: Vec>>, + pub external_asset_references: Vec>>, } -impl From> for CssChunkContentResult { - fn from(from: ChunkContentResult) -> Self { +impl From>>> for CssChunkContentResult { + fn from(from: ChunkContentResult>>) -> Self { CssChunkContentResult { chunk_items: from.chunk_items, chunks: from.chunks, @@ -219,10 +210,10 @@ impl From> for CssChunkContentResult { #[turbo_tasks::function] async fn css_chunk_content( - context: ChunkingContextVc, - entries: CssChunkPlaceablesVc, + context: Vc>, + entries: Vc, availability_info: Value, -) -> Result { +) -> Result> { let entries = entries.await?; let entries = entries.iter().copied(); @@ -234,10 +225,10 @@ async fn css_chunk_content( return Ok(contents.into_iter().next().unwrap()); } - let mut all_chunk_items = IndexSet::::new(); - let mut all_chunks = IndexSet::::new(); - let mut all_async_chunk_group_entries = IndexSet::::new(); - let mut all_external_asset_references = IndexSet::::new(); + let mut all_chunk_items = IndexSet::>>::new(); + let mut all_chunks = IndexSet::>>::new(); + let mut all_async_chunk_group_entries = IndexSet::>>::new(); + let mut all_external_asset_references = IndexSet::>>::new(); for content in contents { let CssChunkContentResult { @@ -263,31 +254,32 @@ async fn css_chunk_content( #[turbo_tasks::function] async fn css_chunk_content_single_entry( - context: ChunkingContextVc, - entry: CssChunkPlaceableVc, + context: Vc>, + entry: Vc>, availability_info: Value, -) -> Result { - let asset = entry.as_asset(); +) -> Result> { + let asset = Vc::upcast(entry); let res = if let Some(res) = - chunk_content::(context, asset, None, availability_info).await? + chunk_content::>(context, asset, None, availability_info).await? { res } else { - chunk_content_split::(context, asset, None, availability_info).await? + chunk_content_split::>(context, asset, None, availability_info) + .await? }; - Ok(CssChunkContentResultVc::cell(res.into())) + Ok(CssChunkContentResult::cell(res.into())) } #[turbo_tasks::value_impl] impl Chunk for CssChunk { #[turbo_tasks::function] - fn chunking_context(&self) -> ChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn parallel_chunks(&self) -> Result { + async fn parallel_chunks(&self) -> Result> { let content = css_chunk_content( self.context, self.main_entries, @@ -298,14 +290,14 @@ impl Chunk for CssChunk { for chunk in content.chunks.iter() { chunks.push(*chunk); } - Ok(ChunksVc::cell(chunks)) + Ok(Vc::cell(chunks)) } } #[turbo_tasks::value_impl] impl OutputChunk for CssChunk { #[turbo_tasks::function] - async fn runtime_info(&self) -> Result { + async fn runtime_info(&self) -> Result> { let content = css_chunk_content( self.context, self.main_entries, @@ -348,11 +340,11 @@ impl OutputChunk for CssChunk { .chunk_items .iter() .chain(imports_chunk_items.iter()) - .map(|item| SingleItemCssChunkVc::new(self.context, *item).into()) + .map(|item| Vc::upcast(SingleItemCssChunk::new(self.context, *item))) .collect(); Ok(OutputChunkRuntimeInfo { - included_ids: Some(ModuleIdsVc::cell(included_ids)), - module_chunks: Some(AssetsVc::cell(module_chunks)), + included_ids: Some(Vc::cell(included_ids)), + module_chunks: Some(Vc::cell(module_chunks)), ..Default::default() } .cell()) @@ -362,11 +354,11 @@ impl OutputChunk for CssChunk { #[turbo_tasks::value_impl] impl Asset for CssChunk { #[turbo_tasks::function] - async fn ident(self_vc: CssChunkVc) -> Result { - let this = self_vc.await?; + async fn ident(self: Vc) -> Result> { + let this = self.await?; let main_entries = this.main_entries.await?; - let main_entry_key = StringVc::cell(String::new()); + let main_entry_key = Vc::cell(String::new()); let assets = main_entries .iter() .map(|entry| (main_entry_key, entry.ident())) @@ -376,7 +368,7 @@ impl Asset for CssChunk { ident } else { let (_, ident) = assets[0]; - AssetIdentVc::new(Value::new(AssetIdent { + AssetIdent::new(Value::new(AssetIdent { path: ident.path(), query: None, fragment: None, @@ -386,19 +378,19 @@ impl Asset for CssChunk { })) }; - Ok(AssetIdentVc::from_path( - this.context.chunk_path(ident, ".css"), + Ok(AssetIdent::from_path( + this.context.chunk_path(ident, ".css".to_string()), )) } #[turbo_tasks::function] - fn content(self_vc: CssChunkVc) -> AssetContentVc { - self_vc.chunk_content().content() + fn content(self: Vc) -> Vc { + self.chunk_content().content() } #[turbo_tasks::function] - async fn references(self_vc: CssChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let content = css_chunk_content( this.context, this.main_entries, @@ -410,7 +402,9 @@ impl Asset for CssChunk { references.push(*r); for result in r.resolve_reference().await?.primary.iter() { if let PrimaryResolveResult::Asset(asset) = result { - if let Some(embeddable) = CssEmbeddableVc::resolve_from(asset).await? { + if let Some(embeddable) = + Vc::try_resolve_sidecast::>(*asset).await? + { let embed = embeddable.as_css_embed(this.context); references.extend(embed.references().await?.iter()); } @@ -418,44 +412,50 @@ impl Asset for CssChunk { } } for entry in content.async_chunk_group_entries.iter() { - references.push(ChunkGroupReferenceVc::new(this.context, *entry).into()); + references.push(Vc::upcast(ChunkGroupReference::new(this.context, *entry))); } for item in content.chunk_items.iter() { - references.push(SingleItemCssChunkReferenceVc::new(this.context, *item).into()); + references.push(Vc::upcast(SingleItemCssChunkReference::new( + this.context, + *item, + ))); } if *this .context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(CssChunkSourceMapAssetReferenceVc::new(self_vc).into()); + references.push(Vc::upcast(CssChunkSourceMapAssetReference::new(self))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for CssChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: CssChunkVc) -> OptionSourceMapVc { - self_vc.chunk_content().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.chunk_content().generate_source_map() } } #[turbo_tasks::value] pub struct CssChunkContext { - context: ChunkingContextVc, + context: Vc>, } #[turbo_tasks::value_impl] -impl CssChunkContextVc { +impl CssChunkContext { #[turbo_tasks::function] - pub fn of(context: ChunkingContextVc) -> CssChunkContextVc { + pub fn of(context: Vc>) -> Vc { CssChunkContext { context }.cell() } #[turbo_tasks::function] - pub async fn chunk_item_id(self, chunk_item: CssChunkItemVc) -> Result { + pub async fn chunk_item_id( + self: Vc, + chunk_item: Vc>, + ) -> Result> { let layer = self.await?.context.layer(); let mut ident = chunk_item.asset_ident(); if !layer.await?.is_empty() { @@ -467,81 +467,89 @@ impl CssChunkContextVc { #[turbo_tasks::value_trait] pub trait CssChunkPlaceable: Asset { - fn as_chunk_item(&self, context: ChunkingContextVc) -> CssChunkItemVc; + fn as_chunk_item( + self: Vc, + context: Vc>, + ) -> Vc>; } #[turbo_tasks::value(transparent)] -pub struct CssChunkPlaceables(Vec); +pub struct CssChunkPlaceables(Vec>>); #[derive(Clone)] #[turbo_tasks::value(shared)] pub enum CssImport { - External(StringVc), - Internal(ImportAssetReferenceVc, CssChunkItemVc), - Composes(CssChunkItemVc), + External(Vc), + Internal(Vc, Vc>), + Composes(Vc>), } #[turbo_tasks::value(shared)] pub struct CssChunkItemContent { pub inner_code: Rope, pub imports: Vec, - pub source_map: Option, + pub source_map: Option>, } #[turbo_tasks::value_trait] pub trait CssChunkItem: ChunkItem { - fn content(&self) -> CssChunkItemContentVc; - fn chunking_context(&self) -> ChunkingContextVc; - fn id(&self) -> ModuleIdVc { - CssChunkContextVc::of(self.chunking_context()).chunk_item_id(*self) + fn content(self: Vc) -> Vc; + fn chunking_context(self: Vc) -> Vc>; + fn id(self: Vc) -> Vc { + CssChunkContext::of(self.chunking_context()).chunk_item_id(self) } } #[async_trait::async_trait] -impl FromChunkableAsset for CssChunkItemVc { - async fn from_asset(context: ChunkingContextVc, asset: AssetVc) -> Result> { - if let Some(placeable) = CssChunkPlaceableVc::resolve_from(asset).await? { +impl FromChunkableAsset for Box { + async fn from_asset( + context: Vc>, + asset: Vc>, + ) -> Result>> { + if let Some(placeable) = + Vc::try_resolve_sidecast::>(asset).await? + { return Ok(Some(placeable.as_chunk_item(context))); } Ok(None) } async fn from_async_asset( - _context: ChunkingContextVc, - _asset: ChunkableAssetVc, + _context: Vc>, + _asset: Vc>, _availability_info: Value, - ) -> Result> { + ) -> Result>> { Ok(None) } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("css chunk".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("css chunk".to_string()) } #[turbo_tasks::function] -fn entry_module_key() -> StringVc { - StringVc::cell("entry module".to_string()) +fn entry_module_key() -> Vc { + Vc::cell("entry module".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for CssChunk { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(self_vc: CssChunkVc) -> StringVc { - self_vc.path().to_string() + fn title(self: Vc) -> Vc { + self.path().to_string() } #[turbo_tasks::function] - async fn details(self_vc: CssChunkVc) -> Result { - let content = content_to_details(self_vc.content()); + async fn details(self: Vc) -> Result> { + let content = content_to_details(self.content()); let mut details = String::new(); - let this = self_vc.await?; + let this = self.await?; let chunk_content = css_chunk_content( this.context, this.main_entries, @@ -554,17 +562,20 @@ impl Introspectable for CssChunk { } details += "\nContent:\n\n"; write!(details, "{}", content.await?)?; - Ok(StringVc::cell(details)) + Ok(Vc::cell(details)) } #[turbo_tasks::function] - async fn children(self_vc: CssChunkVc) -> Result { - let mut children = children_from_asset_references(self_vc.references()) + async fn children(self: Vc) -> Result> { + let mut children = children_from_asset_references(self.references()) .await? .clone_value(); - for &entry in &*self_vc.await?.main_entries.await? { - children.insert((entry_module_key(), IntrospectableAssetVc::new(entry.into()))); + for &entry in &*self.await?.main_entries.await? { + children.insert(( + entry_module_key(), + IntrospectableAsset::new(Vc::upcast(entry)), + )); } - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-css/src/chunk/single_item_chunk/chunk.rs b/crates/turbopack-css/src/chunk/single_item_chunk/chunk.rs index 34138feb842e9c..5d6e337172f10e 100644 --- a/crates/turbopack-css/src/chunk/single_item_chunk/chunk.rs +++ b/crates/turbopack-css/src/chunk/single_item_chunk/chunk.rs @@ -1,43 +1,43 @@ use std::fmt::Write; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - chunk::{Chunk, ChunkItem, ChunkVc, ChunkingContext, ChunkingContextVc}, - code_builder::{CodeBuilder, CodeVc}, - ident::AssetIdentVc, - introspect::{Introspectable, IntrospectableVc}, - reference::AssetReferencesVc, - source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, + asset::{Asset, AssetContent}, + chunk::{Chunk, ChunkItem, ChunkingContext}, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + introspect::Introspectable, + reference::AssetReferences, + source_map::{GenerateSourceMap, OptionSourceMap}, }; -use super::source_map::SingleItemCssChunkSourceMapAssetReferenceVc; -use crate::chunk::{CssChunkItem, CssChunkItemVc}; +use super::source_map::SingleItemCssChunkSourceMapAssetReference; +use crate::chunk::CssChunkItem; /// A CSS chunk that only contains a single item. This is used for selectively /// loading CSS modules that are part of a larger chunk in development mode, and /// avoiding rule duplication. #[turbo_tasks::value] pub struct SingleItemCssChunk { - context: ChunkingContextVc, - item: CssChunkItemVc, + context: Vc>, + item: Vc>, } #[turbo_tasks::value_impl] -impl SingleItemCssChunkVc { - /// Creates a new [`SingleItemCssChunkVc`]. +impl SingleItemCssChunk { + /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub fn new(context: ChunkingContextVc, item: CssChunkItemVc) -> Self { + pub fn new(context: Vc>, item: Vc>) -> Vc { SingleItemCssChunk { context, item }.cell() } } #[turbo_tasks::value_impl] -impl SingleItemCssChunkVc { +impl SingleItemCssChunk { #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { use std::io::Write; let this = self.await?; @@ -47,14 +47,11 @@ impl SingleItemCssChunkVc { writeln!(code, "/* {} */", id)?; let content = this.item.content().await?; - code.push_source( - &content.inner_code, - content.source_map.map(|sm| sm.as_generate_source_map()), - ); + code.push_source(&content.inner_code, content.source_map.map(Vc::upcast)); if *this .context - .reference_chunk_source_maps(self.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? && code.has_source_map() { @@ -74,90 +71,94 @@ impl SingleItemCssChunkVc { #[turbo_tasks::value_impl] impl Chunk for SingleItemCssChunk { #[turbo_tasks::function] - fn chunking_context(&self) -> ChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } } #[turbo_tasks::function] -fn single_item_modifier() -> StringVc { - StringVc::cell("single item css chunk".to_string()) +fn single_item_modifier() -> Vc { + Vc::cell("single item css chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for SingleItemCssChunk { #[turbo_tasks::function] - async fn ident(&self) -> Result { - Ok(AssetIdentVc::from_path( + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path( self.context.chunk_path( self.item .asset_ident() .with_modifier(single_item_modifier()), - ".css", + ".css".to_string(), ), )) } #[turbo_tasks::function] - async fn content(self_vc: SingleItemCssChunkVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } #[turbo_tasks::function] - async fn references(self_vc: SingleItemCssChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let mut references = Vec::new(); if *this .context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(SingleItemCssChunkSourceMapAssetReferenceVc::new(self_vc).into()); + references.push(Vc::upcast(SingleItemCssChunkSourceMapAssetReference::new( + self, + ))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for SingleItemCssChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: SingleItemCssChunkVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("single asset css chunk".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("single asset css chunk".to_string()) } #[turbo_tasks::function] -fn entry_module_key() -> StringVc { - StringVc::cell("entry module".to_string()) +fn entry_module_key() -> Vc { + Vc::cell("entry module".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for SingleItemCssChunk { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(self_vc: SingleItemCssChunkVc) -> StringVc { - self_vc.path().to_string() + fn title(self: Vc) -> Vc { + self.path().to_string() } #[turbo_tasks::function] - async fn details(self_vc: SingleItemCssChunkVc) -> Result { - let this = self_vc.await?; + async fn details(self: Vc) -> Result> { + let this = self.await?; let mut details = String::new(); write!( details, "Chunk item: {}", this.item.asset_ident().to_string().await? )?; - Ok(StringVc::cell(details)) + Ok(Vc::cell(details)) } } diff --git a/crates/turbopack-css/src/chunk/single_item_chunk/reference.rs b/crates/turbopack-css/src/chunk/single_item_chunk/reference.rs index eaf83b03807b98..8972b14cefd725 100644 --- a/crates/turbopack-css/src/chunk/single_item_chunk/reference.rs +++ b/crates/turbopack-css/src/chunk/single_item_chunk/reference.rs @@ -1,30 +1,29 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbopack_core::{ chunk::{ - ChunkItem, ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingContextVc, - ChunkingType, ChunkingTypeOptionVc, + ChunkItem, ChunkableAssetReference, ChunkingContext, ChunkingType, ChunkingTypeOption, }, - reference::{AssetReference, AssetReferenceVc}, - resolve::{ResolveResult, ResolveResultVc}, + reference::AssetReference, + resolve::ResolveResult, }; -use super::chunk::SingleItemCssChunkVc; -use crate::chunk::CssChunkItemVc; +use super::chunk::SingleItemCssChunk; +use crate::chunk::CssChunkItem; -/// A reference to a [`SingleItemCssChunkVc`]. +/// A reference to a [`Vc`]. #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct SingleItemCssChunkReference { - context: ChunkingContextVc, - item: CssChunkItemVc, + context: Vc>, + item: Vc>, } #[turbo_tasks::value_impl] -impl SingleItemCssChunkReferenceVc { - /// Creates a new [`SingleItemCssChunkReferenceVc`]. +impl SingleItemCssChunkReference { + /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub fn new(context: ChunkingContextVc, item: CssChunkItemVc) -> Self { + pub fn new(context: Vc>, item: Vc>) -> Vc { Self::cell(SingleItemCssChunkReference { context, item }) } } @@ -32,16 +31,16 @@ impl SingleItemCssChunkReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for SingleItemCssChunkReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset(SingleItemCssChunkVc::new(self.context, self.item).into()).cell() + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast(SingleItemCssChunk::new(self.context, self.item))).cell() } } #[turbo_tasks::value_impl] impl ValueToString for SingleItemCssChunkReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "css single item chunk {}", self.item.asset_ident().to_string().await? ))) @@ -51,7 +50,7 @@ impl ValueToString for SingleItemCssChunkReference { #[turbo_tasks::value_impl] impl ChunkableAssetReference for SingleItemCssChunkReference { #[turbo_tasks::function] - fn chunking_type(&self) -> Result { - Ok(ChunkingTypeOptionVc::cell(Some(ChunkingType::Separate))) + fn chunking_type(&self) -> Result> { + Ok(Vc::cell(Some(ChunkingType::Separate))) } } diff --git a/crates/turbopack-css/src/chunk/single_item_chunk/source_map.rs b/crates/turbopack-css/src/chunk/single_item_chunk/source_map.rs index ad2a6949b7ddc4..3f01e3b1f6805a 100644 --- a/crates/turbopack-css/src/chunk/single_item_chunk/source_map.rs +++ b/crates/turbopack-css/src/chunk/single_item_chunk/source_map.rs @@ -1,27 +1,27 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::Chunk, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferenceVc}, - resolve::{ResolveResult, ResolveResultVc}, - source_map::{GenerateSourceMap, SourceMapVc}, + ident::AssetIdent, + reference::AssetReference, + resolve::ResolveResult, + source_map::{GenerateSourceMap, SourceMap}, }; -use super::chunk::SingleItemCssChunkVc; +use super::chunk::SingleItemCssChunk; /// Represents the source map of a single item CSS chunk. #[turbo_tasks::value] pub struct SingleItemCssChunkSourceMapAsset { - chunk: SingleItemCssChunkVc, + chunk: Vc, } #[turbo_tasks::value_impl] -impl SingleItemCssChunkSourceMapAssetVc { +impl SingleItemCssChunkSourceMapAsset { #[turbo_tasks::function] - pub fn new(chunk: SingleItemCssChunkVc) -> Self { + pub fn new(chunk: Vc) -> Vc { SingleItemCssChunkSourceMapAsset { chunk }.cell() } } @@ -29,19 +29,21 @@ impl SingleItemCssChunkSourceMapAssetVc { #[turbo_tasks::value_impl] impl Asset for SingleItemCssChunkSourceMapAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { - Ok(AssetIdentVc::from_path(self.chunk.path().append(".map"))) + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path( + self.chunk.path().append(".map".to_string()), + )) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let sm = if let Some(sm) = *self.chunk.generate_source_map().await? { sm } else { - SourceMapVc::empty() + SourceMap::empty() }; let sm = sm.to_rope().await?; - Ok(File::from(sm).into()) + Ok(AssetContent::file(File::from(sm).into())) } } @@ -49,13 +51,13 @@ impl Asset for SingleItemCssChunkSourceMapAsset { /// dev server/build system of the presence of the source map #[turbo_tasks::value] pub struct SingleItemCssChunkSourceMapAssetReference { - chunk: SingleItemCssChunkVc, + chunk: Vc, } #[turbo_tasks::value_impl] -impl SingleItemCssChunkSourceMapAssetReferenceVc { +impl SingleItemCssChunkSourceMapAssetReference { #[turbo_tasks::function] - pub fn new(chunk: SingleItemCssChunkVc) -> Self { + pub fn new(chunk: Vc) -> Vc { SingleItemCssChunkSourceMapAssetReference { chunk }.cell() } } @@ -63,10 +65,10 @@ impl SingleItemCssChunkSourceMapAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for SingleItemCssChunkSourceMapAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { - let source_maps = vec![SingleItemCssChunkSourceMapAsset { chunk: self.chunk } - .cell() - .into()]; + async fn resolve_reference(&self) -> Result> { + let source_maps = vec![Vc::upcast( + SingleItemCssChunkSourceMapAsset { chunk: self.chunk }.cell(), + )]; Ok(ResolveResult::assets_with_references(source_maps, vec![]).cell()) } } @@ -74,8 +76,8 @@ impl AssetReference for SingleItemCssChunkSourceMapAssetReference { #[turbo_tasks::value_impl] impl ValueToString for SingleItemCssChunkSourceMapAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "source maps for {}", self.chunk.path().to_string().await? ))) diff --git a/crates/turbopack-css/src/chunk/source_map.rs b/crates/turbopack-css/src/chunk/source_map.rs index 12b8d7e2aed94c..b1e46fe4383129 100644 --- a/crates/turbopack-css/src/chunk/source_map.rs +++ b/crates/turbopack-css/src/chunk/source_map.rs @@ -1,27 +1,27 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::Chunk, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferenceVc}, - resolve::{ResolveResult, ResolveResultVc}, - source_map::{GenerateSourceMap, SourceMapVc}, + ident::AssetIdent, + reference::AssetReference, + resolve::ResolveResult, + source_map::{GenerateSourceMap, SourceMap}, }; -use super::CssChunkVc; +use super::CssChunk; /// Represents the source map of an css chunk. #[turbo_tasks::value] pub struct CssChunkSourceMapAsset { - chunk: CssChunkVc, + chunk: Vc, } #[turbo_tasks::value_impl] -impl CssChunkSourceMapAssetVc { +impl CssChunkSourceMapAsset { #[turbo_tasks::function] - pub fn new(chunk: CssChunkVc) -> Self { + pub fn new(chunk: Vc) -> Vc { CssChunkSourceMapAsset { chunk }.cell() } } @@ -29,19 +29,21 @@ impl CssChunkSourceMapAssetVc { #[turbo_tasks::value_impl] impl Asset for CssChunkSourceMapAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { - Ok(AssetIdentVc::from_path(self.chunk.path().append(".map"))) + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path( + self.chunk.path().append(".map".to_string()), + )) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let sm = if let Some(sm) = *self.chunk.generate_source_map().await? { sm } else { - SourceMapVc::empty() + SourceMap::empty() }; let sm = sm.to_rope().await?; - Ok(File::from(sm).into()) + Ok(AssetContent::file(File::from(sm).into())) } } @@ -49,13 +51,13 @@ impl Asset for CssChunkSourceMapAsset { /// server/build system of the presence of the source map #[turbo_tasks::value] pub struct CssChunkSourceMapAssetReference { - chunk: CssChunkVc, + chunk: Vc, } #[turbo_tasks::value_impl] -impl CssChunkSourceMapAssetReferenceVc { +impl CssChunkSourceMapAssetReference { #[turbo_tasks::function] - pub fn new(chunk: CssChunkVc) -> Self { + pub fn new(chunk: Vc) -> Vc { CssChunkSourceMapAssetReference { chunk }.cell() } } @@ -63,8 +65,10 @@ impl CssChunkSourceMapAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for CssChunkSourceMapAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { - let source_maps = vec![CssChunkSourceMapAsset { chunk: self.chunk }.cell().into()]; + async fn resolve_reference(&self) -> Result> { + let source_maps = vec![Vc::upcast( + CssChunkSourceMapAsset { chunk: self.chunk }.cell(), + )]; Ok(ResolveResult::assets_with_references(source_maps, vec![]).cell()) } } @@ -72,8 +76,8 @@ impl AssetReference for CssChunkSourceMapAssetReference { #[turbo_tasks::value_impl] impl ValueToString for CssChunkSourceMapAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "source maps for {}", self.chunk.path().to_string().await? ))) diff --git a/crates/turbopack-css/src/chunk/writer.rs b/crates/turbopack-css/src/chunk/writer.rs index b1d1493c03a53f..c83b21dfe51a41 100644 --- a/crates/turbopack-css/src/chunk/writer.rs +++ b/crates/turbopack-css/src/chunk/writer.rs @@ -4,16 +4,15 @@ use std::{ }; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString}; +use turbo_tasks::{ValueToString, Vc}; use turbopack_core::{chunk::ChunkItem, code_builder::CodeBuilder}; -use super::{CssChunkItemVc, CssImport}; -use crate::chunk::CssChunkItem; +use super::{CssChunkItem, CssImport}; pub async fn expand_imports( code: &mut CodeBuilder, - chunk_item: CssChunkItemVc, -) -> Result> { + chunk_item: Vc>, +) -> Result>> { let content = chunk_item.content().await?; let mut stack = vec![( chunk_item, @@ -21,8 +20,9 @@ pub async fn expand_imports( "".to_string(), )]; let mut external_imports = vec![]; - let mut imported_chunk_items: HashSet<(String, String, CssChunkItemVc)> = HashSet::default(); - let mut composed_chunk_items: HashSet = HashSet::default(); + type ImportedChunkItemEntry = (String, String, Vc>); + let mut imported_chunk_items: HashSet = HashSet::default(); + let mut composed_chunk_items: HashSet>> = HashSet::default(); while let Some((chunk_item, imports, close)) = stack.last_mut() { match imports.pop_front() { @@ -73,10 +73,7 @@ pub async fn expand_imports( writeln!(code, "/* {} */", id)?; let content = chunk_item.content().await?; - code.push_source( - &content.inner_code, - content.source_map.map(|sm| sm.as_generate_source_map()), - ); + code.push_source(&content.inner_code, content.source_map.map(Vc::upcast)); writeln!(code, "\n{}", close)?; diff --git a/crates/turbopack-css/src/code_gen.rs b/crates/turbopack-css/src/code_gen.rs index 499a5d42e11e9a..5af2388bf7d96e 100644 --- a/crates/turbopack-css/src/code_gen.rs +++ b/crates/turbopack-css/src/code_gen.rs @@ -1,5 +1,6 @@ use swc_core::css::visit::{AstParentKind, VisitMut}; -use turbopack_core::chunk::ChunkingContextVc; +use turbo_tasks::Vc; +use turbopack_core::chunk::ChunkingContext; use crate::chunk::CssImport; @@ -26,11 +27,12 @@ pub trait VisitorFactory: Send + Sync { #[turbo_tasks::value_trait] pub trait CodeGenerateable { - fn code_generation(&self, context: ChunkingContextVc) -> CodeGenerationVc; + fn code_generation(self: Vc, context: Vc>) + -> Vc; } #[turbo_tasks::value(transparent)] -pub struct CodeGenerateables(Vec); +pub struct CodeGenerateables(Vec>>); pub fn path_to( path: &[AstParentKind], diff --git a/crates/turbopack-css/src/embed.rs b/crates/turbopack-css/src/embed.rs index 7d35313de659c8..313f5c65387960 100644 --- a/crates/turbopack-css/src/embed.rs +++ b/crates/turbopack-css/src/embed.rs @@ -1,12 +1,14 @@ +use turbo_tasks::Vc; use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{ChunkableAsset, ChunkableAssetVc, ChunkingContextVc}, - reference::AssetReferencesVc, + asset::Asset, + chunk::{ChunkableAsset, ChunkingContext}, + reference::AssetReferences, }; #[turbo_tasks::value_trait] pub trait CssEmbeddable: ChunkableAsset + Asset { - fn as_css_embed(&self, context: ChunkingContextVc) -> CssEmbedVc; + fn as_css_embed(self: Vc, context: Vc>) + -> Vc>; } #[turbo_tasks::value_trait] @@ -15,6 +17,6 @@ pub trait CssEmbed { /// [Asset]. /// TODO(alexkirsz) This should have a default impl that returns empty /// references. - fn references(&self) -> AssetReferencesVc; - fn embeddable_asset(&self) -> AssetVc; + fn references(self: Vc) -> Vc; + fn embeddable_asset(self: Vc) -> Vc>; } diff --git a/crates/turbopack-css/src/lib.rs b/crates/turbopack-css/src/lib.rs index 7c18bc012cbb6a..acf513ff9597ab 100644 --- a/crates/turbopack-css/src/lib.rs +++ b/crates/turbopack-css/src/lib.rs @@ -2,6 +2,8 @@ #![feature(box_patterns)] #![feature(iter_intersperse)] #![feature(int_roundings)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] mod asset; pub mod chunk; @@ -14,12 +16,11 @@ pub(crate) mod references; pub(crate) mod transform; pub(crate) mod util; -use anyhow::Result; -pub use asset::CssModuleAssetVc; -pub use module_asset::ModuleCssModuleAssetVc; -pub use transform::{CssInputTransform, CssInputTransformsVc}; +pub use asset::CssModuleAsset; +pub use module_asset::ModuleCssModuleAsset; +pub use transform::{CssInputTransform, CssInputTransforms}; -use crate::references::import::ImportAssetReferenceVc; +use crate::references::import::ImportAssetReference; #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(PartialOrd, Ord, Hash, Debug, Copy, Clone)] diff --git a/crates/turbopack-css/src/module_asset.rs b/crates/turbopack-css/src/module_asset.rs index 93bc66b34fa494..2b5b7b04662f9a 100644 --- a/crates/turbopack-css/src/module_asset.rs +++ b/crates/turbopack-css/src/module_asset.rs @@ -7,63 +7,58 @@ use swc_core::{ common::{BytePos, FileName, LineCol, SourceMap}, css::modules::CssClassName, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContextVc, - ChunkingType, ChunkingTypeOptionVc, - }, - context::AssetContextVc, - ident::AssetIdentVc, - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - ResolveResult, ResolveResultVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, + ChunkableAssetReference, ChunkingContext, ChunkingType, ChunkingTypeOption, }, + context::AssetContext, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity}, + reference::{AssetReference, AssetReferences}, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; use turbopack_ecmascript::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, - EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemExt, + EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports, }, utils::StringifyJs, - ParseResultSourceMap, ParseResultSourceMapVc, + ParseResultSourceMap, }; use crate::{ - chunk::{ - CssChunkItem, CssChunkItemContentVc, CssChunkItemVc, CssChunkPlaceable, - CssChunkPlaceableVc, CssChunkVc, - }, + chunk::{CssChunk, CssChunkItem, CssChunkItemContent, CssChunkPlaceable}, parse::ParseResult, - references::compose::CssModuleComposeReferenceVc, - transform::CssInputTransformsVc, - CssModuleAssetVc, + references::compose::CssModuleComposeReference, + transform::CssInputTransforms, + CssModuleAsset, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("css module".to_string()) +fn modifier() -> Vc { + Vc::cell("css module".to_string()) } #[turbo_tasks::value] #[derive(Clone)] pub struct ModuleCssModuleAsset { - pub inner: CssModuleAssetVc, + pub inner: Vc, } #[turbo_tasks::value_impl] -impl ModuleCssModuleAssetVc { +impl ModuleCssModuleAsset { #[turbo_tasks::function] - pub fn new(source: AssetVc, context: AssetContextVc, transforms: CssInputTransformsVc) -> Self { + pub fn new( + source: Vc>, + context: Vc>, + transforms: Vc, + ) -> Vc { Self::cell(ModuleCssModuleAsset { - inner: CssModuleAssetVc::new_module(source, context, transforms), + inner: CssModuleAsset::new_module(source, context, transforms), }) } } @@ -71,19 +66,19 @@ impl ModuleCssModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for ModuleCssModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.inner.source_ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.inner.content() } #[turbo_tasks::function] - async fn references(self_vc: ModuleCssModuleAssetVc) -> Result { - let references = self_vc.await?.inner.references().await?; - let module_references = self_vc.module_references().await?; + async fn references(self: Vc) -> Result> { + let references = self.await?.inner.references().await?; + let module_references = self.module_references().await?; let references: Vec<_> = references .iter() @@ -91,7 +86,7 @@ impl Asset for ModuleCssModuleAsset { .chain(module_references.iter().copied()) .collect(); - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } @@ -109,7 +104,7 @@ enum ModuleCssClass { }, Import { original: String, - from: CssModuleComposeReferenceVc, + from: Vc, }, } @@ -140,9 +135,9 @@ enum ModuleCssClass { struct ModuleCssClasses(IndexMap>); #[turbo_tasks::value_impl] -impl ModuleCssModuleAssetVc { +impl ModuleCssModuleAsset { #[turbo_tasks::function] - async fn classes(self) -> Result { + async fn classes(self: Vc) -> Result> { let inner = self.await?.inner; let parse_result = inner.parse().await?; let mut classes = IndexMap::default(); @@ -156,9 +151,9 @@ impl ModuleCssModuleAssetVc { export.push(match export_class_name { CssClassName::Import { from, name } => ModuleCssClass::Import { original: name.value.to_string(), - from: CssModuleComposeReferenceVc::new( - self.as_resolve_origin(), - RequestVc::parse(Value::new(from.to_string().into())), + from: CssModuleComposeReference::new( + Vc::upcast(self), + Request::parse(Value::new(from.to_string().into())), ), }, CssClassName::Local { name } => ModuleCssClass::Local { @@ -174,25 +169,25 @@ impl ModuleCssModuleAssetVc { } } - Ok(ModuleCssClassesVc::cell(classes)) + Ok(Vc::cell(classes)) } #[turbo_tasks::function] - async fn module_references(self) -> Result { + async fn module_references(self: Vc) -> Result> { let mut references = vec![]; for (_, class_names) in &*self.classes().await? { for class_name in class_names { match class_name { ModuleCssClass::Import { from, .. } => { - references.push((*from).into()); + references.push(Vc::upcast(*from)); } ModuleCssClass::Local { .. } | ModuleCssClass::Global { .. } => {} } } } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } @@ -200,11 +195,15 @@ impl ModuleCssModuleAssetVc { impl ChunkableAsset for ModuleCssModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: ModuleCssModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new(context, self_vc.into(), availability_info).into() + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( + context, + Vc::upcast(self), + availability_info, + )) } } @@ -212,19 +211,20 @@ impl ChunkableAsset for ModuleCssModuleAsset { impl EcmascriptChunkPlaceable for ModuleCssModuleAsset { #[turbo_tasks::function] fn as_chunk_item( - self_vc: ModuleCssModuleAssetVc, - context: EcmascriptChunkingContextVc, - ) -> EcmascriptChunkItemVc { - ModuleChunkItem { - context, - module: self_vc, - } - .cell() - .into() + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast( + ModuleChunkItem { + context, + module: self, + } + .cell(), + ) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } } @@ -232,57 +232,58 @@ impl EcmascriptChunkPlaceable for ModuleCssModuleAsset { #[turbo_tasks::value_impl] impl ResolveOrigin for ModuleCssModuleAsset { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.inner.ident().path() } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { + fn context(&self) -> Vc> { self.inner.context() } } #[turbo_tasks::value] struct ModuleChunkItem { - module: ModuleCssModuleAssetVc, - context: EcmascriptChunkingContextVc, + module: Vc, + context: Vc>, } #[turbo_tasks::value_impl] impl ChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.module.ident() } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { // The proxy reference must come first so it is processed before other potential // references inside of the CSS, like `@import` and `composes:`. // This affects the order in which the resulting CSS chunks will be loaded: // later references are processed first in the post-order traversal of the // reference tree, and as such they will be loaded first in the resulting HTML. - let mut references = vec![CssProxyToCssAssetReference { - module: self.module, - } - .cell() - .into()]; + let mut references = vec![Vc::upcast( + CssProxyToCssAssetReference { + module: self.module, + } + .cell(), + )]; references.extend(self.module.references().await?.iter().copied()); - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::value_impl] impl EcmascriptChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let classes = self.module.classes().await?; let mut code = "__turbopack_export_value__({\n".to_string(); @@ -301,47 +302,46 @@ impl EcmascriptChunkItem for ModuleChunkItem { CssModuleComposesIssue { severity: IssueSeverity::Error.cell(), source: self.module.ident(), - message: StringVc::cell(formatdoc! { + message: Vc::cell(formatdoc! { r#" Module {from} referenced in `composes: ... from {from};` can't be resolved. "#, from = &*from.await?.request.to_string().await? }), - }.cell().as_issue().emit(); + }.cell().emit(); continue; }; - let Some(css_module) = ModuleCssModuleAssetVc::resolve_from(resolved_module).await? else { + let Some(css_module) = Vc::try_resolve_downcast_type::(*resolved_module).await? else { CssModuleComposesIssue { severity: IssueSeverity::Error.cell(), source: self.module.ident(), - message: StringVc::cell(formatdoc! { + message: Vc::cell(formatdoc! { r#" Module {from} referenced in `composes: ... from {from};` is not a CSS module. "#, from = &*from.await?.request.to_string().await? }), - }.cell().as_issue().emit(); + }.cell().emit(); continue; }; // TODO(alexkirsz) We should also warn if `original_name` can't be found in // the target module. - let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(css_module).await? else { - unreachable!("ModuleCssModuleAsset implements EcmascriptChunkPlaceableVc"); - }; + let placeable: Vc> = + Vc::upcast(css_module); let module_id = placeable.as_chunk_item(self.context).id().await?; let module_id = StringifyJs(&*module_id); - let original_name = StringifyJs(original_name); + let original_name = StringifyJs(&original_name); exported_class_names.push(format! { "__turbopack_import__({module_id})[{original_name}]" }); } ModuleCssClass::Local { name: class_name } | ModuleCssClass::Global { name: class_name } => { - exported_class_names.push(StringifyJs(class_name).to_string()); + exported_class_names.push(StringifyJs(&class_name).to_string()); } } } @@ -370,14 +370,14 @@ impl EcmascriptChunkItem for ModuleChunkItem { #[turbo_tasks::value] struct CssProxyToCssAssetReference { - module: ModuleCssModuleAssetVc, + module: Vc, } #[turbo_tasks::value_impl] impl ValueToString for CssProxyToCssAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "proxy(css) {}", self.module.ident().to_string().await?, ))) @@ -387,14 +387,13 @@ impl ValueToString for CssProxyToCssAssetReference { #[turbo_tasks::value_impl] impl AssetReference for CssProxyToCssAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset( + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast( CssProxyModuleAsset { module: self.module, } - .cell() - .into(), - ) + .cell(), + )) .cell() } } @@ -402,8 +401,8 @@ impl AssetReference for CssProxyToCssAssetReference { #[turbo_tasks::value_impl] impl ChunkableAssetReference for CssProxyToCssAssetReference { #[turbo_tasks::function] - fn chunking_type(&self) -> ChunkingTypeOptionVc { - ChunkingTypeOptionVc::cell(Some(ChunkingType::Parallel)) + fn chunking_type(&self) -> Vc { + Vc::cell(Some(ChunkingType::Parallel)) } } @@ -412,23 +411,23 @@ impl ChunkableAssetReference for CssProxyToCssAssetReference { #[turbo_tasks::value] #[derive(Clone)] struct CssProxyModuleAsset { - module: ModuleCssModuleAssetVc, + module: Vc, } #[turbo_tasks::value_impl] impl Asset for CssProxyModuleAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { Ok(self.module.await?.inner.ident().with_modifier(modifier())) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.module.content() } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { // The original references must come first so they're processed before other // potential references inside of the CSS, like `@import` and `composes:`. This // affects the order in which the resulting CSS chunks will be loaded: @@ -439,7 +438,7 @@ impl Asset for CssProxyModuleAsset { references.extend(self.module.module_references().await?.iter().copied()); - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } @@ -447,54 +446,56 @@ impl Asset for CssProxyModuleAsset { impl ChunkableAsset for CssProxyModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: CssProxyModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - CssChunkVc::new(context, self_vc.into(), availability_info).into() + ) -> Vc> { + Vc::upcast(CssChunk::new(context, Vc::upcast(self), availability_info)) } } #[turbo_tasks::value_impl] impl CssChunkPlaceable for CssProxyModuleAsset { #[turbo_tasks::function] - fn as_chunk_item(self_vc: CssProxyModuleAssetVc, context: ChunkingContextVc) -> CssChunkItemVc { - CssProxyModuleChunkItemVc::cell(CssProxyModuleChunkItem { - inner: self_vc, + fn as_chunk_item( + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(CssProxyModuleChunkItem::cell(CssProxyModuleChunkItem { + inner: self, context, - }) - .into() + })) } } #[turbo_tasks::value_impl] impl ResolveOrigin for CssProxyModuleAsset { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.module.ident().path() } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { + fn context(&self) -> Vc> { self.module.context() } } #[turbo_tasks::value] struct CssProxyModuleChunkItem { - inner: CssProxyModuleAssetVc, - context: ChunkingContextVc, + inner: Vc, + context: Vc>, } #[turbo_tasks::value_impl] impl ChunkItem for CssProxyModuleChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.inner.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.inner.references() } } @@ -502,7 +503,7 @@ impl ChunkItem for CssProxyModuleChunkItem { #[turbo_tasks::value_impl] impl CssChunkItem for CssProxyModuleChunkItem { #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { Ok(self .inner .await? @@ -514,12 +515,12 @@ impl CssChunkItem for CssProxyModuleChunkItem { } #[turbo_tasks::function] - fn chunking_context(&self) -> ChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } } -fn generate_minimal_source_map(filename: String, source: String) -> ParseResultSourceMapVc { +fn generate_minimal_source_map(filename: String, source: String) -> Vc { let mut mappings = vec![]; // Start from 1 because 0 is reserved for dummy spans in SWC. let mut pos = 1; @@ -541,37 +542,37 @@ fn generate_minimal_source_map(filename: String, source: String) -> ParseResultS #[turbo_tasks::value(shared)] struct CssModuleComposesIssue { - severity: IssueSeverityVc, - source: AssetIdentVc, - message: StringVc, + severity: Vc, + source: Vc, + message: Vc, } #[turbo_tasks::value_impl] impl Issue for CssModuleComposesIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - async fn title(&self) -> Result { - Ok(StringVc::cell( + async fn title(&self) -> Result> { + Ok(Vc::cell( "An issue occurred while resolving a CSS module `composes:` rule".to_string(), )) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("css".to_string()) + fn category(&self) -> Vc { + Vc::cell("css".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.source.path() } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.message } } diff --git a/crates/turbopack-css/src/parse.rs b/crates/turbopack-css/src/parse.rs index e50fae880a1ec2..32f9ed38a8b866 100644 --- a/crates/turbopack-css/src/parse.rs +++ b/crates/turbopack-css/src/parse.rs @@ -15,17 +15,17 @@ use swc_core::{ }, ecma::atoms::JsWord, }; -use turbo_tasks::{Value, ValueToString}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbo_tasks_fs::{FileContent, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContent, AssetVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, + asset::{Asset, AssetContent}, + source_map::{GenerateSourceMap, OptionSourceMap}, SOURCE_MAP_ROOT_NAME, }; use turbopack_swc_utils::emitter::IssueEmitter; use crate::{ - transform::{CssInputTransform, CssInputTransformsVc, TransformContext}, + transform::{CssInputTransform, CssInputTransforms, TransformContext}, CssModuleAssetType, }; @@ -86,13 +86,13 @@ impl ParseResultSourceMap { #[turbo_tasks::value_impl] impl GenerateSourceMap for ParseResultSourceMap { #[turbo_tasks::function] - fn generate_source_map(&self) -> OptionSourceMapVc { + fn generate_source_map(&self) -> Vc { let map = self.source_map.build_source_map_with_config( &self.mappings, None, InlineSourcesContentConfig {}, ); - OptionSourceMapVc::cell(Some( + Vc::cell(Some( turbopack_core::source_map::SourceMap::new_regular(map).cell(), )) } @@ -118,10 +118,10 @@ impl SourceMapGenConfig for InlineSourcesContentConfig { #[turbo_tasks::function] pub async fn parse( - source: AssetVc, + source: Vc>, ty: Value, - transforms: CssInputTransformsVc, -) -> Result { + transforms: Vc, +) -> Result> { let content = source.content(); let fs_path = &*source.ident().path().await?; let ident_str = &*source.ident().to_string().await?; @@ -153,10 +153,10 @@ async fn parse_content( string: String, fs_path: &FileSystemPath, ident_str: &str, - source: AssetVc, + source: Vc>, ty: CssModuleAssetType, transforms: &[CssInputTransform], -) -> Result { +) -> Result> { let source_map: Arc = Default::default(); let handler = Handler::with_emitter( true, diff --git a/crates/turbopack-css/src/references/compose.rs b/crates/turbopack-css/src/references/compose.rs index 9230f4ddd7a095..77c873cff1914d 100644 --- a/crates/turbopack-css/src/references/compose.rs +++ b/crates/turbopack-css/src/references/compose.rs @@ -1,11 +1,11 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - chunk::{ChunkableAssetReference, ChunkableAssetReferenceVc}, - issue::OptionIssueSourceVc, - reference::{AssetReference, AssetReferenceVc}, + chunk::ChunkableAssetReference, + issue::OptionIssueSource, + reference::AssetReference, reference_type::CssReferenceSubType, - resolve::{origin::ResolveOriginVc, parse::RequestVc, ResolveResultVc}, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; use crate::references::css_resolve; @@ -14,15 +14,15 @@ use crate::references::css_resolve; #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct CssModuleComposeReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, + pub origin: Vc>, + pub request: Vc, } #[turbo_tasks::value_impl] -impl CssModuleComposeReferenceVc { +impl CssModuleComposeReference { /// Creates a new [`CssModuleComposeReference`]. #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, request: RequestVc) -> Self { + pub fn new(origin: Vc>, request: Vc) -> Vc { Self::cell(CssModuleComposeReference { origin, request }) } } @@ -30,7 +30,7 @@ impl CssModuleComposeReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for CssModuleComposeReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { css_resolve( self.origin, self.request, @@ -38,7 +38,7 @@ impl AssetReference for CssModuleComposeReference { // TODO: add real issue source, currently impossible because `CssClassName` doesn't // contain the source span // https://docs.rs/swc_css_modules/0.21.16/swc_css_modules/enum.CssClassName.html - OptionIssueSourceVc::none(), + OptionIssueSource::none(), ) } } @@ -46,8 +46,8 @@ impl AssetReference for CssModuleComposeReference { #[turbo_tasks::value_impl] impl ValueToString for CssModuleComposeReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "compose(url) {}", self.request.to_string().await?, ))) diff --git a/crates/turbopack-css/src/references/import.rs b/crates/turbopack-css/src/references/import.rs index 7e1bb9d18ad087..05e3545c1b7bcb 100644 --- a/crates/turbopack-css/src/references/import.rs +++ b/crates/turbopack-css/src/references/import.rs @@ -9,23 +9,19 @@ use swc_core::{ }, }, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - chunk::{ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingContextVc}, - issue::{IssueSourceVc, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, + chunk::{ChunkableAssetReference, ChunkingContext}, + issue::{IssueSource, OptionIssueSource}, + reference::AssetReference, reference_type::CssReferenceSubType, - resolve::{ - origin::ResolveOriginVc, - parse::{Request, RequestVc}, - ResolveResultVc, - }, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; use crate::{ chunk::CssImport, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, - references::{css_resolve, AstPathVc}, + code_gen::{CodeGenerateable, CodeGeneration}, + references::{css_resolve, AstPath}, }; #[turbo_tasks::value(into = "new")] @@ -187,23 +183,23 @@ impl ImportAttributes { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct ImportAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub path: AstPathVc, - pub attributes: ImportAttributesVc, - pub issue_source: IssueSourceVc, + pub origin: Vc>, + pub request: Vc, + pub path: Vc, + pub attributes: Vc, + pub issue_source: Vc, } #[turbo_tasks::value_impl] -impl ImportAssetReferenceVc { +impl ImportAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - path: AstPathVc, - attributes: ImportAttributesVc, - issue_source: IssueSourceVc, - ) -> Self { + origin: Vc>, + request: Vc, + path: Vc, + attributes: Vc, + issue_source: Vc, + ) -> Vc { Self::cell(ImportAssetReference { origin, request, @@ -217,12 +213,12 @@ impl ImportAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for ImportAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { css_resolve( self.origin, self.request, Value::new(CssReferenceSubType::AtImport), - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), ) } } @@ -230,8 +226,8 @@ impl AssetReference for ImportAssetReference { #[turbo_tasks::value_impl] impl ValueToString for ImportAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "import(url) {}", self.request.to_string().await?, ))) @@ -242,17 +238,17 @@ impl ValueToString for ImportAssetReference { impl CodeGenerateable for ImportAssetReference { #[turbo_tasks::function] async fn code_generation( - self_vc: ImportAssetReferenceVc, - _context: ChunkingContextVc, - ) -> Result { - let this = &*self_vc.await?; + self: Vc, + _context: Vc>, + ) -> Result> { + let this = &*self.await?; let mut imports = vec![]; if let Request::Uri { protocol, remainder, } = &*this.request.await? { - imports.push(CssImport::External(StringVc::cell(format!( + imports.push(CssImport::External(Vc::cell(format!( "{}{}", protocol, remainder )))) diff --git a/crates/turbopack-css/src/references/mod.rs b/crates/turbopack-css/src/references/mod.rs index 110817577619bc..8961227249eed4 100644 --- a/crates/turbopack-css/src/references/mod.rs +++ b/crates/turbopack-css/src/references/mod.rs @@ -10,17 +10,17 @@ use swc_core::{ visit::{AstNodePath, AstParentKind, VisitAstPath, VisitWithPath}, }, }; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ - asset::AssetVc, - issue::{IssueSeverity, IssueSourceVc, OptionIssueSourceVc}, - reference::{AssetReferenceVc, AssetReferencesVc}, + asset::Asset, + issue::{IssueSeverity, IssueSource, OptionIssueSource}, + reference::{AssetReference, AssetReferences}, reference_type::{CssReferenceSubType, ReferenceType}, resolve::{ handle_resolve_error, - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - ResolveResultVc, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + ResolveResult, }, }; use turbopack_swc_utils::emitter::IssueEmitter; @@ -28,10 +28,10 @@ use turbopack_swc_utils::emitter::IssueEmitter; use crate::{ parse::{parse, ParseResult}, references::{ - import::{ImportAssetReferenceVc, ImportAttributes}, - url::UrlAssetReferenceVc, + import::{ImportAssetReference, ImportAttributes}, + url::UrlAssetReference, }, - CssInputTransformsVc, CssModuleAssetType, + CssInputTransforms, CssModuleAssetType, }; pub(crate) mod compose; @@ -40,11 +40,11 @@ pub(crate) mod url; #[turbo_tasks::function] pub async fn analyze_css_stylesheet( - source: AssetVc, - origin: ResolveOriginVc, + source: Vc>, + origin: Vc>, ty: Value, - transforms: CssInputTransformsVc, -) -> Result { + transforms: Vc, +) -> Result> { let mut references = Vec::new(); let parsed = parse(source, ty, transforms).await?; @@ -73,21 +73,21 @@ pub async fn analyze_css_stylesheet( }) }); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } struct AssetReferencesVisitor<'a> { - source: AssetVc, - origin: ResolveOriginVc, - references: &'a mut Vec, + source: Vc>, + origin: Vc>, + references: &'a mut Vec>>, is_import: bool, } impl<'a> AssetReferencesVisitor<'a> { fn new( - source: AssetVc, - origin: ResolveOriginVc, - references: &'a mut Vec, + source: Vc>, + origin: Vc>, + references: &'a mut Vec>>, ) -> Self { Self { source, @@ -127,20 +127,17 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { let issue_span = i.href.span(); - self.references.push( - ImportAssetReferenceVc::new( - self.origin, - RequestVc::parse(Value::new(src.to_string().into())), - AstPathVc::cell(as_parent_path(ast_path)), - ImportAttributes::new_from_prelude(i).into(), - IssueSourceVc::from_byte_offset( - self.source, - issue_span.lo.to_usize(), - issue_span.hi.to_usize(), - ), - ) - .into(), - ); + self.references.push(Vc::upcast(ImportAssetReference::new( + self.origin, + Request::parse(Value::new(src.to_string().into())), + Vc::cell(as_parent_path(ast_path)), + ImportAttributes::new_from_prelude(i).into(), + IssueSource::from_byte_offset( + self.source, + issue_span.lo.to_usize(), + issue_span.hi.to_usize(), + ), + ))); self.is_import = true; i.visit_children_with_path(self, ast_path); @@ -158,19 +155,16 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { // ignore server-relative urls like `url(/foo)` if !matches!(src.bytes().next(), Some(b'#') | Some(b'/')) { let issue_span = u.span; - self.references.push( - UrlAssetReferenceVc::new( - self.origin, - RequestVc::parse(Value::new(src.to_string().into())), - AstPathVc::cell(as_parent_path(ast_path)), - IssueSourceVc::from_byte_offset( - self.source, - issue_span.lo.to_usize(), - issue_span.hi.to_usize(), - ), - ) - .into(), - ); + self.references.push(Vc::upcast(UrlAssetReference::new( + self.origin, + Request::parse(Value::new(src.to_string().into())), + Vc::cell(as_parent_path(ast_path)), + IssueSource::from_byte_offset( + self.source, + issue_span.lo.to_usize(), + issue_span.hi.to_usize(), + ), + ))); } u.visit_children_with_path(self, ast_path); @@ -179,11 +173,11 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { #[turbo_tasks::function] pub async fn css_resolve( - origin: ResolveOriginVc, - request: RequestVc, + origin: Vc>, + request: Vc, ty: Value, - issue_source: OptionIssueSourceVc, -) -> Result { + issue_source: Vc, +) -> Result> { let ty = Value::new(ReferenceType::Css(ty.into_value())); let options = origin.resolve_options(ty.clone()); let result = origin.resolve_asset(request, options, ty.clone()); diff --git a/crates/turbopack-css/src/references/url.rs b/crates/turbopack-css/src/references/url.rs index 185fe24f63e6db..56d293e3d206ef 100644 --- a/crates/turbopack-css/src/references/url.rs +++ b/crates/turbopack-css/src/references/url.rs @@ -3,53 +3,49 @@ use swc_core::{ common::DUMMY_SP, css::ast::{Str, UrlValue}, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{ChunkingContext, ChunkingContextVc}, - ident::AssetIdentVc, - issue::{IssueSeverity, IssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, + asset::Asset, + chunk::ChunkingContext, + ident::AssetIdent, + issue::{IssueSeverity, IssueSource}, + reference::AssetReference, reference_type::UrlReferenceSubType, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - PrimaryResolveResult, ResolveResultVc, - }, + resolve::{origin::ResolveOrigin, parse::Request, PrimaryResolveResult, ResolveResult}, }; use turbopack_ecmascript::resolve::url_resolve; use crate::{ - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, - embed::{CssEmbed, CssEmbeddable, CssEmbeddableVc}, - references::AstPathVc, + embed::{CssEmbed, CssEmbeddable}, + references::AstPath, }; #[turbo_tasks::value(into = "new")] pub enum ReferencedAsset { - Some(AssetVc), + Some(Vc>), None, } #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct UrlAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub path: AstPathVc, - pub issue_source: IssueSourceVc, + pub origin: Vc>, + pub request: Vc, + pub path: Vc, + pub issue_source: Vc, } #[turbo_tasks::value_impl] -impl UrlAssetReferenceVc { +impl UrlAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - path: AstPathVc, - issue_source: IssueSourceVc, - ) -> Self { + origin: Vc>, + request: Vc, + path: Vc, + issue_source: Vc, + ) -> Vc { Self::cell(UrlAssetReference { origin, request, @@ -59,10 +55,15 @@ impl UrlAssetReferenceVc { } #[turbo_tasks::function] - async fn get_referenced_asset(self, context: ChunkingContextVc) -> Result { + async fn get_referenced_asset( + self: Vc, + context: Vc>, + ) -> Result> { for result in self.resolve_reference().await?.primary.iter() { if let PrimaryResolveResult::Asset(asset) = result { - if let Some(embeddable) = CssEmbeddableVc::resolve_from(asset).await? { + if let Some(embeddable) = + Vc::try_resolve_sidecast::>(*asset).await? + { return Ok(ReferencedAsset::Some( embeddable.as_css_embed(context).embeddable_asset(), ) @@ -70,14 +71,14 @@ impl UrlAssetReferenceVc { } } } - Ok(ReferencedAssetVc::cell(ReferencedAsset::None)) + Ok(ReferencedAsset::cell(ReferencedAsset::None)) } } #[turbo_tasks::value_impl] impl AssetReference for UrlAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { url_resolve( self.origin, self.request, @@ -91,11 +92,10 @@ impl AssetReference for UrlAssetReference { #[turbo_tasks::value_impl] impl ValueToString for UrlAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( - "url {}", - self.request.to_string().await?, - ))) + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!("url {}", self.request.to_string().await?,), + )) } } @@ -103,19 +103,21 @@ impl ValueToString for UrlAssetReference { impl CodeGenerateable for UrlAssetReference { #[turbo_tasks::function] async fn code_generation( - self_vc: UrlAssetReferenceVc, - context: ChunkingContextVc, - ) -> Result { - let this = self_vc.await?; + self: Vc, + context: Vc>, + ) -> Result> { + let this = self.await?; // TODO(WEB-662) This is not the correct way to get the current chunk path. It // currently works as all chunks are in the same directory. - let chunk_path = - context.chunk_path(AssetIdentVc::from_path(this.origin.origin_path()), ".css"); + let chunk_path = context.chunk_path( + AssetIdent::from_path(this.origin.origin_path()), + ".css".to_string(), + ); let context_path = chunk_path.parent().await?; let mut visitors = Vec::new(); - if let ReferencedAsset::Some(asset) = &*self_vc.get_referenced_asset(context).await? { + if let ReferencedAsset::Some(asset) = &*self.get_referenced_asset(context).await? { // TODO(WEB-662) This is not the correct way to get the path of the asset. // `asset` is on module-level, but we need the output-level asset instead. let path = asset.ident().path().await?; diff --git a/crates/turbopack-dev-server/src/html.rs b/crates/turbopack-dev-server/src/html.rs index bc49af84a072d9..fb9856aa15a1e3 100644 --- a/crates/turbopack-dev-server/src/html.rs +++ b/crates/turbopack-dev-server/src/html.rs @@ -1,79 +1,73 @@ use anyhow::{anyhow, Result}; use mime_guess::mime::TEXT_HTML_UTF_8; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt}; -use turbo_tasks_fs::{File, FileSystemPathVc}; +use turbo_tasks::{ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::{File, FileSystemPath}; use turbo_tasks_hash::{encode_hex, Xxh3Hash64Hasher}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ - ChunkableAsset, ChunkableAssetVc, ChunkingContext, ChunkingContextVc, EvaluatableAssetsVc, - }, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, - version::{Version, VersionVc, VersionedContent, VersionedContentVc}, + asset::{Asset, AssetContent, Assets}, + chunk::{ChunkableAsset, ChunkingContext, EvaluatableAssets}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, + version::{Version, VersionedContent}, }; +// TODO(WEB-945) This should become a struct once we have a +// `turbo_tasks::input` attribute macro/`Input` derive macro. +type DevHtmlEntry = ( + Vc>, + Vc>, + Option>, +); + /// The HTML entry point of the dev server. /// /// Generates an HTML page that includes the ES and CSS chunks. #[turbo_tasks::value(shared)] #[derive(Clone)] pub struct DevHtmlAsset { - path: FileSystemPathVc, - // TODO(WEB-945) This should become a `Vec` once we have a - // `turbo_tasks::input` attribute macro/`Input` derive macro. - entries: Vec<( - ChunkableAssetVc, - ChunkingContextVc, - Option, - )>, + path: Vc, + entries: Vec, body: Option, } #[turbo_tasks::function] -fn dev_html_chunk_reference_description() -> StringVc { - StringVc::cell("dev html chunk".to_string()) +fn dev_html_chunk_reference_description() -> Vc { + Vc::cell("dev html chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for DevHtmlAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - AssetIdentVc::from_path(self.path) + fn ident(&self) -> Vc { + AssetIdent::from_path(self.path) } #[turbo_tasks::function] - fn content(self_vc: DevHtmlAssetVc) -> AssetContentVc { - self_vc.html_content().content() + fn content(self: Vc) -> Vc { + self.html_content().content() } #[turbo_tasks::function] - async fn references(self_vc: DevHtmlAssetVc) -> Result { + async fn references(self: Vc) -> Result> { let mut references = Vec::new(); - for chunk in &*self_vc.chunks().await? { - references.push( - SingleAssetReferenceVc::new(*chunk, dev_html_chunk_reference_description()).into(), - ); + for chunk in &*self.chunks().await? { + references.push(Vc::upcast(SingleAssetReference::new( + *chunk, + dev_html_chunk_reference_description(), + ))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } #[turbo_tasks::function] - fn versioned_content(self_vc: DevHtmlAssetVc) -> VersionedContentVc { - self_vc.html_content().into() + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.html_content()) } } -impl DevHtmlAssetVc { +impl DevHtmlAsset { /// Create a new dev HTML asset. - pub fn new( - path: FileSystemPathVc, - entries: Vec<( - ChunkableAssetVc, - ChunkingContextVc, - Option, - )>, - ) -> Self { + pub fn new(path: Vc, entries: Vec) -> Vc { DevHtmlAsset { path, entries, @@ -84,14 +78,10 @@ impl DevHtmlAssetVc { /// Create a new dev HTML asset. pub fn new_with_body( - path: FileSystemPathVc, - entries: Vec<( - ChunkableAssetVc, - ChunkingContextVc, - Option, - )>, + path: Vc, + entries: Vec, body: String, - ) -> Self { + ) -> Vc { DevHtmlAsset { path, entries, @@ -102,16 +92,16 @@ impl DevHtmlAssetVc { } #[turbo_tasks::value_impl] -impl DevHtmlAssetVc { +impl DevHtmlAsset { #[turbo_tasks::function] - pub async fn with_path(self, path: FileSystemPathVc) -> Result { + pub async fn with_path(self: Vc, path: Vc) -> Result> { let mut html: DevHtmlAsset = self.await?.clone_value(); html.path = path; Ok(html.cell()) } #[turbo_tasks::function] - pub async fn with_body(self, body: String) -> Result { + pub async fn with_body(self: Vc, body: String) -> Result> { let mut html: DevHtmlAsset = self.await?.clone_value(); html.body = Some(body); Ok(html.cell()) @@ -119,9 +109,9 @@ impl DevHtmlAssetVc { } #[turbo_tasks::value_impl] -impl DevHtmlAssetVc { +impl DevHtmlAsset { #[turbo_tasks::function] - async fn html_content(self) -> Result { + async fn html_content(self: Vc) -> Result> { let this = self.await?; let context_path = this.path.parent().await?; @@ -133,11 +123,11 @@ impl DevHtmlAssetVc { } } - Ok(DevHtmlAssetContentVc::new(chunk_paths, this.body.clone())) + Ok(DevHtmlAssetContent::new(chunk_paths, this.body.clone())) } #[turbo_tasks::function] - async fn chunks(self) -> Result { + async fn chunks(self: Vc) -> Result> { let this = self.await?; let all_assets = this @@ -162,7 +152,7 @@ impl DevHtmlAssetVc { .copied() .collect(); - Ok(AssetsVc::cell(all_assets)) + Ok(Vc::cell(all_assets)) } } @@ -172,16 +162,16 @@ struct DevHtmlAssetContent { body: Option, } -impl DevHtmlAssetContentVc { - pub fn new(chunk_paths: Vec, body: Option) -> Self { +impl DevHtmlAssetContent { + pub fn new(chunk_paths: Vec, body: Option) -> Vc { DevHtmlAssetContent { chunk_paths, body }.cell() } } #[turbo_tasks::value_impl] -impl DevHtmlAssetContentVc { +impl DevHtmlAssetContent { #[turbo_tasks::function] - async fn content(self) -> Result { + async fn content(self: Vc) -> Result> { let this = self.await?; let mut scripts = Vec::new(); @@ -212,11 +202,13 @@ impl DevHtmlAssetContentVc { scripts.join("\n"), ); - Ok(File::from(html).with_content_type(TEXT_HTML_UTF_8).into()) + Ok(AssetContent::file( + File::from(html).with_content_type(TEXT_HTML_UTF_8).into(), + )) } #[turbo_tasks::function] - async fn version(self) -> Result { + async fn version(self: Vc) -> Result> { let this = self.await?; Ok(DevHtmlAssetVersion { content: this }.cell()) } @@ -225,25 +217,25 @@ impl DevHtmlAssetContentVc { #[turbo_tasks::value_impl] impl VersionedContent for DevHtmlAssetContent { #[turbo_tasks::function] - fn content(self_vc: DevHtmlAssetContentVc) -> AssetContentVc { - self_vc.content() + fn content(self: Vc) -> Vc { + self.content() } #[turbo_tasks::function] - fn version(self_vc: DevHtmlAssetContentVc) -> VersionVc { - self_vc.version().into() + fn version(self: Vc) -> Vc> { + Vc::upcast(self.version()) } } #[turbo_tasks::value] struct DevHtmlAssetVersion { - content: DevHtmlAssetContentReadRef, + content: ReadRef, } #[turbo_tasks::value_impl] impl Version for DevHtmlAssetVersion { #[turbo_tasks::function] - async fn id(&self) -> Result { + async fn id(&self) -> Result> { let mut hasher = Xxh3Hash64Hasher::new(); for relative_path in &*self.content.chunk_paths { hasher.write_ref(relative_path); @@ -253,6 +245,6 @@ impl Version for DevHtmlAssetVersion { } let hash = hasher.finish(); let hex_hash = encode_hex(hash); - Ok(StringVc::cell(hex_hash)) + Ok(Vc::cell(hex_hash)) } } diff --git a/crates/turbopack-dev-server/src/http.rs b/crates/turbopack-dev-server/src/http.rs index 5635b564995ad8..607c642748ae0e 100644 --- a/crates/turbopack-dev-server/src/http.rs +++ b/crates/turbopack-dev-server/src/http.rs @@ -10,29 +10,29 @@ use hyper::{ use mime::Mime; use mime_guess::mime; use tokio_util::io::{ReaderStream, StreamReader}; -use turbo_tasks::{util::SharedError, TransientInstance}; +use turbo_tasks::{util::SharedError, ReadRef, TransientInstance, Vc}; use turbo_tasks_bytes::Bytes; -use turbo_tasks_fs::{FileContent, FileContentReadRef}; -use turbopack_core::{asset::AssetContent, issue::IssueReporterVc, version::VersionedContent}; +use turbo_tasks_fs::FileContent; +use turbopack_core::{asset::AssetContent, issue::IssueReporter, version::VersionedContent}; use crate::{ handle_issues, source::{ request::SourceRequest, resolve::{resolve_source_request, ResolveSourceRequestResult}, - Body, ContentSourceVc, HeaderListReadRef, ProxyResultReadRef, + Body, ContentSource, HeaderList, ProxyResult, }, }; #[turbo_tasks::value(serialization = "none")] enum GetFromSourceResult { Static { - content: FileContentReadRef, + content: ReadRef, status_code: u16, - headers: HeaderListReadRef, - header_overwrites: HeaderListReadRef, + headers: ReadRef, + header_overwrites: ReadRef, }, - HttpProxy(ProxyResultReadRef), + HttpProxy(ReadRef), NotFound, } @@ -40,9 +40,9 @@ enum GetFromSourceResult { /// corresponding content as a #[turbo_tasks::function] async fn get_from_source( - source: ContentSourceVc, + source: Vc>, request: TransientInstance, -) -> Result { +) -> Result> { Ok(match &*resolve_source_request(source, request).await? { ResolveSourceRequestResult::Static(static_content_vc, header_overwrites) => { let static_content = static_content_vc.await?; @@ -68,9 +68,9 @@ async fn get_from_source( /// Processes an HTTP request within a given content source and returns the /// response. pub async fn process_request_with_content_source( - source: ContentSourceVc, + source: Vc>, request: Request, - issue_reporter: IssueReporterVc, + issue_reporter: Vc>, ) -> Result> { let original_path = request.uri().path().to_string(); let request = http_request_to_source_request(request).await?; diff --git a/crates/turbopack-dev-server/src/introspect/mod.rs b/crates/turbopack-dev-server/src/introspect/mod.rs index e9f52ee25d0894..603d0c59a88a6a 100644 --- a/crates/turbopack-dev-server/src/introspect/mod.rs +++ b/crates/turbopack-dev-server/src/introspect/mod.rs @@ -1,43 +1,38 @@ use std::{borrow::Cow, collections::HashSet, fmt::Display}; use anyhow::Result; -use turbo_tasks::{ - primitives::{StringReadRef, StringVc}, - registry, CellId, RawVc, TryJoinIterExt, -}; -use turbo_tasks_fs::{json::parse_json_with_source_context, File, FileContent}; +use turbo_tasks::{registry, CellId, RawVc, ReadRef, TryJoinIterExt, Vc}; +use turbo_tasks_fs::{json::parse_json_with_source_context, File}; use turbopack_core::{ asset::AssetContent, - introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}, + introspect::{Introspectable, IntrospectableChildren}, + version::VersionedContentExt, }; use turbopack_ecmascript::utils::FormatIter; -use crate::source::{ - ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceResultVc, - ContentSourceVc, -}; +use crate::source::{ContentSource, ContentSourceContent, ContentSourceData, ContentSourceResult}; #[turbo_tasks::value(shared)] pub struct IntrospectionSource { - pub roots: HashSet, + pub roots: HashSet>>, } #[turbo_tasks::value_impl] impl Introspectable for IntrospectionSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("introspection-source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("introspection-source".to_string()) } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("introspection-source".to_string()) + fn title(&self) -> Vc { + Vc::cell("introspection-source".to_string()) } #[turbo_tasks::function] - fn children(&self) -> IntrospectableChildrenVc { - let name = StringVc::cell("root".to_string()); - IntrospectableChildrenVc::cell(self.roots.iter().map(|root| (name, *root)).collect()) + fn children(&self) -> Vc { + let name = Vc::cell("root".to_string()); + Vc::cell(self.roots.iter().map(|root| (name, *root)).collect()) } } @@ -78,30 +73,30 @@ impl Display for HtmlStringEscaped { impl ContentSource for IntrospectionSource { #[turbo_tasks::function] async fn get( - self_vc: IntrospectionSourceVc, - path: &str, + self: Vc, + path: String, _data: turbo_tasks::Value, - ) -> Result { + ) -> Result> { let introspectable = if path.is_empty() { - let roots = &self_vc.await?.roots; + let roots = &self.await?.roots; if roots.len() == 1 { *roots.iter().next().unwrap() } else { - self_vc.as_introspectable() + Vc::upcast(self) } } else { - parse_json_with_source_context(path)? + parse_json_with_source_context(path.as_str())? } .resolve() .await?; - let raw_vc: RawVc = introspectable.into(); + let raw_vc: RawVc = introspectable.node; let internal_ty = if let RawVc::TaskCell(_, CellId { type_id, index }) = raw_vc { let value_ty = registry::get_value_type(type_id); format!("{}#{}", value_ty.name, index) } else { unreachable!() }; - fn str_or_err(s: &Result) -> Cow<'_, str> { + fn str_or_err(s: &Result>) -> Cow<'_, str> { s.as_ref().map_or_else( |e| Cow::<'_, str>::Owned(format!("ERROR: {:?}", e)), |d| Cow::Borrowed(&**d), @@ -164,16 +159,15 @@ impl ContentSource for IntrospectionSource { ty = HtmlEscaped(ty), children = FormatIter(|| children.iter()) ); - Ok(ContentSourceResultVc::exact( - ContentSourceContentVc::static_content( - AssetContent::File( - FileContent::Content(File::from(html).with_content_type(mime::TEXT_HTML_UTF_8)) - .cell(), + Ok(ContentSourceResult::exact(Vc::upcast( + ContentSourceContent::static_content( + AssetContent::file( + File::from(html) + .with_content_type(mime::TEXT_HTML_UTF_8) + .into(), ) - .cell() - .into(), - ) - .into(), - )) + .versioned(), + ), + ))) } } diff --git a/crates/turbopack-dev-server/src/lib.rs b/crates/turbopack-dev-server/src/lib.rs index 4247828a902f0f..1d2a8bcca50cb8 100644 --- a/crates/turbopack-dev-server/src/lib.rs +++ b/crates/turbopack-dev-server/src/lib.rs @@ -2,6 +2,8 @@ #![feature(trait_alias)] #![feature(array_chunks)] #![feature(iter_intersperse)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub mod html; mod http; @@ -27,34 +29,34 @@ use hyper::{ use socket2::{Domain, Protocol, Socket, Type}; use tracing::{event, info_span, Instrument, Level, Span}; use turbo_tasks::{ - run_once_with_reason, trace::TraceRawVcs, util::FormatDuration, CollectiblesSource, RawVc, - TransientInstance, TransientValue, TurboTasksApi, + run_once_with_reason, trace::TraceRawVcs, util::FormatDuration, TransientInstance, + TransientValue, TurboTasksApi, Vc, }; use turbopack_core::{ error::PrettyPrintError, - issue::{IssueReporter, IssueReporterVc, IssueVc}, + issue::{IssueContextExt, IssueReporter}, }; use self::{ - source::{ContentSourceResultVc, ContentSourceVc}, + source::{ContentSource, ContentSourceResult}, update::UpdateServer, }; use crate::invalidation::ServerRequest; pub trait SourceProvider: Send + Clone + 'static { /// must call a turbo-tasks function internally - fn get_source(&self) -> ContentSourceVc; + fn get_source(&self) -> Vc>; } pub trait ContentProvider: Send + Clone + 'static { - fn get_content(&self) -> ContentSourceResultVc; + fn get_content(&self) -> Vc; } impl SourceProvider for T where - T: Fn() -> ContentSourceVc + Send + Clone + 'static, + T: Fn() -> Vc> + Send + Clone + 'static, { - fn get_source(&self) -> ContentSourceVc { + fn get_source(&self) -> Vc> { self() } } @@ -75,20 +77,21 @@ pub struct DevServer { pub future: Pin> + Send + 'static>>, } -async fn handle_issues + CollectiblesSource + Copy>( - source: T, +async fn handle_issues( + source: Vc, path: &str, operation: &str, - issue_reporter: IssueReporterVc, + issue_reporter: Vc>, ) -> Result<()> { - let issues = IssueVc::peek_issues_with_path(source) + let issues = source + .peek_issues_with_path() .await? .strongly_consistent() .await?; let has_fatal = issue_reporter.report_issues( TransientInstance::new(issues.clone()), - TransientValue::new(source.into()), + TransientValue::new(source.node), ); if *has_fatal.await? { @@ -138,7 +141,7 @@ impl DevServerBuilder { self, turbo_tasks: Arc, source_provider: impl SourceProvider + Clone + Send + Sync, - get_issue_reporter: Arc IssueReporterVc + Send + Sync>, + get_issue_reporter: Arc Vc> + Send + Sync>, ) -> DevServer { let make_svc = make_service_fn(move |_| { let tt = turbo_tasks.clone(); diff --git a/crates/turbopack-dev-server/src/source/asset_graph.rs b/crates/turbopack-dev-server/src/source/asset_graph.rs index bd5bd82d3ecb53..838065a1ecd17c 100644 --- a/crates/turbopack-dev-server/src/source/asset_graph.rs +++ b/crates/turbopack-dev-server/src/source/asset_graph.rs @@ -5,39 +5,36 @@ use std::{ use anyhow::Result; use indexmap::{indexset, IndexSet}; -use turbo_tasks::{primitives::StringVc, State, Value, ValueToString}; -use turbo_tasks_fs::{FileSystemPath, FileSystemPathVc}; +use turbo_tasks::{State, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetVc, AssetsSetVc}, - introspect::{ - asset::IntrospectableAssetVc, Introspectable, IntrospectableChildrenVc, IntrospectableVc, - }, + asset::{Asset, AssetsSet}, + introspect::{asset::IntrospectableAsset, Introspectable, IntrospectableChildren}, reference::all_referenced_assets, }; -use super::{ - ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceResultVc, - ContentSourceVc, -}; +use super::{ContentSource, ContentSourceContent, ContentSourceData, ContentSourceResult}; #[turbo_tasks::value(transparent)] -struct AssetsMap(HashMap); +struct AssetsMap(HashMap>>); + +type ExpandedState = State>>>; #[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] pub struct AssetGraphContentSource { - root_path: FileSystemPathVc, - root_assets: AssetsSetVc, - expanded: Option>>, + root_path: Vc, + root_assets: Vc, + expanded: Option, } #[turbo_tasks::value_impl] -impl AssetGraphContentSourceVc { +impl AssetGraphContentSource { /// Serves all assets references by root_asset. #[turbo_tasks::function] - pub fn new_eager(root_path: FileSystemPathVc, root_asset: AssetVc) -> Self { + pub fn new_eager(root_path: Vc, root_asset: Vc>) -> Vc { Self::cell(AssetGraphContentSource { root_path, - root_assets: AssetsSetVc::cell(indexset! { root_asset }), + root_assets: Vc::cell(indexset! { root_asset }), expanded: None, }) } @@ -45,17 +42,20 @@ impl AssetGraphContentSourceVc { /// Serves all assets references by root_asset. Only serve references of an /// asset when it has served its content before. #[turbo_tasks::function] - pub fn new_lazy(root_path: FileSystemPathVc, root_asset: AssetVc) -> Self { + pub fn new_lazy(root_path: Vc, root_asset: Vc>) -> Vc { Self::cell(AssetGraphContentSource { root_path, - root_assets: AssetsSetVc::cell(indexset! { root_asset }), + root_assets: Vc::cell(indexset! { root_asset }), expanded: Some(State::new(HashSet::new())), }) } /// Serves all assets references by all root_assets. #[turbo_tasks::function] - pub fn new_eager_multiple(root_path: FileSystemPathVc, root_assets: AssetsSetVc) -> Self { + pub fn new_eager_multiple( + root_path: Vc, + root_assets: Vc, + ) -> Vc { Self::cell(AssetGraphContentSource { root_path, root_assets, @@ -66,7 +66,10 @@ impl AssetGraphContentSourceVc { /// Serves all assets references by all root_assets. Only serve references /// of an asset when it has served its content before. #[turbo_tasks::function] - pub fn new_lazy_multiple(root_path: FileSystemPathVc, root_assets: AssetsSetVc) -> Self { + pub fn new_lazy_multiple( + root_path: Vc, + root_assets: Vc, + ) -> Vc { Self::cell(AssetGraphContentSource { root_path, root_assets, @@ -75,9 +78,9 @@ impl AssetGraphContentSourceVc { } #[turbo_tasks::function] - async fn all_assets_map(self) -> Result { + async fn all_assets_map(self: Vc) -> Result> { let this = self.await?; - Ok(AssetsMapVc::cell( + Ok(Vc::cell( expand( &*this.root_assets.await?, &*this.root_path.await?, @@ -89,10 +92,10 @@ impl AssetGraphContentSourceVc { } async fn expand( - root_assets: &IndexSet, + root_assets: &IndexSet>>, root_path: &FileSystemPath, - expanded: Option<&State>>, -) -> Result> { + expanded: Option<&ExpandedState>, +) -> Result>>> { let mut map = HashMap::new(); let mut assets = Vec::new(); let mut queue = VecDeque::with_capacity(32); @@ -152,95 +155,95 @@ async fn expand( impl ContentSource for AssetGraphContentSource { #[turbo_tasks::function] async fn get( - self_vc: AssetGraphContentSourceVc, - path: &str, + self: Vc, + path: String, _data: Value, - ) -> Result { - let assets = self_vc.all_assets_map().strongly_consistent().await?; + ) -> Result> { + let assets = self.all_assets_map().strongly_consistent().await?; - if let Some(asset) = assets.get(path) { + if let Some(asset) = assets.get(&path) { { - let this = self_vc.await?; + let this = self.await?; if let Some(expanded) = &this.expanded { expanded.update_conditionally(|expanded| expanded.insert(*asset)); } } - return Ok(ContentSourceResultVc::exact( - ContentSourceContentVc::static_content(asset.versioned_content()).into(), - )); + return Ok(ContentSourceResult::exact(Vc::upcast( + ContentSourceContent::static_content(asset.versioned_content()), + ))); } - Ok(ContentSourceResultVc::not_found()) + Ok(ContentSourceResult::not_found()) } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("asset graph content source".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("asset graph content source".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for AssetGraphContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { self.root_path.to_string() } #[turbo_tasks::function] - async fn children(self_vc: AssetGraphContentSourceVc) -> Result { - let this = self_vc.await?; - let key = StringVc::cell("root".to_string()); - let expanded_key = StringVc::cell("expanded".to_string()); + async fn children(self: Vc) -> Result> { + let this = self.await?; + let key = Vc::cell("root".to_string()); + let expanded_key = Vc::cell("expanded".to_string()); let root_assets = this.root_assets.await?; let root_assets = root_assets .iter() - .map(|&asset| (key, IntrospectableAssetVc::new(asset))); + .map(|&asset| (key, IntrospectableAsset::new(asset))); - Ok(IntrospectableChildrenVc::cell( + Ok(Vc::cell( root_assets - .chain(once((expanded_key, FullyExpaned(self_vc).cell().into()))) + .chain(once((expanded_key, Vc::upcast(FullyExpaned(self).cell())))) .collect(), )) } } #[turbo_tasks::function] -fn fully_expaned_introspectable_type() -> StringVc { - StringVc::cell("fully expanded asset graph content source".to_string()) +fn fully_expaned_introspectable_type() -> Vc { + Vc::cell("fully expanded asset graph content source".to_string()) } #[turbo_tasks::value] -struct FullyExpaned(AssetGraphContentSourceVc); +struct FullyExpaned(Vc); #[turbo_tasks::value_impl] impl Introspectable for FullyExpaned { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { fully_expaned_introspectable_type() } #[turbo_tasks::function] - async fn title(&self) -> Result { + async fn title(&self) -> Result> { Ok(self.0.await?.root_path.to_string()) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let source = self.0.await?; - let key = StringVc::cell("asset".to_string()); + let key = Vc::cell("asset".to_string()); let expanded_assets = expand(&*source.root_assets.await?, &*source.root_path.await?, None).await?; let children = expanded_assets .iter() - .map(|(_k, &v)| (key, IntrospectableAssetVc::new(v))) + .map(|(_k, &v)| (key, IntrospectableAsset::new(v))) .collect(); - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-dev-server/src/source/combined.rs b/crates/turbopack-dev-server/src/source/combined.rs index 801e02cb5ed772..33dbe38ec02a01 100644 --- a/crates/turbopack-dev-server/src/source/combined.rs +++ b/crates/turbopack-dev-server/src/source/combined.rs @@ -1,21 +1,20 @@ use std::mem; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value}; -use turbopack_core::introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}; +use turbo_tasks::{ReadRef, TryJoinIterExt, Value, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; use super::{ - specificity::SpecificityReadRef, ContentSource, ContentSourceData, ContentSourceResult, - ContentSourceResultVc, ContentSourceVc, NeededData, + specificity::Specificity, ContentSource, ContentSourceData, ContentSourceResult, NeededData, }; -use crate::source::ContentSourcesVc; +use crate::source::ContentSources; /// Combines multiple [ContentSource]s by trying all content sources in order. /// The content source which responds with the most specific response (that is /// not a [ContentSourceContent::NotFound]) will be returned. #[turbo_tasks::value(shared)] pub struct CombinedContentSource { - pub sources: Vec, + pub sources: Vec>>, } /// A helper source which allows the [CombinedContentSource] to be paused while @@ -31,10 +30,10 @@ pub struct PausableCombinedContentSource { pending: Option, /// A [CombinedContentSource] which we are querying for content. - inner: CombinedContentSourceVc, + inner: Vc, /// The current most-specific content result. - max: Option<(SpecificityReadRef, ContentSourceResultVc)>, + max: Option<(ReadRef, Vc)>, } /// Stores partially computed data that an inner [ContentSource] returned when @@ -49,11 +48,11 @@ struct PendingState { /// A partially computed content source to receive the requested data. Note /// that this is not necessarily the same content source value that /// exists inside the [CombinedContentSource]'s sources vector. - source: ContentSourceVc, + source: Vc>, } -impl CombinedContentSourceVc { - pub fn new(sources: Vec) -> Self { +impl CombinedContentSource { + pub fn new(sources: Vec>>) -> Vc { CombinedContentSource { sources }.cell() } } @@ -62,22 +61,22 @@ impl CombinedContentSourceVc { impl ContentSource for CombinedContentSource { #[turbo_tasks::function] async fn get( - self_vc: CombinedContentSourceVc, - path: &str, + self: Vc, + path: String, data: Value, - ) -> Result { - let pauseable = PausableCombinedContentSource::new(self_vc); - pauseable.pauseable_get(path, data).await + ) -> Result> { + let pauseable = PausableCombinedContentSource::new(self); + pauseable.pauseable_get(path.as_str(), data).await } #[turbo_tasks::function] - fn get_children(&self) -> ContentSourcesVc { - ContentSourcesVc::cell(self.sources.clone()) + fn get_children(&self) -> Vc { + Vc::cell(self.sources.clone()) } } impl PausableCombinedContentSource { - fn new(inner: CombinedContentSourceVc) -> Self { + fn new(inner: Vc) -> Self { PausableCombinedContentSource { inner, index: 0, @@ -92,7 +91,7 @@ impl PausableCombinedContentSource { &self, path: &str, mut data: Value, - ) -> Result { + ) -> Result> { let inner = self.inner; let mut max = self.max.clone(); let mut pending = self.pending.clone(); @@ -106,8 +105,11 @@ impl PausableCombinedContentSource { .source .resolve() .await? - .get(&pending.path, mem::take(&mut data)), - None => source.resolve().await?.get(path, Default::default()), + .get(pending.path, mem::take(&mut data)), + None => source + .resolve() + .await? + .get(path.to_string(), Default::default()), }; let res = result.await?; @@ -122,12 +124,12 @@ impl PausableCombinedContentSource { max, }; - return Ok(ContentSourceResultVc::need_data(Value::new(NeededData { + return Ok(ContentSourceResult::need_data(Value::new(NeededData { // We do not return data.path because that would affect later content source // requests. However, when we resume, we'll use the path stored in pending // to correctly requery this source. path: path.to_string(), - source: paused.cell().into(), + source: Vc::upcast(paused.cell()), vary: data.vary.clone(), }))); } @@ -153,7 +155,7 @@ impl PausableCombinedContentSource { if let Some((_, result)) = max { Ok(result) } else { - Ok(ContentSourceResultVc::not_found()) + Ok(ContentSourceResult::not_found()) } } } @@ -172,28 +174,30 @@ impl ContentSource for PausableCombinedContentSource { #[turbo_tasks::function] async fn get( &self, - path: &str, + path: String, data: Value, - ) -> Result { - self.pauseable_get(path, data).await + ) -> Result> { + self.pauseable_get(&path, data).await } } #[turbo_tasks::value_impl] impl Introspectable for CombinedContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("combined content source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("combined content source".to_string()) } #[turbo_tasks::function] - async fn title(&self) -> Result { + async fn title(&self) -> Result> { let titles = self .sources .iter() .map(|&source| async move { Ok( - if let Some(source) = IntrospectableVc::resolve_from(source).await? { + if let Some(source) = + Vc::try_resolve_sidecast::>(source).await? + { Some(source.title().await?) } else { None @@ -214,17 +218,19 @@ impl Introspectable for CombinedContentSource { if titles.len() > NUMBER_OF_TITLES_TO_DISPLAY { titles[NUMBER_OF_TITLES_TO_DISPLAY] = "..."; } - Ok(StringVc::cell(titles.join(", "))) + Ok(Vc::cell(titles.join(", "))) } #[turbo_tasks::function] - async fn children(&self) -> Result { - let source = StringVc::cell("source".to_string()); - Ok(IntrospectableChildrenVc::cell( + async fn children(&self) -> Result> { + let source = Vc::cell("source".to_string()); + Ok(Vc::cell( self.sources .iter() .copied() - .map(|s| async move { Ok(IntrospectableVc::resolve_from(s).await?) }) + .map(|s| async move { + Ok(Vc::try_resolve_sidecast::>(s).await?) + }) .try_join() .await? .into_iter() diff --git a/crates/turbopack-dev-server/src/source/conditional.rs b/crates/turbopack-dev-server/src/source/conditional.rs index a8226620da6009..2a16509a248584 100644 --- a/crates/turbopack-dev-server/src/source/conditional.rs +++ b/crates/turbopack-dev-server/src/source/conditional.rs @@ -1,13 +1,12 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, State, Value}; -use turbopack_core::introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}; +use turbo_tasks::{ReadRef, State, Value, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; use super::{ - combined::CombinedContentSource, ContentSource, ContentSourceData, ContentSourceDataVaryVc, - ContentSourceResult, ContentSourceResultVc, ContentSourceVc, GetContentSourceContent, - GetContentSourceContentVc, + combined::CombinedContentSource, ContentSource, ContentSourceData, ContentSourceDataVary, + ContentSourceResult, GetContentSourceContent, }; -use crate::source::{ContentSourceContentVc, ContentSourcesVc}; +use crate::source::{ContentSourceContent, ContentSources}; /// Combines two [ContentSource]s like the [CombinedContentSource], but only /// allows to serve from the second source when the first source has @@ -21,15 +20,18 @@ use crate::source::{ContentSourceContentVc, ContentSourcesVc}; /// served once. #[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] pub struct ConditionalContentSource { - activator: ContentSourceVc, - action: ContentSourceVc, + activator: Vc>, + action: Vc>, activated: State, } #[turbo_tasks::value_impl] -impl ConditionalContentSourceVc { +impl ConditionalContentSource { #[turbo_tasks::function] - pub fn new(activator: ContentSourceVc, action: ContentSourceVc) -> Self { + pub fn new( + activator: Vc>, + action: Vc>, + ) -> Vc { ConditionalContentSource { activator, action, @@ -43,11 +45,11 @@ impl ConditionalContentSourceVc { impl ContentSource for ConditionalContentSource { #[turbo_tasks::function] async fn get( - self_vc: ConditionalContentSourceVc, - path: &str, + self: Vc, + path: String, data: turbo_tasks::Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result> { + let this = self.await?; if !*this.activated.get() { let first = this.activator.get(path, data.clone()); let first_value = first.await?; @@ -56,12 +58,13 @@ impl ContentSource for ConditionalContentSource { get_content, specificity, } => ContentSourceResult::Result { - get_content: ActivateOnGetContentSource { - source: this, - get_content, - } - .cell() - .into(), + get_content: Vc::upcast( + ActivateOnGetContentSource { + source: this, + get_content, + } + .cell(), + ), specificity, } .cell(), @@ -76,50 +79,52 @@ impl ContentSource for ConditionalContentSource { } #[turbo_tasks::function] - fn get_children(&self) -> ContentSourcesVc { - ContentSourcesVc::cell(vec![self.activator, self.action]) + fn get_children(&self) -> Vc { + Vc::cell(vec![self.activator, self.action]) } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("conditional content source".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("conditional content source".to_string()) } #[turbo_tasks::function] -fn activator_key() -> StringVc { - StringVc::cell("activator".to_string()) +fn activator_key() -> Vc { + Vc::cell("activator".to_string()) } #[turbo_tasks::function] -fn action_key() -> StringVc { - StringVc::cell("action".to_string()) +fn action_key() -> Vc { + Vc::cell("action".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for ConditionalContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - async fn title(&self) -> Result { - if let Some(activator) = IntrospectableVc::resolve_from(self.activator).await? { + async fn title(&self) -> Result> { + if let Some(activator) = + Vc::try_resolve_sidecast::>(self.activator).await? + { Ok(activator.title()) } else { - Ok(StringVc::empty()) + Ok(Vc::::empty()) } } #[turbo_tasks::function] - async fn children(&self) -> Result { - Ok(IntrospectableChildrenVc::cell( + async fn children(&self) -> Result> { + Ok(Vc::cell( [ - IntrospectableVc::resolve_from(self.activator) + Vc::try_resolve_sidecast::>(self.activator) .await? .map(|i| (activator_key(), i)), - IntrospectableVc::resolve_from(self.action) + Vc::try_resolve_sidecast::>(self.action) .await? .map(|i| (action_key(), i)), ] @@ -132,19 +137,19 @@ impl Introspectable for ConditionalContentSource { #[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] struct ActivateOnGetContentSource { - source: ConditionalContentSourceReadRef, - get_content: GetContentSourceContentVc, + source: ReadRef, + get_content: Vc>, } #[turbo_tasks::value_impl] impl GetContentSourceContent for ActivateOnGetContentSource { #[turbo_tasks::function] - fn vary(&self) -> ContentSourceDataVaryVc { + fn vary(&self) -> Vc { self.get_content.vary() } #[turbo_tasks::function] - fn get(&self, data: Value) -> ContentSourceContentVc { + fn get(&self, data: Value) -> Vc { self.source.activated.set(true); self.get_content.get(data) } diff --git a/crates/turbopack-dev-server/src/source/issue_context.rs b/crates/turbopack-dev-server/src/source/issue_context.rs index 8e460ca2101322..02cd0303b22a83 100644 --- a/crates/turbopack-dev-server/src/source/issue_context.rs +++ b/crates/turbopack-dev-server/src/source/issue_context.rs @@ -1,45 +1,44 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}, + introspect::{Introspectable, IntrospectableChildren}, issue::IssueContextExt, }; use super::{ - ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceDataVaryVc, - ContentSourceResult, ContentSourceResultVc, ContentSourceVc, ContentSourcesVc, - GetContentSourceContent, GetContentSourceContentVc, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary, + ContentSourceResult, ContentSources, GetContentSourceContent, }; #[turbo_tasks::value] pub struct IssueContextContentSource { - context: Option, + context: Option>, description: String, - source: ContentSourceVc, + source: Vc>, } #[turbo_tasks::value_impl] -impl IssueContextContentSourceVc { +impl IssueContextContentSource { #[turbo_tasks::function] pub fn new_context( - context: FileSystemPathVc, - description: &str, - source: ContentSourceVc, - ) -> Self { + context: Vc, + description: String, + source: Vc>, + ) -> Vc { IssueContextContentSource { context: Some(context), - description: description.to_string(), + description, source, } .cell() } #[turbo_tasks::function] - pub fn new_description(description: &str, source: ContentSourceVc) -> Self { + pub fn new_description(description: String, source: Vc>) -> Vc { IssueContextContentSource { context: None, - description: description.to_string(), + description, source, } .cell() @@ -50,11 +49,11 @@ impl IssueContextContentSourceVc { impl ContentSource for IssueContextContentSource { #[turbo_tasks::function] async fn get( - self_vc: IssueContextContentSourceVc, - path: &str, + self: Vc, + path: String, data: Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result> { + let this = self.await?; let result = this .source .get(path, data) @@ -66,12 +65,13 @@ impl ContentSource for IssueContextContentSource { } = *result.await? { Ok(ContentSourceResult::Result { - get_content: IssueContextGetContentSourceContent { - get_content, - source: self_vc, - } - .cell() - .into(), + get_content: Vc::upcast( + IssueContextGetContentSourceContent { + get_content, + source: self, + } + .cell(), + ), specificity, } .cell()) @@ -81,21 +81,21 @@ impl ContentSource for IssueContextContentSource { } #[turbo_tasks::function] - fn get_children(&self) -> ContentSourcesVc { - ContentSourcesVc::cell(vec![self.source]) + fn get_children(&self) -> Vc { + Vc::cell(vec![self.source]) } } #[turbo_tasks::value] struct IssueContextGetContentSourceContent { - get_content: GetContentSourceContentVc, - source: IssueContextContentSourceVc, + get_content: Vc>, + source: Vc, } #[turbo_tasks::value_impl] impl GetContentSourceContent for IssueContextGetContentSourceContent { #[turbo_tasks::function] - async fn vary(&self) -> Result { + async fn vary(&self) -> Result> { let source = self.source.await?; let result = self .get_content @@ -106,7 +106,7 @@ impl GetContentSourceContent for IssueContextGetContentSourceContent { } #[turbo_tasks::function] - async fn get(&self, data: Value) -> Result { + async fn get(&self, data: Value) -> Result> { let source = self.source.await?; let result = self .get_content @@ -120,46 +120,54 @@ impl GetContentSourceContent for IssueContextGetContentSourceContent { #[turbo_tasks::value_impl] impl Introspectable for IssueContextContentSource { #[turbo_tasks::function] - async fn ty(&self) -> Result { + async fn ty(&self) -> Result> { Ok( - if let Some(source) = IntrospectableVc::resolve_from(self.source).await? { + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { source.ty() } else { - StringVc::cell("IssueContextContentSource".to_string()) + Vc::cell("IssueContextContentSource".to_string()) }, ) } #[turbo_tasks::function] - async fn title(&self) -> Result { + async fn title(&self) -> Result> { Ok( - if let Some(source) = IntrospectableVc::resolve_from(self.source).await? { + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { let title = source.title().await?; - StringVc::cell(format!("{}: {}", self.description, title)) + Vc::cell(format!("{}: {}", self.description, title)) } else { - StringVc::cell(self.description.clone()) + Vc::cell(self.description.clone()) }, ) } #[turbo_tasks::function] - async fn details(&self) -> Result { + async fn details(&self) -> Result> { Ok( - if let Some(source) = IntrospectableVc::resolve_from(self.source).await? { + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { source.details() } else { - StringVc::cell(String::new()) + Vc::cell(String::new()) }, ) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { Ok( - if let Some(source) = IntrospectableVc::resolve_from(self.source).await? { + if let Some(source) = + Vc::try_resolve_sidecast::>(self.source).await? + { source.children() } else { - IntrospectableChildrenVc::cell(Default::default()) + Vc::cell(Default::default()) }, ) } diff --git a/crates/turbopack-dev-server/src/source/lazy_instantiated.rs b/crates/turbopack-dev-server/src/source/lazy_instantiated.rs index 9132cedd426483..844fd8101afada 100644 --- a/crates/turbopack-dev-server/src/source/lazy_instantiated.rs +++ b/crates/turbopack-dev-server/src/source/lazy_instantiated.rs @@ -1,22 +1,22 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbopack_core::introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}; +use turbo_tasks::Vc; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; -use super::{ContentSource, ContentSourceData, ContentSourceResultVc, ContentSourceVc}; +use super::{ContentSource, ContentSourceData, ContentSourceResult}; /// A functor to get a [ContentSource]. Will be invoked when needed when using /// [LazyInstantiatedContentSource]. #[turbo_tasks::value_trait] pub trait GetContentSource { /// Returns the [ContentSource] - fn content_source(&self) -> ContentSourceVc; + fn content_source(self: Vc) -> Vc>; } /// Wraps the [ContentSource] creation in a way that only creates it when /// actually used. #[turbo_tasks::value(shared)] pub struct LazyInstantiatedContentSource { - pub get_source: GetContentSourceVc, + pub get_source: Vc>, } #[turbo_tasks::value_impl] @@ -24,37 +24,39 @@ impl ContentSource for LazyInstantiatedContentSource { #[turbo_tasks::function] fn get( &self, - path: &str, + path: String, data: turbo_tasks::Value, - ) -> ContentSourceResultVc { + ) -> Vc { self.get_source.content_source().get(path, data) } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("lazy instantiated content source".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("lazy instantiated content source".to_string()) } #[turbo_tasks::function] -fn source_key() -> StringVc { - StringVc::cell("source".to_string()) +fn source_key() -> Vc { + Vc::cell("source".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for LazyInstantiatedContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - async fn children(&self) -> Result { - Ok(IntrospectableChildrenVc::cell( + async fn children(&self) -> Result> { + Ok(Vc::cell( [ - IntrospectableVc::resolve_from(self.get_source.content_source()) - .await? - .map(|i| (source_key(), i)), + Vc::try_resolve_sidecast::>( + self.get_source.content_source(), + ) + .await? + .map(|i| (source_key(), i)), ] .into_iter() .flatten() diff --git a/crates/turbopack-dev-server/src/source/mod.rs b/crates/turbopack-dev-server/src/source/mod.rs index 1df9c935719d0d..51b018f1802f37 100644 --- a/crates/turbopack-dev-server/src/source/mod.rs +++ b/crates/turbopack-dev-server/src/source/mod.rs @@ -18,15 +18,15 @@ use std::collections::BTreeSet; use anyhow::Result; use futures::{stream::Stream as StreamTrait, TryStreamExt}; use serde::{Deserialize, Serialize}; -use turbo_tasks::{primitives::StringVc, trace::TraceRawVcs, util::SharedError, Value}; +use turbo_tasks::{trace::TraceRawVcs, util::SharedError, Upcast, Value, ValueDefault, Vc}; use turbo_tasks_bytes::{Bytes, Stream, StreamRead}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::FileSystemPath; use turbo_tasks_hash::{DeterministicHash, DeterministicHasher, Xxh3Hash64Hasher}; -use turbopack_core::version::{Version, VersionVc, VersionedContentVc}; +use turbopack_core::version::{Version, VersionedContent}; use self::{ - headers::Headers, issue_context::IssueContextContentSourceVc, query::Query, - specificity::SpecificityVc, + headers::Headers, issue_context::IssueContextContentSource, query::Query, + specificity::Specificity, }; /// The result of proxying a request to another HTTP server. @@ -43,7 +43,7 @@ pub struct ProxyResult { #[turbo_tasks::value_impl] impl Version for ProxyResult { #[turbo_tasks::function] - async fn id(&self) -> Result { + async fn id(&self) -> Result> { let mut hash = Xxh3Hash64Hasher::new(); hash.write_u16(self.status); for (name, value) in &self.headers { @@ -54,7 +54,7 @@ impl Version for ProxyResult { while let Some(chunk) = read.try_next().await? { hash.write_bytes(&chunk); } - Ok(StringVc::cell(hash.finish().to_string())) + Ok(Vc::cell(hash.finish().to_string())) } } @@ -66,8 +66,8 @@ pub enum ContentSourceResult { NotFound, NeedData(NeededData), Result { - specificity: SpecificityVc, - get_content: GetContentSourceContentVc, + specificity: Vc, + get_content: Vc>, }, } @@ -75,21 +75,21 @@ pub enum ContentSourceResult { impl ContentSource for ContentSourceResult { #[turbo_tasks::function] fn get( - self_vc: ContentSourceResultVc, - _path: &str, + self: Vc, + _path: String, _data: Value, - ) -> ContentSourceResultVc { - self_vc + ) -> Vc { + self } } #[turbo_tasks::value_impl] -impl ContentSourceResultVc { +impl ContentSourceResult { /// Wraps some content source content with exact match specificity. #[turbo_tasks::function] - pub fn exact(get_content: GetContentSourceContentVc) -> ContentSourceResultVc { + pub fn exact(get_content: Vc>) -> Vc { ContentSourceResult::Result { - specificity: SpecificityVc::exact(), + specificity: Specificity::exact(), get_content, } .cell() @@ -97,13 +97,13 @@ impl ContentSourceResultVc { /// Wraps some content source content with exact match specificity. #[turbo_tasks::function] - pub fn need_data(data: Value) -> ContentSourceResultVc { + pub fn need_data(data: Value) -> Vc { ContentSourceResult::NeedData(data.into_value()).cell() } /// Result when no match was found with the lowest specificity. #[turbo_tasks::function] - pub fn not_found() -> ContentSourceResultVc { + pub fn not_found() -> Vc { ContentSourceResult::NotFound.cell() } } @@ -113,19 +113,19 @@ impl ContentSourceResultVc { pub trait GetContentSourceContent { /// Specifies data requirements for the get function. Restricting data /// passed allows to cache the get method. - fn vary(&self) -> ContentSourceDataVaryVc { + fn vary(self: Vc) -> Vc { ContentSourceDataVary::default().cell() } /// Get the content - fn get(&self, data: Value) -> ContentSourceContentVc; + fn get(self: Vc, data: Value) -> Vc; } #[turbo_tasks::value] pub struct StaticContent { - pub content: VersionedContentVc, + pub content: Vc>, pub status_code: u16, - pub headers: HeaderListVc, + pub headers: Vc, } #[turbo_tasks::value(shared)] @@ -133,31 +133,28 @@ pub struct StaticContent { /// The content of a result that is returned by a content source. pub enum ContentSourceContent { NotFound, - Static(StaticContentVc), - HttpProxy(ProxyResultVc), - Rewrite(RewriteVc), + Static(Vc), + HttpProxy(Vc), + Rewrite(Vc), } #[turbo_tasks::value_impl] impl GetContentSourceContent for ContentSourceContent { #[turbo_tasks::function] - fn get( - self_vc: ContentSourceContentVc, - _data: Value, - ) -> ContentSourceContentVc { - self_vc + fn get(self: Vc, _data: Value) -> Vc { + self } } #[turbo_tasks::value_impl] -impl ContentSourceContentVc { +impl ContentSourceContent { #[turbo_tasks::function] - pub fn static_content(content: VersionedContentVc) -> ContentSourceContentVc { + pub fn static_content(content: Vc>) -> Vc { ContentSourceContent::Static( StaticContent { content, status_code: 200, - headers: HeaderListVc::empty(), + headers: HeaderList::empty(), } .cell(), ) @@ -166,10 +163,10 @@ impl ContentSourceContentVc { #[turbo_tasks::function] pub fn static_with_headers( - content: VersionedContentVc, + content: Vc>, status_code: u16, - headers: HeaderListVc, - ) -> ContentSourceContentVc { + headers: Vc, + ) -> Vc { ContentSourceContent::Static( StaticContent { content, @@ -182,7 +179,7 @@ impl ContentSourceContentVc { } #[turbo_tasks::function] - pub fn not_found() -> ContentSourceContentVc { + pub fn not_found() -> Vc { ContentSourceContent::NotFound.cell() } } @@ -192,14 +189,14 @@ impl ContentSourceContentVc { pub struct HeaderList(Vec<(String, String)>); #[turbo_tasks::value_impl] -impl HeaderListVc { +impl HeaderList { #[turbo_tasks::function] - pub fn new(headers: Vec<(String, String)>) -> Self { + pub fn new(headers: Vec<(String, String)>) -> Vc { HeaderList(headers).cell() } #[turbo_tasks::function] - pub fn empty() -> Self { + pub fn empty() -> Vc { HeaderList(vec![]).cell() } } @@ -213,7 +210,7 @@ impl HeaderListVc { pub struct NeededData { /// A [ContentSource] to query once the data has been extracted from the /// server. This _does not_ need to be the original content source. - pub source: ContentSourceVc, + pub source: Vc>, /// A path with which to call into that content source. This _does not_ need /// to be the original path. @@ -250,7 +247,7 @@ pub struct ContentSourceData { /// requested. pub raw_headers: Option>, /// Request body, if requested. - pub body: Option, + pub body: Option>, /// See [ContentSourceDataVary::cache_buster]. pub cache_buster: u64, } @@ -293,8 +290,8 @@ impl> From for Body { } } -impl Default for BodyVc { - fn default() -> Self { +impl ValueDefault for Body { + fn value_default() -> Vc { Body::default().cell() } } @@ -466,30 +463,48 @@ pub trait ContentSource { /// This is useful as this method call will be cached based on it's /// arguments, so we want to make the arguments contain as little /// information as possible to increase cache hit ratio. - fn get(&self, path: &str, data: Value) -> ContentSourceResultVc; + fn get(self: Vc, path: String, data: Value) + -> Vc; /// Gets any content sources wrapped in this content source. - fn get_children(&self) -> ContentSourcesVc { - ContentSourcesVc::empty() + fn get_children(self: Vc) -> Vc { + ContentSources::empty() } } -#[turbo_tasks::value_impl] -impl ContentSourceVc { - #[turbo_tasks::function] - pub fn issue_context(self, context: FileSystemPathVc, description: &str) -> ContentSourceVc { - IssueContextContentSourceVc::new_context(context, description, self).into() +pub trait ContentSourceExt { + fn issue_context( + self: Vc, + context: Vc, + description: String, + ) -> Vc>; +} + +impl ContentSourceExt for T +where + T: Upcast>, +{ + fn issue_context( + self: Vc, + context: Vc, + description: String, + ) -> Vc> { + Vc::upcast(IssueContextContentSource::new_context( + context, + description, + Vc::upcast(self), + )) } } #[turbo_tasks::value(transparent)] -pub struct ContentSources(Vec); +pub struct ContentSources(Vec>>); #[turbo_tasks::value_impl] -impl ContentSourcesVc { +impl ContentSources { #[turbo_tasks::function] - pub fn empty() -> Self { - ContentSourcesVc::cell(Vec::new()) + pub fn empty() -> Vc { + Vc::cell(Vec::new()) } } @@ -499,17 +514,17 @@ impl ContentSourcesVc { pub struct NoContentSource; #[turbo_tasks::value_impl] -impl NoContentSourceVc { +impl NoContentSource { #[turbo_tasks::function] - pub fn new() -> Self { + pub fn new() -> Vc { NoContentSource.cell() } } #[turbo_tasks::value_impl] impl ContentSource for NoContentSource { #[turbo_tasks::function] - fn get(&self, _path: &str, _data: Value) -> ContentSourceResultVc { - ContentSourceResultVc::not_found() + fn get(&self, _path: String, _data: Value) -> Vc { + ContentSourceResult::not_found() } } @@ -526,15 +541,15 @@ pub struct Rewrite { /// A [ContentSource] from which to restart the lookup process. This _does /// not_ need to be the original content source. Having [None] source will /// restart the lookup process from the original root ContentSource. - pub source: Option, + pub source: Option>>, /// A [Headers] which will be appended to the eventual, fully resolved /// content result. This overwrites any previous matching headers. - pub response_headers: Option, + pub response_headers: Option>, /// A [HeaderList] which will overwrite the values used during the lookup /// process. All headers not present in this list will be deleted. - pub request_headers: Option, + pub request_headers: Option>, } pub struct RewriteBuilder { @@ -556,26 +571,26 @@ impl RewriteBuilder { /// Sets the [ContentSource] from which to restart the lookup process. /// Without a source, the lookup will restart from the original root /// ContentSource. - pub fn content_source(mut self, source: ContentSourceVc) -> Self { + pub fn content_source(mut self, source: Vc>) -> Self { self.rewrite.source = Some(source); self } /// Sets response headers to append to the eventual, fully resolved content /// result. - pub fn response_headers(mut self, headers: HeaderListVc) -> Self { + pub fn response_headers(mut self, headers: Vc) -> Self { self.rewrite.response_headers = Some(headers); self } /// Sets request headers to overwrite the headers used during the lookup /// process. - pub fn request_headers(mut self, headers: HeaderListVc) -> Self { + pub fn request_headers(mut self, headers: Vc) -> Self { self.rewrite.request_headers = Some(headers); self } - pub fn build(self) -> RewriteVc { + pub fn build(self) -> Vc { self.rewrite.cell() } } diff --git a/crates/turbopack-dev-server/src/source/resolve.rs b/crates/turbopack-dev-server/src/source/resolve.rs index 36cb62e240b843..c0f6b59fa0d1e9 100644 --- a/crates/turbopack-dev-server/src/source/resolve.rs +++ b/crates/turbopack-dev-server/src/source/resolve.rs @@ -8,16 +8,15 @@ use hyper::{ header::{HeaderName as HyperHeaderName, HeaderValue as HyperHeaderValue}, Uri, }; -use turbo_tasks::{TransientInstance, Value}; +use turbo_tasks::{TransientInstance, Value, Vc}; use super::{ headers::{HeaderValue, Headers}, query::Query, request::SourceRequest, - ContentSourceContent, ContentSourceDataVary, ContentSourceResult, ContentSourceVc, - HeaderListVc, ProxyResultVc, StaticContentVc, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary, + ContentSourceResult, GetContentSourceContent, HeaderList, ProxyResult, StaticContent, }; -use crate::source::{ContentSource, ContentSourceData, GetContentSourceContent}; /// The result of [`resolve_source_request`]. Similar to a /// `ContentSourceContent`, but without the `Rewrite` variant as this is taken @@ -25,17 +24,17 @@ use crate::source::{ContentSource, ContentSourceData, GetContentSourceContent}; #[turbo_tasks::value(serialization = "none")] pub enum ResolveSourceRequestResult { NotFound, - Static(StaticContentVc, HeaderListVc), - HttpProxy(ProxyResultVc), + Static(Vc, Vc), + HttpProxy(Vc), } /// Resolves a [SourceRequest] within a [super::ContentSource], returning the /// corresponding content. #[turbo_tasks::function] pub async fn resolve_source_request( - source: ContentSourceVc, + source: Vc>, request: TransientInstance, -) -> Result { +) -> Result> { let mut data = ContentSourceData::default(); let mut current_source = source; // Remove leading slash. @@ -44,7 +43,7 @@ pub async fn resolve_source_request( let mut request_overwrites = (*request).clone(); let mut response_header_overwrites = Vec::new(); loop { - let result = current_source.get(¤t_asset_path, Value::new(data)); + let result = current_source.get(current_asset_path, Value::new(data)); match &*result.strongly_consistent().await? { ContentSourceResult::NotFound => break Ok(ResolveSourceRequestResult::NotFound.cell()), ContentSourceResult::NeedData(needed) => { @@ -92,7 +91,7 @@ pub async fn resolve_source_request( ContentSourceContent::Static(static_content) => { break Ok(ResolveSourceRequestResult::Static( *static_content, - HeaderListVc::new(response_header_overwrites), + HeaderList::new(response_header_overwrites), ) .cell()); } diff --git a/crates/turbopack-dev-server/src/source/router.rs b/crates/turbopack-dev-server/src/source/router.rs index 8605b6754961f9..3e64132cc8544a 100644 --- a/crates/turbopack-dev-server/src/source/router.rs +++ b/crates/turbopack-dev-server/src/source/router.rs @@ -1,17 +1,17 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value}; -use turbopack_core::introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}; +use turbo_tasks::{TryJoinIterExt, Value, Vc}; +use turbopack_core::introspect::{Introspectable, IntrospectableChildren}; -use super::{ContentSource, ContentSourceData, ContentSourceResultVc, ContentSourceVc}; -use crate::source::ContentSourcesVc; +use super::{ContentSource, ContentSourceData, ContentSourceResult}; +use crate::source::ContentSources; /// Binds different ContentSources to different subpaths. A fallback /// ContentSource will serve all other subpaths. // TODO(WEB-1151): Remove this and migrate all users to PrefixedRouterContentSource. #[turbo_tasks::value(shared)] pub struct RouterContentSource { - pub routes: Vec<(String, ContentSourceVc)>, - pub fallback: ContentSourceVc, + pub routes: Vec<(String, Vc>)>, + pub fallback: Vc>, } /// Binds different ContentSources to different subpaths. The request path must @@ -20,19 +20,19 @@ pub struct RouterContentSource { /// other subpaths, including if the request path does not include the prefix. #[turbo_tasks::value(shared)] pub struct PrefixedRouterContentSource { - prefix: StringVc, - routes: Vec<(String, ContentSourceVc)>, - fallback: ContentSourceVc, + prefix: Vc, + routes: Vec<(String, Vc>)>, + fallback: Vc>, } #[turbo_tasks::value_impl] -impl PrefixedRouterContentSourceVc { +impl PrefixedRouterContentSource { #[turbo_tasks::function] pub async fn new( - prefix: StringVc, - routes: Vec<(String, ContentSourceVc)>, - fallback: ContentSourceVc, - ) -> Result { + prefix: Vc, + routes: Vec<(String, Vc>)>, + fallback: Vc>, + ) -> Result> { if cfg!(debug_assertions) { let prefix_string = prefix.await?; debug_assert!(prefix_string.is_empty() || prefix_string.ends_with('/')); @@ -52,12 +52,12 @@ impl PrefixedRouterContentSourceVc { /// and subpath) is used to query the matching ContentSource. If no match is /// found, then the fallback is queried with the original path. async fn get( - routes: &[(String, ContentSourceVc)], - fallback: &ContentSourceVc, + routes: &[(String, Vc>)], + fallback: &Vc>, prefix: &str, path: &str, data: Value, -) -> Result { +) -> Result> { let mut found = None; if let Some(path) = path.strip_prefix(prefix) { @@ -70,14 +70,14 @@ async fn get( } let (source, path) = found.unwrap_or((fallback, path)); - Ok(source.resolve().await?.get(path, data)) + Ok(source.resolve().await?.get(path.to_string(), data)) } fn get_children( - routes: &[(String, ContentSourceVc)], - fallback: &ContentSourceVc, -) -> ContentSourcesVc { - ContentSourcesVc::cell( + routes: &[(String, Vc>)], + fallback: &Vc>, +) -> Vc { + Vc::cell( routes .iter() .map(|r| r.1) @@ -87,18 +87,18 @@ fn get_children( } async fn get_introspection_children( - routes: &[(String, ContentSourceVc)], - fallback: &ContentSourceVc, -) -> Result { - Ok(IntrospectableChildrenVc::cell( + routes: &[(String, Vc>)], + fallback: &Vc>, +) -> Result> { + Ok(Vc::cell( routes .iter() .cloned() .chain(std::iter::once((String::new(), *fallback))) .map(|(path, source)| async move { - Ok(IntrospectableVc::resolve_from(source) + Ok(Vc::try_resolve_sidecast::>(source) .await? - .map(|i| (StringVc::cell(path), i))) + .map(|i| (Vc::cell(path), i))) }) .try_join() .await? @@ -113,14 +113,14 @@ impl ContentSource for RouterContentSource { #[turbo_tasks::function] async fn get( &self, - path: &str, + path: String, data: Value, - ) -> Result { - get(&self.routes, &self.fallback, "", path, data).await + ) -> Result> { + get(&self.routes, &self.fallback, "", &path, data).await } #[turbo_tasks::function] - fn get_children(&self) -> ContentSourcesVc { + fn get_children(&self) -> Vc { get_children(&self.routes, &self.fallback) } } @@ -128,12 +128,12 @@ impl ContentSource for RouterContentSource { #[turbo_tasks::value_impl] impl Introspectable for RouterContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("router content source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("router content source".to_string()) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { get_introspection_children(&self.routes, &self.fallback).await } } @@ -143,15 +143,15 @@ impl ContentSource for PrefixedRouterContentSource { #[turbo_tasks::function] async fn get( &self, - path: &str, + path: String, data: Value, - ) -> Result { + ) -> Result> { let prefix = self.prefix.await?; - get(&self.routes, &self.fallback, &prefix, path, data).await + get(&self.routes, &self.fallback, &prefix, &path, data).await } #[turbo_tasks::function] - fn get_children(&self) -> ContentSourcesVc { + fn get_children(&self) -> Vc { get_children(&self.routes, &self.fallback) } } @@ -159,18 +159,18 @@ impl ContentSource for PrefixedRouterContentSource { #[turbo_tasks::value_impl] impl Introspectable for PrefixedRouterContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("prefixed router content source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("prefixed router content source".to_string()) } #[turbo_tasks::function] - async fn details(&self) -> Result { + async fn details(&self) -> Result> { let prefix = self.prefix.await?; - Ok(StringVc::cell(format!("prefix: '{}'", prefix))) + Ok(Vc::cell(format!("prefix: '{}'", prefix))) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { get_introspection_children(&self.routes, &self.fallback).await } } diff --git a/crates/turbopack-dev-server/src/source/source_maps.rs b/crates/turbopack-dev-server/src/source/source_maps.rs index 6726f1c59a69d4..e2079f9610216b 100644 --- a/crates/turbopack-dev-server/src/source/source_maps.rs +++ b/crates/turbopack-dev-server/src/source/source_maps.rs @@ -1,22 +1,17 @@ use anyhow::Result; use mime::APPLICATION_JSON; -use turbo_tasks::{primitives::StringVc, Value}; +use turbo_tasks::{Value, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::AssetContentVc, - introspect::{Introspectable, IntrospectableVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc}, + asset::AssetContent, introspect::Introspectable, source_map::GenerateSourceMap, + version::VersionedContentExt, }; use super::{ query::QueryValue, - wrapping_source::{ - encode_pathname_to_url, ContentSourceProcessor, ContentSourceProcessorVc, - WrappedContentSourceVc, - }, - ContentSource, ContentSourceContent, ContentSourceContentVc, ContentSourceData, - ContentSourceDataFilter, ContentSourceDataVary, ContentSourceResultVc, ContentSourceVc, - NeededData, RewriteBuilder, + wrapping_source::{encode_pathname_to_url, ContentSourceProcessor, WrappedContentSource}, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataFilter, + ContentSourceDataVary, ContentSourceResult, NeededData, RewriteBuilder, }; /// SourceMapContentSource allows us to serve full source maps, and individual @@ -32,13 +27,13 @@ use super::{ #[turbo_tasks::value(shared)] pub struct SourceMapContentSource { /// A wrapped content source from which we will fetch assets. - asset_source: ContentSourceVc, + asset_source: Vc>, } #[turbo_tasks::value_impl] -impl SourceMapContentSourceVc { +impl SourceMapContentSource { #[turbo_tasks::function] - pub fn new(asset_source: ContentSourceVc) -> SourceMapContentSourceVc { + pub fn new(asset_source: Vc>) -> Vc { SourceMapContentSource { asset_source }.cell() } } @@ -47,20 +42,20 @@ impl SourceMapContentSourceVc { impl ContentSource for SourceMapContentSource { #[turbo_tasks::function] async fn get( - self_vc: SourceMapContentSourceVc, - path: &str, + self: Vc, + path: String, data: Value, - ) -> Result { + ) -> Result> { let pathname = match path.strip_suffix(".map") { Some(p) => p, - _ => return Ok(ContentSourceResultVc::not_found()), + _ => return Ok(ContentSourceResult::not_found()), }; let query = match &data.query { Some(q) => q, None => { - return Ok(ContentSourceResultVc::need_data(Value::new(NeededData { - source: self_vc.into(), + return Ok(ContentSourceResult::need_data(Value::new(NeededData { + source: Vc::upcast(self), path: path.to_string(), vary: ContentSourceDataVary { query: Some(ContentSourceDataFilter::Subset(["id".to_string()].into())), @@ -75,32 +70,31 @@ impl ContentSource for SourceMapContentSource { _ => None, }; - let wrapped = WrappedContentSourceVc::new( - self_vc.await?.asset_source, - SourceMapContentProcessorVc::new(id).into(), + let wrapped = WrappedContentSource::new( + self.await?.asset_source, + Vc::upcast(SourceMapContentProcessor::new(id)), ); - Ok(ContentSourceResultVc::exact( + Ok(ContentSourceResult::exact(Vc::upcast( ContentSourceContent::Rewrite( RewriteBuilder::new(encode_pathname_to_url(pathname)) - .content_source(wrapped.as_content_source()) + .content_source(Vc::upcast(wrapped)) .build(), ) - .cell() - .into(), - )) + .cell(), + ))) } } #[turbo_tasks::value_impl] impl Introspectable for SourceMapContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("source map content source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("source map content source".to_string()) } #[turbo_tasks::function] - fn details(&self) -> StringVc { - StringVc::cell("serves chunk and chunk item source maps".to_string()) + fn details(&self) -> Vc { + Vc::cell("serves chunk and chunk item source maps".to_string()) } } @@ -115,9 +109,9 @@ pub struct SourceMapContentProcessor { } #[turbo_tasks::value_impl] -impl SourceMapContentProcessorVc { +impl SourceMapContentProcessor { #[turbo_tasks::function] - fn new(id: Option) -> Self { + fn new(id: Option) -> Vc { SourceMapContentProcessor { id }.cell() } } @@ -125,29 +119,33 @@ impl SourceMapContentProcessorVc { #[turbo_tasks::value_impl] impl ContentSourceProcessor for SourceMapContentProcessor { #[turbo_tasks::function] - async fn process(&self, content: ContentSourceContentVc) -> Result { + async fn process(&self, content: Vc) -> Result> { let file = match &*content.await? { ContentSourceContent::Static(static_content) => static_content.await?.content, - _ => return Ok(ContentSourceContentVc::not_found()), + _ => return Ok(ContentSourceContent::not_found()), }; - let gen = match GenerateSourceMapVc::resolve_from(file).await? { + let gen = match Vc::try_resolve_sidecast::>(file).await? { Some(f) => f, - None => return Ok(ContentSourceContentVc::not_found()), + None => return Ok(ContentSourceContent::not_found()), }; let sm = if let Some(id) = &self.id { - gen.by_section(id).await? + gen.by_section(id.clone()).await? } else { gen.generate_source_map().await? }; let sm = match &*sm { Some(sm) => *sm, - None => return Ok(ContentSourceContentVc::not_found()), + None => return Ok(ContentSourceContent::not_found()), }; let content = sm.to_rope().await?; - let asset = AssetContentVc::from(File::from(content).with_content_type(APPLICATION_JSON)); - Ok(ContentSourceContentVc::static_content(asset.into())) + let asset = AssetContent::file( + File::from(content) + .with_content_type(APPLICATION_JSON) + .into(), + ); + Ok(ContentSourceContent::static_content(asset.versioned())) } } diff --git a/crates/turbopack-dev-server/src/source/specificity.rs b/crates/turbopack-dev-server/src/source/specificity.rs index 6199dcc6ceb713..d5571bc7f56405 100644 --- a/crates/turbopack-dev-server/src/source/specificity.rs +++ b/crates/turbopack-dev-server/src/source/specificity.rs @@ -2,7 +2,7 @@ use std::{cmp::Ordering, fmt::Display}; use anyhow::Result; use serde::{Deserialize, Serialize}; -use turbo_tasks::trace::TraceRawVcs; +use turbo_tasks::{trace::TraceRawVcs, Vc}; /// Type of something that affects the specificity of a URL, making a URL match /// less specific. @@ -98,7 +98,7 @@ impl Specificity { } /// The lowest possible specificity. Used when no match is found. - pub fn not_found() -> Self { + pub fn not_found_ref() -> Self { Specificity { elements: vec![SpecificityElement { position: 0, @@ -132,16 +132,16 @@ impl Display for Specificity { } #[turbo_tasks::value_impl] -impl SpecificityVc { +impl Specificity { /// The lowest possible specificity. Used when no match is found. #[turbo_tasks::function] - pub fn not_found() -> Self { - Specificity::not_found().cell() + pub fn not_found() -> Vc { + Specificity::not_found_ref().cell() } /// The highest possible specificity. Used for exact matches. #[turbo_tasks::function] - pub fn exact() -> Self { + pub fn exact() -> Vc { Specificity { elements: Vec::new(), } @@ -150,7 +150,7 @@ impl SpecificityVc { /// The specificity with an additional catch all at the specified position. #[turbo_tasks::function] - pub async fn with_catch_all(self, position: u32) -> Result { + pub async fn with_catch_all(self: Vc, position: u32) -> Result> { Ok(self .await? .with(position, SpecificityElementType::CatchAll) @@ -160,7 +160,7 @@ impl SpecificityVc { /// The specificity with an additional dynamic segment at the specified /// position. #[turbo_tasks::function] - pub async fn with_dynamic_segment(self, position: u32) -> Result { + pub async fn with_dynamic_segment(self: Vc, position: u32) -> Result> { Ok(self .await? .with(position, SpecificityElementType::DynamicSegment) @@ -170,7 +170,7 @@ impl SpecificityVc { /// The specificity with an additional fallback match at the specified /// position. #[turbo_tasks::function] - pub async fn with_fallback(self, position: u32) -> Result { + pub async fn with_fallback(self: Vc, position: u32) -> Result> { Ok(self .await? .with(position, SpecificityElementType::Fallback) diff --git a/crates/turbopack-dev-server/src/source/static_assets.rs b/crates/turbopack-dev-server/src/source/static_assets.rs index 1d5c3ccbbeaf62..f9d7ccd75e7a47 100644 --- a/crates/turbopack-dev-server/src/source/static_assets.rs +++ b/crates/turbopack-dev-server/src/source/static_assets.rs @@ -1,38 +1,34 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value}; -use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPathVc}; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath}; use turbopack_core::{ asset::Asset, - introspect::{ - asset::IntrospectableAssetVc, Introspectable, IntrospectableChildrenVc, IntrospectableVc, - }, - source_asset::SourceAssetVc, + introspect::{asset::IntrospectableAsset, Introspectable, IntrospectableChildren}, + source_asset::SourceAsset, + version::VersionedContentExt, }; -use super::{ - ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceResultVc, - ContentSourceVc, -}; +use super::{ContentSource, ContentSourceContent, ContentSourceData, ContentSourceResult}; #[turbo_tasks::value(shared)] pub struct StaticAssetsContentSource { - pub prefix: StringVc, - pub dir: FileSystemPathVc, + pub prefix: Vc, + pub dir: Vc, } #[turbo_tasks::value_impl] -impl StaticAssetsContentSourceVc { +impl StaticAssetsContentSource { // TODO(WEB-1151): Remove this method and migrate users to `with_prefix`. #[turbo_tasks::function] - pub fn new(prefix: String, dir: FileSystemPathVc) -> StaticAssetsContentSourceVc { - StaticAssetsContentSourceVc::with_prefix(StringVc::cell(prefix), dir) + pub fn new(prefix: String, dir: Vc) -> Vc { + StaticAssetsContentSource::with_prefix(Vc::cell(prefix), dir) } #[turbo_tasks::function] pub async fn with_prefix( - prefix: StringVc, - dir: FileSystemPathVc, - ) -> Result { + prefix: Vc, + dir: Vc, + ) -> Result> { if cfg!(debug_assertions) { let prefix_string = prefix.await?; debug_assert!(prefix_string.is_empty() || prefix_string.ends_with('/')); @@ -47,41 +43,41 @@ impl ContentSource for StaticAssetsContentSource { #[turbo_tasks::function] async fn get( &self, - path: &str, + path: String, _data: Value, - ) -> Result { + ) -> Result> { if !path.is_empty() { let prefix = self.prefix.await?; if let Some(path) = path.strip_prefix(&*prefix) { - let path = self.dir.join(path); + let path = self.dir.join(path.to_string()); let ty = path.get_type().await?; if matches!( &*ty, FileSystemEntryType::File | FileSystemEntryType::Symlink ) { - let content = SourceAssetVc::new(path).as_asset().content(); - return Ok(ContentSourceResultVc::exact( - ContentSourceContentVc::static_content(content.into()).into(), - )); + let content = Vc::upcast::>(SourceAsset::new(path)).content(); + return Ok(ContentSourceResult::exact(Vc::upcast( + ContentSourceContent::static_content(content.versioned()), + ))); } } } - Ok(ContentSourceResultVc::not_found()) + Ok(ContentSourceResult::not_found()) } } #[turbo_tasks::value_impl] impl Introspectable for StaticAssetsContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("static assets directory content source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("static assets directory content source".to_string()) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let dir = self.dir.read_dir().await?; let DirectoryContent::Entries(entries) = &*dir else { - return Ok(IntrospectableChildrenVc::cell(Default::default())); + return Ok(Vc::cell(Default::default())); }; let prefix = self.prefix.await?; @@ -90,19 +86,20 @@ impl Introspectable for StaticAssetsContentSource { .map(|(name, entry)| { let child = match entry { DirectoryEntry::File(path) | DirectoryEntry::Symlink(path) => { - IntrospectableAssetVc::new(SourceAssetVc::new(*path).as_asset()) + IntrospectableAsset::new(Vc::upcast(SourceAsset::new(*path))) + } + DirectoryEntry::Directory(path) => { + Vc::upcast(StaticAssetsContentSource::with_prefix( + Vc::cell(format!("{}{name}/", &*prefix)), + *path, + )) } - DirectoryEntry::Directory(path) => StaticAssetsContentSourceVc::with_prefix( - StringVc::cell(format!("{}{name}/", &*prefix)), - *path, - ) - .into(), DirectoryEntry::Other(_) => todo!("what's DirectoryContent::Other?"), DirectoryEntry::Error => todo!(), }; - (StringVc::cell(name.clone()), child) + (Vc::cell(name.clone()), child) }) .collect(); - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-dev-server/src/source/wrapping_source.rs b/crates/turbopack-dev-server/src/source/wrapping_source.rs index f937b0b5639933..12fae893b4a202 100644 --- a/crates/turbopack-dev-server/src/source/wrapping_source.rs +++ b/crates/turbopack-dev-server/src/source/wrapping_source.rs @@ -1,14 +1,12 @@ use std::{borrow::Cow, iter::once}; use anyhow::Result; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use super::{ - ContentSource, ContentSourceContentVc, ContentSourceData, ContentSourceDataVaryVc, - ContentSourceResult, ContentSourceResultVc, ContentSourceVc, GetContentSourceContent, - GetContentSourceContentVc, NeededData, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary, + ContentSourceResult, GetContentSourceContent, NeededData, Rewrite, }; -use crate::source::{ContentSourceContent, Rewrite}; /// A ContentSourceProcessor handles the final processing of an eventual /// [ContentSourceContent]. @@ -19,7 +17,7 @@ use crate::source::{ContentSourceContent, Rewrite}; /// [ContentSourceContent]. #[turbo_tasks::value_trait] pub trait ContentSourceProcessor { - fn process(&self, content: ContentSourceContentVc) -> ContentSourceContentVc; + fn process(self: Vc, content: Vc) -> Vc; } pub fn encode_pathname_to_url(pathname: &str) -> String { @@ -43,14 +41,17 @@ pub fn encode_pathname_to_url(pathname: &str) -> String { /// [WrappedGetContentSourceContent]. #[turbo_tasks::value] pub struct WrappedContentSource { - inner: ContentSourceVc, - processor: ContentSourceProcessorVc, + inner: Vc>, + processor: Vc>, } #[turbo_tasks::value_impl] -impl WrappedContentSourceVc { +impl WrappedContentSource { #[turbo_tasks::function] - pub async fn new(inner: ContentSourceVc, processor: ContentSourceProcessorVc) -> Self { + pub async fn new( + inner: Vc>, + processor: Vc>, + ) -> Vc { WrappedContentSource { inner, processor }.cell() } } @@ -60,9 +61,9 @@ impl ContentSource for WrappedContentSource { #[turbo_tasks::function] async fn get( &self, - path: &str, + path: String, data: Value, - ) -> Result { + ) -> Result> { let res = self.inner.get(path, data); Ok(match &*res.await? { @@ -72,8 +73,8 @@ impl ContentSource for WrappedContentSource { // in a new wrapped processor. That way, whatever ContentSourceResult is // returned when we resume can itself be wrapped, or be wrapped with a // WrappedGetContentSourceContent. - ContentSourceResultVc::need_data(Value::new(NeededData { - source: WrappedContentSourceVc::new(needed.source, self.processor).into(), + ContentSourceResult::need_data(Value::new(NeededData { + source: Vc::upcast(WrappedContentSource::new(needed.source, self.processor)), path: needed.path.clone(), vary: needed.vary.clone(), })) @@ -88,12 +89,11 @@ impl ContentSource for WrappedContentSource { // returns. ContentSourceResult::Result { specificity: *specificity, - get_content: WrappedGetContentSourceContentVc::new( + get_content: Vc::upcast(WrappedGetContentSourceContent::new( self.inner, *get_content, self.processor, - ) - .into(), + )), } .cell() } @@ -110,19 +110,19 @@ impl ContentSource for WrappedContentSource { /// ContentSourceResult. #[turbo_tasks::value] struct WrappedGetContentSourceContent { - inner_source: ContentSourceVc, - inner: GetContentSourceContentVc, - processor: ContentSourceProcessorVc, + inner_source: Vc>, + inner: Vc>, + processor: Vc>, } #[turbo_tasks::value_impl] -impl WrappedGetContentSourceContentVc { +impl WrappedGetContentSourceContent { #[turbo_tasks::function] fn new( - inner_source: ContentSourceVc, - inner: GetContentSourceContentVc, - processor: ContentSourceProcessorVc, - ) -> Self { + inner_source: Vc>, + inner: Vc>, + processor: Vc>, + ) -> Vc { WrappedGetContentSourceContent { inner_source, inner, @@ -135,25 +135,22 @@ impl WrappedGetContentSourceContentVc { #[turbo_tasks::value_impl] impl GetContentSourceContent for WrappedGetContentSourceContent { #[turbo_tasks::function] - fn vary(&self) -> ContentSourceDataVaryVc { + fn vary(&self) -> Vc { self.inner.vary() } #[turbo_tasks::function] - async fn get(&self, data: Value) -> Result { + async fn get(&self, data: Value) -> Result> { let res = self.inner.get(data); if let ContentSourceContent::Rewrite(rewrite) = &*res.await? { let rewrite = rewrite.await?; return Ok(ContentSourceContent::Rewrite( Rewrite { path_and_query: rewrite.path_and_query.clone(), - source: Some( - WrappedContentSourceVc::new( - rewrite.source.unwrap_or(self.inner_source), - self.processor, - ) - .into(), - ), + source: Some(Vc::upcast(WrappedContentSource::new( + rewrite.source.unwrap_or(self.inner_source), + self.processor, + ))), response_headers: rewrite.response_headers, request_headers: rewrite.request_headers, } diff --git a/crates/turbopack-dev-server/src/update/server.rs b/crates/turbopack-dev-server/src/update/server.rs index d201dc82cb3962..7d1e8586081eac 100644 --- a/crates/turbopack-dev-server/src/update/server.rs +++ b/crates/turbopack-dev-server/src/update/server.rs @@ -11,9 +11,9 @@ use pin_project_lite::pin_project; use tokio::select; use tokio_stream::StreamMap; use tracing::{instrument, Level}; -use turbo_tasks::{TransientInstance, TurboTasksApi}; +use turbo_tasks::{TransientInstance, TurboTasksApi, Vc}; use turbo_tasks_fs::json::parse_json_with_source_context; -use turbopack_core::{error::PrettyPrintError, issue::IssueReporterVc, version::Update}; +use turbopack_core::{error::PrettyPrintError, issue::IssueReporter, version::Update}; use super::{ protocol::{ClientMessage, ClientUpdateInstruction, Issue, ResourceIdentifier}, @@ -29,12 +29,12 @@ use crate::{ pub(crate) struct UpdateServer { source_provider: P, #[allow(dead_code)] - issue_reporter: IssueReporterVc, + issue_reporter: Vc>, } impl UpdateServer

{ /// Create a new update server with the given websocket and content source. - pub fn new(source_provider: P, issue_reporter: IssueReporterVc) -> Self { + pub fn new(source_provider: P, issue_reporter: Vc>) -> Self { Self { source_provider, issue_reporter, diff --git a/crates/turbopack-dev-server/src/update/stream.rs b/crates/turbopack-dev-server/src/update/stream.rs index 4fa14f79eb39e1..d20c1277415863 100644 --- a/crates/turbopack-dev-server/src/update/stream.rs +++ b/crates/turbopack-dev-server/src/update/stream.rs @@ -5,37 +5,26 @@ use futures::{prelude::*, Stream}; use tokio::sync::mpsc::Sender; use tokio_stream::wrappers::ReceiverStream; use tracing::Instrument; -use turbo_tasks::{ - primitives::StringVc, CollectiblesSource, IntoTraitRef, State, TraitRef, TransientInstance, -}; -use turbo_tasks_fs::{FileSystem, FileSystemPathVc}; +use turbo_tasks::{IntoTraitRef, ReadRef, State, TraitRef, TransientInstance, Vc}; +use turbo_tasks_fs::{FileSystem, FileSystemPath}; use turbopack_core::{ error::PrettyPrintError, - issue::{ - Issue, IssueSeverity, IssueSeverityVc, IssueVc, OptionIssueProcessingPathItemsVc, - PlainIssueReadRef, - }, - server_fs::ServerFileSystemVc, - version::{ - NotFoundVersionVc, PartialUpdate, TotalUpdate, Update, UpdateReadRef, VersionVc, - VersionedContent, - }, + issue::{Issue, IssueContextExt, IssueSeverity, OptionIssueProcessingPathItems, PlainIssue}, + server_fs::ServerFileSystem, + version::{NotFoundVersion, PartialUpdate, TotalUpdate, Update, Version, VersionedContent}, }; -use crate::source::{ - resolve::{ResolveSourceRequestResult, ResolveSourceRequestResultVc}, - ProxyResultVc, -}; +use crate::source::{resolve::ResolveSourceRequestResult, ProxyResult}; -type GetContentFn = Box ResolveSourceRequestResultVc + Send + Sync>; +type GetContentFn = Box Vc + Send + Sync>; -async fn peek_issues(source: T) -> Result> { - let captured = IssueVc::peek_issues_with_path(source).await?.await?; +async fn peek_issues(source: Vc) -> Result>> { + let captured = source.peek_issues_with_path().await?.await?; captured.get_plain_issues().await } -fn extend_issues(issues: &mut Vec, new_issues: Vec) { +fn extend_issues(issues: &mut Vec>, new_issues: Vec>) { for issue in new_issues { if issues.contains(&issue) { continue; @@ -47,10 +36,10 @@ fn extend_issues(issues: &mut Vec, new_issues: Vec, get_content: TransientInstance, -) -> Result { +) -> Result> { let content = get_content(); let mut plain_issues = peek_issues(content).await?; @@ -60,17 +49,15 @@ async fn get_update_stream_item( plain_issues.push( FatalStreamIssue { resource: resource.to_string(), - description: StringVc::cell(format!("{}", PrettyPrintError(&e))), + description: Vc::cell(format!("{}", PrettyPrintError(&e))), } .cell() - .as_issue() - .into_plain(OptionIssueProcessingPathItemsVc::none()) + .into_plain(OptionIssueProcessingPathItems::none()) .await?, ); let update = Update::Total(TotalUpdate { - to: NotFoundVersionVc::new() - .as_version() + to: Vc::upcast::>(NotFoundVersion::new()) .into_trait_ref() .await?, }) @@ -116,7 +103,7 @@ async fn get_update_stream_item( extend_issues(&mut plain_issues, peek_issues(proxy_result).await?); let from = from.get(); - if let Some(from) = ProxyResultVc::resolve_from(from).await? { + if let Some(from) = Vc::try_resolve_downcast_type::(from).await? { if from.await? == proxy_result_value { return Ok(UpdateStreamItem::Found { update: Update::None.cell().await?, @@ -128,7 +115,9 @@ async fn get_update_stream_item( Ok(UpdateStreamItem::Found { update: Update::Total(TotalUpdate { - to: proxy_result.as_version().into_trait_ref().await?, + to: Vc::upcast::>(proxy_result) + .into_trait_ref() + .await?, }) .cell() .await?, @@ -143,8 +132,7 @@ async fn get_update_stream_item( // TODO add special instructions for removed assets to handled it in a better // way Update::Total(TotalUpdate { - to: NotFoundVersionVc::new() - .as_version() + to: Vc::upcast::>(NotFoundVersion::new()) .into_trait_ref() .await?, }) @@ -164,10 +152,10 @@ async fn get_update_stream_item( #[turbo_tasks::function] async fn compute_update_stream( - resource: &str, - from: VersionStateVc, + resource: String, + from: Vc, get_content: TransientInstance, - sender: TransientInstance>>, + sender: TransientInstance>>>, ) { let item = get_update_stream_item(resource, from, get_content) .strongly_consistent() @@ -180,27 +168,27 @@ async fn compute_update_stream( #[turbo_tasks::value] struct VersionState { #[turbo_tasks(trace_ignore)] - version: State>, + version: State>>, } #[turbo_tasks::value_impl] -impl VersionStateVc { +impl VersionState { #[turbo_tasks::function] - async fn get(self) -> Result { + async fn get(self: Vc) -> Result>> { let this = self.await?; let version = TraitRef::cell(this.version.get().clone()); Ok(version) } } -impl VersionStateVc { - async fn new(version: TraitRef) -> Result { +impl VersionState { + async fn new(version: TraitRef>) -> Result> { Ok(Self::cell(VersionState { version: State::new(version), })) } - async fn set(&self, new_version: TraitRef) -> Result<()> { + async fn set(self: Vc, new_version: TraitRef>) -> Result<()> { let this = self.await?; this.version.set(new_version); Ok(()) @@ -208,7 +196,7 @@ impl VersionStateVc { } pub(super) struct UpdateStream( - Pin> + Send + Sync>>, + Pin>> + Send + Sync>>, ); impl UpdateStream { @@ -226,13 +214,13 @@ impl UpdateStream { ResolveSourceRequestResult::Static(static_content, _) => { static_content.await?.content.version() } - ResolveSourceRequestResult::HttpProxy(proxy_result) => proxy_result.into(), - _ => NotFoundVersionVc::new().into(), + ResolveSourceRequestResult::HttpProxy(proxy_result) => Vc::upcast(proxy_result), + _ => Vc::upcast(NotFoundVersion::new()), }; - let version_state = VersionStateVc::new(version.into_trait_ref().await?).await?; + let version_state = VersionState::new(version.into_trait_ref().await?).await?; compute_update_stream( - &resource, + resource, version_state, get_content, TransientInstance::new(sx), @@ -291,7 +279,7 @@ impl UpdateStream { } impl Stream for UpdateStream { - type Item = Result; + type Item = Result>; fn poll_next( self: Pin<&mut Self>, @@ -306,41 +294,41 @@ impl Stream for UpdateStream { pub enum UpdateStreamItem { NotFound, Found { - update: UpdateReadRef, - issues: Vec, + update: ReadRef, + issues: Vec>, }, } #[turbo_tasks::value(serialization = "none")] struct FatalStreamIssue { - description: StringVc, + description: Vc, resource: String, } #[turbo_tasks::value_impl] impl Issue for FatalStreamIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Fatal.into() } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { - ServerFileSystemVc::new().root().join(&self.resource) + fn context(&self) -> Vc { + ServerFileSystem::new().root().join(self.resource.clone()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("websocket".to_string()) + fn category(&self) -> Vc { + Vc::cell("websocket".to_string()) } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Fatal error while getting content to stream".to_string()) + fn title(&self) -> Vc { + Vc::cell("Fatal error while getting content to stream".to_string()) } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.description } } diff --git a/crates/turbopack-dev/src/chunking_context.rs b/crates/turbopack-dev/src/chunking_context.rs index 1cdab38e0581c9..f8db4be04e0e74 100644 --- a/crates/turbopack-dev/src/chunking_context.rs +++ b/crates/turbopack-dev/src/chunking_context.rs @@ -2,31 +2,25 @@ use anyhow::Result; use indexmap::IndexSet; use turbo_tasks::{ graph::{GraphTraversal, ReverseTopological}, - primitives::{BoolVc, StringVc}, - TryJoinIterExt, Value, + TryJoinIterExt, Value, Vc, }; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetVc, AssetsVc}, - chunk::{ - Chunk, ChunkVc, ChunkableAsset, ChunkingContext, ChunkingContextVc, ChunksVc, - EvaluatableAssetsVc, - }, - environment::EnvironmentVc, - ident::AssetIdentVc, -}; -use turbopack_css::chunk::{CssChunkVc, CssChunksVc}; -use turbopack_ecmascript::chunk::{ - EcmascriptChunkVc, EcmascriptChunkingContext, EcmascriptChunkingContextVc, EcmascriptChunksVc, + asset::{Asset, Assets}, + chunk::{Chunk, ChunkableAsset, ChunkingContext, Chunks, EvaluatableAssets}, + environment::Environment, + ident::AssetIdent, }; +use turbopack_css::chunk::CssChunk; +use turbopack_ecmascript::chunk::{EcmascriptChunk, EcmascriptChunkingContext}; use turbopack_ecmascript_runtime::RuntimeType; use crate::{ css::optimize::optimize_css_chunks, ecmascript::{ - chunk::EcmascriptDevChunkVc, - evaluate::chunk::EcmascriptDevEvaluateChunkVc, - list::asset::{EcmascriptDevChunkListSource, EcmascriptDevChunkListVc}, + chunk::EcmascriptDevChunk, + evaluate::chunk::EcmascriptDevEvaluateChunk, + list::asset::{EcmascriptDevChunkList, EcmascriptDevChunkListSource}, optimize::optimize_ecmascript_chunks, }, }; @@ -61,8 +55,8 @@ impl DevChunkingContextBuilder { self } - pub fn build(self) -> ChunkingContextVc { - DevChunkingContextVc::new(Value::new(self.context)).into() + pub fn build(self) -> Vc> { + Vc::upcast(DevChunkingContext::new(Value::new(self.context))) } } @@ -76,34 +70,34 @@ impl DevChunkingContextBuilder { pub struct DevChunkingContext { /// This path get stripped off of chunk paths before generating output asset /// paths. - context_path: FileSystemPathVc, + context_path: Vc, /// This path is used to compute the url to request chunks or assets from - output_root: FileSystemPathVc, + output_root: Vc, /// Chunks are placed at this path - chunk_root_path: FileSystemPathVc, + chunk_root_path: Vc, /// Chunks reference source maps assets reference_chunk_source_maps: bool, /// Css chunks reference source maps assets reference_css_chunk_source_maps: bool, /// Static assets are placed at this path - asset_root_path: FileSystemPathVc, + asset_root_path: Vc, /// Layer name within this context layer: Option, /// Enable HMR for this chunking enable_hot_module_replacement: bool, /// The environment chunks will be evaluated in. - environment: EnvironmentVc, + environment: Vc, /// The kind of runtime to include in the output. runtime_type: RuntimeType, } -impl DevChunkingContextVc { +impl DevChunkingContext { pub fn builder( - context_path: FileSystemPathVc, - output_root: FileSystemPathVc, - chunk_root_path: FileSystemPathVc, - asset_root_path: FileSystemPathVc, - environment: EnvironmentVc, + context_path: Vc, + output_root: Vc, + chunk_root_path: Vc, + asset_root_path: Vc, + environment: Vc, ) -> DevChunkingContextBuilder { DevChunkingContextBuilder { context: DevChunkingContext { @@ -133,40 +127,54 @@ impl DevChunkingContext { } #[turbo_tasks::value_impl] -impl DevChunkingContextVc { +impl DevChunkingContext { #[turbo_tasks::function] - fn new(this: Value) -> Self { + fn new(this: Value) -> Vc { this.into_value().cell() } #[turbo_tasks::function] fn generate_evaluate_chunk( - self_vc: DevChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> AssetVc { - EcmascriptDevEvaluateChunkVc::new(self_vc, entry_chunk, other_chunks, evaluatable_assets) - .into() + self: Vc, + entry_chunk: Vc>, + other_chunks: Vc, + evaluatable_assets: Vc, + ) -> Vc> { + Vc::upcast(EcmascriptDevEvaluateChunk::new( + self, + entry_chunk, + other_chunks, + evaluatable_assets, + )) } #[turbo_tasks::function] fn generate_chunk_list_register_chunk( - self_vc: DevChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, + self: Vc, + entry_chunk: Vc>, + other_chunks: Vc, source: Value, - ) -> AssetVc { - EcmascriptDevChunkListVc::new(self_vc, entry_chunk, other_chunks, source).into() + ) -> Vc> { + Vc::upcast(EcmascriptDevChunkList::new( + self, + entry_chunk, + other_chunks, + source, + )) } #[turbo_tasks::function] - async fn generate_chunk(self, chunk: ChunkVc) -> Result { + async fn generate_chunk( + self: Vc, + chunk: Vc>, + ) -> Result>> { Ok( - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(chunk).await? { - EcmascriptDevChunkVc::new(self, ecmascript_chunk).into() + if let Some(ecmascript_chunk) = + Vc::try_resolve_downcast_type::(chunk).await? + { + Vc::upcast(EcmascriptDevChunk::new(self, ecmascript_chunk)) } else { - chunk.into() + Vc::upcast(chunk) }, ) } @@ -175,37 +183,41 @@ impl DevChunkingContextVc { #[turbo_tasks::value_impl] impl ChunkingContext for DevChunkingContext { #[turbo_tasks::function] - fn context_path(&self) -> FileSystemPathVc { + fn context_path(&self) -> Vc { self.context_path } #[turbo_tasks::function] - fn output_root(&self) -> FileSystemPathVc { + fn output_root(&self) -> Vc { self.output_root } #[turbo_tasks::function] - fn environment(&self) -> EnvironmentVc { + fn environment(&self) -> Vc { self.environment } #[turbo_tasks::function] - async fn chunk_path(&self, ident: AssetIdentVc, extension: &str) -> Result { + async fn chunk_path( + &self, + ident: Vc, + extension: String, + ) -> Result> { let root_path = self.chunk_root_path; let root_path = if let Some(layer) = self.layer.as_deref() { - root_path.join(layer) + root_path.join(layer.to_string()) } else { root_path }; let name = ident.output_name(self.context_path, extension).await?; - Ok(root_path.join(&name)) + Ok(root_path.join(name.clone_value())) } #[turbo_tasks::function] - async fn reference_chunk_source_maps(&self, chunk: AssetVc) -> Result { + async fn reference_chunk_source_maps(&self, chunk: Vc>) -> Result> { let mut source_maps = self.reference_chunk_source_maps; let path = chunk.ident().path().await?; - let extension = path.extension().unwrap_or_default(); + let extension = path.extension_ref().unwrap_or_default(); #[allow(clippy::single_match, reason = "future extensions")] match extension { ".css" => { @@ -213,32 +225,36 @@ impl ChunkingContext for DevChunkingContext { } _ => {} } - Ok(BoolVc::cell(source_maps)) + Ok(Vc::cell(source_maps)) } #[turbo_tasks::function] - async fn can_be_in_same_chunk(&self, asset_a: AssetVc, asset_b: AssetVc) -> Result { + async fn can_be_in_same_chunk( + &self, + asset_a: Vc>, + asset_b: Vc>, + ) -> Result> { let parent_dir = asset_a.ident().path().parent().await?; let path = asset_b.ident().path().await?; if let Some(rel_path) = parent_dir.get_path_to(&path) { if !rel_path.starts_with("node_modules/") && !rel_path.contains("/node_modules/") { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } - Ok(BoolVc::cell(false)) + Ok(Vc::cell(false)) } #[turbo_tasks::function] async fn asset_path( &self, - content_hash: &str, - original_asset_ident: AssetIdentVc, - ) -> Result { + content_hash: String, + original_asset_ident: Vc, + ) -> Result> { let source_path = original_asset_ident.path().await?; let basename = source_path.file_name(); - let asset_path = match source_path.extension() { + let asset_path = match source_path.extension_ref() { Some(ext) => format!( "{basename}.{content_hash}.{ext}", basename = &basename[..basename.len() - ext.len() - 1], @@ -249,53 +265,53 @@ impl ChunkingContext for DevChunkingContext { content_hash = &content_hash[..8] ), }; - Ok(self.asset_root_path.join(&asset_path)) + Ok(self.asset_root_path.join(asset_path)) } #[turbo_tasks::function] - fn is_hot_module_replacement_enabled(&self) -> BoolVc { - BoolVc::cell(self.enable_hot_module_replacement) + fn is_hot_module_replacement_enabled(&self) -> Vc { + Vc::cell(self.enable_hot_module_replacement) } #[turbo_tasks::function] - fn layer(&self) -> StringVc { - StringVc::cell(self.layer.clone().unwrap_or_default()) + fn layer(&self) -> Vc { + Vc::cell(self.layer.clone().unwrap_or_default()) } #[turbo_tasks::function] - async fn with_layer(self_vc: DevChunkingContextVc, layer: &str) -> Result { - let mut context = self_vc.await?.clone_value(); + async fn with_layer(self: Vc, layer: String) -> Result>> { + let mut context = self.await?.clone_value(); context.layer = (!layer.is_empty()).then(|| layer.to_string()); - Ok(DevChunkingContextVc::new(Value::new(context)).into()) + Ok(Vc::upcast(DevChunkingContext::new(Value::new(context)))) } #[turbo_tasks::function] - async fn chunk_group(self_vc: DevChunkingContextVc, entry_chunk: ChunkVc) -> Result { + async fn chunk_group(self: Vc, entry_chunk: Vc>) -> Result> { let parallel_chunks = get_parallel_chunks([entry_chunk]).await?; let optimized_chunks = get_optimized_chunks(parallel_chunks).await?; - let mut assets: Vec = optimized_chunks + let mut assets: Vec>> = optimized_chunks .await? .iter() - .map(|chunk| self_vc.generate_chunk(*chunk)) + .map(|chunk| self.generate_chunk(*chunk)) .collect(); - assets.push(self_vc.generate_chunk_list_register_chunk( + assets.push(self.generate_chunk_list_register_chunk( entry_chunk, - AssetsVc::cell(assets.clone()), + Vc::cell(assets.clone()), Value::new(EcmascriptDevChunkListSource::Dynamic), )); - Ok(AssetsVc::cell(assets)) + Ok(Vc::cell(assets)) } #[turbo_tasks::function] async fn evaluated_chunk_group( - self_vc: DevChunkingContextVc, - entry_chunk: ChunkVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> Result { + self: Vc, + entry_chunk: Vc>, + evaluatable_assets: Vc, + ) -> Result> { let evaluatable_assets_ref = evaluatable_assets.await?; let mut entry_assets: IndexSet<_> = evaluatable_assets_ref @@ -303,7 +319,7 @@ impl ChunkingContext for DevChunkingContext { .map({ move |evaluatable_asset| async move { evaluatable_asset - .as_root_chunk(self_vc.into()) + .as_root_chunk(Vc::upcast(self)) .resolve() .await } @@ -319,41 +335,41 @@ impl ChunkingContext for DevChunkingContext { let optimized_chunks = get_optimized_chunks(parallel_chunks).await?; - let mut assets: Vec = optimized_chunks + let mut assets: Vec>> = optimized_chunks .await? .iter() - .map(|chunk| self_vc.generate_chunk(*chunk)) + .map(|chunk| self.generate_chunk(*chunk)) .collect(); - let other_assets = AssetsVc::cell(assets.clone()); + let other_assets = Vc::cell(assets.clone()); - assets.push(self_vc.generate_chunk_list_register_chunk( + assets.push(self.generate_chunk_list_register_chunk( entry_chunk, other_assets, Value::new(EcmascriptDevChunkListSource::Entry), )); - assets.push(self_vc.generate_evaluate_chunk(entry_chunk, other_assets, evaluatable_assets)); + assets.push(self.generate_evaluate_chunk(entry_chunk, other_assets, evaluatable_assets)); - Ok(AssetsVc::cell(assets)) + Ok(Vc::cell(assets)) } } #[turbo_tasks::value_impl] impl EcmascriptChunkingContext for DevChunkingContext { #[turbo_tasks::function] - fn has_react_refresh(&self) -> BoolVc { - BoolVc::cell(true) + fn has_react_refresh(&self) -> Vc { + Vc::cell(true) } } -async fn get_parallel_chunks(entries: I) -> Result> +async fn get_parallel_chunks(entries: I) -> Result>>> where - I: IntoIterator, + I: IntoIterator>>, { Ok(ReverseTopological::new() .skip_duplicates() - .visit(entries, |chunk: ChunkVc| async move { + .visit(entries, |chunk: Vc>| async move { Ok(chunk .parallel_chunks() .await? @@ -368,35 +384,36 @@ where .into_iter()) } -async fn get_optimized_chunks(chunks: I) -> Result +async fn get_optimized_chunks(chunks: I) -> Result> where - I: IntoIterator, + I: IntoIterator>>, { let mut ecmascript_chunks = vec![]; let mut css_chunks = vec![]; let mut other_chunks = vec![]; for chunk in chunks.into_iter() { - if let Some(ecmascript_chunk) = EcmascriptChunkVc::resolve_from(&chunk).await? { + if let Some(ecmascript_chunk) = + Vc::try_resolve_downcast_type::(chunk).await? + { ecmascript_chunks.push(ecmascript_chunk); - } else if let Some(css_chunk) = CssChunkVc::resolve_from(&chunk).await? { + } else if let Some(css_chunk) = Vc::try_resolve_downcast_type::(chunk).await? { css_chunks.push(css_chunk); } else { other_chunks.push(chunk); } } - let ecmascript_chunks = - optimize_ecmascript_chunks(EcmascriptChunksVc::cell(ecmascript_chunks)).await?; - let css_chunks = optimize_css_chunks(CssChunksVc::cell(css_chunks)).await?; + let ecmascript_chunks = optimize_ecmascript_chunks(Vc::cell(ecmascript_chunks)).await?; + let css_chunks = optimize_css_chunks(Vc::cell(css_chunks)).await?; let chunks = ecmascript_chunks .iter() .copied() - .map(|chunk| chunk.as_chunk()) - .chain(css_chunks.iter().copied().map(|chunk| chunk.as_chunk())) + .map(Vc::upcast) + .chain(css_chunks.iter().copied().map(Vc::upcast)) .chain(other_chunks.into_iter()) .collect(); - Ok(ChunksVc::cell(chunks)) + Ok(Vc::cell(chunks)) } diff --git a/crates/turbopack-dev/src/css/optimize.rs b/crates/turbopack-dev/src/css/optimize.rs index e71aa0d6373f1a..cfb1946f079a4f 100644 --- a/crates/turbopack-dev/src/css/optimize.rs +++ b/crates/turbopack-dev/src/css/optimize.rs @@ -1,10 +1,10 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::{TryJoinIterExt, Value}; -use turbopack_css::chunk::{CssChunkPlaceablesVc, CssChunkVc, CssChunksVc}; +use turbo_tasks::{TryJoinIterExt, Value, Vc}; +use turbopack_css::chunk::{CssChunk, CssChunks}; #[turbo_tasks::function] -pub async fn optimize_css_chunks(chunks: CssChunksVc) -> Result { +pub async fn optimize_css_chunks(chunks: Vc) -> Result> { // The CSS optimizer works under the constraint that the order in which // CSS chunks are loaded must be preserved, as CSS rules // precedence is determined by the order in which they are @@ -21,9 +21,9 @@ pub async fn optimize_css_chunks(chunks: CssChunksVc) -> Result { } async fn merge_chunks( - first: CssChunkVc, - chunks: impl IntoIterator, -) -> Result { + first: Vc, + chunks: impl IntoIterator>, +) -> Result> { let chunks = chunks.into_iter().copied().try_join().await?; let main_entries = chunks .iter() @@ -33,9 +33,9 @@ async fn merge_chunks( .iter() .flat_map(|e| e.iter().copied()) .collect::>(); - Ok(CssChunkVc::new_normalized( + Ok(CssChunk::new_normalized( first.await?.context, - CssChunkPlaceablesVc::cell(main_entries.into_iter().collect()), + Vc::cell(main_entries.into_iter().collect()), Value::new(first.await?.availability_info), )) } @@ -45,7 +45,7 @@ async fn merge_chunks( const MAX_CHUNK_COUNT: usize = 20; /// Groups adjacent chunks into at most `MAX_CHUNK_COUNT` groups. -fn aggregate_adjacent_chunks(chunks: &[CssChunkVc]) -> Vec> { +fn aggregate_adjacent_chunks(chunks: &[Vc]) -> Vec>> { // Each of the resulting merged chunks will have `chunks_per_merged_chunk` // chunks in them, except for the first `chunks_mod` chunks, which will have // one more chunk. @@ -76,7 +76,7 @@ fn aggregate_adjacent_chunks(chunks: &[CssChunkVc]) -> Vec> { } /// Merges adjacent chunks into at most `MAX_CHUNK_COUNT` chunks. -async fn merge_adjacent_chunks(chunks_vc: CssChunksVc) -> Result { +async fn merge_adjacent_chunks(chunks_vc: Vc) -> Result> { let chunks = chunks_vc.await?; if chunks.len() <= MAX_CHUNK_COUNT { @@ -91,5 +91,5 @@ async fn merge_adjacent_chunks(chunks_vc: CssChunksVc) -> Result { .try_join() .await?; - Ok(CssChunksVc::cell(chunks)) + Ok(Vc::cell(chunks)) } diff --git a/crates/turbopack-dev/src/ecmascript/chunk.rs b/crates/turbopack-dev/src/ecmascript/chunk.rs index aa14726146ba5b..c677cfd1d15493 100644 --- a/crates/turbopack-dev/src/ecmascript/chunk.rs +++ b/crates/turbopack-dev/src/ecmascript/chunk.rs @@ -1,36 +1,31 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - chunk::{ - ChunkingContext, OutputChunk, OutputChunkRuntimeInfo, OutputChunkRuntimeInfoVc, - OutputChunkVc, - }, - ident::AssetIdentVc, - introspect::{Introspectable, IntrospectableChildrenVc, IntrospectableVc}, - reference::AssetReferencesVc, - source_map::{ - GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, - }, - version::{VersionedContent, VersionedContentVc}, + asset::{Asset, AssetContent}, + chunk::{ChunkingContext, OutputChunk, OutputChunkRuntimeInfo}, + ident::AssetIdent, + introspect::{Introspectable, IntrospectableChildren}, + reference::AssetReferences, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAssetReference}, + version::VersionedContent, }; -use turbopack_ecmascript::chunk::EcmascriptChunkVc; +use turbopack_ecmascript::chunk::EcmascriptChunk; -use crate::{ecmascript::content::EcmascriptDevChunkContentVc, DevChunkingContextVc}; +use crate::{ecmascript::content::EcmascriptDevChunkContent, DevChunkingContext}; /// Development Ecmascript chunk. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptDevChunk { - chunking_context: DevChunkingContextVc, - chunk: EcmascriptChunkVc, + chunking_context: Vc, + chunk: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkVc { - /// Creates a new [`EcmascriptDevChunkVc`]. +impl EcmascriptDevChunk { + /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub fn new(chunking_context: DevChunkingContextVc, chunk: EcmascriptChunkVc) -> Self { + pub fn new(chunking_context: Vc, chunk: Vc) -> Vc { EcmascriptDevChunk { chunking_context, chunk, @@ -42,15 +37,15 @@ impl EcmascriptDevChunkVc { #[turbo_tasks::value_impl] impl ValueToString for EcmascriptDevChunk { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("Ecmascript Dev Chunk".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Chunk".to_string())) } } #[turbo_tasks::value_impl] impl OutputChunk for EcmascriptDevChunk { #[turbo_tasks::function] - fn runtime_info(&self) -> OutputChunkRuntimeInfoVc { + fn runtime_info(&self) -> Vc { OutputChunkRuntimeInfo { included_ids: Some(self.chunk.entry_ids()), ..Default::default() @@ -60,16 +55,16 @@ impl OutputChunk for EcmascriptDevChunk { } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript dev chunk".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript dev chunk".to_string()) } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkVc { +impl EcmascriptDevChunk { #[turbo_tasks::function] - async fn own_content(self) -> Result { + async fn own_content(self: Vc) -> Result> { let this = self.await?; - Ok(EcmascriptDevChunkContentVc::new( + Ok(EcmascriptDevChunkContent::new( this.chunking_context, self, this.chunk.chunk_content(), @@ -80,14 +75,14 @@ impl EcmascriptDevChunkVc { #[turbo_tasks::value_impl] impl Asset for EcmascriptDevChunk { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { let ident = self.chunk.ident().with_modifier(modifier()); - AssetIdentVc::from_path(self.chunking_context.chunk_path(ident, ".js")) + AssetIdent::from_path(self.chunking_context.chunk_path(ident, ".js".to_string())) } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptDevChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let chunk_references = this.chunk.references().await?; let mut references = Vec::with_capacity(chunk_references.len() + 1); @@ -97,67 +92,68 @@ impl Asset for EcmascriptDevChunk { if *this .chunking_context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()); + references.push(Vc::upcast(SourceMapAssetReference::new(Vc::upcast(self)))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } #[turbo_tasks::function] - fn content(self_vc: EcmascriptDevChunkVc) -> AssetContentVc { - self_vc.own_content().content() + fn content(self: Vc) -> Vc { + self.own_content().content() } #[turbo_tasks::function] - fn versioned_content(self_vc: EcmascriptDevChunkVc) -> VersionedContentVc { - self_vc.own_content().into() + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.own_content()) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptDevChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptDevChunkVc) -> OptionSourceMapVc { - self_vc.own_content().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.own_content().generate_source_map() } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("dev ecmascript chunk".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("dev ecmascript chunk".to_string()) } #[turbo_tasks::function] -fn introspectable_details() -> StringVc { - StringVc::cell("generates a development ecmascript chunk".to_string()) +fn introspectable_details() -> Vc { + Vc::cell("generates a development ecmascript chunk".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for EcmascriptDevChunk { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(self_vc: EcmascriptDevChunkVc) -> StringVc { - self_vc.ident().to_string() + fn title(self: Vc) -> Vc { + self.ident().to_string() } #[turbo_tasks::function] - fn details(&self) -> StringVc { + fn details(&self) -> Vc { introspectable_details() } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let mut children = IndexSet::new(); - if let Some(chunk) = IntrospectableVc::resolve_from(self.chunk).await? { - children.insert((StringVc::cell("chunk".to_string()), chunk)); - } - Ok(IntrospectableChildrenVc::cell(children)) + let chunk = Vc::upcast::>(self.chunk) + .resolve() + .await?; + children.insert((Vc::cell("chunk".to_string()), chunk)); + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-dev/src/ecmascript/content.rs b/crates/turbopack-dev/src/ecmascript/content.rs index 6df7f43da5007f..90bc3dd07a4e6e 100644 --- a/crates/turbopack-dev/src/ecmascript/content.rs +++ b/crates/turbopack-dev/src/ecmascript/content.rs @@ -2,41 +2,41 @@ use std::io::Write; use anyhow::{bail, Result}; use indoc::writedoc; +use turbo_tasks::Vc; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc}, + asset::{Asset, AssetContent}, chunk::{ChunkingContext, ModuleId}, - code_builder::{CodeBuilder, CodeVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, + code_builder::{Code, CodeBuilder}, + source_map::{GenerateSourceMap, OptionSourceMap}, version::{ - MergeableVersionedContent, MergeableVersionedContentVc, UpdateVc, VersionVc, - VersionedContent, VersionedContentMergerVc, VersionedContentVc, + MergeableVersionedContent, Update, Version, VersionedContent, VersionedContentMerger, }, }; -use turbopack_ecmascript::{chunk::EcmascriptChunkContentVc, utils::StringifyJs}; +use turbopack_ecmascript::{chunk::EcmascriptChunkContent, utils::StringifyJs}; use super::{ - chunk::EcmascriptDevChunkVc, content_entry::EcmascriptDevChunkContentEntriesVc, - merged::merger::EcmascriptDevChunkContentMergerVc, version::EcmascriptDevChunkVersionVc, + chunk::EcmascriptDevChunk, content_entry::EcmascriptDevChunkContentEntries, + merged::merger::EcmascriptDevChunkContentMerger, version::EcmascriptDevChunkVersion, }; -use crate::DevChunkingContextVc; +use crate::DevChunkingContext; #[turbo_tasks::value(serialization = "none")] pub(super) struct EcmascriptDevChunkContent { - pub(super) entries: EcmascriptDevChunkContentEntriesVc, - pub(super) chunking_context: DevChunkingContextVc, - pub(super) chunk: EcmascriptDevChunkVc, + pub(super) entries: Vc, + pub(super) chunking_context: Vc, + pub(super) chunk: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkContentVc { +impl EcmascriptDevChunkContent { #[turbo_tasks::function] pub(crate) async fn new( - chunking_context: DevChunkingContextVc, - chunk: EcmascriptDevChunkVc, - content: EcmascriptChunkContentVc, - ) -> Result { - let entries = EcmascriptDevChunkContentEntriesVc::new(content) + chunking_context: Vc, + chunk: Vc, + content: Vc, + ) -> Result> { + let entries = EcmascriptDevChunkContentEntries::new(content) .resolve() .await?; Ok(EcmascriptDevChunkContent { @@ -49,11 +49,11 @@ impl EcmascriptDevChunkContentVc { } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkContentVc { +impl EcmascriptDevChunkContent { #[turbo_tasks::function] - pub(crate) async fn own_version(self) -> Result { + pub(crate) async fn own_version(self: Vc) -> Result> { let this = self.await?; - Ok(EcmascriptDevChunkVersionVc::new( + Ok(EcmascriptDevChunkVersion::new( this.chunking_context.output_root(), this.chunk.ident().path(), this.entries, @@ -61,7 +61,7 @@ impl EcmascriptDevChunkContentVc { } #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { let this = self.await?; let output_root = this.chunking_context.output_root().await?; let chunk_path = this.chunk.ident().path().await?; @@ -111,18 +111,20 @@ impl EcmascriptDevChunkContentVc { #[turbo_tasks::value_impl] impl VersionedContent for EcmascriptDevChunkContent { #[turbo_tasks::function] - async fn content(self_vc: EcmascriptDevChunkContentVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } #[turbo_tasks::function] - fn version(self_vc: EcmascriptDevChunkContentVc) -> VersionVc { - self_vc.own_version().into() + fn version(self: Vc) -> Vc> { + Vc::upcast(self.own_version()) } #[turbo_tasks::function] - fn update(_self_vc: EcmascriptDevChunkContentVc, _from_version: VersionVc) -> Result { + fn update(self: Vc, _from_version: Vc>) -> Result> { bail!("EcmascriptDevChunkContent is not updateable") } } @@ -130,23 +132,23 @@ impl VersionedContent for EcmascriptDevChunkContent { #[turbo_tasks::value_impl] impl MergeableVersionedContent for EcmascriptDevChunkContent { #[turbo_tasks::function] - fn get_merger(&self) -> VersionedContentMergerVc { - EcmascriptDevChunkContentMergerVc::new().into() + fn get_merger(&self) -> Vc> { + Vc::upcast(EcmascriptDevChunkContentMerger::new()) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptDevChunkContent { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptDevChunkContentVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } #[turbo_tasks::function] - async fn by_section(&self, section: &str) -> Result { + async fn by_section(&self, section: String) -> Result> { // Weirdly, the ContentSource will have already URL decoded the ModuleId, and we // can't reparse that via serde. - if let Ok(id) = ModuleId::parse(section) { + if let Ok(id) = ModuleId::parse(§ion) { for (entry_id, entry) in self.entries.await?.iter() { if id == **entry_id { let sm = entry.code.generate_source_map(); @@ -155,6 +157,6 @@ impl GenerateSourceMap for EcmascriptDevChunkContent { } } - Ok(OptionSourceMapVc::cell(None)) + Ok(Vc::cell(None)) } } diff --git a/crates/turbopack-dev/src/ecmascript/content_entry.rs b/crates/turbopack-dev/src/ecmascript/content_entry.rs index 51b6bd6652b38e..60f841a9469bae 100644 --- a/crates/turbopack-dev/src/ecmascript/content_entry.rs +++ b/crates/turbopack-dev/src/ecmascript/content_entry.rs @@ -3,36 +3,33 @@ use std::io::Write as _; use anyhow::Result; use indexmap::IndexMap; use tracing::{info_span, Instrument}; -use turbo_tasks::{ - primitives::{StringVc, U64Vc}, - TryJoinIterExt, Value, ValueToString, -}; +use turbo_tasks::{ReadRef, TryJoinIterExt, Value, ValueToString, Vc}; use turbopack_core::{ - chunk::{availability_info::AvailabilityInfo, ChunkItem, ModuleIdReadRef}, - code_builder::{CodeBuilder, CodeVc}, + chunk::{availability_info::AvailabilityInfo, ChunkItem, ModuleId}, + code_builder::{Code, CodeBuilder}, error::PrettyPrintError, - issue::{code_gen::CodeGenerationIssue, IssueSeverity}, + issue::{code_gen::CodeGenerationIssue, IssueExt, IssueSeverity}, }; use turbopack_ecmascript::chunk::{ - EcmascriptChunkContentVc, EcmascriptChunkItem, EcmascriptChunkItemVc, + EcmascriptChunkContent, EcmascriptChunkItem, EcmascriptChunkItemExt, }; /// A chunk item's content entry. /// -/// Instead of storing the [`EcmascriptChunkItemVc`] itself from which `code` -/// and `hash` are derived, we store `Vc`s directly. This avoids creating tasks -/// in a hot loop when iterating over thousands of entries when computing -/// updates. +/// Instead of storing the [`Vc>`] itself from +/// which `code` and `hash` are derived, we store `Vc`s directly. This avoids +/// creating tasks in a hot loop when iterating over thousands of entries when +/// computing updates. #[turbo_tasks::value] #[derive(Debug)] pub(super) struct EcmascriptDevChunkContentEntry { - pub code: CodeVc, - pub hash: U64Vc, + pub code: Vc, + pub hash: Vc, } impl EcmascriptDevChunkContentEntry { pub async fn new( - chunk_item: EcmascriptChunkItemVc, + chunk_item: Vc>, availability_info: AvailabilityInfo, ) -> Result { let code = chunk_item @@ -48,15 +45,15 @@ impl EcmascriptDevChunkContentEntry { #[turbo_tasks::value(transparent)] pub(super) struct EcmascriptDevChunkContentEntries( - IndexMap, + IndexMap, EcmascriptDevChunkContentEntry>, ); #[turbo_tasks::value_impl] -impl EcmascriptDevChunkContentEntriesVc { +impl EcmascriptDevChunkContentEntries { #[turbo_tasks::function] pub async fn new( - chunk_content: EcmascriptChunkContentVc, - ) -> Result { + chunk_content: Vc, + ) -> Result> { let chunk_content = chunk_content.await?; let availability_info = chunk_content.availability_info; @@ -81,15 +78,15 @@ impl EcmascriptDevChunkContentEntriesVc { .into_iter() .collect(); - Ok(EcmascriptDevChunkContentEntriesVc::cell(entries)) + Ok(Vc::cell(entries)) } } #[turbo_tasks::function] async fn item_code( - item: EcmascriptChunkItemVc, + item: Vc>, availability_info: Value, -) -> Result { +) -> Result> { Ok( match item .content_with_availability_info(availability_info) @@ -107,14 +104,14 @@ async fn item_code( )); let error_message = format!("{}", PrettyPrintError(&error)); let js_error_message = serde_json::to_string(&error_message)?; - let issue = CodeGenerationIssue { + CodeGenerationIssue { severity: IssueSeverity::Error.cell(), path: item.asset_ident().path(), - title: StringVc::cell("Code generation for chunk item errored".to_string()), - message: StringVc::cell(error_message), + title: Vc::cell("Code generation for chunk item errored".to_string()), + message: Vc::cell(error_message), } - .cell(); - issue.as_issue().emit(); + .cell() + .emit(); let mut code = CodeBuilder::default(); code += "(() => {{\n\n"; writeln!(code, "throw new Error({error});", error = &js_error_message)?; diff --git a/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs b/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs index 3dd90e16f9ddc6..6a4d916a417798 100644 --- a/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs +++ b/crates/turbopack-dev/src/ecmascript/evaluate/chunk.rs @@ -3,49 +3,45 @@ use std::io::Write; use anyhow::{bail, Result}; use indoc::writedoc; use serde::Serialize; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{ReadRef, TryJoinIterExt, Value, ValueToString, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ - ChunkDataVc, ChunkVc, ChunkingContext, ChunksDataVc, EvaluatableAssetsVc, ModuleIdReadRef, - }, - code_builder::{CodeBuilder, CodeVc}, - ident::AssetIdentVc, - reference::AssetReferencesVc, - source_map::{ - GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc, SourceMapAssetReferenceVc, - }, + asset::{Asset, AssetContent, Assets}, + chunk::{Chunk, ChunkData, ChunkingContext, ChunksData, EvaluatableAssets, ModuleId}, + code_builder::{Code, CodeBuilder}, + ident::AssetIdent, + reference::AssetReferences, + source_map::{GenerateSourceMap, OptionSourceMap, SourceMapAssetReference}, }; use turbopack_ecmascript::{ - chunk::{EcmascriptChunkData, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, + chunk::{EcmascriptChunkData, EcmascriptChunkItemExt, EcmascriptChunkPlaceable}, utils::StringifyJs, }; use turbopack_ecmascript_runtime::RuntimeType; -use crate::DevChunkingContextVc; +use crate::DevChunkingContext; /// An Ecmascript chunk that: /// * Contains the Turbopack dev runtime code; and /// * Evaluates a list of runtime entries. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptDevEvaluateChunk { - chunking_context: DevChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, + chunking_context: Vc, + entry_chunk: Vc>, + other_chunks: Vc, + evaluatable_assets: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptDevEvaluateChunkVc { - /// Creates a new [`EcmascriptDevEvaluateChunkVc`]. +impl EcmascriptDevEvaluateChunk { + /// Creates a new [`Vc`]. #[turbo_tasks::function] pub fn new( - chunking_context: DevChunkingContextVc, - entry_chunk: ChunkVc, - other_chunks: AssetsVc, - evaluatable_assets: EvaluatableAssetsVc, - ) -> Self { + chunking_context: Vc, + entry_chunk: Vc>, + other_chunks: Vc, + evaluatable_assets: Vc, + ) -> Vc { EcmascriptDevEvaluateChunk { chunking_context, entry_chunk, @@ -56,16 +52,16 @@ impl EcmascriptDevEvaluateChunkVc { } #[turbo_tasks::function] - async fn chunks_data(self) -> Result { + async fn chunks_data(self: Vc) -> Result> { let this = self.await?; - Ok(ChunkDataVc::from_assets( + Ok(ChunkData::from_assets( this.chunking_context.output_root(), this.other_chunks, )) } #[turbo_tasks::function] - async fn code(self) -> Result { + async fn code(self: Vc) -> Result> { let this = self.await?; let environment = this.chunking_context.environment(); @@ -95,11 +91,13 @@ impl EcmascriptDevEvaluateChunkVc { .map({ let chunking_context = this.chunking_context; move |entry| async move { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(entry).await? + if let Some(placeable) = + Vc::try_resolve_sidecast::>(*entry) + .await? { Ok(Some( placeable - .as_chunk_item(chunking_context.into()) + .as_chunk_item(Vc::upcast(chunking_context)) .id() .await?, )) @@ -154,27 +152,27 @@ impl EcmascriptDevEvaluateChunkVc { write!(code, "\n\n//# sourceMappingURL={}.map", filename)?; } - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } } #[turbo_tasks::value_impl] impl ValueToString for EcmascriptDevEvaluateChunk { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("Ecmascript Dev Evaluate Chunk".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Evaluate Chunk".to_string())) } } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript dev evaluate chunk".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript dev evaluate chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for EcmascriptDevEvaluateChunk { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { let mut ident = self.entry_chunk.ident().await?.clone_value(); ident.add_modifier(modifier()); @@ -190,44 +188,46 @@ impl Asset for EcmascriptDevEvaluateChunk { ident.add_modifier(chunk.ident().to_string()); } - let ident = AssetIdentVc::new(Value::new(ident)); - Ok(AssetIdentVc::from_path( - self.chunking_context.chunk_path(ident, ".js"), + let ident = AssetIdent::new(Value::new(ident)); + Ok(AssetIdent::from_path( + self.chunking_context.chunk_path(ident, ".js".to_string()), )) } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptDevEvaluateChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let mut references = Vec::new(); if *this .chunking_context - .reference_chunk_source_maps(self_vc.into()) + .reference_chunk_source_maps(Vc::upcast(self)) .await? { - references.push(SourceMapAssetReferenceVc::new(self_vc.into()).into()); + references.push(Vc::upcast(SourceMapAssetReference::new(Vc::upcast(self)))); } - for chunk_data in &*self_vc.chunks_data().await? { + for chunk_data in &*self.chunks_data().await? { references.extend(chunk_data.references().await?.iter().copied()); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } #[turbo_tasks::function] - async fn content(self_vc: EcmascriptDevEvaluateChunkVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } } #[turbo_tasks::value_impl] impl GenerateSourceMap for EcmascriptDevEvaluateChunk { #[turbo_tasks::function] - fn generate_source_map(self_vc: EcmascriptDevEvaluateChunkVc) -> OptionSourceMapVc { - self_vc.code().generate_source_map() + fn generate_source_map(self: Vc) -> Vc { + self.code().generate_source_map() } } @@ -241,5 +241,5 @@ struct EcmascriptDevChunkRuntimeParams<'a, T> { /// instantiated. other_chunks: &'a [T], /// List of module IDs that this chunk should instantiate when executed. - runtime_module_ids: Vec, + runtime_module_ids: Vec>, } diff --git a/crates/turbopack-dev/src/ecmascript/list/asset.rs b/crates/turbopack-dev/src/ecmascript/list/asset.rs index bd41f536552142..75dd5ce41a08a6 100644 --- a/crates/turbopack-dev/src/ecmascript/list/asset.rs +++ b/crates/turbopack-dev/src/ecmascript/list/asset.rs @@ -1,16 +1,16 @@ use anyhow::Result; use serde::Serialize; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ChunkVc, ChunkingContext}, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, - version::{VersionedContent, VersionedContentVc}, + asset::{Asset, AssetContent, Assets}, + chunk::{Chunk, ChunkingContext}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, + version::VersionedContent, }; -use super::content::EcmascriptDevChunkListContentVc; -use crate::DevChunkingContextVc; +use super::content::EcmascriptDevChunkListContent; +use crate::DevChunkingContext; /// An asset that represents a list of chunks that exist together in a chunk /// group, and should be *updated* together. @@ -25,22 +25,22 @@ use crate::DevChunkingContextVc; /// * changing a chunk's path. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptDevChunkList { - pub(super) chunking_context: DevChunkingContextVc, - pub(super) entry_chunk: ChunkVc, - pub(super) chunks: AssetsVc, + pub(super) chunking_context: Vc, + pub(super) entry_chunk: Vc>, + pub(super) chunks: Vc, pub(super) source: EcmascriptDevChunkListSource, } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkListVc { - /// Creates a new [`EcmascriptDevChunkListVc`]. +impl EcmascriptDevChunkList { + /// Creates a new [`Vc`]. #[turbo_tasks::function] pub fn new( - chunking_context: DevChunkingContextVc, - entry_chunk: ChunkVc, - chunks: AssetsVc, + chunking_context: Vc, + entry_chunk: Vc>, + chunks: Vc, source: Value, - ) -> Self { + ) -> Vc { EcmascriptDevChunkList { chunking_context, entry_chunk, @@ -51,33 +51,33 @@ impl EcmascriptDevChunkListVc { } #[turbo_tasks::function] - fn own_content(self) -> EcmascriptDevChunkListContentVc { - EcmascriptDevChunkListContentVc::new(self) + fn own_content(self: Vc) -> Vc { + EcmascriptDevChunkListContent::new(self) } } #[turbo_tasks::value_impl] impl ValueToString for EcmascriptDevChunkList { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("Ecmascript Dev Chunk List".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Chunk List".to_string())) } } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript dev chunk list".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript dev chunk list".to_string()) } #[turbo_tasks::function] -fn chunk_list_chunk_reference_description() -> StringVc { - StringVc::cell("chunk list chunk".to_string()) +fn chunk_list_chunk_reference_description() -> Vc { + Vc::cell("chunk list chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for EcmascriptDevChunkList { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { let mut ident = self.entry_chunk.ident().await?.clone_value(); ident.add_modifier(modifier()); @@ -86,34 +86,36 @@ impl Asset for EcmascriptDevChunkList { // ident, because it must remain stable whenever a chunk is added or // removed from the list. - let ident = AssetIdentVc::new(Value::new(ident)); - Ok(AssetIdentVc::from_path( - self.chunking_context.chunk_path(ident, ".js"), + let ident = AssetIdent::new(Value::new(ident)); + Ok(AssetIdent::from_path( + self.chunking_context.chunk_path(ident, ".js".to_string()), )) } #[turbo_tasks::function] - async fn references(&self) -> Result { - Ok(AssetReferencesVc::cell( + async fn references(&self) -> Result> { + Ok(Vc::cell( self.chunks .await? .iter() .map(|chunk| { - SingleAssetReferenceVc::new(*chunk, chunk_list_chunk_reference_description()) - .into() + Vc::upcast(SingleAssetReference::new( + *chunk, + chunk_list_chunk_reference_description(), + )) }) .collect(), )) } #[turbo_tasks::function] - fn content(self_vc: EcmascriptDevChunkListVc) -> AssetContentVc { - self_vc.own_content().content() + fn content(self: Vc) -> Vc { + self.own_content().content() } #[turbo_tasks::function] - fn versioned_content(self_vc: EcmascriptDevChunkListVc) -> VersionedContentVc { - self_vc.own_content().into() + fn versioned_content(self: Vc) -> Vc> { + Vc::upcast(self.own_content()) } } diff --git a/crates/turbopack-dev/src/ecmascript/list/content.rs b/crates/turbopack-dev/src/ecmascript/list/content.rs index 01e69b0bc47160..320b181f0a3dc4 100644 --- a/crates/turbopack-dev/src/ecmascript/list/content.rs +++ b/crates/turbopack-dev/src/ecmascript/list/content.rs @@ -4,38 +4,37 @@ use anyhow::{Context, Result}; use indexmap::IndexMap; use indoc::writedoc; use serde::Serialize; -use turbo_tasks::{IntoTraitRef, TryJoinIterExt}; +use turbo_tasks::{IntoTraitRef, TryJoinIterExt, Vc}; use turbo_tasks_fs::File; use turbopack_core::{ - asset::{Asset, AssetContentVc}, + asset::{Asset, AssetContent}, chunk::ChunkingContext, - code_builder::{CodeBuilder, CodeVc}, + code_builder::{Code, CodeBuilder}, version::{ - MergeableVersionedContent, MergeableVersionedContentVc, UpdateVc, VersionVc, - VersionedContent, VersionedContentMerger, VersionedContentVc, VersionedContentsVc, + MergeableVersionedContent, Update, Version, VersionedContent, VersionedContentMerger, }, }; use turbopack_ecmascript::utils::StringifyJs; use super::{ - asset::{EcmascriptDevChunkListSource, EcmascriptDevChunkListVc}, + asset::{EcmascriptDevChunkList, EcmascriptDevChunkListSource}, update::update_chunk_list, - version::{EcmascriptDevChunkListVersion, EcmascriptDevChunkListVersionVc}, + version::EcmascriptDevChunkListVersion, }; /// Contents of an [`EcmascriptDevChunkList`]. #[turbo_tasks::value] pub(super) struct EcmascriptDevChunkListContent { chunk_list_path: String, - pub(super) chunks_contents: IndexMap, + pub(super) chunks_contents: IndexMap>>, source: EcmascriptDevChunkListSource, } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkListContentVc { +impl EcmascriptDevChunkListContent { /// Creates a new [`EcmascriptDevChunkListContent`]. #[turbo_tasks::function] - pub async fn new(chunk_list: EcmascriptDevChunkListVc) -> Result { + pub async fn new(chunk_list: Vc) -> Result> { let chunk_list_ref = chunk_list.await?; let output_root = chunk_list_ref.chunking_context.output_root().await?; Ok(EcmascriptDevChunkListContent { @@ -70,7 +69,7 @@ impl EcmascriptDevChunkListContentVc { /// Computes the version of this content. #[turbo_tasks::function] - pub async fn version(self) -> Result { + pub async fn version(self: Vc) -> Result> { let this = self.await?; let mut by_merger = IndexMap::<_, Vec<_>>::new(); @@ -78,7 +77,8 @@ impl EcmascriptDevChunkListContentVc { for (chunk_path, chunk_content) in &this.chunks_contents { if let Some(mergeable) = - MergeableVersionedContentVc::resolve_from(chunk_content).await? + Vc::try_resolve_sidecast::>(*chunk_content) + .await? { let merger = mergeable.get_merger().resolve().await?; by_merger.entry(merger).or_default().push(*chunk_content); @@ -98,7 +98,7 @@ impl EcmascriptDevChunkListContentVc { Ok(( merger, merger - .merge(VersionedContentsVc::cell(contents)) + .merge(Vc::cell(contents)) .version() .into_trait_ref() .await?, @@ -114,7 +114,7 @@ impl EcmascriptDevChunkListContentVc { } #[turbo_tasks::function] - pub(super) async fn code(self) -> Result { + pub(super) async fn code(self: Vc) -> Result> { let this = self.await?; let params = EcmascriptDevChunkListParams { @@ -141,26 +141,28 @@ impl EcmascriptDevChunkListContentVc { StringifyJs(¶ms), )?; - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } } #[turbo_tasks::value_impl] impl VersionedContent for EcmascriptDevChunkListContent { #[turbo_tasks::function] - async fn content(self_vc: EcmascriptDevChunkListContentVc) -> Result { - let code = self_vc.code().await?; - Ok(File::from(code.source_code().clone()).into()) + async fn content(self: Vc) -> Result> { + let code = self.code().await?; + Ok(AssetContent::file( + File::from(code.source_code().clone()).into(), + )) } #[turbo_tasks::function] - fn version(self_vc: EcmascriptDevChunkListContentVc) -> VersionVc { - self_vc.version().into() + fn version(self: Vc) -> Vc> { + Vc::upcast(self.version()) } #[turbo_tasks::function] - fn update(self_vc: EcmascriptDevChunkListContentVc, from_version: VersionVc) -> UpdateVc { - update_chunk_list(self_vc, from_version) + fn update(self: Vc, from_version: Vc>) -> Vc { + update_chunk_list(self, from_version) } } diff --git a/crates/turbopack-dev/src/ecmascript/list/update.rs b/crates/turbopack-dev/src/ecmascript/list/update.rs index 251dcc5b0cb205..87284f950c7552 100644 --- a/crates/turbopack-dev/src/ecmascript/list/update.rs +++ b/crates/turbopack-dev/src/ecmascript/list/update.rs @@ -3,13 +3,13 @@ use std::sync::Arc; use anyhow::Result; use indexmap::IndexMap; use serde::Serialize; -use turbo_tasks::{IntoTraitRef, TraitRef}; +use turbo_tasks::{IntoTraitRef, TraitRef, Vc}; use turbopack_core::version::{ - MergeableVersionedContent, MergeableVersionedContentVc, PartialUpdate, TotalUpdate, Update, - UpdateVc, VersionVc, VersionedContent, VersionedContentMerger, VersionedContentsVc, + MergeableVersionedContent, PartialUpdate, TotalUpdate, Update, Version, VersionedContent, + VersionedContentMerger, }; -use super::{content::EcmascriptDevChunkListContentVc, version::EcmascriptDevChunkListVersionVc}; +use super::{content::EcmascriptDevChunkListContent, version::EcmascriptDevChunkListVersion}; /// Update of a chunk list from one version to another. #[derive(Serialize)] @@ -50,27 +50,31 @@ impl<'a> ChunkListUpdate<'a> { /// Computes the update of a chunk list from one version to another. #[turbo_tasks::function] pub(super) async fn update_chunk_list( - content: EcmascriptDevChunkListContentVc, - from_version: VersionVc, -) -> Result { + content: Vc, + from_version: Vc>, +) -> Result> { let to_version = content.version(); - let from_version = - if let Some(from) = EcmascriptDevChunkListVersionVc::resolve_from(from_version).await? { - from - } else { - // It's likely `from_version` is `NotFoundVersion`. - return Ok(Update::Total(TotalUpdate { - to: to_version.as_version().into_trait_ref().await?, - }) - .cell()); - }; + let from_version = if let Some(from) = + Vc::try_resolve_downcast_type::(from_version).await? + { + from + } else { + // It's likely `from_version` is `NotFoundVersion`. + return Ok(Update::Total(TotalUpdate { + to: Vc::upcast::>(to_version) + .into_trait_ref() + .await?, + }) + .cell()); + }; let to = to_version.await?; let from = from_version.await?; // When to and from point to the same value we can skip comparing them. - // This will happen since `TraitRef::cell` will not clone the value, - // but only make the cell point to the same immutable value (Arc). + // This will happen since `TraitRef>>::cell` will not clone + // the value, but only make the cell point to the same immutable value + // (Arc). if from.ptr_eq(&to) { return Ok(Update::None.cell()); } @@ -88,7 +92,9 @@ pub(super) async fn update_chunk_list( let mut by_path = IndexMap::<_, _>::new(); for (chunk_path, chunk_content) in &content.chunks_contents { - if let Some(mergeable) = MergeableVersionedContentVc::resolve_from(chunk_content).await? { + if let Some(mergeable) = + Vc::try_resolve_sidecast::>(*chunk_content).await? + { let merger = mergeable.get_merger().resolve().await?; by_merger.entry(merger).or_default().push(*chunk_content); } else { @@ -131,7 +137,7 @@ pub(super) async fn update_chunk_list( for (merger, chunks_contents) in by_merger { if let Some(from_version) = from.by_merger.get(&merger) { - let content = merger.merge(VersionedContentsVc::cell(chunks_contents)); + let content = merger.merge(Vc::cell(chunks_contents)); let chunk_update = content.update(TraitRef::cell(from_version.clone())).await?; @@ -141,7 +147,9 @@ pub(super) async fn update_chunk_list( // the update. Update::Total(_) => { return Ok(Update::Total(TotalUpdate { - to: to_version.as_version().into_trait_ref().await?, + to: Vc::upcast::>(to_version) + .into_trait_ref() + .await?, }) .cell()); } @@ -158,7 +166,9 @@ pub(super) async fn update_chunk_list( Update::None } else { Update::Partial(PartialUpdate { - to: to_version.as_version().into_trait_ref().await?, + to: Vc::upcast::>(to_version) + .into_trait_ref() + .await?, instruction: Arc::new(serde_json::to_value(&update)?), }) }; diff --git a/crates/turbopack-dev/src/ecmascript/list/version.rs b/crates/turbopack-dev/src/ecmascript/list/version.rs index 1c787a7f49d09f..d13458fad92a73 100644 --- a/crates/turbopack-dev/src/ecmascript/list/version.rs +++ b/crates/turbopack-dev/src/ecmascript/list/version.rs @@ -1,8 +1,10 @@ use anyhow::Result; use indexmap::IndexMap; -use turbo_tasks::{primitives::StringVc, TraitRef, TryJoinIterExt}; +use turbo_tasks::{TraitRef, TryJoinIterExt, Vc}; use turbo_tasks_hash::{encode_hex, Xxh3Hash64Hasher}; -use turbopack_core::version::{Version, VersionVc, VersionedContentMergerVc}; +use turbopack_core::version::{Version, VersionedContentMerger}; + +type VersionTraitRef = TraitRef>; /// The version of a [`EcmascriptDevChunkListContent`]. /// @@ -11,16 +13,16 @@ use turbopack_core::version::{Version, VersionVc, VersionedContentMergerVc}; pub(super) struct EcmascriptDevChunkListVersion { /// A map from chunk path to its version. #[turbo_tasks(trace_ignore)] - pub by_path: IndexMap>, + pub by_path: IndexMap, /// A map from chunk merger to the version of the merged contents of chunks. #[turbo_tasks(trace_ignore)] - pub by_merger: IndexMap>, + pub by_merger: IndexMap>, VersionTraitRef>, } #[turbo_tasks::value_impl] impl Version for EcmascriptDevChunkListVersion { #[turbo_tasks::function] - async fn id(&self) -> Result { + async fn id(&self) -> Result> { let by_path = { let mut by_path = self .by_path @@ -58,6 +60,6 @@ impl Version for EcmascriptDevChunkListVersion { } let hash = hasher.finish(); let hex_hash = encode_hex(hash); - Ok(StringVc::cell(hex_hash)) + Ok(Vc::cell(hex_hash)) } } diff --git a/crates/turbopack-dev/src/ecmascript/merged/content.rs b/crates/turbopack-dev/src/ecmascript/merged/content.rs index 3186b19531cc1f..a852ca7d90f9fc 100644 --- a/crates/turbopack-dev/src/ecmascript/merged/content.rs +++ b/crates/turbopack-dev/src/ecmascript/merged/content.rs @@ -1,14 +1,13 @@ use anyhow::{bail, Result}; -use turbo_tasks::TryJoinIterExt; +use turbo_tasks::{TryJoinIterExt, Vc}; use turbopack_core::{ - asset::AssetContentVc, - version::{UpdateVc, VersionVc, VersionedContent, VersionedContentVc}, + asset::AssetContent, + version::{Update, Version, VersionedContent}, }; use super::{ - super::content::EcmascriptDevChunkContentVc, - update::update_ecmascript_merged_chunk, - version::{EcmascriptDevMergedChunkVersion, EcmascriptDevMergedChunkVersionVc}, + super::content::EcmascriptDevChunkContent, update::update_ecmascript_merged_chunk, + version::EcmascriptDevMergedChunkVersion, }; /// Composite [`EcmascriptChunkContent`] that is the result of merging multiple @@ -18,13 +17,13 @@ use super::{ /// [`EcmascriptChunkContentMerger`]: super::merger::EcmascriptChunkContentMerger #[turbo_tasks::value(serialization = "none", shared)] pub(super) struct EcmascriptDevMergedChunkContent { - pub contents: Vec, + pub contents: Vec>, } #[turbo_tasks::value_impl] -impl EcmascriptDevMergedChunkContentVc { +impl EcmascriptDevMergedChunkContent { #[turbo_tasks::function] - pub async fn version(self) -> Result { + pub async fn version(self: Vc) -> Result> { Ok(EcmascriptDevMergedChunkVersion { versions: self .await? @@ -41,21 +40,18 @@ impl EcmascriptDevMergedChunkContentVc { #[turbo_tasks::value_impl] impl VersionedContent for EcmascriptDevMergedChunkContent { #[turbo_tasks::function] - fn content(_self_vc: EcmascriptDevMergedChunkContentVc) -> Result { + fn content(self: Vc) -> Result> { bail!("EcmascriptDevMergedChunkContent does not have content") } #[turbo_tasks::function] - fn version(self_vc: EcmascriptDevMergedChunkContentVc) -> VersionVc { - self_vc.version().into() + fn version(self: Vc) -> Vc> { + Vc::upcast(self.version()) } #[turbo_tasks::function] - async fn update( - self_vc: EcmascriptDevMergedChunkContentVc, - from_version: VersionVc, - ) -> Result { - Ok(update_ecmascript_merged_chunk(self_vc, from_version) + async fn update(self: Vc, from_version: Vc>) -> Result> { + Ok(update_ecmascript_merged_chunk(self, from_version) .await? .cell()) } diff --git a/crates/turbopack-dev/src/ecmascript/merged/merger.rs b/crates/turbopack-dev/src/ecmascript/merged/merger.rs index a97caa22332c12..f2ac81dfe6563c 100644 --- a/crates/turbopack-dev/src/ecmascript/merged/merger.rs +++ b/crates/turbopack-dev/src/ecmascript/merged/merger.rs @@ -1,12 +1,8 @@ use anyhow::{bail, Result}; -use turbo_tasks::TryJoinIterExt; -use turbopack_core::version::{ - VersionedContentMerger, VersionedContentMergerVc, VersionedContentVc, VersionedContentsVc, -}; +use turbo_tasks::{TryJoinIterExt, Vc}; +use turbopack_core::version::{VersionedContent, VersionedContentMerger, VersionedContents}; -use super::{ - super::content::EcmascriptDevChunkContentVc, content::EcmascriptDevMergedChunkContent, -}; +use super::{super::content::EcmascriptDevChunkContent, content::EcmascriptDevMergedChunkContent}; /// Merges multiple [`EcmascriptChunkContent`] into a single /// [`EcmascriptDevMergedChunkContent`]. This is useful for generating a single @@ -15,10 +11,10 @@ use super::{ pub(crate) struct EcmascriptDevChunkContentMerger; #[turbo_tasks::value_impl] -impl EcmascriptDevChunkContentMergerVc { +impl EcmascriptDevChunkContentMerger { /// Creates a new [`EcmascriptDevChunkContentMerger`]. #[turbo_tasks::function] - pub fn new() -> Self { + pub fn new() -> Vc { Self::cell(EcmascriptDevChunkContentMerger) } } @@ -26,20 +22,27 @@ impl EcmascriptDevChunkContentMergerVc { #[turbo_tasks::value_impl] impl VersionedContentMerger for EcmascriptDevChunkContentMerger { #[turbo_tasks::function] - async fn merge(&self, contents: VersionedContentsVc) -> Result { + async fn merge( + &self, + contents: Vc, + ) -> Result>> { let contents = contents .await? .iter() .map(|content| async move { - if let Some(content) = EcmascriptDevChunkContentVc::resolve_from(content).await? { + if let Some(content) = + Vc::try_resolve_downcast_type::(*content).await? + { Ok(content) } else { - bail!("expected EcmascriptDevChunkContentVc") + bail!("expected Vc") } }) .try_join() .await?; - Ok(EcmascriptDevMergedChunkContent { contents }.cell().into()) + Ok(Vc::upcast( + EcmascriptDevMergedChunkContent { contents }.cell(), + )) } } diff --git a/crates/turbopack-dev/src/ecmascript/merged/update.rs b/crates/turbopack-dev/src/ecmascript/merged/update.rs index d09b83ef9d7d2a..a46ab5fd71ff20 100644 --- a/crates/turbopack-dev/src/ecmascript/merged/update.rs +++ b/crates/turbopack-dev/src/ecmascript/merged/update.rs @@ -3,22 +3,22 @@ use std::sync::Arc; use anyhow::Result; use indexmap::{IndexMap, IndexSet}; use serde::Serialize; -use turbo_tasks::{IntoTraitRef, TryJoinIterExt}; +use turbo_tasks::{IntoTraitRef, ReadRef, TryJoinIterExt, Vc}; use turbo_tasks_fs::rope::Rope; use turbopack_core::{ asset::Asset, - chunk::{ChunkingContext, ModuleId, ModuleIdReadRef}, - code_builder::CodeReadRef, - version::{PartialUpdate, TotalUpdate, Update, VersionVc}, + chunk::{ChunkingContext, ModuleId}, + code_builder::Code, + version::{PartialUpdate, TotalUpdate, Update, Version}, }; use super::{ super::{ update::{update_ecmascript_chunk, EcmascriptChunkUpdate}, - version::EcmascriptDevChunkVersionReadRef, + version::EcmascriptDevChunkVersion, }, - content::EcmascriptDevMergedChunkContentVc, - version::EcmascriptDevMergedChunkVersionVc, + content::EcmascriptDevMergedChunkContent, + version::EcmascriptDevMergedChunkVersion, }; #[derive(Serialize, Default)] @@ -26,7 +26,7 @@ use super::{ struct EcmascriptMergedUpdate<'a> { /// A map from module id to latest module entry. #[serde(skip_serializing_if = "IndexMap::is_empty")] - entries: IndexMap, + entries: IndexMap, EcmascriptModuleEntry>, /// A map from chunk path to the chunk update. #[serde(skip_serializing_if = "IndexMap::is_empty")] chunks: IndexMap<&'a str, EcmascriptMergedChunkUpdate>, @@ -50,7 +50,7 @@ enum EcmascriptMergedChunkUpdate { #[serde(rename_all = "camelCase")] struct EcmascriptMergedChunkAdded { #[serde(skip_serializing_if = "IndexSet::is_empty")] - modules: IndexSet, + modules: IndexSet>, } #[derive(Serialize, Default)] @@ -60,16 +60,16 @@ struct EcmascriptMergedChunkDeleted { // modules in the chunk from the previous version. However, it's useful for // merging updates without access to an initial state. #[serde(skip_serializing_if = "IndexSet::is_empty")] - modules: IndexSet, + modules: IndexSet>, } #[derive(Serialize, Default)] #[serde(rename_all = "camelCase")] struct EcmascriptMergedChunkPartial { #[serde(skip_serializing_if = "IndexSet::is_empty")] - added: IndexSet, + added: IndexSet>, #[serde(skip_serializing_if = "IndexSet::is_empty")] - deleted: IndexSet, + deleted: IndexSet>, } #[derive(Serialize)] @@ -80,7 +80,7 @@ struct EcmascriptModuleEntry { } impl EcmascriptModuleEntry { - fn new(id: &ModuleId, code: CodeReadRef, chunk_path: &str) -> Self { + fn new(id: &ModuleId, code: ReadRef, chunk_path: &str) -> Self { /// serde_qs can't serialize a lone enum when it's [serde::untagged]. #[derive(Serialize)] struct Id<'a> { @@ -102,18 +102,18 @@ impl EcmascriptModuleEntry { /// versions, without having to actually merge the versions into a single /// hashmap, which would be expensive. struct MergedModuleMap { - versions: Vec, + versions: Vec>, } impl MergedModuleMap { /// Creates a new `MergedModuleMap` from the given versions. - fn new(versions: Vec) -> Self { + fn new(versions: Vec>) -> Self { Self { versions } } /// Returns the hash of the module with the given id, or `None` if the /// module is not present in any of the versions. - fn get(&self, id: &ModuleId) -> Option { + fn get(&self, id: &ReadRef) -> Option { for version in &self.versions { if let Some(hash) = version.entries_hashes.get(id) { return Some(*hash); @@ -124,26 +124,30 @@ impl MergedModuleMap { } pub(super) async fn update_ecmascript_merged_chunk( - content: EcmascriptDevMergedChunkContentVc, - from_version: VersionVc, + content: Vc, + from_version: Vc>, ) -> Result { let to_merged_version = content.version(); - let from_merged_version = - if let Some(from) = EcmascriptDevMergedChunkVersionVc::resolve_from(from_version).await? { - from - } else { - // It's likely `from_version` is `NotFoundVersion`. - return Ok(Update::Total(TotalUpdate { - to: to_merged_version.as_version().into_trait_ref().await?, - })); - }; + let from_merged_version = if let Some(from) = + Vc::try_resolve_downcast_type::(from_version).await? + { + from + } else { + // It's likely `from_version` is `NotFoundVersion`. + return Ok(Update::Total(TotalUpdate { + to: Vc::upcast::>(to_merged_version) + .into_trait_ref() + .await?, + })); + }; let to = to_merged_version.await?; let from = from_merged_version.await?; // When to and from point to the same value we can skip comparing them. - // This will happen since `TraitRef::cell` will not clone the value, - // but only make the cell point to the same immutable value (Arc). + // This will happen since `TraitRef>>::cell` will not clone + // the value, but only make the cell point to the same immutable value + // (Arc). if from.ptr_eq(&to) { return Ok(Update::None); } @@ -251,7 +255,9 @@ pub(super) async fn update_ecmascript_merged_chunk( Update::None } else { Update::Partial(PartialUpdate { - to: to_merged_version.as_version().into_trait_ref().await?, + to: Vc::upcast::>(to_merged_version) + .into_trait_ref() + .await?, instruction: Arc::new(serde_json::to_value(&merged_update)?), }) }; diff --git a/crates/turbopack-dev/src/ecmascript/merged/version.rs b/crates/turbopack-dev/src/ecmascript/merged/version.rs index cbe7cfb581e6ff..a20bfc27e0d3f2 100644 --- a/crates/turbopack-dev/src/ecmascript/merged/version.rs +++ b/crates/turbopack-dev/src/ecmascript/merged/version.rs @@ -1,22 +1,22 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ReadRef, TryJoinIterExt}; +use turbo_tasks::{ReadRef, TryJoinIterExt, Vc}; use turbo_tasks_hash::{encode_hex, Xxh3Hash64Hasher}; -use turbopack_core::version::{Version, VersionVc}; +use turbopack_core::version::Version; -use super::super::version::EcmascriptDevChunkVersionReadRef; +use super::super::version::EcmascriptDevChunkVersion; /// The version of a [`super::content::EcmascriptMergedChunkContent`]. This is /// essentially a composite [`EcmascriptChunkVersion`]. #[turbo_tasks::value(serialization = "none", shared)] pub(super) struct EcmascriptDevMergedChunkVersion { #[turbo_tasks(trace_ignore)] - pub(super) versions: Vec, + pub(super) versions: Vec>, } #[turbo_tasks::value_impl] impl Version for EcmascriptDevMergedChunkVersion { #[turbo_tasks::function] - async fn id(&self) -> Result { + async fn id(&self) -> Result> { let mut hasher = Xxh3Hash64Hasher::new(); hasher.write_value(self.versions.len()); let sorted_ids = { @@ -34,6 +34,6 @@ impl Version for EcmascriptDevMergedChunkVersion { } let hash = hasher.finish(); let hex_hash = encode_hex(hash); - Ok(StringVc::cell(hex_hash)) + Ok(Vc::cell(hex_hash)) } } diff --git a/crates/turbopack-dev/src/ecmascript/optimize.rs b/crates/turbopack-dev/src/ecmascript/optimize.rs index 66a58050f90f58..a119130234271f 100644 --- a/crates/turbopack-dev/src/ecmascript/optimize.rs +++ b/crates/turbopack-dev/src/ecmascript/optimize.rs @@ -4,42 +4,44 @@ use std::{cmp::Ordering, collections::HashSet}; use anyhow::Result; use indexmap::{IndexMap, IndexSet}; -use turbo_tasks::{TryJoinIterExt, Value}; -use turbo_tasks_fs::FileSystemPathOptionVc; +use turbo_tasks::{TryJoinIterExt, Value, Vc}; +use turbo_tasks_fs::FileSystemPathOption; use turbopack_core::chunk::optimize::optimize_by_common_parent; -use turbopack_ecmascript::chunk::{ - EcmascriptChunkPlaceablesVc, EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptChunksVc, -}; +use turbopack_ecmascript::chunk::{EcmascriptChunk, EcmascriptChunkingContext, EcmascriptChunks}; #[turbo_tasks::function] -pub async fn optimize_ecmascript_chunks(chunks: EcmascriptChunksVc) -> Result { +pub async fn optimize_ecmascript_chunks( + chunks: Vc, +) -> Result> { // Ecmascript chunks in the same chunk group can have different chunking // contexts (e.g. through Next.js' with-client-chunks transition). They must not // be merged together, as this affects how module ids are computed within the // chunk. - let chunks_by_chunking_context: IndexMap> = - chunks - .await? - .iter() - .map(|chunk| async move { - let chunking_context = chunk.await?.context.resolve().await?; - Ok((chunking_context, chunk)) - }) - .try_join() - .await? - .into_iter() - .fold(IndexMap::new(), |mut acc, (chunking_context, chunk)| { - acc.entry(chunking_context) - .or_insert_with(Vec::new) - .push(*chunk); - acc - }); + let chunks_by_chunking_context: IndexMap< + Vc>, + Vec>, + > = chunks + .await? + .iter() + .map(|chunk| async move { + let chunking_context = chunk.await?.context.resolve().await?; + Ok((chunking_context, chunk)) + }) + .try_join() + .await? + .into_iter() + .fold(IndexMap::new(), |mut acc, (chunking_context, chunk)| { + acc.entry(chunking_context) + .or_insert_with(Vec::new) + .push(*chunk); + acc + }); let optimized_chunks = chunks_by_chunking_context .into_values() .map(|chunks| async move { optimize_by_common_parent(&chunks, get_common_parent, |local, children| { - optimize_ecmascript(local.map(EcmascriptChunksVc::cell), children) + optimize_ecmascript(local.map(Vc::cell), children) }) .await? .await @@ -50,19 +52,19 @@ pub async fn optimize_ecmascript_chunks(chunks: EcmascriptChunksVc) -> Result>()) .collect::>(); - Ok(EcmascriptChunksVc::cell(optimized_chunks)) + Ok(Vc::cell(optimized_chunks)) } #[turbo_tasks::function] -async fn get_common_parent(chunk: EcmascriptChunkVc) -> Result { +async fn get_common_parent(chunk: Vc) -> Result> { Ok(chunk.common_parent()) } /// Merge a few chunks into a single chunk. async fn merge_chunks( - first: EcmascriptChunkVc, - chunks: &[EcmascriptChunkVc], -) -> Result { + first: Vc, + chunks: &[Vc], +) -> Result> { let first = first.await?; let chunks = chunks.iter().copied().try_join().await?; let main_entries = chunks @@ -73,9 +75,9 @@ async fn merge_chunks( .iter() .flat_map(|e| e.iter().copied()) .collect::>(); - Ok(EcmascriptChunkVc::new_normalized( + Ok(EcmascriptChunk::new_normalized( first.context, - EcmascriptChunkPlaceablesVc::cell(main_entries.into_iter().collect()), + Vc::cell(main_entries.into_iter().collect()), None, Value::new(first.availability_info), )) @@ -101,13 +103,13 @@ const MAX_CHUNK_ITEMS_PER_CHUNK: usize = 3000; /// Merge chunks with high duplication between them. async fn merge_duplicated_and_contained( - chunks: &mut Vec<(EcmascriptChunkVc, Option)>, + chunks: &mut Vec<(Vc, Option>)>, mut unoptimized_count: usize, ) -> Result<()> { struct Comparison { /// Index of chunk in the `chunks` vec index: usize, - other: EcmascriptChunkVc, + other: Vc, shared: usize, left: usize, right: usize, @@ -157,7 +159,7 @@ async fn merge_duplicated_and_contained( .enumerate() .take(COMPARE_WITH_COUNT) .map(|(j, &(other, _))| async move { - let compare = EcmascriptChunkVc::compare(chunk, other).await?; + let compare = EcmascriptChunk::compare(chunk, other).await?; Ok(Comparison { // since enumerate is offset by `i + 1` we need to account for that index: i + j + 1, @@ -286,9 +288,9 @@ async fn merge_duplicated_and_contained( /// all chunks from a single source and if that's not enough it will merge /// chunks into equal sized groups. async fn merge_to_limit( - chunks: Vec<(EcmascriptChunkVc, Option)>, + chunks: Vec<(Vc, Option>)>, target_count: usize, -) -> Result> { +) -> Result>> { let mut remaining = chunks.len(); // Collecting chunks by source into an index map to keep original order let mut chunks_by_source = IndexMap::new(); @@ -343,8 +345,8 @@ async fn merge_to_limit( /// Merge chunks into a few chunks as possible while staying below the chunk /// size limit. async fn merge_by_size( - chunks: impl IntoIterator, -) -> Result> { + chunks: impl IntoIterator>, +) -> Result>> { let mut merged = Vec::new(); let mut current = Vec::new(); let mut current_items = 0; @@ -384,10 +386,10 @@ async fn merge_by_size( /// Chunk optimization for ecmascript chunks. #[turbo_tasks::function] async fn optimize_ecmascript( - local: Option, - children: Vec, -) -> Result { - let mut chunks = Vec::<(EcmascriptChunkVc, Option)>::new(); + local: Option>, + children: Vec>, +) -> Result> { + let mut chunks = Vec::<(Vc, Option>)>::new(); // TODO optimize let mut unoptimized_count = 0; if let Some(local) = local { @@ -398,7 +400,7 @@ async fn optimize_ecmascript( } for chunk in local.iter_mut() { let content = (*chunk).await?; - *chunk = EcmascriptChunkVc::new_normalized( + *chunk = EcmascriptChunk::new_normalized( content.context, content.main_entries, content.omit_entries, @@ -441,5 +443,5 @@ async fn optimize_ecmascript( chunks.into_iter().map(|(c, _)| c).collect() }; - Ok(EcmascriptChunksVc::cell(chunks)) + Ok(Vc::cell(chunks)) } diff --git a/crates/turbopack-dev/src/ecmascript/runtime.rs b/crates/turbopack-dev/src/ecmascript/runtime.rs index 5e1845029b39fb..6ee84f5cc99319 100644 --- a/crates/turbopack-dev/src/ecmascript/runtime.rs +++ b/crates/turbopack-dev/src/ecmascript/runtime.rs @@ -1,40 +1,40 @@ use anyhow::{bail, Result}; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ asset::Asset, - chunk::{ChunkGroupVc, ChunkListReferenceVc, ChunkingContext}, - ident::AssetIdentVc, - reference::AssetReferencesVc, + chunk::{ChunkGroup, ChunkListReference, ChunkingContext}, + ident::AssetIdent, + reference::AssetReferences, }; use turbopack_ecmascript::chunk::{ - EcmascriptChunkPlaceablesVc, EcmascriptChunkRuntime, EcmascriptChunkRuntimeContentVc, - EcmascriptChunkRuntimeVc, EcmascriptChunkVc, EcmascriptChunkingContextVc, + EcmascriptChunk, EcmascriptChunkPlaceables, EcmascriptChunkRuntime, + EcmascriptChunkRuntimeContent, EcmascriptChunkingContext, }; -use crate::ecmascript::content::EcmascriptDevChunkContentVc; +use crate::ecmascript::content::EcmascriptDevChunkContent; /// Development runtime for Ecmascript chunks. #[turbo_tasks::value(shared)] pub(crate) struct EcmascriptDevChunkRuntime { /// The chunking context that created this runtime. - chunking_context: EcmascriptChunkingContextVc, + chunking_context: Vc>, /// All chunks of this chunk group need to be ready for execution to start. /// When None, it will use a chunk group created from the current chunk. - chunk_group: Option, + chunk_group: Option>, /// If any evaluated entries are set, the main runtime code will be included /// in the chunk and the provided entries will be evaluated as soon as the /// chunk executes. - evaluated_entries: Option, + evaluated_entries: Option>, } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkRuntimeVc { - /// Creates a new [`EcmascriptDevChunkRuntimeVc`]. +impl EcmascriptDevChunkRuntime { + /// Creates a new [`Vc`]. #[turbo_tasks::function] pub fn new( - chunking_context: EcmascriptChunkingContextVc, - evaluated_entries: Option, - ) -> Self { + chunking_context: Vc>, + evaluated_entries: Option>, + ) -> Vc { EcmascriptDevChunkRuntime { chunking_context, chunk_group: None, @@ -47,14 +47,14 @@ impl EcmascriptDevChunkRuntimeVc { #[turbo_tasks::value_impl] impl ValueToString for EcmascriptDevChunkRuntime { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("Ecmascript Dev Runtime".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("Ecmascript Dev Runtime".to_string())) } } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript dev chunk".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript dev chunk".to_string()) } #[turbo_tasks::value_impl] @@ -62,9 +62,9 @@ impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { #[turbo_tasks::function] async fn decorate_asset_ident( &self, - origin_chunk: EcmascriptChunkVc, - ident: AssetIdentVc, - ) -> Result { + origin_chunk: Vc, + ident: Vc, + ) -> Result> { let Self { chunking_context: _, chunk_group, @@ -100,12 +100,12 @@ impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { } } - Ok(AssetIdentVc::new(Value::new(ident))) + Ok(AssetIdent::new(Value::new(ident))) } #[turbo_tasks::function] - fn with_chunk_group(&self, chunk_group: ChunkGroupVc) -> EcmascriptDevChunkRuntimeVc { - EcmascriptDevChunkRuntimeVc::cell(EcmascriptDevChunkRuntime { + fn with_chunk_group(&self, chunk_group: Vc) -> Vc { + EcmascriptDevChunkRuntime::cell(EcmascriptDevChunkRuntime { chunking_context: self.chunking_context, chunk_group: Some(chunk_group), evaluated_entries: self.evaluated_entries, @@ -113,7 +113,7 @@ impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { } #[turbo_tasks::function] - fn references(&self, origin_chunk: EcmascriptChunkVc) -> AssetReferencesVc { + fn references(&self, origin_chunk: Vc) -> Vc { let Self { chunk_group, chunking_context, @@ -123,30 +123,30 @@ impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { let mut references = vec![]; if evaluated_entries.is_some() { let chunk_group = - chunk_group.unwrap_or_else(|| ChunkGroupVc::from_chunk(origin_chunk.into())); - references.push( - ChunkListReferenceVc::new(chunking_context.output_root(), chunk_group).into(), - ); + chunk_group.unwrap_or_else(|| ChunkGroup::from_chunk(origin_chunk.into())); + references.push(Vc::upcast(ChunkListReference::new( + chunking_context.output_root(), + chunk_group, + ))); } - AssetReferencesVc::cell(references) + Vc::cell(references) } #[turbo_tasks::function] - fn content(&self, origin_chunk: EcmascriptChunkVc) -> EcmascriptChunkRuntimeContentVc { - EcmascriptDevChunkContentVc::new( + fn content(&self, origin_chunk: Vc) -> Vc { + Vc::upcast(EcmascriptDevChunkContent::new( origin_chunk, self.chunking_context, self.chunk_group, self.evaluated_entries, - ) - .into() + )) } #[turbo_tasks::function] async fn merge( &self, - runtimes: Vec, - ) -> Result { + runtimes: Vec>, + ) -> Result> { let Self { chunking_context, chunk_group, @@ -167,7 +167,7 @@ impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { }; for runtime in runtimes { - let Some(runtime) = EcmascriptDevChunkRuntimeVc::resolve_from(runtime).await? else { + let Some(runtime) = Vc::try_resolve_downcast_type::(runtime).await? else { bail!("cannot merge EcmascriptDevChunkRuntime with non-EcmascriptDevChunkRuntime"); }; @@ -206,7 +206,7 @@ impl EcmascriptChunkRuntime for EcmascriptDevChunkRuntime { Ok(EcmascriptDevChunkRuntime { chunking_context, chunk_group, - evaluated_entries: evaluated_entries.map(EcmascriptChunkPlaceablesVc::cell), + evaluated_entries: evaluated_entries.map(Vc::cell), } .cell() .into()) diff --git a/crates/turbopack-dev/src/ecmascript/update.rs b/crates/turbopack-dev/src/ecmascript/update.rs index ed4b8e18579c32..2b6376722ea424 100644 --- a/crates/turbopack-dev/src/ecmascript/update.rs +++ b/crates/turbopack-dev/src/ecmascript/update.rs @@ -1,8 +1,9 @@ use anyhow::Result; use indexmap::IndexMap; -use turbopack_core::{chunk::ModuleIdReadRef, code_builder::CodeReadRef}; +use turbo_tasks::{ReadRef, Vc}; +use turbopack_core::{chunk::ModuleId, code_builder::Code}; -use super::{content::EcmascriptDevChunkContentVc, version::EcmascriptDevChunkVersionReadRef}; +use super::{content::EcmascriptDevChunkContent, version::EcmascriptDevChunkVersion}; pub(super) enum EcmascriptChunkUpdate { None, @@ -10,20 +11,21 @@ pub(super) enum EcmascriptChunkUpdate { } pub(super) struct EcmascriptChunkPartialUpdate { - pub added: IndexMap, - pub deleted: IndexMap, - pub modified: IndexMap, + pub added: IndexMap, (u64, ReadRef)>, + pub deleted: IndexMap, u64>, + pub modified: IndexMap, ReadRef>, } pub(super) async fn update_ecmascript_chunk( - content: EcmascriptDevChunkContentVc, - from: &EcmascriptDevChunkVersionReadRef, + content: Vc, + from: &ReadRef, ) -> Result { let to = content.own_version().await?; // When to and from point to the same value we can skip comparing them. - // This will happen since `TraitRef::cell` will not clone the value, - // but only make the cell point to the same immutable value (Arc). + // This will happen since `TraitRef>>::cell` will not clone + // the value, but only make the cell point to the same immutable value + // (Arc). if from.ptr_eq(&to) { return Ok(EcmascriptChunkUpdate::None); } diff --git a/crates/turbopack-dev/src/ecmascript/version.rs b/crates/turbopack-dev/src/ecmascript/version.rs index 2b46ad95ecac6d..09ba53047d39b2 100644 --- a/crates/turbopack-dev/src/ecmascript/version.rs +++ b/crates/turbopack-dev/src/ecmascript/version.rs @@ -1,29 +1,26 @@ use anyhow::{bail, Result}; use indexmap::IndexMap; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ReadRef, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbo_tasks_hash::{encode_hex, Xxh3Hash64Hasher}; -use turbopack_core::{ - chunk::ModuleIdReadRef, - version::{Version, VersionVc}, -}; +use turbopack_core::{chunk::ModuleId, version::Version}; -use super::content_entry::EcmascriptDevChunkContentEntriesVc; +use super::content_entry::EcmascriptDevChunkContentEntries; #[turbo_tasks::value(serialization = "none")] pub(super) struct EcmascriptDevChunkVersion { pub(super) chunk_path: String, - pub(super) entries_hashes: IndexMap, + pub(super) entries_hashes: IndexMap, u64>, } #[turbo_tasks::value_impl] -impl EcmascriptDevChunkVersionVc { +impl EcmascriptDevChunkVersion { #[turbo_tasks::function] pub async fn new( - output_root: FileSystemPathVc, - chunk_path: FileSystemPathVc, - entries: EcmascriptDevChunkContentEntriesVc, - ) -> Result { + output_root: Vc, + chunk_path: Vc, + entries: Vc, + ) -> Result> { let output_root = output_root.await?; let chunk_path = chunk_path.await?; let chunk_path = if let Some(path) = output_root.get_path_to(&chunk_path) { @@ -51,7 +48,7 @@ impl EcmascriptDevChunkVersionVc { #[turbo_tasks::value_impl] impl Version for EcmascriptDevChunkVersion { #[turbo_tasks::function] - fn id(&self) -> StringVc { + fn id(&self) -> Vc { let mut hasher = Xxh3Hash64Hasher::new(); let sorted_hashes = { let mut hashes: Vec<_> = self.entries_hashes.values().copied().collect(); @@ -63,6 +60,6 @@ impl Version for EcmascriptDevChunkVersion { } let hash = hasher.finish(); let hex_hash = encode_hex(hash); - StringVc::cell(hex_hash) + Vc::cell(hex_hash) } } diff --git a/crates/turbopack-dev/src/lib.rs b/crates/turbopack-dev/src/lib.rs index f18625f7a387d6..0e90e0e5549da8 100644 --- a/crates/turbopack-dev/src/lib.rs +++ b/crates/turbopack-dev/src/lib.rs @@ -1,13 +1,15 @@ #![feature(lint_reasons)] #![feature(iter_intersperse)] #![feature(int_roundings)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub(crate) mod chunking_context; pub(crate) mod css; pub(crate) mod ecmascript; pub mod react_refresh; -pub use chunking_context::{DevChunkingContext, DevChunkingContextBuilder, DevChunkingContextVc}; +pub use chunking_context::{DevChunkingContext, DevChunkingContextBuilder}; pub fn register() { turbo_tasks::register(); diff --git a/crates/turbopack-dev/src/react_refresh.rs b/crates/turbopack-dev/src/react_refresh.rs index 4320dac8b6c185..a2f7f798a1e4d1 100644 --- a/crates/turbopack-dev/src/react_refresh.rs +++ b/crates/turbopack-dev/src/react_refresh.rs @@ -1,31 +1,31 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack::resolve_options_context::ResolveOptionsContextVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack::resolve_options_context::ResolveOptionsContext; use turbopack_core::{ - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, - resolve::parse::RequestVc, + issue::{Issue, IssueExt, IssueSeverity}, + resolve::parse::Request, }; use turbopack_ecmascript::resolve::apply_cjs_specific_options; #[turbo_tasks::function] -fn react_refresh_request() -> RequestVc { - RequestVc::parse_string("@next/react-refresh-utils/dist/runtime".to_string()) +fn react_refresh_request() -> Vc { + Request::parse_string("@next/react-refresh-utils/dist/runtime".to_string()) } #[turbo_tasks::function] -fn react_refresh_request_in_next() -> RequestVc { - RequestVc::parse_string("next/dist/compiled/@next/react-refresh-utils/dist/runtime".to_string()) +fn react_refresh_request_in_next() -> Vc { + Request::parse_string("next/dist/compiled/@next/react-refresh-utils/dist/runtime".to_string()) } #[turbo_tasks::value] pub enum ResolveReactRefreshResult { NotFound, - Found(RequestVc), + Found(Vc), } impl ResolveReactRefreshResult { - pub fn as_request(&self) -> Option { + pub fn as_request(&self) -> Option> { match self { ResolveReactRefreshResult::NotFound => None, ResolveReactRefreshResult::Found(r) => Some(*r), @@ -43,9 +43,9 @@ impl ResolveReactRefreshResult { /// given path. Emits an issue if we can't. #[turbo_tasks::function] pub async fn assert_can_resolve_react_refresh( - path: FileSystemPathVc, - resolve_options_context: ResolveOptionsContextVc, -) -> Result { + path: Vc, + resolve_options_context: Vc, +) -> Result> { let resolve_options = apply_cjs_specific_options(turbopack::resolve_options(path, resolve_options_context)); for request in [react_refresh_request_in_next(), react_refresh_request()] { @@ -55,41 +55,41 @@ pub async fn assert_can_resolve_react_refresh( return Ok(ResolveReactRefreshResult::Found(request).cell()); } } - ReactRefreshResolvingIssue { path }.cell().as_issue().emit(); + ReactRefreshResolvingIssue { path }.cell().emit(); Ok(ResolveReactRefreshResult::NotFound.cell()) } /// An issue that occurred while resolving the React Refresh runtime module. #[turbo_tasks::value(shared)] pub struct ReactRefreshResolvingIssue { - path: FileSystemPathVc, + path: Vc, } #[turbo_tasks::value_impl] impl Issue for ReactRefreshResolvingIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Could not resolve React Refresh runtime".to_string()) + fn title(&self) -> Vc { + Vc::cell("Could not resolve React Refresh runtime".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("other".to_string()) + fn category(&self) -> Vc { + Vc::cell("other".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.path } #[turbo_tasks::function] - fn description(&self) -> StringVc { - StringVc::cell( + fn description(&self) -> Vc { + Vc::cell( "React Refresh will be disabled.\nTo enable React Refresh, install the \ `react-refresh` and `@next/react-refresh-utils` modules." .to_string(), diff --git a/crates/turbopack-ecmascript-plugins/src/lib.rs b/crates/turbopack-ecmascript-plugins/src/lib.rs index 4eeb5f3c51497a..973f77197906b7 100644 --- a/crates/turbopack-ecmascript-plugins/src/lib.rs +++ b/crates/turbopack-ecmascript-plugins/src/lib.rs @@ -1,3 +1,6 @@ +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] + pub mod transform; pub fn register() { diff --git a/crates/turbopack-ecmascript-plugins/src/transform/directives/client.rs b/crates/turbopack-ecmascript-plugins/src/transform/directives/client.rs index 17863f485f852b..05c4c7c73b6d1f 100644 --- a/crates/turbopack-ecmascript-plugins/src/transform/directives/client.rs +++ b/crates/turbopack-ecmascript-plugins/src/transform/directives/client.rs @@ -1,18 +1,18 @@ use anyhow::Result; use async_trait::async_trait; use swc_core::ecma::{ast::Program, transforms::base::resolver, visit::VisitMutWith}; -use turbo_tasks::primitives::StringVc; +use turbo_tasks::Vc; use turbopack_ecmascript::{CustomTransformer, TransformContext}; use super::{is_client_module, server_to_client_proxy::create_proxy_module}; #[derive(Debug)] pub struct ClientDirectiveTransformer { - transition_name: StringVc, + transition_name: Vc, } impl ClientDirectiveTransformer { - pub fn new(transition_name: &StringVc) -> Self { + pub fn new(transition_name: &Vc) -> Self { Self { transition_name: *transition_name, } diff --git a/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs b/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs index 16dd9490a0c6fe..df8def467b7153 100644 --- a/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs +++ b/crates/turbopack-ecmascript-plugins/src/transform/directives/server.rs @@ -4,7 +4,8 @@ use swc_core::{ ecma::ast::{ModuleItem, Program}, quote, }; -use turbo_tasks::primitives::StringVc; +use turbo_tasks::Vc; +use turbopack_core::issue::IssueExt; use turbopack_ecmascript::{CustomTransformer, TransformContext, UnsupportedServerActionIssue}; use super::is_server_module; @@ -14,11 +15,11 @@ pub struct ServerDirectiveTransformer { // ServerDirective is not implemented yet and always reports an issue. // We don't have to pass a valid transition name yet, but the API is prepared. #[allow(unused)] - transition_name: StringVc, + transition_name: Vc, } impl ServerDirectiveTransformer { - pub fn new(transition_name: &StringVc) -> Self { + pub fn new(transition_name: &Vc) -> Self { Self { transition_name: *transition_name, } @@ -41,7 +42,6 @@ impl CustomTransformer for ServerDirectiveTransformer { context: ctx.file_path, } .cell() - .as_issue() .emit(); } diff --git a/crates/turbopack-ecmascript-plugins/src/transform/emotion.rs b/crates/turbopack-ecmascript-plugins/src/transform/emotion.rs index 2215b3fbcaecee..92bc780c77e221 100644 --- a/crates/turbopack-ecmascript-plugins/src/transform/emotion.rs +++ b/crates/turbopack-ecmascript-plugins/src/transform/emotion.rs @@ -14,7 +14,7 @@ use swc_core::{ visit::FoldWith, }, }; -use turbo_tasks::trace::TraceRawVcs; +use turbo_tasks::{trace::TraceRawVcs, ValueDefault, Vc}; use turbopack_ecmascript::{CustomTransformer, TransformContext}; #[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] @@ -26,7 +26,7 @@ pub enum EmotionLabelKind { } #[turbo_tasks::value(transparent)] -pub struct OptionEmotionTransformConfig(Option); +pub struct OptionEmotionTransformConfig(Option>); //[TODO]: need to support importmap, there are type mismatch between //next.config.js to swc's emotion options @@ -40,16 +40,16 @@ pub struct EmotionTransformConfig { } #[turbo_tasks::value_impl] -impl EmotionTransformConfigVc { +impl EmotionTransformConfig { #[turbo_tasks::function] - pub fn default() -> Self { + pub fn default_private() -> Vc { Self::cell(Default::default()) } } -impl Default for EmotionTransformConfigVc { - fn default() -> Self { - Self::default() +impl ValueDefault for EmotionTransformConfig { + fn value_default() -> Vc { + EmotionTransformConfig::default_private() } } diff --git a/crates/turbopack-ecmascript-plugins/src/transform/styled_components.rs b/crates/turbopack-ecmascript-plugins/src/transform/styled_components.rs index bedb6886db4210..dad95ea347f6c2 100644 --- a/crates/turbopack-ecmascript-plugins/src/transform/styled_components.rs +++ b/crates/turbopack-ecmascript-plugins/src/transform/styled_components.rs @@ -6,10 +6,11 @@ use swc_core::{ common::FileName, ecma::{ast::Program, atoms::JsWord, visit::VisitMutWith}, }; +use turbo_tasks::{ValueDefault, Vc}; use turbopack_ecmascript::{CustomTransformer, TransformContext}; #[turbo_tasks::value(transparent)] -pub struct OptionStyledComponentsTransformConfig(Option); +pub struct OptionStyledComponentsTransformConfig(Option>); #[turbo_tasks::value(shared)] #[derive(Clone, Debug)] @@ -39,16 +40,16 @@ impl Default for StyledComponentsTransformConfig { } #[turbo_tasks::value_impl] -impl StyledComponentsTransformConfigVc { +impl StyledComponentsTransformConfig { #[turbo_tasks::function] - pub fn default() -> Self { + fn default_private() -> Vc { Self::cell(Default::default()) } } -impl Default for StyledComponentsTransformConfigVc { - fn default() -> Self { - Self::default() +impl ValueDefault for StyledComponentsTransformConfig { + fn value_default() -> Vc { + StyledComponentsTransformConfig::default_private() } } diff --git a/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs b/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs index e6963b31a7da5e..5146caf9cd1b1a 100644 --- a/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs +++ b/crates/turbopack-ecmascript-plugins/src/transform/swc_ecma_transform_plugins.rs @@ -1,9 +1,9 @@ use anyhow::Result; use async_trait::async_trait; use swc_core::ecma::ast::Program; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueSeverity}; use turbopack_ecmascript::{CustomTransformer, TransformContext}; /// A wrapper around an SWC's ecma transform wasm plugin module bytes, allowing @@ -54,36 +54,36 @@ impl SwcPluginModule { #[turbo_tasks::value(shared)] struct UnsupportedSwcEcmaTransformPluginsIssue { - pub context: FileSystemPathVc, + pub context: Vc, } #[turbo_tasks::value_impl] impl Issue for UnsupportedSwcEcmaTransformPluginsIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("transform".to_string()) + fn category(&self) -> Vc { + Vc::cell("transform".to_string()) } #[turbo_tasks::function] - async fn title(&self) -> Result { - Ok(StringVc::cell( + async fn title(&self) -> Result> { + Ok(Vc::cell( "Unsupported SWC EcmaScript transform plugins on this platform.".to_string(), )) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - fn description(&self) -> StringVc { - StringVc::cell( + fn description(&self) -> Vc { + Vc::cell( "Turbopack does not yet support running SWC EcmaScript transform plugins on this \ platform." .to_string(), @@ -95,12 +95,12 @@ impl Issue for UnsupportedSwcEcmaTransformPluginsIssue { #[derive(Debug)] pub struct SwcEcmaTransformPluginsTransformer { #[cfg(feature = "swc_ecma_transform_plugin")] - plugins: Vec<(SwcPluginModuleVc, serde_json::Value)>, + plugins: Vec<(Vc, serde_json::Value)>, } impl SwcEcmaTransformPluginsTransformer { #[cfg(feature = "swc_ecma_transform_plugin")] - pub fn new(plugins: Vec<(SwcPluginModuleVc, serde_json::Value)>) -> Self { + pub fn new(plugins: Vec<(Vc, serde_json::Value)>) -> Self { Self { plugins } } @@ -223,12 +223,13 @@ impl CustomTransformer for SwcEcmaTransformPluginsTransformer { #[cfg(not(feature = "swc_ecma_transform_plugin"))] { - let issue: UnsupportedSwcEcmaTransformPluginsIssueVc = - UnsupportedSwcEcmaTransformPluginsIssue { - context: ctx.file_path, - } - .into(); - issue.as_issue().emit(); + use turbopack_core::issue::IssueExt; + + UnsupportedSwcEcmaTransformPluginsIssue { + context: ctx.file_path, + } + .cell() + .emit(); } Ok(()) diff --git a/crates/turbopack-ecmascript-runtime/src/asset_context.rs b/crates/turbopack-ecmascript-runtime/src/asset_context.rs index 62c26a6fb2ed34..9b43906468c7c3 100644 --- a/crates/turbopack-ecmascript-runtime/src/asset_context.rs +++ b/crates/turbopack-ecmascript-runtime/src/asset_context.rs @@ -1,16 +1,14 @@ +use turbo_tasks::Vc; use turbopack::{ module_options::{ModuleOptionsContext, TypescriptTransformOptions}, - resolve_options_context::ResolveOptionsContextVc, - transition::TransitionsByNameVc, - ModuleAssetContextVc, + ModuleAssetContext, }; use turbopack_core::{ - compile_time_info::CompileTimeInfo, context::AssetContextVc, environment::EnvironmentVc, + compile_time_info::CompileTimeInfo, context::AssetContext, environment::Environment, }; /// Returns the runtime asset context to use to process runtime code assets. -pub fn get_runtime_asset_context(environment: EnvironmentVc) -> AssetContextVc { - let resolve_options_context = ResolveOptionsContextVc::default(); +pub fn get_runtime_asset_context(environment: Vc) -> Vc> { let module_options_context = ModuleOptionsContext { enable_typescript_transform: Some(TypescriptTransformOptions::default().cell()), ..Default::default() @@ -18,13 +16,12 @@ pub fn get_runtime_asset_context(environment: EnvironmentVc) -> AssetContextVc { .cell(); let compile_time_info = CompileTimeInfo::builder(environment).cell(); - let context: AssetContextVc = ModuleAssetContextVc::new( - TransitionsByNameVc::cell(Default::default()), + let context: Vc> = Vc::upcast(ModuleAssetContext::new( + Vc::cell(Default::default()), compile_time_info, module_options_context, - resolve_options_context, - ) - .into(); + Vc::default(), + )); context } diff --git a/crates/turbopack-ecmascript-runtime/src/build_runtime.rs b/crates/turbopack-ecmascript-runtime/src/build_runtime.rs index 75bffaee9d9bf7..0fb899ff793e60 100644 --- a/crates/turbopack-ecmascript-runtime/src/build_runtime.rs +++ b/crates/turbopack-ecmascript-runtime/src/build_runtime.rs @@ -1,27 +1,33 @@ use anyhow::Result; +use turbo_tasks::Vc; use turbopack_core::{ - code_builder::{CodeBuilder, CodeVc}, - environment::EnvironmentVc, + code_builder::{Code, CodeBuilder}, + environment::Environment, }; -use turbopack_ecmascript::StaticEcmascriptCodeVc; +use turbopack_ecmascript::StaticEcmascriptCode; use crate::{asset_context::get_runtime_asset_context, embed_file_path}; /// Returns the code for the Node.js production ECMAScript runtime. #[turbo_tasks::function] -pub async fn get_build_runtime_code(environment: EnvironmentVc) -> Result { +pub async fn get_build_runtime_code(environment: Vc) -> Result> { let asset_context = get_runtime_asset_context(environment); - let shared_runtime_utils_code = - StaticEcmascriptCodeVc::new(asset_context, embed_file_path("shared/runtime-utils.ts")) - .code(); + let shared_runtime_utils_code = StaticEcmascriptCode::new( + asset_context, + embed_file_path("shared/runtime-utils.ts".to_string()), + ) + .code(); - let runtime_code = - StaticEcmascriptCodeVc::new(asset_context, embed_file_path("build/runtime.ts")).code(); + let runtime_code = StaticEcmascriptCode::new( + asset_context, + embed_file_path("build/runtime.ts".to_string()), + ) + .code(); let mut code = CodeBuilder::default(); code.push_code(&*shared_runtime_utils_code.await?); code.push_code(&*runtime_code.await?); - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } diff --git a/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs b/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs index a5aa64746c7963..02920dc769d493 100644 --- a/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs +++ b/crates/turbopack-ecmascript-runtime/src/dev_runtime.rs @@ -2,31 +2,34 @@ use std::io::Write; use anyhow::Result; use indoc::writedoc; +use turbo_tasks::Vc; use turbopack_core::{ - code_builder::{CodeBuilder, CodeVc}, + code_builder::{Code, CodeBuilder}, context::AssetContext, - environment::{ChunkLoading, EnvironmentVc}, + environment::{ChunkLoading, Environment}, }; -use turbopack_ecmascript::StaticEcmascriptCodeVc; +use turbopack_ecmascript::StaticEcmascriptCode; use crate::{asset_context::get_runtime_asset_context, embed_file_path}; /// Returns the code for the development ECMAScript runtime. #[turbo_tasks::function] -pub async fn get_dev_runtime_code(environment: EnvironmentVc) -> Result { +pub async fn get_dev_runtime_code(environment: Vc) -> Result> { let asset_context = get_runtime_asset_context(environment); - let shared_runtime_utils_code = - StaticEcmascriptCodeVc::new(asset_context, embed_file_path("shared/runtime-utils.ts")) - .code(); + let shared_runtime_utils_code = StaticEcmascriptCode::new( + asset_context, + embed_file_path("shared/runtime-utils.ts".to_string()), + ) + .code(); - let runtime_base_code = StaticEcmascriptCodeVc::new( + let runtime_base_code = StaticEcmascriptCode::new( asset_context, - embed_file_path("dev/runtime/base/runtime-base.ts"), + embed_file_path("dev/runtime/base/runtime-base.ts".to_string()), ) .code(); - let runtime_backend_code = StaticEcmascriptCodeVc::new( + let runtime_backend_code = StaticEcmascriptCode::new( asset_context, match &*asset_context .compile_time_info() @@ -34,9 +37,15 @@ pub async fn get_dev_runtime_code(environment: EnvironmentVc) -> Result .chunk_loading() .await? { - ChunkLoading::None => embed_file_path("dev/runtime/none/runtime-backend-none.ts"), - ChunkLoading::NodeJs => embed_file_path("dev/runtime/nodejs/runtime-backend-nodejs.ts"), - ChunkLoading::Dom => embed_file_path("dev/runtime/dom/runtime-backend-dom.ts"), + ChunkLoading::None => { + embed_file_path("dev/runtime/none/runtime-backend-none.ts".to_string()) + } + ChunkLoading::NodeJs => { + embed_file_path("dev/runtime/nodejs/runtime-backend-nodejs.ts".to_string()) + } + ChunkLoading::Dom => { + embed_file_path("dev/runtime/dom/runtime-backend-dom.ts".to_string()) + } }, ) .code(); @@ -69,5 +78,5 @@ pub async fn get_dev_runtime_code(environment: EnvironmentVc) -> Result "# )?; - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } diff --git a/crates/turbopack-ecmascript-runtime/src/embed_js.rs b/crates/turbopack-ecmascript-runtime/src/embed_js.rs index ff3e36f6f916bb..383a63b5472a54 100644 --- a/crates/turbopack-ecmascript-runtime/src/embed_js.rs +++ b/crates/turbopack-ecmascript-runtime/src/embed_js.rs @@ -1,16 +1,17 @@ -use turbo_tasks_fs::{embed_directory, FileContentVc, FileSystem, FileSystemPathVc, FileSystemVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{embed_directory, FileContent, FileSystem, FileSystemPath}; #[turbo_tasks::function] -pub fn embed_fs() -> FileSystemVc { +pub fn embed_fs() -> Vc> { embed_directory!("turbopack", "$CARGO_MANIFEST_DIR/js/src") } #[turbo_tasks::function] -pub fn embed_file(path: &str) -> FileContentVc { +pub fn embed_file(path: String) -> Vc { embed_fs().root().join(path).read() } #[turbo_tasks::function] -pub fn embed_file_path(path: &str) -> FileSystemPathVc { +pub fn embed_file_path(path: String) -> Vc { embed_fs().root().join(path) } diff --git a/crates/turbopack-ecmascript-runtime/src/lib.rs b/crates/turbopack-ecmascript-runtime/src/lib.rs index 32d2a56b8c1aef..09018796af1615 100644 --- a/crates/turbopack-ecmascript-runtime/src/lib.rs +++ b/crates/turbopack-ecmascript-runtime/src/lib.rs @@ -1,3 +1,6 @@ +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] + pub(crate) mod asset_context; pub(crate) mod build_runtime; pub(crate) mod dev_runtime; diff --git a/crates/turbopack-ecmascript/benches/analyzer.rs b/crates/turbopack-ecmascript/benches/analyzer.rs index 1e404a99c4dc66..c2b4932151b469 100644 --- a/crates/turbopack-ecmascript/benches/analyzer.rs +++ b/crates/turbopack-ecmascript/benches/analyzer.rs @@ -14,8 +14,8 @@ use turbo_tasks::Value; use turbo_tasks_testing::VcStorage; use turbopack_core::{ compile_time_info::CompileTimeInfo, - environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, - target::CompileTargetVc, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, + target::CompileTarget, }; use turbopack_ecmascript::analyzer::{ graph::{create_graph, EvalContext, VarGraph}, @@ -93,10 +93,10 @@ fn bench_link(b: &mut Bencher, input: &BenchInput) { b.to_async(rt).iter(|| async { for val in input.var_graph.values.values() { VcStorage::with(async { - let compile_time_info = CompileTimeInfo::builder(EnvironmentVc::new( + let compile_time_info = CompileTimeInfo::builder(Environment::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment { - compile_target: CompileTargetVc::unknown(), + compile_target: CompileTarget::unknown(), ..Default::default() } .into(), diff --git a/crates/turbopack-ecmascript/src/analyzer/mod.rs b/crates/turbopack-ecmascript/src/analyzer/mod.rs index 0faf2e5116e8cd..189fe1e5c89dad 100644 --- a/crates/turbopack-ecmascript/src/analyzer/mod.rs +++ b/crates/turbopack-ecmascript/src/analyzer/mod.rs @@ -22,12 +22,13 @@ use swc_core::{ atoms::{Atom, JsWord}, }, }; +use turbo_tasks::Vc; use turbopack_core::compile_time_info::CompileTimeDefineValue; use url::Url; use self::imports::ImportAnnotations; pub(crate) use self::imports::ImportMap; -use crate::{references::require_context::RequireContextMapVc, utils::StringifyJs}; +use crate::{references::require_context::RequireContextMap, utils::StringifyJs}; pub mod builtin; pub mod graph; @@ -2998,22 +2999,16 @@ pub fn parse_require_context(args: &Vec) -> Result); #[turbo_tasks::value_impl] -impl RequireContextValueVc { +impl RequireContextValue { #[turbo_tasks::function] - pub async fn from_context_map(map: RequireContextMapVc) -> Result { + pub async fn from_context_map(map: Vc) -> Result> { let mut context_map = IndexMap::new(); for (key, entry) in map.await?.iter() { context_map.insert(key.clone(), entry.origin_relative.clone()); } - Ok(Self::cell(context_map)) - } -} - -impl From for RequireContextValueVc { - fn from(map: RequireContextMapVc) -> Self { - Self::from_context_map(map) + Ok(Vc::cell(context_map)) } } @@ -3040,9 +3035,9 @@ pub enum WellKnownFunctionKind { Require, RequireResolve, RequireContext, - RequireContextRequire(RequireContextValueVc), - RequireContextRequireKeys(RequireContextValueVc), - RequireContextRequireResolve(RequireContextValueVc), + RequireContextRequire(Vc), + RequireContextRequireKeys(Vc), + RequireContextRequireResolve(Vc), Define, FsReadMethod(JsWord), PathToFileUrl, @@ -3084,13 +3079,14 @@ fn is_unresolved(i: &Ident, unresolved_mark: Mark) -> bool { pub mod test_utils { use anyhow::Result; use indexmap::IndexMap; - use turbopack_core::{compile_time_info::CompileTimeInfoVc, error::PrettyPrintError}; + use turbo_tasks::Vc; + use turbopack_core::{compile_time_info::CompileTimeInfo, error::PrettyPrintError}; use super::{ builtin::early_replace_builtin, well_known::replace_well_known, JsValue, ModuleValue, WellKnownFunctionKind, WellKnownObjectKind, }; - use crate::analyzer::{builtin::replace_builtin, parse_require_context, RequireContextValueVc}; + use crate::analyzer::{builtin::replace_builtin, parse_require_context}; pub async fn early_visitor(mut v: JsValue) -> Result<(JsValue, bool)> { let m = early_replace_builtin(&mut v); @@ -3099,7 +3095,7 @@ pub mod test_utils { pub async fn visitor( v: JsValue, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, ) -> Result<(JsValue, bool)> { let mut new_value = match v { JsValue::Call( @@ -3123,7 +3119,7 @@ pub mod test_utils { map.insert("./c".into(), format!("[context: {}]/c", options.dir)); JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequire( - RequireContextValueVc::cell(map), + Vc::cell(map), )) } Err(err) => v.into_unknown(PrettyPrintError(&err).to_string()), @@ -3173,9 +3169,7 @@ mod tests { use turbo_tasks::{util::FormatDuration, Value}; use turbopack_core::{ compile_time_info::CompileTimeInfo, - environment::{ - EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment, - }, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, target::{Arch, CompileTarget, Endianness, Libc, Platform}, }; @@ -3438,7 +3432,7 @@ mod tests { async fn resolve(var_graph: &VarGraph, val: JsValue) -> JsValue { turbo_tasks_testing::VcStorage::with(async { - let compile_time_info = CompileTimeInfo::builder(EnvironmentVc::new( + let compile_time_info = CompileTimeInfo::builder(Environment::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment { compile_target: CompileTarget { diff --git a/crates/turbopack-ecmascript/src/analyzer/well_known.rs b/crates/turbopack-ecmascript/src/analyzer/well_known.rs index cdb8006f01812f..ab4d7658bf4980 100644 --- a/crates/turbopack-ecmascript/src/analyzer/well_known.rs +++ b/crates/turbopack-ecmascript/src/analyzer/well_known.rs @@ -1,18 +1,19 @@ use std::mem::take; use anyhow::Result; -use turbopack_core::compile_time_info::CompileTimeInfoVc; +use turbo_tasks::Vc; +use turbopack_core::compile_time_info::CompileTimeInfo; use url::Url; use super::{ imports::ImportAnnotations, ConstantValue, JsValue, ModuleValue, WellKnownFunctionKind, WellKnownObjectKind, }; -use crate::analyzer::RequireContextValueVc; +use crate::analyzer::RequireContextValue; pub async fn replace_well_known( value: JsValue, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, ) -> Result<(JsValue, bool)> { Ok(match value { JsValue::Call(_, box JsValue::WellKnownFunction(kind), args) => ( @@ -49,7 +50,7 @@ pub async fn well_known_function_call( kind: WellKnownFunctionKind, _this: JsValue, args: Vec, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, ) -> Result { Ok(match kind { WellKnownFunctionKind::ObjectAssign => object_assign(args), @@ -344,7 +345,7 @@ pub fn require(args: Vec) -> JsValue { /// (try to) statically evaluate `require.context(...)()` pub async fn require_context_require( - val: RequireContextValueVc, + val: Vc, args: Vec, ) -> Result { if args.is_empty() { @@ -388,7 +389,7 @@ pub async fn require_context_require( /// (try to) statically evaluate `require.context(...).keys()` pub async fn require_context_require_keys( - val: RequireContextValueVc, + val: Vc, args: Vec, ) -> Result { Ok(if args.is_empty() { @@ -409,7 +410,7 @@ pub async fn require_context_require_keys( /// (try to) statically evaluate `require.context(...).resolve()` pub async fn require_context_require_resolve( - val: RequireContextValueVc, + val: Vc, args: Vec, ) -> Result { if args.len() != 1 { @@ -529,7 +530,7 @@ pub fn well_known_function_member(kind: WellKnownFunctionKind, prop: JsValue) -> pub async fn well_known_object_member( kind: WellKnownObjectKind, prop: JsValue, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, ) -> Result<(JsValue, bool)> { let new_value = match kind { WellKnownObjectKind::GlobalObject => global_object(prop), @@ -689,7 +690,7 @@ fn os_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue { async fn node_process_member( prop: JsValue, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, ) -> Result { Ok(match prop.as_str() { Some("arch") => compile_time_info diff --git a/crates/turbopack-ecmascript/src/chunk/content.rs b/crates/turbopack-ecmascript/src/chunk/content.rs index d6c0cfca6f82fd..571675531cf8fe 100644 --- a/crates/turbopack-ecmascript/src/chunk/content.rs +++ b/crates/turbopack-ecmascript/src/chunk/content.rs @@ -1,31 +1,31 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ chunk::{ - availability_info::AvailabilityInfo, chunk_content, chunk_content_split, - ChunkContentResult, ChunkVc, + availability_info::AvailabilityInfo, chunk_content, chunk_content_split, Chunk, + ChunkContentResult, }, - reference::AssetReferenceVc, + reference::AssetReference, }; use super::{ - item::EcmascriptChunkItemVc, - placeable::{EcmascriptChunkPlaceableVc, EcmascriptChunkPlaceablesVc}, - EcmascriptChunkingContextVc, + item::EcmascriptChunkItem, + placeable::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceables}, + EcmascriptChunkingContext, }; #[turbo_tasks::value] pub struct EcmascriptChunkContent { - pub chunk_items: Vec, - pub chunks: Vec, - pub async_chunk_group_entries: Vec, - pub external_asset_references: Vec, + pub chunk_items: Vec>>, + pub chunks: Vec>>, + pub async_chunk_group_entries: Vec>>, + pub external_asset_references: Vec>>, pub availability_info: AvailabilityInfo, } -impl From> for EcmascriptChunkContent { - fn from(from: ChunkContentResult) -> Self { +impl From>>> for EcmascriptChunkContent { + fn from(from: ChunkContentResult>>) -> Self { EcmascriptChunkContent { chunk_items: from.chunk_items, chunks: from.chunks, @@ -37,20 +37,23 @@ impl From> for EcmascriptChunkContent } #[turbo_tasks::value_impl] -impl EcmascriptChunkContentVc { +impl EcmascriptChunkContent { #[turbo_tasks::function] - pub fn filter(self, _other: EcmascriptChunkContentVc) -> EcmascriptChunkContentVc { + pub fn filter( + self: Vc, + _other: Vc, + ) -> Vc { todo!() } } #[turbo_tasks::function] pub(crate) fn ecmascript_chunk_content( - context: EcmascriptChunkingContextVc, - main_entries: EcmascriptChunkPlaceablesVc, - omit_entries: Option, + context: Vc>, + main_entries: Vc, + omit_entries: Option>, availability_info: Value, -) -> EcmascriptChunkContentVc { +) -> Vc { let mut chunk_content = ecmascript_chunk_content_internal(context, main_entries, availability_info); if let Some(omit_entries) = omit_entries { @@ -63,10 +66,10 @@ pub(crate) fn ecmascript_chunk_content( #[turbo_tasks::function] async fn ecmascript_chunk_content_internal( - context: EcmascriptChunkingContextVc, - entries: EcmascriptChunkPlaceablesVc, + context: Vc>, + entries: Vc, availability_info: Value, -) -> Result { +) -> Result> { let entries = entries.await?; let entries = entries.iter().copied(); @@ -78,10 +81,10 @@ async fn ecmascript_chunk_content_internal( return Ok(contents.into_iter().next().unwrap()); } - let mut all_chunk_items = IndexSet::::new(); - let mut all_chunks = IndexSet::::new(); - let mut all_async_chunk_group_entries = IndexSet::::new(); - let mut all_external_asset_references = IndexSet::::new(); + let mut all_chunk_items = IndexSet::>>::new(); + let mut all_chunks = IndexSet::>>::new(); + let mut all_async_chunk_group_entries = IndexSet::>>::new(); + let mut all_external_asset_references = IndexSet::>>::new(); for content in contents { let EcmascriptChunkContent { @@ -109,21 +112,25 @@ async fn ecmascript_chunk_content_internal( #[turbo_tasks::function] async fn ecmascript_chunk_content_single_entry( - context: EcmascriptChunkingContextVc, - entry: EcmascriptChunkPlaceableVc, + context: Vc>, + entry: Vc>, availability_info: Value, -) -> Result { - let asset = entry.as_asset(); +) -> Result> { + let asset = Vc::upcast(entry); - Ok(EcmascriptChunkContentVc::cell( - if let Some(res) = - chunk_content::(context.into(), asset, None, availability_info) - .await? + Ok(EcmascriptChunkContent::cell( + if let Some(res) = chunk_content::>( + Vc::upcast(context), + asset, + None, + availability_info, + ) + .await? { res } else { - chunk_content_split::( - context.into(), + chunk_content_split::>( + Vc::upcast(context), asset, None, availability_info, diff --git a/crates/turbopack-ecmascript/src/chunk/context.rs b/crates/turbopack-ecmascript/src/chunk/context.rs index 6a2243c5e77bfd..6b9ff4973dfdb6 100644 --- a/crates/turbopack-ecmascript/src/chunk/context.rs +++ b/crates/turbopack-ecmascript/src/chunk/context.rs @@ -1,8 +1,8 @@ use anyhow::Result; -use turbo_tasks::{primitives::BoolVc, ValueToString}; -use turbopack_core::chunk::{ChunkItem, ChunkingContext, ChunkingContextVc, ModuleId, ModuleIdVc}; +use turbo_tasks::{ValueToString, Vc}; +use turbopack_core::chunk::{ChunkItem, ChunkingContext, ModuleId}; -use super::item::EcmascriptChunkItemVc; +use super::item::EcmascriptChunkItem; /// [`EcmascriptChunkingContext`] must be implemented by [`ChunkingContext`] /// implementors that want to operate on [`EcmascriptChunk`]s. @@ -10,11 +10,14 @@ use super::item::EcmascriptChunkItemVc; pub trait EcmascriptChunkingContext: ChunkingContext { /// Whether chunk items generated by this chunking context should include /// the `__turbopack_refresh__` argument. - fn has_react_refresh(&self) -> BoolVc { - BoolVc::cell(false) + fn has_react_refresh(self: Vc) -> Vc { + Vc::cell(false) } - async fn chunk_item_id(&self, chunk_item: EcmascriptChunkItemVc) -> Result { + async fn chunk_item_id( + self: Vc, + chunk_item: Vc>, + ) -> Result> { let layer = self.layer(); let mut ident = chunk_item.asset_ident(); if !layer.await?.is_empty() { diff --git a/crates/turbopack-ecmascript/src/chunk/data.rs b/crates/turbopack-ecmascript/src/chunk/data.rs index 2c352c0b0ca425..cdb0c862bc2075 100644 --- a/crates/turbopack-ecmascript/src/chunk/data.rs +++ b/crates/turbopack-ecmascript/src/chunk/data.rs @@ -1,5 +1,6 @@ use serde::Serialize; -use turbopack_core::chunk::{ChunkData, ModuleIdReadRef}; +use turbo_tasks::ReadRef; +use turbopack_core::chunk::{ChunkData, ModuleId}; #[derive(Serialize, Hash, PartialEq, Eq)] #[serde(untagged)] @@ -9,9 +10,9 @@ pub enum EcmascriptChunkData<'a> { WithRuntimeInfo { path: &'a str, #[serde(skip_serializing_if = "<[_]>::is_empty", default)] - included: &'a [ModuleIdReadRef], + included: &'a [ReadRef], #[serde(skip_serializing_if = "<[_]>::is_empty", default)] - excluded: &'a [ModuleIdReadRef], + excluded: &'a [ReadRef], #[serde(skip_serializing_if = "<[_]>::is_empty", default)] module_chunks: &'a [String], }, diff --git a/crates/turbopack-ecmascript/src/chunk/item.rs b/crates/turbopack-ecmascript/src/chunk/item.rs index 3d7a75b6c97d8e..5bc8fe40e2a5f9 100644 --- a/crates/turbopack-ecmascript/src/chunk/item.rs +++ b/crates/turbopack-ecmascript/src/chunk/item.rs @@ -2,46 +2,42 @@ use std::io::Write; use anyhow::Result; use serde::{Deserialize, Serialize}; -use turbo_tasks::{primitives::StringVc, trace::TraceRawVcs, Value, ValueToString}; +use turbo_tasks::{trace::TraceRawVcs, Upcast, Value, ValueToString, Vc}; use turbo_tasks_fs::rope::Rope; use turbopack_core::{ - asset::AssetVc, + asset::Asset, chunk::{ - availability_info::AvailabilityInfo, available_assets::AvailableAssetsVc, ChunkItem, - ChunkItemVc, ChunkableAssetVc, ChunkingContext, ChunkingContextVc, FromChunkableAsset, - ModuleIdVc, + availability_info::AvailabilityInfo, available_assets::AvailableAssets, ChunkItem, + ChunkableAsset, ChunkingContext, FromChunkableAsset, ModuleId, }, - code_builder::{CodeBuilder, CodeVc}, + code_builder::{Code, CodeBuilder}, error::PrettyPrintError, - issue::{code_gen::CodeGenerationIssue, IssueSeverity}, + issue::{code_gen::CodeGenerationIssue, IssueExt, IssueSeverity}, }; -use super::{ - context::EcmascriptChunkingContextVc, placeable::EcmascriptChunkPlaceableVc, - EcmascriptChunkPlaceable, EcmascriptChunkingContext, -}; +use super::{EcmascriptChunkPlaceable, EcmascriptChunkingContext}; use crate::{ - manifest::{chunk_asset::ManifestChunkAssetVc, loader_item::ManifestLoaderItemVc}, + manifest::{chunk_asset::ManifestChunkAsset, loader_item::ManifestLoaderItem}, utils::FormatIter, - EcmascriptModuleContentVc, ParseResultSourceMapVc, + EcmascriptModuleContent, ParseResultSourceMap, }; #[turbo_tasks::value(shared)] #[derive(Default)] pub struct EcmascriptChunkItemContent { pub inner_code: Rope, - pub source_map: Option, + pub source_map: Option>, pub options: EcmascriptChunkItemOptions, pub placeholder_for_future_extensions: (), } #[turbo_tasks::value_impl] -impl EcmascriptChunkItemContentVc { +impl EcmascriptChunkItemContent { #[turbo_tasks::function] pub async fn new( - content: EcmascriptModuleContentVc, - context: EcmascriptChunkingContextVc, - ) -> Result { + content: Vc, + context: Vc>, + ) -> Result> { let refresh = *context.has_react_refresh().await?; let externals = *context.environment().node_externals().await?; @@ -72,7 +68,7 @@ impl EcmascriptChunkItemContentVc { } #[turbo_tasks::function] - pub async fn module_factory(self) -> Result { + pub async fn module_factory(self: Vc) -> Result> { let this = self.await?; let mut args = vec![ "r: __turbopack_require__", @@ -108,7 +104,7 @@ impl EcmascriptChunkItemContentVc { write!(code, "(({{ {} }}) => (() => {{\n\n", args,)?; } - let source_map = this.source_map.map(|sm| sm.as_generate_source_map()); + let source_map = this.source_map.map(Vc::upcast); code.push_source(&this.inner_code, source_map); if this.options.this { code += "\n}.call(this) })"; @@ -139,71 +135,91 @@ pub struct EcmascriptChunkItemOptions { #[turbo_tasks::value_trait] pub trait EcmascriptChunkItem: ChunkItem { - fn content(&self) -> EcmascriptChunkItemContentVc; + fn content(self: Vc) -> Vc; fn content_with_availability_info( - &self, + self: Vc, _availability_info: Value, - ) -> EcmascriptChunkItemContentVc { + ) -> Vc { self.content() } - fn chunking_context(&self) -> EcmascriptChunkingContextVc; + fn chunking_context(self: Vc) -> Vc>; } -#[turbo_tasks::value_impl] -impl EcmascriptChunkItemVc { +pub trait EcmascriptChunkItemExt { /// Returns the module id of this chunk item. - #[turbo_tasks::function] - pub fn id(self) -> ModuleIdVc { - self.chunking_context().chunk_item_id(self) + fn id(self: Vc) -> Vc; + + /// Generates the module factory for this chunk item. + fn code(self: Vc, availability_info: Value) -> Vc; +} + +impl EcmascriptChunkItemExt for T +where + T: Upcast>, +{ + /// Returns the module id of this chunk item. + fn id(self: Vc) -> Vc { + let chunk_item = Vc::upcast(self); + chunk_item.chunking_context().chunk_item_id(chunk_item) } /// Generates the module factory for this chunk item. - #[turbo_tasks::function] - pub async fn code(self, availability_info: Value) -> Result { - Ok( - match self - .content_with_availability_info(availability_info) - .module_factory() - .resolve() - .await - { - Ok(factory) => factory, - Err(error) => { - let id = self.id().to_string().await; - let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id); - let error = error.context(format!( - "An error occurred while generating the chunk item {}", - id - )); - let error_message = format!("{}", PrettyPrintError(&error)); - let js_error_message = serde_json::to_string(&error_message)?; - let issue = CodeGenerationIssue { - severity: IssueSeverity::Error.cell(), - path: self.asset_ident().path(), - title: StringVc::cell("Code generation for chunk item errored".to_string()), - message: StringVc::cell(error_message), - } - .cell(); - issue.as_issue().emit(); - let mut code = CodeBuilder::default(); - code += "(() => {{\n\n"; - writeln!(code, "throw new Error({error});", error = &js_error_message)?; - code += "\n}})"; - code.build().cell() - } - }, - ) + fn code(self: Vc, availability_info: Value) -> Vc { + module_factory_with_code_generation_issue(Vc::upcast(self), availability_info) } } +#[turbo_tasks::function] +async fn module_factory_with_code_generation_issue( + chunk_item: Vc>, + availability_info: Value, +) -> Result> { + Ok( + match chunk_item + .content_with_availability_info(availability_info) + .module_factory() + .resolve() + .await + { + Ok(factory) => factory, + Err(error) => { + let id = chunk_item.id().to_string().await; + let id = id.as_ref().map_or_else(|_| "unknown", |id| &**id); + let error = error.context(format!( + "An error occurred while generating the chunk item {}", + id + )); + let error_message = format!("{}", PrettyPrintError(&error)); + let js_error_message = serde_json::to_string(&error_message)?; + CodeGenerationIssue { + severity: IssueSeverity::Error.cell(), + path: chunk_item.asset_ident().path(), + title: Vc::cell("Code generation for chunk item errored".to_string()), + message: Vc::cell(error_message), + } + .cell() + .emit(); + let mut code = CodeBuilder::default(); + code += "(() => {{\n\n"; + writeln!(code, "throw new Error({error});", error = &js_error_message)?; + code += "\n}})"; + code.build().cell() + } + }, + ) +} + #[async_trait::async_trait] -impl FromChunkableAsset for EcmascriptChunkItemVc { - async fn from_asset(context: ChunkingContextVc, asset: AssetVc) -> Result> { - let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? else { +impl FromChunkableAsset for Box { + async fn from_asset( + context: Vc>, + asset: Vc>, + ) -> Result>> { + let Some(placeable) = Vc::try_resolve_sidecast::>(asset).await? else { return Ok(None); }; - let Some(context) = EcmascriptChunkingContextVc::resolve_from(context).await? else { + let Some(context) = Vc::try_resolve_sidecast::>(context).await? else { return Ok(None); }; @@ -211,11 +227,11 @@ impl FromChunkableAsset for EcmascriptChunkItemVc { } async fn from_async_asset( - context: ChunkingContextVc, - asset: ChunkableAssetVc, + context: Vc>, + asset: Vc>, availability_info: Value, - ) -> Result> { - let Some(context) = EcmascriptChunkingContextVc::resolve_from(context).await? else { + ) -> Result>> { + let Some(context) = Vc::try_resolve_sidecast::>(context).await? else { return Ok(None); }; @@ -224,26 +240,26 @@ impl FromChunkableAsset for EcmascriptChunkItemVc { AvailabilityInfo::Root { current_availability_root, } => AvailabilityInfo::Inner { - available_assets: AvailableAssetsVc::new(vec![current_availability_root]), - current_availability_root: asset.as_asset(), + available_assets: AvailableAssets::new(vec![current_availability_root]), + current_availability_root: Vc::upcast(asset), }, AvailabilityInfo::Inner { available_assets, current_availability_root, } => AvailabilityInfo::Inner { available_assets: available_assets.with_roots(vec![current_availability_root]), - current_availability_root: asset.as_asset(), + current_availability_root: Vc::upcast(asset), }, }; let manifest_asset = - ManifestChunkAssetVc::new(asset, context, Value::new(next_availability_info)); - Ok(Some(ManifestLoaderItemVc::new(manifest_asset).into())) + ManifestChunkAsset::new(asset, context, Value::new(next_availability_info)); + Ok(Some(Vc::upcast(ManifestLoaderItem::new(manifest_asset)))) } } #[turbo_tasks::value(transparent)] -pub struct EcmascriptChunkItemsChunk(Vec); +pub struct EcmascriptChunkItemsChunk(Vec>>); #[turbo_tasks::value(transparent)] -pub struct EcmascriptChunkItems(pub(super) Vec); +pub struct EcmascriptChunkItems(pub(super) Vec>>); diff --git a/crates/turbopack-ecmascript/src/chunk/mod.rs b/crates/turbopack-ecmascript/src/chunk/mod.rs index d35a650934e888..b0764fe8407cbc 100644 --- a/crates/turbopack-ecmascript/src/chunk/mod.rs +++ b/crates/turbopack-ecmascript/src/chunk/mod.rs @@ -8,61 +8,55 @@ use std::fmt::Write; use anyhow::{anyhow, bail, Result}; use indexmap::IndexSet; -use turbo_tasks::{ - primitives::{StringReadRef, StringVc, UsizeVc}, - TryJoinIterExt, Value, ValueToString, ValueToStringVc, -}; -use turbo_tasks_fs::FileSystemPathOptionVc; +use turbo_tasks::{ReadRef, TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPathOption; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, Chunk, ChunkGroupReferenceVc, ChunkItem, ChunkVc, - ChunkingContextVc, ChunksVc, ModuleIdsVc, + availability_info::AvailabilityInfo, Chunk, ChunkGroupReference, ChunkItem, + ChunkingContext, Chunks, ModuleIds, }, - ident::{AssetIdent, AssetIdentVc}, + ident::AssetIdent, introspect::{ - asset::{children_from_asset_references, content_to_details, IntrospectableAssetVc}, - Introspectable, IntrospectableChildrenVc, IntrospectableVc, + asset::{children_from_asset_references, content_to_details, IntrospectableAsset}, + Introspectable, IntrospectableChildren, }, - reference::AssetReferencesVc, + reference::AssetReferences, }; use self::content::ecmascript_chunk_content; pub use self::{ - content::{EcmascriptChunkContent, EcmascriptChunkContentVc}, - context::{EcmascriptChunkingContext, EcmascriptChunkingContextVc}, + content::EcmascriptChunkContent, + context::EcmascriptChunkingContext, data::EcmascriptChunkData, item::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemOptions, EcmascriptChunkItemVc, - }, - placeable::{ - EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkPlaceables, - EcmascriptChunkPlaceablesVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemExt, + EcmascriptChunkItemOptions, }, + placeable::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceables, EcmascriptExports}, }; use crate::utils::FormatIter; #[turbo_tasks::value] pub struct EcmascriptChunk { - pub context: EcmascriptChunkingContextVc, - pub main_entries: EcmascriptChunkPlaceablesVc, - pub omit_entries: Option, + pub context: Vc>, + pub main_entries: Vc, + pub omit_entries: Option>, pub availability_info: AvailabilityInfo, } #[turbo_tasks::value(transparent)] -pub struct EcmascriptChunks(Vec); +pub struct EcmascriptChunks(Vec>); #[turbo_tasks::value_impl] -impl EcmascriptChunkVc { +impl EcmascriptChunk { #[turbo_tasks::function] pub fn new_normalized( - context: EcmascriptChunkingContextVc, - main_entries: EcmascriptChunkPlaceablesVc, - omit_entries: Option, + context: Vc>, + main_entries: Vc, + omit_entries: Option>, availability_info: Value, - ) -> Self { + ) -> Vc { EcmascriptChunk { context, main_entries, @@ -74,17 +68,17 @@ impl EcmascriptChunkVc { #[turbo_tasks::function] pub async fn new( - context: ChunkingContextVc, - main_entry: EcmascriptChunkPlaceableVc, + context: Vc>, + main_entry: Vc>, availability_info: Value, - ) -> Result { - let Some(context) = EcmascriptChunkingContextVc::resolve_from(&context).await? else { + ) -> Result> { + let Some(context) = Vc::try_resolve_sidecast::>(context).await? else { bail!("Ecmascript chunking context not found"); }; Ok(Self::new_normalized( context, - EcmascriptChunkPlaceablesVc::cell(vec![main_entry]), + Vc::cell(vec![main_entry]), None, availability_info, )) @@ -92,38 +86,38 @@ impl EcmascriptChunkVc { #[turbo_tasks::function] pub async fn new_root( - context: ChunkingContextVc, - main_entry: EcmascriptChunkPlaceableVc, - ) -> Result { - let Some(context) = EcmascriptChunkingContextVc::resolve_from(&context).await? else { + context: Vc>, + main_entry: Vc>, + ) -> Result> { + let Some(context) = Vc::try_resolve_sidecast::>(context).await? else { bail!("Ecmascript chunking context not found"); }; Ok(Self::new_normalized( context, - EcmascriptChunkPlaceablesVc::cell(vec![main_entry]), + Vc::cell(vec![main_entry]), None, Value::new(AvailabilityInfo::Root { - current_availability_root: main_entry.as_asset(), + current_availability_root: Vc::upcast(main_entry), }), )) } #[turbo_tasks::function] pub async fn new_root_with_entries( - context: EcmascriptChunkingContextVc, - main_entry: EcmascriptChunkPlaceableVc, - other_entries: EcmascriptChunkPlaceablesVc, - ) -> Result { + context: Vc>, + main_entry: Vc>, + other_entries: Vc, + ) -> Result> { let mut main_entries = other_entries.await?.clone_value(); main_entries.push(main_entry); Ok(Self::new_normalized( context, - EcmascriptChunkPlaceablesVc::cell(main_entries), + Vc::cell(main_entries), None, Value::new(AvailabilityInfo::Root { - current_availability_root: main_entry.as_asset(), + current_availability_root: Vc::upcast(main_entry), }), )) } @@ -131,7 +125,7 @@ impl EcmascriptChunkVc { /// Return the most specific directory which contains all elements of the /// chunk. #[turbo_tasks::function] - pub async fn common_parent(self) -> Result { + pub async fn common_parent(self: Vc) -> Result> { let this = self.await?; let main_entries = this.main_entries.await?; let mut paths = main_entries @@ -147,16 +141,16 @@ impl EcmascriptChunkVc { while !*path.is_inside_or_equal(current).await? { let parent = current.parent().resolve().await?; if parent == current { - return Ok(FileSystemPathOptionVc::cell(None)); + return Ok(Vc::cell(None)); } current = parent; } } - Ok(FileSystemPathOptionVc::cell(Some(current))) + Ok(Vc::cell(Some(current))) } #[turbo_tasks::function] - pub async fn entry_ids(self) -> Result { + pub async fn entry_ids(self: Vc) -> Result> { let this = self.await?; let entries = this .main_entries @@ -164,14 +158,14 @@ impl EcmascriptChunkVc { .iter() .map(|&entry| entry.as_chunk_item(this.context).id()) .collect(); - Ok(ModuleIdsVc::cell(entries)) + Ok(Vc::cell(entries)) } #[turbo_tasks::function] pub async fn compare( - left: EcmascriptChunkVc, - right: EcmascriptChunkVc, - ) -> Result { + left: Vc, + right: Vc, + ) -> Result> { let a = left.await?; let b = right.await?; @@ -221,12 +215,12 @@ pub struct EcmascriptChunkComparison { #[turbo_tasks::value_impl] impl Chunk for EcmascriptChunk { #[turbo_tasks::function] - fn chunking_context(&self) -> ChunkingContextVc { - self.context.into() + fn chunking_context(&self) -> Vc> { + Vc::upcast(self.context) } #[turbo_tasks::function] - async fn parallel_chunks(&self) -> Result { + async fn parallel_chunks(&self) -> Result> { let content = ecmascript_chunk_content( self.context, self.main_entries, @@ -238,17 +232,17 @@ impl Chunk for EcmascriptChunk { for chunk in content.chunks.iter() { chunks.push(*chunk); } - Ok(ChunksVc::cell(chunks)) + Ok(Vc::cell(chunks)) } } #[turbo_tasks::value_impl] impl ValueToString for EcmascriptChunk { #[turbo_tasks::function] - async fn to_string(&self) -> Result { + async fn to_string(&self) -> Result> { async fn entries_to_string( - entries: Option, - ) -> Result> { + entries: Option>, + ) -> Result>> { Ok(if let Some(entries) = entries { entries .await? @@ -265,7 +259,7 @@ impl ValueToString for EcmascriptChunk { let omit_entry_strings = entries_to_string(self.omit_entries).await?; let omit_entry_strs = || omit_entry_strings.iter().flat_map(|s| [" - ", s.as_str()]); - Ok(StringVc::cell(format!( + Ok(Vc::cell(format!( "chunk {}{}", FormatIter(entry_strs), FormatIter(omit_entry_strs), @@ -274,9 +268,9 @@ impl ValueToString for EcmascriptChunk { } #[turbo_tasks::value_impl] -impl EcmascriptChunkVc { +impl EcmascriptChunk { #[turbo_tasks::function] - pub async fn chunk_content(self) -> Result { + pub async fn chunk_content(self: Vc) -> Result> { let this = self.await?; Ok(ecmascript_chunk_content( this.context, @@ -287,28 +281,28 @@ impl EcmascriptChunkVc { } #[turbo_tasks::function] - pub async fn main_entries(self) -> Result { + pub async fn main_entries(self: Vc) -> Result> { let this = self.await?; Ok(this.main_entries) } #[turbo_tasks::function] - pub async fn chunk_items_count(self) -> Result { - Ok(UsizeVc::cell(self.chunk_content().await?.chunk_items.len())) + pub async fn chunk_items_count(self: Vc) -> Result> { + Ok(Vc::cell(self.chunk_content().await?.chunk_items.len())) } } #[turbo_tasks::value_impl] impl Asset for EcmascriptChunk { #[turbo_tasks::function] - async fn ident(self_vc: EcmascriptChunkVc) -> Result { - let this = self_vc.await?; + async fn ident(self: Vc) -> Result> { + let this = self.await?; // All information that makes the chunk unique need to be encoded in the params. // All main entries are included let main_entries = this.main_entries.await?; - let main_entry_key = StringVc::cell(String::new()); + let main_entry_key = Vc::cell(String::new()); let mut assets = main_entries .iter() .map(|entry| (main_entry_key, entry.ident())) @@ -318,7 +312,7 @@ impl Asset for EcmascriptChunk { // entries. let path = if let [(_, ident)] = &assets[..] { ident.path() - } else if let &Some(common_parent) = &*self_vc.common_parent().await? { + } else if let &Some(common_parent) = &*self.common_parent().await? { common_parent } else { let (_, ident) = assets[0]; @@ -328,7 +322,7 @@ impl Asset for EcmascriptChunk { // All omit entries are included if let Some(omit_entries) = this.omit_entries { let omit_entries = omit_entries.await?; - let omit_entry_key = StringVc::cell("omit".to_string()); + let omit_entry_key = Vc::cell("omit".to_string()); for entry in omit_entries.iter() { assets.push((omit_entry_key, entry.ident())) } @@ -344,7 +338,7 @@ impl Asset for EcmascriptChunk { true }; if need_root { - let availability_root_key = StringVc::cell("current_availability_root".to_string()); + let availability_root_key = Vc::cell("current_availability_root".to_string()); assets.push((availability_root_key, ident)); } } @@ -353,14 +347,14 @@ impl Asset for EcmascriptChunk { // Available assets are included if let Some(available_assets) = this.availability_info.available_assets() { - modifiers.push(available_assets.hash().to_string()); + modifiers.push(Vc::cell(available_assets.hash().await?.to_string())); } // Simplify when it's only a single main entry without extra info let ident = if assets.len() == 1 && modifiers.is_empty() { assets[0].1 } else { - AssetIdentVc::new(Value::new(AssetIdent { + AssetIdent::new(Value::new(AssetIdent { path, query: None, fragment: None, @@ -374,13 +368,13 @@ impl Asset for EcmascriptChunk { } #[turbo_tasks::function] - fn content(_self_vc: EcmascriptChunkVc) -> Result { - bail!("EcmascriptChunkVc::content() is not implemented") + fn content(self: Vc) -> Result> { + bail!("EcmascriptChunk::content() is not implemented") } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptChunkVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let content = ecmascript_chunk_content( this.context, this.main_entries, @@ -393,40 +387,43 @@ impl Asset for EcmascriptChunk { references.push(*r); } for entry in content.async_chunk_group_entries.iter() { - references.push(ChunkGroupReferenceVc::new(this.context.into(), *entry).into()); + references.push(Vc::upcast(ChunkGroupReference::new( + Vc::upcast(this.context), + *entry, + ))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("ecmascript chunk".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("ecmascript chunk".to_string()) } #[turbo_tasks::function] -fn entry_module_key() -> StringVc { - StringVc::cell("entry module".to_string()) +fn entry_module_key() -> Vc { + Vc::cell("entry module".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for EcmascriptChunk { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(self_vc: EcmascriptChunkVc) -> StringVc { - self_vc.path().to_string() + fn title(self: Vc) -> Vc { + self.path().to_string() } #[turbo_tasks::function] - async fn details(self_vc: EcmascriptChunkVc) -> Result { - let content = content_to_details(self_vc.content()); + async fn details(self: Vc) -> Result> { + let content = content_to_details(self.content()); let mut details = String::new(); - let this = self_vc.await?; + let this = self.await?; let chunk_content = ecmascript_chunk_content( this.context, this.main_entries, @@ -440,17 +437,20 @@ impl Introspectable for EcmascriptChunk { } details += "\nContent:\n\n"; write!(details, "{}", content.await?)?; - Ok(StringVc::cell(details)) + Ok(Vc::cell(details)) } #[turbo_tasks::function] - async fn children(self_vc: EcmascriptChunkVc) -> Result { - let mut children = children_from_asset_references(self_vc.references()) + async fn children(self: Vc) -> Result> { + let mut children = children_from_asset_references(self.references()) .await? .clone_value(); - for &entry in &*self_vc.await?.main_entries.await? { - children.insert((entry_module_key(), IntrospectableAssetVc::new(entry.into()))); + for &entry in &*self.await?.main_entries.await? { + children.insert(( + entry_module_key(), + IntrospectableAsset::new(Vc::upcast(entry)), + )); } - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-ecmascript/src/chunk/placeable.rs b/crates/turbopack-ecmascript/src/chunk/placeable.rs index 2aad24ef88f219..08fe626c8a6ae2 100644 --- a/crates/turbopack-ecmascript/src/chunk/placeable.rs +++ b/crates/turbopack-ecmascript/src/chunk/placeable.rs @@ -1,32 +1,32 @@ -use anyhow::Result; -use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{ChunkableAsset, ChunkableAssetVc}, -}; +use turbo_tasks::Vc; +use turbopack_core::{asset::Asset, chunk::ChunkableAsset}; -use super::{item::EcmascriptChunkItemVc, EcmascriptChunkingContextVc}; -use crate::references::esm::EsmExportsVc; +use super::{item::EcmascriptChunkItem, EcmascriptChunkingContext}; +use crate::references::esm::EsmExports; #[turbo_tasks::value_trait] pub trait EcmascriptChunkPlaceable: ChunkableAsset + Asset { - fn as_chunk_item(&self, context: EcmascriptChunkingContextVc) -> EcmascriptChunkItemVc; - fn get_exports(&self) -> EcmascriptExportsVc; + fn as_chunk_item( + self: Vc, + context: Vc>, + ) -> Vc>; + fn get_exports(self: Vc) -> Vc; } #[turbo_tasks::value(transparent)] -pub struct EcmascriptChunkPlaceables(Vec); +pub struct EcmascriptChunkPlaceables(Vec>>); #[turbo_tasks::value_impl] -impl EcmascriptChunkPlaceablesVc { +impl EcmascriptChunkPlaceables { #[turbo_tasks::function] - pub fn empty() -> Self { - Self::cell(Vec::new()) + pub fn empty() -> Vc { + Vc::cell(Vec::new()) } } #[turbo_tasks::value(shared)] pub enum EcmascriptExports { - EsmExports(EsmExportsVc), + EsmExports(Vc), CommonJs, Value, None, diff --git a/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs b/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs index 2adb66120a2023..66cb3f69377b0e 100644 --- a/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs +++ b/crates/turbopack-ecmascript/src/chunk_group_files_asset.rs @@ -1,58 +1,59 @@ use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt, Value, ValueToString}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, + asset::{Asset, AssetContent, Assets}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetVc, ChunkingContext, ChunkingContextVc, EvaluatableAssetsVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, ChunkingContext, + EvaluatableAssets, }, - ident::AssetIdentVc, + ident::AssetIdent, introspect::{ - asset::{content_to_details, IntrospectableAssetVc}, - Introspectable, IntrospectableChildrenVc, IntrospectableVc, + asset::{content_to_details, IntrospectableAsset}, + Introspectable, IntrospectableChildren, }, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, + reference::{AssetReferences, SingleAssetReference}, }; use crate::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, - EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable, + EcmascriptChunkingContext, EcmascriptExports, }, utils::StringifyJs, - EcmascriptModuleAssetVc, + EcmascriptModuleAsset, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("chunk group files".to_string()) +fn modifier() -> Vc { + Vc::cell("chunk group files".to_string()) } /// An asset that exports a list of chunk URLs by putting the [asset] into a /// ChunkGroup with the provided ChunkingContext. #[turbo_tasks::value(shared)] pub struct ChunkGroupFilesAsset { - pub asset: ChunkableAssetVc, - pub client_root: FileSystemPathVc, - pub chunking_context: ChunkingContextVc, - pub runtime_entries: Option, + pub asset: Vc>, + pub client_root: Vc, + pub chunking_context: Vc>, + pub runtime_entries: Option>, } #[turbo_tasks::value_impl] -impl ChunkGroupFilesAssetVc { +impl ChunkGroupFilesAsset { #[turbo_tasks::function] - async fn chunks(self) -> Result { + async fn chunks(self: Vc) -> Result> { let this = self.await?; Ok( - if let Some(ecma) = EcmascriptModuleAssetVc::resolve_from(this.asset).await? { + if let Some(ecma) = + Vc::try_resolve_downcast_type::(this.asset).await? + { this.chunking_context.evaluated_chunk_group( ecma.as_root_chunk(this.chunking_context), this.runtime_entries - .unwrap_or_else(EvaluatableAssetsVc::empty) - .with_entry(ecma.into()), + .unwrap_or_else(EvaluatableAssets::empty) + .with_entry(Vc::upcast(ecma)), ) } else { this.chunking_context @@ -63,35 +64,35 @@ impl ChunkGroupFilesAssetVc { } #[turbo_tasks::function] -fn chunk_group_chunk_reference_description() -> StringVc { - StringVc::cell("chunk group chunk".to_string()) +fn chunk_group_chunk_reference_description() -> Vc { + Vc::cell("chunk group chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for ChunkGroupFilesAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.asset.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { unimplemented!() } #[turbo_tasks::function] - async fn references(self_vc: ChunkGroupFilesAssetVc) -> Result { - let chunks = self_vc.chunks(); + async fn references(self: Vc) -> Result> { + let chunks = self.chunks(); - Ok(AssetReferencesVc::cell( + Ok(Vc::cell( chunks .await? .iter() .copied() .map(|chunk| { - SingleAssetReferenceVc::new(chunk, chunk_group_chunk_reference_description()) + SingleAssetReference::new(chunk, chunk_group_chunk_reference_description()) }) - .map(Into::into) + .map(Vc::upcast) .collect(), )) } @@ -101,16 +102,15 @@ impl Asset for ChunkGroupFilesAsset { impl ChunkableAsset for ChunkGroupFilesAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: ChunkGroupFilesAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } @@ -118,48 +118,49 @@ impl ChunkableAsset for ChunkGroupFilesAsset { impl EcmascriptChunkPlaceable for ChunkGroupFilesAsset { #[turbo_tasks::function] async fn as_chunk_item( - self_vc: ChunkGroupFilesAssetVc, - context: EcmascriptChunkingContextVc, - ) -> Result { - let this = self_vc.await?; - Ok(ChunkGroupFilesChunkItem { - context, - client_root: this.client_root, - inner: self_vc, - chunk: this.asset.as_chunk( - context.into(), - Value::new(AvailabilityInfo::Root { - current_availability_root: this.asset.into(), - }), - ), - } - .cell() - .into()) + self: Vc, + context: Vc>, + ) -> Result>> { + let this = self.await?; + Ok(Vc::upcast( + ChunkGroupFilesChunkItem { + context, + client_root: this.client_root, + inner: self, + chunk: this.asset.as_chunk( + Vc::upcast(context), + Value::new(AvailabilityInfo::Root { + current_availability_root: Vc::upcast(this.asset), + }), + ), + } + .cell(), + )) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } } #[turbo_tasks::value] struct ChunkGroupFilesChunkItem { - context: EcmascriptChunkingContextVc, - client_root: FileSystemPathVc, - inner: ChunkGroupFilesAssetVc, - chunk: ChunkVc, + context: Vc>, + client_root: Vc, + inner: Vc, + chunk: Vc>, } #[turbo_tasks::value_impl] impl EcmascriptChunkItem for ChunkGroupFilesChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let chunks = self.inner.chunks(); let client_root = self.client_root.await?; let chunks_paths = chunks @@ -187,12 +188,12 @@ impl EcmascriptChunkItem for ChunkGroupFilesChunkItem { #[turbo_tasks::value_impl] impl ChunkItem for ChunkGroupFilesChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.inner.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.inner.references() } } @@ -200,31 +201,31 @@ impl ChunkItem for ChunkGroupFilesChunkItem { #[turbo_tasks::value_impl] impl Introspectable for ChunkGroupFilesAsset { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("chunk group files asset".to_string()) + fn ty(&self) -> Vc { + Vc::cell("chunk group files asset".to_string()) } #[turbo_tasks::function] - fn details(self_vc: ChunkGroupFilesAssetVc) -> StringVc { - content_to_details(self_vc.content()) + fn details(self: Vc) -> Vc { + content_to_details(self.content()) } #[turbo_tasks::function] - fn title(self_vc: ChunkGroupFilesAssetVc) -> StringVc { - self_vc.ident().to_string() + fn title(self: Vc) -> Vc { + self.ident().to_string() } #[turbo_tasks::function] - async fn children(self_vc: ChunkGroupFilesAssetVc) -> Result { + async fn children(self: Vc) -> Result> { let mut children = IndexSet::new(); - let chunk_ty = StringVc::cell("chunk".to_string()); - for &chunk in self_vc.chunks().await?.iter() { - children.insert((chunk_ty, IntrospectableAssetVc::new(chunk))); + let chunk_ty = Vc::cell("chunk".to_string()); + for &chunk in self.chunks().await?.iter() { + children.insert((chunk_ty, IntrospectableAsset::new(chunk))); } children.insert(( - StringVc::cell("inner asset".to_string()), - IntrospectableAssetVc::new(self_vc.await?.asset.into()), + Vc::cell("inner asset".to_string()), + IntrospectableAsset::new(Vc::upcast(self.await?.asset)), )); - Ok(IntrospectableChildrenVc::cell(children)) + Ok(Vc::cell(children)) } } diff --git a/crates/turbopack-ecmascript/src/code_gen.rs b/crates/turbopack-ecmascript/src/code_gen.rs index 943261825958a4..b135840effdc08 100644 --- a/crates/turbopack-ecmascript/src/code_gen.rs +++ b/crates/turbopack-ecmascript/src/code_gen.rs @@ -1,9 +1,9 @@ use serde::{Deserialize, Serialize}; use swc_core::ecma::visit::{AstParentKind, VisitMut}; -use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, Value}; +use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, Value, Vc}; use turbopack_core::chunk::availability_info::AvailabilityInfo; -use crate::chunk::EcmascriptChunkingContextVc; +use crate::chunk::EcmascriptChunkingContext; /// impl of code generation inferred from a AssetReference. /// This is rust only and can't be implemented by non-rust plugins. @@ -26,22 +26,25 @@ pub trait VisitorFactory: Send + Sync { #[turbo_tasks::value_trait] pub trait CodeGenerateable { - fn code_generation(&self, context: EcmascriptChunkingContextVc) -> CodeGenerationVc; + fn code_generation( + self: Vc, + context: Vc>, + ) -> Vc; } #[turbo_tasks::value_trait] pub trait CodeGenerateableWithAvailabilityInfo { fn code_generation( - &self, - context: EcmascriptChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> CodeGenerationVc; + ) -> Vc; } #[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat)] pub enum CodeGen { - CodeGenerateable(CodeGenerateableVc), - CodeGenerateableWithAvailabilityInfo(CodeGenerateableWithAvailabilityInfoVc), + CodeGenerateable(Vc>), + CodeGenerateableWithAvailabilityInfo(Vc>), } #[turbo_tasks::value(transparent)] @@ -70,20 +73,15 @@ pub fn path_to( /// possible visit methods. #[macro_export] macro_rules! create_visitor { - (exact $ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => { - $crate::create_visitor!(__ $ast_path.to_vec(), $name($arg: &mut $ty) $b) - }; - ($ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => { - $crate::create_visitor!(__ $crate::code_gen::path_to(&$ast_path, |n| { - matches!(n, swc_core::ecma::visit::AstParentKind::$ty(_)) - }), $name($arg: &mut $ty) $b) - }; - (__ $ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => {{ - struct Visitor { - $name: T, + // This rule needs to be first, otherwise we run into the following error: + // expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found `:` + // This is a regression on nightly. + (visit_mut_program($arg:ident: &mut Program) $b:block) => {{ + struct Visitor { + visit_mut_program: T, } - impl $crate::code_gen::VisitorFactory + impl $crate::code_gen::VisitorFactory for Box> { fn create<'a>(&'a self) -> Box { @@ -91,27 +89,35 @@ macro_rules! create_visitor { } } - impl<'a, T: Fn(&mut swc_core::ecma::ast::$ty) + Send + Sync> swc_core::ecma::visit::VisitMut + impl<'a, T: Fn(&mut swc_core::ecma::ast::Program) + Send + Sync> swc_core::ecma::visit::VisitMut for &'a Visitor { - fn $name(&mut self, $arg: &mut swc_core::ecma::ast::$ty) { - (self.$name)($arg); + fn visit_mut_program(&mut self, $arg: &mut swc_core::ecma::ast::Program) { + (self.visit_mut_program)($arg); } } ( - $ast_path, + Vec::new(), Box::new(Box::new(Visitor { - $name: move |$arg: &mut swc_core::ecma::ast::$ty| $b, + visit_mut_program: move |$arg: &mut swc_core::ecma::ast::Program| $b, })) as Box, ) }}; - (visit_mut_program($arg:ident: &mut Program) $b:block) => {{ - struct Visitor { - visit_mut_program: T, + (exact $ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => { + $crate::create_visitor!(__ $ast_path.to_vec(), $name($arg: &mut $ty) $b) + }; + ($ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => { + $crate::create_visitor!(__ $crate::code_gen::path_to(&$ast_path, |n| { + matches!(n, swc_core::ecma::visit::AstParentKind::$ty(_)) + }), $name($arg: &mut $ty) $b) + }; + (__ $ast_path:expr, $name:ident($arg:ident: &mut $ty:ident) $b:block) => {{ + struct Visitor { + $name: T, } - impl $crate::code_gen::VisitorFactory + impl $crate::code_gen::VisitorFactory for Box> { fn create<'a>(&'a self) -> Box { @@ -119,18 +125,18 @@ macro_rules! create_visitor { } } - impl<'a, T: Fn(&mut swc_core::ecma::ast::Program) + Send + Sync> swc_core::ecma::visit::VisitMut + impl<'a, T: Fn(&mut swc_core::ecma::ast::$ty) + Send + Sync> swc_core::ecma::visit::VisitMut for &'a Visitor { - fn visit_mut_program(&mut self, $arg: &mut swc_core::ecma::ast::Program) { - (self.visit_mut_program)($arg); + fn $name(&mut self, $arg: &mut swc_core::ecma::ast::$ty) { + (self.$name)($arg); } } ( - Vec::new(), + $ast_path, Box::new(Box::new(Visitor { - visit_mut_program: move |$arg: &mut swc_core::ecma::ast::Program| $b, + $name: move |$arg: &mut swc_core::ecma::ast::$ty| $b, })) as Box, ) }}; diff --git a/crates/turbopack-ecmascript/src/lib.rs b/crates/turbopack-ecmascript/src/lib.rs index a5744faa570c45..64be169619bfed 100644 --- a/crates/turbopack-ecmascript/src/lib.rs +++ b/crates/turbopack-ecmascript/src/lib.rs @@ -3,6 +3,8 @@ #![feature(iter_intersperse)] #![feature(int_roundings)] #![feature(slice_group_by)] +#![feature(async_fn_in_trait)] +#![feature(arbitrary_self_types)] #![recursion_limit = "256"] #![allow(clippy::too_many_arguments)] @@ -28,16 +30,14 @@ pub mod webpack; use anyhow::Result; use chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemVc, EcmascriptChunkPlaceablesVc, EcmascriptChunkVc, - EcmascriptChunkingContextVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceables, EcmascriptChunkingContext, }; -use code_gen::CodeGenerateableVc; +use code_gen::CodeGenerateable; +pub use parse::ParseResultSourceMap; use parse::{parse, ParseResult}; -pub use parse::{ParseResultSourceMap, ParseResultSourceMapVc}; use path_visitor::ApplyVisitors; -use references::AnalyzeEcmascriptModuleResult; -pub use references::TURBOPACK_HELPER; -pub use static_code::{StaticEcmascriptCode, StaticEcmascriptCodeVc}; +pub use references::{AnalyzeEcmascriptModuleResult, TURBOPACK_HELPER}; +pub use static_code::StaticEcmascriptCode; use swc_core::{ common::GLOBALS, ecma::{ @@ -46,48 +46,32 @@ use swc_core::{ }, }; pub use transform::{ - CustomTransformer, EcmascriptInputTransform, EcmascriptInputTransformsVc, - OptionTransformPlugin, OptionTransformPluginVc, TransformContext, TransformPlugin, - TransformPluginVc, UnsupportedServerActionIssue, + CustomTransformer, EcmascriptInputTransform, EcmascriptInputTransforms, OptionTransformPlugin, + TransformContext, TransformPlugin, UnsupportedServerActionIssue, }; -use turbo_tasks::{ - primitives::StringVc, trace::TraceRawVcs, RawVc, ReadRef, TryJoinIterExt, Value, ValueToString, -}; -use turbo_tasks_fs::{rope::Rope, FileSystemPathVc}; +use turbo_tasks::{trace::TraceRawVcs, RawVc, ReadRef, TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks_fs::{rope::Rope, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetOptionVc, AssetVc}, + asset::{Asset, AssetContent, AssetOption}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetVc, ChunkingContextVc, EvaluatableAsset, EvaluatableAssetVc, - }, - compile_time_info::CompileTimeInfoVc, - context::AssetContextVc, - ident::AssetIdentVc, - reference::{AssetReferencesReadRef, AssetReferencesVc}, - reference_type::InnerAssetsVc, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - ModulePartVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, ChunkingContext, + EvaluatableAsset, }, + compile_time_info::CompileTimeInfo, + context::AssetContext, + ident::AssetIdent, + reference::AssetReferences, + reference_type::InnerAssets, + resolve::{origin::ResolveOrigin, parse::Request, ModulePart}, }; -pub use self::references::AnalyzeEcmascriptModuleResultVc; use self::{ - chunk::{ - placeable::EcmascriptExportsReadRef, EcmascriptChunkItemContentVc, EcmascriptExportsVc, - }, - code_gen::{ - CodeGen, CodeGenerateableWithAvailabilityInfo, CodeGenerateableWithAvailabilityInfoVc, - VisitorFactory, - }, - parse::ParseResultVc, - tree_shake::asset::EcmascriptModulePartAssetVc, + chunk::{EcmascriptChunkItemContent, EcmascriptExports}, + code_gen::{CodeGen, CodeGenerateableWithAvailabilityInfo, VisitorFactory}, + tree_shake::asset::EcmascriptModulePartAsset, }; use crate::{ - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc}, - code_gen::CodeGenerateable, - references::analyze_ecmascript_module, + chunk::EcmascriptChunkPlaceable, references::analyze_ecmascript_module, transform::remove_shebang, }; @@ -126,30 +110,30 @@ pub enum EcmascriptModuleAssetType { } #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("ecmascript".to_string()) +fn modifier() -> Vc { + Vc::cell("ecmascript".to_string()) } #[derive(PartialEq, Eq, Clone, TraceRawVcs)] struct MemoizedSuccessfulAnalysis { operation: RawVc, - references: AssetReferencesReadRef, - exports: EcmascriptExportsReadRef, + references: ReadRef, + exports: ReadRef, } pub struct EcmascriptModuleAssetBuilder { - source: AssetVc, - context: AssetContextVc, + source: Vc>, + context: Vc>, ty: EcmascriptModuleAssetType, - transforms: EcmascriptInputTransformsVc, + transforms: Vc, options: EcmascriptOptions, - compile_time_info: CompileTimeInfoVc, - inner_assets: Option, - part: Option, + compile_time_info: Vc, + inner_assets: Option>, + part: Option>, } impl EcmascriptModuleAssetBuilder { - pub fn with_inner_assets(mut self, inner_assets: InnerAssetsVc) -> Self { + pub fn with_inner_assets(mut self, inner_assets: Vc) -> Self { self.inner_assets = Some(inner_assets); self } @@ -159,14 +143,14 @@ impl EcmascriptModuleAssetBuilder { self } - pub fn with_part(mut self, part: ModulePartVc) -> Self { + pub fn with_part(mut self, part: Vc) -> Self { self.part = Some(part); self } - pub fn build(self) -> AssetVc { + pub fn build(self) -> Vc> { let base = if let Some(inner_assets) = self.inner_assets { - EcmascriptModuleAssetVc::new_with_inner_assets( + EcmascriptModuleAsset::new_with_inner_assets( self.source, self.context, Value::new(self.ty), @@ -176,7 +160,7 @@ impl EcmascriptModuleAssetBuilder { inner_assets, ) } else { - EcmascriptModuleAssetVc::new( + EcmascriptModuleAsset::new( self.source, self.context, Value::new(self.ty), @@ -186,22 +170,22 @@ impl EcmascriptModuleAssetBuilder { ) }; if let Some(part) = self.part { - EcmascriptModulePartAssetVc::new(base, part).into() + Vc::upcast(EcmascriptModulePartAsset::new(base, part)) } else { - base.into() + Vc::upcast(base) } } } #[turbo_tasks::value] pub struct EcmascriptModuleAsset { - pub source: AssetVc, - pub context: AssetContextVc, + pub source: Vc>, + pub context: Vc>, pub ty: EcmascriptModuleAssetType, - pub transforms: EcmascriptInputTransformsVc, + pub transforms: Vc, pub options: EcmascriptOptions, - pub compile_time_info: CompileTimeInfoVc, - pub inner_assets: Option, + pub compile_time_info: Vc, + pub inner_assets: Option>, #[turbo_tasks(debug_ignore)] #[serde(skip)] last_successful_analysis: turbo_tasks::State>, @@ -209,15 +193,15 @@ pub struct EcmascriptModuleAsset { /// An optional [EcmascriptModuleAsset] #[turbo_tasks::value(transparent)] -pub struct OptionEcmascriptModuleAsset(Option); +pub struct OptionEcmascriptModuleAsset(Option>); -impl EcmascriptModuleAssetVc { +impl EcmascriptModuleAsset { pub fn builder( - source: AssetVc, - context: AssetContextVc, - transforms: EcmascriptInputTransformsVc, + source: Vc>, + context: Vc>, + transforms: Vc, options: EcmascriptOptions, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, ) -> EcmascriptModuleAssetBuilder { EcmascriptModuleAssetBuilder { source, @@ -233,16 +217,16 @@ impl EcmascriptModuleAssetVc { } #[turbo_tasks::value_impl] -impl EcmascriptModuleAssetVc { +impl EcmascriptModuleAsset { #[turbo_tasks::function] pub fn new( - source: AssetVc, - context: AssetContextVc, + source: Vc>, + context: Vc>, ty: Value, - transforms: EcmascriptInputTransformsVc, + transforms: Vc, options: Value, - compile_time_info: CompileTimeInfoVc, - ) -> Self { + compile_time_info: Vc, + ) -> Vc { Self::cell(EcmascriptModuleAsset { source, context, @@ -257,14 +241,14 @@ impl EcmascriptModuleAssetVc { #[turbo_tasks::function] pub fn new_with_inner_assets( - source: AssetVc, - context: AssetContextVc, + source: Vc>, + context: Vc>, ty: Value, - transforms: EcmascriptInputTransformsVc, + transforms: Vc, options: Value, - compile_time_info: CompileTimeInfoVc, - inner_assets: InnerAssetsVc, - ) -> Self { + compile_time_info: Vc, + inner_assets: Vc, + ) -> Vc { Self::cell(EcmascriptModuleAsset { source, context, @@ -279,19 +263,23 @@ impl EcmascriptModuleAssetVc { #[turbo_tasks::function] pub fn as_root_chunk_with_entries( - self_vc: EcmascriptModuleAssetVc, - context: EcmascriptChunkingContextVc, - other_entries: EcmascriptChunkPlaceablesVc, - ) -> ChunkVc { - EcmascriptChunkVc::new_root_with_entries(context, self_vc.into(), other_entries).into() + self: Vc, + context: Vc>, + other_entries: Vc, + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new_root_with_entries( + context, + Vc::upcast(self), + other_entries, + )) } #[turbo_tasks::function] - pub async fn analyze(self) -> Result { + pub async fn analyze(self: Vc) -> Result> { let this = self.await?; Ok(analyze_ecmascript_module( this.source, - self.as_resolve_origin(), + Vc::upcast(self), Value::new(this.ty), this.transforms, Value::new(this.options), @@ -301,14 +289,14 @@ impl EcmascriptModuleAssetVc { } #[turbo_tasks::function] - pub async fn failsafe_analyze(self) -> Result { + pub async fn failsafe_analyze(self: Vc) -> Result> { let this = self.await?; let result = self.analyze(); let result_value = result.await?; if result_value.successful { this.last_successful_analysis .set(Some(MemoizedSuccessfulAnalysis { - operation: result.into(), + operation: result.node, // We need to store the ReadRefs since we want to keep a snapshot. references: result_value.references.await?, exports: result_value.exports.await?, @@ -335,7 +323,7 @@ impl EcmascriptModuleAssetVc { } #[turbo_tasks::function] - pub async fn parse(self) -> Result { + pub async fn parse(self: Vc) -> Result> { let this = self.await?; Ok(parse(this.source, Value::new(this.ty), this.transforms)) } @@ -343,12 +331,14 @@ impl EcmascriptModuleAssetVc { /// Generates module contents without an analysis pass. This is useful for /// transforming code that is not a module, e.g. runtime code. #[turbo_tasks::function] - pub async fn module_content_without_analysis(self) -> Result { + pub async fn module_content_without_analysis( + self: Vc, + ) -> Result> { let this = self.await?; let parsed = parse(this.source, Value::new(this.ty), this.transforms); - Ok(EcmascriptModuleContentVc::new_without_analysis( + Ok(EcmascriptModuleContent::new_without_analysis( parsed, self.ident(), )) @@ -356,10 +346,10 @@ impl EcmascriptModuleAssetVc { #[turbo_tasks::function] pub async fn module_content( - self, - chunking_context: EcmascriptChunkingContextVc, + self: Vc, + chunking_context: Vc>, availability_info: Value, - ) -> Result { + ) -> Result> { let this = self.await?; if *self.analyze().needs_availability_info().await? { availability_info @@ -369,7 +359,7 @@ impl EcmascriptModuleAssetVc { let parsed = parse(this.source, Value::new(this.ty), this.transforms); - Ok(EcmascriptModuleContentVc::new( + Ok(EcmascriptModuleContent::new( parsed, self.ident(), chunking_context, @@ -382,27 +372,27 @@ impl EcmascriptModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for EcmascriptModuleAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { if let Some(inner_assets) = self.inner_assets { let mut ident = self.source.ident().await?.clone_value(); for (name, asset) in inner_assets.await?.iter() { - ident.add_asset(StringVc::cell(name.clone()), asset.ident()); + ident.add_asset(Vc::cell(name.clone()), asset.ident()); } ident.add_modifier(modifier()); - Ok(AssetIdentVc::new(Value::new(ident))) + Ok(AssetIdent::new(Value::new(ident))) } else { Ok(self.source.ident().with_modifier(modifier())) } } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } #[turbo_tasks::function] - async fn references(self_vc: EcmascriptModuleAssetVc) -> Result { - Ok(self_vc.failsafe_analyze().await?.references) + async fn references(self: Vc) -> Result> { + Ok(self.failsafe_analyze().await?.references) } } @@ -410,16 +400,15 @@ impl Asset for EcmascriptModuleAsset { impl ChunkableAsset for EcmascriptModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: EcmascriptModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } @@ -427,19 +416,18 @@ impl ChunkableAsset for EcmascriptModuleAsset { impl EcmascriptChunkPlaceable for EcmascriptModuleAsset { #[turbo_tasks::function] fn as_chunk_item( - self_vc: EcmascriptModuleAssetVc, - context: EcmascriptChunkingContextVc, - ) -> EcmascriptChunkItemVc { - ModuleChunkItemVc::cell(ModuleChunkItem { - module: self_vc, + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(ModuleChunkItem::cell(ModuleChunkItem { + module: self, context, - }) - .into() + })) } #[turbo_tasks::function] - async fn get_exports(self_vc: EcmascriptModuleAssetVc) -> Result { - Ok(self_vc.failsafe_analyze().await?.exports) + async fn get_exports(self: Vc) -> Result> { + Ok(self.failsafe_analyze().await?.exports) } } @@ -449,46 +437,44 @@ impl EvaluatableAsset for EcmascriptModuleAsset {} #[turbo_tasks::value_impl] impl ResolveOrigin for EcmascriptModuleAsset { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.source.ident().path() } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { + fn context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn get_inner_asset(&self, request: RequestVc) -> Result { - Ok(AssetOptionVc::cell( - if let Some(inner_assets) = &self.inner_assets { - if let Some(request) = request.await?.request() { - inner_assets.await?.get(&request).copied() - } else { - None - } + async fn get_inner_asset(&self, request: Vc) -> Result> { + Ok(Vc::cell(if let Some(inner_assets) = &self.inner_assets { + if let Some(request) = request.await?.request() { + inner_assets.await?.get(&request).copied() } else { None - }, - )) + } + } else { + None + })) } } #[turbo_tasks::value] struct ModuleChunkItem { - module: EcmascriptModuleAssetVc, - context: EcmascriptChunkingContextVc, + module: Vc, + context: Vc>, } #[turbo_tasks::value_impl] impl ChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.module.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.module.references() } } @@ -496,23 +482,23 @@ impl ChunkItem for ModuleChunkItem { #[turbo_tasks::value_impl] impl EcmascriptChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - fn content(self_vc: ModuleChunkItemVc) -> EcmascriptChunkItemContentVc { - self_vc.content_with_availability_info(Value::new(AvailabilityInfo::Untracked)) + fn content(self: Vc) -> Vc { + self.content_with_availability_info(Value::new(AvailabilityInfo::Untracked)) } #[turbo_tasks::function] async fn content_with_availability_info( - self_vc: ModuleChunkItemVc, + self: Vc, availability_info: Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result> { + let this = self.await?; let content = this.module.module_content(this.context, availability_info); - Ok(EcmascriptChunkItemContentVc::new(content, this.context)) + Ok(EcmascriptChunkItemContent::new(content, this.context)) } } @@ -520,21 +506,21 @@ impl EcmascriptChunkItem for ModuleChunkItem { #[turbo_tasks::value] pub struct EcmascriptModuleContent { pub inner_code: Rope, - pub source_map: Option, + pub source_map: Option>, pub is_esm: bool, } #[turbo_tasks::value_impl] -impl EcmascriptModuleContentVc { - /// Creates a new [`EcmascriptModuleContentVc`]. +impl EcmascriptModuleContent { + /// Creates a new [`Vc`]. #[turbo_tasks::function] pub async fn new( - parsed: ParseResultVc, - ident: AssetIdentVc, - context: EcmascriptChunkingContextVc, - analyzed: AnalyzeEcmascriptModuleResultVc, + parsed: Vc, + ident: Vc, + context: Vc>, + analyzed: Vc, availability_info: Value, - ) -> Result { + ) -> Result> { let AnalyzeEcmascriptModuleResult { references, code_generation, @@ -544,9 +530,13 @@ impl EcmascriptModuleContentVc { let mut code_gens = Vec::new(); for r in references.await?.iter() { let r = r.resolve().await?; - if let Some(code_gen) = CodeGenerateableWithAvailabilityInfoVc::resolve_from(r).await? { + if let Some(code_gen) = + Vc::try_resolve_sidecast::>(r).await? + { code_gens.push(code_gen.code_generation(context, availability_info)); - } else if let Some(code_gen) = CodeGenerateableVc::resolve_from(r).await? { + } else if let Some(code_gen) = + Vc::try_resolve_sidecast::>(r).await? + { code_gens.push(code_gen.code_generation(context)); } } @@ -579,22 +569,25 @@ impl EcmascriptModuleContentVc { gen_content_with_visitors(parsed, ident, visitors, root_visitors).await } - /// Creates a new [`EcmascriptModuleContentVc`] without an analysis pass. + /// Creates a new [`Vc`] without an analysis pass. #[turbo_tasks::function] - pub async fn new_without_analysis(parsed: ParseResultVc, ident: AssetIdentVc) -> Result { + pub async fn new_without_analysis( + parsed: Vc, + ident: Vc, + ) -> Result> { gen_content_with_visitors(parsed, ident, Vec::new(), Vec::new()).await } } async fn gen_content_with_visitors( - parsed: ParseResultVc, - ident: AssetIdentVc, + parsed: Vc, + ident: Vc, visitors: Vec<( &Vec, &dyn VisitorFactory, )>, root_visitors: Vec<&dyn VisitorFactory>, -) -> Result { +) -> Result> { let parsed = parsed.await?; if let ParseResult::Ok { diff --git a/crates/turbopack-ecmascript/src/manifest/chunk_asset.rs b/crates/turbopack-ecmascript/src/manifest/chunk_asset.rs index 8dfe461fffb4a4..cd4f0566375b3a 100644 --- a/crates/turbopack-ecmascript/src/manifest/chunk_asset.rs +++ b/crates/turbopack-ecmascript/src/manifest/chunk_asset.rs @@ -1,24 +1,21 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value}; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ - availability_info::AvailabilityInfo, ChunkVc, ChunkableAsset, ChunkableAssetVc, - ChunkingContext, ChunkingContextVc, - }, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, + asset::{Asset, AssetContent, Assets}, + chunk::{availability_info::AvailabilityInfo, Chunk, ChunkableAsset, ChunkingContext}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, }; use super::chunk_item::ManifestChunkItem; use crate::chunk::{ - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc, - EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceable, EcmascriptChunkingContext, + EcmascriptExports, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("manifest chunk".to_string()) +fn modifier() -> Vc { + Vc::cell("manifest chunk".to_string()) } /// The manifest chunk is deferred until requested by the manifest loader @@ -33,19 +30,19 @@ fn modifier() -> StringVc { /// import appears in. #[turbo_tasks::value(shared)] pub struct ManifestChunkAsset { - pub asset: ChunkableAssetVc, - pub chunking_context: EcmascriptChunkingContextVc, + pub asset: Vc>, + pub chunking_context: Vc>, pub availability_info: AvailabilityInfo, } #[turbo_tasks::value_impl] -impl ManifestChunkAssetVc { +impl ManifestChunkAsset { #[turbo_tasks::function] pub fn new( - asset: ChunkableAssetVc, - chunking_context: EcmascriptChunkingContextVc, + asset: Vc>, + chunking_context: Vc>, availability_info: Value, - ) -> Self { + ) -> Vc { Self::cell(ManifestChunkAsset { asset, chunking_context, @@ -54,59 +51,61 @@ impl ManifestChunkAssetVc { } #[turbo_tasks::function] - pub(super) async fn entry_chunk(self) -> Result { + pub(super) async fn entry_chunk(self: Vc) -> Result>> { let this = self.await?; Ok(this.asset.as_chunk( - this.chunking_context.into(), + Vc::upcast(this.chunking_context), Value::new(this.availability_info), )) } #[turbo_tasks::function] - pub(super) async fn chunks(self) -> Result { + pub(super) async fn chunks(self: Vc) -> Result> { let this = self.await?; Ok(this.chunking_context.chunk_group(self.entry_chunk())) } #[turbo_tasks::function] - pub async fn manifest_chunks(self) -> Result { + pub async fn manifest_chunks(self: Vc) -> Result> { let this = self.await?; Ok(this.chunking_context.chunk_group(self.as_chunk( - this.chunking_context.into(), + Vc::upcast(this.chunking_context), Value::new(this.availability_info), ))) } } #[turbo_tasks::function] -fn manifest_chunk_reference_description() -> StringVc { - StringVc::cell("manifest chunk".to_string()) +fn manifest_chunk_reference_description() -> Vc { + Vc::cell("manifest chunk".to_string()) } #[turbo_tasks::value_impl] impl Asset for ManifestChunkAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.asset.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { todo!() } #[turbo_tasks::function] - async fn references(self_vc: ManifestChunkAssetVc) -> Result { - let chunks = self_vc.chunks(); + async fn references(self: Vc) -> Result> { + let chunks = self.chunks(); - Ok(AssetReferencesVc::cell( + Ok(Vc::cell( chunks .await? .iter() .copied() .map(|chunk| { - SingleAssetReferenceVc::new(chunk, manifest_chunk_reference_description()) - .into() + Vc::upcast(SingleAssetReference::new( + chunk, + manifest_chunk_reference_description(), + )) }) .collect(), )) @@ -117,11 +116,15 @@ impl Asset for ManifestChunkAsset { impl ChunkableAsset for ManifestChunkAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: ManifestChunkAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new(context, self_vc.into(), availability_info).into() + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( + context, + Vc::upcast(self), + availability_info, + )) } } @@ -129,19 +132,20 @@ impl ChunkableAsset for ManifestChunkAsset { impl EcmascriptChunkPlaceable for ManifestChunkAsset { #[turbo_tasks::function] async fn as_chunk_item( - self_vc: ManifestChunkAssetVc, - context: EcmascriptChunkingContextVc, - ) -> Result { - Ok(ManifestChunkItem { - context, - manifest: self_vc, - } - .cell() - .into()) + self: Vc, + context: Vc>, + ) -> Result>> { + Ok(Vc::upcast( + ManifestChunkItem { + context, + manifest: self, + } + .cell(), + )) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } } diff --git a/crates/turbopack-ecmascript/src/manifest/chunk_item.rs b/crates/turbopack-ecmascript/src/manifest/chunk_item.rs index 5c9ab98796a475..54d4c74d4a1b30 100644 --- a/crates/turbopack-ecmascript/src/manifest/chunk_item.rs +++ b/crates/turbopack-ecmascript/src/manifest/chunk_item.rs @@ -1,18 +1,18 @@ use anyhow::Result; use indoc::formatdoc; -use turbo_tasks::TryJoinIterExt; +use turbo_tasks::{TryJoinIterExt, Vc}; use turbopack_core::{ asset::Asset, - chunk::{ChunkDataVc, ChunkItem, ChunkItemVc, ChunkingContext, ChunksDataVc}, - ident::AssetIdentVc, - reference::AssetReferencesVc, + chunk::{ChunkData, ChunkItem, ChunkingContext, ChunksData}, + ident::AssetIdent, + reference::AssetReferences, }; -use super::chunk_asset::ManifestChunkAssetVc; +use super::chunk_asset::ManifestChunkAsset; use crate::{ chunk::{ data::EcmascriptChunkData, EcmascriptChunkItem, EcmascriptChunkItemContent, - EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkingContextVc, + EcmascriptChunkingContext, }, utils::StringifyJs, }; @@ -22,16 +22,16 @@ use crate::{ /// __turbopack_import__ the actual module that was dynamically imported. #[turbo_tasks::value(shared)] pub(super) struct ManifestChunkItem { - pub context: EcmascriptChunkingContextVc, - pub manifest: ManifestChunkAssetVc, + pub context: Vc>, + pub manifest: Vc, } #[turbo_tasks::value_impl] -impl ManifestChunkItemVc { +impl ManifestChunkItem { #[turbo_tasks::function] - async fn chunks_data(self) -> Result { + async fn chunks_data(self: Vc) -> Result> { let this = self.await?; - Ok(ChunkDataVc::from_assets( + Ok(ChunkData::from_assets( this.context.output_root(), this.manifest.chunks(), )) @@ -41,13 +41,13 @@ impl ManifestChunkItemVc { #[turbo_tasks::value_impl] impl EcmascriptChunkItem for ManifestChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn content(self_vc: ManifestChunkItemVc) -> Result { - let chunks_data = self_vc.chunks_data().await?; + async fn content(self: Vc) -> Result> { + let chunks_data = self.chunks_data().await?; let chunks_data = chunks_data.iter().try_join().await?; let chunks_data: Vec<_> = chunks_data .iter() @@ -72,19 +72,19 @@ impl EcmascriptChunkItem for ManifestChunkItem { #[turbo_tasks::value_impl] impl ChunkItem for ManifestChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.manifest.ident() } #[turbo_tasks::function] - async fn references(self_vc: ManifestChunkItemVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let mut references = this.manifest.references().await?.clone_value(); - for chunk_data in &*self_vc.chunks_data().await? { + for chunk_data in &*self.chunks_data().await? { references.extend(chunk_data.references().await?.iter().copied()); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } diff --git a/crates/turbopack-ecmascript/src/manifest/loader_item.rs b/crates/turbopack-ecmascript/src/manifest/loader_item.rs index a44a2255c74b8e..99c81f84c91ed9 100644 --- a/crates/turbopack-ecmascript/src/manifest/loader_item.rs +++ b/crates/turbopack-ecmascript/src/manifest/loader_item.rs @@ -2,27 +2,26 @@ use std::io::Write as _; use anyhow::{anyhow, Result}; use indoc::writedoc; -use turbo_tasks::{primitives::StringVc, TryJoinIterExt}; +use turbo_tasks::{TryJoinIterExt, Vc}; use turbopack_core::{ asset::Asset, - chunk::{ChunkDataVc, ChunkItem, ChunkItemVc, ChunkingContext, ChunksDataVc}, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, + chunk::{ChunkData, ChunkItem, ChunkingContext, ChunksData}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, }; -use super::chunk_asset::ManifestChunkAssetVc; +use super::chunk_asset::ManifestChunkAsset; use crate::{ chunk::{ - data::EcmascriptChunkData, EcmascriptChunkItem, EcmascriptChunkItemContent, - EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, EcmascriptChunkPlaceable, - EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc, + data::EcmascriptChunkData, item::EcmascriptChunkItemExt, EcmascriptChunkItem, + EcmascriptChunkItemContent, EcmascriptChunkPlaceable, EcmascriptChunkingContext, }, utils::StringifyJs, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("loader".to_string()) +fn modifier() -> Vc { + Vc::cell("loader".to_string()) } /// The manifest loader item is shipped in the same chunk that uses the dynamic @@ -39,22 +38,22 @@ fn modifier() -> StringVc { /// import appears in. #[turbo_tasks::value] pub struct ManifestLoaderItem { - manifest: ManifestChunkAssetVc, + manifest: Vc, } #[turbo_tasks::value_impl] -impl ManifestLoaderItemVc { +impl ManifestLoaderItem { #[turbo_tasks::function] - pub fn new(manifest: ManifestChunkAssetVc) -> Self { + pub fn new(manifest: Vc) -> Vc { Self::cell(ManifestLoaderItem { manifest }) } #[turbo_tasks::function] - pub async fn chunks_data(self) -> Result { + pub async fn chunks_data(self: Vc) -> Result> { let this = self.await?; let chunks = this.manifest.manifest_chunks(); let manifest = this.manifest.await?; - Ok(ChunkDataVc::from_assets( + Ok(ChunkData::from_assets( manifest.chunking_context.output_root(), chunks, )) @@ -62,20 +61,20 @@ impl ManifestLoaderItemVc { } #[turbo_tasks::function] -fn manifest_loader_chunk_reference_description() -> StringVc { - StringVc::cell("manifest loader chunk".to_string()) +fn manifest_loader_chunk_reference_description() -> Vc { + Vc::cell("manifest loader chunk".to_string()) } #[turbo_tasks::value_impl] impl ChunkItem for ManifestLoaderItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.manifest.ident().with_modifier(modifier()) } #[turbo_tasks::function] - async fn references(self_vc: ManifestLoaderItemVc) -> Result { - let this = self_vc.await?; + async fn references(self: Vc) -> Result> { + let this = self.await?; let chunks = this.manifest.manifest_chunks(); @@ -83,39 +82,40 @@ impl ChunkItem for ManifestLoaderItem { .await? .iter() .map(|chunk| { - SingleAssetReferenceVc::new(*chunk, manifest_loader_chunk_reference_description()) - .into() + Vc::upcast(SingleAssetReference::new( + *chunk, + manifest_loader_chunk_reference_description(), + )) }) .collect(); - for chunk_data in &*self_vc.chunks_data().await? { + for chunk_data in &*self.chunks_data().await? { references.extend(chunk_data.references().await?.iter().copied()); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::value_impl] impl EcmascriptChunkItem for ManifestLoaderItem { #[turbo_tasks::function] - async fn chunking_context(&self) -> Result { + async fn chunking_context(&self) -> Result>> { Ok(self.manifest.await?.chunking_context) } #[turbo_tasks::function] - async fn content(self_vc: ManifestLoaderItemVc) -> Result { - let this = &*self_vc.await?; + async fn content(self: Vc) -> Result> { + let this = &*self.await?; let mut code = Vec::new(); let manifest = this.manifest.await?; - let asset = manifest.asset.as_asset(); // We need several items in order for a dynamic import to fully load. First, we // need the chunk path of the manifest chunk, relative from the output root. The // chunk is a servable file, which will contain the manifest chunk item, which // will perform the actual chunk traversal and generate load statements. - let chunks_server_data = &*self_vc.chunks_data().await?.iter().try_join().await?; + let chunks_server_data = &*self.chunks_data().await?.iter().try_join().await?; // We also need the manifest chunk item's id, which points to a CJS module that // exports a promise for all of the necessary chunk loads. @@ -127,9 +127,10 @@ impl EcmascriptChunkItem for ManifestLoaderItem { // Finally, we need the id of the module that we're actually trying to // dynamically import. - let placeable = EcmascriptChunkPlaceableVc::resolve_from(asset) - .await? - .ok_or_else(|| anyhow!("asset is not placeable in ecmascript chunk"))?; + let placeable = + Vc::try_resolve_downcast::>(manifest.asset) + .await? + .ok_or_else(|| anyhow!("asset is not placeable in ecmascript chunk"))?; let dynamic_id = &*placeable .as_chunk_item(manifest.chunking_context) .id() diff --git a/crates/turbopack-ecmascript/src/parse.rs b/crates/turbopack-ecmascript/src/parse.rs index 83b2c8e1581832..d6fa1c8eb75045 100644 --- a/crates/turbopack-ecmascript/src/parse.rs +++ b/crates/turbopack-ecmascript/src/parse.rs @@ -19,18 +19,14 @@ use swc_core::{ visit::VisitMutWith, }, }; -use turbo_tasks::{ - primitives::{StringVc, U64Vc}, - util::WrapFuture, - Value, ValueToString, -}; -use turbo_tasks_fs::{FileContent, FileSystemPath, FileSystemPathVc}; +use turbo_tasks::{util::WrapFuture, Value, ValueToString, Vc}; +use turbo_tasks_fs::{FileContent, FileSystemPath}; use turbo_tasks_hash::hash_xxh3_hash64; use turbopack_core::{ - asset::{Asset, AssetContent, AssetVc}, + asset::{Asset, AssetContent}, error::PrettyPrintError, - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, + issue::{Issue, IssueExt, IssueSeverity}, + source_map::{GenerateSourceMap, OptionSourceMap}, SOURCE_MAP_ROOT_NAME, }; use turbopack_swc_utils::emitter::IssueEmitter; @@ -38,7 +34,7 @@ use turbopack_swc_utils::emitter::IssueEmitter; use super::EcmascriptModuleAssetType; use crate::{ analyzer::graph::EvalContext, - transform::{EcmascriptInputTransformsVc, TransformContext}, + transform::{EcmascriptInputTransforms, TransformContext}, EcmascriptInputTransform, }; @@ -105,13 +101,13 @@ impl ParseResultSourceMap { #[turbo_tasks::value_impl] impl GenerateSourceMap for ParseResultSourceMap { #[turbo_tasks::function] - fn generate_source_map(&self) -> OptionSourceMapVc { + fn generate_source_map(&self) -> Vc { let map = self.source_map.build_source_map_with_config( &self.mappings, None, InlineSourcesContentConfig {}, ); - OptionSourceMapVc::cell(Some( + Vc::cell(Some( turbopack_core::source_map::SourceMap::new_regular(map).cell(), )) } @@ -139,10 +135,10 @@ impl SourceMapGenConfig for InlineSourcesContentConfig { #[turbo_tasks::function] pub async fn parse( - source: AssetVc, + source: Vc>, ty: Value, - transforms: EcmascriptInputTransformsVc, -) -> Result { + transforms: Vc, +) -> Result> { match parse_internal(source, ty, transforms).await { Ok(result) => Ok(result), Err(error) => Err(error.context(format!( @@ -153,10 +149,10 @@ pub async fn parse( } async fn parse_internal( - source: AssetVc, + source: Vc>, ty: Value, - transforms: EcmascriptInputTransformsVc, -) -> Result { + transforms: Vc, +) -> Result> { let content = source.content(); let fs_path_vc = source.ident().path(); let fs_path = &*fs_path_vc.await?; @@ -171,7 +167,6 @@ async fn parse_internal( error: PrettyPrintError(&error).to_string(), } .cell() - .as_issue() .emit(); return Ok(ParseResult::Unparseable.cell()); } @@ -209,7 +204,6 @@ async fn parse_internal( error: PrettyPrintError(&error).to_string(), } .cell() - .as_issue() .emit(); ParseResult::Unparseable.cell() } @@ -221,14 +215,14 @@ async fn parse_internal( async fn parse_content( string: String, - fs_path_vc: FileSystemPathVc, + fs_path_vc: Vc, fs_path: &FileSystemPath, ident: &str, file_path_hash: u128, - source: AssetVc, + source: Vc>, ty: EcmascriptModuleAssetType, transforms: &[EcmascriptInputTransform], -) -> Result { +) -> Result> { let source_map: Arc = Default::default(); let handler = Handler::with_emitter( true, @@ -243,11 +237,6 @@ async fn parse_content( let globals_ref = &globals; let helpers = GLOBALS.set(globals_ref, || Helpers::new(true)); let mut result = WrapFuture::new( - |f, cx| { - GLOBALS.set(globals_ref, || { - HANDLER.set(&handler, || HELPERS.set(&helpers, || f.poll(cx))) - }) - }, async { let file_name = FileName::Custom(ident.to_string()); let fm = source_map.new_source_file(file_name.clone(), string); @@ -360,6 +349,11 @@ async fn parse_content( source_map, }) }, + |f, cx| { + GLOBALS.set(globals_ref, || { + HANDLER.set(&handler, || HELPERS.set(&helpers, || f.poll(cx))) + }) + }, ) .await?; if let ParseResult::Ok { @@ -373,44 +367,44 @@ async fn parse_content( } #[turbo_tasks::function] -async fn hash_ident(ident: StringVc) -> Result { +async fn hash_ident(ident: Vc) -> Result> { let ident = &*ident.await?; - Ok(U64Vc::cell(hash_xxh3_hash64(ident))) + Ok(Vc::cell(hash_xxh3_hash64(ident))) } #[turbo_tasks::value] struct ReadSourceIssue { - source: AssetVc, + source: Vc>, error: String, } #[turbo_tasks::value_impl] impl Issue for ReadSourceIssue { #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.source.ident().path() } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Reading source code for parsing failed".to_string()) + fn title(&self) -> Vc { + Vc::cell("Reading source code for parsing failed".to_string()) } #[turbo_tasks::function] - fn description(&self) -> StringVc { - StringVc::cell(format!( + fn description(&self) -> Vc { + Vc::cell(format!( "An unexpected error happened while trying to read the source code to parse: {}", self.error )) } #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Error.cell() } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("parse".to_string()) + fn category(&self) -> Vc { + Vc::cell("parse".to_string()) } } diff --git a/crates/turbopack-ecmascript/src/references/amd.rs b/crates/turbopack-ecmascript/src/references/amd.rs index 4b58932cda1388..8d336262241776 100644 --- a/crates/turbopack-ecmascript/src/references/amd.rs +++ b/crates/turbopack-ecmascript/src/references/amd.rs @@ -11,46 +11,42 @@ use swc_core::{ quote, quote_expr, }; use turbo_tasks::{ - debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs, TryJoinIterExt, Value, - ValueToString, ValueToStringVc, + debug::ValueDebugFormat, trace::TraceRawVcs, ReadRef, TryJoinIterExt, Value, ValueToString, Vc, }; use turbopack_core::{ - chunk::{ChunkableAssetReference, ChunkableAssetReferenceVc}, - issue::{IssueSourceVc, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, - resolve::{origin::ResolveOriginVc, parse::RequestVc, ResolveResultVc}, + chunk::ChunkableAssetReference, + issue::{IssueSource, OptionIssueSource}, + reference::AssetReference, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; -use super::pattern_mapping::{PatternMappingVc, ResolveType::Cjs}; +use super::pattern_mapping::{PatternMapping, ResolveType::Cjs}; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, - references::{ - pattern_mapping::{PatternMapping, PatternMappingReadRef}, - AstPathVc, - }, + references::AstPath, resolve::{cjs_resolve, try_to_severity}, }; #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct AmdDefineAssetReference { - origin: ResolveOriginVc, - request: RequestVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + issue_source: Vc, in_try: bool, } #[turbo_tasks::value_impl] -impl AmdDefineAssetReferenceVc { +impl AmdDefineAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { Self::cell(AmdDefineAssetReference { origin, request, @@ -63,11 +59,11 @@ impl AmdDefineAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for AmdDefineAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ) } @@ -76,8 +72,8 @@ impl AssetReference for AmdDefineAssetReference { #[turbo_tasks::value_impl] impl ValueToString for AmdDefineAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "AMD define dependency {}", self.request.to_string().await?, ))) @@ -91,7 +87,7 @@ impl ChunkableAssetReference for AmdDefineAssetReference {} ValueDebugFormat, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs, Copy, Clone, )] pub enum AmdDefineDependencyElement { - Request(RequestVc), + Request(Vc), Exports, Module, Require, @@ -110,22 +106,22 @@ pub enum AmdDefineFactoryType { #[derive(Debug)] pub struct AmdDefineWithDependenciesCodeGen { dependencies_requests: Vec, - origin: ResolveOriginVc, - path: AstPathVc, + origin: Vc>, + path: Vc, factory_type: AmdDefineFactoryType, - issue_source: IssueSourceVc, + issue_source: Vc, in_try: bool, } -impl AmdDefineWithDependenciesCodeGenVc { +impl AmdDefineWithDependenciesCodeGen { pub fn new( dependencies_requests: Vec, - origin: ResolveOriginVc, - path: AstPathVc, + origin: Vc>, + path: Vc, factory_type: AmdDefineFactoryType, - issue_source: IssueSourceVc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { Self::cell(AmdDefineWithDependenciesCodeGen { dependencies_requests, origin, @@ -142,8 +138,8 @@ impl CodeGenerateable for AmdDefineWithDependenciesCodeGen { #[turbo_tasks::function] async fn code_generation( &self, - context: EcmascriptChunkingContextVc, - ) -> Result { + context: Vc>, + ) -> Result> { let mut visitors = Vec::new(); let resolved_elements = self @@ -153,14 +149,14 @@ impl CodeGenerateable for AmdDefineWithDependenciesCodeGen { Ok(match element { AmdDefineDependencyElement::Request(request) => { ResolvedElement::PatternMapping( - PatternMappingVc::resolve_request( + PatternMapping::resolve_request( *request, self.origin, - context.into(), + Vc::upcast(context), cjs_resolve( self.origin, *request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ), Value::new(Cjs), @@ -197,7 +193,7 @@ impl CodeGenerateable for AmdDefineWithDependenciesCodeGen { } enum ResolvedElement { - PatternMapping(PatternMappingReadRef, Option), + PatternMapping(ReadRef, Option), Expr(Expr), } diff --git a/crates/turbopack-ecmascript/src/references/cjs.rs b/crates/turbopack-ecmascript/src/references/cjs.rs index aea9912a611556..d692ade49dae91 100644 --- a/crates/turbopack-ecmascript/src/references/cjs.rs +++ b/crates/turbopack-ecmascript/src/references/cjs.rs @@ -3,41 +3,41 @@ use swc_core::{ common::DUMMY_SP, ecma::ast::{Callee, Expr, ExprOrSpread, Ident, ObjectLit}, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - chunk::{ChunkableAssetReference, ChunkableAssetReferenceVc}, - issue::{IssueSourceVc, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, - resolve::{origin::ResolveOriginVc, parse::RequestVc, ResolveResultVc}, + chunk::ChunkableAssetReference, + issue::{IssueSource, OptionIssueSource}, + reference::AssetReference, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; -use super::pattern_mapping::{PatternMapping, PatternMappingVc, ResolveType::Cjs}; +use super::pattern_mapping::{PatternMapping, ResolveType::Cjs}; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, - references::{util::throw_module_not_found_expr, AstPathVc}, + references::{util::throw_module_not_found_expr, AstPath}, resolve::{cjs_resolve, try_to_severity}, }; #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct CjsAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub issue_source: IssueSourceVc, + pub origin: Vc>, + pub request: Vc, + pub issue_source: Vc, pub in_try: bool, } #[turbo_tasks::value_impl] -impl CjsAssetReferenceVc { +impl CjsAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { Self::cell(CjsAssetReference { origin, request, @@ -50,11 +50,11 @@ impl CjsAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for CjsAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ) } @@ -63,8 +63,8 @@ impl AssetReference for CjsAssetReference { #[turbo_tasks::value_impl] impl ValueToString for CjsAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "generic commonjs {}", self.request.to_string().await?, ))) @@ -77,23 +77,23 @@ impl ChunkableAssetReference for CjsAssetReference {} #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct CjsRequireAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub path: AstPathVc, - pub issue_source: IssueSourceVc, + pub origin: Vc>, + pub request: Vc, + pub path: Vc, + pub issue_source: Vc, pub in_try: bool, } #[turbo_tasks::value_impl] -impl CjsRequireAssetReferenceVc { +impl CjsRequireAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - path: AstPathVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + path: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { Self::cell(CjsRequireAssetReference { origin, request, @@ -107,11 +107,11 @@ impl CjsRequireAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for CjsRequireAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ) } @@ -120,8 +120,8 @@ impl AssetReference for CjsRequireAssetReference { #[turbo_tasks::value_impl] impl ValueToString for CjsRequireAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "require {}", self.request.to_string().await?, ))) @@ -136,16 +136,16 @@ impl CodeGenerateable for CjsRequireAssetReference { #[turbo_tasks::function] async fn code_generation( &self, - context: EcmascriptChunkingContextVc, - ) -> Result { - let pm = PatternMappingVc::resolve_request( + context: Vc>, + ) -> Result> { + let pm = PatternMapping::resolve_request( self.request, self.origin, - context.into(), + Vc::upcast(context), cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ), Value::new(Cjs), @@ -201,23 +201,23 @@ impl CodeGenerateable for CjsRequireAssetReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct CjsRequireResolveAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub path: AstPathVc, - pub issue_source: IssueSourceVc, + pub origin: Vc>, + pub request: Vc, + pub path: Vc, + pub issue_source: Vc, pub in_try: bool, } #[turbo_tasks::value_impl] -impl CjsRequireResolveAssetReferenceVc { +impl CjsRequireResolveAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - path: AstPathVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + path: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { Self::cell(CjsRequireResolveAssetReference { origin, request, @@ -231,11 +231,11 @@ impl CjsRequireResolveAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for CjsRequireResolveAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ) } @@ -244,8 +244,8 @@ impl AssetReference for CjsRequireResolveAssetReference { #[turbo_tasks::value_impl] impl ValueToString for CjsRequireResolveAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "require.resolve {}", self.request.to_string().await?, ))) @@ -260,16 +260,16 @@ impl CodeGenerateable for CjsRequireResolveAssetReference { #[turbo_tasks::function] async fn code_generation( &self, - context: EcmascriptChunkingContextVc, - ) -> Result { - let pm = PatternMappingVc::resolve_request( + context: Vc>, + ) -> Result> { + let pm = PatternMapping::resolve_request( self.request, self.origin, - context.into(), + Vc::upcast(context), cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ), Value::new(Cjs), @@ -307,7 +307,7 @@ impl CodeGenerateable for CjsRequireResolveAssetReference { #[turbo_tasks::value(shared)] #[derive(Hash, Debug)] pub struct CjsRequireCacheAccess { - pub path: AstPathVc, + pub path: Vc, } #[turbo_tasks::value_impl] @@ -315,8 +315,8 @@ impl CodeGenerateable for CjsRequireCacheAccess { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let mut visitors = Vec::new(); let path = &self.path.await?; diff --git a/crates/turbopack-ecmascript/src/references/constant_condition.rs b/crates/turbopack-ecmascript/src/references/constant_condition.rs index b1215e660c00ea..b91b88d0a5a4be 100644 --- a/crates/turbopack-ecmascript/src/references/constant_condition.rs +++ b/crates/turbopack-ecmascript/src/references/constant_condition.rs @@ -1,11 +1,11 @@ use anyhow::Result; use swc_core::quote; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; -use super::AstPathVc; +use super::AstPath; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, }; @@ -20,13 +20,13 @@ pub enum ConstantConditionValue { #[turbo_tasks::value] pub struct ConstantCondition { value: ConstantConditionValue, - path: AstPathVc, + path: Vc, } #[turbo_tasks::value_impl] -impl ConstantConditionVc { +impl ConstantCondition { #[turbo_tasks::function] - pub fn new(value: Value, path: AstPathVc) -> Self { + pub fn new(value: Value, path: Vc) -> Vc { Self::cell(ConstantCondition { value: value.into_value(), path, @@ -39,8 +39,8 @@ impl CodeGenerateable for ConstantCondition { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let value = self.value; let visitors = [ create_visitor!(exact &self.path.await?, visit_mut_expr(expr: &mut Expr) { diff --git a/crates/turbopack-ecmascript/src/references/constant_value.rs b/crates/turbopack-ecmascript/src/references/constant_value.rs index cf18be458dc99c..762260d19d25fc 100644 --- a/crates/turbopack-ecmascript/src/references/constant_value.rs +++ b/crates/turbopack-ecmascript/src/references/constant_value.rs @@ -1,25 +1,25 @@ use anyhow::Result; use swc_core::quote; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::compile_time_info::CompileTimeDefineValue; -use super::AstPathVc; +use super::AstPath; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, }; #[turbo_tasks::value] pub struct ConstantValue { value: CompileTimeDefineValue, - path: AstPathVc, + path: Vc, } #[turbo_tasks::value_impl] -impl ConstantValueVc { +impl ConstantValue { #[turbo_tasks::function] - pub fn new(value: Value, path: AstPathVc) -> Self { + pub fn new(value: Value, path: Vc) -> Vc { Self::cell(ConstantValue { value: value.into_value(), path, @@ -32,8 +32,8 @@ impl CodeGenerateable for ConstantValue { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let value = self.value.clone(); let visitors = [ create_visitor!(exact &self.path.await?, visit_mut_expr(expr: &mut Expr) { diff --git a/crates/turbopack-ecmascript/src/references/esm/base.rs b/crates/turbopack-ecmascript/src/references/esm/base.rs index 2e2ef97f0758ce..33b89dfecaf4ef 100644 --- a/crates/turbopack-ecmascript/src/references/esm/base.rs +++ b/crates/turbopack-ecmascript/src/references/esm/base.rs @@ -5,26 +5,24 @@ use swc_core::{ ecma::ast::{Expr, ExprStmt, Ident, Lit, Module, ModuleItem, Program, Script, Stmt}, quote, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ asset::Asset, - chunk::{ - ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingContext, ChunkingType, - ChunkingTypeOptionVc, ModuleId, - }, - issue::{IssueSeverity, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, + chunk::{ChunkableAssetReference, ChunkingContext, ChunkingType, ChunkingTypeOption, ModuleId}, + issue::{IssueSeverity, OptionIssueSource}, + reference::AssetReference, reference_type::EcmaScriptModulesReferenceSubType, resolve::{ - origin::ResolveOriginVc, parse::RequestVc, ModulePartVc, PrimaryResolveResult, - ResolveResultVc, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + ModulePart, PrimaryResolveResult, ResolveResult, }, }; use crate::{ analyzer::imports::ImportAnnotations, - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc}, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::{item::EcmascriptChunkItemExt, EcmascriptChunkPlaceable, EcmascriptChunkingContext}, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, magic_identifier, references::util::{request_to_string, throw_module_not_found_expr}, resolve::esm_resolve, @@ -32,7 +30,7 @@ use crate::{ #[turbo_tasks::value] pub enum ReferencedAsset { - Some(EcmascriptChunkPlaceableVc), + Some(Vc>), OriginalReferenceTypeExternal(String), None, } @@ -49,7 +47,7 @@ impl ReferencedAsset { } pub(crate) async fn get_ident_from_placeable( - asset: &EcmascriptChunkPlaceableVc, + asset: &Vc>, ) -> Result { let path = asset.ident().to_string().await?; Ok(magic_identifier::mangle(&format!( @@ -60,19 +58,19 @@ impl ReferencedAsset { } #[turbo_tasks::value_impl] -impl ReferencedAssetVc { +impl ReferencedAsset { #[turbo_tasks::function] pub async fn from_resolve_result( - resolve_result: ResolveResultVc, - request: RequestVc, - ) -> Result { + resolve_result: Vc, + request: Vc, + ) -> Result> { for result in resolve_result.await?.primary.iter() { match result { PrimaryResolveResult::OriginalReferenceExternal => { if let Some(request) = request.await?.request() { return Ok(ReferencedAsset::OriginalReferenceTypeExternal(request).cell()); } else { - return Ok(ReferencedAssetVc::cell(ReferencedAsset::None)); + return Ok(ReferencedAsset::cell(ReferencedAsset::None)); } } PrimaryResolveResult::OriginalReferenceTypeExternal(request) => { @@ -81,46 +79,48 @@ impl ReferencedAssetVc { ); } PrimaryResolveResult::Asset(asset) => { - if let Some(placeable) = EcmascriptChunkPlaceableVc::resolve_from(asset).await? + if let Some(placeable) = + Vc::try_resolve_sidecast::>(*asset) + .await? { - return Ok(ReferencedAssetVc::cell(ReferencedAsset::Some(placeable))); + return Ok(ReferencedAsset::cell(ReferencedAsset::Some(placeable))); } } // TODO ignore should probably be handled differently _ => {} } } - Ok(ReferencedAssetVc::cell(ReferencedAsset::None)) + Ok(ReferencedAsset::cell(ReferencedAsset::None)) } } #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct EsmAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, + pub origin: Vc>, + pub request: Vc, pub annotations: ImportAnnotations, - pub export_name: Option, + pub export_name: Option>, } impl EsmAssetReference { - fn get_origin(&self) -> ResolveOriginVc { + fn get_origin(&self) -> Vc> { let mut origin = self.origin; if let Some(transition) = self.annotations.transition() { - origin = origin.with_transition(transition); + origin = origin.with_transition(transition.to_string()); } origin } } #[turbo_tasks::value_impl] -impl EsmAssetReferenceVc { +impl EsmAssetReference { #[turbo_tasks::function] - pub(super) async fn get_referenced_asset(self) -> Result { + pub(super) async fn get_referenced_asset(self: Vc) -> Result> { let this = self.await?; - Ok(ReferencedAssetVc::from_resolve_result( + Ok(ReferencedAsset::from_resolve_result( self.resolve_reference(), this.request, )) @@ -128,11 +128,11 @@ impl EsmAssetReferenceVc { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, + origin: Vc>, + request: Vc, annotations: Value, - export_name: Option, - ) -> Self { + export_name: Option>, + ) -> Vc { Self::cell(EsmAssetReference { origin, request, @@ -145,7 +145,7 @@ impl EsmAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for EsmAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { let ty = Value::new(match &self.export_name { Some(part) => EcmaScriptModulesReferenceSubType::ImportPart(*part), None => EcmaScriptModulesReferenceSubType::Undefined, @@ -155,7 +155,7 @@ impl AssetReference for EsmAssetReference { self.get_origin(), self.request, ty, - OptionIssueSourceVc::none(), + OptionIssueSource::none(), IssueSeverity::Error.cell(), ) } @@ -164,8 +164,8 @@ impl AssetReference for EsmAssetReference { #[turbo_tasks::value_impl] impl ValueToString for EsmAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "import {} {}", self.request.to_string().await?, self.annotations @@ -176,8 +176,8 @@ impl ValueToString for EsmAssetReference { #[turbo_tasks::value_impl] impl ChunkableAssetReference for EsmAssetReference { #[turbo_tasks::function] - fn chunking_type(&self) -> Result { - Ok(ChunkingTypeOptionVc::cell( + fn chunking_type(&self) -> Result> { + Ok(Vc::cell( if let Some(chunking_type) = self.annotations.chunking_type() { match chunking_type { "separate" => Some(ChunkingType::Separate), @@ -197,18 +197,18 @@ impl ChunkableAssetReference for EsmAssetReference { impl CodeGenerateable for EsmAssetReference { #[turbo_tasks::function] async fn code_generation( - self_vc: EsmAssetReferenceVc, - context: EcmascriptChunkingContextVc, - ) -> Result { + self: Vc, + context: Vc>, + ) -> Result> { let mut visitors = Vec::new(); - let chunking_type = self_vc.chunking_type().await?; - let resolved = self_vc.resolve_reference().await?; + let chunking_type = self.chunking_type().await?; + let resolved = self.resolve_reference().await?; // Insert code that throws immediately at time of import if a request is // unresolvable - if resolved.is_unresolveable() { - let this = &*self_vc.await?; + if resolved.is_unresolveable_ref() { + let this = &*self.await?; let request = request_to_string(this.request).await?.to_string(); visitors.push(create_visitor!(visit_mut_program(program: &mut Program) { insert_hoisted_stmt(program, Stmt::Expr(ExprStmt { @@ -224,7 +224,7 @@ impl CodeGenerateable for EsmAssetReference { // separate chunks can't be imported as the modules are not available if !matches!(*chunking_type, None | Some(ChunkingType::Separate)) { - let referenced_asset = self_vc.get_referenced_asset().await?; + let referenced_asset = self.get_referenced_asset().await?; if let Some(ident) = referenced_asset.get_ident().await? { match &*referenced_asset { ReferencedAsset::Some(asset) => { diff --git a/crates/turbopack-ecmascript/src/references/esm/binding.rs b/crates/turbopack-ecmascript/src/references/esm/binding.rs index ff2d5f3dae1509..eff4eba93db492 100644 --- a/crates/turbopack-ecmascript/src/references/esm/binding.rs +++ b/crates/turbopack-ecmascript/src/references/esm/binding.rs @@ -9,31 +9,32 @@ use swc_core::{ visit::fields::PropField, }, }; +use turbo_tasks::Vc; -use super::EsmAssetReferenceVc; +use super::EsmAssetReference; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, - references::AstPathVc, + references::AstPath, }; #[turbo_tasks::value(shared)] #[derive(Hash, Debug)] pub struct EsmBinding { - pub reference: EsmAssetReferenceVc, + pub reference: Vc, pub export: Option, - pub ast_path: AstPathVc, + pub ast_path: Vc, } #[turbo_tasks::value_impl] -impl EsmBindingVc { +impl EsmBinding { #[turbo_tasks::function] pub fn new( - reference: EsmAssetReferenceVc, + reference: Vc, export: Option, - ast_path: AstPathVc, - ) -> Self { + ast_path: Vc, + ) -> Vc { EsmBinding { reference, export, @@ -47,10 +48,10 @@ impl EsmBindingVc { impl CodeGenerateable for EsmBinding { #[turbo_tasks::function] async fn code_generation( - self_vc: EsmBindingVc, - _context: EcmascriptChunkingContextVc, - ) -> Result { - let this = self_vc.await?; + self: Vc, + _context: Vc>, + ) -> Result> { + let this = self.await?; let mut visitors = Vec::new(); let imported_module = this.reference.get_referenced_asset(); diff --git a/crates/turbopack-ecmascript/src/references/esm/dynamic.rs b/crates/turbopack-ecmascript/src/references/esm/dynamic.rs index f1587dfd339ee3..73694915318a99 100644 --- a/crates/turbopack-ecmascript/src/references/esm/dynamic.rs +++ b/crates/turbopack-ecmascript/src/references/esm/dynamic.rs @@ -3,50 +3,47 @@ use swc_core::{ ecma::ast::{Callee, ExprOrSpread}, quote_expr, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ chunk::{ - availability_info::AvailabilityInfo, ChunkableAssetReference, ChunkableAssetReferenceVc, - ChunkingType, ChunkingTypeOptionVc, + availability_info::AvailabilityInfo, ChunkableAssetReference, ChunkingType, + ChunkingTypeOption, }, - issue::{IssueSourceVc, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, + issue::{IssueSource, OptionIssueSource}, + reference::AssetReference, reference_type::EcmaScriptModulesReferenceSubType, - resolve::{origin::ResolveOriginVc, parse::RequestVc, ResolveResultVc}, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; -use super::super::pattern_mapping::{PatternMapping, PatternMappingVc, ResolveType::EsmAsync}; +use super::super::pattern_mapping::{PatternMapping, ResolveType::EsmAsync}; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{ - CodeGenerateableWithAvailabilityInfo, CodeGenerateableWithAvailabilityInfoVc, - CodeGeneration, CodeGenerationVc, - }, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateableWithAvailabilityInfo, CodeGeneration}, create_visitor, - references::AstPathVc, + references::AstPath, resolve::{esm_resolve, try_to_severity}, }; #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct EsmAsyncAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub path: AstPathVc, - pub issue_source: IssueSourceVc, + pub origin: Vc>, + pub request: Vc, + pub path: Vc, + pub issue_source: Vc, pub in_try: bool, } #[turbo_tasks::value_impl] -impl EsmAsyncAssetReferenceVc { +impl EsmAsyncAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - path: AstPathVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + path: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { Self::cell(EsmAsyncAssetReference { origin, request, @@ -60,12 +57,12 @@ impl EsmAsyncAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for EsmAsyncAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { esm_resolve( self.origin, self.request, Default::default(), - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ) } @@ -74,8 +71,8 @@ impl AssetReference for EsmAsyncAssetReference { #[turbo_tasks::value_impl] impl ValueToString for EsmAsyncAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "dynamic import {}", self.request.to_string().await?, ))) @@ -85,8 +82,8 @@ impl ValueToString for EsmAsyncAssetReference { #[turbo_tasks::value_impl] impl ChunkableAssetReference for EsmAsyncAssetReference { #[turbo_tasks::function] - fn chunking_type(&self) -> ChunkingTypeOptionVc { - ChunkingTypeOptionVc::cell(Some(ChunkingType::SeparateAsync)) + fn chunking_type(&self) -> Vc { + Vc::cell(Some(ChunkingType::SeparateAsync)) } } @@ -95,18 +92,18 @@ impl CodeGenerateableWithAvailabilityInfo for EsmAsyncAssetReference { #[turbo_tasks::function] async fn code_generation( &self, - context: EcmascriptChunkingContextVc, + context: Vc>, availability_info: Value, - ) -> Result { - let pm = PatternMappingVc::resolve_request( + ) -> Result> { + let pm = PatternMapping::resolve_request( self.request, self.origin, - context.into(), + Vc::upcast(context), esm_resolve( self.origin, self.request, Value::new(EcmaScriptModulesReferenceSubType::Undefined), - OptionIssueSourceVc::some(self.issue_source), + OptionIssueSource::some(self.issue_source), try_to_severity(self.in_try), ), Value::new(EsmAsync(availability_info.into_value())), diff --git a/crates/turbopack-ecmascript/src/references/esm/export.rs b/crates/turbopack-ecmascript/src/references/esm/export.rs index 5f62f5e389258a..d251115c48c2f9 100644 --- a/crates/turbopack-ecmascript/src/references/esm/export.rs +++ b/crates/turbopack-ecmascript/src/references/esm/export.rs @@ -13,19 +13,16 @@ use swc_core::{ }, quote, quote_expr, }; -use turbo_tasks::{primitives::StringVc, trace::TraceRawVcs, ValueToString}; +use turbo_tasks::{trace::TraceRawVcs, ValueToString, Vc}; use turbopack_core::{ asset::Asset, - issue::{analyze::AnalyzeIssue, IssueSeverity}, + issue::{analyze::AnalyzeIssue, IssueExt, IssueSeverity}, }; -use super::{base::ReferencedAsset, EsmAssetReferenceVc}; +use super::{base::ReferencedAsset, EsmAssetReference}; use crate::{ - chunk::{ - EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkingContextVc, - EcmascriptExports, - }, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::{EcmascriptChunkPlaceable, EcmascriptChunkingContext, EcmascriptExports}, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, references::esm::base::insert_hoisted_stmt, }; @@ -33,8 +30,8 @@ use crate::{ #[derive(Clone, Hash, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] pub enum EsmExport { LocalBinding(String), - ImportedBinding(EsmAssetReferenceVc, String), - ImportedNamespace(EsmAssetReferenceVc), + ImportedBinding(Vc, String), + ImportedNamespace(Vc), Error, } @@ -45,7 +42,9 @@ struct ExpandResults { } #[turbo_tasks::function] -async fn expand_star_exports(root_asset: EcmascriptChunkPlaceableVc) -> Result { +async fn expand_star_exports( + root_asset: Vc>, +) -> Result> { let mut set = HashSet::new(); let mut has_cjs_exports = false; let mut checked_assets = HashSet::new(); @@ -66,8 +65,8 @@ async fn expand_star_exports(root_asset: EcmascriptChunkPlaceableVc) -> Result AnalyzeIssue { code: None, - category: StringVc::cell("analyze".to_string()), - message: StringVc::cell(format!( + category: Vc::cell("analyze".to_string()), + message: Vc::cell(format!( "export * used with module {} which has no exports\nTypescript only: Did you \ want to export only types with `export type * from \"...\"`?\nNote: Using \ `export type` is more efficient than `export *` as it won't emit any runtime \ @@ -77,15 +76,14 @@ async fn expand_star_exports(root_asset: EcmascriptChunkPlaceableVc) -> Result AnalyzeIssue { code: None, - category: StringVc::cell("analyze".to_string()), - message: StringVc::cell(format!( + category: Vc::cell("analyze".to_string()), + message: Vc::cell(format!( "export * used with module {} which only has a default export (default export \ is not exported with export *)\nDid you want to use `export {{ default }} \ from \"...\";` instead?", @@ -94,17 +92,17 @@ async fn expand_star_exports(root_asset: EcmascriptChunkPlaceableVc) -> Result { has_cjs_exports = true; + AnalyzeIssue { code: None, - category: StringVc::cell("analyze".to_string()), - message: StringVc::cell(format!( + category: Vc::cell("analyze".to_string()), + message: Vc::cell(format!( "export * used with module {} which is a CommonJS module with exports \ only available at runtime\nList all export names manually (`export {{ a, \ b, c }} from \"...\") or rewrite the module to ESM, to avoid the \ @@ -114,15 +112,14 @@ async fn expand_star_exports(root_asset: EcmascriptChunkPlaceableVc) -> Result Result, - pub star_exports: Vec, + pub star_exports: Vec>, } #[turbo_tasks::value_impl] impl CodeGenerateable for EsmExports { #[turbo_tasks::function] async fn code_generation( - self_vc: EsmExportsVc, - _context: EcmascriptChunkingContextVc, - ) -> Result { - let this = self_vc.await?; + self: Vc, + _context: Vc>, + ) -> Result> { + let this = self.await?; let mut visitors = Vec::new(); let mut all_exports: BTreeMap, Cow> = this diff --git a/crates/turbopack-ecmascript/src/references/esm/meta.rs b/crates/turbopack-ecmascript/src/references/esm/meta.rs index 3750052a3614ca..d02eade7a73367 100644 --- a/crates/turbopack-ecmascript/src/references/esm/meta.rs +++ b/crates/turbopack-ecmascript/src/references/esm/meta.rs @@ -6,13 +6,14 @@ use swc_core::{ ecma::ast::{Expr, Ident}, quote, }; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, magic_identifier, - references::{as_abs_path, esm::base::insert_hoisted_stmt, AstPathVc}, + references::{as_abs_path, esm::base::insert_hoisted_stmt, AstPath}, }; /// Responsible for initializing the `import.meta` object binding, so that it @@ -23,13 +24,13 @@ use crate::{ #[turbo_tasks::value(shared)] #[derive(Hash, Debug)] pub struct ImportMetaBinding { - path: FileSystemPathVc, + path: Vc, } #[turbo_tasks::value_impl] -impl ImportMetaBindingVc { +impl ImportMetaBinding { #[turbo_tasks::function] - pub fn new(path: FileSystemPathVc) -> Self { + pub fn new(path: Vc) -> Vc { ImportMetaBinding { path }.cell() } } @@ -39,8 +40,8 @@ impl CodeGenerateable for ImportMetaBinding { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let path = as_abs_path(self.path).await?.as_str().map_or_else( || { quote!( @@ -75,13 +76,13 @@ impl CodeGenerateable for ImportMetaBinding { #[turbo_tasks::value(shared)] #[derive(Hash, Debug)] pub struct ImportMetaRef { - ast_path: AstPathVc, + ast_path: Vc, } #[turbo_tasks::value_impl] -impl ImportMetaRefVc { +impl ImportMetaRef { #[turbo_tasks::function] - pub fn new(ast_path: AstPathVc) -> Self { + pub fn new(ast_path: Vc) -> Vc { ImportMetaRef { ast_path }.cell() } } @@ -91,8 +92,8 @@ impl CodeGenerateable for ImportMetaRef { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let ast_path = &self.ast_path.await?; let visitor = create_visitor!(ast_path, visit_mut_expr(expr: &mut Expr) { *expr = Expr::Ident(meta_ident()); diff --git a/crates/turbopack-ecmascript/src/references/esm/mod.rs b/crates/turbopack-ecmascript/src/references/esm/mod.rs index ae44a6ff0087e6..ee3e24ab6cddd6 100644 --- a/crates/turbopack-ecmascript/src/references/esm/mod.rs +++ b/crates/turbopack-ecmascript/src/references/esm/mod.rs @@ -8,11 +8,11 @@ pub(crate) mod module_item; pub(crate) mod url; pub use self::{ - base::{EsmAssetReference, EsmAssetReferenceVc}, - binding::{EsmBinding, EsmBindingVc}, - dynamic::{EsmAsyncAssetReference, EsmAsyncAssetReferenceVc}, - export::{EsmExports, EsmExportsVc}, - meta::{ImportMetaBinding, ImportMetaBindingVc, ImportMetaRef, ImportMetaRefVc}, - module_item::{EsmModuleItem, EsmModuleItemVc}, - url::{UrlAssetReference, UrlAssetReferenceVc}, + base::EsmAssetReference, + binding::EsmBinding, + dynamic::EsmAsyncAssetReference, + export::EsmExports, + meta::{ImportMetaBinding, ImportMetaRef}, + module_item::EsmModuleItem, + url::UrlAssetReference, }; diff --git a/crates/turbopack-ecmascript/src/references/esm/module_id.rs b/crates/turbopack-ecmascript/src/references/esm/module_id.rs index 9c5c8df9970d7b..78dae4d7c4de75 100644 --- a/crates/turbopack-ecmascript/src/references/esm/module_id.rs +++ b/crates/turbopack-ecmascript/src/references/esm/module_id.rs @@ -1,31 +1,31 @@ use anyhow::Result; use swc_core::{ecma::ast::Expr, quote}; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbopack_core::{ - chunk::{ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingTypeOptionVc, ModuleId}, - reference::{AssetReference, AssetReferenceVc}, - resolve::ResolveResultVc, + chunk::{ChunkableAssetReference, ChunkingTypeOption, ModuleId}, + reference::AssetReference, + resolve::ResolveResult, }; -use super::{base::ReferencedAsset, EsmAssetReferenceVc}; +use super::{base::ReferencedAsset, EsmAssetReference}; use crate::{ - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkingContextVc}, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::{item::EcmascriptChunkItemExt, EcmascriptChunkPlaceable, EcmascriptChunkingContext}, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, - references::AstPathVc, + references::AstPath, }; #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct EsmModuleIdAssetReference { - inner: EsmAssetReferenceVc, - ast_path: AstPathVc, + inner: Vc, + ast_path: Vc, } #[turbo_tasks::value_impl] -impl EsmModuleIdAssetReferenceVc { +impl EsmModuleIdAssetReference { #[turbo_tasks::function] - pub fn new(inner: EsmAssetReferenceVc, ast_path: AstPathVc) -> Self { + pub fn new(inner: Vc, ast_path: Vc) -> Vc { Self::cell(EsmModuleIdAssetReference { inner, ast_path }) } } @@ -33,7 +33,7 @@ impl EsmModuleIdAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for EsmModuleIdAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { self.inner.resolve_reference() } } @@ -41,8 +41,8 @@ impl AssetReference for EsmModuleIdAssetReference { #[turbo_tasks::value_impl] impl ValueToString for EsmModuleIdAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "module id of {}", self.inner.to_string().await?, ))) @@ -52,7 +52,7 @@ impl ValueToString for EsmModuleIdAssetReference { #[turbo_tasks::value_impl] impl ChunkableAssetReference for EsmModuleIdAssetReference { #[turbo_tasks::function] - fn chunking_type(&self) -> ChunkingTypeOptionVc { + fn chunking_type(&self) -> Vc { self.inner.chunking_type() } } @@ -62,8 +62,8 @@ impl CodeGenerateable for EsmModuleIdAssetReference { #[turbo_tasks::function] async fn code_generation( &self, - context: EcmascriptChunkingContextVc, - ) -> Result { + context: Vc>, + ) -> Result> { let mut visitors = Vec::new(); if let ReferencedAsset::Some(asset) = &*self.inner.get_referenced_asset().await? { diff --git a/crates/turbopack-ecmascript/src/references/esm/module_item.rs b/crates/turbopack-ecmascript/src/references/esm/module_item.rs index 5cd863307cf064..269910a7b015cc 100644 --- a/crates/turbopack-ecmascript/src/references/esm/module_item.rs +++ b/crates/turbopack-ecmascript/src/references/esm/module_item.rs @@ -9,12 +9,13 @@ use swc_core::{ }, quote, }; +use turbo_tasks::Vc; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, magic_identifier, - references::AstPathVc, + references::AstPath, }; /// Makes code changes to remove export/import declarations and places the @@ -23,13 +24,13 @@ use crate::{ #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct EsmModuleItem { - pub path: AstPathVc, + pub path: Vc, } #[turbo_tasks::value_impl] -impl EsmModuleItemVc { +impl EsmModuleItem { #[turbo_tasks::function] - pub fn new(path: AstPathVc) -> Self { + pub fn new(path: Vc) -> Vc { Self::cell(EsmModuleItem { path }) } } @@ -39,8 +40,8 @@ impl CodeGenerateable for EsmModuleItem { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let mut visitors = Vec::new(); let path = &self.path.await?; diff --git a/crates/turbopack-ecmascript/src/references/esm/url.rs b/crates/turbopack-ecmascript/src/references/esm/url.rs index 2a46394c4fd742..c6a6d724c2539f 100644 --- a/crates/turbopack-ecmascript/src/references/esm/url.rs +++ b/crates/turbopack-ecmascript/src/references/esm/url.rs @@ -3,28 +3,22 @@ use swc_core::{ ecma::ast::{Expr, ExprOrSpread, NewExpr}, quote, }; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - chunk::{ - ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkingType, ChunkingTypeOptionVc, - }, - environment::{Rendering, RenderingVc}, - issue::{code_gen::CodeGenerationIssue, IssueSeverity, IssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, + chunk::{ChunkableAssetReference, ChunkingType, ChunkingTypeOption}, + environment::Rendering, + issue::{code_gen::CodeGenerationIssue, IssueExt, IssueSeverity, IssueSource}, + reference::AssetReference, reference_type::UrlReferenceSubType, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - ResolveResultVc, - }, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; -use super::base::{ReferencedAsset, ReferencedAssetVc}; +use super::base::ReferencedAsset; use crate::{ - chunk::{EcmascriptChunkPlaceable, EcmascriptChunkingContextVc}, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::{item::EcmascriptChunkItemExt, EcmascriptChunkPlaceable, EcmascriptChunkingContext}, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, - references::AstPathVc, + references::AstPath, resolve::{try_to_severity, url_resolve}, utils::module_id_to_lit, }; @@ -36,25 +30,25 @@ use crate::{ /// referenced file to be imported/fetched/etc. #[turbo_tasks::value] pub struct UrlAssetReference { - origin: ResolveOriginVc, - request: RequestVc, - rendering: RenderingVc, - ast_path: AstPathVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + rendering: Vc, + ast_path: Vc, + issue_source: Vc, in_try: bool, } #[turbo_tasks::value_impl] -impl UrlAssetReferenceVc { +impl UrlAssetReference { #[turbo_tasks::function] pub fn new( - origin: ResolveOriginVc, - request: RequestVc, - rendering: RenderingVc, - ast_path: AstPathVc, - issue_source: IssueSourceVc, + origin: Vc>, + request: Vc, + rendering: Vc, + ast_path: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { + ) -> Vc { UrlAssetReference { origin, request, @@ -67,9 +61,9 @@ impl UrlAssetReferenceVc { } #[turbo_tasks::function] - pub(super) async fn get_referenced_asset(self) -> Result { + pub(super) async fn get_referenced_asset(self: Vc) -> Result> { let this = self.await?; - Ok(ReferencedAssetVc::from_resolve_result( + Ok(ReferencedAsset::from_resolve_result( self.resolve_reference(), this.request, )) @@ -79,7 +73,7 @@ impl UrlAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for UrlAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> ResolveResultVc { + async fn resolve_reference(&self) -> Vc { url_resolve( self.origin, self.request, @@ -93,8 +87,8 @@ impl AssetReference for UrlAssetReference { #[turbo_tasks::value_impl] impl ValueToString for UrlAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "new URL({})", self.request.to_string().await?, ))) @@ -104,8 +98,8 @@ impl ValueToString for UrlAssetReference { #[turbo_tasks::value_impl] impl ChunkableAssetReference for UrlAssetReference { #[turbo_tasks::function] - fn chunking_type(&self) -> ChunkingTypeOptionVc { - ChunkingTypeOptionVc::cell(Some(ChunkingType::PlacedOrParallel)) + fn chunking_type(&self) -> Vc { + Vc::cell(Some(ChunkingType::PlacedOrParallel)) } } @@ -113,13 +107,13 @@ impl ChunkableAssetReference for UrlAssetReference { impl CodeGenerateable for UrlAssetReference { #[turbo_tasks::function] async fn code_generation( - self_vc: UrlAssetReferenceVc, - context: EcmascriptChunkingContextVc, - ) -> Result { - let this = self_vc.await?; + self: Vc, + context: Vc>, + ) -> Result> { + let this = self.await?; let mut visitors = vec![]; - let referenced_asset = self_vc.get_referenced_asset().await?; + let referenced_asset = self.get_referenced_asset().await?; // For rendering environments (CSR and SSR), we rewrite the `import.meta.url` to // be a location.origin because it allows us to access files from the root of @@ -132,10 +126,8 @@ impl CodeGenerateable for UrlAssetReference { Rendering::None => { CodeGenerationIssue { severity: IssueSeverity::Error.into(), - title: StringVc::cell( - "new URL(…) not implemented for this environment".to_string(), - ), - message: StringVc::cell( + title: Vc::cell("new URL(…) not implemented for this environment".to_string()), + message: Vc::cell( "new URL(…) is only currently supported for rendering environments like \ Client-Side or Server-Side Rendering." .to_string(), @@ -143,7 +135,6 @@ impl CodeGenerateable for UrlAssetReference { path: this.origin.origin_path(), } .cell() - .as_issue() .emit(); None } diff --git a/crates/turbopack-ecmascript/src/references/mod.rs b/crates/turbopack-ecmascript/src/references/mod.rs index d771bdef57c7ac..4f460b8da90aba 100644 --- a/crates/turbopack-ecmascript/src/references/mod.rs +++ b/crates/turbopack-ecmascript/src/references/mod.rs @@ -21,8 +21,8 @@ use std::{ }; use anyhow::Result; -use constant_condition::{ConstantConditionValue, ConstantConditionVc}; -use constant_value::ConstantValueVc; +use constant_condition::{ConstantCondition, ConstantConditionValue}; +use constant_value::ConstantValue; use indexmap::IndexSet; use lazy_static::lazy_static; use parking_lot::Mutex; @@ -43,45 +43,40 @@ use swc_core::{ }, }, }; -use turbo_tasks::{ - primitives::{BoolVc, RegexVc}, - TryJoinIterExt, Value, -}; -use turbo_tasks_fs::{FileJsonContent, FileSystemPathVc}; +use turbo_tasks::{TryJoinIterExt, Upcast, Value, Vc}; +use turbo_tasks_fs::{FileJsonContent, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetVc}, - compile_time_info::{CompileTimeInfoVc, FreeVarReference}, + asset::Asset, + compile_time_info::{CompileTimeInfo, FreeVarReference}, error::PrettyPrintError, - issue::{IssueSourceVc, OptionIssueSourceVc}, - reference::{AssetReferenceVc, AssetReferencesVc, SourceMapReferenceVc}, + issue::{IssueExt, IssueSource, OptionIssueSource}, + reference::{AssetReference, AssetReferences, SourceMapReference}, reference_type::{CommonJsReferenceSubType, ReferenceType}, resolve::{ find_context_file, - origin::{PlainResolveOriginVc, ResolveOrigin, ResolveOriginVc}, + origin::{PlainResolveOrigin, ResolveOrigin, ResolveOriginExt}, package_json, - parse::RequestVc, + parse::Request, pattern::Pattern, - resolve, FindContextFileResult, ModulePartVc, PrimaryResolveResult, + resolve, FindContextFileResult, ModulePart, PrimaryResolveResult, }, }; use turbopack_swc_utils::emitter::IssueEmitter; -use unreachable::UnreachableVc; +use unreachable::Unreachable; use self::{ amd::{ - AmdDefineAssetReferenceVc, AmdDefineDependencyElement, AmdDefineFactoryType, - AmdDefineWithDependenciesCodeGenVc, + AmdDefineAssetReference, AmdDefineDependencyElement, AmdDefineFactoryType, + AmdDefineWithDependenciesCodeGen, }, - cjs::CjsAssetReferenceVc, + cjs::CjsAssetReference, esm::{ - export::EsmExport, EsmAssetReferenceVc, EsmAsyncAssetReferenceVc, EsmExports, - EsmModuleItemVc, ImportMetaBindingVc, ImportMetaRefVc, UrlAssetReferenceVc, - }, - node::{DirAssetReferenceVc, PackageJsonReferenceVc}, - raw::SourceAssetReferenceVc, - typescript::{ - TsConfigReferenceVc, TsReferencePathAssetReferenceVc, TsReferenceTypeAssetReferenceVc, + export::EsmExport, EsmAssetReference, EsmAsyncAssetReference, EsmExports, EsmModuleItem, + ImportMetaBinding, ImportMetaRef, UrlAssetReference, }, + node::{DirAssetReference, PackageJsonReference}, + raw::SourceAssetReference, + typescript::{TsConfigReference, TsReferencePathAssetReference, TsReferenceTypeAssetReference}, }; use super::{ analyzer::{ @@ -97,7 +92,7 @@ use super::{ special_cases::special_cases, utils::js_value_to_pattern, webpack::{ - parse::{webpack_runtime, WebpackRuntime, WebpackRuntimeVc}, + parse::{webpack_runtime, WebpackRuntime}, WebpackChunkAssetReference, WebpackEntryAssetReference, WebpackRuntimeAssetReference, }, EcmascriptModuleAssetType, @@ -107,40 +102,38 @@ use crate::{ builtin::early_replace_builtin, graph::{ConditionalKind, EffectArg, EvalContext, VarGraph}, imports::{ImportedSymbol, Reexport}, - parse_require_context, ModuleValue, RequireContextValueVc, + parse_require_context, ModuleValue, RequireContextValue, }, - chunk::{EcmascriptExports, EcmascriptExportsVc}, + chunk::EcmascriptExports, code_gen::{ - CodeGen, CodeGenerateableVc, CodeGenerateableWithAvailabilityInfoVc, CodeGenerateablesVc, + CodeGen, CodeGenerateable, CodeGenerateableWithAvailabilityInfo, CodeGenerateables, }, magic_identifier, references::{ - cjs::{ - CjsRequireAssetReferenceVc, CjsRequireCacheAccess, CjsRequireResolveAssetReferenceVc, - }, - esm::{module_id::EsmModuleIdAssetReferenceVc, EsmBindingVc, EsmExportsVc}, - require_context::{RequireContextAssetReferenceVc, RequireContextMapVc}, + cjs::{CjsRequireAssetReference, CjsRequireCacheAccess, CjsRequireResolveAssetReference}, + esm::{module_id::EsmModuleIdAssetReference, EsmBinding}, + require_context::{RequireContextAssetReference, RequireContextMap}, type_issue::SpecifiedModuleTypeIssue, }, resolve::try_to_severity, tree_shake::{part_of_module, split}, typescript::resolve::tsconfig, - EcmascriptInputTransformsVc, EcmascriptOptions, SpecifiedModuleType, SpecifiedModuleTypeVc, + EcmascriptInputTransforms, EcmascriptOptions, SpecifiedModuleType, }; #[turbo_tasks::value(shared)] pub struct AnalyzeEcmascriptModuleResult { - pub references: AssetReferencesVc, - pub code_generation: CodeGenerateablesVc, - pub exports: EcmascriptExportsVc, + pub references: Vc, + pub code_generation: Vc, + pub exports: Vc, /// `true` when the analysis was successful. pub successful: bool, } #[turbo_tasks::value_impl] -impl AnalyzeEcmascriptModuleResultVc { +impl AnalyzeEcmascriptModuleResult { #[turbo_tasks::function] - pub async fn needs_availability_info(self) -> Result { + pub async fn needs_availability_info(self: Vc) -> Result> { let AnalyzeEcmascriptModuleResult { references, code_generation, @@ -148,25 +141,25 @@ impl AnalyzeEcmascriptModuleResultVc { } = &*self.await?; for c in code_generation.await?.iter() { if matches!(c, CodeGen::CodeGenerateableWithAvailabilityInfo(..)) { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } for r in references.await?.iter() { - if CodeGenerateableWithAvailabilityInfoVc::resolve_from(r) + if Vc::try_resolve_sidecast::>(*r) .await? .is_some() { - return Ok(BoolVc::cell(true)); + return Ok(Vc::cell(true)); } } - Ok(BoolVc::cell(false)) + Ok(Vc::cell(false)) } } /// A temporary analysis result builder to pass around, to be turned into an -/// `AnalyzeEcmascriptModuleResultVc` eventually. +/// `Vc` eventually. pub(crate) struct AnalyzeEcmascriptModuleResultBuilder { - references: IndexSet, + references: IndexSet>>, code_gens: Vec, exports: EcmascriptExports, successful: bool, @@ -183,32 +176,32 @@ impl AnalyzeEcmascriptModuleResultBuilder { } /// Adds an asset reference to the analysis result. - pub fn add_reference(&mut self, reference: R) + pub fn add_reference(&mut self, reference: Vc) where - R: Into, + R: Upcast>, { - self.references.insert(reference.into()); + self.references.insert(Vc::upcast(reference)); } /// Adds a codegen to the analysis result. - pub fn add_code_gen(&mut self, code_gen: C) + pub fn add_code_gen(&mut self, code_gen: Vc) where - C: Into, + C: Upcast>, { self.code_gens - .push(CodeGen::CodeGenerateable(code_gen.into())); + .push(CodeGen::CodeGenerateable(Vc::upcast(code_gen))); } /// Adds a codegen to the analysis result. #[allow(dead_code)] - pub fn add_code_gen_with_availability_info(&mut self, code_gen: C) + pub fn add_code_gen_with_availability_info(&mut self, code_gen: Vc) where - C: Into, + C: Upcast>, { self.code_gens - .push(CodeGen::CodeGenerateableWithAvailabilityInfo( - code_gen.into(), - )); + .push(CodeGen::CodeGenerateableWithAvailabilityInfo(Vc::upcast( + code_gen, + ))); } /// Sets the analysis result ES export. @@ -223,7 +216,7 @@ impl AnalyzeEcmascriptModuleResultBuilder { /// Builds the final analysis result. Resolves internal Vcs for performance /// in using them. - pub async fn build(mut self) -> Result { + pub async fn build(mut self) -> Result> { let mut references: Vec<_> = self.references.into_iter().collect(); for r in references.iter_mut() { *r = r.resolve().await?; @@ -238,10 +231,10 @@ impl AnalyzeEcmascriptModuleResultBuilder { } } } - Ok(AnalyzeEcmascriptModuleResultVc::cell( + Ok(AnalyzeEcmascriptModuleResult::cell( AnalyzeEcmascriptModuleResult { - references: AssetReferencesVc::cell(references), - code_generation: CodeGenerateablesVc::cell(self.code_gens), + references: Vc::cell(references), + code_generation: Vc::cell(self.code_gens), exports: self.exports.into(), successful: self.successful, }, @@ -256,7 +249,9 @@ impl Default for AnalyzeEcmascriptModuleResultBuilder { } #[turbo_tasks::function] -async fn specified_module_type(package_json: FileSystemPathVc) -> Result { +async fn specified_module_type( + package_json: Vc, +) -> Result> { if let FileJsonContent::Content(content) = &*package_json.read_json().await? { if let Some(r#type) = content.get("type") { match r#type.as_str() { @@ -271,9 +266,9 @@ async fn specified_module_type(package_json: FileSystemPathVc) -> Result { handler: &'a Handler, - source: AssetVc, - origin: ResolveOriginVc, - compile_time_info: CompileTimeInfoVc, + source: Vc>, + origin: Vc>, + compile_time_info: Vc, var_graph: &'a VarGraph, /// This is the current state of known values of function /// arguments. @@ -286,14 +281,14 @@ struct AnalysisState<'a> { #[turbo_tasks::function] pub(crate) async fn analyze_ecmascript_module( - source: AssetVc, - origin: ResolveOriginVc, + source: Vc>, + origin: Vc>, ty: Value, - transforms: EcmascriptInputTransformsVc, + transforms: Vc, options: Value, - compile_time_info: CompileTimeInfoVc, - part: Option, -) -> Result { + compile_time_info: Vc, + part: Option>, +) -> Result> { let mut analysis = AnalyzeEcmascriptModuleResultBuilder::new(); let path = origin.origin_path(); @@ -316,7 +311,7 @@ pub(crate) async fn analyze_ecmascript_module( SpecifiedModuleType::Automatic => { match *find_context_file(path.parent(), package_json()).await? { FindContextFileResult::Found(package_json, _) => { - analysis.add_reference(PackageJsonReferenceVc::new(package_json)); + analysis.add_reference(PackageJsonReference::new(package_json)); *specified_module_type(package_json).await? } FindContextFileResult::NotFound(_) => SpecifiedModuleType::Automatic, @@ -329,7 +324,7 @@ pub(crate) async fn analyze_ecmascript_module( if analyze_types { match &*find_context_file(path.parent(), tsconfig()).await? { FindContextFileResult::Found(tsconfig, _) => { - analysis.add_reference(TsConfigReferenceVc::new(origin, *tsconfig)); + analysis.add_reference(TsConfigReference::new(origin, *tsconfig)); } FindContextFileResult::NotFound(_) => {} }; @@ -368,13 +363,13 @@ pub(crate) async fn analyze_ecmascript_module( let text = &comment.text; if let Some(m) = REFERENCE_PATH.captures(text) { let path = &m[1]; - analysis.add_reference(TsReferencePathAssetReferenceVc::new( + analysis.add_reference(TsReferencePathAssetReference::new( origin, path.to_string(), )); } else if let Some(m) = REFERENCE_TYPES.captures(text) { let types = &m[1]; - analysis.add_reference(TsReferenceTypeAssetReferenceVc::new( + analysis.add_reference(TsReferenceTypeAssetReference::new( origin, types.to_string(), )); @@ -396,9 +391,9 @@ pub(crate) async fn analyze_ecmascript_module( // knows to use that SourceMap when running code generation. // The reference is needed too for turbotrace let origin_path = origin.origin_path(); - analysis.add_reference(SourceMapReferenceVc::new( + analysis.add_reference(SourceMapReference::new( origin_path, - origin_path.parent().join(path), + origin_path.parent().join(path.to_string()), )) } } @@ -420,17 +415,17 @@ pub(crate) async fn analyze_ecmascript_module( }); for r in eval_context.imports.references() { - let r = EsmAssetReferenceVc::new( + let r = EsmAssetReference::new( origin, - RequestVc::parse(Value::new(r.module_path.to_string().into())), + Request::parse(Value::new(r.module_path.to_string().into())), Value::new(r.annotations.clone()), if options.import_parts { match &r.imported_symbol { ImportedSymbol::ModuleEvaluation => { - Some(ModulePartVc::module_evaluation()) + Some(ModulePart::module_evaluation()) } ImportedSymbol::Symbol(name) => { - Some(ModulePartVc::export(name.to_string())) + Some(ModulePart::export(name.to_string())) } ImportedSymbol::Namespace => None, } @@ -507,7 +502,7 @@ pub(crate) async fn analyze_ecmascript_module( let mut ignore_effect_span = None; // Check if it was a webpack entry if let Some((request, span)) = webpack_runtime { - let request = RequestVc::parse(Value::new(request.into())); + let request = Request::parse(Value::new(request.into())); let runtime = resolve_as_webpack_runtime(origin, request, transforms); match &*runtime.await? { WebpackRuntime::Webpack5 { .. } => { @@ -553,10 +548,9 @@ pub(crate) async fn analyze_ecmascript_module( specified_type, } .cell() - .as_issue() .emit(); } - let esm_exports: EsmExportsVc = EsmExports { + let esm_exports: Vc = EsmExports { exports: esm_exports, star_exports: esm_star_exports, } @@ -570,7 +564,6 @@ pub(crate) async fn analyze_ecmascript_module( specified_type, } .cell() - .as_issue() .emit(); } EcmascriptExports::EsmExports( @@ -686,10 +679,10 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(EsmAsyncAssetReferenceVc::new( + analysis.add_reference(EsmAsyncAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), - AstPathVc::cell(ast_path.to_vec()), + Request::parse(Value::new(pat)), + Vc::cell(ast_path.to_vec()), issue_source(source, span), in_try, )); @@ -718,10 +711,10 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(CjsRequireAssetReferenceVc::new( + analysis.add_reference(CjsRequireAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), - AstPathVc::cell(ast_path.to_vec()), + Request::parse(Value::new(pat)), + Vc::cell(ast_path.to_vec()), issue_source(source, span), in_try, )); @@ -764,10 +757,10 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(CjsRequireResolveAssetReferenceVc::new( + analysis.add_reference(CjsRequireResolveAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), - AstPathVc::cell(ast_path.to_vec()), + Request::parse(Value::new(pat)), + Vc::cell(ast_path.to_vec()), issue_source(source, span), in_try, )); @@ -807,14 +800,14 @@ pub(crate) async fn analyze_ecmascript_module( } }; - analysis.add_reference(RequireContextAssetReferenceVc::new( + analysis.add_reference(RequireContextAssetReference::new( source, origin, options.dir, options.include_subdirs, - RegexVc::cell(options.filter), - AstPathVc::cell(ast_path.to_vec()), - OptionIssueSourceVc::some(issue_source(source, span)), + Vc::cell(options.filter), + Vc::cell(ast_path.to_vec()), + OptionIssueSource::some(issue_source(source, span)), in_try, )); } @@ -834,7 +827,7 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(SourceAssetReferenceVc::new(source, pat.into())); + analysis.add_reference(SourceAssetReference::new(source, pat.into())); return Ok(()); } let (args, hints) = explain_args(&args); @@ -876,7 +869,7 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(SourceAssetReferenceVc::new(source, pat.into())); + analysis.add_reference(SourceAssetReference::new(source, pat.into())); return Ok(()); } @@ -904,7 +897,7 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(DirAssetReferenceVc::new(source, pat.into())); + analysis.add_reference(DirAssetReference::new(source, pat.into())); return Ok(()); } JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessSpawnMethod( @@ -924,9 +917,9 @@ pub(crate) async fn analyze_ecmascript_module( if !pat.has_constant_parts() { show_dynamic_warning = true; } - analysis.add_reference(CjsAssetReferenceVc::new( + analysis.add_reference(CjsAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), + Request::parse(Value::new(pat)), issue_source(source, span), in_try, )); @@ -942,7 +935,7 @@ pub(crate) async fn analyze_ecmascript_module( ), ); } - analysis.add_reference(SourceAssetReferenceVc::new(source, pat.into())); + analysis.add_reference(SourceAssetReference::new(source, pat.into())); return Ok(()); } let (args, hints) = explain_args(&args); @@ -974,9 +967,9 @@ pub(crate) async fn analyze_ecmascript_module( ), ); } - analysis.add_reference(CjsAssetReferenceVc::new( + analysis.add_reference(CjsAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), + Request::parse(Value::new(pat)), issue_source(source, span), in_try, )); @@ -995,7 +988,7 @@ pub(crate) async fn analyze_ecmascript_module( ) } JsValue::WellKnownFunction(WellKnownFunctionKind::NodePreGypFind) => { - use crate::resolve::node_native_binding::NodePreGypConfigReferenceVc; + use crate::resolve::node_native_binding::NodePreGypConfigReference; let args = linked_args(args).await?; if args.len() == 1 { @@ -1013,7 +1006,7 @@ pub(crate) async fn analyze_ecmascript_module( ); return Ok(()); } - analysis.add_reference(NodePreGypConfigReferenceVc::new( + analysis.add_reference(NodePreGypConfigReference::new( origin.origin_path().parent(), pat.into(), compile_time_info.environment().compile_target(), @@ -1034,18 +1027,19 @@ pub(crate) async fn analyze_ecmascript_module( ) } JsValue::WellKnownFunction(WellKnownFunctionKind::NodeGypBuild) => { - use crate::resolve::node_native_binding::NodeGypBuildReferenceVc; + use crate::resolve::node_native_binding::NodeGypBuildReference; let args = linked_args(args).await?; if args.len() == 1 { let first_arg = state.link_value(args[0].clone(), in_try).await?; if let Some(s) = first_arg.as_str() { - // TODO this resolving should happen within NodeGypBuildReferenceVc + // TODO this resolving should happen within + // Vc let current_context = origin .origin_path() .root() - .join(s.trim_start_matches("/ROOT/")); - analysis.add_reference(NodeGypBuildReferenceVc::new( + .join(s.trim_start_matches("/ROOT/").to_string()); + analysis.add_reference(NodeGypBuildReference::new( current_context, compile_time_info.environment().compile_target(), )); @@ -1065,13 +1059,13 @@ pub(crate) async fn analyze_ecmascript_module( ) } JsValue::WellKnownFunction(WellKnownFunctionKind::NodeBindings) => { - use crate::resolve::node_native_binding::NodeBindingsReferenceVc; + use crate::resolve::node_native_binding::NodeBindingsReference; let args = linked_args(args).await?; if args.len() == 1 { let first_arg = state.link_value(args[0].clone(), in_try).await?; if let Some(ref s) = first_arg.as_str() { - analysis.add_reference(NodeBindingsReferenceVc::new( + analysis.add_reference(NodeBindingsReference::new( origin.origin_path(), s.to_string(), )); @@ -1134,7 +1128,7 @@ pub(crate) async fn analyze_ecmascript_module( .await?; js_value_to_pattern(&linked_func_call) }; - analysis.add_reference(DirAssetReferenceVc::new( + analysis.add_reference(DirAssetReference::new( source, abs_pattern.into(), )); @@ -1145,9 +1139,9 @@ pub(crate) async fn analyze_ecmascript_module( if let Some(pkg) = pkg_or_dir.as_str() { if pkg != "html" { let pat = js_value_to_pattern(pkg_or_dir); - analysis.add_reference(CjsAssetReferenceVc::new( + analysis.add_reference(CjsAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), + Request::parse(Value::new(pat)), issue_source(source, span), in_try, )); @@ -1196,10 +1190,8 @@ pub(crate) async fn analyze_ecmascript_module( .await?; js_value_to_pattern(&linked_func_call) }; - analysis.add_reference(DirAssetReferenceVc::new( - source, - abs_pattern.into(), - )); + analysis + .add_reference(DirAssetReference::new(source, abs_pattern.into())); return Ok(()); } let (args, hints) = explain_args(&args); @@ -1217,9 +1209,9 @@ pub(crate) async fn analyze_ecmascript_module( JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom) => { let args = linked_args(args).await?; if args.len() == 2 && args.get(1).and_then(|arg| arg.as_str()).is_some() { - analysis.add_reference(CjsAssetReferenceVc::new( + analysis.add_reference(CjsAssetReference::new( origin, - RequestVc::parse(Value::new(js_value_to_pattern(&args[1]))), + Request::parse(Value::new(js_value_to_pattern(&args[1]))), issue_source(source, span), in_try, )); @@ -1260,7 +1252,7 @@ pub(crate) async fn analyze_ecmascript_module( }) .flatten() { - analysis.add_reference(DirAssetReferenceVc::new( + analysis.add_reference(DirAssetReference::new( source, Pattern::Constant(dir).into(), )); @@ -1327,7 +1319,7 @@ pub(crate) async fn analyze_ecmascript_module( ) if s.as_str() == Some("cache") => { analysis.add_code_gen( CjsRequireCacheAccess { - path: AstPathVc::cell(ast_path.to_vec()), + path: Vc::cell(ast_path.to_vec()), } .cell(), ); @@ -1385,9 +1377,9 @@ pub(crate) async fn analyze_ecmascript_module( } match value { FreeVarReference::Value(value) => { - analysis.add_code_gen(ConstantValueVc::new( + analysis.add_code_gen(ConstantValue::new( Value::new(value.clone()), - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), )); } FreeVarReference::EcmaScriptModule { @@ -1395,28 +1387,28 @@ pub(crate) async fn analyze_ecmascript_module( context, export, } => { - let esm_reference = EsmAssetReferenceVc::new( + let esm_reference = EsmAssetReference::new( context.map_or(state.origin, |context| { - PlainResolveOriginVc::new(state.origin.context(), context).into() + Vc::upcast(PlainResolveOrigin::new(state.origin.context(), context)) }), - RequestVc::parse(Value::new(request.clone().into())), + Request::parse(Value::new(request.clone().into())), Default::default(), state .import_parts .then(|| { export .as_ref() - .map(|export| ModulePartVc::export(export.to_string())) + .map(|export| ModulePart::export(export.to_string())) }) .flatten(), ) .resolve() .await?; analysis.add_reference(esm_reference); - analysis.add_code_gen(EsmBindingVc::new( + analysis.add_code_gen(EsmBinding::new( esm_reference, export.clone(), - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), )); } } @@ -1488,16 +1480,16 @@ pub(crate) async fn analyze_ecmascript_module( macro_rules! inactive { ($block:ident) => { - analysis.add_code_gen(UnreachableVc::new(AstPathVc::cell( + analysis.add_code_gen(Unreachable::new(Vc::cell( $block.ast_path.to_vec(), ))); }; } macro_rules! condition { ($expr:expr) => { - analysis.add_code_gen(ConstantConditionVc::new( + analysis.add_code_gen(ConstantCondition::new( Value::new($expr), - AstPathVc::cell(condition_ast_path.to_vec()), + Vc::cell(condition_ast_path.to_vec()), )); }; } @@ -1713,15 +1705,15 @@ pub(crate) async fn analyze_ecmascript_module( } => { if let Some(r) = import_references.get(esm_reference_index) { if let Some("__turbopack_module_id__") = export.as_deref() { - analysis.add_reference(EsmModuleIdAssetReferenceVc::new( + analysis.add_reference(EsmModuleIdAssetReference::new( *r, - AstPathVc::cell(ast_path), + Vc::cell(ast_path), )) } else { - analysis.add_code_gen(EsmBindingVc::new( + analysis.add_code_gen(EsmBinding::new( *r, export, - AstPathVc::cell(ast_path), + Vc::cell(ast_path), )); } } @@ -1733,13 +1725,12 @@ pub(crate) async fn analyze_ecmascript_module( } => { if analysis_state.first_import_meta { analysis_state.first_import_meta = false; - analysis.add_code_gen(ImportMetaBindingVc::new( + analysis.add_code_gen(ImportMetaBinding::new( source.ident().path(), )); } - analysis - .add_code_gen(ImportMetaRefVc::new(AstPathVc::cell(ast_path))); + analysis.add_code_gen(ImportMetaRef::new(Vc::cell(ast_path))); } Effect::Url { input, @@ -1758,12 +1749,12 @@ pub(crate) async fn analyze_ecmascript_module( ), ) } - analysis.add_reference(UrlAssetReferenceVc::new( + analysis.add_reference(UrlAssetReference::new( origin, - RequestVc::parse(Value::new(pat)), + Request::parse(Value::new(pat)), compile_time_info.environment().rendering(), - AstPathVc::cell(ast_path), - IssueSourceVc::from_byte_offset( + Vc::cell(ast_path), + IssueSource::from_byte_offset( source, span.lo.to_usize(), span.hi.to_usize(), @@ -1783,14 +1774,14 @@ pub(crate) async fn analyze_ecmascript_module( analysis.build().await } -fn issue_source(source: AssetVc, span: Span) -> IssueSourceVc { - IssueSourceVc::from_byte_offset(source, span.lo.to_usize(), span.hi.to_usize()) +fn issue_source(source: Vc>, span: Span) -> Vc { + IssueSource::from_byte_offset(source, span.lo.to_usize(), span.hi.to_usize()) } fn analyze_amd_define( - source: AssetVc, + source: Vc>, analysis: &mut AnalyzeEcmascriptModuleResultBuilder, - origin: ResolveOriginVc, + origin: Vc>, handler: &Handler, span: Span, ast_path: &[AstParentKind], @@ -1817,66 +1808,66 @@ fn analyze_amd_define( ); } [JsValue::Constant(id), JsValue::Function(..)] if id.as_str().is_some() => { - analysis.add_code_gen(AmdDefineWithDependenciesCodeGenVc::new( + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( vec![ AmdDefineDependencyElement::Require, AmdDefineDependencyElement::Exports, AmdDefineDependencyElement::Module, ], origin, - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), AmdDefineFactoryType::Function, issue_source(source, span), in_try, )); } [JsValue::Constant(id), _] if id.as_str().is_some() => { - analysis.add_code_gen(AmdDefineWithDependenciesCodeGenVc::new( + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( vec![ AmdDefineDependencyElement::Require, AmdDefineDependencyElement::Exports, AmdDefineDependencyElement::Module, ], origin, - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), AmdDefineFactoryType::Unknown, issue_source(source, span), in_try, )); } [JsValue::Function(..)] => { - analysis.add_code_gen(AmdDefineWithDependenciesCodeGenVc::new( + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( vec![ AmdDefineDependencyElement::Require, AmdDefineDependencyElement::Exports, AmdDefineDependencyElement::Module, ], origin, - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), AmdDefineFactoryType::Function, issue_source(source, span), in_try, )); } [JsValue::Object { .. }] => { - analysis.add_code_gen(AmdDefineWithDependenciesCodeGenVc::new( + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( vec![], origin, - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), AmdDefineFactoryType::Value, issue_source(source, span), in_try, )); } [_] => { - analysis.add_code_gen(AmdDefineWithDependenciesCodeGenVc::new( + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( vec![ AmdDefineDependencyElement::Require, AmdDefineDependencyElement::Exports, AmdDefineDependencyElement::Module, ], origin, - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), AmdDefineFactoryType::Unknown, issue_source(source, span), in_try, @@ -1893,9 +1884,9 @@ fn analyze_amd_define( } fn analyze_amd_define_with_deps( - source: AssetVc, + source: Vc>, analysis: &mut AnalyzeEcmascriptModuleResultBuilder, - origin: ResolveOriginVc, + origin: Vc>, handler: &Handler, span: Span, ast_path: &[AstParentKind], @@ -1924,8 +1915,8 @@ fn analyze_amd_define_with_deps( requests.push(AmdDefineDependencyElement::Module); } _ => { - let request = RequestVc::parse_string(dep.to_string()); - let reference = AmdDefineAssetReferenceVc::new( + let request = Request::parse_string(dep.to_string()); + let reference = AmdDefineAssetReference::new( origin, request, issue_source(source, span), @@ -1954,10 +1945,10 @@ fn analyze_amd_define_with_deps( ); } - analysis.add_code_gen(AmdDefineWithDependenciesCodeGenVc::new( + analysis.add_code_gen(AmdDefineWithDependenciesCodeGen::new( requests, origin, - AstPathVc::cell(ast_path.to_vec()), + Vc::cell(ast_path.to_vec()), AmdDefineFactoryType::Function, issue_source(source, span), in_try, @@ -1966,7 +1957,7 @@ fn analyze_amd_define_with_deps( /// Used to generate the "root" path to a __filename/__dirname/import.meta.url /// reference. -pub async fn as_abs_path(path: FileSystemPathVc) -> Result { +pub async fn as_abs_path(path: Vc) -> Result { // TODO: This should be updated to generate a real system path on the fly // during runtime, so that the generated code is constant between systems // but the runtime evaluation can take into account the project's @@ -1975,7 +1966,7 @@ pub async fn as_abs_path(path: FileSystemPathVc) -> Result { } /// Generates an absolute path usable for `require.resolve()` calls. -async fn require_resolve(path: FileSystemPathVc) -> Result { +async fn require_resolve(path: Vc) -> Result { Ok(format!("/ROOT/{}", path.await?.path.as_str()).into()) } @@ -1985,9 +1976,9 @@ async fn early_value_visitor(mut v: JsValue) -> Result<(JsValue, bool)> { } async fn value_visitor( - origin: ResolveOriginVc, + origin: Vc>, v: JsValue, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, in_try: bool, ) -> Result<(JsValue, bool)> { let (mut v, modified) = value_visitor_inner(origin, v, compile_time_info, in_try).await?; @@ -1996,9 +1987,9 @@ async fn value_visitor( } async fn value_visitor_inner( - origin: ResolveOriginVc, + origin: Vc>, v: JsValue, - compile_time_info: CompileTimeInfoVc, + compile_time_info: Vc, in_try: bool, ) -> Result<(JsValue, bool)> { if let Some(def_name_len) = v.get_defineable_name_len() { @@ -2098,17 +2089,17 @@ async fn value_visitor_inner( } async fn require_resolve_visitor( - origin: ResolveOriginVc, + origin: Vc>, args: Vec, in_try: bool, ) -> Result { Ok(if args.len() == 1 { let pat = js_value_to_pattern(&args[0]); - let request = RequestVc::parse(Value::new(pat.clone())); + let request = Request::parse(Value::new(pat.clone())); let resolved = cjs_resolve( origin, request, - OptionIssueSourceVc::none(), + OptionIssueSource::none(), try_to_severity(in_try), ) .await?; @@ -2155,7 +2146,7 @@ async fn require_resolve_visitor( } async fn require_context_visitor( - origin: ResolveOriginVc, + origin: Vc>, args: Vec, in_try: bool, ) -> Result { @@ -2174,19 +2165,19 @@ async fn require_context_visitor( } }; - let dir = origin.origin_path().parent().join(&options.dir); + let dir = origin.origin_path().parent().join(options.dir.clone()); - let map = RequireContextMapVc::generate( + let map = RequireContextMap::generate( origin, dir, options.include_subdirs, - RegexVc::cell(options.filter), - OptionIssueSourceVc::none(), + Vc::cell(options.filter), + OptionIssueSource::none(), try_to_severity(in_try), ); Ok(JsValue::WellKnownFunction( - WellKnownFunctionKind::RequireContextRequire(RequireContextValueVc::from_context_map(map)), + WellKnownFunctionKind::RequireContextRequire(RequireContextValue::from_context_map(map)), )) } @@ -2253,10 +2244,10 @@ impl StaticAnalyser { struct AssetReferencesVisitor<'a> { eval_context: &'a EvalContext, old_analyser: StaticAnalyser, - import_references: &'a [EsmAssetReferenceVc], + import_references: &'a [Vc], analysis: &'a mut AnalyzeEcmascriptModuleResultBuilder, esm_exports: BTreeMap, - esm_star_exports: Vec, + esm_star_exports: Vec>, webpack_runtime: Option<(String, Span)>, webpack_entry: bool, webpack_chunks: Vec, @@ -2265,7 +2256,7 @@ struct AssetReferencesVisitor<'a> { impl<'a> AssetReferencesVisitor<'a> { fn new( eval_context: &'a EvalContext, - import_references: &'a [EsmAssetReferenceVc], + import_references: &'a [Vc], analysis: &'a mut AnalyzeEcmascriptModuleResultBuilder, ) -> Self { Self { @@ -2349,8 +2340,8 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { export: &'ast ExportAll, ast_path: &mut AstNodePath>, ) { - let path = AstPathVc::cell(as_parent_path(ast_path)); - self.analysis.add_code_gen(EsmModuleItemVc::new(path)); + let path = Vc::cell(as_parent_path(ast_path)); + self.analysis.add_code_gen(EsmModuleItem::new(path)); export.visit_children_with_path(self, ast_path); } @@ -2359,7 +2350,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { export: &'ast NamedExport, ast_path: &mut AstNodePath>, ) { - let path = AstPathVc::cell(as_parent_path(ast_path)); + let path = Vc::cell(as_parent_path(ast_path)); if export.src.is_none() { for spec in export.specifiers.iter() { fn to_string(name: &ModuleExportName) -> String { @@ -2407,7 +2398,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { } } - self.analysis.add_code_gen(EsmModuleItemVc::new(path)); + self.analysis.add_code_gen(EsmModuleItem::new(path)); export.visit_children_with_path(self, ast_path); } @@ -2421,9 +2412,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { .insert(name.clone(), EsmExport::LocalBinding(name)); }); self.analysis - .add_code_gen(EsmModuleItemVc::new(AstPathVc::cell(as_parent_path( - ast_path, - )))); + .add_code_gen(EsmModuleItem::new(Vc::cell(as_parent_path(ast_path)))); export.visit_children_with_path(self, ast_path); } @@ -2437,9 +2426,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { EsmExport::LocalBinding(magic_identifier::mangle("default export")), ); self.analysis - .add_code_gen(EsmModuleItemVc::new(AstPathVc::cell(as_parent_path( - ast_path, - )))); + .add_code_gen(EsmModuleItem::new(Vc::cell(as_parent_path(ast_path)))); export.visit_children_with_path(self, ast_path); } @@ -2465,9 +2452,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { } } self.analysis - .add_code_gen(EsmModuleItemVc::new(AstPathVc::cell(as_parent_path( - ast_path, - )))); + .add_code_gen(EsmModuleItem::new(Vc::cell(as_parent_path(ast_path)))); export.visit_children_with_path(self, ast_path); } @@ -2476,7 +2461,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { import: &'ast ImportDecl, ast_path: &mut AstNodePath>, ) { - let path = AstPathVc::cell(as_parent_path(ast_path)); + let path = Vc::cell(as_parent_path(ast_path)); let src = import.src.value.to_string(); import.visit_children_with_path(self, ast_path); if import.type_only { @@ -2512,7 +2497,7 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { } } } - self.analysis.add_code_gen(EsmModuleItemVc::new(path)); + self.analysis.add_code_gen(EsmModuleItem::new(path)); } fn visit_var_declarator<'ast: 'r, 'r>( @@ -2586,10 +2571,10 @@ impl<'a> VisitAstPath for AssetReferencesVisitor<'a> { #[turbo_tasks::function] async fn resolve_as_webpack_runtime( - origin: ResolveOriginVc, - request: RequestVc, - transforms: EcmascriptInputTransformsVc, -) -> Result { + origin: Vc>, + request: Vc, + transforms: Vc, +) -> Result> { let ty = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)); let options = origin.resolve_options(ty.clone()); diff --git a/crates/turbopack-ecmascript/src/references/node.rs b/crates/turbopack-ecmascript/src/references/node.rs index 12dd9ff50728b2..c734f9be6bf363 100644 --- a/crates/turbopack-ecmascript/src/references/node.rs +++ b/crates/turbopack-ecmascript/src/references/node.rs @@ -2,31 +2,27 @@ use std::{future::Future, pin::Pin}; use anyhow::Result; use indexmap::IndexSet; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::{ - DirectoryContent, DirectoryEntry, FileSystem, FileSystemEntryType, FileSystemPathVc, - FileSystemVc, + DirectoryContent, DirectoryEntry, FileSystem, FileSystemEntryType, FileSystemPath, }; use turbopack_core::{ - asset::{Asset, AssetVc}, - reference::{AssetReference, AssetReferenceVc}, - resolve::{ - pattern::{Pattern, PatternVc}, - ResolveResult, ResolveResultVc, - }, - source_asset::SourceAssetVc, + asset::Asset, + reference::AssetReference, + resolve::{pattern::Pattern, ResolveResult}, + source_asset::SourceAsset, }; #[turbo_tasks::value] #[derive(Hash, Clone, Debug)] pub struct PackageJsonReference { - pub package_json: FileSystemPathVc, + pub package_json: Vc, } #[turbo_tasks::value_impl] -impl PackageJsonReferenceVc { +impl PackageJsonReference { #[turbo_tasks::function] - pub fn new(package_json: FileSystemPathVc) -> Self { + pub fn new(package_json: Vc) -> Vc { Self::cell(PackageJsonReference { package_json }) } } @@ -34,16 +30,16 @@ impl PackageJsonReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for PackageJsonReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset(SourceAssetVc::new(self.package_json).into()).into() + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast(SourceAsset::new(self.package_json))).into() } } #[turbo_tasks::value_impl] impl ValueToString for PackageJsonReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "package.json {}", self.package_json.to_string().await?, ))) @@ -53,14 +49,14 @@ impl ValueToString for PackageJsonReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct DirAssetReference { - pub source: AssetVc, - pub path: PatternVc, + pub source: Vc>, + pub path: Vc, } #[turbo_tasks::value_impl] -impl DirAssetReferenceVc { +impl DirAssetReference { #[turbo_tasks::function] - pub fn new(source: AssetVc, path: PatternVc) -> Self { + pub fn new(source: Vc>, path: Vc) -> Vc { Self::cell(DirAssetReference { source, path }) } } @@ -68,7 +64,7 @@ impl DirAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for DirAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { + async fn resolve_reference(&self) -> Result> { let context_path = self.source.ident().path().await?; // ignore path.join in `node-gyp`, it will includes too many files if context_path.path.contains("node_modules/node-gyp") { @@ -100,20 +96,24 @@ impl AssetReference for DirAssetReference { #[turbo_tasks::value_impl] impl ValueToString for DirAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "directory assets {}", self.path.to_string().await?, ))) } } +type AssetSet = IndexSet>>; + async fn extend_with_constant_pattern( pattern: &str, - fs: FileSystemVc, - result: &mut IndexSet, + fs: Vc>, + result: &mut AssetSet, ) -> Result<()> { - let dest_file_path = fs.root().join(pattern.trim_start_matches("/ROOT/")); + let dest_file_path = fs + .root() + .join(pattern.trim_start_matches("/ROOT/").to_string()); // ignore error let realpath_with_links = match dest_file_path.realpath_with_links().await { Ok(p) => p, @@ -124,7 +124,7 @@ async fn extend_with_constant_pattern( realpath_with_links .symlinks .iter() - .map(|l| SourceAssetVc::new(*l).as_asset()), + .map(|l| Vc::upcast(SourceAsset::new(*l))), ); let entry_type = match dest_file_path.get_type().await { Ok(e) => e, @@ -135,14 +135,14 @@ async fn extend_with_constant_pattern( result.extend(read_dir(dest_file_path).await?); } FileSystemEntryType::File | FileSystemEntryType::Symlink => { - result.insert(SourceAssetVc::new(dest_file_path).into()); + result.insert(Vc::upcast(SourceAsset::new(dest_file_path))); } _ => {} } Ok(()) } -async fn read_dir(p: FileSystemPathVc) -> Result> { +async fn read_dir(p: Vc) -> Result { let mut result = IndexSet::new(); let dir_entries = p.read_dir().await?; if let DirectoryContent::Entries(entries) = &*dir_entries { @@ -151,7 +151,7 @@ async fn read_dir(p: FileSystemPathVc) -> Result> { for (_, entry) in entries { match entry { DirectoryEntry::File(file) => { - result.insert(SourceAssetVc::new(*file).into()); + result.insert(Vc::upcast(SourceAsset::new(*file))); } DirectoryEntry::Directory(dir) => { let sub = read_dir_boxed(*dir).await?; @@ -164,8 +164,6 @@ async fn read_dir(p: FileSystemPathVc) -> Result> { Ok(result) } -fn read_dir_boxed( - p: FileSystemPathVc, -) -> Pin>> + Send>> { +fn read_dir_boxed(p: Vc) -> Pin> + Send>> { Box::pin(read_dir(p)) } diff --git a/crates/turbopack-ecmascript/src/references/pattern_mapping.rs b/crates/turbopack-ecmascript/src/references/pattern_mapping.rs index 16709cb510c1d5..b82e7c793705d5 100644 --- a/crates/turbopack-ecmascript/src/references/pattern_mapping.rs +++ b/crates/turbopack-ecmascript/src/references/pattern_mapping.rs @@ -4,23 +4,22 @@ use swc_core::{ ecma::ast::{Expr, Lit}, quote, }; -use turbo_tasks::{debug::ValueDebug, primitives::StringVc, Value, ValueToString}; +use turbo_tasks::{debug::ValueDebug, Value, ValueToString, Vc}; use turbopack_core::{ asset::Asset, chunk::{ - availability_info::AvailabilityInfo, ChunkableAssetVc, ChunkingContextVc, - FromChunkableAsset, ModuleId, - }, - issue::{code_gen::CodeGenerationIssue, IssueSeverity}, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - PrimaryResolveResult, ResolveResultVc, + availability_info::AvailabilityInfo, ChunkableAsset, ChunkingContext, FromChunkableAsset, + ModuleId, }, + issue::{code_gen::CodeGenerationIssue, IssueExt, IssueSeverity}, + resolve::{origin::ResolveOrigin, parse::Request, PrimaryResolveResult, ResolveResult}, }; use super::util::{request_to_string, throw_module_not_found_expr}; -use crate::{chunk::EcmascriptChunkItemVc, utils::module_id_to_lit}; +use crate::{ + chunk::{item::EcmascriptChunkItemExt, EcmascriptChunkItem}, + utils::module_id_to_lit, +}; /// A mapping from a request pattern (e.g. "./module", `./images/${name}.png`) /// to corresponding module ids. The same pattern can map to multiple module ids @@ -118,18 +117,18 @@ impl PatternMapping { } #[turbo_tasks::value_impl] -impl PatternMappingVc { +impl PatternMapping { /// Resolves a request into a pattern mapping. // NOTE(alexkirsz) I would rather have used `resolve` here but it's already reserved by the Vc // impl. #[turbo_tasks::function] pub async fn resolve_request( - request: RequestVc, - origin: ResolveOriginVc, - context: ChunkingContextVc, - resolve_result: ResolveResultVc, + request: Vc, + origin: Vc>, + context: Vc>, + resolve_result: Vc, resolve_type: Value, - ) -> Result { + ) -> Result> { let result = resolve_result.await?; let asset = match result.primary.first() { None => { @@ -150,10 +149,10 @@ impl PatternMappingVc { // TODO implement mapping CodeGenerationIssue { severity: IssueSeverity::Bug.into(), - title: StringVc::cell( + title: Vc::cell( "pattern mapping is not implemented for this result".to_string(), ), - message: StringVc::cell(format!( + message: Vc::cell(format!( "the reference resolves to a non-trivial result, which is not supported \ yet: {:?}", resolve_result.dbg().await? @@ -161,52 +160,52 @@ impl PatternMappingVc { path: origin.origin_path(), } .cell() - .as_issue() .emit(); - return Ok(PatternMappingVc::cell(PatternMapping::Invalid)); + return Ok(PatternMapping::cell(PatternMapping::Invalid)); } }; - if let Some(chunkable) = ChunkableAssetVc::resolve_from(asset).await? { + if let Some(chunkable) = Vc::try_resolve_sidecast::>(asset).await? { if let ResolveType::EsmAsync(availability_info) = *resolve_type { let available = if let Some(available_assets) = availability_info.available_assets() { - *available_assets.includes(chunkable.into()).await? + *available_assets.includes(Vc::upcast(chunkable)).await? } else { false }; if !available { - if let Some(loader) = EcmascriptChunkItemVc::from_async_asset( + if let Some(loader) = >::from_async_asset( context, chunkable, Value::new(availability_info), ) .await? { - return Ok(PatternMappingVc::cell(PatternMapping::SingleLoader( + return Ok(PatternMapping::cell(PatternMapping::SingleLoader( loader.id().await?.clone_value(), ))); } } } - if let Some(chunk_item) = EcmascriptChunkItemVc::from_asset(context, asset).await? { - return Ok(PatternMappingVc::cell(PatternMapping::Single( + if let Some(chunk_item) = + >::from_asset(context, asset).await? + { + return Ok(PatternMapping::cell(PatternMapping::Single( chunk_item.id().await?.clone_value(), ))); } } CodeGenerationIssue { severity: IssueSeverity::Bug.into(), - title: StringVc::cell("non-ecmascript placeable asset".to_string()), - message: StringVc::cell(format!( + title: Vc::cell("non-ecmascript placeable asset".to_string()), + message: Vc::cell(format!( "asset {} is not placeable in ESM chunks, so it doesn't have a module id", asset.ident().to_string().await? )), path: origin.origin_path(), } .cell() - .as_issue() .emit(); - Ok(PatternMappingVc::cell(PatternMapping::Invalid)) + Ok(PatternMapping::cell(PatternMapping::Invalid)) } } diff --git a/crates/turbopack-ecmascript/src/references/raw.rs b/crates/turbopack-ecmascript/src/references/raw.rs index e0dd7a55d6de46..0ac74518efce43 100644 --- a/crates/turbopack-ecmascript/src/references/raw.rs +++ b/crates/turbopack-ecmascript/src/references/raw.rs @@ -1,22 +1,22 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbopack_core::{ - asset::{Asset, AssetVc}, - reference::{AssetReference, AssetReferenceVc}, - resolve::{pattern::PatternVc, resolve_raw, ResolveResultVc}, + asset::Asset, + reference::AssetReference, + resolve::{pattern::Pattern, resolve_raw, ResolveResult}, }; #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct SourceAssetReference { - pub source: AssetVc, - pub path: PatternVc, + pub source: Vc>, + pub path: Vc, } #[turbo_tasks::value_impl] -impl SourceAssetReferenceVc { +impl SourceAssetReference { #[turbo_tasks::function] - pub fn new(source: AssetVc, path: PatternVc) -> Self { + pub fn new(source: Vc>, path: Vc) -> Vc { Self::cell(SourceAssetReference { source, path }) } } @@ -24,7 +24,7 @@ impl SourceAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for SourceAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { + async fn resolve_reference(&self) -> Result> { let context = self.source.ident().path().parent(); Ok(resolve_raw(context, self.path, false)) @@ -34,8 +34,8 @@ impl AssetReference for SourceAssetReference { #[turbo_tasks::value_impl] impl ValueToString for SourceAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "raw asset {}", self.path.to_string().await?, ))) diff --git a/crates/turbopack-ecmascript/src/references/require_context.rs b/crates/turbopack-ecmascript/src/references/require_context.rs index 439c0d6b7e5900..e541f4340cad9c 100644 --- a/crates/turbopack-ecmascript/src/references/require_context.rs +++ b/crates/turbopack-ecmascript/src/references/require_context.rs @@ -13,70 +13,60 @@ use swc_core::{ }, quote, quote_expr, }; -use turbo_tasks::{ - primitives::{RegexVc, StringVc}, - Value, ValueToString, ValueToStringVc, -}; -use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemPathVc}; +use turbo_tasks::{primitives::Regex, Value, ValueToString, Vc}; +use turbo_tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContext, - ChunkingContextVc, - }, - ident::AssetIdentVc, - issue::{IssueSeverityVc, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - ResolveResult, ResolveResultVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, + ChunkableAssetReference, ChunkingContext, }, + ident::AssetIdent, + issue::{IssueSeverity, OptionIssueSource}, + reference::{AssetReference, AssetReferences}, + resolve::{origin::ResolveOrigin, parse::Request, ResolveResult}, }; use crate::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkVc, - EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + item::EcmascriptChunkItemExt, EcmascriptChunk, EcmascriptChunkItem, + EcmascriptChunkItemContent, EcmascriptChunkingContext, EcmascriptExports, }, - chunk_group_files_asset::ChunkGroupFilesAssetVc, - code_gen::{CodeGenerateable, CodeGeneration, CodeGenerationVc}, + code_gen::CodeGeneration, create_visitor, references::{ - pattern_mapping::{PatternMappingVc, ResolveType::Cjs}, - AstPathVc, + pattern_mapping::{PatternMapping, ResolveType::Cjs}, + AstPath, }, resolve::{cjs_resolve, try_to_severity}, utils::module_id_to_lit, - CodeGenerateableVc, EcmascriptChunkPlaceableVc, + CodeGenerateable, EcmascriptChunkPlaceable, }; #[turbo_tasks::value] #[derive(Debug)] pub(crate) enum DirListEntry { - File(FileSystemPathVc), - Dir(DirListVc), + File(Vc), + Dir(Vc), } #[turbo_tasks::value(transparent)] pub(crate) struct DirList(IndexMap); #[turbo_tasks::value_impl] -impl DirListVc { +impl DirList { #[turbo_tasks::function] - pub(crate) fn read(dir: FileSystemPathVc, recursive: bool, filter: RegexVc) -> Self { + pub(crate) fn read(dir: Vc, recursive: bool, filter: Vc) -> Vc { Self::read_internal(dir, dir, recursive, filter) } #[turbo_tasks::function] pub(crate) async fn read_internal( - root: FileSystemPathVc, - dir: FileSystemPathVc, + root: Vc, + dir: Vc, recursive: bool, - filter: RegexVc, - ) -> Result { + filter: Vc, + ) -> Result> { let root_val = &*dir.await?; let regex = &*filter.await?; @@ -101,7 +91,7 @@ impl DirListVc { if let Some(relative_path) = root_val.get_relative_path_to(&*path.await?) { list.insert( relative_path, - DirListEntry::Dir(DirListVc::read_internal( + DirListEntry::Dir(DirList::read_internal( root, *path, recursive, filter, )), ); @@ -114,11 +104,11 @@ impl DirListVc { list.sort_keys(); - Ok(Self::cell(list)) + Ok(Vc::cell(list)) } #[turbo_tasks::function] - async fn flatten(self) -> Result { + async fn flatten(self: Vc) -> Result> { let this = self.await?; let mut queue = VecDeque::from([this]); @@ -138,18 +128,18 @@ impl DirListVc { } } - Ok(FlatDirListVc::cell(list)) + Ok(Vc::cell(list)) } } #[turbo_tasks::value(transparent)] -pub(crate) struct FlatDirList(IndexMap); +pub(crate) struct FlatDirList(IndexMap>); #[turbo_tasks::value_impl] -impl FlatDirListVc { +impl FlatDirList { #[turbo_tasks::function] - pub(crate) fn read(dir: FileSystemPathVc, recursive: bool, filter: RegexVc) -> Self { - DirListVc::read(dir, recursive, filter).flatten() + pub(crate) fn read(dir: Vc, recursive: bool, filter: Vc) -> Vc { + DirList::read(dir, recursive, filter).flatten() } } @@ -157,8 +147,8 @@ impl FlatDirListVc { #[derive(Debug)] pub struct RequireContextMapEntry { pub origin_relative: String, - pub request: RequestVc, - pub result: ResolveResultVc, + pub request: Vc, + pub result: Vc, } /// The resolved context map for a `require.context(..)` call. @@ -166,25 +156,25 @@ pub struct RequireContextMapEntry { pub struct RequireContextMap(IndexMap); #[turbo_tasks::value_impl] -impl RequireContextMapVc { +impl RequireContextMap { #[turbo_tasks::function] pub(crate) async fn generate( - origin: ResolveOriginVc, - dir: FileSystemPathVc, + origin: Vc>, + dir: Vc, recursive: bool, - filter: RegexVc, - issue_source: OptionIssueSourceVc, - issue_severity: IssueSeverityVc, - ) -> Result { + filter: Vc, + issue_source: Vc, + issue_severity: Vc, + ) -> Result> { let origin_path = &*origin.origin_path().parent().await?; - let list = &*FlatDirListVc::read(dir, recursive, filter).await?; + let list = &*FlatDirList::read(dir, recursive, filter).await?; let mut map = IndexMap::new(); for (context_relative, path) in list { if let Some(origin_relative) = origin_path.get_relative_path_to(&*path.await?) { - let request = RequestVc::parse(Value::new(origin_relative.clone().into())); + let request = Request::parse(Value::new(origin_relative.clone().into())); let result = cjs_resolve(origin, request, issue_source, issue_severity); map.insert( @@ -200,7 +190,7 @@ impl RequireContextMapVc { } } - Ok(Self::cell(map)) + Ok(Vc::cell(map)) } } @@ -209,31 +199,31 @@ impl RequireContextMapVc { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct RequireContextAssetReference { - pub inner: RequireContextAssetVc, + pub inner: Vc, pub dir: String, pub include_subdirs: bool, - pub path: AstPathVc, - pub issue_source: OptionIssueSourceVc, + pub path: Vc, + pub issue_source: Vc, pub in_try: bool, } #[turbo_tasks::value_impl] -impl RequireContextAssetReferenceVc { +impl RequireContextAssetReference { #[turbo_tasks::function] pub fn new( - source: AssetVc, - origin: ResolveOriginVc, + source: Vc>, + origin: Vc>, dir: String, include_subdirs: bool, - filter: RegexVc, - path: AstPathVc, - issue_source: OptionIssueSourceVc, + filter: Vc, + path: Vc, + issue_source: Vc, in_try: bool, - ) -> Self { - let map = RequireContextMapVc::generate( + ) -> Vc { + let map = RequireContextMap::generate( origin, - origin.origin_path().parent().join(&dir), + origin.origin_path().parent().join(dir.clone()), include_subdirs, filter, issue_source, @@ -263,16 +253,16 @@ impl RequireContextAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for RequireContextAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset(self.inner.into()).cell() + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast(self.inner)).cell() } } #[turbo_tasks::value_impl] impl ValueToString for RequireContextAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "require.context {}/{}", self.dir, if self.include_subdirs { "**" } else { "*" }, @@ -288,8 +278,8 @@ impl CodeGenerateable for RequireContextAssetReference { #[turbo_tasks::function] async fn code_generation( &self, - context: EcmascriptChunkingContextVc, - ) -> Result { + context: Vc>, + ) -> Result> { let chunk_item = self.inner.as_chunk_item(context); let module_id = chunk_item.id().await?.clone_value(); @@ -310,12 +300,12 @@ impl CodeGenerateable for RequireContextAssetReference { } #[turbo_tasks::value(transparent)] -pub struct ResolvedAssetReference(ResolveResultVc); +pub struct ResolvedAssetReference(Vc); #[turbo_tasks::value_impl] impl AssetReference for ResolvedAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { self.0 } } @@ -323,8 +313,8 @@ impl AssetReference for ResolvedAssetReference { #[turbo_tasks::value_impl] impl ValueToString for ResolvedAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("resolved reference".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("resolved reference".to_string())) } } @@ -333,18 +323,18 @@ impl ChunkableAssetReference for ResolvedAssetReference {} #[turbo_tasks::value] pub struct RequireContextAsset { - source: AssetVc, + source: Vc>, - origin: ResolveOriginVc, - map: RequireContextMapVc, + origin: Vc>, + map: Vc, dir: String, include_subdirs: bool, } #[turbo_tasks::function] -fn modifier(dir: String, include_subdirs: bool) -> StringVc { - StringVc::cell(format!( +fn modifier(dir: String, include_subdirs: bool) -> Vc { + Vc::cell(format!( "require.context {}/{}", dir, if include_subdirs { "**" } else { "*" }, @@ -354,24 +344,24 @@ fn modifier(dir: String, include_subdirs: bool) -> StringVc { #[turbo_tasks::value_impl] impl Asset for RequireContextAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source .ident() .with_modifier(modifier(self.dir.clone(), self.include_subdirs)) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { unimplemented!() } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { let map = &*self.map.await?; - Ok(AssetReferencesVc::cell( + Ok(Vc::cell( map.iter() - .map(|(_, entry)| ResolvedAssetReferenceVc::cell(entry.result).as_asset_reference()) + .map(|(_, entry)| Vc::upcast(Vc::::cell(entry.result))) .collect(), )) } @@ -381,16 +371,15 @@ impl Asset for RequireContextAsset { impl ChunkableAsset for RequireContextAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: ChunkGroupFilesAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } @@ -398,45 +387,46 @@ impl ChunkableAsset for RequireContextAsset { impl EcmascriptChunkPlaceable for RequireContextAsset { #[turbo_tasks::function] async fn as_chunk_item( - self_vc: RequireContextAssetVc, - context: EcmascriptChunkingContextVc, - ) -> Result { - let this = self_vc.await?; - Ok(RequireContextChunkItem { - context, - inner: self_vc, + self: Vc, + context: Vc>, + ) -> Result>> { + let this = self.await?; + Ok(Vc::upcast( + RequireContextChunkItem { + context, + inner: self, - origin: this.origin, - map: this.map, - } - .cell() - .into()) + origin: this.origin, + map: this.map, + } + .cell(), + )) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } } #[turbo_tasks::value] pub struct RequireContextChunkItem { - context: EcmascriptChunkingContextVc, - inner: RequireContextAssetVc, + context: Vc>, + inner: Vc, - origin: ResolveOriginVc, - map: RequireContextMapVc, + origin: Vc>, + map: Vc, } #[turbo_tasks::value_impl] impl EcmascriptChunkItem for RequireContextChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let map = &*self.map.await?; let mut context_map = ObjectLit { @@ -445,10 +435,10 @@ impl EcmascriptChunkItem for RequireContextChunkItem { }; for (key, entry) in map { - let pm = PatternMappingVc::resolve_request( + let pm = PatternMapping::resolve_request( entry.request, self.origin, - self.context.into(), + Vc::upcast(self.context), entry.result, Value::new(Cjs), ) @@ -514,12 +504,12 @@ impl EcmascriptChunkItem for RequireContextChunkItem { #[turbo_tasks::value_impl] impl ChunkItem for RequireContextChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.inner.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.inner.references() } } diff --git a/crates/turbopack-ecmascript/src/references/type_issue.rs b/crates/turbopack-ecmascript/src/references/type_issue.rs index 13984c0f224177..11724a145e7b76 100644 --- a/crates/turbopack-ecmascript/src/references/type_issue.rs +++ b/crates/turbopack-ecmascript/src/references/type_issue.rs @@ -1,36 +1,36 @@ -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::{Issue, IssueSeverity}; use crate::SpecifiedModuleType; #[turbo_tasks::value(shared)] pub struct SpecifiedModuleTypeIssue { - pub path: FileSystemPathVc, + pub path: Vc, pub specified_type: SpecifiedModuleType, } #[turbo_tasks::value_impl] impl Issue for SpecifiedModuleTypeIssue { #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.path } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { match self.specified_type { - SpecifiedModuleType::CommonJs => StringVc::cell( + SpecifiedModuleType::CommonJs => Vc::cell( "Specified module format (CommonJs) is not matching the module format of the \ source code (EcmaScript Modules)" .to_string(), ), - SpecifiedModuleType::EcmaScript => StringVc::cell( + SpecifiedModuleType::EcmaScript => Vc::cell( "Specified module format (EcmaScript Modules) is not matching the module format \ of the source code (CommonJs)" .to_string(), ), - SpecifiedModuleType::Automatic => StringVc::cell( + SpecifiedModuleType::Automatic => Vc::cell( "Specified module format is not matching the module format of the source code" .to_string(), ), @@ -38,9 +38,9 @@ impl Issue for SpecifiedModuleTypeIssue { } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { match self.specified_type { - SpecifiedModuleType::CommonJs => StringVc::cell( + SpecifiedModuleType::CommonJs => Vc::cell( "The CommonJs module format was specified in the package.json that is affecting \ this source file or by using an special extension, but Ecmascript import/export \ syntax is used in the source code.\nThe module was automatically converted to an \ @@ -52,7 +52,7 @@ impl Issue for SpecifiedModuleTypeIssue { correct syntax." .to_string(), ), - SpecifiedModuleType::EcmaScript => StringVc::cell( + SpecifiedModuleType::EcmaScript => Vc::cell( "The EcmaScript module format was specified in the package.json that is affecting \ this source file or by using an special extension, but it looks like that \ CommonJs syntax is used in the source code.\nExports made by CommonJs syntax \ @@ -61,7 +61,7 @@ impl Issue for SpecifiedModuleTypeIssue { EcmaScript import/export syntax in the source file." .to_string(), ), - SpecifiedModuleType::Automatic => StringVc::cell( + SpecifiedModuleType::Automatic => Vc::cell( "The module format specified in the package.json file is not matching the module \ format of the source code." .to_string(), @@ -70,7 +70,7 @@ impl Issue for SpecifiedModuleTypeIssue { } #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { match self.specified_type { SpecifiedModuleType::CommonJs => IssueSeverity::Error.cell(), SpecifiedModuleType::EcmaScript => IssueSeverity::Warning.cell(), @@ -79,7 +79,7 @@ impl Issue for SpecifiedModuleTypeIssue { } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("module type".to_string()) + fn category(&self) -> Vc { + Vc::cell("module type".to_string()) } } diff --git a/crates/turbopack-ecmascript/src/references/typescript.rs b/crates/turbopack-ecmascript/src/references/typescript.rs index 159e90db5a32c4..d7bdbf847947d1 100644 --- a/crates/turbopack-ecmascript/src/references/typescript.rs +++ b/crates/turbopack-ecmascript/src/references/typescript.rs @@ -1,32 +1,27 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Value, ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ context::AssetContext, - reference::{AssetReference, AssetReferenceVc}, + reference::AssetReference, reference_type::{ReferenceType, TypeScriptReferenceSubType}, - resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - pattern::QueryMapVc, - ResolveResult, ResolveResultVc, - }, - source_asset::SourceAssetVc, + resolve::{origin::ResolveOrigin, parse::Request, pattern::QueryMap, ResolveResult}, + source_asset::SourceAsset, }; -use crate::typescript::{resolve::type_resolve, TsConfigModuleAssetVc}; +use crate::typescript::{resolve::type_resolve, TsConfigModuleAsset}; #[turbo_tasks::value] #[derive(Hash, Clone, Debug)] pub struct TsConfigReference { - pub tsconfig: FileSystemPathVc, - pub origin: ResolveOriginVc, + pub tsconfig: Vc, + pub origin: Vc>, } #[turbo_tasks::value_impl] -impl TsConfigReferenceVc { +impl TsConfigReference { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, tsconfig: FileSystemPathVc) -> Self { + pub fn new(origin: Vc>, tsconfig: Vc) -> Vc { Self::cell(TsConfigReference { tsconfig, origin }) } } @@ -34,11 +29,11 @@ impl TsConfigReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for TsConfigReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset( - TsConfigModuleAssetVc::new(self.origin, SourceAssetVc::new(self.tsconfig).into()) - .into(), - ) + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast(TsConfigModuleAsset::new( + self.origin, + Vc::upcast(SourceAsset::new(self.tsconfig)), + ))) .into() } } @@ -46,8 +41,8 @@ impl AssetReference for TsConfigReference { #[turbo_tasks::value_impl] impl ValueToString for TsConfigReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "tsconfig {}", self.tsconfig.to_string().await?, ))) @@ -57,14 +52,14 @@ impl ValueToString for TsConfigReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct TsReferencePathAssetReference { - pub origin: ResolveOriginVc, + pub origin: Vc>, pub path: String, } #[turbo_tasks::value_impl] -impl TsReferencePathAssetReferenceVc { +impl TsReferencePathAssetReference { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, path: String) -> Self { + pub fn new(origin: Vc>, path: String) -> Vc { Self::cell(TsReferencePathAssetReference { origin, path }) } } @@ -72,17 +67,17 @@ impl TsReferencePathAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for TsReferencePathAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { + async fn resolve_reference(&self) -> Result> { Ok( if let Some(path) = &*self .origin .origin_path() .parent() - .try_join(&self.path) + .try_join(self.path.clone()) .await? { ResolveResult::asset(self.origin.context().process( - SourceAssetVc::new(*path).into(), + Vc::upcast(SourceAsset::new(*path)), Value::new(ReferenceType::TypeScript( TypeScriptReferenceSubType::Undefined, )), @@ -98,8 +93,8 @@ impl AssetReference for TsReferencePathAssetReference { #[turbo_tasks::value_impl] impl ValueToString for TsReferencePathAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "typescript reference path comment {}", self.path, ))) @@ -109,14 +104,14 @@ impl ValueToString for TsReferencePathAssetReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct TsReferenceTypeAssetReference { - pub origin: ResolveOriginVc, + pub origin: Vc>, pub module: String, } #[turbo_tasks::value_impl] -impl TsReferenceTypeAssetReferenceVc { +impl TsReferenceTypeAssetReference { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, module: String) -> Self { + pub fn new(origin: Vc>, module: String) -> Vc { Self::cell(TsReferenceTypeAssetReference { origin, module }) } } @@ -124,13 +119,13 @@ impl TsReferenceTypeAssetReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for TsReferenceTypeAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { type_resolve( self.origin, - RequestVc::module( + Request::module( self.module.clone(), Value::new("".to_string().into()), - QueryMapVc::none(), + QueryMap::none(), ), ) } @@ -139,8 +134,8 @@ impl AssetReference for TsReferenceTypeAssetReference { #[turbo_tasks::value_impl] impl ValueToString for TsReferenceTypeAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "typescript reference type comment {}", self.module, ))) diff --git a/crates/turbopack-ecmascript/src/references/unreachable.rs b/crates/turbopack-ecmascript/src/references/unreachable.rs index 807ae83a8977fc..e7db8159f1ad4f 100644 --- a/crates/turbopack-ecmascript/src/references/unreachable.rs +++ b/crates/turbopack-ecmascript/src/references/unreachable.rs @@ -1,22 +1,23 @@ use anyhow::Result; use swc_core::quote; +use turbo_tasks::Vc; -use super::AstPathVc; +use super::AstPath; use crate::{ - chunk::EcmascriptChunkingContextVc, - code_gen::{CodeGenerateable, CodeGenerateableVc, CodeGeneration, CodeGenerationVc}, + chunk::EcmascriptChunkingContext, + code_gen::{CodeGenerateable, CodeGeneration}, create_visitor, }; #[turbo_tasks::value] pub struct Unreachable { - path: AstPathVc, + path: Vc, } #[turbo_tasks::value_impl] -impl UnreachableVc { +impl Unreachable { #[turbo_tasks::function] - pub fn new(path: AstPathVc) -> Self { + pub fn new(path: Vc) -> Vc { Self::cell(Unreachable { path }) } } @@ -26,8 +27,8 @@ impl CodeGenerateable for Unreachable { #[turbo_tasks::function] async fn code_generation( &self, - _context: EcmascriptChunkingContextVc, - ) -> Result { + _context: Vc>, + ) -> Result> { let path = self.path.await?; let visitors = [ // Unreachable might be used on Stmt or Expr diff --git a/crates/turbopack-ecmascript/src/references/util.rs b/crates/turbopack-ecmascript/src/references/util.rs index ab6d31102be27f..d42a8ef7d7ee37 100644 --- a/crates/turbopack-ecmascript/src/references/util.rs +++ b/crates/turbopack-ecmascript/src/references/util.rs @@ -1,7 +1,7 @@ use anyhow::Result; use swc_core::{ecma::ast::Expr, quote}; -use turbo_tasks::primitives::StringVc; -use turbopack_core::resolve::parse::RequestVc; +use turbo_tasks::Vc; +use turbopack_core::resolve::parse::Request; /// Creates a IIFE expression that throws a "Cannot find module" error for the /// given request string @@ -15,8 +15,8 @@ pub fn throw_module_not_found_expr(request: &str) -> Expr { } #[turbo_tasks::function] -pub async fn request_to_string(request: RequestVc) -> Result { - Ok(StringVc::cell( +pub async fn request_to_string(request: Vc) -> Result> { + Ok(Vc::cell( request .await? .request() diff --git a/crates/turbopack-ecmascript/src/resolve/mod.rs b/crates/turbopack-ecmascript/src/resolve/mod.rs index f7ec1b62da8439..ce8e788ec4673c 100644 --- a/crates/turbopack-ecmascript/src/resolve/mod.rs +++ b/crates/turbopack-ecmascript/src/resolve/mod.rs @@ -1,10 +1,10 @@ pub mod node_native_binding; use anyhow::Result; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ context::AssetContext, - issue::{IssueSeverity, IssueSeverityVc, IssueSourceVc, OptionIssueSourceVc}, + issue::{IssueSeverity, IssueSource, OptionIssueSource}, reference_type::{ CommonJsReferenceSubType, EcmaScriptModulesReferenceSubType, ReferenceType, UrlReferenceSubType, @@ -13,14 +13,13 @@ use turbopack_core::{ handle_resolve_error, options::{ ConditionValue, ResolutionConditions, ResolveInPackage, ResolveIntoPackage, - ResolveOptions, ResolveOptionsVc, + ResolveOptions, }, - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - resolve, ResolveResultVc, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + resolve, ResolveResult, }, }; - /// Retrieves the [ResolutionConditions] of both the "into" package (allowing a /// package to control how it can be imported) and the "in" package (controlling /// how this package imports others) resolution options, so that they can be @@ -41,7 +40,7 @@ fn get_condition_maps(options: &mut ResolveOptions) -> Vec<&mut ResolutionCondit } #[turbo_tasks::function] -pub async fn apply_esm_specific_options(options: ResolveOptionsVc) -> Result { +pub async fn apply_esm_specific_options(options: Vc) -> Result> { let mut options: ResolveOptions = options.await?.clone_value(); for conditions in get_condition_maps(&mut options) { conditions.insert("import".to_string(), ConditionValue::Set); @@ -51,7 +50,7 @@ pub async fn apply_esm_specific_options(options: ResolveOptionsVc) -> Result Result { +pub async fn apply_cjs_specific_options(options: Vc) -> Result> { let mut options: ResolveOptions = options.await?.clone_value(); for conditions in get_condition_maps(&mut options) { conditions.insert("import".to_string(), ConditionValue::Unset); @@ -62,12 +61,12 @@ pub async fn apply_cjs_specific_options(options: ResolveOptionsVc) -> Result>, + request: Vc, ty: Value, - issue_source: OptionIssueSourceVc, - issue_severity: IssueSeverityVc, -) -> Result { + issue_source: Vc, + issue_severity: Vc, +) -> Result> { let ty = Value::new(ReferenceType::EcmaScriptModules(ty.into_value())); let options = apply_esm_specific_options(origin.resolve_options(ty.clone())); specific_resolve(origin, request, options, ty, issue_source, issue_severity).await @@ -75,11 +74,11 @@ pub async fn esm_resolve( #[turbo_tasks::function] pub async fn cjs_resolve( - origin: ResolveOriginVc, - request: RequestVc, - issue_source: OptionIssueSourceVc, - issue_severity: IssueSeverityVc, -) -> Result { + origin: Vc>, + request: Vc, + issue_source: Vc, + issue_severity: Vc, +) -> Result> { // TODO pass CommonJsReferenceSubType let ty = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)); let options = apply_cjs_specific_options(origin.resolve_options(ty.clone())); @@ -88,12 +87,12 @@ pub async fn cjs_resolve( #[turbo_tasks::function] pub async fn url_resolve( - origin: ResolveOriginVc, - request: RequestVc, + origin: Vc>, + request: Vc, ty: Value, - issue_source: IssueSourceVc, - issue_severity: IssueSeverityVc, -) -> Result { + issue_source: Vc, + issue_severity: Vc, +) -> Result> { let ty = Value::new(ReferenceType::Url(ty.into_value())); let resolve_options = origin.resolve_options(ty.clone()); let rel_request = request.as_relative(); @@ -111,7 +110,7 @@ pub async fn url_resolve( origin.origin_path(), request, resolve_options, - OptionIssueSourceVc::some(issue_source), + OptionIssueSource::some(issue_source), issue_severity, ) .await?; @@ -119,13 +118,13 @@ pub async fn url_resolve( } async fn specific_resolve( - origin: ResolveOriginVc, - request: RequestVc, - options: ResolveOptionsVc, + origin: Vc>, + request: Vc, + options: Vc, reference_type: Value, - issue_source: OptionIssueSourceVc, - issue_severity: IssueSeverityVc, -) -> Result { + issue_source: Vc, + issue_severity: Vc, +) -> Result> { let result = origin.resolve_asset(request, options, reference_type.clone()); handle_resolve_error( @@ -140,7 +139,7 @@ async fn specific_resolve( .await } -pub fn try_to_severity(in_try: bool) -> IssueSeverityVc { +pub fn try_to_severity(in_try: bool) -> Vc { if in_try { IssueSeverity::Warning.cell() } else { diff --git a/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs b/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs index 6c8b0be1fa6c41..fe0ed02c719284 100644 --- a/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs +++ b/crates/turbopack-ecmascript/src/resolve/node_native_binding.rs @@ -3,24 +3,23 @@ use indexmap::IndexSet; use lazy_static::lazy_static; use regex::Regex; use serde::{Deserialize, Serialize}; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; +use turbo_tasks::{ValueToString, Vc}; use turbo_tasks_fs::{ - glob::GlobVc, json::parse_json_rope_with_source_context, DirectoryEntry, FileContent, - FileSystemPathVc, + glob::Glob, json::parse_json_rope_with_source_context, DirectoryEntry, FileContent, + FileSystemPath, }; use turbopack_core::{ - asset::{Asset, AssetContent, AssetVc}, - reference::{AssetReference, AssetReferenceVc}, + asset::{Asset, AssetContent}, + reference::AssetReference, resolve::{ - pattern::{Pattern, PatternVc}, - resolve_raw, AffectingResolvingAssetReferenceVc, PrimaryResolveResult, ResolveResult, - ResolveResultVc, + pattern::Pattern, resolve_raw, AffectingResolvingAssetReference, PrimaryResolveResult, + ResolveResult, }, - source_asset::SourceAssetVc, - target::{CompileTargetVc, Platform}, + source_asset::SourceAsset, + target::{CompileTarget, Platform}, }; -use crate::references::raw::SourceAssetReferenceVc; +use crate::references::raw::SourceAssetReference; #[derive(Serialize, Deserialize, Debug)] struct NodePreGypConfigJson { @@ -37,19 +36,19 @@ struct NodePreGypConfig { #[turbo_tasks::value] #[derive(Hash, Clone, Debug)] pub struct NodePreGypConfigReference { - pub context: FileSystemPathVc, - pub config_file_pattern: PatternVc, - pub compile_target: CompileTargetVc, + pub context: Vc, + pub config_file_pattern: Vc, + pub compile_target: Vc, } #[turbo_tasks::value_impl] -impl NodePreGypConfigReferenceVc { +impl NodePreGypConfigReference { #[turbo_tasks::function] pub fn new( - context: FileSystemPathVc, - config_file_pattern: PatternVc, - compile_target: CompileTargetVc, - ) -> Self { + context: Vc, + config_file_pattern: Vc, + compile_target: Vc, + ) -> Vc { Self::cell(NodePreGypConfigReference { context, config_file_pattern, @@ -61,7 +60,7 @@ impl NodePreGypConfigReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for NodePreGypConfigReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { resolve_node_pre_gyp_files(self.context, self.config_file_pattern, self.compile_target) } } @@ -69,8 +68,8 @@ impl AssetReference for NodePreGypConfigReference { #[turbo_tasks::value_impl] impl ValueToString for NodePreGypConfigReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "node-gyp in {} with {} for {}", self.context.to_string().await?, self.config_file_pattern.to_string().await?, @@ -81,10 +80,10 @@ impl ValueToString for NodePreGypConfigReference { #[turbo_tasks::function] pub async fn resolve_node_pre_gyp_files( - context: FileSystemPathVc, - config_file_pattern: PatternVc, - compile_target: CompileTargetVc, -) -> Result { + context: Vc, + config_file_pattern: Vc, + compile_target: Vc, +) -> Result> { lazy_static! { static ref NAPI_VERSION_TEMPLATE: Regex = Regex::new(r"\{(napi_build_version|node_napi_label)\}") @@ -107,7 +106,7 @@ pub async fn resolve_node_pre_gyp_files( let config_file_dir = config_file_path.parent(); let node_pre_gyp_config: NodePreGypConfigJson = parse_json_rope_with_source_context(config_file.content())?; - let mut assets: IndexSet = IndexSet::new(); + let mut assets: IndexSet>> = IndexSet::new(); for version in node_pre_gyp_config.binary.napi_versions.iter() { let native_binding_path = NAPI_VERSION_TEMPLATE.replace( node_pre_gyp_config.binary.module_path.as_str(), @@ -127,17 +126,14 @@ pub async fn resolve_node_pre_gyp_files( "unknown" }, ); - let resolved_file_vc = config_file_dir.join( - format!( - "{}/{}.node", - native_binding_path, node_pre_gyp_config.binary.module_name - ) - .as_str(), - ); + let resolved_file_vc = config_file_dir.join(format!( + "{}/{}.node", + native_binding_path, node_pre_gyp_config.binary.module_name + )); for (_, entry) in config_file_dir - .join(native_binding_path.as_ref()) + .join(native_binding_path.to_string()) .read_glob( - GlobVc::new(format!("*.{}", compile_target.dylib_ext()).as_str()), + Glob::new(format!("*.{}", compile_target.dylib_ext())), false, ) .await? @@ -146,10 +142,10 @@ pub async fn resolve_node_pre_gyp_files( { if let DirectoryEntry::File(dylib) | DirectoryEntry::Symlink(dylib) = entry { - assets.insert(SourceAssetVc::new(*dylib).into()); + assets.insert(Vc::upcast(SourceAsset::new(*dylib))); } } - assets.insert(SourceAssetVc::new(resolved_file_vc).into()); + assets.insert(Vc::upcast(SourceAsset::new(resolved_file_vc))); } for entry in config_asset .ident() @@ -157,29 +153,31 @@ pub async fn resolve_node_pre_gyp_files( .parent() // TODO // read the dependencies path from `bindings.gyp` - .join("deps/lib") - .read_glob(GlobVc::new("*".to_string().as_str()), false) + .join("deps/lib".to_string()) + .read_glob(Glob::new("*".to_string()), false) .await? .results .values() { match entry { DirectoryEntry::File(dylib) => { - assets.insert(SourceAssetVc::new(*dylib).into()); + assets.insert(Vc::upcast(SourceAsset::new(*dylib))); } DirectoryEntry::Symlink(dylib) => { let realpath_with_links = dylib.realpath_with_links().await?; for symlink in realpath_with_links.symlinks.iter() { - assets.insert(SourceAssetVc::new(*symlink).into()); + assets.insert(Vc::upcast(SourceAsset::new(*symlink))); } - assets.insert(SourceAssetVc::new(*dylib).into()); + assets.insert(Vc::upcast(SourceAsset::new(*dylib))); } _ => {} } } return Ok(ResolveResult::assets_with_references( assets.into_iter().collect(), - vec![AffectingResolvingAssetReferenceVc::new(config_file_path).into()], + vec![Vc::upcast(AffectingResolvingAssetReference::new( + config_file_path, + ))], ) .into()); } @@ -191,14 +189,14 @@ pub async fn resolve_node_pre_gyp_files( #[turbo_tasks::value] #[derive(Hash, Clone, Debug)] pub struct NodeGypBuildReference { - pub context: FileSystemPathVc, - pub compile_target: CompileTargetVc, + pub context: Vc, + pub compile_target: Vc, } #[turbo_tasks::value_impl] -impl NodeGypBuildReferenceVc { +impl NodeGypBuildReference { #[turbo_tasks::function] - pub fn new(context: FileSystemPathVc, target: CompileTargetVc) -> Self { + pub fn new(context: Vc, target: Vc) -> Vc { Self::cell(NodeGypBuildReference { context, compile_target: target, @@ -209,7 +207,7 @@ impl NodeGypBuildReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for NodeGypBuildReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { resolve_node_gyp_build_files(self.context, self.compile_target) } } @@ -217,8 +215,8 @@ impl AssetReference for NodeGypBuildReference { #[turbo_tasks::value_impl] impl ValueToString for NodeGypBuildReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "node-gyp in {} for {}", self.context.to_string().await?, self.compile_target.await? @@ -228,15 +226,15 @@ impl ValueToString for NodeGypBuildReference { #[turbo_tasks::function] pub async fn resolve_node_gyp_build_files( - context: FileSystemPathVc, - compile_target: CompileTargetVc, -) -> Result { + context: Vc, + compile_target: Vc, +) -> Result> { lazy_static! { static ref GYP_BUILD_TARGET_NAME: Regex = Regex::new(r#"['"]target_name['"]\s*:\s*(?:"(.*?)"|'(.*?)')"#) .expect("create napi_build_version regex failed"); } - let binding_gyp_pat = PatternVc::new(Pattern::Constant("binding.gyp".to_owned())); + let binding_gyp_pat = Pattern::new(Pattern::Constant("binding.gyp".to_owned())); let gyp_file = resolve_raw(context, binding_gyp_pat, true).await?; if let [PrimaryResolveResult::Asset(binding_gyp)] = &gyp_file.primary[..] { let mut merged_references = gyp_file.references.clone(); @@ -245,13 +243,14 @@ pub async fn resolve_node_gyp_build_files( if let Some(captured) = GYP_BUILD_TARGET_NAME.captures(&config_file.content().to_str()?) { - let mut resolved: IndexSet = IndexSet::with_capacity(captured.len()); + let mut resolved: IndexSet>> = + IndexSet::with_capacity(captured.len()); for found in captured.iter().skip(1).flatten() { let name = found.as_str(); - let target_path = context.join("build").join("Release"); + let target_path = context.join("build/Release".to_string()); let resolved_prebuilt_file = resolve_raw( target_path, - PatternVc::new(Pattern::Constant(format!("{}.node", name))), + Pattern::new(Pattern::Constant(format!("{}.node", name))), true, ) .await?; @@ -292,14 +291,14 @@ pub async fn resolve_node_gyp_build_files( #[turbo_tasks::value] #[derive(Hash, Clone, Debug)] pub struct NodeBindingsReference { - pub context: FileSystemPathVc, + pub context: Vc, pub file_name: String, } #[turbo_tasks::value_impl] -impl NodeBindingsReferenceVc { +impl NodeBindingsReference { #[turbo_tasks::function] - pub fn new(context: FileSystemPathVc, file_name: String) -> Self { + pub fn new(context: Vc, file_name: String) -> Vc { Self::cell(NodeBindingsReference { context, file_name }) } } @@ -307,7 +306,7 @@ impl NodeBindingsReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for NodeBindingsReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { resolve_node_bindings_files(self.context, self.file_name.clone()) } } @@ -315,8 +314,8 @@ impl AssetReference for NodeBindingsReference { #[turbo_tasks::value_impl] impl ValueToString for NodeBindingsReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "bindings in {}", self.context.to_string().await?, ))) @@ -325,9 +324,9 @@ impl ValueToString for NodeBindingsReference { #[turbo_tasks::function] pub async fn resolve_node_bindings_files( - context: FileSystemPathVc, + context: Vc, file_name: String, -) -> Result { +) -> Result> { lazy_static! { static ref BINDINGS_TRY: [&'static str; 5] = [ "build/bindings", @@ -361,20 +360,21 @@ pub async fn resolve_node_bindings_files( } root_context = parent; } - let bindings_try: Vec = BINDINGS_TRY + let bindings_try: Vec>> = BINDINGS_TRY .iter() .map(|try_dir| { - SourceAssetVc::new(root_context.join(&format!("{}/{}", try_dir, &file_name))).into() + Vc::upcast(SourceAsset::new( + root_context.join(format!("{}/{}", try_dir, &file_name)), + )) }) .collect(); Ok(ResolveResult::assets_with_references( bindings_try, - vec![SourceAssetReferenceVc::new( - SourceAssetVc::new(root_context).into(), + vec![Vc::upcast(SourceAssetReference::new( + Vc::upcast(SourceAsset::new(root_context)), Pattern::Concatenation(vec![Pattern::Dynamic, Pattern::Constant(file_name)]).into(), - ) - .into()], + ))], ) .into()) } diff --git a/crates/turbopack-ecmascript/src/static_code.rs b/crates/turbopack-ecmascript/src/static_code.rs index 163d015c5de96a..6a5b83e829b23e 100644 --- a/crates/turbopack-ecmascript/src/static_code.rs +++ b/crates/turbopack-ecmascript/src/static_code.rs @@ -1,14 +1,14 @@ use anyhow::{bail, Result}; -use turbo_tasks::Value; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - code_builder::{CodeBuilder, CodeVc}, - context::{AssetContext, AssetContextVc}, + code_builder::{Code, CodeBuilder}, + context::AssetContext, reference_type::ReferenceType, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; -use crate::EcmascriptModuleAssetVc; +use crate::EcmascriptModuleAsset; /// Static ECMAScript file code, to be used as part of some code. /// @@ -16,20 +16,23 @@ use crate::EcmascriptModuleAssetVc; /// the final runtime code, while keeping source map information. #[turbo_tasks::value] pub struct StaticEcmascriptCode { - asset_context: AssetContextVc, - asset: EcmascriptModuleAssetVc, + asset_context: Vc>, + asset: Vc, } #[turbo_tasks::value_impl] -impl StaticEcmascriptCodeVc { - /// Creates a new [`StaticEcmascriptCodeVc`]. +impl StaticEcmascriptCode { + /// Creates a new [`Vc`]. #[turbo_tasks::function] - pub async fn new(asset_context: AssetContextVc, asset_path: FileSystemPathVc) -> Result { + pub async fn new( + asset_context: Vc>, + asset_path: Vc, + ) -> Result> { let asset = asset_context.process( - SourceAssetVc::new(asset_path).into(), + Vc::upcast(SourceAsset::new(asset_path)), Value::new(ReferenceType::Undefined), ); - let Some(asset) = EcmascriptModuleAssetVc::resolve_from(&asset).await? else { + let Some(asset) = Vc::try_resolve_downcast_type::(asset).await? else { bail!("asset is not an Ecmascript module") }; Ok(Self::cell(StaticEcmascriptCode { @@ -41,14 +44,14 @@ impl StaticEcmascriptCodeVc { /// Computes the contents of the asset and pushes it to /// the code builder, including the source map if available. #[turbo_tasks::function] - pub async fn code(self) -> Result { + pub async fn code(self: Vc) -> Result> { let this = self.await?; let runtime_base_content = this.asset.module_content_without_analysis().await?; let mut code = CodeBuilder::default(); code.push_source( &runtime_base_content.inner_code, - runtime_base_content.source_map.map(|map| map.into()), + runtime_base_content.source_map.map(Vc::upcast), ); - Ok(CodeVc::cell(code.build())) + Ok(Code::cell(code.build())) } } diff --git a/crates/turbopack-ecmascript/src/text/mod.rs b/crates/turbopack-ecmascript/src/text/mod.rs index 843d7b5da7b350..406adb63fd20ec 100644 --- a/crates/turbopack-ecmascript/src/text/mod.rs +++ b/crates/turbopack-ecmascript/src/text/mod.rs @@ -1,29 +1,29 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; +use turbo_tasks::Vc; use turbo_tasks_fs::FileContent; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, }; use crate::utils::StringifyJs; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("text content".to_string()) +fn modifier() -> Vc { + Vc::cell("text content".to_string()) } /// A source asset that exports the string content of an asset as the default /// export of a JS module. #[turbo_tasks::value] pub struct TextContentSourceAsset { - pub source: AssetVc, + pub source: Vc>, } #[turbo_tasks::value_impl] -impl TextContentSourceAssetVc { +impl TextContentSourceAsset { #[turbo_tasks::function] - pub fn new(source: AssetVc) -> Self { + pub fn new(source: Vc>) -> Vc { TextContentSourceAsset { source }.cell() } } @@ -31,22 +31,22 @@ impl TextContentSourceAssetVc { #[turbo_tasks::value_impl] impl Asset for TextContentSourceAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source .ident() .with_modifier(modifier()) - .rename_as("*.mjs") + .rename_as("*.mjs".to_string()) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let source = self.source.content().file_content(); let FileContent::Content(content) = &*source.await? else { - return Ok(FileContent::NotFound.cell().into()); + return Ok(AssetContent::file(FileContent::NotFound.cell())); }; let text = content.content().to_str()?; let code = format!("export default {};", StringifyJs(&text)); let content = FileContent::Content(code.into()).cell(); - Ok(content.into()) + Ok(AssetContent::file(content)) } } diff --git a/crates/turbopack-ecmascript/src/transform/mod.rs b/crates/turbopack-ecmascript/src/transform/mod.rs index 0713a7d066cb94..4b57d233fab2cd 100644 --- a/crates/turbopack-ecmascript/src/transform/mod.rs +++ b/crates/turbopack-ecmascript/src/transform/mod.rs @@ -7,7 +7,9 @@ use swc_core::{ common::{chain, comments::Comments, util::take::Take, Mark, SourceMap}, ecma::{ ast::{Module, ModuleItem, Program, Script}, - preset_env::{self, Targets}, + preset_env::{ + Targets, {self}, + }, transforms::{ base::{feature::FeatureFlag, helpers::inject_helpers, Assumptions}, react::react, @@ -15,28 +17,28 @@ use swc_core::{ visit::{FoldWith, VisitMutWith}, }, }; -use turbo_tasks::primitives::{OptionStringVc, StringVc}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ValueDefault, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - environment::EnvironmentVc, - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, + environment::Environment, + issue::{Issue, IssueSeverity}, }; #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(Debug, Clone, PartialOrd, Ord, Hash)] pub enum EcmascriptInputTransform { CommonJs, - Plugin(TransformPluginVc), - PresetEnv(EnvironmentVc), + Plugin(Vc), + PresetEnv(Vc), React { #[serde(default)] development: bool, #[serde(default)] refresh: bool, // swc.jsc.transform.react.importSource - import_source: OptionStringVc, + import_source: Vc>, // swc.jsc.transform.react.runtime, - runtime: OptionStringVc, + runtime: Vc>, }, // These options are subset of swc_core::ecma::transforms::typescript::Config, but // it doesn't derive `Copy` so repeating values in here @@ -76,11 +78,13 @@ pub trait CustomTransformer: Debug { pub struct TransformPlugin(#[turbo_tasks(trace_ignore)] Box); #[turbo_tasks::value(transparent)] -pub struct OptionTransformPlugin(Option); +pub struct OptionTransformPlugin(Option>); -impl Default for OptionTransformPluginVc { - fn default() -> Self { - OptionTransformPluginVc::cell(None) +#[turbo_tasks::value_impl] +impl ValueDefault for OptionTransformPlugin { + #[turbo_tasks::function] + fn value_default() -> Vc { + Vc::cell(None) } } @@ -96,17 +100,17 @@ impl CustomTransformer for TransformPlugin { pub struct EcmascriptInputTransforms(Vec); #[turbo_tasks::value_impl] -impl EcmascriptInputTransformsVc { +impl EcmascriptInputTransforms { #[turbo_tasks::function] - pub fn empty() -> Self { - EcmascriptInputTransformsVc::cell(Vec::new()) + pub fn empty() -> Vc { + Vc::cell(Vec::new()) } #[turbo_tasks::function] - pub async fn extend(self, other: EcmascriptInputTransformsVc) -> Result { + pub async fn extend(self: Vc, other: Vc) -> Result> { let mut transforms = self.await?.clone_value(); transforms.extend(other.await?.clone_value()); - Ok(EcmascriptInputTransformsVc::cell(transforms)) + Ok(Vc::cell(transforms)) } } @@ -118,7 +122,7 @@ pub struct TransformContext<'a> { pub file_path_str: &'a str, pub file_name_str: &'a str, pub file_name_hash: u128, - pub file_path: FileSystemPathVc, + pub file_path: Vc, } impl EcmascriptInputTransform { @@ -284,33 +288,33 @@ pub fn remove_shebang(program: &mut Program) { #[turbo_tasks::value(shared)] pub struct UnsupportedServerActionIssue { - pub context: FileSystemPathVc, + pub context: Vc, } #[turbo_tasks::value_impl] impl Issue for UnsupportedServerActionIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Error.into() } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("unsupported".to_string()) + fn category(&self) -> Vc { + Vc::cell("unsupported".to_string()) } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Server actions (\"use server\") are not yet supported in Turbopack".into()) + fn title(&self) -> Vc { + Vc::cell("Server actions (\"use server\") are not yet supported in Turbopack".into()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - async fn description(&self) -> Result { - Ok(StringVc::cell("".to_string())) + async fn description(&self) -> Result> { + Ok(Vc::cell("".to_string())) } } diff --git a/crates/turbopack-ecmascript/src/tree_shake/asset.rs b/crates/turbopack-ecmascript/src/tree_shake/asset.rs index ee31970d6bf29c..d0055b63397547 100644 --- a/crates/turbopack-ecmascript/src/tree_shake/asset.rs +++ b/crates/turbopack-ecmascript/src/tree_shake/asset.rs @@ -1,24 +1,21 @@ use anyhow::{bail, Context, Result}; -use turbo_tasks::{primitives::StringVc, Value}; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - chunk::{ - availability_info::AvailabilityInfo, ChunkVc, ChunkableAsset, ChunkableAssetVc, - ChunkingContextVc, - }, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, - resolve::ModulePartVc, + asset::{Asset, AssetContent}, + chunk::{availability_info::AvailabilityInfo, Chunk, ChunkableAsset, ChunkingContext}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, + resolve::ModulePart, }; use super::{chunk_item::EcmascriptModulePartChunkItem, get_part_id, split_module, SplitResult}; use crate::{ chunk::{ - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, - EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkPlaceable, EcmascriptChunkingContext, + EcmascriptExports, }, references::analyze_ecmascript_module, - AnalyzeEcmascriptModuleResultVc, EcmascriptModuleAssetVc, + AnalyzeEcmascriptModuleResult, EcmascriptModuleAsset, }; /// A reference to part of an ES module. @@ -26,17 +23,17 @@ use crate::{ /// This type is used for an advanced tree shkaing. #[turbo_tasks::value] pub struct EcmascriptModulePartAsset { - pub(crate) full_module: EcmascriptModuleAssetVc, - pub(crate) part: ModulePartVc, + pub(crate) full_module: Vc, + pub(crate) part: Vc, } #[turbo_tasks::value_impl] -impl EcmascriptModulePartAssetVc { - /// Create a new instance of [EcmascriptModulePartAssetVc], whcih consists +impl EcmascriptModulePartAsset { + /// Create a new instance of [Vc], whcih consists /// of a pointer to the full module and the [ModulePart] pointing the part /// of the module. #[turbo_tasks::function] - pub fn new(module: EcmascriptModuleAssetVc, part: ModulePartVc) -> Self { + pub fn new(module: Vc, part: Vc) -> Vc { EcmascriptModulePartAsset { full_module: module, part, @@ -48,14 +45,14 @@ impl EcmascriptModulePartAssetVc { #[turbo_tasks::value_impl] impl Asset for EcmascriptModulePartAsset { #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { // This is not reachable because EcmascriptModulePartAsset implements // ChunkableAsset and ChunkableAsset::as_chunk is called instead. todo!("EcmascriptModulePartAsset::content is not implemented") } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { let split_data = split_module(self.full_module).await?; let deps = match &*split_data { @@ -77,15 +74,13 @@ impl Asset for EcmascriptModulePartAsset { let mut assets = deps .iter() .map(|&part_id| { - Ok(SingleAssetReferenceVc::new( - EcmascriptModulePartAssetVc::new( + Ok(Vc::upcast(SingleAssetReference::new( + Vc::upcast(EcmascriptModulePartAsset::new( self.full_module, - ModulePartVc::internal(part_id), - ) - .as_asset(), - StringVc::cell("ecmascript module part".to_string()), - ) - .as_asset_reference()) + ModulePart::internal(part_id), + )), + Vc::cell("ecmascript module part".to_string()), + ))) }) .collect::>>()?; @@ -96,11 +91,11 @@ impl Asset for EcmascriptModulePartAsset { assets.extend(external.iter().cloned()); - Ok(AssetReferencesVc::cell(assets)) + Ok(Vc::cell(assets)) } #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { let inner = self.full_module.ident(); Ok(inner.with_part(self.part)) @@ -111,20 +106,21 @@ impl Asset for EcmascriptModulePartAsset { impl EcmascriptChunkPlaceable for EcmascriptModulePartAsset { #[turbo_tasks::function] async fn as_chunk_item( - self_vc: EcmascriptModulePartAssetVc, - context: EcmascriptChunkingContextVc, - ) -> Result { - Ok(EcmascriptModulePartChunkItem { - module: self_vc, - context, - } - .cell() - .into()) + self: Vc, + context: Vc>, + ) -> Result>> { + Ok(Vc::upcast( + EcmascriptModulePartChunkItem { + module: self, + context, + } + .cell(), + )) } #[turbo_tasks::function] - async fn get_exports(self_vc: EcmascriptModuleAssetVc) -> Result { - Ok(self_vc.analyze().await?.exports) + async fn get_exports(self: Vc) -> Result> { + Ok(self.analyze().await?.exports) } } @@ -132,23 +128,22 @@ impl EcmascriptChunkPlaceable for EcmascriptModulePartAsset { impl ChunkableAsset for EcmascriptModulePartAsset { #[turbo_tasks::function] async fn as_chunk( - self_vc: EcmascriptModulePartAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } #[turbo_tasks::value_impl] -impl EcmascriptModulePartAssetVc { +impl EcmascriptModulePartAsset { #[turbo_tasks::function] - pub(super) async fn analyze(self) -> Result { + pub(super) async fn analyze(self: Vc) -> Result> { let this = self.await?; Ok(analyze(this.full_module, this.part)) @@ -157,14 +152,14 @@ impl EcmascriptModulePartAssetVc { #[turbo_tasks::function] async fn analyze( - full_module: EcmascriptModuleAssetVc, - part: ModulePartVc, -) -> Result { + full_module: Vc, + part: Vc, +) -> Result> { let module = full_module.await?; Ok(analyze_ecmascript_module( module.source, - full_module.as_resolve_origin(), + Vc::upcast(full_module), Value::new(module.ty), module.transforms, Value::new(module.options), diff --git a/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs b/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs index 94b4c8bcbbde4c..af8b5080999b12 100644 --- a/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs +++ b/crates/turbopack-ecmascript/src/tree_shake/chunk_item.rs @@ -1,43 +1,41 @@ use anyhow::Result; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ asset::Asset, - chunk::{availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc}, - ident::AssetIdentVc, - reference::AssetReferencesVc, + chunk::{availability_info::AvailabilityInfo, ChunkItem}, + ident::AssetIdent, + reference::AssetReferences, }; -use super::{asset::EcmascriptModulePartAssetVc, part_of_module, split_module}; +use super::{asset::EcmascriptModulePartAsset, part_of_module, split_module}; use crate::{ - chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, - EcmascriptChunkingContextVc, - }, - EcmascriptModuleContentVc, + chunk::{EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkingContext}, + EcmascriptModuleContent, }; -/// This is an implementation of [ChunkItem] for [EcmascriptModulePartAssetVc]. +/// This is an implementation of [ChunkItem] for +/// [Vc]. /// /// This is a pointer to a part of an ES module. #[turbo_tasks::value(shared)] pub struct EcmascriptModulePartChunkItem { - pub(super) module: EcmascriptModulePartAssetVc, - pub(super) context: EcmascriptChunkingContextVc, + pub(super) module: Vc, + pub(super) context: Vc>, } #[turbo_tasks::value_impl] impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { #[turbo_tasks::function] - fn content(self_vc: EcmascriptModulePartChunkItemVc) -> EcmascriptChunkItemContentVc { - self_vc.content_with_availability_info(Value::new(AvailabilityInfo::Untracked)) + fn content(self: Vc) -> Vc { + self.content_with_availability_info(Value::new(AvailabilityInfo::Untracked)) } #[turbo_tasks::function] async fn content_with_availability_info( - self_vc: EcmascriptModulePartChunkItemVc, + self: Vc, availability_info: Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result> { + let this = self.await?; let availability_info = if *this.module.analyze().needs_availability_info().await? { availability_info } else { @@ -48,7 +46,7 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { let split_data = split_module(module.full_module); let parsed = part_of_module(split_data, module.part); - let content = EcmascriptModuleContentVc::new( + let content = EcmascriptModuleContent::new( parsed, module.full_module.ident(), this.context, @@ -56,11 +54,11 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { availability_info, ); - Ok(EcmascriptChunkItemContentVc::new(content, this.context)) + Ok(EcmascriptChunkItemContent::new(content, this.context)) } #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } } @@ -68,12 +66,12 @@ impl EcmascriptChunkItem for EcmascriptModulePartChunkItem { #[turbo_tasks::value_impl] impl ChunkItem for EcmascriptModulePartChunkItem { #[turbo_tasks::function] - async fn references(&self) -> AssetReferencesVc { + async fn references(&self) -> Vc { self.module.references() } #[turbo_tasks::function] - async fn asset_ident(&self) -> Result { + async fn asset_ident(&self) -> Result> { Ok(self.module.ident()) } } diff --git a/crates/turbopack-ecmascript/src/tree_shake/mod.rs b/crates/turbopack-ecmascript/src/tree_shake/mod.rs index ee79fe45b021d9..8d43b2e03cdd27 100644 --- a/crates/turbopack-ecmascript/src/tree_shake/mod.rs +++ b/crates/turbopack-ecmascript/src/tree_shake/mod.rs @@ -2,15 +2,12 @@ use anyhow::{bail, Result}; use indexmap::IndexSet; use rustc_hash::FxHashMap; use swc_core::ecma::ast::{Id, Module, Program}; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::resolve::{origin::ResolveOrigin, ModulePart, ModulePartVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::resolve::{origin::ResolveOrigin, ModulePart}; use self::graph::{DepGraph, ItemData, ItemId, ItemIdGroupKind, Mode, SplitModuleResult}; -use crate::{ - analyzer::graph::EvalContext, - parse::{ParseResult, ParseResultVc}, - EcmascriptModuleAssetVc, -}; +use crate::{analyzer::graph::EvalContext, parse::ParseResult, EcmascriptModuleAsset}; pub mod asset; pub mod chunk_item; @@ -246,8 +243,8 @@ pub(crate) enum Key { Export(String), } -/// Converts [ModulePartVc] to the index. -async fn get_part_id(result: &SplitResult, part: ModulePartVc) -> Result { +/// Converts [Vc] to the index. +async fn get_part_id(result: &SplitResult, part: Vc) -> Result { let part = part.await?; let key = match &*part { @@ -279,7 +276,7 @@ pub(crate) enum SplitResult { entrypoints: FxHashMap, #[turbo_tasks(debug_ignore, trace_ignore)] - modules: Vec, + modules: Vec>, #[turbo_tasks(debug_ignore, trace_ignore)] deps: FxHashMap>, @@ -298,12 +295,15 @@ impl PartialEq for SplitResult { } #[turbo_tasks::function] -pub(super) fn split_module(asset: EcmascriptModuleAssetVc) -> SplitResultVc { +pub(super) fn split_module(asset: Vc) -> Vc { split(asset.origin_path(), asset.parse()) } #[turbo_tasks::function] -pub(super) async fn split(path: FileSystemPathVc, parsed: ParseResultVc) -> Result { +pub(super) async fn split( + path: Vc, + parsed: Vc, +) -> Result> { let filename = path.await?.file_name().to_string(); let parse_result = parsed.await?; @@ -332,7 +332,7 @@ pub(super) async fn split(path: FileSystemPathVc, parsed: ParseResultVc) -> Resu let program = Program::Module(module); let eval_context = EvalContext::new(&program, eval_context.unresolved_mark); - ParseResultVc::cell(ParseResult::Ok { + ParseResult::cell(ParseResult::Ok { program, globals: globals.clone(), comments: comments.clone(), @@ -356,9 +356,9 @@ pub(super) async fn split(path: FileSystemPathVc, parsed: ParseResultVc) -> Resu #[turbo_tasks::function] pub(super) async fn part_of_module( - split_data: SplitResultVc, - part: ModulePartVc, -) -> Result { + split_data: Vc, + part: Vc, +) -> Result> { let split_data = split_data.await?; match &*split_data { diff --git a/crates/turbopack-ecmascript/src/tree_shake/tests.rs b/crates/turbopack-ecmascript/src/tree_shake/tests.rs index 3b6c65275dce19..0bb2b93ac9d48e 100644 --- a/crates/turbopack-ecmascript/src/tree_shake/tests.rs +++ b/crates/turbopack-ecmascript/src/tree_shake/tests.rs @@ -17,7 +17,9 @@ use swc_core::{ codegen::text_writer::JsWriter, parser::parse_file_as_module, }, - testing::{self, fixture, NormalizedOutput}, + testing::{ + fixture, NormalizedOutput, {self}, + }, }; use super::{ diff --git a/crates/turbopack-ecmascript/src/typescript/mod.rs b/crates/turbopack-ecmascript/src/typescript/mod.rs index 0c63140342346c..eecabce5df4a7d 100644 --- a/crates/turbopack-ecmascript/src/typescript/mod.rs +++ b/crates/turbopack-ecmascript/src/typescript/mod.rs @@ -1,19 +1,20 @@ -use turbo_tasks::{ValueToString, ValueToStringVc}; pub mod resolve; use anyhow::Result; use serde_json::Value as JsonValue; -use turbo_tasks::{primitives::StringVc, Value}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbo_tasks_fs::DirectoryContent; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, - issue::{IssueSeverity, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, + asset::{Asset, AssetContent}, + ident::AssetIdent, + issue::{IssueSeverity, OptionIssueSource}, + reference::{AssetReference, AssetReferences}, reference_type::{CommonJsReferenceSubType, ReferenceType}, resolve::{ - origin::ResolveOriginVc, parse::RequestVc, pattern::QueryMapVc, ResolveResult, - ResolveResultVc, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + pattern::QueryMap, + ResolveResult, }, }; @@ -23,14 +24,14 @@ use crate::resolve::apply_cjs_specific_options; #[turbo_tasks::value] pub struct TsConfigModuleAsset { - pub source: AssetVc, - pub origin: ResolveOriginVc, + pub source: Vc>, + pub origin: Vc>, } #[turbo_tasks::value_impl] -impl TsConfigModuleAssetVc { +impl TsConfigModuleAsset { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, source: AssetVc) -> Self { + pub fn new(origin: Vc>, source: Vc>) -> Vc { Self::cell(TsConfigModuleAsset { origin, source }) } } @@ -38,17 +39,17 @@ impl TsConfigModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for TsConfigModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident() } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { let mut references = Vec::new(); let configs = read_tsconfigs( self.source.content().file_content(), @@ -59,7 +60,7 @@ impl Asset for TsConfigModuleAsset { ) .await?; for (_, config_asset) in configs[1..].iter() { - references.push(TsExtendsReferenceVc::new(*config_asset).into()); + references.push(Vc::upcast(TsExtendsReference::new(*config_asset))); } // ts-node options { @@ -70,13 +71,10 @@ impl Asset for TsConfigModuleAsset { }) .await?; let (_, compiler) = compiler.unwrap_or_else(|| (self.source, "typescript".to_string())); - references.push( - CompilerReferenceVc::new( - self.origin, - RequestVc::parse(Value::new(compiler.to_string().into())), - ) - .into(), - ); + references.push(Vc::upcast(CompilerReference::new( + self.origin, + Request::parse(Value::new(compiler.to_string().into())), + ))); let require = read_from_tsconfigs(&configs, |json, source| { if let JsonValue::Array(array) = &json["ts-node"]["require"] { Some( @@ -92,13 +90,10 @@ impl Asset for TsConfigModuleAsset { .await?; if let Some(require) = require { for (_, request) in require { - references.push( - TsNodeRequireReferenceVc::new( - self.origin, - RequestVc::parse(Value::new(request.into())), - ) - .into(), - ); + references.push(Vc::upcast(TsNodeRequireReference::new( + self.origin, + Request::parse(Value::new(request.into())), + ))); } } } @@ -123,8 +118,10 @@ impl Asset for TsConfigModuleAsset { let mut all_types = Vec::new(); let mut current = self.source.ident().path().parent().resolve().await?; loop { - if let DirectoryContent::Entries(entries) = - &*current.join("node_modules/@types").read_dir().await? + if let DirectoryContent::Entries(entries) = &*current + .join("node_modules/@types".to_string()) + .read_dir() + .await? { all_types.extend(entries.iter().filter_map(|(name, _)| { if name.starts_with('.') { @@ -143,34 +140,27 @@ impl Asset for TsConfigModuleAsset { all_types }; for (_, name) in types { - references.push( - TsConfigTypesReferenceVc::new( - self.origin, - RequestVc::module( - name, - Value::new("".to_string().into()), - QueryMapVc::none(), - ), - ) - .into(), - ); + references.push(Vc::upcast(TsConfigTypesReference::new( + self.origin, + Request::module(name, Value::new("".to_string().into()), QueryMap::none()), + ))); } } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct CompilerReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, + pub origin: Vc>, + pub request: Vc, } #[turbo_tasks::value_impl] -impl CompilerReferenceVc { +impl CompilerReference { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, request: RequestVc) -> Self { + pub fn new(origin: Vc>, request: Vc) -> Vc { Self::cell(CompilerReference { origin, request }) } } @@ -178,11 +168,11 @@ impl CompilerReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for CompilerReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::none(), + OptionIssueSource::none(), IssueSeverity::Error.cell(), ) } @@ -191,8 +181,8 @@ impl AssetReference for CompilerReference { #[turbo_tasks::value_impl] impl ValueToString for CompilerReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "compiler reference {}", self.request.to_string().await? ))) @@ -202,13 +192,13 @@ impl ValueToString for CompilerReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct TsExtendsReference { - pub config: AssetVc, + pub config: Vc>, } #[turbo_tasks::value_impl] -impl TsExtendsReferenceVc { +impl TsExtendsReference { #[turbo_tasks::function] - pub fn new(config: AssetVc) -> Self { + pub fn new(config: Vc>) -> Vc { Self::cell(TsExtendsReference { config }) } } @@ -216,7 +206,7 @@ impl TsExtendsReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for TsExtendsReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { ResolveResult::asset(self.config).into() } } @@ -224,8 +214,8 @@ impl AssetReference for TsExtendsReference { #[turbo_tasks::value_impl] impl ValueToString for TsExtendsReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "tsconfig extends {}", self.config.ident().to_string().await?, ))) @@ -235,14 +225,14 @@ impl ValueToString for TsExtendsReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct TsNodeRequireReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, + pub origin: Vc>, + pub request: Vc, } #[turbo_tasks::value_impl] -impl TsNodeRequireReferenceVc { +impl TsNodeRequireReference { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, request: RequestVc) -> Self { + pub fn new(origin: Vc>, request: Vc) -> Vc { Self::cell(TsNodeRequireReference { origin, request }) } } @@ -250,11 +240,11 @@ impl TsNodeRequireReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for TsNodeRequireReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { cjs_resolve( self.origin, self.request, - OptionIssueSourceVc::none(), + OptionIssueSource::none(), IssueSeverity::Error.cell(), ) } @@ -263,8 +253,8 @@ impl AssetReference for TsNodeRequireReference { #[turbo_tasks::value_impl] impl ValueToString for TsNodeRequireReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "tsconfig tsnode require {}", self.request.to_string().await? ))) @@ -274,14 +264,14 @@ impl ValueToString for TsNodeRequireReference { #[turbo_tasks::value] #[derive(Hash, Debug)] pub struct TsConfigTypesReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, + pub origin: Vc>, + pub request: Vc, } #[turbo_tasks::value_impl] -impl TsConfigTypesReferenceVc { +impl TsConfigTypesReference { #[turbo_tasks::function] - pub fn new(origin: ResolveOriginVc, request: RequestVc) -> Self { + pub fn new(origin: Vc>, request: Vc) -> Vc { Self::cell(TsConfigTypesReference { origin, request }) } } @@ -289,7 +279,7 @@ impl TsConfigTypesReferenceVc { #[turbo_tasks::value_impl] impl AssetReference for TsConfigTypesReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { type_resolve(self.origin, self.request) } } @@ -297,8 +287,8 @@ impl AssetReference for TsConfigTypesReference { #[turbo_tasks::value_impl] impl ValueToString for TsConfigTypesReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "tsconfig types {}", self.request.to_string().await?, ))) diff --git a/crates/turbopack-ecmascript/src/typescript/resolve.rs b/crates/turbopack-ecmascript/src/typescript/resolve.rs index d3ded5e65ace88..298ae86a268647 100644 --- a/crates/turbopack-ecmascript/src/typescript/resolve.rs +++ b/crates/turbopack-ecmascript/src/typescript/resolve.rs @@ -2,54 +2,48 @@ use std::{collections::HashMap, fmt::Write}; use anyhow::Result; use serde_json::Value as JsonValue; -use turbo_tasks::{ - primitives::{StringVc, StringsVc}, - Value, ValueToString, ValueToStringVc, -}; -use turbo_tasks_fs::{ - FileContent, FileContentVc, FileJsonContent, FileJsonContentVc, FileSystemPathVc, -}; +use turbo_tasks::{Value, ValueDefault, ValueToString, Vc}; +use turbo_tasks_fs::{FileContent, FileJsonContent, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetOptionVc, AssetVc}, + asset::{Asset, AssetOption}, context::AssetContext, - ident::AssetIdentVc, - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc, OptionIssueSourceVc}, - reference::{AssetReference, AssetReferenceVc}, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity, OptionIssueSource}, + reference::AssetReference, reference_type::{ReferenceType, TypeScriptReferenceSubType}, resolve::{ handle_resolve_error, node::node_cjs_resolve_options, options::{ - ConditionValue, ImportMap, ImportMapVc, ImportMapping, ResolveInPackage, - ResolveIntoPackage, ResolveModules, ResolveOptionsVc, + ConditionValue, ImportMap, ImportMapping, ResolveInPackage, ResolveIntoPackage, + ResolveModules, ResolveOptions, }, - origin::{ResolveOrigin, ResolveOriginVc}, - parse::{Request, RequestVc}, - pattern::{Pattern, QueryMapVc}, - resolve, AliasPattern, ResolveResultVc, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + pattern::{Pattern, QueryMap}, + resolve, AliasPattern, ResolveResult, }, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; - #[turbo_tasks::value(shared)] pub struct TsConfigIssue { - pub severity: IssueSeverityVc, - pub source_ident: AssetIdentVc, - pub message: StringVc, + pub severity: Vc, + pub source_ident: Vc, + pub message: Vc, } #[turbo_tasks::function] -async fn json_only(resolve_options: ResolveOptionsVc) -> Result { +async fn json_only(resolve_options: Vc) -> Result> { let mut opts = resolve_options.await?.clone_value(); opts.extensions = vec![".json".to_string()]; Ok(opts.cell()) } pub async fn read_tsconfigs( - mut data: FileContentVc, - mut tsconfig: AssetVc, - resolve_options: ResolveOptionsVc, -) -> Result> { + mut data: Vc, + mut tsconfig: Vc>, + resolve_options: Vc, +) -> Result, Vc>)>> { let mut configs = Vec::new(); let resolve_options = json_only(resolve_options); loop { @@ -66,20 +60,18 @@ pub async fn read_tsconfigs( TsConfigIssue { severity: IssueSeverity::Error.into(), source_ident: tsconfig.ident(), - message: StringVc::cell(message), + message: Vc::cell(message), } .cell() - .as_issue() .emit(); } FileJsonContent::NotFound => { TsConfigIssue { severity: IssueSeverity::Error.into(), source_ident: tsconfig.ident(), - message: StringVc::cell("tsconfig not found".into()), + message: Vc::cell("tsconfig not found".into()), } .cell() - .as_issue() .emit(); } FileJsonContent::Content(json) => { @@ -94,12 +86,9 @@ pub async fn read_tsconfigs( TsConfigIssue { severity: IssueSeverity::Error.into(), source_ident: tsconfig.ident(), - message: StringVc::cell( - "extends doesn't resolve correctly".to_string(), - ), + message: Vc::cell("extends doesn't resolve correctly".to_string()), } .cell() - .as_issue() .emit(); } } @@ -113,12 +102,12 @@ pub async fn read_tsconfigs( /// Resolves tsconfig files according to TS's implementation: /// https://github.com/microsoft/TypeScript/blob/611a912d/src/compiler/commandLineParser.ts#L3294-L3326 async fn resolve_extends( - tsconfig: AssetVc, + tsconfig: Vc>, extends: &str, - resolve_options: ResolveOptionsVc, -) -> Result { + resolve_options: Vc, +) -> Result> { let context = tsconfig.ident().path().parent(); - let request = RequestVc::parse_string(extends.to_string()); + let request = Request::parse_string(extends.to_string()); // TS's resolution is weird, and has special behavior for different import // types. There might be multiple alternatives like @@ -144,7 +133,7 @@ async fn resolve_extends( // An empty extends is treated as "./tsconfig" Request::Empty => { - let request = RequestVc::parse_string("./tsconfig".to_string()); + let request = Request::parse_string("./tsconfig".to_string()); Ok(resolve(context, request, resolve_options).first_asset()) } @@ -153,7 +142,7 @@ async fn resolve_extends( _ => { let mut result = resolve(context, request, resolve_options).first_asset(); if result.await?.is_none() { - let request = RequestVc::parse_string(format!("{extends}/tsconfig")); + let request = Request::parse_string(format!("{extends}/tsconfig")); result = resolve(context, request, resolve_options).first_asset(); } Ok(result) @@ -162,26 +151,28 @@ async fn resolve_extends( } async fn resolve_extends_rooted_or_relative( - context: FileSystemPathVc, - request: RequestVc, - resolve_options: ResolveOptionsVc, + context: Vc, + request: Vc, + resolve_options: Vc, path: &str, -) -> Result { +) -> Result> { let mut result = resolve(context, request, resolve_options).first_asset(); // If the file doesn't end with ".json" and we can't find the file, then we have // to try again with it. // https://github.com/microsoft/TypeScript/blob/611a912d/src/compiler/commandLineParser.ts#L3305 if !path.ends_with(".json") && result.await?.is_none() { - let request = RequestVc::parse_string(format!("{path}.json")); + let request = Request::parse_string(format!("{path}.json")); result = resolve(context, request, resolve_options).first_asset(); } Ok(result) } +type Config = (Vc, Vc>); + pub async fn read_from_tsconfigs( - configs: &[(FileJsonContentVc, AssetVc)], - accessor: impl Fn(&JsonValue, AssetVc) -> Option, + configs: &[Config], + accessor: impl Fn(&JsonValue, Vc>) -> Option, ) -> Result> { for (config, source) in configs.iter() { if let FileJsonContent::Content(json) = &*config.await? { @@ -197,24 +188,26 @@ pub async fn read_from_tsconfigs( #[turbo_tasks::value] #[derive(Default)] pub struct TsConfigResolveOptions { - base_url: Option, - import_map: Option, + base_url: Option>, + import_map: Option>, } -impl Default for TsConfigResolveOptionsVc { - fn default() -> Self { - Self::cell(Default::default()) +#[turbo_tasks::value_impl] +impl ValueDefault for TsConfigResolveOptions { + #[turbo_tasks::function] + fn value_default() -> Vc { + Self::default().cell() } } /// Returns the resolve options #[turbo_tasks::function] pub async fn tsconfig_resolve_options( - tsconfig: FileSystemPathVc, -) -> Result { + tsconfig: Vc, +) -> Result> { let configs = read_tsconfigs( tsconfig.read(), - SourceAssetVc::new(tsconfig).into(), + Vc::upcast(SourceAsset::new(tsconfig)), node_cjs_resolve_options(tsconfig.root()), ) .await?; @@ -224,9 +217,13 @@ pub async fn tsconfig_resolve_options( } let base_url = if let Some(base_url) = read_from_tsconfigs(&configs, |json, source| { - json["compilerOptions"]["baseUrl"] - .as_str() - .map(|base_url| source.ident().path().parent().try_join(base_url)) + json["compilerOptions"]["baseUrl"].as_str().map(|base_url| { + source + .ident() + .path() + .parent() + .try_join(base_url.to_string()) + }) }) .await? { @@ -241,7 +238,7 @@ pub async fn tsconfig_resolve_options( if let JsonValue::Object(paths) = &json["compilerOptions"]["paths"] { let mut context = source.ident().path().parent(); if let Some(base_url) = json["compilerOptions"]["baseUrl"].as_str() { - if let Some(new_context) = *context.try_join(base_url).await? { + if let Some(new_context) = *context.try_join(base_url.to_string()).await? { context = new_context; } }; @@ -259,7 +256,7 @@ pub async fn tsconfig_resolve_options( TsConfigIssue { severity: IssueSeverity::Warning.cell(), source_ident: source.ident(), - message: StringVc::cell(format!( + message: Vc::cell(format!( "compilerOptions.paths[{key}] doesn't contains an array as \ expected\n{key}: {value:#}", key = serde_json::to_string(key)?, @@ -267,7 +264,6 @@ pub async fn tsconfig_resolve_options( )), } .cell() - .as_issue() .emit() } } @@ -293,8 +289,8 @@ pub async fn tsconfig_resolve_options( } #[turbo_tasks::function] -pub fn tsconfig() -> StringsVc { - StringsVc::cell(vec![ +pub fn tsconfig() -> Vc> { + Vc::cell(vec![ "tsconfig.json".to_string(), "jsconfig.json".to_string(), ]) @@ -302,9 +298,9 @@ pub fn tsconfig() -> StringsVc { #[turbo_tasks::function] pub async fn apply_tsconfig_resolve_options( - resolve_options: ResolveOptionsVc, - tsconfig_resolve_options: TsConfigResolveOptionsVc, -) -> Result { + resolve_options: Vc, + tsconfig_resolve_options: Vc, +) -> Result> { let tsconfig_resolve_options = tsconfig_resolve_options.await?; let mut resolve_options = resolve_options.await?.clone_value(); if let Some(base_url) = tsconfig_resolve_options.base_url { @@ -326,7 +322,10 @@ pub async fn apply_tsconfig_resolve_options( } #[turbo_tasks::function] -pub async fn type_resolve(origin: ResolveOriginVc, request: RequestVc) -> Result { +pub async fn type_resolve( + origin: Vc>, + request: Vc, +) -> Result> { let ty = Value::new(ReferenceType::TypeScript( TypeScriptReferenceSubType::Undefined, )); @@ -344,10 +343,10 @@ pub async fn type_resolve(origin: ResolveOriginVc, request: RequestVc) -> Result } else { m.clone() }; - Some(RequestVc::module( + Some(Request::module( format!("@types/{m}"), Value::new(p.clone()), - QueryMapVc::none(), + QueryMap::none(), )) } else { None @@ -369,7 +368,7 @@ pub async fn type_resolve(origin: ResolveOriginVc, request: RequestVc) -> Result origin.origin_path(), request, options, - OptionIssueSourceVc::none(), + OptionIssueSource::none(), IssueSeverity::Error.cell(), ) .await @@ -377,14 +376,14 @@ pub async fn type_resolve(origin: ResolveOriginVc, request: RequestVc) -> Result #[turbo_tasks::value] pub struct TypescriptTypesAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, + pub origin: Vc>, + pub request: Vc, } #[turbo_tasks::value_impl] impl AssetReference for TypescriptTypesAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { + fn resolve_reference(&self) -> Vc { type_resolve(self.origin, self.request) } } @@ -392,24 +391,24 @@ impl AssetReference for TypescriptTypesAssetReference { #[turbo_tasks::value_impl] impl ValueToString for TypescriptTypesAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "typescript types {}", self.request.to_string().await?, ))) } } -impl TypescriptTypesAssetReferenceVc { - pub fn new(origin: ResolveOriginVc, request: RequestVc) -> Self { +impl TypescriptTypesAssetReference { + pub fn new(origin: Vc>, request: Vc) -> Vc { Self::cell(TypescriptTypesAssetReference { origin, request }) } } #[turbo_tasks::function] async fn apply_typescript_types_options( - resolve_options: ResolveOptionsVc, -) -> Result { + resolve_options: Vc, +) -> Result> { let mut resolve_options = resolve_options.await?.clone_value(); resolve_options.extensions = vec![".tsx".to_string(), ".ts".to_string(), ".d.ts".to_string()]; resolve_options.into_package = resolve_options @@ -448,29 +447,29 @@ async fn apply_typescript_types_options( #[turbo_tasks::value_impl] impl Issue for TsConfigIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - async fn title(&self) -> Result { - Ok(StringVc::cell( + async fn title(&self) -> Result> { + Ok(Vc::cell( "An issue occurred while parsing a tsconfig.json file.".to_string(), )) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("typescript".to_string()) + fn category(&self) -> Vc { + Vc::cell("typescript".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.source_ident.path() } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.message } } diff --git a/crates/turbopack-ecmascript/src/webpack/mod.rs b/crates/turbopack-ecmascript/src/webpack/mod.rs index 9780ec1ee263d9..af52de463466f7 100644 --- a/crates/turbopack-ecmascript/src/webpack/mod.rs +++ b/crates/turbopack-ecmascript/src/webpack/mod.rs @@ -1,49 +1,46 @@ use anyhow::Result; use swc_core::ecma::ast::Lit; -use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, + asset::{Asset, AssetContent}, + ident::AssetIdent, + reference::{AssetReference, AssetReferences}, reference_type::{CommonJsReferenceSubType, ReferenceType}, resolve::{ - origin::{ResolveOrigin, ResolveOriginVc}, - parse::RequestVc, - resolve, ResolveResult, ResolveResultVc, + origin::{ResolveOrigin, ResolveOriginExt}, + parse::Request, + resolve, ResolveResult, }, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; -use self::{ - parse::{WebpackRuntime, WebpackRuntimeVc}, - references::module_references, -}; +use self::{parse::WebpackRuntime, references::module_references}; use super::resolve::apply_cjs_specific_options; -use crate::EcmascriptInputTransformsVc; +use crate::EcmascriptInputTransforms; pub mod parse; pub(crate) mod references; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("webpack".to_string()) +fn modifier() -> Vc { + Vc::cell("webpack".to_string()) } #[turbo_tasks::value] pub struct WebpackModuleAsset { - pub source: AssetVc, - pub runtime: WebpackRuntimeVc, - pub transforms: EcmascriptInputTransformsVc, + pub source: Vc>, + pub runtime: Vc, + pub transforms: Vc, } #[turbo_tasks::value_impl] -impl WebpackModuleAssetVc { +impl WebpackModuleAsset { #[turbo_tasks::function] pub fn new( - source: AssetVc, - runtime: WebpackRuntimeVc, - transforms: EcmascriptInputTransformsVc, - ) -> Self { + source: Vc>, + runtime: Vc, + transforms: Vc, + ) -> Vc { Self::cell(WebpackModuleAsset { source, runtime, @@ -55,17 +52,17 @@ impl WebpackModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for WebpackModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { module_references(self.source, self.runtime, self.transforms) } } @@ -74,14 +71,14 @@ impl Asset for WebpackModuleAsset { pub struct WebpackChunkAssetReference { #[turbo_tasks(trace_ignore)] pub chunk_id: Lit, - pub runtime: WebpackRuntimeVc, - pub transforms: EcmascriptInputTransformsVc, + pub runtime: Vc, + pub transforms: Vc, } #[turbo_tasks::value_impl] impl AssetReference for WebpackChunkAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { + async fn resolve_reference(&self) -> Result> { let runtime = self.runtime.await?; Ok(match &*runtime { WebpackRuntime::Webpack5 { @@ -95,11 +92,13 @@ impl AssetReference for WebpackChunkAssetReference { _ => todo!(), }; let filename = format!("./chunks/{}.js", chunk_id); - let source = SourceAssetVc::new(context_path.join(&filename)).into(); + let source = Vc::upcast(SourceAsset::new(context_path.join(filename))); - ResolveResult::asset( - WebpackModuleAssetVc::new(source, self.runtime, self.transforms).into(), - ) + ResolveResult::asset(Vc::upcast(WebpackModuleAsset::new( + source, + self.runtime, + self.transforms, + ))) .into() } WebpackRuntime::None => ResolveResult::unresolveable().into(), @@ -110,30 +109,32 @@ impl AssetReference for WebpackChunkAssetReference { #[turbo_tasks::value_impl] impl ValueToString for WebpackChunkAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { + async fn to_string(&self) -> Result> { let chunk_id = match &self.chunk_id { Lit::Str(str) => str.value.to_string(), Lit::Num(num) => format!("{num}"), _ => todo!(), }; - Ok(StringVc::cell(format!("webpack chunk {}", chunk_id))) + Ok(Vc::cell(format!("webpack chunk {}", chunk_id))) } } #[turbo_tasks::value(shared)] pub struct WebpackEntryAssetReference { - pub source: AssetVc, - pub runtime: WebpackRuntimeVc, - pub transforms: EcmascriptInputTransformsVc, + pub source: Vc>, + pub runtime: Vc, + pub transforms: Vc, } #[turbo_tasks::value_impl] impl AssetReference for WebpackEntryAssetReference { #[turbo_tasks::function] - fn resolve_reference(&self) -> ResolveResultVc { - ResolveResult::asset( - WebpackModuleAssetVc::new(self.source, self.runtime, self.transforms).into(), - ) + fn resolve_reference(&self) -> Vc { + ResolveResult::asset(Vc::upcast(WebpackModuleAsset::new( + self.source, + self.runtime, + self.transforms, + ))) .into() } } @@ -141,23 +142,23 @@ impl AssetReference for WebpackEntryAssetReference { #[turbo_tasks::value_impl] impl ValueToString for WebpackEntryAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell("webpack entry".to_string())) + async fn to_string(&self) -> Result> { + Ok(Vc::cell("webpack entry".to_string())) } } #[turbo_tasks::value(shared)] pub struct WebpackRuntimeAssetReference { - pub origin: ResolveOriginVc, - pub request: RequestVc, - pub runtime: WebpackRuntimeVc, - pub transforms: EcmascriptInputTransformsVc, + pub origin: Vc>, + pub request: Vc, + pub runtime: Vc, + pub transforms: Vc, } #[turbo_tasks::value_impl] impl AssetReference for WebpackRuntimeAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { + async fn resolve_reference(&self) -> Result> { let ty = Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)); let options = self.origin.resolve_options(ty.clone()); @@ -173,7 +174,11 @@ impl AssetReference for WebpackRuntimeAssetReference { .await? .map( |source| async move { - Ok(WebpackModuleAssetVc::new(source, self.runtime, self.transforms).into()) + Ok(Vc::upcast(WebpackModuleAsset::new( + source, + self.runtime, + self.transforms, + ))) }, |r| async move { Ok(r) }, ) @@ -185,8 +190,8 @@ impl AssetReference for WebpackRuntimeAssetReference { #[turbo_tasks::value_impl] impl ValueToString for WebpackRuntimeAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "webpack {}", self.request.to_string().await?, ))) diff --git a/crates/turbopack-ecmascript/src/webpack/parse.rs b/crates/turbopack-ecmascript/src/webpack/parse.rs index a04dfb34cfe1b1..b9db204c68458c 100644 --- a/crates/turbopack-ecmascript/src/webpack/parse.rs +++ b/crates/turbopack-ecmascript/src/webpack/parse.rs @@ -11,15 +11,15 @@ use swc_core::{ visit::{Visit, VisitWith}, }, }; -use turbo_tasks::Value; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::asset::{Asset, AssetVc}; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::asset::Asset; use crate::{ analyzer::{graph::EvalContext, JsValue}, parse::{parse, ParseResult}, utils::unparen, - EcmascriptInputTransformsVc, EcmascriptModuleAssetType, + EcmascriptInputTransforms, EcmascriptModuleAssetType, }; #[turbo_tasks::value(shared, serialization = "none")] @@ -30,7 +30,7 @@ pub enum WebpackRuntime { /// before converting to string #[turbo_tasks(trace_ignore)] chunk_request_expr: JsValue, - context_path: FileSystemPathVc, + context_path: Vc, }, None, } @@ -182,9 +182,9 @@ fn get_require_prefix(stmts: &Vec) -> Option { #[turbo_tasks::function] pub async fn webpack_runtime( - asset: AssetVc, - transforms: EcmascriptInputTransformsVc, -) -> Result { + asset: Vc>, + transforms: Vc, +) -> Result> { let parsed = parse( asset, Value::new(EcmascriptModuleAssetType::Ecmascript), diff --git a/crates/turbopack-ecmascript/src/webpack/references.rs b/crates/turbopack-ecmascript/src/webpack/references.rs index 81e30f8630ce95..4d5772c921925c 100644 --- a/crates/turbopack-ecmascript/src/webpack/references.rs +++ b/crates/turbopack-ecmascript/src/webpack/references.rs @@ -6,25 +6,25 @@ use swc_core::{ visit::{Visit, VisitWith}, }, }; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ - asset::AssetVc, - reference::{AssetReferenceVc, AssetReferencesVc}, + asset::Asset, + reference::{AssetReference, AssetReferences}, }; use turbopack_swc_utils::emitter::IssueEmitter; -use super::{parse::WebpackRuntimeVc, WebpackChunkAssetReference}; +use super::{parse::WebpackRuntime, WebpackChunkAssetReference}; use crate::{ parse::{parse, ParseResult}, - EcmascriptInputTransformsVc, EcmascriptModuleAssetType, + EcmascriptInputTransforms, EcmascriptModuleAssetType, }; #[turbo_tasks::function] pub async fn module_references( - source: AssetVc, - runtime: WebpackRuntimeVc, - transforms: EcmascriptInputTransformsVc, -) -> Result { + source: Vc>, + runtime: Vc, + transforms: Vc, +) -> Result> { let parsed = parse( source, Value::new(EcmascriptModuleAssetType::Ecmascript), @@ -55,16 +55,16 @@ pub async fn module_references( HANDLER.set(&handler, || { program.visit_with(&mut visitor); }); - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } - ParseResult::Unparseable | ParseResult::NotFound => Ok(AssetReferencesVc::cell(Vec::new())), + ParseResult::Unparseable | ParseResult::NotFound => Ok(Vc::cell(Vec::new())), } } struct AssetReferencesVisitor<'a> { - runtime: WebpackRuntimeVc, - references: &'a mut Vec, - transforms: EcmascriptInputTransformsVc, + runtime: Vc, + references: &'a mut Vec>>, + transforms: Vc, } impl<'a> Visit for AssetReferencesVisitor<'a> { @@ -74,15 +74,14 @@ impl<'a> Visit for AssetReferencesVisitor<'a> { if &*obj.sym == "__webpack_require__" && &*prop.sym == "e" { if let [ExprOrSpread { spread: None, expr }] = &call.args[..] { if let Expr::Lit(lit) = &**expr { - self.references.push( + self.references.push(Vc::upcast( WebpackChunkAssetReference { chunk_id: lit.clone(), runtime: self.runtime, transforms: self.transforms, } - .cell() - .into(), - ); + .cell(), + )); } } } diff --git a/crates/turbopack-env/src/asset.rs b/crates/turbopack-env/src/asset.rs index 905192659f0fba..a5e6e73dab83b3 100644 --- a/crates/turbopack-env/src/asset.rs +++ b/crates/turbopack-env/src/asset.rs @@ -1,11 +1,12 @@ use std::io::Write; use anyhow::Result; -use turbo_tasks_env::{ProcessEnv, ProcessEnvVc}; -use turbo_tasks_fs::{rope::RopeBuilder, File, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{rope::RopeBuilder, File, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, }; use turbopack_ecmascript::utils::StringifyJs; @@ -14,16 +15,16 @@ use turbopack_ecmascript::utils::StringifyJs; #[turbo_tasks::value] pub struct ProcessEnvAsset { /// The root path which we can construct our env asset path. - root: FileSystemPathVc, + root: Vc, /// A HashMap filled with the env key/values. - env: ProcessEnvVc, + env: Vc>, } #[turbo_tasks::value_impl] -impl ProcessEnvAssetVc { +impl ProcessEnvAsset { #[turbo_tasks::function] - pub fn new(root: FileSystemPathVc, env: ProcessEnvVc) -> Self { + pub fn new(root: Vc, env: Vc>) -> Vc { ProcessEnvAsset { root, env }.cell() } } @@ -31,12 +32,12 @@ impl ProcessEnvAssetVc { #[turbo_tasks::value_impl] impl Asset for ProcessEnvAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - AssetIdentVc::from_path(self.root.join(".env.js")) + fn ident(&self) -> Vc { + AssetIdent::from_path(self.root.join(".env.js".to_string())) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let env = self.env.read_all().await?; // TODO: In SSR, we use the native process.env, which can only contain string @@ -54,6 +55,6 @@ impl Asset for ProcessEnvAsset { writeln!(code, "env[{}] = {};", StringifyJs(name), val)?; } - Ok(File::from(code.build()).into()) + Ok(AssetContent::file(File::from(code.build()).into())) } } diff --git a/crates/turbopack-env/src/dotenv.rs b/crates/turbopack-env/src/dotenv.rs index fa9a9ab57da25d..e66925fa2528a9 100644 --- a/crates/turbopack-env/src/dotenv.rs +++ b/crates/turbopack-env/src/dotenv.rs @@ -1,28 +1,26 @@ use anyhow::Result; use indexmap::indexmap; -use turbo_tasks_env::{ - CommandLineProcessEnvVc, CustomProcessEnvVc, EnvMapVc, ProcessEnv, ProcessEnvVc, -}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_env::{CommandLineProcessEnv, CustomProcessEnv, ProcessEnv}; +use turbo_tasks_fs::FileSystemPath; -use crate::TryDotenvProcessEnvVc; +use crate::TryDotenvProcessEnv; /// Loads a series of dotenv files according to the precedence rules set by /// https://nextjs.org/docs/basic-features/environment-variables#environment-variable-load-order #[turbo_tasks::function] -pub async fn load_env(project_path: FileSystemPathVc) -> Result { - let env = CommandLineProcessEnvVc::new().as_process_env(); +pub async fn load_env(project_path: Vc) -> Result>> { + let env: Vc> = Vc::upcast(CommandLineProcessEnv::new()); - let node_env = env.read("NODE_ENV").await?; + let node_env = env.read("NODE_ENV".to_string()).await?; let node_env = node_env.as_deref().unwrap_or("development"); - let env = CustomProcessEnvVc::new( + let env = Vc::upcast(CustomProcessEnv::new( env, - EnvMapVc::cell(indexmap! { + Vc::cell(indexmap! { "NODE_ENV".to_string() => node_env.to_string(), }), - ) - .as_process_env(); + )); let files = [ Some(format!(".env.{node_env}.local")), @@ -38,8 +36,8 @@ pub async fn load_env(project_path: FileSystemPathVc) -> Result { .flatten(); let env = files.fold(env, |prior, f| { - let path = project_path.join(&f); - TryDotenvProcessEnvVc::new(prior, path).as_process_env() + let path = project_path.join(f); + Vc::upcast(TryDotenvProcessEnv::new(prior, path)) }); Ok(env) diff --git a/crates/turbopack-env/src/embeddable.rs b/crates/turbopack-env/src/embeddable.rs index 7fa74d5abbe01a..e7a419148b49af 100644 --- a/crates/turbopack-env/src/embeddable.rs +++ b/crates/turbopack-env/src/embeddable.rs @@ -1,19 +1,19 @@ use anyhow::Result; -use turbo_tasks::primitives::OptionStringVc; -use turbo_tasks_env::{EnvMapVc, ProcessEnv, ProcessEnvVc}; +use turbo_tasks::Vc; +use turbo_tasks_env::{EnvMap, ProcessEnv}; use turbopack_ecmascript::utils::StringifyJs; /// Encodes values as JS strings so that they can be safely injected into a JS /// output. #[turbo_tasks::value] pub struct EmbeddableProcessEnv { - prior: ProcessEnvVc, + prior: Vc>, } #[turbo_tasks::value_impl] -impl EmbeddableProcessEnvVc { +impl EmbeddableProcessEnv { #[turbo_tasks::function] - pub fn new(prior: ProcessEnvVc) -> Self { + pub fn new(prior: Vc>) -> Vc { EmbeddableProcessEnv { prior }.cell() } } @@ -21,7 +21,7 @@ impl EmbeddableProcessEnvVc { #[turbo_tasks::value_impl] impl ProcessEnv for EmbeddableProcessEnv { #[turbo_tasks::function] - async fn read_all(&self) -> Result { + async fn read_all(&self) -> Result> { let prior = self.prior.read_all().await?; let encoded = prior @@ -29,13 +29,13 @@ impl ProcessEnv for EmbeddableProcessEnv { .map(|(k, v)| (k.clone(), StringifyJs(v).to_string())) .collect(); - Ok(EnvMapVc::cell(encoded)) + Ok(Vc::cell(encoded)) } #[turbo_tasks::function] - async fn read(&self, name: &str) -> Result { + async fn read(&self, name: String) -> Result>> { let prior = self.prior.read(name).await?; let encoded = prior.as_deref().map(|s| StringifyJs(s).to_string()); - Ok(OptionStringVc::cell(encoded)) + Ok(Vc::cell(encoded)) } } diff --git a/crates/turbopack-env/src/issue.rs b/crates/turbopack-env/src/issue.rs index 6c2d2cb3d6d79b..a42813bf23511f 100644 --- a/crates/turbopack-env/src/issue.rs +++ b/crates/turbopack-env/src/issue.rs @@ -1,34 +1,33 @@ -use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::issue::{Issue, IssueVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::Issue; /// An issue that occurred while resolving the parsing or evaluating the .env. #[turbo_tasks::value(shared)] pub struct ProcessEnvIssue { - pub path: FileSystemPathVc, - pub description: StringVc, + pub path: Vc, + pub description: Vc, } #[turbo_tasks::value_impl] impl Issue for ProcessEnvIssue { #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Error loading dotenv file".to_string()) + fn title(&self) -> Vc { + Vc::cell("Error loading dotenv file".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("parse".to_string()) + fn category(&self) -> Vc { + Vc::cell("parse".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.path } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.description } } diff --git a/crates/turbopack-env/src/lib.rs b/crates/turbopack-env/src/lib.rs index 375a6d9653c388..06b0420128aa56 100644 --- a/crates/turbopack-env/src/lib.rs +++ b/crates/turbopack-env/src/lib.rs @@ -11,6 +11,8 @@ #![feature(async_closure)] #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] mod asset; pub mod dotenv; @@ -18,10 +20,10 @@ mod embeddable; mod issue; mod try_env; -pub use asset::{ProcessEnvAsset, ProcessEnvAssetVc}; -pub use embeddable::EmbeddableProcessEnvVc; -pub use issue::{ProcessEnvIssue, ProcessEnvIssueVc}; -pub use try_env::TryDotenvProcessEnvVc; +pub use asset::ProcessEnvAsset; +pub use embeddable::EmbeddableProcessEnv; +pub use issue::ProcessEnvIssue; +pub use try_env::TryDotenvProcessEnv; pub fn register() { turbo_tasks::register(); diff --git a/crates/turbopack-env/src/try_env.rs b/crates/turbopack-env/src/try_env.rs index f8b1db562148cf..969b18b543c7ad 100644 --- a/crates/turbopack-env/src/try_env.rs +++ b/crates/turbopack-env/src/try_env.rs @@ -1,22 +1,23 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_env::{DotenvProcessEnvVc, EnvMapVc, ProcessEnv, ProcessEnvVc}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_env::{DotenvProcessEnv, EnvMap, ProcessEnv}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::IssueExt; use crate::ProcessEnvIssue; #[turbo_tasks::value] pub struct TryDotenvProcessEnv { - dotenv: DotenvProcessEnvVc, - prior: ProcessEnvVc, - path: FileSystemPathVc, + dotenv: Vc, + prior: Vc>, + path: Vc, } #[turbo_tasks::value_impl] -impl TryDotenvProcessEnvVc { +impl TryDotenvProcessEnv { #[turbo_tasks::function] - pub fn new(prior: ProcessEnvVc, path: FileSystemPathVc) -> Self { - let dotenv = DotenvProcessEnvVc::new(Some(prior), path); + pub fn new(prior: Vc>, path: Vc) -> Vc { + let dotenv = DotenvProcessEnv::new(Some(prior), path); TryDotenvProcessEnv { dotenv, prior, @@ -29,7 +30,7 @@ impl TryDotenvProcessEnvVc { #[turbo_tasks::value_impl] impl ProcessEnv for TryDotenvProcessEnv { #[turbo_tasks::function] - async fn read_all(&self) -> Result { + async fn read_all(&self) -> Result> { let dotenv = self.dotenv; let prior = dotenv.read_prior(); @@ -49,10 +50,9 @@ impl ProcessEnv for TryDotenvProcessEnv { // read_all_with_prior will wrap a current error with a context containing the // failing file, which we don't really care about (we report the filepath as the // Issue context, not the description). So extract the real error. - description: StringVc::cell(e.root_cause().to_string()), + description: Vc::cell(e.root_cause().to_string()), } .cell() - .as_issue() .emit(); Ok(prior) } diff --git a/crates/turbopack-image/src/lib.rs b/crates/turbopack-image/src/lib.rs index d4bf74ce99301c..9bc25592e0448a 100644 --- a/crates/turbopack-image/src/lib.rs +++ b/crates/turbopack-image/src/lib.rs @@ -1,3 +1,6 @@ +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] + pub mod process; pub fn register() { diff --git a/crates/turbopack-image/src/process/mod.rs b/crates/turbopack-image/src/process/mod.rs index 35030ed8266898..65bf55ac94c563 100644 --- a/crates/turbopack-image/src/process/mod.rs +++ b/crates/turbopack-image/src/process/mod.rs @@ -17,12 +17,12 @@ use image::{ use mime::Mime; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; -use turbo_tasks::{debug::ValueDebugFormat, primitives::StringVc, trace::TraceRawVcs}; -use turbo_tasks_fs::{File, FileContent, FileContentVc, FileSystemPathVc}; +use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, Vc}; +use turbo_tasks_fs::{File, FileContent, FileSystemPath}; use turbopack_core::{ error::PrettyPrintError, - ident::AssetIdentVc, - issue::{Issue, IssueVc}, + ident::AssetIdent, + issue::{Issue, IssueExt}, }; use self::svg::calculate; @@ -101,16 +101,15 @@ fn extension_to_image_format(extension: &str) -> Option { }) } -fn result_to_issue(ident: AssetIdentVc, result: Result) -> Option { +fn result_to_issue(ident: Vc, result: Result) -> Option { match result { Ok(r) => Some(r), Err(err) => { ImageProcessingIssue { path: ident.path(), - message: StringVc::cell(format!("{}", PrettyPrintError(&err))), + message: Vc::cell(format!("{}", PrettyPrintError(&err))), } .cell() - .as_issue() .emit(); None } @@ -118,7 +117,7 @@ fn result_to_issue(ident: AssetIdentVc, result: Result) -> Option { } fn load_image( - ident: AssetIdentVc, + ident: Vc, bytes: &[u8], extension: Option<&str>, ) -> Option<(image::DynamicImage, Option)> { @@ -147,7 +146,7 @@ fn load_image_internal( } fn compute_blur_data( - ident: AssetIdentVc, + ident: Vc, image: image::DynamicImage, format: ImageFormat, options: &BlurPlaceholderOptions, @@ -159,10 +158,9 @@ fn compute_blur_data( Err(err) => { ImageProcessingIssue { path: ident.path(), - message: StringVc::cell(format!("{}", PrettyPrintError(&err))), + message: Vc::cell(format!("{}", PrettyPrintError(&err))), } .cell() - .as_issue() .emit(); Some(BlurPlaceholder::fallback()) } @@ -286,16 +284,16 @@ fn image_format_to_mime_type(format: ImageFormat) -> Result> { /// Optionally computes a blur placeholder. #[turbo_tasks::function] pub async fn get_meta_data( - ident: AssetIdentVc, - content: FileContentVc, - blur_placeholder: Option, -) -> Result { + ident: Vc, + content: Vc, + blur_placeholder: Option>, +) -> Result> { let FileContent::Content(content) = &*content.await? else { bail!("Input image not found"); }; let bytes = content.content().to_bytes()?; let path = ident.path().await?; - let extension = path.extension(); + let extension = path.extension_ref(); if extension == Some("svg") { let content = result_to_issue( ident, @@ -357,17 +355,17 @@ pub async fn get_meta_data( #[turbo_tasks::function] pub async fn optimize( - ident: AssetIdentVc, - content: FileContentVc, + ident: Vc, + content: Vc, max_width: u32, max_height: u32, quality: u8, -) -> Result { +) -> Result> { let FileContent::Content(content) = &*content.await? else { return Ok(FileContent::NotFound.cell()); }; let bytes = content.content().to_bytes()?; - let Some((image, mut format)) = load_image(ident, &bytes, ident.path().await?.extension()) else { + let Some((image, mut format)) = load_image(ident, &bytes, ident.path().await?.extension_ref()) else { return Ok(FileContent::NotFound.cell()); }; let (width, height) = image.dimensions(); @@ -392,26 +390,26 @@ pub async fn optimize( #[turbo_tasks::value] struct ImageProcessingIssue { - path: FileSystemPathVc, - message: StringVc, + path: Vc, + message: Vc, } #[turbo_tasks::value_impl] impl Issue for ImageProcessingIssue { #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.path } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("image".to_string()) + fn category(&self) -> Vc { + Vc::cell("image".to_string()) } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Processing image failed".to_string()) + fn title(&self) -> Vc { + Vc::cell("Processing image failed".to_string()) } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.message } } diff --git a/crates/turbopack-json/src/lib.rs b/crates/turbopack-json/src/lib.rs index 0bc81ca7909ec7..9348ec8be0d3a5 100644 --- a/crates/turbopack-json/src/lib.rs +++ b/crates/turbopack-json/src/lib.rs @@ -6,41 +6,41 @@ //! JSON value as an object. #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use std::fmt::Write; use anyhow::{bail, Error, Result}; -use turbo_tasks::{primitives::StringVc, Value, ValueToString}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbo_tasks_fs::{FileContent, FileJsonContent}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetVc, ChunkingContextVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, ChunkingContext, }, - ident::AssetIdentVc, - reference::AssetReferencesVc, + ident::AssetIdent, + reference::AssetReferences, }; use turbopack_ecmascript::chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc, - EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable, + EcmascriptChunkingContext, EcmascriptExports, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("json".to_string()) +fn modifier() -> Vc { + Vc::cell("json".to_string()) } #[turbo_tasks::value] pub struct JsonModuleAsset { - source: AssetVc, + source: Vc>, } #[turbo_tasks::value_impl] -impl JsonModuleAssetVc { +impl JsonModuleAsset { #[turbo_tasks::function] - pub fn new(source: AssetVc) -> Self { + pub fn new(source: Vc>) -> Vc { Self::cell(JsonModuleAsset { source }) } } @@ -48,12 +48,12 @@ impl JsonModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for JsonModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } } @@ -62,16 +62,15 @@ impl Asset for JsonModuleAsset { impl ChunkableAsset for JsonModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: JsonModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } @@ -79,37 +78,36 @@ impl ChunkableAsset for JsonModuleAsset { impl EcmascriptChunkPlaceable for JsonModuleAsset { #[turbo_tasks::function] fn as_chunk_item( - self_vc: JsonModuleAssetVc, - context: EcmascriptChunkingContextVc, - ) -> EcmascriptChunkItemVc { - JsonChunkItemVc::cell(JsonChunkItem { - module: self_vc, + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(JsonChunkItem::cell(JsonChunkItem { + module: self, context, - }) - .into() + })) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } } #[turbo_tasks::value] struct JsonChunkItem { - module: JsonModuleAssetVc, - context: EcmascriptChunkingContextVc, + module: Vc, + context: Vc>, } #[turbo_tasks::value_impl] impl ChunkItem for JsonChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.module.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.module.references() } } @@ -117,12 +115,12 @@ impl ChunkItem for JsonChunkItem { #[turbo_tasks::value_impl] impl EcmascriptChunkItem for JsonChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { // We parse to JSON and then stringify again to ensure that the // JSON is valid. let content = self.module.content().file_content(); diff --git a/crates/turbopack-mdx/src/lib.rs b/crates/turbopack-mdx/src/lib.rs index ae09eb867e6161..37687e69168a1e 100644 --- a/crates/turbopack-mdx/src/lib.rs +++ b/crates/turbopack-mdx/src/lib.rs @@ -1,34 +1,34 @@ #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] use anyhow::{anyhow, Result}; use mdxjs::{compile, Options}; -use turbo_tasks::{primitives::StringVc, Value}; -use turbo_tasks_fs::{rope::Rope, File, FileContent, FileSystemPathVc}; +use turbo_tasks::{Value, ValueDefault, Vc}; +use turbo_tasks_fs::{rope::Rope, File, FileContent, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetVc, ChunkingContextVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, ChunkingContext, }, - context::{AssetContext, AssetContextVc}, - ident::AssetIdentVc, - reference::AssetReferencesVc, - resolve::origin::{ResolveOrigin, ResolveOriginVc}, - virtual_asset::VirtualAssetVc, + context::AssetContext, + ident::AssetIdent, + reference::AssetReferences, + resolve::origin::ResolveOrigin, + virtual_asset::VirtualAsset, }; use turbopack_ecmascript::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContentVc, EcmascriptChunkItemVc, - EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc, - EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable, + EcmascriptChunkingContext, EcmascriptExports, }, - AnalyzeEcmascriptModuleResultVc, EcmascriptInputTransformsVc, EcmascriptModuleAssetType, - EcmascriptModuleAssetVc, + AnalyzeEcmascriptModuleResult, EcmascriptInputTransforms, EcmascriptModuleAsset, + EcmascriptModuleAssetType, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("mdx".to_string()) +fn modifier() -> Vc { + Vc::cell("mdx".to_string()) } /// Subset of mdxjs::Options to allow to inherit turbopack's jsx-related configs @@ -56,26 +56,26 @@ impl Default for MdxTransformOptions { } #[turbo_tasks::value_impl] -impl MdxTransformOptionsVc { +impl MdxTransformOptions { #[turbo_tasks::function] - pub fn default() -> Self { + fn default_private() -> Vc { Self::cell(Default::default()) } } -impl Default for MdxTransformOptionsVc { - fn default() -> Self { - Self::default() +impl ValueDefault for MdxTransformOptions { + fn value_default() -> Vc { + Self::default_private() } } #[turbo_tasks::value] #[derive(Clone, Copy)] pub struct MdxModuleAsset { - source: AssetVc, - context: AssetContextVc, - transforms: EcmascriptInputTransformsVc, - options: MdxTransformOptionsVc, + source: Vc>, + context: Vc>, + transforms: Vc, + options: Vc, } /// MDX components should be treated as normal j|tsx components to analyze @@ -84,8 +84,8 @@ pub struct MdxModuleAsset { /// can't pass it forward directly. Internally creates an jsx from mdx /// via mdxrs, then pass it through existing ecmascript analyzer. async fn into_ecmascript_module_asset( - current_context: &MdxModuleAssetVc, -) -> Result { + current_context: &Vc, +) -> Result> { let content = current_context.content(); let this = current_context.await?; let transform_options = this.options.await?; @@ -124,12 +124,12 @@ async fn into_ecmascript_module_asset( let mdx_jsx_component = compile(&file.content().to_str()?, &options).map_err(|e| anyhow!("{}", e))?; - let source = VirtualAssetVc::new_with_ident( + let source = VirtualAsset::new_with_ident( this.source.ident(), - File::from(Rope::from(mdx_jsx_component)).into(), + AssetContent::file(File::from(Rope::from(mdx_jsx_component)).into()), ); - Ok(EcmascriptModuleAssetVc::new( - source.into(), + Ok(EcmascriptModuleAsset::new( + Vc::upcast(source), this.context, Value::new(EcmascriptModuleAssetType::Typescript), this.transforms, @@ -139,14 +139,14 @@ async fn into_ecmascript_module_asset( } #[turbo_tasks::value_impl] -impl MdxModuleAssetVc { +impl MdxModuleAsset { #[turbo_tasks::function] pub fn new( - source: AssetVc, - context: AssetContextVc, - transforms: EcmascriptInputTransformsVc, - options: MdxTransformOptionsVc, - ) -> Self { + source: Vc>, + context: Vc>, + transforms: Vc, + options: Vc, + ) -> Vc { Self::cell(MdxModuleAsset { source, context, @@ -156,7 +156,7 @@ impl MdxModuleAssetVc { } #[turbo_tasks::function] - async fn failsafe_analyze(self) -> Result { + async fn failsafe_analyze(self: Vc) -> Result> { Ok(into_ecmascript_module_asset(&self) .await? .failsafe_analyze()) @@ -166,18 +166,18 @@ impl MdxModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for MdxModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } #[turbo_tasks::function] - async fn references(self_vc: MdxModuleAssetVc) -> Result { - Ok(self_vc.failsafe_analyze().await?.references) + async fn references(self: Vc) -> Result> { + Ok(self.failsafe_analyze().await?.references) } } @@ -185,16 +185,15 @@ impl Asset for MdxModuleAsset { impl ChunkableAsset for MdxModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: MdxModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } @@ -202,18 +201,17 @@ impl ChunkableAsset for MdxModuleAsset { impl EcmascriptChunkPlaceable for MdxModuleAsset { #[turbo_tasks::function] fn as_chunk_item( - self_vc: MdxModuleAssetVc, - context: EcmascriptChunkingContextVc, - ) -> EcmascriptChunkItemVc { - MdxChunkItemVc::cell(MdxChunkItem { - module: self_vc, + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(MdxChunkItem::cell(MdxChunkItem { + module: self, context, - }) - .into() + })) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.cell() } } @@ -221,31 +219,31 @@ impl EcmascriptChunkPlaceable for MdxModuleAsset { #[turbo_tasks::value_impl] impl ResolveOrigin for MdxModuleAsset { #[turbo_tasks::function] - fn origin_path(&self) -> FileSystemPathVc { + fn origin_path(&self) -> Vc { self.source.ident().path() } #[turbo_tasks::function] - fn context(&self) -> AssetContextVc { + fn context(&self) -> Vc> { self.context } } #[turbo_tasks::value] struct MdxChunkItem { - module: MdxModuleAssetVc, - context: EcmascriptChunkingContextVc, + module: Vc, + context: Vc>, } #[turbo_tasks::value_impl] impl ChunkItem for MdxChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.module.ident() } #[turbo_tasks::function] - fn references(&self) -> AssetReferencesVc { + fn references(&self) -> Vc { self.module.references() } } @@ -253,14 +251,14 @@ impl ChunkItem for MdxChunkItem { #[turbo_tasks::value_impl] impl EcmascriptChunkItem for MdxChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } /// Once we have mdx contents, we should treat it as j|tsx components and /// apply all of the ecma transforms #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { Ok(into_ecmascript_module_asset(&self.module) .await? .as_chunk_item(self.context) diff --git a/crates/turbopack-node/src/bootstrap.rs b/crates/turbopack-node/src/bootstrap.rs index 0c805dc32c329f..c03fc75083cf48 100644 --- a/crates/turbopack-node/src/bootstrap.rs +++ b/crates/turbopack-node/src/bootstrap.rs @@ -1,31 +1,31 @@ use std::fmt::Write; use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::{File, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{File, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc, AssetsVc}, - chunk::{ChunkVc, ChunkingContext, ChunkingContextVc, EvaluatableAssetsVc}, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, + asset::{Asset, AssetContent, Assets}, + chunk::{Chunk, ChunkingContext, EvaluatableAssets}, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, }; use turbopack_ecmascript::utils::StringifyJs; #[turbo_tasks::value(shared)] pub(super) struct NodeJsBootstrapAsset { - pub(super) path: FileSystemPathVc, - pub(super) chunking_context: ChunkingContextVc, - pub(super) entry: ChunkVc, - pub(super) evaluatable_assets: EvaluatableAssetsVc, + pub(super) path: Vc, + pub(super) chunking_context: Vc>, + pub(super) entry: Vc>, + pub(super) evaluatable_assets: Vc, } #[turbo_tasks::function] -fn node_js_bootstrap_chunk_reference_description() -> StringVc { - StringVc::cell("node.js bootstrap chunk".to_string()) +fn node_js_bootstrap_chunk_reference_description() -> Vc { + Vc::cell("node.js bootstrap chunk".to_string()) } impl NodeJsBootstrapAsset { - fn chunks(&self) -> AssetsVc { + fn chunks(&self) -> Vc { self.chunking_context .evaluated_chunk_group(self.entry, self.evaluatable_assets) } @@ -34,12 +34,12 @@ impl NodeJsBootstrapAsset { #[turbo_tasks::value_impl] impl Asset for NodeJsBootstrapAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - AssetIdentVc::from_path(self.path) + fn ident(&self) -> Vc { + AssetIdent::from_path(self.path) } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { let context_path = self.path.parent().await?; // TODO(sokra) We need to have a chunk format for node.js @@ -55,22 +55,19 @@ impl Asset for NodeJsBootstrapAsset { } } - Ok(File::from(output).into()) + Ok(AssetContent::file(File::from(output).into())) } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { let chunks = self.chunks().await?; let mut references = Vec::new(); for chunk in chunks.iter() { - references.push( - SingleAssetReferenceVc::new( - *chunk, - node_js_bootstrap_chunk_reference_description(), - ) - .into(), - ); + references.push(Vc::upcast(SingleAssetReference::new( + *chunk, + node_js_bootstrap_chunk_reference_description(), + ))); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } diff --git a/crates/turbopack-node/src/embed_js.rs b/crates/turbopack-node/src/embed_js.rs index f2e8bf817644e3..a13d379e216da3 100644 --- a/crates/turbopack-node/src/embed_js.rs +++ b/crates/turbopack-node/src/embed_js.rs @@ -1,16 +1,17 @@ -use turbo_tasks_fs::{embed_directory, FileContentVc, FileSystem, FileSystemPathVc, FileSystemVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{embed_directory, FileContent, FileSystem, FileSystemPath}; #[turbo_tasks::function] -pub fn embed_fs() -> FileSystemVc { +pub fn embed_fs() -> Vc> { embed_directory!("turbopack-node", "$CARGO_MANIFEST_DIR/js/src") } #[turbo_tasks::function] -pub(crate) fn embed_file(path: &str) -> FileContentVc { +pub(crate) fn embed_file(path: String) -> Vc { embed_fs().root().join(path).read() } #[turbo_tasks::function] -pub(crate) fn embed_file_path(path: &str) -> FileSystemPathVc { +pub(crate) fn embed_file_path(path: String) -> Vc { embed_fs().root().join(path) } diff --git a/crates/turbopack-node/src/evaluate.rs b/crates/turbopack-node/src/evaluate.rs index 43ed8ee00df8f3..ce3ee7fc0b226d 100644 --- a/crates/turbopack-node/src/evaluate.rs +++ b/crates/turbopack-node/src/evaluate.rs @@ -12,36 +12,32 @@ use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; use turbo_tasks::{ - duration_span, mark_finished, - primitives::{JsonValueVc, StringVc}, - util::SharedError, - CompletionVc, RawVc, TryJoinIterExt, Value, ValueToString, + duration_span, mark_finished, util::SharedError, Completion, RawVc, TryJoinIterExt, Value, + ValueToString, Vc, }; use turbo_tasks_bytes::{Bytes, Stream}; -use turbo_tasks_env::{ProcessEnv, ProcessEnvVc}; +use turbo_tasks_env::ProcessEnv; use turbo_tasks_fs::{ - glob::GlobVc, to_sys_path, DirectoryEntry, File, FileSystemPathVc, ReadGlobResultVc, + glob::Glob, to_sys_path, DirectoryEntry, File, FileSystemPath, ReadGlobResult, }; use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{ - ChunkableAsset, ChunkingContext, ChunkingContextVc, EvaluatableAssetVc, EvaluatableAssetsVc, - }, - context::{AssetContext, AssetContextVc}, - ident::AssetIdentVc, - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, - reference_type::{InnerAssetsVc, ReferenceType}, - source_asset::SourceAssetVc, - virtual_asset::VirtualAssetVc, + asset::{Asset, AssetContent}, + chunk::{ChunkableAsset, ChunkingContext, EvaluatableAsset, EvaluatableAssets}, + context::AssetContext, + ident::AssetIdent, + issue::{Issue, IssueExt, IssueSeverity}, + reference_type::{InnerAssets, ReferenceType}, + source_asset::SourceAsset, + virtual_asset::VirtualAsset, }; use crate::{ bootstrap::NodeJsBootstrapAsset, embed_js::embed_file_path, emit, emit_package_json, internal_assets_for_source_mapping, - pool::{FormattingMode, NodeJsOperation, NodeJsPool, NodeJsPoolVc}, + pool::{FormattingMode, NodeJsOperation, NodeJsPool}, source_map::StructuredError, - AssetsForSourceMappingVc, + AssetsForSourceMapping, }; #[derive(Serialize)] @@ -98,18 +94,20 @@ pub struct JavaScriptEvaluation(#[turbo_tasks(trace_ignore)] JavaScriptStream); /// Pass the file you cared as `runtime_entries` to invalidate and reload the /// evaluated result automatically. pub async fn get_evaluate_pool( - module_asset: AssetVc, - cwd: FileSystemPathVc, - env: ProcessEnvVc, - context: AssetContextVc, - chunking_context: ChunkingContextVc, - runtime_entries: Option, - additional_invalidation: CompletionVc, + module_asset: Vc>, + cwd: Vc, + env: Vc>, + context: Vc>, + chunking_context: Vc>, + runtime_entries: Option>, + additional_invalidation: Vc, debug: bool, -) -> Result { +) -> Result> { let runtime_asset = context.process( - SourceAssetVc::new(embed_file_path("ipc/evaluate.ts")).into(), - Value::new(ReferenceType::Internal(InnerAssetsVc::empty())), + Vc::upcast(SourceAsset::new(embed_file_path( + "ipc/evaluate.ts".to_string(), + ))), + Value::new(ReferenceType::Internal(InnerAssets::empty())), ); let module_path = module_asset.ident().path().await?; @@ -121,24 +119,25 @@ pub async fn get_evaluate_pool( } else { Cow::Owned(format!("{file_name}.js")) }; - let path = chunking_context.output_root().join(file_name.as_ref()); + let path = chunking_context.output_root().join(file_name.to_string()); let entry_module = context.process( - VirtualAssetVc::new( - runtime_asset.ident().path().join("evaluate.js"), - File::from( - "import { run } from 'RUNTIME'; run((...args) => \ - (require('INNER').default(...args)))", - ) - .into(), - ) - .into(), - Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! { + Vc::upcast(VirtualAsset::new( + runtime_asset.ident().path().join("evaluate.js".to_string()), + AssetContent::file( + File::from( + "import { run } from 'RUNTIME'; run((...args) => \ + (require('INNER').default(...args)))", + ) + .into(), + ), + )), + Value::new(ReferenceType::Internal(Vc::cell(indexmap! { "INNER".to_string() => module_asset, "RUNTIME".to_string() => runtime_asset }))), ); - let Some(entry_module) = EvaluatableAssetVc::resolve_from(entry_module).await? else { + let Some(entry_module) = Vc::try_resolve_sidecast::>(entry_module).await? else { bail!("Internal module is not evaluatable"); }; @@ -148,11 +147,11 @@ pub async fn get_evaluate_pool( let runtime_entries = { let globals_module = context.process( - SourceAssetVc::new(embed_file_path("globals.ts")).into(), - Value::new(ReferenceType::Internal(InnerAssetsVc::empty())), + Vc::upcast(SourceAsset::new(embed_file_path("globals.ts".to_string()))), + Value::new(ReferenceType::Internal(InnerAssets::empty())), ); - let Some(globals_module) = EvaluatableAssetVc::resolve_from(globals_module).await? else { + let Some(globals_module) = Vc::try_resolve_sidecast::>(globals_module).await? else { bail!("Internal module is not evaluatable"); }; @@ -163,17 +162,18 @@ pub async fn get_evaluate_pool( } } - EvaluatableAssetsVc::cell(entries) + Vc::::cell(entries) }; - let bootstrap = NodeJsBootstrapAsset { - path, - chunking_context, - entry: entry_module.as_root_chunk(chunking_context), - evaluatable_assets: runtime_entries.with_entry(entry_module), - } - .cell() - .into(); + let bootstrap = Vc::upcast( + NodeJsBootstrapAsset { + path, + chunking_context, + entry: entry_module.as_root_chunk(chunking_context), + evaluatable_assets: runtime_entries.with_entry(entry_module), + } + .cell(), + ); let output_root = chunking_context.output_root(); let emit_package = emit_package_json(output_root); @@ -224,17 +224,17 @@ impl futures_retry::ErrorHandler for PoolErrorHandler { /// evaluated result automatically. #[turbo_tasks::function] pub fn evaluate( - module_asset: AssetVc, - cwd: FileSystemPathVc, - env: ProcessEnvVc, - context_ident_for_issue: AssetIdentVc, - context: AssetContextVc, - chunking_context: ChunkingContextVc, - runtime_entries: Option, - args: Vec, - additional_invalidation: CompletionVc, + module_asset: Vc>, + cwd: Vc, + env: Vc>, + context_ident_for_issue: Vc, + context: Vc>, + chunking_context: Vc>, + runtime_entries: Option>, + args: Vec>, + additional_invalidation: Vc, debug: bool, -) -> JavaScriptEvaluationVc { +) -> Vc { // Note the following code uses some hacks to create a child task that produces // a stream that is returned by this task. @@ -288,17 +288,17 @@ pub fn evaluate( #[turbo_tasks::function] async fn compute_evaluate_stream( - module_asset: AssetVc, - cwd: FileSystemPathVc, - env: ProcessEnvVc, - context_ident_for_issue: AssetIdentVc, - context: AssetContextVc, - chunking_context: ChunkingContextVc, - runtime_entries: Option, - args: Vec, - additional_invalidation: CompletionVc, + module_asset: Vc>, + cwd: Vc, + env: Vc>, + context_ident_for_issue: Vc, + context: Vc>, + chunking_context: Vc>, + runtime_entries: Option>, + args: Vec>, + additional_invalidation: Vc, debug: bool, - sender: JavaScriptStreamSenderVc, + sender: Vc, ) { mark_finished(); let Ok(sender) = sender.await else { @@ -393,10 +393,10 @@ async fn compute_evaluate_stream( /// value/error/end. async fn pull_operation( operation: &mut NodeJsOperation, - cwd: FileSystemPathVc, + cwd: Vc, pool: &NodeJsPool, - context_ident_for_issue: AssetIdentVc, - chunking_context: ChunkingContextVc, + context_ident_for_issue: Vc, + chunking_context: Vc>, ) -> Result { let mut file_dependencies = Vec::new(); let mut dir_dependencies = Vec::new(); @@ -414,7 +414,6 @@ async fn pull_operation( project_dir: chunking_context.context_path().root(), } .cell() - .as_issue() .emit(); // Do not reuse the process in case of error operation.disallow_reuse(); @@ -425,22 +424,21 @@ async fn pull_operation( EvalJavaScriptIncomingMessage::End { data } => break ControlFlow::Break(Ok(data)), EvalJavaScriptIncomingMessage::FileDependency { path } => { // TODO We might miss some changes that happened during execution - file_dependencies.push(cwd.join(&path).read()); + file_dependencies.push(cwd.join(path).read()); } EvalJavaScriptIncomingMessage::BuildDependency { path } => { // TODO We might miss some changes that happened during execution BuildDependencyIssue { context_ident: context_ident_for_issue, - path: cwd.join(&path), + path: cwd.join(path), } .cell() - .as_issue() .emit(); } EvalJavaScriptIncomingMessage::DirDependency { path, glob } => { // TODO We might miss some changes that happened during execution dir_dependencies.push(dir_dependency( - cwd.join(&path).read_glob(GlobVc::new(&glob), false), + cwd.join(path).read_glob(Glob::new(glob), false), )); } EvalJavaScriptIncomingMessage::EmittedError { error, severity } => { @@ -453,7 +451,6 @@ async fn pull_operation( project_dir: chunking_context.context_path().root(), } .cell() - .as_issue() .emit(); } } @@ -475,33 +472,33 @@ async fn pull_operation( /// An issue that occurred while evaluating node code. #[turbo_tasks::value(shared)] pub struct EvaluationIssue { - pub context_ident: AssetIdentVc, + pub context_ident: Vc, pub error: StructuredError, - pub assets_for_source_mapping: AssetsForSourceMappingVc, - pub assets_root: FileSystemPathVc, - pub project_dir: FileSystemPathVc, + pub assets_for_source_mapping: Vc, + pub assets_root: Vc, + pub project_dir: Vc, } #[turbo_tasks::value_impl] impl Issue for EvaluationIssue { #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Error evaluating Node.js code".to_string()) + fn title(&self) -> Vc { + Vc::cell("Error evaluating Node.js code".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("build".to_string()) + fn category(&self) -> Vc { + Vc::cell("build".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context_ident.path() } #[turbo_tasks::function] - async fn description(&self) -> Result { - Ok(StringVc::cell( + async fn description(&self) -> Result> { + Ok(Vc::cell( self.error .print( self.assets_for_source_mapping, @@ -517,35 +514,35 @@ impl Issue for EvaluationIssue { /// An issue that occurred while evaluating node code. #[turbo_tasks::value(shared)] pub struct BuildDependencyIssue { - pub context_ident: AssetIdentVc, - pub path: FileSystemPathVc, + pub context_ident: Vc, + pub path: Vc, } #[turbo_tasks::value_impl] impl Issue for BuildDependencyIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Build dependencies are not yet supported".to_string()) + fn title(&self) -> Vc { + Vc::cell("Build dependencies are not yet supported".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("build".to_string()) + fn category(&self) -> Vc { + Vc::cell("build".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context_ident.path() } #[turbo_tasks::function] - async fn description(&self) -> Result { - Ok(StringVc::cell( + async fn description(&self) -> Result> { + Ok(Vc::cell( format!("The file at {} is a build dependency, which is not yet implemented. Changing this file or any dependency will not be recognized and might require restarting the server", self.path.to_string().await?) )) @@ -555,7 +552,7 @@ Changing this file or any dependency will not be recognized and might require re /// A hack to invalidate when any file in a directory changes. Need to be /// awaited before files are accessed. #[turbo_tasks::function] -async fn dir_dependency(glob: ReadGlobResultVc) -> Result { +async fn dir_dependency(glob: Vc) -> Result> { let shallow = dir_dependency_shallow(glob); let glob = glob.await?; glob.inner @@ -564,11 +561,11 @@ async fn dir_dependency(glob: ReadGlobResultVc) -> Result { .try_join() .await?; shallow.await?; - Ok(CompletionVc::new()) + Ok(Completion::new()) } #[turbo_tasks::function] -async fn dir_dependency_shallow(glob: ReadGlobResultVc) -> Result { +async fn dir_dependency_shallow(glob: Vc) -> Result> { let glob = glob.await?; for item in glob.results.values() { // Reading all files to add itself as dependency @@ -577,7 +574,7 @@ async fn dir_dependency_shallow(glob: ReadGlobResultVc) -> Result file.track().await?; } DirectoryEntry::Directory(dir) => { - dir_dependency(dir.read_glob(GlobVc::new("**"), false)).await?; + dir_dependency(dir.read_glob(Glob::new("**".to_string()), false)).await?; } DirectoryEntry::Symlink(symlink) => { symlink.read_link().await?; @@ -588,44 +585,44 @@ async fn dir_dependency_shallow(glob: ReadGlobResultVc) -> Result DirectoryEntry::Error => {} } } - Ok(CompletionVc::new()) + Ok(Completion::new()) } #[turbo_tasks::value(shared)] pub struct EvaluateEmittedErrorIssue { - pub context: FileSystemPathVc, - pub severity: IssueSeverityVc, + pub context: Vc, + pub severity: Vc, pub error: StructuredError, - pub assets_for_source_mapping: AssetsForSourceMappingVc, - pub assets_root: FileSystemPathVc, - pub project_dir: FileSystemPathVc, + pub assets_for_source_mapping: Vc, + pub assets_root: Vc, + pub project_dir: Vc, } #[turbo_tasks::value_impl] impl Issue for EvaluateEmittedErrorIssue { #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { self.severity } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("loaders".to_string()) + fn category(&self) -> Vc { + Vc::cell("loaders".to_string()) } #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Issue while running loader".to_string()) + fn title(&self) -> Vc { + Vc::cell("Issue while running loader".to_string()) } #[turbo_tasks::function] - async fn description(&self) -> Result { - Ok(StringVc::cell( + async fn description(&self) -> Result> { + Ok(Vc::cell( self.error .print( self.assets_for_source_mapping, diff --git a/crates/turbopack-node/src/execution_context.rs b/crates/turbopack-node/src/execution_context.rs index 120f346eddb7cc..712bc1909f3c19 100644 --- a/crates/turbopack-node/src/execution_context.rs +++ b/crates/turbopack-node/src/execution_context.rs @@ -1,23 +1,24 @@ use anyhow::Result; -use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::chunk::{ChunkingContext, ChunkingContextVc}; +use turbo_tasks::Vc; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::chunk::ChunkingContext; #[turbo_tasks::value] pub struct ExecutionContext { - pub project_path: FileSystemPathVc, - pub chunking_context: ChunkingContextVc, - pub env: ProcessEnvVc, + pub project_path: Vc, + pub chunking_context: Vc>, + pub env: Vc>, } #[turbo_tasks::value_impl] -impl ExecutionContextVc { +impl ExecutionContext { #[turbo_tasks::function] pub fn new( - project_path: FileSystemPathVc, - chunking_context: ChunkingContextVc, - env: ProcessEnvVc, - ) -> Self { + project_path: Vc, + chunking_context: Vc>, + env: Vc>, + ) -> Vc { ExecutionContext { project_path, chunking_context, @@ -27,7 +28,7 @@ impl ExecutionContextVc { } #[turbo_tasks::function] - pub async fn with_layer(self, layer: &str) -> Result { + pub async fn with_layer(self: Vc, layer: String) -> Result> { let this = self.await?; Ok(ExecutionContext { project_path: this.project_path, @@ -38,17 +39,17 @@ impl ExecutionContextVc { } #[turbo_tasks::function] - pub async fn project_path(self) -> Result { + pub async fn project_path(self: Vc) -> Result> { Ok(self.await?.project_path) } #[turbo_tasks::function] - pub async fn chunking_context(self) -> Result { + pub async fn chunking_context(self: Vc) -> Result>> { Ok(self.await?.chunking_context) } #[turbo_tasks::function] - pub async fn env(self) -> Result { + pub async fn env(self: Vc) -> Result>> { Ok(self.await?.env) } } diff --git a/crates/turbopack-node/src/lib.rs b/crates/turbopack-node/src/lib.rs index 6648db9bd7cdb3..4f926f2b588026 100644 --- a/crates/turbopack-node/src/lib.rs +++ b/crates/turbopack-node/src/lib.rs @@ -1,36 +1,30 @@ #![feature(async_closure)] #![feature(min_specialization)] #![feature(lint_reasons)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] #![allow(clippy::too_many_arguments)] use std::{collections::HashMap, iter::once, thread::available_parallelism}; use anyhow::{bail, Result}; use indexmap::IndexSet; -pub use node_entry::{ - NodeEntry, NodeEntryVc, NodeRenderingEntriesVc, NodeRenderingEntry, NodeRenderingEntryVc, -}; +pub use node_entry::{NodeEntry, NodeRenderingEntries, NodeRenderingEntry}; use turbo_tasks::{ graph::{GraphTraversal, ReverseTopological}, - CompletionVc, CompletionsVc, TryJoinIterExt, ValueToString, + Completion, Completions, TryJoinIterExt, ValueToString, Vc, }; -use turbo_tasks_env::{ProcessEnv, ProcessEnvVc}; -use turbo_tasks_fs::{to_sys_path, File, FileContent, FileSystemPathVc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{to_sys_path, File, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetVc, AssetsSetVc}, - chunk::{ - ChunkableAsset, ChunkingContext, ChunkingContextVc, EvaluatableAssetVc, EvaluatableAssetsVc, - }, + asset::{Asset, AssetContent, AssetsSet}, + chunk::{ChunkableAsset, ChunkingContext, EvaluatableAsset, EvaluatableAssets}, reference::primary_referenced_assets, - source_map::GenerateSourceMapVc, - virtual_asset::VirtualAssetVc, + source_map::GenerateSourceMap, + virtual_asset::VirtualAsset, }; -use self::{ - bootstrap::NodeJsBootstrapAsset, - pool::{NodeJsPool, NodeJsPoolVc}, - source_map::StructuredError, -}; +use self::{bootstrap::NodeJsBootstrapAsset, pool::NodeJsPool, source_map::StructuredError}; pub mod bootstrap; pub mod debug; @@ -46,10 +40,10 @@ pub mod transforms; #[turbo_tasks::function] async fn emit( - intermediate_asset: AssetVc, - intermediate_output_path: FileSystemPathVc, -) -> Result { - Ok(CompletionsVc::cell( + intermediate_asset: Vc>, + intermediate_output_path: Vc, +) -> Result> { + Ok(Vc::::cell( internal_assets(intermediate_asset, intermediate_output_path) .strongly_consistent() .await? @@ -65,8 +59,8 @@ async fn emit( #[derive(Debug)] #[turbo_tasks::value] struct SeparatedAssets { - internal_assets: AssetsSetVc, - external_asset_entrypoints: AssetsSetVc, + internal_assets: Vc, + external_asset_entrypoints: Vc, } /// Extracts the subgraph of "internal" assets (assets within the passes @@ -74,9 +68,9 @@ struct SeparatedAssets { /// "internal" subgraph. #[turbo_tasks::function] async fn internal_assets( - intermediate_asset: AssetVc, - intermediate_output_path: FileSystemPathVc, -) -> Result { + intermediate_asset: Vc>, + intermediate_output_path: Vc, +) -> Result> { Ok( separate_assets(intermediate_asset, intermediate_output_path) .strongly_consistent() @@ -86,40 +80,40 @@ async fn internal_assets( } #[turbo_tasks::value(transparent)] -pub struct AssetsForSourceMapping(HashMap); +pub struct AssetsForSourceMapping(HashMap>>); /// Extracts a map of "internal" assets ([`internal_assets`]) which implement /// the [GenerateSourceMap] trait. #[turbo_tasks::function] async fn internal_assets_for_source_mapping( - intermediate_asset: AssetVc, - intermediate_output_path: FileSystemPathVc, -) -> Result { + intermediate_asset: Vc>, + intermediate_output_path: Vc, +) -> Result> { let internal_assets = internal_assets(intermediate_asset, intermediate_output_path).await?; let intermediate_output_path = &*intermediate_output_path.await?; let mut internal_assets_for_source_mapping = HashMap::new(); for asset in internal_assets.iter() { - if let Some(generate_source_map) = GenerateSourceMapVc::resolve_from(asset).await? { + if let Some(generate_source_map) = + Vc::try_resolve_sidecast::>(*asset).await? + { if let Some(path) = intermediate_output_path.get_path_to(&*asset.ident().path().await?) { internal_assets_for_source_mapping.insert(path.to_string(), generate_source_map); } } } - Ok(AssetsForSourceMappingVc::cell( - internal_assets_for_source_mapping, - )) + Ok(Vc::cell(internal_assets_for_source_mapping)) } /// Returns a set of "external" assets on the boundary of the "internal" /// subgraph #[turbo_tasks::function] pub async fn external_asset_entrypoints( - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, -) -> Result { + module: Vc>, + runtime_entries: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, +) -> Result> { Ok(separate_assets( get_intermediate_asset(chunking_context, module, runtime_entries) .resolve() @@ -135,14 +129,14 @@ pub async fn external_asset_entrypoints( /// assets. #[turbo_tasks::function] async fn separate_assets( - intermediate_asset: AssetVc, - intermediate_output_path: FileSystemPathVc, -) -> Result { + intermediate_asset: Vc>, + intermediate_output_path: Vc, +) -> Result> { let intermediate_output_path = &*intermediate_output_path.await?; #[derive(PartialEq, Eq, Hash, Clone, Copy)] enum Type { - Internal(AssetVc), - External(AssetVc), + Internal(Vc>), + External(Vc>), } let get_asset_children = |asset| async move { let Type::Internal(asset) = asset else { @@ -160,7 +154,7 @@ async fn separate_assets( .ident() .path() .await? - .is_inside(intermediate_output_path) + .is_inside_ref(intermediate_output_path) { Ok(Type::Internal(*asset)) } else { @@ -193,8 +187,8 @@ async fn separate_assets( } Ok(SeparatedAssets { - internal_assets: AssetsSetVc::cell(internal_assets), - external_asset_entrypoints: AssetsSetVc::cell(external_asset_entrypoints), + internal_assets: Vc::cell(internal_assets), + external_asset_entrypoints: Vc::cell(external_asset_entrypoints), } .cell()) } @@ -202,13 +196,12 @@ async fn separate_assets( /// Emit a basic package.json that sets the type of the package to commonjs. /// Currently code generated for Node is CommonJS, while authored code may be /// ESM, for example. -pub(self) fn emit_package_json(dir: FileSystemPathVc) -> CompletionVc { +pub(self) fn emit_package_json(dir: Vc) -> Vc { emit( - VirtualAssetVc::new( - dir.join("package.json"), - FileContent::Content(File::from("{\"type\": \"commonjs\"}")).into(), - ) - .into(), + Vc::upcast(VirtualAsset::new( + dir.join("package.json".to_string()), + AssetContent::file(File::from("{\"type\": \"commonjs\"}").into()), + )), dir, ) } @@ -216,14 +209,14 @@ pub(self) fn emit_package_json(dir: FileSystemPathVc) -> CompletionVc { /// Creates a node.js renderer pool for an entrypoint. #[turbo_tasks::function] pub async fn get_renderer_pool( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - intermediate_asset: AssetVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, + cwd: Vc, + env: Vc>, + intermediate_asset: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, debug: bool, -) -> Result { +) -> Result> { emit_package_json(intermediate_output_path).await?; let emit = emit(intermediate_asset, output_root); @@ -260,18 +253,19 @@ pub async fn get_renderer_pool( /// Converts a module graph into node.js executable assets #[turbo_tasks::function] pub async fn get_intermediate_asset( - chunking_context: ChunkingContextVc, - main_entry: EvaluatableAssetVc, - other_entries: EvaluatableAssetsVc, -) -> Result { - Ok(NodeJsBootstrapAsset { - path: chunking_context.chunk_path(main_entry.ident(), ".js"), - chunking_context, - entry: main_entry.as_root_chunk(chunking_context), - evaluatable_assets: other_entries.with_entry(main_entry), - } - .cell() - .into()) + chunking_context: Vc>, + main_entry: Vc>, + other_entries: Vc, +) -> Result>> { + Ok(Vc::upcast( + NodeJsBootstrapAsset { + path: chunking_context.chunk_path(main_entry.ident(), ".js".to_string()), + chunking_context, + entry: main_entry.as_root_chunk(chunking_context), + evaluatable_assets: other_entries.with_entry(main_entry), + } + .cell(), + )) } #[derive(Clone, Debug)] diff --git a/crates/turbopack-node/src/node_entry.rs b/crates/turbopack-node/src/node_entry.rs index ba3579c0a59598..3faabc33f609c8 100644 --- a/crates/turbopack-node/src/node_entry.rs +++ b/crates/turbopack-node/src/node_entry.rs @@ -1,27 +1,26 @@ -use anyhow::Result; -use turbo_tasks::Value; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::chunk::{ChunkingContextVc, EvaluatableAssetVc, EvaluatableAssetsVc}; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::chunk::{ChunkingContext, EvaluatableAsset, EvaluatableAssets}; use turbopack_dev_server::source::ContentSourceData; #[turbo_tasks::value(shared)] pub struct NodeRenderingEntry { - pub runtime_entries: EvaluatableAssetsVc, - pub module: EvaluatableAssetVc, - pub chunking_context: ChunkingContextVc, - pub intermediate_output_path: FileSystemPathVc, - pub output_root: FileSystemPathVc, - pub project_dir: FileSystemPathVc, + pub runtime_entries: Vc, + pub module: Vc>, + pub chunking_context: Vc>, + pub intermediate_output_path: Vc, + pub output_root: Vc, + pub project_dir: Vc, } #[turbo_tasks::value(transparent)] -pub struct NodeRenderingEntries(Vec); +pub struct NodeRenderingEntries(Vec>); /// Trait that allows to get the entry module for rendering something in Node.js #[turbo_tasks::value_trait] pub trait NodeEntry { - fn entry(&self, data: Value) -> NodeRenderingEntryVc; - fn entries(&self) -> NodeRenderingEntriesVc { - NodeRenderingEntriesVc::cell(vec![self.entry(Value::new(Default::default()))]) + fn entry(self: Vc, data: Value) -> Vc; + fn entries(self: Vc) -> Vc { + Vc::cell(vec![self.entry(Value::new(Default::default()))]) } } diff --git a/crates/turbopack-node/src/pool.rs b/crates/turbopack-node/src/pool.rs index 90ebe06180e51c..d6f9651e380002 100644 --- a/crates/turbopack-node/src/pool.rs +++ b/crates/turbopack-node/src/pool.rs @@ -26,10 +26,11 @@ use tokio::{ sync::{OwnedSemaphorePermit, Semaphore}, time::{sleep, timeout}, }; -use turbo_tasks_fs::{json::parse_json_with_source_context, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{json::parse_json_with_source_context, FileSystemPath}; use turbopack_ecmascript::magic_identifier::unmangle_identifiers; -use crate::{source_map::apply_source_mapping, AssetsForSourceMappingVc}; +use crate::{source_map::apply_source_mapping, AssetsForSourceMapping}; #[derive(Clone, Copy)] pub enum FormattingMode { @@ -72,9 +73,9 @@ enum NodeJsPoolProcess { struct SpawnedNodeJsPoolProcess { child: Child, listener: TcpListener, - assets_for_source_mapping: AssetsForSourceMappingVc, - assets_root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + assets_root: Vc, + project_dir: Vc, shared_stdout: SharedOutputSet, shared_stderr: SharedOutputSet, debug: bool, @@ -83,9 +84,9 @@ struct SpawnedNodeJsPoolProcess { struct RunningNodeJsPoolProcess { child: Option, connection: TcpStream, - assets_for_source_mapping: AssetsForSourceMappingVc, - assets_root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + assets_root: Vc, + project_dir: Vc, stdout_handler: OutputStreamHandler, stderr_handler: OutputStreamHandler, debug: bool, @@ -141,9 +142,9 @@ static MARKER_STR: &str = "TURBOPACK_OUTPUT_"; struct OutputStreamHandler { stream: BufReader, shared: SharedOutputSet, - assets_for_source_mapping: AssetsForSourceMappingVc, - root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + root: Vc, + project_dir: Vc, final_stream: W, } @@ -179,9 +180,9 @@ impl OutputStreamHandler { async fn write_source_mapped_final( bytes: &[u8], - assets_for_source_mapping: AssetsForSourceMappingVc, - root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + root: Vc, + project_dir: Vc, final_stream: &mut W, ) -> Result<()> { if let Ok(text) = std::str::from_utf8(bytes) { @@ -326,9 +327,9 @@ impl NodeJsPoolProcess { cwd: &Path, env: &HashMap, entrypoint: &Path, - assets_for_source_mapping: AssetsForSourceMappingVc, - assets_root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + assets_root: Vc, + project_dir: Vc, shared_stdout: SharedOutputSet, shared_stderr: SharedOutputSet, debug: bool, @@ -549,9 +550,9 @@ pub struct NodeJsPool { cwd: PathBuf, entrypoint: PathBuf, env: HashMap, - pub assets_for_source_mapping: AssetsForSourceMappingVc, - pub assets_root: FileSystemPathVc, - pub project_dir: FileSystemPathVc, + pub assets_for_source_mapping: Vc, + pub assets_root: Vc, + pub project_dir: Vc, #[turbo_tasks(trace_ignore, debug_ignore)] processes: Arc>>, #[turbo_tasks(trace_ignore, debug_ignore)] @@ -570,9 +571,9 @@ impl NodeJsPool { cwd: PathBuf, entrypoint: PathBuf, env: HashMap, - assets_for_source_mapping: AssetsForSourceMappingVc, - assets_root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + assets_root: Vc, + project_dir: Vc, concurrency: usize, debug: bool, ) -> Self { diff --git a/crates/turbopack-node/src/render/error_page.rs b/crates/turbopack-node/src/render/error_page.rs index 48339cdd22ea36..05567b8363f34a 100644 --- a/crates/turbopack-node/src/render/error_page.rs +++ b/crates/turbopack-node/src/render/error_page.rs @@ -1,5 +1,5 @@ use anyhow::{Context, Result}; -use turbo_tasks::primitives::StringVc; +use turbo_tasks::Vc; use turbo_tasks_fs::embed_file; #[turbo_tasks::function] @@ -7,10 +7,10 @@ pub(super) async fn error_html( status_code: u16, title: String, details: String, -) -> Result { +) -> Result> { let html = create_html(status_code, title, details).await?; - Ok(StringVc::cell(html)) + Ok(Vc::cell(html)) } #[turbo_tasks::function] @@ -18,13 +18,13 @@ pub(super) async fn error_html_body( status_code: u16, title: String, details: String, -) -> Result { +) -> Result> { let html = create_html(status_code, title, details).await?; let (_, body) = html.split_once("").context("no body in html")?; let (body, _) = body.split_once("").context("no body in html")?; - Ok(StringVc::cell(body.to_string())) + Ok(Vc::cell(body.to_string())) } async fn create_html(status_code: u16, title: String, details: String) -> Result { diff --git a/crates/turbopack-node/src/render/issue.rs b/crates/turbopack-node/src/render/issue.rs index 6e234755df9f2b..4c9cd5f46ec551 100644 --- a/crates/turbopack-node/src/render/issue.rs +++ b/crates/turbopack-node/src/render/issue.rs @@ -1,40 +1,40 @@ use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::FileSystemPathVc; -use turbopack_core::issue::{Issue, IssueVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; +use turbopack_core::issue::Issue; #[turbo_tasks::value(shared)] #[derive(Copy, Clone)] pub struct RenderingIssue { - pub context: FileSystemPathVc, - pub message: StringVc, + pub context: Vc, + pub message: Vc, pub status: Option, } #[turbo_tasks::value_impl] impl Issue for RenderingIssue { #[turbo_tasks::function] - fn title(&self) -> StringVc { - StringVc::cell("Error during SSR Rendering".to_string()) + fn title(&self) -> Vc { + Vc::cell("Error during SSR Rendering".to_string()) } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("rendering".to_string()) + fn category(&self) -> Vc { + Vc::cell("rendering".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.message } #[turbo_tasks::function] - async fn detail(&self) -> Result { + async fn detail(&self) -> Result> { let mut details = vec![]; if let Some(status) = self.status { @@ -43,7 +43,7 @@ impl Issue for RenderingIssue { } } - Ok(StringVc::cell(details.join("\n"))) + Ok(Vc::cell(details.join("\n"))) } // TODO parse stack trace into source location diff --git a/crates/turbopack-node/src/render/mod.rs b/crates/turbopack-node/src/render/mod.rs index 2b72d7f6475ef1..1ccc03f3c09551 100644 --- a/crates/turbopack-node/src/render/mod.rs +++ b/crates/turbopack-node/src/render/mod.rs @@ -1,6 +1,7 @@ use indexmap::IndexMap; use serde::{Deserialize, Serialize}; -use turbo_tasks::primitives::JsonValueReadRef; +use serde_json::Value as JsonValue; +use turbo_tasks::ReadRef; use crate::{route_matcher::Param, ResponseHeaders, StructuredError}; @@ -21,7 +22,7 @@ pub struct RenderData { raw_query: String, raw_headers: Vec<(String, String)>, path: String, - data: Option, + data: Option>, } #[derive(Serialize)] diff --git a/crates/turbopack-node/src/render/node_api_source.rs b/crates/turbopack-node/src/render/node_api_source.rs index f4ff8536ac6602..60dedda1276e27 100644 --- a/crates/turbopack-node/src/render/node_api_source.rs +++ b/crates/turbopack-node/src/render/node_api_source.rs @@ -1,53 +1,47 @@ use anyhow::{anyhow, Result}; use indexmap::IndexSet; -use turbo_tasks::{ - primitives::{JsonValueVc, StringVc}, - Value, -}; -use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::FileSystemPathVc; +use serde_json::Value as JsonValue; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::introspect::{ - asset::IntrospectableAssetVc, Introspectable, IntrospectableChildrenVc, IntrospectableVc, + asset::IntrospectableAsset, Introspectable, IntrospectableChildren, }; use turbopack_dev_server::source::{ - specificity::SpecificityVc, ContentSource, ContentSourceContent, ContentSourceContentVc, - ContentSourceData, ContentSourceDataVary, ContentSourceDataVaryVc, ContentSourceResult, - ContentSourceResultVc, ContentSourceVc, GetContentSourceContent, GetContentSourceContentVc, + specificity::Specificity, ContentSource, ContentSourceContent, ContentSourceData, + ContentSourceDataVary, ContentSourceResult, GetContentSourceContent, }; use super::{render_proxy::render_proxy, RenderData}; -use crate::{ - get_intermediate_asset, - node_entry::{NodeEntry, NodeEntryVc}, - route_matcher::{RouteMatcher, RouteMatcherVc}, -}; +use crate::{get_intermediate_asset, node_entry::NodeEntry, route_matcher::RouteMatcher}; /// Creates a [NodeApiContentSource]. #[turbo_tasks::function] pub fn create_node_api_source( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - specificity: SpecificityVc, - server_root: FileSystemPathVc, - route_match: RouteMatcherVc, - pathname: StringVc, - entry: NodeEntryVc, - render_data: JsonValueVc, + cwd: Vc, + env: Vc>, + specificity: Vc, + server_root: Vc, + route_match: Vc>, + pathname: Vc, + entry: Vc>, + render_data: Vc, debug: bool, -) -> ContentSourceVc { - NodeApiContentSource { - cwd, - env, - specificity, - server_root, - pathname, - route_match, - entry, - render_data, - debug, - } - .cell() - .into() +) -> Vc> { + Vc::upcast( + NodeApiContentSource { + cwd, + env, + specificity, + server_root, + pathname, + route_match, + entry, + render_data, + debug, + } + .cell(), + ) } /// A content source that proxies API requests to one-off Node.js @@ -58,21 +52,21 @@ pub fn create_node_api_source( /// to this directory. #[turbo_tasks::value] pub struct NodeApiContentSource { - cwd: FileSystemPathVc, - env: ProcessEnvVc, - specificity: SpecificityVc, - server_root: FileSystemPathVc, - pathname: StringVc, - route_match: RouteMatcherVc, - entry: NodeEntryVc, - render_data: JsonValueVc, + cwd: Vc, + env: Vc>, + specificity: Vc, + server_root: Vc, + pathname: Vc, + route_match: Vc>, + entry: Vc>, + render_data: Vc, debug: bool, } #[turbo_tasks::value_impl] -impl NodeApiContentSourceVc { +impl NodeApiContentSource { #[turbo_tasks::function] - pub async fn get_pathname(self) -> Result { + pub async fn get_pathname(self: Vc) -> Result> { Ok(self.await?.pathname) } } @@ -81,33 +75,34 @@ impl NodeApiContentSourceVc { impl ContentSource for NodeApiContentSource { #[turbo_tasks::function] async fn get( - self_vc: NodeApiContentSourceVc, - path: &str, + self: Vc, + path: String, _data: turbo_tasks::Value, - ) -> Result { - let this = self_vc.await?; - if *this.route_match.matches(path).await? { + ) -> Result> { + let this = self.await?; + if *this.route_match.matches(path.clone()).await? { return Ok(ContentSourceResult::Result { specificity: this.specificity, - get_content: NodeApiGetContentResult { - source: self_vc, - render_data: this.render_data, - path: path.to_string(), - debug: this.debug, - } - .cell() - .into(), + get_content: Vc::upcast( + NodeApiGetContentResult { + source: self, + render_data: this.render_data, + path: path.to_string(), + debug: this.debug, + } + .cell(), + ), } .cell()); } - Ok(ContentSourceResultVc::not_found()) + Ok(ContentSourceResult::not_found()) } } #[turbo_tasks::value] struct NodeApiGetContentResult { - source: NodeApiContentSourceVc, - render_data: JsonValueVc, + source: Vc, + render_data: Vc, path: String, debug: bool, } @@ -115,7 +110,7 @@ struct NodeApiGetContentResult { #[turbo_tasks::value_impl] impl GetContentSourceContent for NodeApiGetContentResult { #[turbo_tasks::function] - fn vary(&self) -> ContentSourceDataVaryVc { + fn vary(&self) -> Vc { ContentSourceDataVary { method: true, url: true, @@ -130,9 +125,9 @@ impl GetContentSourceContent for NodeApiGetContentResult { } #[turbo_tasks::function] - async fn get(&self, data: Value) -> Result { + async fn get(&self, data: Value) -> Result> { let source = self.source.await?; - let Some(params) = &*source.route_match.params(&self.path).await? else { + let Some(params) = &*source.route_match.params(self.path.clone()).await? else { return Err(anyhow!("Non matching path provided")); }; let ContentSourceData { @@ -150,7 +145,7 @@ impl GetContentSourceContent for NodeApiGetContentResult { Ok(ContentSourceContent::HttpProxy(render_proxy( source.cwd, source.env, - source.server_root.join(&self.path), + source.server_root.join(self.path.clone()), entry.module, entry.runtime_entries, entry.chunking_context, @@ -176,48 +171,48 @@ impl GetContentSourceContent for NodeApiGetContentResult { } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("node api content source".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("node api content source".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for NodeApiContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { self.pathname } #[turbo_tasks::function] - async fn details(&self) -> Result { - Ok(StringVc::cell(format!( + async fn details(&self) -> Result> { + Ok(Vc::cell(format!( "Specificity: {}", self.specificity.await? ))) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let mut set = IndexSet::new(); for &entry in self.entry.entries().await?.iter() { let entry = entry.await?; set.insert(( - StringVc::cell("module".to_string()), - IntrospectableAssetVc::new(entry.module.into()), + Vc::cell("module".to_string()), + IntrospectableAsset::new(Vc::upcast(entry.module)), )); set.insert(( - StringVc::cell("intermediate asset".to_string()), - IntrospectableAssetVc::new(get_intermediate_asset( + Vc::cell("intermediate asset".to_string()), + IntrospectableAsset::new(get_intermediate_asset( entry.chunking_context, entry.module, entry.runtime_entries, )), )); } - Ok(IntrospectableChildrenVc::cell(set)) + Ok(Vc::cell(set)) } } diff --git a/crates/turbopack-node/src/render/render_proxy.rs b/crates/turbopack-node/src/render/render_proxy.rs index 5973a8146e172e..cd8fb1b988a9f4 100644 --- a/crates/turbopack-node/src/render/render_proxy.rs +++ b/crates/turbopack-node/src/render/render_proxy.rs @@ -5,21 +5,20 @@ use futures::{ pin_mut, SinkExt, StreamExt, TryStreamExt, }; use parking_lot::Mutex; -use turbo_tasks::{ - duration_span, mark_finished, primitives::StringVc, util::SharedError, RawVc, ValueToString, -}; +use turbo_tasks::{duration_span, mark_finished, util::SharedError, RawVc, ValueToString, Vc}; use turbo_tasks_bytes::{Bytes, Stream}; -use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ asset::Asset, - chunk::{ChunkingContextVc, EvaluatableAssetVc, EvaluatableAssetsVc}, + chunk::{ChunkingContext, EvaluatableAsset, EvaluatableAssets}, error::PrettyPrintError, + issue::IssueExt, }; -use turbopack_dev_server::source::{Body, BodyVc, ProxyResult, ProxyResultVc}; +use turbopack_dev_server::source::{Body, ProxyResult}; use super::{ - issue::RenderingIssue, RenderDataVc, RenderProxyIncomingMessage, RenderProxyOutgoingMessage, + issue::RenderingIssue, RenderData, RenderProxyIncomingMessage, RenderProxyOutgoingMessage, ResponseHeaders, }; use crate::{ @@ -30,19 +29,19 @@ use crate::{ /// Renders a module as static HTML in a node.js process. #[turbo_tasks::function] pub async fn render_proxy( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - path: FileSystemPathVc, - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, - data: RenderDataVc, - body: BodyVc, + cwd: Vc, + env: Vc>, + path: Vc, + module: Vc>, + runtime_entries: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, + data: Vc, + body: Vc, debug: bool, -) -> Result { +) -> Result> { let render = render_stream( cwd, env, @@ -91,7 +90,7 @@ pub async fn render_proxy( } async fn proxy_error( - path: FileSystemPathVc, + path: Vc, error: anyhow::Error, operation: Option, ) -> Result<(u16, String)> { @@ -118,11 +117,10 @@ async fn proxy_error( RenderingIssue { context: path, - message: StringVc::cell(message), + message: Vc::cell(message), status: status.and_then(|status| status.code()), } .cell() - .as_issue() .emit(); Ok((status_code, body)) @@ -148,19 +146,19 @@ struct RenderStream(#[turbo_tasks(trace_ignore)] Stream); #[turbo_tasks::function] fn render_stream( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - path: FileSystemPathVc, - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, - data: RenderDataVc, - body: BodyVc, + cwd: Vc, + env: Vc>, + path: Vc, + module: Vc>, + runtime_entries: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, + data: Vc, + body: Vc, debug: bool, -) -> RenderStreamVc { +) -> Vc { // Note the following code uses some hacks to create a child task that produces // a stream that is returned by this task. @@ -210,18 +208,18 @@ fn render_stream( #[turbo_tasks::function] async fn render_stream_internal( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - path: FileSystemPathVc, - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, - data: RenderDataVc, - body: BodyVc, - sender: RenderStreamSenderVc, + cwd: Vc, + env: Vc>, + path: Vc, + module: Vc>, + runtime_entries: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, + data: Vc, + body: Vc, + sender: Vc, debug: bool, ) { mark_finished(); diff --git a/crates/turbopack-node/src/render/render_static.rs b/crates/turbopack-node/src/render/render_static.rs index 2cc151ab7f20be..cbd2674cdee658 100644 --- a/crates/turbopack-node/src/render/render_static.rs +++ b/crates/turbopack-node/src/render/render_static.rs @@ -5,24 +5,23 @@ use futures::{ pin_mut, SinkExt, StreamExt, TryStreamExt, }; use parking_lot::Mutex; -use turbo_tasks::{ - duration_span, mark_finished, primitives::StringVc, util::SharedError, RawVc, ValueToString, -}; +use turbo_tasks::{duration_span, mark_finished, util::SharedError, RawVc, ValueToString, Vc}; use turbo_tasks_bytes::{Bytes, Stream}; -use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::{File, FileContent, FileSystemPathVc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::{File, FileSystemPath}; use turbopack_core::{ - asset::{Asset, AssetContentVc}, - chunk::{ChunkingContextVc, EvaluatableAssetVc, EvaluatableAssetsVc}, + asset::{Asset, AssetContent}, + chunk::{ChunkingContext, EvaluatableAsset, EvaluatableAssets}, error::PrettyPrintError, + issue::IssueExt, }; use turbopack_dev_server::{ - html::DevHtmlAssetVc, - source::{Body, HeaderListVc, RewriteBuilder, RewriteVc}, + html::DevHtmlAsset, + source::{Body, HeaderList, Rewrite, RewriteBuilder}, }; use super::{ - issue::RenderingIssue, RenderDataVc, RenderStaticIncomingMessage, RenderStaticOutgoingMessage, + issue::RenderingIssue, RenderData, RenderStaticIncomingMessage, RenderStaticOutgoingMessage, }; use crate::{ get_intermediate_asset, get_renderer_pool, pool::NodeJsOperation, @@ -33,22 +32,26 @@ use crate::{ #[turbo_tasks::value] pub enum StaticResult { Content { - content: AssetContentVc, + content: Vc, status_code: u16, - headers: HeaderListVc, + headers: Vc, }, StreamedContent { status: u16, - headers: HeaderListVc, + headers: Vc, body: Body, }, - Rewrite(RewriteVc), + Rewrite(Vc), } #[turbo_tasks::value_impl] -impl StaticResultVc { +impl StaticResult { #[turbo_tasks::function] - pub fn content(content: AssetContentVc, status_code: u16, headers: HeaderListVc) -> Self { + pub fn content( + content: Vc, + status_code: u16, + headers: Vc, + ) -> Vc { StaticResult::Content { content, status_code, @@ -58,7 +61,7 @@ impl StaticResultVc { } #[turbo_tasks::function] - pub fn rewrite(rewrite: RewriteVc) -> Self { + pub fn rewrite(rewrite: Vc) -> Vc { StaticResult::Rewrite(rewrite).cell() } } @@ -66,19 +69,19 @@ impl StaticResultVc { /// Renders a module as static HTML in a node.js process. #[turbo_tasks::function] pub async fn render_static( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - path: FileSystemPathVc, - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - fallback_page: DevHtmlAssetVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, - data: RenderDataVc, + cwd: Vc, + env: Vc>, + path: Vc, + module: Vc>, + runtime_entries: Vc, + fallback_page: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, + data: Vc, debug: bool, -) -> Result { +) -> Result> { let render = render_stream( cwd, env, @@ -118,7 +121,7 @@ pub async fn render_static( }); StaticResult::StreamedContent { status: data.status, - headers: HeaderListVc::cell(data.headers), + headers: Vc::cell(data.headers), body: Body::from_stream(body), } .cell() @@ -128,11 +131,11 @@ pub async fn render_static( } async fn static_error( - path: FileSystemPathVc, + path: Vc, error: anyhow::Error, operation: Option, - fallback_page: DevHtmlAssetVc, -) -> Result { + fallback_page: Vc, +) -> Result> { let status = match operation { Some(operation) => Some(operation.wait_or_kill().await?), None => None, @@ -161,11 +164,11 @@ async fn static_error( let issue = RenderingIssue { context: path, - message: StringVc::cell(error), + message: Vc::cell(error), status: status.and_then(|status| status.code()), }; - issue.cell().as_issue().emit(); + issue.cell().emit(); let html = fallback_page.with_body(body); @@ -175,7 +178,7 @@ async fn static_error( #[derive(Clone, Debug)] #[turbo_tasks::value] enum RenderItem { - Response(StaticResultVc), + Response(Vc), Headers(ResponseHeaders), BodyChunk(Bytes), } @@ -193,19 +196,19 @@ struct RenderStream(#[turbo_tasks(trace_ignore)] Stream); #[turbo_tasks::function] fn render_stream( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - path: FileSystemPathVc, - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - fallback_page: DevHtmlAssetVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, - data: RenderDataVc, + cwd: Vc, + env: Vc>, + path: Vc, + module: Vc>, + runtime_entries: Vc, + fallback_page: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, + data: Vc, debug: bool, -) -> RenderStreamVc { +) -> Vc { // Note the following code uses some hacks to create a child task that produces // a stream that is returned by this task. @@ -255,18 +258,18 @@ fn render_stream( #[turbo_tasks::function] async fn render_stream_internal( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - path: FileSystemPathVc, - module: EvaluatableAssetVc, - runtime_entries: EvaluatableAssetsVc, - fallback_page: DevHtmlAssetVc, - chunking_context: ChunkingContextVc, - intermediate_output_path: FileSystemPathVc, - output_root: FileSystemPathVc, - project_dir: FileSystemPathVc, - data: RenderDataVc, - sender: RenderStreamSenderVc, + cwd: Vc, + env: Vc>, + path: Vc, + module: Vc>, + runtime_entries: Vc, + fallback_page: Vc, + chunking_context: Vc>, + intermediate_output_path: Vc, + output_root: Vc, + project_dir: Vc, + data: Vc, + sender: Vc, debug: bool, ) { mark_finished(); @@ -309,7 +312,7 @@ async fn render_stream_internal( RenderStaticIncomingMessage::Headers { data } => yield RenderItem::Headers(data), RenderStaticIncomingMessage::Rewrite { path } => { drop(guard); - yield RenderItem::Response(StaticResultVc::rewrite(RewriteBuilder::new(path).build())); + yield RenderItem::Response(StaticResult::rewrite(RewriteBuilder::new(path).build())); return; } RenderStaticIncomingMessage::Response { @@ -318,10 +321,10 @@ async fn render_stream_internal( body, } => { drop(guard); - yield RenderItem::Response(StaticResultVc::content( - FileContent::Content(File::from(body)).into(), + yield RenderItem::Response(StaticResult::content( + AssetContent::file(File::from(body).into()), status_code, - HeaderListVc::cell(headers), + Vc::cell(headers), )); return; } @@ -337,10 +340,10 @@ async fn render_stream_internal( ) .await?; yield RenderItem::Response( - StaticResultVc::content( + StaticResult::content( static_error(path, anyhow!(trace), Some(operation), fallback_page).await?, 500, - HeaderListVc::empty(), + HeaderList::empty(), ) ); return; diff --git a/crates/turbopack-node/src/render/rendered_source.rs b/crates/turbopack-node/src/render/rendered_source.rs index fd918ed6b27205..44f56aaccf8160 100644 --- a/crates/turbopack-node/src/render/rendered_source.rs +++ b/crates/turbopack-node/src/render/rendered_source.rs @@ -1,30 +1,26 @@ use anyhow::{anyhow, Result}; use indexmap::IndexSet; -use turbo_tasks::{ - primitives::{JsonValueVc, StringVc}, - Value, -}; -use turbo_tasks_env::ProcessEnvVc; -use turbo_tasks_fs::FileSystemPathVc; +use serde_json::Value as JsonValue; +use turbo_tasks::{Value, Vc}; +use turbo_tasks_env::ProcessEnv; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetsSetVc}, - introspect::{ - asset::IntrospectableAssetVc, Introspectable, IntrospectableChildrenVc, IntrospectableVc, - }, + asset::Asset, + introspect::{asset::IntrospectableAsset, Introspectable, IntrospectableChildren}, issue::IssueContextExt, reference::AssetReference, resolve::PrimaryResolveResult, + version::VersionedContentExt, }; use turbopack_dev_server::{ - html::DevHtmlAssetVc, + html::DevHtmlAsset, source::{ - asset_graph::AssetGraphContentSourceVc, - conditional::ConditionalContentSourceVc, - lazy_instantiated::{GetContentSource, GetContentSourceVc, LazyInstantiatedContentSource}, - specificity::SpecificityVc, - ContentSource, ContentSourceContent, ContentSourceContentVc, ContentSourceData, - ContentSourceDataVary, ContentSourceDataVaryVc, ContentSourceResult, ContentSourceResultVc, - ContentSourceVc, GetContentSourceContent, GetContentSourceContentVc, ProxyResult, + asset_graph::AssetGraphContentSource, + conditional::ConditionalContentSource, + lazy_instantiated::{GetContentSource, LazyInstantiatedContentSource}, + specificity::Specificity, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary, + ContentSourceResult, GetContentSourceContent, ProxyResult, }, }; @@ -33,9 +29,8 @@ use super::{ RenderData, }; use crate::{ - external_asset_entrypoints, get_intermediate_asset, - node_entry::{NodeEntry, NodeEntryVc}, - route_matcher::{RouteMatcher, RouteMatcherVc}, + external_asset_entrypoints, get_intermediate_asset, node_entry::NodeEntry, + route_matcher::RouteMatcher, }; /// Creates a content source that renders something in Node.js with the passed @@ -46,17 +41,17 @@ use crate::{ /// to this directory. #[turbo_tasks::function] pub fn create_node_rendered_source( - cwd: FileSystemPathVc, - env: ProcessEnvVc, - specificity: SpecificityVc, - server_root: FileSystemPathVc, - route_match: RouteMatcherVc, - pathname: StringVc, - entry: NodeEntryVc, - fallback_page: DevHtmlAssetVc, - render_data: JsonValueVc, + cwd: Vc, + env: Vc>, + specificity: Vc, + server_root: Vc, + route_match: Vc>, + pathname: Vc, + entry: Vc>, + fallback_page: Vc, + render_data: Vc, debug: bool, -) -> ContentSourceVc { +) -> Vc> { let source = NodeRenderContentSource { cwd, env, @@ -70,36 +65,36 @@ pub fn create_node_rendered_source( debug, } .cell(); - ConditionalContentSourceVc::new( - source.into(), - LazyInstantiatedContentSource { - get_source: source.as_get_content_source(), - } - .cell() - .into(), - ) - .into() + Vc::upcast(ConditionalContentSource::new( + Vc::upcast(source), + Vc::upcast( + LazyInstantiatedContentSource { + get_source: Vc::upcast(source), + } + .cell(), + ), + )) } /// see [create_node_rendered_source] #[turbo_tasks::value] pub struct NodeRenderContentSource { - cwd: FileSystemPathVc, - env: ProcessEnvVc, - specificity: SpecificityVc, - server_root: FileSystemPathVc, - route_match: RouteMatcherVc, - pathname: StringVc, - entry: NodeEntryVc, - fallback_page: DevHtmlAssetVc, - render_data: JsonValueVc, + cwd: Vc, + env: Vc>, + specificity: Vc, + server_root: Vc, + route_match: Vc>, + pathname: Vc, + entry: Vc>, + fallback_page: Vc, + render_data: Vc, debug: bool, } #[turbo_tasks::value_impl] -impl NodeRenderContentSourceVc { +impl NodeRenderContentSource { #[turbo_tasks::function] - pub async fn get_pathname(self) -> Result { + pub async fn get_pathname(self: Vc) -> Result> { Ok(self.await?.pathname) } } @@ -109,7 +104,7 @@ impl GetContentSource for NodeRenderContentSource { /// Returns the [ContentSource] that serves all referenced external /// assets. This is wrapped into [LazyInstantiatedContentSource]. #[turbo_tasks::function] - async fn content_source(&self) -> Result { + async fn content_source(&self) -> Result>> { let entries = self.entry.entries(); let mut set = IndexSet::new(); for reference in self.fallback_page.references().await?.iter() { @@ -142,10 +137,10 @@ impl GetContentSource for NodeRenderContentSource { .copied(), ) } - Ok( - AssetGraphContentSourceVc::new_lazy_multiple(self.server_root, AssetsSetVc::cell(set)) - .into(), - ) + Ok(Vc::upcast(AssetGraphContentSource::new_lazy_multiple( + self.server_root, + Vc::cell(set), + ))) } } @@ -153,33 +148,34 @@ impl GetContentSource for NodeRenderContentSource { impl ContentSource for NodeRenderContentSource { #[turbo_tasks::function] async fn get( - self_vc: NodeRenderContentSourceVc, - path: &str, + self: Vc, + path: String, _data: turbo_tasks::Value, - ) -> Result { - let this = self_vc.await?; - if *this.route_match.matches(path).await? { + ) -> Result> { + let this = self.await?; + if *this.route_match.matches(path.clone()).await? { return Ok(ContentSourceResult::Result { specificity: this.specificity, - get_content: NodeRenderGetContentResult { - source: self_vc, - render_data: this.render_data, - path: path.to_string(), - debug: this.debug, - } - .cell() - .into(), + get_content: Vc::upcast( + NodeRenderGetContentResult { + source: self, + render_data: this.render_data, + path: path.to_string(), + debug: this.debug, + } + .cell(), + ), } .cell()); } - Ok(ContentSourceResultVc::not_found()) + Ok(ContentSourceResult::not_found()) } } #[turbo_tasks::value] struct NodeRenderGetContentResult { - source: NodeRenderContentSourceVc, - render_data: JsonValueVc, + source: Vc, + render_data: Vc, path: String, debug: bool, } @@ -187,7 +183,7 @@ struct NodeRenderGetContentResult { #[turbo_tasks::value_impl] impl GetContentSourceContent for NodeRenderGetContentResult { #[turbo_tasks::function] - fn vary(&self) -> ContentSourceDataVaryVc { + fn vary(&self) -> Vc { ContentSourceDataVary { method: true, url: true, @@ -200,9 +196,9 @@ impl GetContentSourceContent for NodeRenderGetContentResult { } #[turbo_tasks::function] - async fn get(&self, data: Value) -> Result { + async fn get(&self, data: Value) -> Result> { let source = self.source.await?; - let Some(params) = &*source.route_match.params(&self.path).await? else { + let Some(params) = &*source.route_match.params(self.path.clone()).await? else { return Err(anyhow!("Non matching path provided")); }; let ContentSourceData { @@ -219,7 +215,7 @@ impl GetContentSourceContent for NodeRenderGetContentResult { let result = render_static( source.cwd, source.env, - source.server_root.join(&self.path), + source.server_root.join(self.path.clone()), entry.module, entry.runtime_entries, source.fallback_page, @@ -250,7 +246,9 @@ impl GetContentSourceContent for NodeRenderGetContentResult { content, status_code, headers, - } => ContentSourceContentVc::static_with_headers(content.into(), status_code, headers), + } => { + ContentSourceContent::static_with_headers(content.versioned(), status_code, headers) + } StaticResult::StreamedContent { status, headers, @@ -270,48 +268,48 @@ impl GetContentSourceContent for NodeRenderGetContentResult { } #[turbo_tasks::function] -fn introspectable_type() -> StringVc { - StringVc::cell("node render content source".to_string()) +fn introspectable_type() -> Vc { + Vc::cell("node render content source".to_string()) } #[turbo_tasks::value_impl] impl Introspectable for NodeRenderContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { + fn ty(&self) -> Vc { introspectable_type() } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { self.pathname } #[turbo_tasks::function] - async fn details(&self) -> Result { - Ok(StringVc::cell(format!( + async fn details(&self) -> Result> { + Ok(Vc::cell(format!( "Specificity: {}", self.specificity.await? ))) } #[turbo_tasks::function] - async fn children(&self) -> Result { + async fn children(&self) -> Result> { let mut set = IndexSet::new(); for &entry in self.entry.entries().await?.iter() { let entry = entry.await?; set.insert(( - StringVc::cell("module".to_string()), - IntrospectableAssetVc::new(entry.module.into()), + Vc::cell("module".to_string()), + IntrospectableAsset::new(Vc::upcast(entry.module)), )); set.insert(( - StringVc::cell("intermediate asset".to_string()), - IntrospectableAssetVc::new(get_intermediate_asset( + Vc::cell("intermediate asset".to_string()), + IntrospectableAsset::new(get_intermediate_asset( entry.chunking_context, entry.module, entry.runtime_entries, )), )); } - Ok(IntrospectableChildrenVc::cell(set)) + Ok(Vc::cell(set)) } } diff --git a/crates/turbopack-node/src/route_matcher.rs b/crates/turbopack-node/src/route_matcher.rs index 8edf2bc564db09..18ef21acd13588 100644 --- a/crates/turbopack-node/src/route_matcher.rs +++ b/crates/turbopack-node/src/route_matcher.rs @@ -1,5 +1,5 @@ use indexmap::IndexMap; -use turbo_tasks::primitives::BoolVc; +use turbo_tasks::Vc; #[turbo_tasks::value(transparent)] #[derive(Debug, Clone)] @@ -11,14 +11,23 @@ pub enum Param { #[turbo_tasks::value(transparent)] #[derive(Debug, Clone)] -pub struct Params(Option>); +pub struct Params(pub Option>); /// Extracts parameters from a URL path. +pub trait RouteMatcherRef { + /// Returns whether the given path is a match for the route. + fn matches(&self, path: &str) -> bool; + + /// Returns the parameters extracted from the given path. + fn params(&self, path: &str) -> Params; +} + +/// Extracts parameters from a URL path (Vc version) #[turbo_tasks::value_trait] pub trait RouteMatcher { /// Returns whether the given path is a match for the route. - fn matches(&self, path: &str) -> BoolVc; + fn matches(self: Vc, path: String) -> Vc; /// Returns the parameters extracted from the given path. - fn params(&self, path: &str) -> ParamsVc; + fn params(self: Vc, path: String) -> Vc; } diff --git a/crates/turbopack-node/src/source_map/content_source.rs b/crates/turbopack-node/src/source_map/content_source.rs index fe97d9fe7977d2..93ec060d478660 100644 --- a/crates/turbopack-node/src/source_map/content_source.rs +++ b/crates/turbopack-node/src/source_map/content_source.rs @@ -1,30 +1,27 @@ use anyhow::Result; -use turbo_tasks::{primitives::StringVc, Value}; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ - introspect::{Introspectable, IntrospectableVc}, - source_map::{GenerateSourceMap, GenerateSourceMapVc}, + introspect::Introspectable, source_map::GenerateSourceMap, version::VersionedContentExt, }; use turbopack_dev_server::source::{ - wrapping_source::{ContentSourceProcessor, ContentSourceProcessorVc, WrappedContentSourceVc}, - ContentSource, ContentSourceContent, ContentSourceContentVc, ContentSourceData, - ContentSourceDataVary, ContentSourceResultVc, ContentSourceVc, ContentSourcesVc, NeededData, - RewriteBuilder, + wrapping_source::{ContentSourceProcessor, WrappedContentSource}, + ContentSource, ContentSourceContent, ContentSourceData, ContentSourceDataVary, + ContentSourceResult, ContentSources, NeededData, RewriteBuilder, }; use url::Url; -use super::{SourceMapTraceVc, StackFrame}; - +use super::{SourceMapTrace, StackFrame}; /// Responsible for performinmg source map tracging for individual error stack /// frames. This is the API end of the client's Overlay stack-frame.ts. #[turbo_tasks::value(shared)] pub struct NextSourceMapTraceContentSource { - asset_source: ContentSourceVc, + asset_source: Vc>, } #[turbo_tasks::value_impl] -impl NextSourceMapTraceContentSourceVc { +impl NextSourceMapTraceContentSource { #[turbo_tasks::function] - pub fn new(asset_source: ContentSourceVc) -> NextSourceMapTraceContentSourceVc { + pub fn new(asset_source: Vc>) -> Vc { NextSourceMapTraceContentSource { asset_source }.cell() } } @@ -33,14 +30,14 @@ impl NextSourceMapTraceContentSourceVc { impl ContentSource for NextSourceMapTraceContentSource { #[turbo_tasks::function] async fn get( - self_vc: NextSourceMapTraceContentSourceVc, - path: &str, + self: Vc, + path: String, data: Value, - ) -> Result { + ) -> Result> { let raw_query = match &data.raw_query { None => { - return Ok(ContentSourceResultVc::need_data(Value::new(NeededData { - source: self_vc.into(), + return Ok(ContentSourceResult::need_data(Value::new(NeededData { + source: Vc::upcast(self), path: path.to_string(), vary: ContentSourceDataVary { raw_query: true, @@ -53,17 +50,17 @@ impl ContentSource for NextSourceMapTraceContentSource { let frame: StackFrame = match serde_qs::from_str(raw_query) { Ok(f) => f, - _ => return Ok(ContentSourceResultVc::not_found()), + _ => return Ok(ContentSourceResult::not_found()), }; let (line, column) = match frame.get_pos() { Some((l, c)) => (l, c), - _ => return Ok(ContentSourceResultVc::not_found()), + _ => return Ok(ContentSourceResult::not_found()), }; // The file is some percent encoded `http://localhost:3000/_next/foo/bar.js` let file = match Url::parse(&frame.file) { Ok(u) => u, - _ => return Ok(ContentSourceResultVc::not_found()), + _ => return Ok(ContentSourceResult::not_found()), }; let id = file.query_pairs().find_map(|(k, v)| { @@ -74,43 +71,41 @@ impl ContentSource for NextSourceMapTraceContentSource { } }); - let wrapped = WrappedContentSourceVc::new( - self_vc.await?.asset_source, - NextSourceMapTraceContentProcessorVc::new( + let wrapped = WrappedContentSource::new( + self.await?.asset_source, + Vc::upcast(NextSourceMapTraceContentProcessor::new( id, line, column, frame.name.map(|c| c.to_string()), - ) - .into(), + )), ); - Ok(ContentSourceResultVc::exact( + Ok(ContentSourceResult::exact(Vc::upcast( ContentSourceContent::Rewrite( RewriteBuilder::new(file.path().to_string()) - .content_source(wrapped.as_content_source()) + .content_source(Vc::upcast(wrapped)) .build(), ) - .cell() - .into(), - )) + .cell(), + ))) } #[turbo_tasks::function] - fn get_children(&self) -> ContentSourcesVc { - ContentSourcesVc::cell(vec![self.asset_source]) + fn get_children(&self) -> Vc { + Vc::cell(vec![self.asset_source]) } } #[turbo_tasks::value_impl] impl Introspectable for NextSourceMapTraceContentSource { #[turbo_tasks::function] - fn ty(&self) -> StringVc { - StringVc::cell("next source map trace content source".to_string()) + fn ty(&self) -> Vc { + Vc::cell("next source map trace content source".to_string()) } #[turbo_tasks::function] - fn details(&self) -> StringVc { - StringVc::cell( + fn details(&self) -> Vc { + Vc::cell( "supports tracing an error stack frame to its original source location".to_string(), ) } @@ -137,9 +132,9 @@ pub struct NextSourceMapTraceContentProcessor { } #[turbo_tasks::value_impl] -impl NextSourceMapTraceContentProcessorVc { +impl NextSourceMapTraceContentProcessor { #[turbo_tasks::function] - fn new(id: Option, line: usize, column: usize, name: Option) -> Self { + fn new(id: Option, line: usize, column: usize, name: Option) -> Vc { NextSourceMapTraceContentProcessor { id, line, @@ -153,30 +148,30 @@ impl NextSourceMapTraceContentProcessorVc { #[turbo_tasks::value_impl] impl ContentSourceProcessor for NextSourceMapTraceContentProcessor { #[turbo_tasks::function] - async fn process(&self, content: ContentSourceContentVc) -> Result { + async fn process(&self, content: Vc) -> Result> { let file = match &*content.await? { ContentSourceContent::Static(static_content) => static_content.await?.content, - _ => return Ok(ContentSourceContentVc::not_found()), + _ => return Ok(ContentSourceContent::not_found()), }; - let gen = match GenerateSourceMapVc::resolve_from(file).await? { + let gen = match Vc::try_resolve_sidecast::>(file).await? { Some(f) => f, - _ => return Ok(ContentSourceContentVc::not_found()), + _ => return Ok(ContentSourceContent::not_found()), }; let sm = if let Some(id) = &self.id { - gen.by_section(id).await? + gen.by_section(id.clone()).await? } else { gen.generate_source_map().await? }; let sm = match &*sm { Some(sm) => *sm, - None => return Ok(ContentSourceContentVc::not_found()), + None => return Ok(ContentSourceContent::not_found()), }; - let traced = SourceMapTraceVc::new(sm, self.line, self.column, self.name.clone()); - Ok(ContentSourceContentVc::static_content( - traced.content().into(), + let traced = SourceMapTrace::new(sm, self.line, self.column, self.name.clone()); + Ok(ContentSourceContent::static_content( + traced.content().versioned(), )) } } diff --git a/crates/turbopack-node/src/source_map/mod.rs b/crates/turbopack-node/src/source_map/mod.rs index a1541d27166063..7241fe3259c3d7 100644 --- a/crates/turbopack-node/src/source_map/mod.rs +++ b/crates/turbopack-node/src/source_map/mod.rs @@ -6,22 +6,22 @@ use std::{ use anyhow::Result; use const_format::concatcp; -pub use content_source::{NextSourceMapTraceContentSource, NextSourceMapTraceContentSourceVc}; +pub use content_source::NextSourceMapTraceContentSource; use once_cell::sync::Lazy; use regex::Regex; -pub use trace::{SourceMapTrace, SourceMapTraceVc, StackFrame, TraceResult, TraceResultVc}; +pub use trace::{SourceMapTrace, StackFrame, TraceResult}; use tracing::{instrument, Level}; +use turbo_tasks::{ReadRef, Vc}; use turbo_tasks_fs::{ - source_context::get_source_context, to_sys_path, FileLinesContent, FileLinesContentReadRef, - FileSystemPathReadRef, FileSystemPathVc, + source_context::get_source_context, to_sys_path, FileLinesContent, FileSystemPath, }; use turbopack_cli_utils::source_context::format_source_context_lines; use turbopack_core::{ - asset::AssetVc, source_map::GenerateSourceMap, PROJECT_FILESYSTEM_NAME, SOURCE_MAP_ROOT_NAME, + asset::Asset, source_map::GenerateSourceMap, PROJECT_FILESYSTEM_NAME, SOURCE_MAP_ROOT_NAME, }; use turbopack_ecmascript::magic_identifier::unmangle_identifiers; -use crate::{internal_assets_for_source_mapping, pool::FormattingMode, AssetsForSourceMappingVc}; +use crate::{internal_assets_for_source_mapping, pool::FormattingMode, AssetsForSourceMapping}; pub mod content_source; pub mod trace; @@ -30,9 +30,9 @@ const MAX_CODE_FRAMES: usize = 3; pub async fn apply_source_mapping( text: &'_ str, - assets_for_source_mapping: AssetsForSourceMappingVc, - root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + root: Vc, + project_dir: Vc, formatting_mode: FormattingMode, ) -> Result> { static STACK_TRACE_LINE: Lazy = @@ -188,19 +188,19 @@ enum ResolvedSourceMapping { }, MappedProject { frame: StackFrame<'static>, - project_path: FileSystemPathReadRef, - lines: FileLinesContentReadRef, + project_path: ReadRef, + lines: ReadRef, }, MappedLibrary { frame: StackFrame<'static>, - project_path: FileSystemPathReadRef, + project_path: ReadRef, }, } async fn resolve_source_mapping( - assets_for_source_mapping: AssetsForSourceMappingVc, - root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + root: Vc, + project_dir: Vc, frame: &StackFrame<'_>, ) -> Result { let Some((line, column)) = frame.get_pos() else { @@ -227,7 +227,7 @@ async fn resolve_source_mapping( let Some(sm) = *generate_source_map.generate_source_map().await? else { return Ok(ResolvedSourceMapping::NoSourceMap); }; - let trace = SourceMapTraceVc::new(sm, line, column, name.map(|s| s.to_string())) + let trace = SourceMapTrace::new(sm, line, column, name.map(|s| s.to_string())) .trace() .await?; match &*trace { @@ -240,7 +240,7 @@ async fn resolve_source_mapping( PROJECT_FILESYSTEM_NAME, "]/" )) { - let fs_path = project_dir.join(project_path); + let fs_path = project_dir.join(project_path.to_string()); if lib_code { return Ok(ResolvedSourceMapping::MappedLibrary { frame: frame.clone(), @@ -275,9 +275,9 @@ pub struct StructuredError { impl StructuredError { pub async fn print( &self, - assets_for_source_mapping: AssetsForSourceMappingVc, - root: FileSystemPathVc, - project_dir: FileSystemPathVc, + assets_for_source_mapping: Vc, + root: Vc, + project_dir: Vc, formatting_mode: FormattingMode, ) -> Result { let mut message = String::new(); @@ -315,9 +315,9 @@ impl StructuredError { #[instrument(level = Level::TRACE, skip_all)] pub async fn trace_stack( error: StructuredError, - root_asset: AssetVc, - output_path: FileSystemPathVc, - project_dir: FileSystemPathVc, + root_asset: Vc>, + output_path: Vc, + project_dir: Vc, ) -> Result { let assets_for_source_mapping = internal_assets_for_source_mapping(root_asset, output_path); diff --git a/crates/turbopack-node/src/source_map/trace.rs b/crates/turbopack-node/src/source_map/trace.rs index afedeea9b6964f..b3985a355df375 100644 --- a/crates/turbopack-node/src/source_map/trace.rs +++ b/crates/turbopack-node/src/source_map/trace.rs @@ -4,10 +4,11 @@ use anyhow::Result; use mime::APPLICATION_JSON; use serde::{Deserialize, Serialize}; use serde_json::json; +use turbo_tasks::Vc; use turbo_tasks_fs::File; use turbopack_core::{ - asset::AssetContentVc, - source_map::{SourceMapVc, Token}, + asset::AssetContent, + source_map::{SourceMap, Token}, }; use turbopack_ecmascript::magic_identifier::unmangle_identifiers; @@ -84,7 +85,7 @@ impl<'a> Display for StackFrame<'a> { #[turbo_tasks::value(shared)] #[derive(Debug)] pub struct SourceMapTrace { - map: SourceMapVc, + map: Vc, line: usize, column: usize, name: Option, @@ -99,9 +100,14 @@ pub enum TraceResult { } #[turbo_tasks::value_impl] -impl SourceMapTraceVc { +impl SourceMapTrace { #[turbo_tasks::function] - pub async fn new(map: SourceMapVc, line: usize, column: usize, name: Option) -> Self { + pub async fn new( + map: Vc, + line: usize, + column: usize, + name: Option, + ) -> Vc { SourceMapTrace { map, line, @@ -122,7 +128,7 @@ impl SourceMapTraceVc { /// the individual sections of the JS file's map without the /// serialization. #[turbo_tasks::function] - pub async fn trace(self) -> Result { + pub async fn trace(self: Vc) -> Result> { let this = self.await?; let token = this @@ -144,7 +150,7 @@ impl SourceMapTraceVc { /// Takes the trace and generates a (possibly valid) JSON asset content. #[turbo_tasks::function] - pub async fn content(self) -> Result { + pub async fn content(self: Vc) -> Result> { let trace = self.trace().await?; let result = match &*trace { // purposefully invalid JSON (it can't be empty), so that the catch handler will default @@ -158,6 +164,6 @@ impl SourceMapTraceVc { .to_string(), }; let file = File::from(result).with_content_type(APPLICATION_JSON); - Ok(file.into()) + Ok(AssetContent::file(file.into())) } } diff --git a/crates/turbopack-node/src/transforms/postcss.rs b/crates/turbopack-node/src/transforms/postcss.rs index a08866c5d9af0c..5035e732a5dff3 100644 --- a/crates/turbopack-node/src/transforms/postcss.rs +++ b/crates/turbopack-node/src/transforms/postcss.rs @@ -1,33 +1,28 @@ use anyhow::{bail, Context, Result}; use indexmap::indexmap; use serde::{Deserialize, Serialize}; -use turbo_tasks::{ - primitives::{JsonValueVc, StringsVc}, - CompletionVc, CompletionsVc, TryJoinIterExt, Value, -}; +use turbo_tasks::{Completion, Completions, TryJoinIterExt, Value, Vc}; use turbo_tasks_bytes::stream::SingleValue; use turbo_tasks_fs::{ - json::parse_json_with_source_context, File, FileContent, FileSystemEntryType, FileSystemPathVc, + json::parse_json_with_source_context, File, FileContent, FileSystemEntryType, FileSystemPath, }; use turbopack_core::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, changed::any_content_changed, - context::{AssetContext, AssetContextVc}, - ident::AssetIdentVc, + context::AssetContext, + ident::AssetIdent, issue::IssueContextExt, - reference_type::{EntryReferenceSubType, InnerAssetsVc, ReferenceType}, + reference_type::{EntryReferenceSubType, InnerAssets, ReferenceType}, resolve::{find_context_file, FindContextFileResult}, - source_asset::SourceAssetVc, - source_transform::{SourceTransform, SourceTransformVc}, - virtual_asset::VirtualAssetVc, + source_asset::SourceAsset, + source_transform::SourceTransform, + virtual_asset::VirtualAsset, }; use super::util::{emitted_assets_to_virtual_assets, EmittedAsset}; use crate::{ - debug::should_debug, - embed_js::embed_file, - evaluate::evaluate, - execution_context::{ExecutionContext, ExecutionContextVc}, + debug::should_debug, embed_js::embed_file, evaluate::evaluate, + execution_context::ExecutionContext, }; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -41,8 +36,8 @@ struct PostCssProcessingResult { } #[turbo_tasks::function] -fn postcss_configs() -> StringsVc { - StringsVc::cell( +fn postcss_configs() -> Vc> { + Vc::cell( [ ".postcssrc", ".postcssrc.json", @@ -70,14 +65,17 @@ fn postcss_configs() -> StringsVc { #[turbo_tasks::value] pub struct PostCssTransform { - evaluate_context: AssetContextVc, - execution_context: ExecutionContextVc, + evaluate_context: Vc>, + execution_context: Vc, } #[turbo_tasks::value_impl] -impl PostCssTransformVc { +impl PostCssTransform { #[turbo_tasks::function] - pub fn new(evaluate_context: AssetContextVc, execution_context: ExecutionContextVc) -> Self { + pub fn new( + evaluate_context: Vc>, + execution_context: Vc, + ) -> Vc { PostCssTransform { evaluate_context, execution_context, @@ -89,35 +87,36 @@ impl PostCssTransformVc { #[turbo_tasks::value_impl] impl SourceTransform for PostCssTransform { #[turbo_tasks::function] - fn transform(&self, source: AssetVc) -> AssetVc { - PostCssTransformedAsset { - evaluate_context: self.evaluate_context, - execution_context: self.execution_context, - source, - } - .cell() - .into() + fn transform(&self, source: Vc>) -> Vc> { + Vc::upcast( + PostCssTransformedAsset { + evaluate_context: self.evaluate_context, + execution_context: self.execution_context, + source, + } + .cell(), + ) } } #[turbo_tasks::value] struct PostCssTransformedAsset { - evaluate_context: AssetContextVc, - execution_context: ExecutionContextVc, - source: AssetVc, + evaluate_context: Vc>, + execution_context: Vc, + source: Vc>, } #[turbo_tasks::value_impl] impl Asset for PostCssTransformedAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident() } #[turbo_tasks::function] - async fn content(self_vc: PostCssTransformedAssetVc) -> Result { - let this = self_vc.await?; - Ok(self_vc + async fn content(self: Vc) -> Result> { + let this = self.await?; + Ok(self .process() .issue_context(this.source.ident().path(), "PostCSS processing") .await? @@ -128,24 +127,26 @@ impl Asset for PostCssTransformedAsset { #[turbo_tasks::value] struct ProcessPostCssResult { - content: AssetContentVc, - assets: Vec, + content: Vc, + assets: Vec>, } #[turbo_tasks::function] async fn extra_configs( - context: AssetContextVc, - postcss_config_path: FileSystemPathVc, -) -> Result { - let config_paths = [postcss_config_path.parent().join("tailwind.config.js")]; + context: Vc>, + postcss_config_path: Vc, +) -> Result> { + let config_paths = [postcss_config_path + .parent() + .join("tailwind.config.js".to_string())]; let configs = config_paths .into_iter() .map(|path| async move { Ok( matches!(&*path.get_type().await?, FileSystemEntryType::File).then(|| { any_content_changed(context.process( - SourceAssetVc::new(path).into(), - Value::new(ReferenceType::Internal(InnerAssetsVc::empty())), + Vc::upcast(SourceAsset::new(path)), + Value::new(ReferenceType::Internal(InnerAssets::empty())), )) }), ) @@ -156,32 +157,34 @@ async fn extra_configs( .flatten() .collect::>(); - Ok(CompletionsVc::cell(configs).completed()) + Ok(Vc::::cell(configs).completed()) } #[turbo_tasks::function] -fn postcss_executor(context: AssetContextVc, postcss_config_path: FileSystemPathVc) -> AssetVc { +fn postcss_executor( + context: Vc>, + postcss_config_path: Vc, +) -> Vc> { let config_asset = context.process( - SourceAssetVc::new(postcss_config_path).into(), + Vc::upcast(SourceAsset::new(postcss_config_path)), Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)), ); context.process( - VirtualAssetVc::new( - postcss_config_path.join("transform.ts"), - AssetContent::File(embed_file("transforms/postcss.ts")).cell(), - ) - .into(), - Value::new(ReferenceType::Internal(InnerAssetsVc::cell(indexmap! { + Vc::upcast(VirtualAsset::new( + postcss_config_path.join("transform.ts".to_string()), + AssetContent::File(embed_file("transforms/postcss.ts".to_string())).cell(), + )), + Value::new(ReferenceType::Internal(Vc::cell(indexmap! { "CONFIG".to_string() => config_asset }))), ) } #[turbo_tasks::value_impl] -impl PostCssTransformedAssetVc { +impl PostCssTransformedAsset { #[turbo_tasks::function] - async fn process(self) -> Result { + async fn process(self: Vc) -> Result> { let this = self.await?; let find_config_result = find_context_file(this.source.ident().path().parent(), postcss_configs()); @@ -225,10 +228,7 @@ impl PostCssTransformedAssetVc { context, chunking_context, None, - vec![ - JsonValueVc::cell(content.into()), - JsonValueVc::cell(css_path.into()), - ], + vec![Vc::cell(content.into()), Vc::cell(css_path.into())], extra_configs_changed, should_debug("postcss_transform"), ) diff --git a/crates/turbopack-node/src/transforms/util.rs b/crates/turbopack-node/src/transforms/util.rs index fca0f3e051648c..f979051762f665 100644 --- a/crates/turbopack-node/src/transforms/util.rs +++ b/crates/turbopack-node/src/transforms/util.rs @@ -2,9 +2,10 @@ use std::collections::BTreeMap; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; +use turbo_tasks::Vc; use turbo_tasks_fs::{File, FileContent, FileSystem}; use turbopack_core::{ - asset::AssetContent, server_fs::ServerFileSystemVc, virtual_asset::VirtualAssetVc, + asset::AssetContent, server_fs::ServerFileSystem, virtual_asset::VirtualAsset, }; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] @@ -15,7 +16,9 @@ pub struct EmittedAsset { source_map: Option, } -pub fn emitted_assets_to_virtual_assets(assets: Option>) -> Vec { +pub fn emitted_assets_to_virtual_assets( + assets: Option>, +) -> Vec> { assets .into_iter() .flatten() @@ -31,8 +34,8 @@ pub fn emitted_assets_to_virtual_assets(assets: Option>) -> Ve .into_iter() .map(|(file, (content, _source_map))| { // TODO handle SourceMap - VirtualAssetVc::new( - ServerFileSystemVc::new().root().join(&file), + VirtualAsset::new( + ServerFileSystem::new().root().join(file), AssetContent::File(FileContent::Content(File::from(content)).cell()).cell(), ) }) diff --git a/crates/turbopack-node/src/transforms/webpack.rs b/crates/turbopack-node/src/transforms/webpack.rs index 7c68e52e437dcd..374099af974293 100644 --- a/crates/turbopack-node/src/transforms/webpack.rs +++ b/crates/turbopack-node/src/transforms/webpack.rs @@ -1,25 +1,23 @@ use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; use serde_json::json; -use turbo_tasks::{primitives::JsonValueVc, trace::TraceRawVcs, CompletionVc, Value}; +use turbo_tasks::{trace::TraceRawVcs, Completion, Value, Vc}; use turbo_tasks_bytes::stream::SingleValue; use turbo_tasks_fs::{json::parse_json_with_source_context, File, FileContent}; use turbopack_core::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, - context::{AssetContext, AssetContextVc}, - ident::AssetIdentVc, - reference_type::{InnerAssetsVc, ReferenceType}, - source_asset::SourceAssetVc, - source_transform::{SourceTransform, SourceTransformVc}, - virtual_asset::VirtualAssetVc, + asset::{Asset, AssetContent}, + context::AssetContext, + ident::AssetIdent, + reference_type::{InnerAssets, ReferenceType}, + source_asset::SourceAsset, + source_transform::SourceTransform, + virtual_asset::VirtualAsset, }; use super::util::{emitted_assets_to_virtual_assets, EmittedAsset}; use crate::{ - debug::should_debug, - embed_js::embed_file_path, - evaluate::evaluate, - execution_context::{ExecutionContext, ExecutionContextVc}, + debug::should_debug, embed_js::embed_file_path, evaluate::evaluate, + execution_context::ExecutionContext, }; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -45,21 +43,21 @@ pub struct WebpackLoaderItems(pub Vec); #[turbo_tasks::value] pub struct WebpackLoaders { - evaluate_context: AssetContextVc, - execution_context: ExecutionContextVc, - loaders: WebpackLoaderItemsVc, + evaluate_context: Vc>, + execution_context: Vc, + loaders: Vc, rename_as: Option, } #[turbo_tasks::value_impl] -impl WebpackLoadersVc { +impl WebpackLoaders { #[turbo_tasks::function] pub fn new( - evaluate_context: AssetContextVc, - execution_context: ExecutionContextVc, - loaders: WebpackLoaderItemsVc, + evaluate_context: Vc>, + execution_context: Vc, + loaders: Vc, rename_as: Option, - ) -> Self { + ) -> Vc { WebpackLoaders { evaluate_context, execution_context, @@ -73,29 +71,30 @@ impl WebpackLoadersVc { #[turbo_tasks::value_impl] impl SourceTransform for WebpackLoaders { #[turbo_tasks::function] - fn transform(self_vc: WebpackLoadersVc, source: AssetVc) -> AssetVc { - WebpackLoadersProcessedAsset { - transform: self_vc, - source, - } - .cell() - .into() + fn transform(self: Vc, source: Vc>) -> Vc> { + Vc::upcast( + WebpackLoadersProcessedAsset { + transform: self, + source, + } + .cell(), + ) } } #[turbo_tasks::value] struct WebpackLoadersProcessedAsset { - transform: WebpackLoadersVc, - source: AssetVc, + transform: Vc, + source: Vc>, } #[turbo_tasks::value_impl] impl Asset for WebpackLoadersProcessedAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { Ok( if let Some(rename_as) = self.transform.await?.rename_as.as_deref() { - self.source.ident().rename_as(rename_as) + self.source.ident().rename_as(rename_as.to_string()) } else { self.source.ident() }, @@ -103,29 +102,31 @@ impl Asset for WebpackLoadersProcessedAsset { } #[turbo_tasks::function] - async fn content(self_vc: WebpackLoadersProcessedAssetVc) -> Result { - Ok(self_vc.process().await?.content) + async fn content(self: Vc) -> Result> { + Ok(self.process().await?.content) } } #[turbo_tasks::value] struct ProcessWebpackLoadersResult { - content: AssetContentVc, - assets: Vec, + content: Vc, + assets: Vec>, } #[turbo_tasks::function] -fn webpack_loaders_executor(context: AssetContextVc) -> AssetVc { +fn webpack_loaders_executor(context: Vc>) -> Vc> { context.process( - SourceAssetVc::new(embed_file_path("transforms/webpack-loaders.ts")).into(), - Value::new(ReferenceType::Internal(InnerAssetsVc::empty())), + Vc::upcast(SourceAsset::new(embed_file_path( + "transforms/webpack-loaders.ts".to_string(), + ))), + Value::new(ReferenceType::Internal(InnerAssets::empty())), ) } #[turbo_tasks::value_impl] -impl WebpackLoadersProcessedAssetVc { +impl WebpackLoadersProcessedAsset { #[turbo_tasks::function] - async fn process(self) -> Result { + async fn process(self: Vc) -> Result> { let this = self.await?; let transform = this.transform.await?; @@ -160,11 +161,11 @@ impl WebpackLoadersProcessedAssetVc { chunking_context, None, vec![ - JsonValueVc::cell(content.into()), - JsonValueVc::cell(resource_path.into()), - JsonValueVc::cell(json!(*loaders)), + Vc::cell(content.into()), + Vc::cell(resource_path.into()), + Vc::cell(json!(*loaders)), ], - CompletionVc::immutable(), + Completion::immutable(), should_debug("webpack_loader"), ) .await?; diff --git a/crates/turbopack-static/src/fixed.rs b/crates/turbopack-static/src/fixed.rs index 2023779d83eb32..5100222842a1de 100644 --- a/crates/turbopack-static/src/fixed.rs +++ b/crates/turbopack-static/src/fixed.rs @@ -1,22 +1,23 @@ use anyhow::Result; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::Vc; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, }; /// A static asset that is served at a fixed output path. It won't use /// content hashing to generate a long term cacheable URL. #[turbo_tasks::value] pub struct FixedStaticAsset { - output_path: FileSystemPathVc, - source: AssetVc, + output_path: Vc, + source: Vc>, } #[turbo_tasks::value_impl] -impl FixedStaticAssetVc { +impl FixedStaticAsset { #[turbo_tasks::function] - pub fn new(output_path: FileSystemPathVc, source: AssetVc) -> Self { + pub fn new(output_path: Vc, source: Vc>) -> Vc { FixedStaticAsset { output_path, source, @@ -28,12 +29,12 @@ impl FixedStaticAssetVc { #[turbo_tasks::value_impl] impl Asset for FixedStaticAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { - Ok(AssetIdentVc::from_path(self.output_path)) + async fn ident(&self) -> Result> { + Ok(AssetIdent::from_path(self.output_path)) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } } diff --git a/crates/turbopack-static/src/lib.rs b/crates/turbopack-static/src/lib.rs index 59429bf9234eca..57a662f8e7cc69 100644 --- a/crates/turbopack-static/src/lib.rs +++ b/crates/turbopack-static/src/lib.rs @@ -9,59 +9,59 @@ //! path. #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub mod fixed; use anyhow::{anyhow, Result}; -use turbo_tasks::{primitives::StringVc, Value, ValueToString}; +use turbo_tasks::{Value, ValueToString, Vc}; use turbo_tasks_fs::FileContent; use turbopack_core::{ - asset::{Asset, AssetContent, AssetContentVc, AssetVc}, + asset::{Asset, AssetContent}, chunk::{ - availability_info::AvailabilityInfo, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, - ChunkableAssetVc, ChunkingContext, ChunkingContextVc, + availability_info::AvailabilityInfo, Chunk, ChunkItem, ChunkableAsset, ChunkingContext, }, - context::AssetContextVc, - ident::AssetIdentVc, - reference::{AssetReferencesVc, SingleAssetReferenceVc}, + context::AssetContext, + ident::AssetIdent, + reference::{AssetReferences, SingleAssetReference}, }; -use turbopack_css::embed::{CssEmbed, CssEmbedVc, CssEmbeddable, CssEmbeddableVc}; +use turbopack_css::embed::{CssEmbed, CssEmbeddable}; use turbopack_ecmascript::{ chunk::{ - EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemContentVc, - EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, - EcmascriptChunkVc, EcmascriptChunkingContextVc, EcmascriptExports, EcmascriptExportsVc, + EcmascriptChunk, EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable, + EcmascriptChunkingContext, EcmascriptExports, }, utils::StringifyJs, }; #[turbo_tasks::function] -fn modifier() -> StringVc { - StringVc::cell("static".to_string()) +fn modifier() -> Vc { + Vc::cell("static".to_string()) } #[turbo_tasks::value] #[derive(Clone)] pub struct StaticModuleAsset { - pub source: AssetVc, - pub context: AssetContextVc, + pub source: Vc>, + pub context: Vc>, } #[turbo_tasks::value_impl] -impl StaticModuleAssetVc { +impl StaticModuleAsset { #[turbo_tasks::function] - pub fn new(source: AssetVc, context: AssetContextVc) -> Self { + pub fn new(source: Vc>, context: Vc>) -> Vc { Self::cell(StaticModuleAsset { source, context }) } #[turbo_tasks::function] async fn static_asset( - self_vc: StaticModuleAssetVc, - context: ChunkingContextVc, - ) -> Result { - Ok(StaticAssetVc::cell(StaticAsset { + self: Vc, + context: Vc>, + ) -> Result> { + Ok(StaticAsset::cell(StaticAsset { context, - source: self_vc.await?.source, + source: self.await?.source, })) } } @@ -69,12 +69,12 @@ impl StaticModuleAssetVc { #[turbo_tasks::value_impl] impl Asset for StaticModuleAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { + fn ident(&self) -> Vc { self.source.ident().with_modifier(modifier()) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } } @@ -83,16 +83,15 @@ impl Asset for StaticModuleAsset { impl ChunkableAsset for StaticModuleAsset { #[turbo_tasks::function] fn as_chunk( - self_vc: StaticModuleAssetVc, - context: ChunkingContextVc, + self: Vc, + context: Vc>, availability_info: Value, - ) -> ChunkVc { - EcmascriptChunkVc::new( + ) -> Vc> { + Vc::upcast(EcmascriptChunk::new( context, - self_vc.as_ecmascript_chunk_placeable(), + Vc::upcast(self), availability_info, - ) - .into() + )) } } @@ -100,19 +99,18 @@ impl ChunkableAsset for StaticModuleAsset { impl EcmascriptChunkPlaceable for StaticModuleAsset { #[turbo_tasks::function] fn as_chunk_item( - self_vc: StaticModuleAssetVc, - context: EcmascriptChunkingContextVc, - ) -> EcmascriptChunkItemVc { - ModuleChunkItemVc::cell(ModuleChunkItem { - module: self_vc, + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(ModuleChunkItem::cell(ModuleChunkItem { + module: self, context, - static_asset: self_vc.static_asset(context.into()), - }) - .into() + static_asset: self.static_asset(Vc::upcast(context)), + })) } #[turbo_tasks::function] - fn get_exports(&self) -> EcmascriptExportsVc { + fn get_exports(&self) -> Vc { EcmascriptExports::Value.into() } } @@ -120,24 +118,26 @@ impl EcmascriptChunkPlaceable for StaticModuleAsset { #[turbo_tasks::value_impl] impl CssEmbeddable for StaticModuleAsset { #[turbo_tasks::function] - fn as_css_embed(self_vc: StaticModuleAssetVc, context: ChunkingContextVc) -> CssEmbedVc { - StaticCssEmbedVc::cell(StaticCssEmbed { - static_asset: self_vc.static_asset(context), - }) - .into() + fn as_css_embed( + self: Vc, + context: Vc>, + ) -> Vc> { + Vc::upcast(StaticCssEmbed::cell(StaticCssEmbed { + static_asset: self.static_asset(context), + })) } } #[turbo_tasks::value] struct StaticAsset { - context: ChunkingContextVc, - source: AssetVc, + context: Vc>, + source: Vc>, } #[turbo_tasks::value_impl] impl Asset for StaticAsset { #[turbo_tasks::function] - async fn ident(&self) -> Result { + async fn ident(&self) -> Result> { let content = self.source.content(); let content_hash = if let AssetContent::File(file) = &*content.await? { if let FileContent::Content(file) = &*file.await? { @@ -151,52 +151,51 @@ impl Asset for StaticAsset { let content_hash_b16 = turbo_tasks_hash::encode_hex(content_hash); let asset_path = self .context - .asset_path(&content_hash_b16, self.source.ident()); - Ok(AssetIdentVc::from_path(asset_path)) + .asset_path(content_hash_b16, self.source.ident()); + Ok(AssetIdent::from_path(asset_path)) } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } } #[turbo_tasks::value] struct ModuleChunkItem { - module: StaticModuleAssetVc, - context: EcmascriptChunkingContextVc, - static_asset: StaticAssetVc, + module: Vc, + context: Vc>, + static_asset: Vc, } #[turbo_tasks::value_impl] impl ChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn asset_ident(&self) -> AssetIdentVc { + fn asset_ident(&self) -> Vc { self.module.ident() } #[turbo_tasks::function] - async fn references(&self) -> Result { - Ok(AssetReferencesVc::cell(vec![SingleAssetReferenceVc::new( - self.static_asset.into(), - StringVc::cell(format!( + async fn references(&self) -> Result> { + Ok(Vc::cell(vec![Vc::upcast(SingleAssetReference::new( + Vc::upcast(self.static_asset), + Vc::cell(format!( "static(url) {}", self.static_asset.ident().to_string().await? )), - ) - .into()])) + ))])) } } #[turbo_tasks::value_impl] impl EcmascriptChunkItem for ModuleChunkItem { #[turbo_tasks::function] - fn chunking_context(&self) -> EcmascriptChunkingContextVc { + fn chunking_context(&self) -> Vc> { self.context } #[turbo_tasks::function] - async fn content(&self) -> Result { + async fn content(&self) -> Result> { Ok(EcmascriptChunkItemContent { inner_code: format!( "__turbopack_export_value__({path});", @@ -214,26 +213,25 @@ impl EcmascriptChunkItem for ModuleChunkItem { #[turbo_tasks::value] struct StaticCssEmbed { - static_asset: StaticAssetVc, + static_asset: Vc, } #[turbo_tasks::value_impl] impl CssEmbed for StaticCssEmbed { #[turbo_tasks::function] - async fn references(&self) -> Result { - Ok(AssetReferencesVc::cell(vec![SingleAssetReferenceVc::new( - self.static_asset.into(), - StringVc::cell(format!( + async fn references(&self) -> Result> { + Ok(Vc::cell(vec![Vc::upcast(SingleAssetReference::new( + Vc::upcast(self.static_asset), + Vc::cell(format!( "static(url) {}", self.static_asset.ident().path().await? )), - ) - .into()])) + ))])) } #[turbo_tasks::function] - fn embeddable_asset(&self) -> AssetVc { - self.static_asset.as_asset() + fn embeddable_asset(&self) -> Vc> { + Vc::upcast(self.static_asset) } } diff --git a/crates/turbopack-swc-utils/src/emitter.rs b/crates/turbopack-swc-utils/src/emitter.rs index e91f7621f49bd7..2587e80c22f3e5 100644 --- a/crates/turbopack-swc-utils/src/emitter.rs +++ b/crates/turbopack-swc-utils/src/emitter.rs @@ -5,14 +5,14 @@ use swc_core::common::{ source_map::Pos, SourceMap, }; -use turbo_tasks::primitives::StringVc; +use turbo_tasks::Vc; use turbopack_core::{ - asset::{Asset, AssetVc}, - issue::{analyze::AnalyzeIssue, IssueSeverity, IssueSourceVc}, + asset::Asset, + issue::{analyze::AnalyzeIssue, IssueExt, IssueSeverity, IssueSource}, }; pub struct IssueEmitter { - pub source: AssetVc, + pub source: Vc>, pub source_map: Arc, pub title: Option, } @@ -41,7 +41,7 @@ impl Emitter for IssueEmitter { } let source = db.span.primary_span().map(|span| { - IssueSourceVc::from_byte_offset( + IssueSource::from_byte_offset( self.source, self.source_map.lookup_byte_offset(span.lo()).pos.to_usize(), self.source_map.lookup_byte_offset(span.lo()).pos.to_usize(), @@ -49,7 +49,7 @@ impl Emitter for IssueEmitter { }); // TODO add other primary and secondary spans with labels as sub_issues - let issue = AnalyzeIssue { + AnalyzeIssue { severity: match level { Level::Bug => IssueSeverity::Bug, Level::Fatal | Level::PhaseFatal => IssueSeverity::Fatal, @@ -61,14 +61,14 @@ impl Emitter for IssueEmitter { Level::FailureNote => IssueSeverity::Note, } .cell(), - category: StringVc::cell("parse".to_string()), + category: Vc::cell("parse".to_string()), source_ident: self.source.ident(), - title: StringVc::cell(title), - message: StringVc::cell(message), + title: Vc::cell(title), + message: Vc::cell(message), code, source, } - .cell(); - issue.as_issue().emit(); + .cell() + .emit(); } } diff --git a/crates/turbopack-test-utils/src/lib.rs b/crates/turbopack-test-utils/src/lib.rs index 1aa34d7e723a0c..1613847b027677 100644 --- a/crates/turbopack-test-utils/src/lib.rs +++ b/crates/turbopack-test-utils/src/lib.rs @@ -1,3 +1,5 @@ #![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] pub mod snapshot; diff --git a/crates/turbopack-test-utils/src/snapshot.rs b/crates/turbopack-test-utils/src/snapshot.rs index 7d6b65708aaab5..8e22967066caaf 100644 --- a/crates/turbopack-test-utils/src/snapshot.rs +++ b/crates/turbopack-test-utils/src/snapshot.rs @@ -6,26 +6,23 @@ use std::{ use anyhow::{anyhow, bail, Context, Result}; use once_cell::sync::Lazy; use similar::TextDiff; -use turbo_tasks::{debug::ValueDebugStringReadRef, TryJoinIterExt, ValueToString}; +use turbo_tasks::{debug::ValueDebugString, ReadRef, TryJoinIterExt, ValueToString, Vc}; use turbo_tasks_fs::{ - DirectoryContent, DirectoryEntry, DiskFileSystemVc, File, FileContent, FileSystemEntryType, - FileSystemPathVc, + DirectoryContent, DirectoryEntry, DiskFileSystem, File, FileContent, FileSystemEntryType, + FileSystemPath, }; use turbo_tasks_hash::encode_hex; -use turbopack_core::{ - asset::{AssetContent, AssetContentVc}, - issue::PlainIssueReadRef, -}; +use turbopack_core::{asset::AssetContent, issue::PlainIssue}; // Updates the existing snapshot outputs with the actual outputs of this run. // e.g. `UPDATE=1 cargo test -p turbopack-tests -- test_my_pattern` static UPDATE: Lazy = Lazy::new(|| env::var("UPDATE").unwrap_or_default() == "1"); pub async fn snapshot_issues< - I: IntoIterator, + I: IntoIterator, ReadRef)>, >( captured_issues: I, - issues_path: FileSystemPathVc, + issues_path: Vc, workspace_root: &str, ) -> Result<()> { let expected_issues = expected(issues_path).await?; @@ -44,9 +41,9 @@ pub async fn snapshot_issues< } else { &title }; - let hash = encode_hex(plain_issue.internal_hash(true)); + let hash = encode_hex(plain_issue.internal_hash_ref(true)); - let path = issues_path.join(&format!("{title}-{}.txt", &hash[0..6])); + let path = issues_path.join(format!("{title}-{}.txt", &hash[0..6])); if !seen.insert(path) { continue; } @@ -59,7 +56,7 @@ pub async fn snapshot_issues< .replace(workspace_root, "WORKSPACE_ROOT") // Normalize syspaths from Windows. These appear in stack traces. .replace("\\\\", "/"); - let asset = File::from(content).into(); + let asset = AssetContent::file(File::from(content).into()); diff(path, asset).await?; } @@ -67,7 +64,7 @@ pub async fn snapshot_issues< matches_expected(expected_issues, seen).await } -pub async fn expected(dir: FileSystemPathVc) -> Result> { +pub async fn expected(dir: Vc) -> Result>> { let mut expected = HashSet::new(); let entries = dir.read_dir().await?; if let DirectoryContent::Entries(entries) = &*entries { @@ -88,8 +85,8 @@ pub async fn expected(dir: FileSystemPathVc) -> Result } pub async fn matches_expected( - expected: HashSet, - seen: HashSet, + expected: HashSet>, + seen: HashSet>, ) -> Result<()> { for path in diff_paths(&expected, &seen).await? { let p = &path.await?.path; @@ -103,9 +100,9 @@ pub async fn matches_expected( Ok(()) } -pub async fn diff(path: FileSystemPathVc, actual: AssetContentVc) -> Result<()> { +pub async fn diff(path: Vc, actual: Vc) -> Result<()> { let path_str = &path.await?.path; - let expected = path.read().into(); + let expected = AssetContent::file(path.read()); let actual = get_contents(actual, path).await?; let expected = get_contents(expected, path).await?; @@ -140,7 +137,7 @@ pub async fn diff(path: FileSystemPathVc, actual: AssetContentVc) -> Result<()> Ok(()) } -async fn get_contents(file: AssetContentVc, path: FileSystemPathVc) -> Result> { +async fn get_contents(file: Vc, path: Vc) -> Result> { Ok( match &*file.await.context(format!( "Unable to read AssetContent of {}", @@ -163,8 +160,8 @@ async fn get_contents(file: AssetContentVc, path: FileSystemPathVc) -> Result Result<()> { - let fs = DiskFileSystemVc::resolve_from(path.fs()) +async fn remove_file(path: Vc) -> Result<()> { + let fs = Vc::try_resolve_downcast_type::(path.fs()) .await? .context(anyhow!("unexpected fs type"))? .await?; @@ -174,12 +171,12 @@ async fn remove_file(path: FileSystemPathVc) -> Result<()> { } /// Values in left that are not in right. -/// FileSystemPathVc hashes as a Vc, not as the file path, so we need to get the -/// path to properly diff. +/// Vc hashes as a Vc, not as the file path, so we need to get +/// the path to properly diff. async fn diff_paths( - left: &HashSet, - right: &HashSet, -) -> Result> { + left: &HashSet>, + right: &HashSet>, +) -> Result>> { let mut map = left .iter() .map(|p| async move { Ok((p.await?.path.clone(), *p)) }) diff --git a/crates/turbopack-tests/tests/snapshot.rs b/crates/turbopack-tests/tests/snapshot.rs index 90be2f1cd48399..305deca6c08dd1 100644 --- a/crates/turbopack-tests/tests/snapshot.rs +++ b/crates/turbopack-tests/tests/snapshot.rs @@ -10,50 +10,45 @@ use anyhow::{anyhow, Context, Result}; use dunce::canonicalize; use once_cell::sync::Lazy; use serde::Deserialize; -use turbo_tasks::{debug::ValueDebug, NothingVc, TryJoinIterExt, TurboTasks, Value, ValueToString}; -use turbo_tasks_env::DotenvProcessEnvVc; +use turbo_tasks::{ + debug::ValueDebug, unit, ReadRef, TryJoinIterExt, TurboTasks, Value, ValueToString, Vc, +}; +use turbo_tasks_env::DotenvProcessEnv; use turbo_tasks_fs::{ - json::parse_json_with_source_context, util::sys_to_unix, DiskFileSystemVc, FileSystem, - FileSystemPathReadRef, FileSystemPathVc, + json::parse_json_with_source_context, util::sys_to_unix, DiskFileSystem, FileSystem, + FileSystemPath, }; use turbo_tasks_memory::MemoryBackend; use turbopack::{ condition::ContextCondition, - ecmascript::{EcmascriptModuleAssetVc, TransformPluginVc}, - module_options::{ - CustomEcmascriptTransformPlugins, CustomEcmascriptTransformPluginsVc, JsxTransformOptions, - JsxTransformOptionsVc, ModuleOptionsContext, - }, + ecmascript::EcmascriptModuleAsset, + module_options::{CustomEcmascriptTransformPlugins, JsxTransformOptions, ModuleOptionsContext}, resolve_options_context::ResolveOptionsContext, - transition::TransitionsByNameVc, - ModuleAssetContextVc, + ModuleAssetContext, }; -use turbopack_build::BuildChunkingContextVc; +use turbopack_build::BuildChunkingContext; use turbopack_core::{ - asset::{Asset, AssetVc}, - chunk::{ - ChunkableAsset, ChunkableAssetVc, ChunkingContext, ChunkingContextVc, EvaluatableAssetVc, - EvaluatableAssetsVc, - }, + asset::Asset, + chunk::{ChunkableAsset, ChunkingContext, EvaluatableAssetExt, EvaluatableAssets}, compile_time_defines, compile_time_info::CompileTimeInfo, - context::{AssetContext, AssetContextVc}, + context::AssetContext, environment::{ - BrowserEnvironment, EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, + BrowserEnvironment, Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment, }, - issue::IssueVc, + issue::{Issue, IssueContextExt}, reference::all_referenced_assets, reference_type::{EntryReferenceSubType, ReferenceType}, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; -use turbopack_dev::DevChunkingContextVc; +use turbopack_dev::DevChunkingContext; use turbopack_ecmascript_plugins::transform::{ emotion::{EmotionTransformConfig, EmotionTransformer}, styled_components::{StyledComponentsTransformConfig, StyledComponentsTransformer}, }; use turbopack_ecmascript_runtime::RuntimeType; -use turbopack_env::ProcessEnvAssetVc; +use turbopack_env::ProcessEnvAsset; use turbopack_test_utils::snapshot::{diff, expected, matches_expected, snapshot_issues}; fn register() { @@ -94,7 +89,7 @@ struct SnapshotOptions { #[serde(default = "default_runtime_type")] runtime_type: RuntimeType, #[serde(default)] - environment: Environment, + environment: SnapshotEnvironment, } #[derive(Debug, Deserialize, Default)] @@ -105,7 +100,7 @@ enum Runtime { } #[derive(Debug, Deserialize, Default)] -enum Environment { +enum SnapshotEnvironment { #[default] Browser, NodeJs, @@ -155,8 +150,9 @@ async fn run(resource: PathBuf) -> Result<()> { let tt = TurboTasks::new(MemoryBackend::default()); let task = tt.spawn_once_task(async move { - let out = run_test(resource.to_str().unwrap()); - let captured_issues = IssueVc::peek_issues_with_path(out) + let out = run_test(resource.to_str().unwrap().to_string()); + let captured_issues = out + .peek_issues_with_path() .await? .strongly_consistent() .await?; @@ -174,12 +170,12 @@ async fn run(resource: PathBuf) -> Result<()> { snapshot_issues( plain_issues.into_iter(), - out.join("issues"), + out.join("issues".to_string()), &WORKSPACE_ROOT, ) .await .context("Unable to handle issues")?; - Ok(NothingVc::new().into()) + Ok(unit().node) }); tt.wait_task_completion(task, true).await?; @@ -187,8 +183,8 @@ async fn run(resource: PathBuf) -> Result<()> { } #[turbo_tasks::function] -async fn run_test(resource: &str) -> Result { - let test_path = Path::new(resource); +async fn run_test(resource: String) -> Result> { + let test_path = Path::new(&resource); assert!(test_path.exists(), "{} does not exist", resource); assert!( test_path.is_dir(), @@ -201,21 +197,21 @@ async fn run_test(resource: &str) -> Result { Err(_) => SnapshotOptions::default(), Ok(options_str) => parse_json_with_source_context(&options_str).unwrap(), }; - let root_fs = DiskFileSystemVc::new("workspace".to_string(), WORKSPACE_ROOT.clone()); - let project_fs = DiskFileSystemVc::new("project".to_string(), WORKSPACE_ROOT.clone()); + let root_fs = DiskFileSystem::new("workspace".to_string(), WORKSPACE_ROOT.clone()); + let project_fs = DiskFileSystem::new("project".to_string(), WORKSPACE_ROOT.clone()); let project_root = project_fs.root(); let relative_path = test_path.strip_prefix(&*WORKSPACE_ROOT)?; let relative_path = sys_to_unix(relative_path.to_str().unwrap()); - let path = root_fs.root().join(&relative_path); - let project_path = project_root.join(&relative_path); + let path = root_fs.root().join(relative_path.to_string()); + let project_path = project_root.join(relative_path.to_string()); - let entry_asset = project_path.join(&options.entry); + let entry_asset = project_path.join(options.entry); let entry_paths = vec![entry_asset]; - let env = EnvironmentVc::new( + let env = Environment::new( Value::new(match options.environment { - Environment::Browser => { + SnapshotEnvironment::Browser => { ExecutionEnvironment::Browser( // TODO: load more from options.json BrowserEnvironment { @@ -227,7 +223,7 @@ async fn run_test(resource: &str) -> Result { .into(), ) } - Environment::NodeJs => { + SnapshotEnvironment::NodeJs => { ExecutionEnvironment::NodeJsBuildTime( // TODO: load more from options.json NodeJsEnvironment::default().into(), @@ -248,28 +244,28 @@ async fn run_test(resource: &str) -> Result { ) .cell(); - let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPluginsVc::cell( + let custom_ecma_transform_plugins = Some(CustomEcmascriptTransformPlugins::cell( CustomEcmascriptTransformPlugins { source_transforms: vec![ - TransformPluginVc::cell(Box::new( + Vc::cell(Box::new( EmotionTransformer::new(&EmotionTransformConfig { sourcemap: Some(false), ..Default::default() }) .expect("Should be able to create emotion transformer"), - )), - TransformPluginVc::cell(Box::new(StyledComponentsTransformer::new( + ) as _), + Vc::cell(Box::new(StyledComponentsTransformer::new( &StyledComponentsTransformConfig::default(), - ))), + )) as _), ], output_transforms: vec![], }, )); - let context: AssetContextVc = ModuleAssetContextVc::new( - TransitionsByNameVc::cell(HashMap::new()), + let context: Vc> = Vc::upcast(ModuleAssetContext::new( + Vc::cell(HashMap::new()), compile_time_info, ModuleOptionsContext { - enable_jsx: Some(JsxTransformOptionsVc::cell(JsxTransformOptions { + enable_jsx: Some(JsxTransformOptions::cell(JsxTransformOptions { development: true, ..Default::default() })), @@ -302,35 +298,31 @@ async fn run_test(resource: &str) -> Result { ..Default::default() } .cell(), - ) - .into(); + )); let runtime_entries = maybe_load_env(context, project_path) .await? - .map(|asset| EvaluatableAssetsVc::one(EvaluatableAssetVc::from_asset(asset, context))); - - let chunk_root_path = path.join("output"); - let static_root_path = path.join("static"); - let chunking_context: ChunkingContextVc = match options.runtime { - Runtime::Dev => DevChunkingContextVc::builder( - project_root, - path, - chunk_root_path, - static_root_path, - env, - ) - .runtime_type(options.runtime_type) - .build(), - Runtime::Build => BuildChunkingContextVc::builder( - project_root, - path, - chunk_root_path, - static_root_path, - env, - ) - .runtime_type(options.runtime_type) - .build() - .into(), + .map(|asset| EvaluatableAssets::one(asset.to_evaluatable(context))); + + let chunk_root_path = path.join("output".to_string()); + let static_root_path = path.join("static".to_string()); + let chunking_context: Vc> = match options.runtime { + Runtime::Dev => { + DevChunkingContext::builder(project_root, path, chunk_root_path, static_root_path, env) + .runtime_type(options.runtime_type) + .build() + } + Runtime::Build => Vc::upcast( + BuildChunkingContext::builder( + project_root, + path, + chunk_root_path, + static_root_path, + env, + ) + .runtime_type(options.runtime_type) + .build(), + ), }; let expected_paths = expected(chunk_root_path) @@ -339,24 +331,28 @@ async fn run_test(resource: &str) -> Result { .copied() .collect(); - let modules = entry_paths.into_iter().map(SourceAssetVc::new).map(|p| { + let modules = entry_paths.into_iter().map(SourceAsset::new).map(|p| { context.process( - p.into(), + Vc::upcast(p), Value::new(ReferenceType::Entry(EntryReferenceSubType::Undefined)), ) }); let chunk_groups = modules .map(|module| async move { - if let Some(ecmascript) = EcmascriptModuleAssetVc::resolve_from(module).await? { + if let Some(ecmascript) = + Vc::try_resolve_downcast_type::(module).await? + { // TODO: Load runtime entries from snapshots Ok(chunking_context.evaluated_chunk_group( ecmascript.as_root_chunk(chunking_context), runtime_entries - .unwrap_or_else(EvaluatableAssetsVc::empty) - .with_entry(ecmascript.into()), + .unwrap_or_else(EvaluatableAssets::empty) + .with_entry(Vc::upcast(ecmascript)), )) - } else if let Some(chunkable) = ChunkableAssetVc::resolve_from(module).await? { + } else if let Some(chunkable) = + Vc::try_resolve_sidecast::>(module).await? + { Ok(chunking_context.chunk_group(chunkable.as_root_chunk(chunking_context))) } else { // TODO convert into a serve-able asset @@ -399,10 +395,10 @@ async fn run_test(resource: &str) -> Result { } async fn walk_asset( - asset: AssetVc, - output_path: &FileSystemPathReadRef, - seen: &mut HashSet, - queue: &mut VecDeque, + asset: Vc>, + output_path: &ReadRef, + seen: &mut HashSet>, + queue: &mut VecDeque>>, ) -> Result<()> { let path = asset.ident().path().resolve().await?; @@ -410,7 +406,7 @@ async fn walk_asset( return Ok(()); } - if path.await?.is_inside(output_path) { + if path.await?.is_inside_ref(output_path) { // Only consider assets that should be written to disk. diff(path, asset.content()).await?; } @@ -421,16 +417,16 @@ async fn walk_asset( } async fn maybe_load_env( - _context: AssetContextVc, - path: FileSystemPathVc, -) -> Result> { - let dotenv_path = path.join("input/.env"); + _context: Vc>, + path: Vc, +) -> Result>>> { + let dotenv_path = path.join("input/.env".to_string()); if !dotenv_path.read().await?.is_content() { return Ok(None); } - let env = DotenvProcessEnvVc::new(None, dotenv_path); - let asset = ProcessEnvAssetVc::new(dotenv_path, env.into()); - Ok(Some(asset.into())) + let env = DotenvProcessEnv::new(None, dotenv_path); + let asset = ProcessEnvAsset::new(dotenv_path, Vc::upcast(env)); + Ok(Some(Vc::upcast(asset))) } diff --git a/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-b5c990.txt b/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-5567c6.txt similarity index 59% rename from crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-b5c990.txt rename to crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-5567c6.txt index a3290a6eaf2cd8..f2c3813dddcbeb 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-b5c990.txt +++ b/crates/turbopack-tests/tests/snapshot/imports/json/issues/Code generation for chunk item errored-5567c6.txt @@ -3,7 +3,7 @@ PlainIssue { context: "[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json", category: "code generation", title: "Code generation for chunk item errored", - description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }", + description: "An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of ::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }", detail: "", documentation_link: "", source: None, diff --git a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js index d95eee1e8894ee..2f99860355b503 100644 --- a/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js +++ b/crates/turbopack-tests/tests/snapshot/imports/json/output/crates_turbopack-tests_tests_snapshot_imports_json_input_index_b53fce.js @@ -2,7 +2,7 @@ "[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)": (() => {{ -throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of EcmascriptChunkItemContentVc::module_factory failed\n- Execution of JsonChunkItem::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }"); +throw new Error("An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n\nCaused by:\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n\nDebug info:\n- An error occurred while generating the chunk item [project]/crates/turbopack-tests/tests/snapshot/imports/json/input/invalid.json (json)\n- Execution of ::content failed\n- Unable to make a module from invalid JSON: expected `,` or `}` at line 3 column 26\n at nested.?\n 1 | {\n 2 | \"nested\": {\n | v\n 3 + \"this-is\": \"invalid\" // lint-staged will remove trailing commas, so here's a comment\n | ^\n 4 | }\n 5 | }"); }}), "[project]/crates/turbopack-tests/tests/snapshot/imports/json/input/package.json (json)": (({ r: __turbopack_require__, f: __turbopack_require_context__, i: __turbopack_import__, s: __turbopack_esm__, v: __turbopack_export_value__, n: __turbopack_export_namespace__, c: __turbopack_cache__, l: __turbopack_load__, j: __turbopack_cjs__, g: global, __dirname }) => (() => { diff --git a/crates/turbopack/benches/node_file_trace.rs b/crates/turbopack/benches/node_file_trace.rs index fd3b9a8c5cd32d..b38ee5ab7ac443 100644 --- a/crates/turbopack/benches/node_file_trace.rs +++ b/crates/turbopack/benches/node_file_trace.rs @@ -2,20 +2,19 @@ use std::{collections::HashMap, fs, path::PathBuf}; use criterion::{Bencher, BenchmarkId, Criterion}; use regex::Regex; -use turbo_tasks::{NothingVc, TurboTasks, Value}; -use turbo_tasks_fs::{DiskFileSystemVc, FileSystem, NullFileSystem, NullFileSystemVc}; +use turbo_tasks::{unit, TurboTasks, Value, Vc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem, NullFileSystem}; use turbo_tasks_memory::MemoryBackend; use turbopack::{ - emit_with_completion, module_options::ModuleOptionsContext, rebase::RebasedAssetVc, register, - resolve_options_context::ResolveOptionsContext, transition::TransitionsByNameVc, - ModuleAssetContextVc, + emit_with_completion, module_options::ModuleOptionsContext, rebase::RebasedAsset, register, + resolve_options_context::ResolveOptionsContext, ModuleAssetContext, }; use turbopack_core::{ compile_time_info::CompileTimeInfo, context::AssetContext, - environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, reference_type::ReferenceType, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; // TODO this should move to the `node-file-trace` crate @@ -72,23 +71,23 @@ fn bench_emit(b: &mut Bencher, bench_input: &BenchInput) { let input = bench_input.input.clone(); async move { let task = tt.spawn_once_task(async move { - let input_fs = DiskFileSystemVc::new("tests".to_string(), tests_root.clone()); - let input = input_fs.root().join(&input); + let input_fs = DiskFileSystem::new("tests".to_string(), tests_root.clone()); + let input = input_fs.root().join(input.clone()); let input_dir = input.parent().parent(); - let output_fs: NullFileSystemVc = NullFileSystem.into(); + let output_fs: Vc = NullFileSystem.into(); let output_dir = output_fs.root(); - let source = SourceAssetVc::new(input); - let compile_time_info = CompileTimeInfo::builder(EnvironmentVc::new( + let source = SourceAsset::new(input); + let compile_time_info = CompileTimeInfo::builder(Environment::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment::default().into(), )), Value::new(EnvironmentIntention::ServerRendering), )) .cell(); - let context = ModuleAssetContextVc::new( - TransitionsByNameVc::cell(HashMap::new()), + let context = ModuleAssetContext::new( + Vc::cell(HashMap::new()), compile_time_info, ModuleOptionsContext { enable_types: true, @@ -101,12 +100,13 @@ fn bench_emit(b: &mut Bencher, bench_input: &BenchInput) { } .cell(), ); - let module = context.process(source.into(), Value::new(ReferenceType::Undefined)); - let rebased = RebasedAssetVc::new(module, input_dir, output_dir); + let module = + context.process(Vc::upcast(source), Value::new(ReferenceType::Undefined)); + let rebased = RebasedAsset::new(module, input_dir, output_dir); - emit_with_completion(rebased.into(), output_dir).await?; + emit_with_completion(Vc::upcast(rebased), output_dir).await?; - Ok(NothingVc::new().into()) + Ok(unit().node) }); tt.wait_task_completion(task, true).await.unwrap(); } diff --git a/crates/turbopack/examples/turbopack.rs b/crates/turbopack/examples/turbopack.rs index 328cc1a5b468cb..c7809e4b0359a2 100644 --- a/crates/turbopack/examples/turbopack.rs +++ b/crates/turbopack/examples/turbopack.rs @@ -1,6 +1,4 @@ #![feature(trivial_bounds)] -#![feature(once_cell)] -#![feature(min_specialization)] use std::{ collections::HashMap, @@ -12,23 +10,23 @@ use std::{ use anyhow::Result; use tokio::{spawn, time::sleep}; use turbo_tasks::{ - util::FormatDuration, NothingVc, TurboTasks, TurboTasksBackendApi, UpdateInfo, Value, + unit, util::FormatDuration, TurboTasks, TurboTasksBackendApi, UpdateInfo, Value, Vc, }; -use turbo_tasks_fs::{DiskFileSystemVc, FileSystem, FileSystemVc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem}; use turbo_tasks_memory::{ stats::{ReferenceType, Stats}, viz::graph::{visualize_stats_tree, wrap_html}, MemoryBackend, }; use turbopack::{ - emit_with_completion, rebase::RebasedAssetVc, register, - resolve_options_context::ResolveOptionsContext, transition::TransitionsByNameVc, + emit_with_completion, rebase::RebasedAsset, register, + resolve_options_context::ResolveOptionsContext, }; use turbopack_core::{ - compile_time_info::CompileTimeInfoVc, + compile_time_info::CompileTimeInfo, context::AssetContext, - environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, - source_asset::SourceAssetVc, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, + source_asset::SourceAsset, PROJECT_FILESYSTEM_NAME, }; @@ -42,19 +40,19 @@ async fn main() -> Result<()> { let task = tt.spawn_root_task(|| { Box::pin(async { let root = current_dir().unwrap().to_str().unwrap().to_string(); - let disk_fs = DiskFileSystemVc::new(PROJECT_FILESYSTEM_NAME.to_string(), root); + let disk_fs = DiskFileSystem::new(PROJECT_FILESYSTEM_NAME.to_string(), root); disk_fs.await?.start_watching()?; // Smart Pointer cast - let fs: FileSystemVc = disk_fs.into(); - let input = fs.root().join("demo"); - let output = fs.root().join("out"); - let entry = fs.root().join("demo/index.js"); - - let source = SourceAssetVc::new(entry); - let context = turbopack::ModuleAssetContextVc::new( - TransitionsByNameVc::cell(HashMap::new()), - CompileTimeInfoVc::new(EnvironmentVc::new( + let fs: Vc> = Vc::upcast(disk_fs); + let input = fs.root().join("demo".to_string()); + let output = fs.root().join("out".to_string()); + let entry = fs.root().join("demo/index.js".to_string()); + + let source = SourceAsset::new(entry); + let context = turbopack::ModuleAssetContext::new( + Vc::cell(HashMap::new()), + CompileTimeInfo::new(Environment::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment::default().into(), )), @@ -71,13 +69,13 @@ async fn main() -> Result<()> { .cell(), ); let module = context.process( - source.into(), + Vc::upcast(source), Value::new(turbopack_core::reference_type::ReferenceType::Undefined), ); - let rebased = RebasedAssetVc::new(module, input, output); - emit_with_completion(rebased.into(), output).await?; + let rebased = RebasedAsset::new(module, input, output); + emit_with_completion(Vc::upcast(rebased), output).await?; - Ok(NothingVc::new().into()) + Ok(unit().node) }) }); spawn({ diff --git a/crates/turbopack/src/condition.rs b/crates/turbopack/src/condition.rs index 4b732ece7d25f3..52a874e1503f19 100644 --- a/crates/turbopack/src/condition.rs +++ b/crates/turbopack/src/condition.rs @@ -2,8 +2,8 @@ use anyhow::Result; use async_recursion::async_recursion; use futures::{stream, StreamExt}; use serde::{Deserialize, Serialize}; -use turbo_tasks::trace::TraceRawVcs; -use turbo_tasks_fs::{FileSystemPath, FileSystemPathVc}; +use turbo_tasks::{trace::TraceRawVcs, Vc}; +use turbo_tasks_fs::FileSystemPath; #[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq)] pub enum ContextCondition { @@ -11,7 +11,7 @@ pub enum ContextCondition { Any(Vec), Not(Box), InDirectory(String), - InPath(FileSystemPathVc), + InPath(Vc), } impl ContextCondition { @@ -50,7 +50,7 @@ impl ContextCondition { .await } ContextCondition::Not(condition) => condition.matches(context).await.map(|b| !b), - ContextCondition::InPath(path) => Ok(context.is_inside(&*path.await?)), + ContextCondition::InPath(path) => Ok(context.is_inside_ref(&*path.await?)), ContextCondition::InDirectory(dir) => Ok(context.path.starts_with(&format!("{dir}/")) || context.path.contains(&format!("/{dir}/")) || context.path.ends_with(&format!("/{dir}")) diff --git a/crates/turbopack/src/evaluate_context.rs b/crates/turbopack/src/evaluate_context.rs index 72ec8ff21a0b09..bf5e6638154828 100644 --- a/crates/turbopack/src/evaluate_context.rs +++ b/crates/turbopack/src/evaluate_context.rs @@ -1,24 +1,24 @@ use anyhow::Result; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbo_tasks_env::ProcessEnv; use turbo_tasks_fs::FileSystem; use turbopack_core::{ compile_time_defines, compile_time_info::CompileTimeInfo, - context::AssetContextVc, - environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, - resolve::options::{ImportMap, ImportMapVc, ImportMapping}, + context::AssetContext, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, + resolve::options::{ImportMap, ImportMapping}, }; -use turbopack_node::execution_context::ExecutionContextVc; +use turbopack_node::execution_context::ExecutionContext; use crate::{ module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext, - transition::TransitionsByNameVc, ModuleAssetContextVc, + transition::TransitionsByName, ModuleAssetContext, }; #[turbo_tasks::function] -pub fn node_build_environment() -> EnvironmentVc { - EnvironmentVc::new( +pub fn node_build_environment() -> Vc { + Environment::new( Value::new(ExecutionEnvironment::NodeJsBuildTime( NodeJsEnvironment::default().cell(), )), @@ -28,10 +28,10 @@ pub fn node_build_environment() -> EnvironmentVc { #[turbo_tasks::function] pub async fn node_evaluate_asset_context( - execution_context: ExecutionContextVc, - import_map: Option, - transitions: Option, -) -> Result { + execution_context: Vc, + import_map: Option>, + transitions: Option>, +) -> Result>> { let mut import_map = if let Some(import_map) = import_map { import_map.await?.clone_value() } else { @@ -46,13 +46,14 @@ pub async fn node_evaluate_asset_context( .cell(), ); let import_map = import_map.cell(); - let node_env = if let Some(node_env) = &*execution_context.env().read("NODE_ENV").await? { - node_env.clone() - } else { - "development".to_string() - }; - Ok(ModuleAssetContextVc::new( - transitions.unwrap_or_else(|| TransitionsByNameVc::cell(Default::default())), + let node_env = + if let Some(node_env) = &*execution_context.env().read("NODE_ENV".to_string()).await? { + node_env.clone() + } else { + "development".to_string() + }; + Ok(Vc::upcast(ModuleAssetContext::new( + transitions.unwrap_or_else(|| Vc::cell(Default::default())), CompileTimeInfo::builder(node_build_environment()) .defines( compile_time_defines!( @@ -77,6 +78,5 @@ pub async fn node_evaluate_asset_context( ..Default::default() } .cell(), - ) - .as_asset_context()) + ))) } diff --git a/crates/turbopack/src/graph/mod.rs b/crates/turbopack/src/graph/mod.rs index c5f01f2574f8e4..378186151bc14f 100644 --- a/crates/turbopack/src/graph/mod.rs +++ b/crates/turbopack/src/graph/mod.rs @@ -1,22 +1,23 @@ use std::collections::HashSet; use anyhow::Result; -use turbopack_core::{asset::AssetVc, reference::all_referenced_assets}; +use turbo_tasks::Vc; +use turbopack_core::{asset::Asset, reference::all_referenced_assets}; #[turbo_tasks::value(shared)] pub enum AggregatedGraph { - Leaf(AssetVc), + Leaf(Vc>), Node { depth: usize, - content: HashSet, - references: HashSet, + content: HashSet>, + references: HashSet>, }, } #[turbo_tasks::value_impl] -impl AggregatedGraphVc { +impl AggregatedGraph { #[turbo_tasks::function] - fn leaf(asset: AssetVc) -> Self { + fn leaf(asset: Vc>) -> Vc { Self::cell(AggregatedGraph::Leaf(asset)) } } @@ -31,9 +32,9 @@ impl AggregatedGraph { } #[turbo_tasks::value_impl] -impl AggregatedGraphVc { +impl AggregatedGraph { #[turbo_tasks::function] - pub async fn content(self) -> Result { + pub async fn content(self: Vc) -> Result> { Ok(match *self.await? { AggregatedGraph::Leaf(asset) => AggregatedGraphNodeContent::Asset(asset).into(), AggregatedGraph::Node { ref content, .. } => { @@ -43,14 +44,14 @@ impl AggregatedGraphVc { } #[turbo_tasks::function] - async fn references(self) -> Result { + async fn references(self: Vc) -> Result> { Ok(match *self.await? { AggregatedGraph::Leaf(asset) => { let mut refs = HashSet::new(); for reference in all_referenced_assets(asset).await?.iter() { let reference = reference.resolve().await?; if asset != reference { - refs.insert(AggregatedGraphVc::leaf(reference)); + refs.insert(AggregatedGraph::leaf(reference)); } } AggregatedGraphsSet { set: refs }.into() @@ -71,7 +72,7 @@ impl AggregatedGraphVc { } #[turbo_tasks::function] - async fn cost(self) -> Result { + async fn cost(self: Vc) -> Result> { Ok(match *self.await? { AggregatedGraph::Leaf(asset) => { AggregationCost(all_referenced_assets(asset).await?.len()).into() @@ -83,7 +84,7 @@ impl AggregatedGraphVc { } #[turbo_tasks::function] - async fn valued_references(self) -> Result { + async fn valued_references(self: Vc) -> Result> { let self_cost = self.cost().await?.0; let mut inner = HashSet::new(); let mut outer = HashSet::new(); @@ -115,8 +116,8 @@ impl AggregatedGraphVc { } #[turbo_tasks::function] -pub async fn aggregate(asset: AssetVc) -> Result { - let mut current = AggregatedGraphVc::leaf(asset); +pub async fn aggregate(asset: Vc>) -> Result> { + let mut current = AggregatedGraph::leaf(asset); loop { if current.references().await?.set.is_empty() { return Ok(current); @@ -130,7 +131,7 @@ pub async fn aggregate(asset: AssetVc) -> Result { struct AggregationCost(usize); #[turbo_tasks::function] -async fn aggregate_more(node: AggregatedGraphVc) -> Result { +async fn aggregate_more(node: Vc) -> Result> { let node_data = node.await?; let depth = node_data.depth(); let mut in_progress = HashSet::new(); @@ -183,18 +184,18 @@ async fn aggregate_more(node: AggregatedGraphVc) -> Result { #[turbo_tasks::value(shared)] struct AggregatedGraphsSet { - pub set: HashSet, + pub set: HashSet>, } #[turbo_tasks::value(shared)] pub enum AggregatedGraphNodeContent { - Asset(AssetVc), - Children(HashSet), + Asset(Vc>), + Children(HashSet>), } #[turbo_tasks::value(shared)] struct AggregatedGraphsValuedReferences { - pub inner: HashSet, - pub outer: HashSet, - pub references: HashSet, + pub inner: HashSet>, + pub outer: HashSet>, + pub references: HashSet>, } diff --git a/crates/turbopack/src/lib.rs b/crates/turbopack/src/lib.rs index 57db670a0940e3..fbfb20329c7970 100644 --- a/crates/turbopack/src/lib.rs +++ b/crates/turbopack/src/lib.rs @@ -3,9 +3,20 @@ #![feature(min_specialization)] #![feature(map_try_insert)] #![feature(option_get_or_insert_default)] -#![feature(once_cell)] #![feature(hash_set_entry)] #![recursion_limit = "256"] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] + +pub mod condition; +pub mod evaluate_context; +mod graph; +pub mod module_options; +pub mod rebase; +pub mod resolve; +pub mod resolve_options_context; +pub mod transition; +pub(crate) mod unsupported_sass; use std::{ collections::{HashMap, HashSet}, @@ -13,97 +24,77 @@ use std::{ }; use anyhow::Result; -use css::{CssModuleAssetVc, ModuleCssModuleAssetVc}; +use css::{CssModuleAsset, ModuleCssModuleAsset}; use ecmascript::{ - typescript::resolve::TypescriptTypesAssetReferenceVc, EcmascriptModuleAssetType, - EcmascriptModuleAssetVc, -}; -use graph::{aggregate, AggregatedGraphNodeContent, AggregatedGraphVc}; -use module_options::{ - ModuleOptionsContextVc, ModuleOptionsVc, ModuleRuleEffect, ModuleType, ModuleTypeVc, + typescript::resolve::TypescriptTypesAssetReference, EcmascriptModuleAsset, + EcmascriptModuleAssetType, }; +use graph::{aggregate, AggregatedGraph, AggregatedGraphNodeContent}; +use module_options::{ModuleOptions, ModuleOptionsContext, ModuleRuleEffect, ModuleType}; pub use resolve::resolve_options; -use turbo_tasks::{ - primitives::{BoolVc, StringVc}, - CompletionVc, Value, -}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{Completion, Value, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetVc}, - compile_time_info::CompileTimeInfoVc, - context::{AssetContext, AssetContextVc}, - ident::AssetIdentVc, - issue::{Issue, IssueVc}, + asset::Asset, + compile_time_info::CompileTimeInfo, + context::AssetContext, + ident::AssetIdent, + issue::{Issue, IssueExt}, plugin::CustomModuleType, reference::all_referenced_assets, - reference_type::{EcmaScriptModulesReferenceSubType, InnerAssetsVc, ReferenceType}, + reference_type::{EcmaScriptModulesReferenceSubType, InnerAssets, ReferenceType}, resolve::{ - options::ResolveOptionsVc, origin::PlainResolveOriginVc, parse::RequestVc, resolve, - ModulePartVc, ResolveResultVc, + options::ResolveOptions, origin::PlainResolveOrigin, parse::Request, resolve, ModulePart, + ResolveResult, }, }; - -use crate::transition::Transition; - -pub mod condition; -pub mod evaluate_context; -mod graph; -pub mod module_options; -pub mod rebase; -pub mod resolve; -pub mod resolve_options_context; -pub mod transition; -pub(crate) mod unsupported_sass; - pub use turbopack_css as css; pub use turbopack_ecmascript as ecmascript; -use turbopack_json::JsonModuleAssetVc; -use turbopack_mdx::MdxModuleAssetVc; -use turbopack_static::StaticModuleAssetVc; +use turbopack_json::JsonModuleAsset; +use turbopack_mdx::MdxModuleAsset; +use turbopack_static::StaticModuleAsset; -use self::{ - resolve_options_context::ResolveOptionsContextVc, - transition::{TransitionVc, TransitionsByNameVc}, -}; +use self::{resolve_options_context::ResolveOptionsContext, transition::TransitionsByName}; +use crate::transition::Transition; #[turbo_tasks::value] struct ModuleIssue { - ident: AssetIdentVc, - title: StringVc, - description: StringVc, + ident: Vc, + title: Vc, + description: Vc, } #[turbo_tasks::value_impl] impl Issue for ModuleIssue { #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("other".to_string()) + fn category(&self) -> Vc { + Vc::cell("other".to_string()) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.ident.path() } #[turbo_tasks::function] - fn title(&self) -> StringVc { + fn title(&self) -> Vc { self.title } #[turbo_tasks::function] - fn description(&self) -> StringVc { + fn description(&self) -> Vc { self.description } } #[turbo_tasks::function] async fn apply_module_type( - source: AssetVc, - context: ModuleAssetContextVc, - module_type: ModuleTypeVc, - part: Option, - inner_assets: Option, -) -> Result { + source: Vc>, + context: Vc, + module_type: Vc, + part: Option>, + inner_assets: Option>, +) -> Result>> { let module_type = &*module_type.await?; Ok(match module_type { ModuleType::Ecmascript { @@ -129,9 +120,9 @@ async fn apply_module_type( } _ => context, }; - let mut builder = EcmascriptModuleAssetVc::builder( + let mut builder = EcmascriptModuleAsset::builder( source, - context_for_module.into(), + Vc::upcast(context_for_module), *transforms, *options, context.compile_time_info(), @@ -165,42 +156,51 @@ async fn apply_module_type( builder.build() } - ModuleType::Json => JsonModuleAssetVc::new(source).into(), + ModuleType::Json => Vc::upcast(JsonModuleAsset::new(source)), ModuleType::Raw => source, - ModuleType::Css(transforms) => { - CssModuleAssetVc::new(source, context.into(), *transforms).into() - } - ModuleType::CssModule(transforms) => { - ModuleCssModuleAssetVc::new(source, context.into(), *transforms).into() - } - ModuleType::Static => StaticModuleAssetVc::new(source, context.into()).into(), + ModuleType::Css(transforms) => Vc::upcast(CssModuleAsset::new( + source, + Vc::upcast(context), + *transforms, + )), + ModuleType::CssModule(transforms) => Vc::upcast(ModuleCssModuleAsset::new( + source, + Vc::upcast(context), + *transforms, + )), + ModuleType::Static => Vc::upcast(StaticModuleAsset::new(source, Vc::upcast(context))), ModuleType::Mdx { transforms, options, - } => MdxModuleAssetVc::new(source, context.into(), *transforms, *options).into(), - ModuleType::Custom(custom) => custom.create_module(source, context.into(), part), + } => Vc::upcast(MdxModuleAsset::new( + source, + Vc::upcast(context), + *transforms, + *options, + )), + ModuleType::Custom(custom) => custom.create_module(source, Vc::upcast(context), part), }) } #[turbo_tasks::value] #[derive(Debug)] pub struct ModuleAssetContext { - pub transitions: TransitionsByNameVc, - pub compile_time_info: CompileTimeInfoVc, - pub module_options_context: ModuleOptionsContextVc, - pub resolve_options_context: ResolveOptionsContextVc, - transition: Option, + pub transitions: Vc, + pub compile_time_info: Vc, + pub module_options_context: Vc, + pub resolve_options_context: Vc, + transition: Option>>, } #[turbo_tasks::value_impl] -impl ModuleAssetContextVc { +impl ModuleAssetContext { #[turbo_tasks::function] pub fn new( - transitions: TransitionsByNameVc, - compile_time_info: CompileTimeInfoVc, - module_options_context: ModuleOptionsContextVc, - resolve_options_context: ResolveOptionsContextVc, - ) -> Self { + transitions: Vc, + compile_time_info: Vc, + module_options_context: Vc, + resolve_options_context: Vc, + ) -> Vc { Self::cell(ModuleAssetContext { transitions, compile_time_info, @@ -212,12 +212,12 @@ impl ModuleAssetContextVc { #[turbo_tasks::function] pub fn new_transition( - transitions: TransitionsByNameVc, - compile_time_info: CompileTimeInfoVc, - module_options_context: ModuleOptionsContextVc, - resolve_options_context: ResolveOptionsContextVc, - transition: TransitionVc, - ) -> Self { + transitions: Vc, + compile_time_info: Vc, + module_options_context: Vc, + resolve_options_context: Vc, + transition: Vc>, + ) -> Vc { Self::cell(ModuleAssetContext { transitions, compile_time_info, @@ -228,20 +228,18 @@ impl ModuleAssetContextVc { } #[turbo_tasks::function] - pub async fn module_options_context(self) -> Result { + pub async fn module_options_context(self: Vc) -> Result> { Ok(self.await?.module_options_context) } #[turbo_tasks::function] - pub async fn is_types_resolving_enabled(self) -> Result { + pub async fn is_types_resolving_enabled(self: Vc) -> Result> { let context = self.await?.resolve_options_context.await?; - Ok(BoolVc::cell( - context.enable_types && context.enable_typescript, - )) + Ok(Vc::cell(context.enable_types && context.enable_typescript)) } #[turbo_tasks::function] - pub async fn with_types_resolving_enabled(self) -> Result { + pub async fn with_types_resolving_enabled(self: Vc) -> Result> { if *self.is_types_resolving_enabled().await? { return Ok(self); } @@ -251,7 +249,7 @@ impl ModuleAssetContextVc { .with_types_enabled() .resolve() .await?; - Ok(ModuleAssetContextVc::new( + Ok(ModuleAssetContext::new( this.transitions, this.compile_time_info, this.module_options_context, @@ -261,26 +259,26 @@ impl ModuleAssetContextVc { #[turbo_tasks::function] fn process_default( - self_vc: ModuleAssetContextVc, - source: AssetVc, + self: Vc, + source: Vc>, reference_type: Value, - ) -> AssetVc { - process_default(self_vc, source, reference_type, Vec::new()) + ) -> Vc> { + process_default(self, source, reference_type, Vec::new()) } } #[turbo_tasks::function] async fn process_default( - context: ModuleAssetContextVc, - source: AssetVc, + context: Vc, + source: Vc>, reference_type: Value, processed_rules: Vec, -) -> Result { +) -> Result>> { let ident = source.ident().resolve().await?; - let options = ModuleOptionsVc::new(ident.path().parent(), context.module_options_context()); + let options = ModuleOptions::new(ident.path().parent(), context.module_options_context()); let reference_type = reference_type.into_value(); - let part: Option = match &reference_type { + let part: Option> = match &reference_type { ReferenceType::EcmaScriptModules(EcmaScriptModulesReferenceSubType::ImportPart(part)) => { Some(*part) } @@ -345,30 +343,28 @@ async fn process_default( Some(module_type) => { ModuleIssue { ident, - title: StringVc::cell("Invalid module type".to_string()), - description: StringVc::cell( + title: Vc::cell("Invalid module type".to_string()), + description: Vc::cell( "The module type must be Ecmascript or Typescript to add \ Ecmascript transforms" .to_string(), ), } .cell() - .as_issue() .emit(); Some(module_type) } None => { ModuleIssue { ident, - title: StringVc::cell("Missing module type".to_string()), - description: StringVc::cell( + title: Vc::cell("Missing module type".to_string()), + description: Vc::cell( "The module type effect must be applied before adding \ Ecmascript transforms" .to_string(), ), } .cell() - .as_issue() .emit(); None } @@ -393,21 +389,21 @@ async fn process_default( #[turbo_tasks::value_impl] impl AssetContext for ModuleAssetContext { #[turbo_tasks::function] - fn compile_time_info(&self) -> CompileTimeInfoVc { + fn compile_time_info(&self) -> Vc { self.compile_time_info } #[turbo_tasks::function] async fn resolve_options( - self_vc: ModuleAssetContextVc, - origin_path: FileSystemPathVc, + self: Vc, + origin_path: Vc, _reference_type: Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result> { + let this = self.await?; let context = if let Some(transition) = this.transition { - transition.process_context(self_vc) + transition.process_context(self) } else { - self_vc + self }; // TODO move `apply_commonjs/esm_resolve_options` etc. to here Ok(resolve_options( @@ -418,24 +414,24 @@ impl AssetContext for ModuleAssetContext { #[turbo_tasks::function] async fn resolve_asset( - self_vc: ModuleAssetContextVc, - origin_path: FileSystemPathVc, - request: RequestVc, - resolve_options: ResolveOptionsVc, + self: Vc, + origin_path: Vc, + request: Vc, + resolve_options: Vc, reference_type: Value, - ) -> Result { + ) -> Result> { let context_path = origin_path.parent().resolve().await?; let result = resolve(context_path, request, resolve_options); - let result = self_vc.process_resolve_result(result, reference_type); + let result = self.process_resolve_result(result, reference_type); - if *self_vc.is_types_resolving_enabled().await? { - let types_reference = TypescriptTypesAssetReferenceVc::new( - PlainResolveOriginVc::new(self_vc.into(), origin_path).into(), + if *self.is_types_resolving_enabled().await? { + let types_reference = TypescriptTypesAssetReference::new( + Vc::upcast(PlainResolveOrigin::new(Vc::upcast(self), origin_path)), request, ); - result.add_reference(types_reference.into()); + result.add_reference(Vc::upcast(types_reference)); } Ok(result) @@ -443,14 +439,14 @@ impl AssetContext for ModuleAssetContext { #[turbo_tasks::function] async fn process_resolve_result( - self_vc: ModuleAssetContextVc, - result: ResolveResultVc, + self: Vc, + result: Vc, reference_type: Value, - ) -> Result { + ) -> Result> { Ok(result .await? .map( - |a| self_vc.process(a, reference_type.clone()).resolve(), + |a| self.process(a, reference_type.clone()).resolve(), |i| async move { Ok(i) }, ) .await? @@ -458,96 +454,102 @@ impl AssetContext for ModuleAssetContext { } #[turbo_tasks::function] async fn process( - self_vc: ModuleAssetContextVc, - asset: AssetVc, + self: Vc, + asset: Vc>, reference_type: Value, - ) -> Result { - let this = self_vc.await?; + ) -> Result>> { + let this = self.await?; if let Some(transition) = this.transition { - Ok(transition.process(asset, self_vc, reference_type)) + Ok(transition.process(asset, self, reference_type)) } else { - Ok(self_vc.process_default(asset, reference_type)) + Ok(self.process_default(asset, reference_type)) } } #[turbo_tasks::function] - async fn with_transition(&self, transition: &str) -> Result { + async fn with_transition(&self, transition: String) -> Result>> { Ok( - if let Some(transition) = self.transitions.await?.get(transition) { - ModuleAssetContextVc::new_transition( + if let Some(transition) = self.transitions.await?.get(&transition) { + Vc::upcast(ModuleAssetContext::new_transition( self.transitions, self.compile_time_info, self.module_options_context, self.resolve_options_context, *transition, - ) - .into() + )) } else { // TODO report issue - ModuleAssetContextVc::new( + Vc::upcast(ModuleAssetContext::new( self.transitions, self.compile_time_info, self.module_options_context, self.resolve_options_context, - ) - .into() + )) }, ) } } #[turbo_tasks::function] -pub async fn emit_with_completion(asset: AssetVc, output_dir: FileSystemPathVc) -> CompletionVc { +pub async fn emit_with_completion( + asset: Vc>, + output_dir: Vc, +) -> Vc { emit_assets_aggregated(asset, output_dir) } #[turbo_tasks::function] -async fn emit_assets_aggregated(asset: AssetVc, output_dir: FileSystemPathVc) -> CompletionVc { +async fn emit_assets_aggregated( + asset: Vc>, + output_dir: Vc, +) -> Vc { let aggregated = aggregate(asset); emit_aggregated_assets(aggregated, output_dir) } #[turbo_tasks::function] async fn emit_aggregated_assets( - aggregated: AggregatedGraphVc, - output_dir: FileSystemPathVc, -) -> Result { + aggregated: Vc, + output_dir: Vc, +) -> Result> { Ok(match &*aggregated.content().await? { AggregatedGraphNodeContent::Asset(asset) => emit_asset_into_dir(*asset, output_dir), AggregatedGraphNodeContent::Children(children) => { for aggregated in children { emit_aggregated_assets(*aggregated, output_dir).await?; } - CompletionVc::new() + Completion::new() } }) } #[turbo_tasks::function] -pub async fn emit_asset(asset: AssetVc) -> CompletionVc { +pub async fn emit_asset(asset: Vc>) -> Vc { asset.content().write(asset.ident().path()) } #[turbo_tasks::function] pub async fn emit_asset_into_dir( - asset: AssetVc, - output_dir: FileSystemPathVc, -) -> Result { + asset: Vc>, + output_dir: Vc, +) -> Result> { let dir = &*output_dir.await?; - Ok(if asset.ident().path().await?.is_inside(dir) { + Ok(if asset.ident().path().await?.is_inside_ref(dir) { emit_asset(asset) } else { - CompletionVc::new() + Completion::new() }) } +type AssetSet = HashSet>>; + #[turbo_tasks::value(shared)] struct ReferencesList { - referenced_by: HashMap>, + referenced_by: HashMap>, AssetSet>, } #[turbo_tasks::function] -async fn compute_back_references(aggregated: AggregatedGraphVc) -> Result { +async fn compute_back_references(aggregated: Vc) -> Result> { Ok(match &*aggregated.content().await? { AggregatedGraphNodeContent::Asset(asset) => { let mut referenced_by = HashMap::new(); @@ -557,7 +559,7 @@ async fn compute_back_references(aggregated: AggregatedGraphVc) -> Result { - let mut referenced_by = HashMap::>::new(); + let mut referenced_by = HashMap::>, AssetSet>::new(); let lists = children .iter() .map(|child| compute_back_references(*child)) @@ -579,10 +581,10 @@ async fn compute_back_references(aggregated: AggregatedGraphVc) -> Result Result { +async fn top_references(list: Vc) -> Result> { let list = list.await?; const N: usize = 5; - let mut top = Vec::<(&AssetVc, &HashSet)>::new(); + let mut top = Vec::<(&Vc>, &HashSet>>)>::new(); for tuple in list.referenced_by.iter() { let mut current = tuple; for item in &mut top { diff --git a/crates/turbopack/src/module_options/mod.rs b/crates/turbopack/src/module_options/mod.rs index 5ac0d264cd3d34..8c33dc3128bfd6 100644 --- a/crates/turbopack/src/module_options/mod.rs +++ b/crates/turbopack/src/module_options/mod.rs @@ -6,27 +6,24 @@ use anyhow::{Context, Result}; pub use module_options_context::*; pub use module_rule::*; pub use rule_condition::*; -use turbo_tasks::primitives::OptionStringVc; -use turbo_tasks_fs::{glob::GlobVc, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{glob::Glob, FileSystemPath}; use turbopack_core::{ reference_type::{ReferenceType, UrlReferenceSubType}, - resolve::options::{ImportMap, ImportMapVc, ImportMapping, ImportMappingVc}, - source_transform::SourceTransformsVc, -}; -use turbopack_css::{CssInputTransform, CssInputTransformsVc}; -use turbopack_ecmascript::{ - EcmascriptInputTransform, EcmascriptInputTransformsVc, EcmascriptOptions, SpecifiedModuleType, + resolve::options::{ImportMap, ImportMapping}, }; +use turbopack_css::CssInputTransform; +use turbopack_ecmascript::{EcmascriptInputTransform, EcmascriptOptions, SpecifiedModuleType}; use turbopack_mdx::MdxTransformOptions; -use turbopack_node::transforms::{postcss::PostCssTransformVc, webpack::WebpackLoadersVc}; +use turbopack_node::transforms::{postcss::PostCssTransform, webpack::WebpackLoaders}; use crate::evaluate_context::node_evaluate_asset_context; #[turbo_tasks::function] async fn package_import_map_from_import_mapping( - package_name: &str, - package_mapping: ImportMappingVc, -) -> Result { + package_name: String, + package_mapping: Vc, +) -> Result> { let mut import_map = ImportMap::default(); import_map.insert_exact_alias( format!("@vercel/turbopack/{}", package_name), @@ -37,13 +34,13 @@ async fn package_import_map_from_import_mapping( #[turbo_tasks::function] async fn package_import_map_from_context( - package_name: &str, - context_path: FileSystemPathVc, -) -> Result { + package_name: String, + context_path: Vc, +) -> Result> { let mut import_map = ImportMap::default(); import_map.insert_exact_alias( format!("@vercel/turbopack/{}", package_name), - ImportMapping::PrimaryAlternative(package_name.to_string(), Some(context_path)).cell(), + ImportMapping::PrimaryAlternative(package_name, Some(context_path)).cell(), ); Ok(import_map.cell()) } @@ -54,12 +51,12 @@ pub struct ModuleOptions { } #[turbo_tasks::value_impl] -impl ModuleOptionsVc { +impl ModuleOptions { #[turbo_tasks::function] pub async fn new( - path: FileSystemPathVc, - context: ModuleOptionsContextVc, - ) -> Result { + path: Vc, + context: Vc, + ) -> Result> { let ModuleOptionsContext { enable_jsx, enable_types, @@ -82,7 +79,7 @@ impl ModuleOptionsVc { for (condition, new_context) in rules.iter() { if condition.matches(&path_value).await? { - return Ok(ModuleOptionsVc::new(path, *new_context)); + return Ok(ModuleOptions::new(path, *new_context)); } } } @@ -120,8 +117,8 @@ impl ModuleOptionsVc { transforms.push(EcmascriptInputTransform::React { development: jsx.development, refresh: jsx.react_refresh, - import_source: OptionStringVc::cell(jsx.import_source.clone()), - runtime: OptionStringVc::cell(jsx.runtime.clone()), + import_source: Vc::cell(jsx.import_source.clone()), + runtime: Vc::cell(jsx.runtime.clone()), }); } @@ -159,14 +156,14 @@ impl ModuleOptionsVc { None }; - let vendor_transforms = EcmascriptInputTransformsVc::cell(vec![]); + let vendor_transforms = Vc::cell(vec![]); let ts_app_transforms = if let Some(transform) = &ts_transform { let base_transforms = if let Some(decorators_transform) = &decorators_transform { vec![decorators_transform.clone(), transform.clone()] } else { vec![transform.clone()] }; - EcmascriptInputTransformsVc::cell( + Vc::cell( base_transforms .iter() .cloned() @@ -175,11 +172,11 @@ impl ModuleOptionsVc { .collect(), ) } else { - EcmascriptInputTransformsVc::cell(transforms.clone()) + Vc::cell(transforms.clone()) }; - let css_transforms = CssInputTransformsVc::cell(vec![CssInputTransform::Nested]); - let mdx_transforms = EcmascriptInputTransformsVc::cell( + let css_transforms = Vc::cell(vec![CssInputTransform::Nested]); + let mdx_transforms = Vc::cell( if let Some(transform) = &ts_transform { if let Some(decorators_transform) = &decorators_transform { vec![decorators_transform.clone(), transform.clone()] @@ -204,7 +201,7 @@ impl ModuleOptionsVc { // Since typescript transform (`ts_app_transforms`) needs to apply decorators // _before_ stripping types, we create ts_app_transforms first in a // specific order with typescript, then apply decorators to app_transforms. - let app_transforms = EcmascriptInputTransformsVc::cell( + let app_transforms = Vc::cell( if let Some(decorators_transform) = &decorators_transform { vec![decorators_transform.clone()] } else { @@ -228,24 +225,26 @@ impl ModuleOptionsVc { if let Some(options) = enable_postcss_transform { let execution_context = execution_context .context("execution_context is required for the postcss_transform")? - .with_layer("postcss"); + .with_layer("postcss".to_string()); let import_map = if let Some(postcss_package) = options.postcss_package { - package_import_map_from_import_mapping("postcss", postcss_package) + package_import_map_from_import_mapping( + "postcss".to_string(), + postcss_package, + ) } else { - package_import_map_from_context("postcss", path) + package_import_map_from_context("postcss".to_string(), path) }; - Some(ModuleRuleEffect::SourceTransforms( - SourceTransformsVc::cell(vec![PostCssTransformVc::new( + Some(ModuleRuleEffect::SourceTransforms(Vc::cell(vec![ + Vc::upcast(PostCssTransform::new( node_evaluate_asset_context( execution_context, Some(import_map), None, ), execution_context, - ) - .into()]), - )) + )), + ]))) } else { None }, @@ -404,7 +403,7 @@ impl ModuleOptionsVc { }; let mdx_options = enable_mdx_rs - .unwrap_or(MdxTransformModuleOptionsVc::default()) + .unwrap_or(MdxTransformModuleOptions::default()) .await?; let mdx_transform_options = (MdxTransformOptions { @@ -432,23 +431,28 @@ impl ModuleOptionsVc { let webpack_loaders_options = webpack_loaders_options.await?; let execution_context = execution_context .context("execution_context is required for webpack_loaders")? - .with_layer("webpack_loaders"); + .with_layer("webpack_loaders".to_string()); let import_map = if let Some(loader_runner_package) = webpack_loaders_options.loader_runner_package { - package_import_map_from_import_mapping("loader-runner", loader_runner_package) + package_import_map_from_import_mapping( + "loader-runner".to_string(), + loader_runner_package, + ) } else { - package_import_map_from_context("loader-runner", path) + package_import_map_from_context("loader-runner".to_string(), path) }; for (glob, rule) in webpack_loaders_options.rules.await?.iter() { rules.push(ModuleRule::new( ModuleRuleCondition::All(vec![ if !glob.contains('/') { - ModuleRuleCondition::ResourceBasePathGlob(GlobVc::new(glob).await?) + ModuleRuleCondition::ResourceBasePathGlob( + Glob::new(glob.clone()).await?, + ) } else { ModuleRuleCondition::ResourcePathGlob { base: execution_context.project_path().await?, - glob: GlobVc::new(glob).await?, + glob: Glob::new(glob.clone()).await?, } }, ModuleRuleCondition::not(ModuleRuleCondition::ResourceIsVirtualAsset), @@ -460,8 +464,8 @@ impl ModuleOptionsVc { transforms: app_transforms, options: ecmascript_options, }), - ModuleRuleEffect::SourceTransforms(SourceTransformsVc::cell(vec![ - WebpackLoadersVc::new( + ModuleRuleEffect::SourceTransforms(Vc::cell(vec![Vc::upcast( + WebpackLoaders::new( node_evaluate_asset_context( execution_context, Some(import_map), @@ -470,9 +474,8 @@ impl ModuleOptionsVc { execution_context, rule.loaders, rule.rename_as.clone(), - ) - .into(), - ])), + ), + )])), ], )); } @@ -480,6 +483,6 @@ impl ModuleOptionsVc { rules.extend(custom_rules.iter().cloned()); - Ok(ModuleOptionsVc::cell(ModuleOptions { rules })) + Ok(ModuleOptions::cell(ModuleOptions { rules })) } } diff --git a/crates/turbopack/src/module_options/module_options_context.rs b/crates/turbopack/src/module_options/module_options_context.rs index 646a28460e68b0..6bb7b1d9a8d54f 100644 --- a/crates/turbopack/src/module_options/module_options_context.rs +++ b/crates/turbopack/src/module_options/module_options_context.rs @@ -1,10 +1,10 @@ use indexmap::IndexMap; use serde::{Deserialize, Serialize}; -use turbo_tasks::trace::TraceRawVcs; -use turbopack_core::{environment::EnvironmentVc, resolve::options::ImportMappingVc}; -use turbopack_ecmascript::TransformPluginVc; +use turbo_tasks::{trace::TraceRawVcs, ValueDefault, Vc}; +use turbopack_core::{environment::Environment, resolve::options::ImportMapping}; +use turbopack_ecmascript::TransformPlugin; use turbopack_node::{ - execution_context::ExecutionContextVc, transforms::webpack::WebpackLoaderItemsVc, + execution_context::ExecutionContext, transforms::webpack::WebpackLoaderItems, }; use super::ModuleRule; @@ -12,13 +12,13 @@ use crate::condition::ContextCondition; #[derive(Default, Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] pub struct PostCssTransformOptions { - pub postcss_package: Option, + pub postcss_package: Option>, pub placeholder_for_future_extensions: (), } #[derive(Clone, PartialEq, Eq, Debug, TraceRawVcs, Serialize, Deserialize)] pub struct LoaderRuleItem { - pub loaders: WebpackLoaderItemsVc, + pub loaders: Vc, pub rename_as: Option, } @@ -28,18 +28,18 @@ pub struct WebpackRules(IndexMap); #[derive(Default)] #[turbo_tasks::value(transparent)] -pub struct OptionWebpackRules(Option); +pub struct OptionWebpackRules(Option>); #[turbo_tasks::value(shared)] #[derive(Clone, Debug)] pub struct WebpackLoadersOptions { - pub rules: WebpackRulesVc, - pub loader_runner_package: Option, + pub rules: Vc, + pub loader_runner_package: Option>, } #[derive(Default)] #[turbo_tasks::value(transparent)] -pub struct OptionWebpackLoadersOptions(Option); +pub struct OptionWebpackLoadersOptions(Option>); /// The kind of decorators transform to use. /// [TODO]: might need bikeshed for the name (Ecma) @@ -71,16 +71,10 @@ pub struct DecoratorsOptions { } #[turbo_tasks::value_impl] -impl DecoratorsOptionsVc { +impl ValueDefault for DecoratorsOptions { #[turbo_tasks::function] - pub fn default() -> Self { - Self::cell(Default::default()) - } -} - -impl Default for DecoratorsOptionsVc { - fn default() -> Self { - Self::default() + fn value_default() -> Vc { + Self::default().cell() } } @@ -93,16 +87,10 @@ pub struct TypescriptTransformOptions { } #[turbo_tasks::value_impl] -impl TypescriptTransformOptionsVc { +impl ValueDefault for TypescriptTransformOptions { #[turbo_tasks::function] - pub fn default() -> Self { - Self::cell(Default::default()) - } -} - -impl Default for TypescriptTransformOptionsVc { - fn default() -> Self { - Self::default() + fn value_default() -> Vc { + Self::default().cell() } } @@ -122,10 +110,10 @@ pub struct JsxTransformOptions { pub struct CustomEcmascriptTransformPlugins { /// List of plugins to be applied before the main transform. /// Transform will be applied in the order of the list. - pub source_transforms: Vec, + pub source_transforms: Vec>, /// List of plugins to be applied after the main transform. /// Transform will be applied in the order of the list. - pub output_transforms: Vec, + pub output_transforms: Vec>, } #[turbo_tasks::value(shared)] @@ -139,9 +127,9 @@ pub struct MdxTransformModuleOptions { } #[turbo_tasks::value_impl] -impl MdxTransformModuleOptionsVc { +impl MdxTransformModuleOptions { #[turbo_tasks::function] - pub fn default() -> Self { + pub fn default() -> Vc { Self::cell(Default::default()) } } @@ -150,38 +138,32 @@ impl MdxTransformModuleOptionsVc { #[derive(Default, Clone)] #[serde(default)] pub struct ModuleOptionsContext { - pub enable_jsx: Option, + pub enable_jsx: Option>, pub enable_postcss_transform: Option, - pub enable_webpack_loaders: Option, + pub enable_webpack_loaders: Option>, pub enable_types: bool, - pub enable_typescript_transform: Option, - pub decorators: Option, + pub enable_typescript_transform: Option>, + pub decorators: Option>, pub enable_mdx: bool, // [Note]: currently mdx, and mdx_rs have different configuration entrypoint from next.config.js, // however we might want to unify them in the future. - pub enable_mdx_rs: Option, - pub preset_env_versions: Option, - pub custom_ecma_transform_plugins: Option, + pub enable_mdx_rs: Option>, + pub preset_env_versions: Option>, + pub custom_ecma_transform_plugins: Option>, /// Custom rules to be applied after all default rules. pub custom_rules: Vec, - pub execution_context: Option, + pub execution_context: Option>, /// A list of rules to use a different module option context for certain /// context paths. The first matching is used. - pub rules: Vec<(ContextCondition, ModuleOptionsContextVc)>, + pub rules: Vec<(ContextCondition, Vc)>, pub placeholder_for_future_extensions: (), pub enable_tree_shaking: bool, } #[turbo_tasks::value_impl] -impl ModuleOptionsContextVc { +impl ValueDefault for ModuleOptionsContext { #[turbo_tasks::function] - pub fn default() -> Self { + fn value_default() -> Vc { Self::cell(Default::default()) } } - -impl Default for ModuleOptionsContextVc { - fn default() -> Self { - Self::default() - } -} diff --git a/crates/turbopack/src/module_options/module_rule.rs b/crates/turbopack/src/module_options/module_rule.rs index fc7223dd0ed5cb..3eb34a5e82ad27 100644 --- a/crates/turbopack/src/module_options/module_rule.rs +++ b/crates/turbopack/src/module_options/module_rule.rs @@ -1,14 +1,14 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; -use turbo_tasks::trace::TraceRawVcs; +use turbo_tasks::{trace::TraceRawVcs, Vc}; use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::AssetVc, plugin::CustomModuleTypeVc, reference_type::ReferenceType, - source_transform::SourceTransformsVc, + asset::Asset, plugin::CustomModuleType, reference_type::ReferenceType, + source_transform::SourceTransforms, }; -use turbopack_css::CssInputTransformsVc; -use turbopack_ecmascript::{EcmascriptInputTransformsVc, EcmascriptOptions}; -use turbopack_mdx::MdxTransformOptionsVc; +use turbopack_css::CssInputTransforms; +use turbopack_ecmascript::{EcmascriptInputTransforms, EcmascriptOptions}; +use turbopack_mdx::MdxTransformOptions; use super::ModuleRuleCondition; @@ -29,7 +29,7 @@ impl ModuleRule { pub async fn matches( &self, - source: AssetVc, + source: Vc>, path: &FileSystemPath, reference_type: &ReferenceType, ) -> Result { @@ -41,41 +41,41 @@ impl ModuleRule { #[derive(Debug, Clone)] pub enum ModuleRuleEffect { ModuleType(ModuleType), - AddEcmascriptTransforms(EcmascriptInputTransformsVc), - SourceTransforms(SourceTransformsVc), + AddEcmascriptTransforms(Vc), + SourceTransforms(Vc), } #[turbo_tasks::value(serialization = "auto_for_input", shared)] #[derive(PartialOrd, Ord, Hash, Debug, Copy, Clone)] pub enum ModuleType { Ecmascript { - transforms: EcmascriptInputTransformsVc, + transforms: Vc, #[turbo_tasks(trace_ignore)] options: EcmascriptOptions, }, Typescript { - transforms: EcmascriptInputTransformsVc, + transforms: Vc, #[turbo_tasks(trace_ignore)] options: EcmascriptOptions, }, TypescriptWithTypes { - transforms: EcmascriptInputTransformsVc, + transforms: Vc, #[turbo_tasks(trace_ignore)] options: EcmascriptOptions, }, TypescriptDeclaration { - transforms: EcmascriptInputTransformsVc, + transforms: Vc, #[turbo_tasks(trace_ignore)] options: EcmascriptOptions, }, Json, Raw, Mdx { - transforms: EcmascriptInputTransformsVc, - options: MdxTransformOptionsVc, + transforms: Vc, + options: Vc, }, - Css(CssInputTransformsVc), - CssModule(CssInputTransformsVc), + Css(Vc), + CssModule(Vc), Static, - Custom(CustomModuleTypeVc), + Custom(Vc>), } diff --git a/crates/turbopack/src/module_options/rule_condition.rs b/crates/turbopack/src/module_options/rule_condition.rs index 05a6df90bfaadc..e58f1c66a78306 100644 --- a/crates/turbopack/src/module_options/rule_condition.rs +++ b/crates/turbopack/src/module_options/rule_condition.rs @@ -1,11 +1,9 @@ use anyhow::Result; use async_recursion::async_recursion; use serde::{Deserialize, Serialize}; -use turbo_tasks::{primitives::Regex, trace::TraceRawVcs}; -use turbo_tasks_fs::{glob::GlobReadRef, FileSystemPath, FileSystemPathReadRef}; -use turbopack_core::{ - asset::AssetVc, reference_type::ReferenceType, virtual_asset::VirtualAssetVc, -}; +use turbo_tasks::{primitives::Regex, trace::TraceRawVcs, ReadRef, Vc}; +use turbo_tasks_fs::{glob::Glob, FileSystemPath}; +use turbopack_core::{asset::Asset, reference_type::ReferenceType, virtual_asset::VirtualAsset}; #[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq)] pub enum ModuleRuleCondition { @@ -14,11 +12,11 @@ pub enum ModuleRuleCondition { Not(Box), ReferenceType(ReferenceType), ResourceIsVirtualAsset, - ResourcePathEquals(FileSystemPathReadRef), + ResourcePathEquals(ReadRef), ResourcePathHasNoExtension, ResourcePathEndsWith(String), ResourcePathInDirectory(String), - ResourcePathInExactDirectory(FileSystemPathReadRef), + ResourcePathInExactDirectory(ReadRef), ResourcePathRegex(#[turbo_tasks(trace_ignore)] Regex), /// For paths that are within the same filesystem as the `base`, it need to /// match the relative path from base to resource. This includes `./` or @@ -27,11 +25,11 @@ pub enum ModuleRuleCondition { /// any glob starting with `./` or `../` will only match paths in the /// project. Globs starting with `**` can match any path. ResourcePathGlob { - base: FileSystemPathReadRef, + base: ReadRef, #[turbo_tasks(trace_ignore)] - glob: GlobReadRef, + glob: ReadRef, }, - ResourceBasePathGlob(#[turbo_tasks(trace_ignore)] GlobReadRef), + ResourceBasePathGlob(#[turbo_tasks(trace_ignore)] ReadRef), } impl ModuleRuleCondition { @@ -53,7 +51,7 @@ impl ModuleRuleCondition { #[async_recursion] pub async fn matches( &self, - source: AssetVc, + source: Vc>, path: &FileSystemPath, reference_type: &ReferenceType, ) -> Result { @@ -94,13 +92,15 @@ impl ModuleRuleCondition { path.path.starts_with(&format!("{dir}/")) || path.path.contains(&format!("/{dir}/")) } ModuleRuleCondition::ResourcePathInExactDirectory(parent_path) => { - path.is_inside(parent_path) + path.is_inside_ref(parent_path) } ModuleRuleCondition::ReferenceType(condition_ty) => { condition_ty.includes(reference_type) } ModuleRuleCondition::ResourceIsVirtualAsset => { - VirtualAssetVc::resolve_from(source).await?.is_some() + Vc::try_resolve_downcast_type::(source) + .await? + .is_some() } ModuleRuleCondition::ResourcePathGlob { glob, base } => { if let Some(path) = base.get_relative_path_to(path) { diff --git a/crates/turbopack/src/rebase/mod.rs b/crates/turbopack/src/rebase/mod.rs index ed259c433db5a2..1c34cb4c96b945 100644 --- a/crates/turbopack/src/rebase/mod.rs +++ b/crates/turbopack/src/rebase/mod.rs @@ -1,27 +1,31 @@ use std::hash::Hash; use anyhow::Result; -use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc}; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - asset::{Asset, AssetContentVc, AssetVc}, - ident::AssetIdentVc, - reference::{AssetReference, AssetReferenceVc, AssetReferencesVc}, - resolve::ResolveResultVc, + asset::{Asset, AssetContent}, + ident::AssetIdent, + reference::{AssetReference, AssetReferences}, + resolve::ResolveResult, }; #[turbo_tasks::value] #[derive(Hash)] pub struct RebasedAsset { - source: AssetVc, - input_dir: FileSystemPathVc, - output_dir: FileSystemPathVc, + source: Vc>, + input_dir: Vc, + output_dir: Vc, } #[turbo_tasks::value_impl] -impl RebasedAssetVc { +impl RebasedAsset { #[turbo_tasks::function] - pub fn new(source: AssetVc, input_dir: FileSystemPathVc, output_dir: FileSystemPathVc) -> Self { + pub fn new( + source: Vc>, + input_dir: Vc, + output_dir: Vc, + ) -> Vc { Self::cell(RebasedAsset { source, input_dir, @@ -33,8 +37,8 @@ impl RebasedAssetVc { #[turbo_tasks::value_impl] impl Asset for RebasedAsset { #[turbo_tasks::function] - fn ident(&self) -> AssetIdentVc { - AssetIdentVc::from_path(FileSystemPathVc::rebase( + fn ident(&self) -> Vc { + AssetIdent::from_path(FileSystemPath::rebase( self.source.ident().path(), self.input_dir, self.output_dir, @@ -42,55 +46,56 @@ impl Asset for RebasedAsset { } #[turbo_tasks::function] - fn content(&self) -> AssetContentVc { + fn content(&self) -> Vc { self.source.content() } #[turbo_tasks::function] - async fn references(&self) -> Result { + async fn references(&self) -> Result> { let input_references = self.source.references().await?; let mut references = Vec::new(); for reference in input_references.iter() { - references.push( + references.push(Vc::upcast( RebasedAssetReference { reference: *reference, input_dir: self.input_dir, output_dir: self.output_dir, } - .cell() - .into(), - ); + .cell(), + )); } - Ok(AssetReferencesVc::cell(references)) + Ok(Vc::cell(references)) } } #[turbo_tasks::value(shared)] struct RebasedAssetReference { - reference: AssetReferenceVc, - input_dir: FileSystemPathVc, - output_dir: FileSystemPathVc, + reference: Vc>, + input_dir: Vc, + output_dir: Vc, } #[turbo_tasks::value_impl] impl AssetReference for RebasedAssetReference { #[turbo_tasks::function] - async fn resolve_reference(&self) -> Result { + async fn resolve_reference(&self) -> Result> { let result = self.reference.resolve_reference().await?; Ok(result .map( |asset| { - let asset = RebasedAssetVc::new(asset, self.input_dir, self.output_dir).into(); + let asset = + Vc::upcast(RebasedAsset::new(asset, self.input_dir, self.output_dir)); async move { Ok(asset) } }, |reference| { - let reference: AssetReferenceVc = RebasedAssetReference { - reference, - input_dir: self.input_dir, - output_dir: self.output_dir, - } - .cell() - .into(); + let reference: Vc> = Vc::upcast( + RebasedAssetReference { + reference, + input_dir: self.input_dir, + output_dir: self.output_dir, + } + .cell(), + ); async move { Ok(reference) } }, ) @@ -102,8 +107,8 @@ impl AssetReference for RebasedAssetReference { #[turbo_tasks::value_impl] impl ValueToString for RebasedAssetReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result { - Ok(StringVc::cell(format!( + async fn to_string(&self) -> Result> { + Ok(Vc::cell(format!( "rebased {}", self.reference.to_string().await? ))) diff --git a/crates/turbopack/src/resolve.rs b/crates/turbopack/src/resolve.rs index ba7d5166367060..970ccdf40dd3ea 100644 --- a/crates/turbopack/src/resolve.rs +++ b/crates/turbopack/src/resolve.rs @@ -1,10 +1,11 @@ use anyhow::Result; -use turbo_tasks_fs::{FileSystem, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{FileSystem, FileSystemPath}; use turbopack_core::resolve::{ find_context_file, options::{ ConditionValue, ImportMap, ImportMapping, ResolutionConditions, ResolveInPackage, - ResolveIntoPackage, ResolveModules, ResolveOptions, ResolveOptionsVc, + ResolveIntoPackage, ResolveModules, ResolveOptions, }, AliasMap, AliasPattern, FindContextFileResult, }; @@ -12,7 +13,7 @@ use turbopack_ecmascript::typescript::resolve::{ apply_tsconfig_resolve_options, tsconfig, tsconfig_resolve_options, }; -use crate::resolve_options_context::ResolveOptionsContextVc; +use crate::resolve_options_context::ResolveOptionsContext; const NODE_EXTERNALS: [&str; 51] = [ "assert", @@ -70,9 +71,9 @@ const NODE_EXTERNALS: [&str; 51] = [ #[turbo_tasks::function] async fn base_resolve_options( - context: FileSystemPathVc, - options_context: ResolveOptionsContextVc, -) -> Result { + context: Vc, + options_context: Vc, +) -> Result> { let parent = context.parent().resolve().await?; if parent != context { return Ok(base_resolve_options(parent, options_context)); @@ -103,7 +104,7 @@ async fn base_resolve_options( let mut import_map = ImportMap::new(direct_mappings); if let Some(additional_import_map) = opt.import_map { let additional_import_map = additional_import_map.await?; - import_map.extend(&additional_import_map); + import_map.extend_ref(&additional_import_map); } let import_map = import_map.cell(); @@ -231,9 +232,9 @@ async fn base_resolve_options( #[turbo_tasks::function] pub async fn resolve_options( - context: FileSystemPathVc, - options_context: ResolveOptionsContextVc, -) -> Result { + context: Vc, + options_context: Vc, +) -> Result> { let options_context_value = options_context.await?; if !options_context_value.rules.is_empty() { let context_value = &*context.await?; diff --git a/crates/turbopack/src/resolve_options_context.rs b/crates/turbopack/src/resolve_options_context.rs index a72052c0e2bc24..89d375dd88f55c 100644 --- a/crates/turbopack/src/resolve_options_context.rs +++ b/crates/turbopack/src/resolve_options_context.rs @@ -1,10 +1,11 @@ use anyhow::Result; -use turbo_tasks_fs::FileSystemPathVc; +use turbo_tasks::{ValueDefault, Vc}; +use turbo_tasks_fs::FileSystemPath; use turbopack_core::{ - environment::EnvironmentVc, + environment::Environment, resolve::{ - options::{ImportMapVc, ResolvedMapVc}, - plugin::ResolvePluginVc, + options::{ImportMap, ResolvedMap}, + plugin::ResolvePlugin, }, }; @@ -14,7 +15,7 @@ use crate::condition::ContextCondition; #[derive(Default, Clone)] pub struct ResolveOptionsContext { #[serde(default)] - pub emulate_environment: Option, + pub emulate_environment: Option>, #[serde(default)] pub enable_types: bool, #[serde(default)] @@ -26,7 +27,7 @@ pub struct ResolveOptionsContext { #[serde(default)] /// Enable resolving of the node_modules folder when within the provided /// directory - pub enable_node_modules: Option, + pub enable_node_modules: Option>, #[serde(default)] /// Mark well-known Node.js modules as external imports and load them using /// native `require`. e.g. url, querystring, os @@ -45,48 +46,46 @@ pub struct ResolveOptionsContext { /// If set, this import map will be applied to `ResolveOption::import_map`. /// It is always applied last, so any mapping defined within will take /// precedence over any other (e.g. tsconfig.json `compilerOptions.paths`). - pub import_map: Option, + pub import_map: Option>, #[serde(default)] /// An import map to fall back to when a request could not be resolved. /// /// If set, this import map will be applied to /// `ResolveOption::fallback_import_map`. It is always applied last, so /// any mapping defined within will take precedence over any other. - pub fallback_import_map: Option, + pub fallback_import_map: Option>, #[serde(default)] /// An additional resolved map to use after modules have been resolved. - pub resolved_map: Option, + pub resolved_map: Option>, #[serde(default)] /// A list of rules to use a different resolve option context for certain /// context paths. The first matching is used. - pub rules: Vec<(ContextCondition, ResolveOptionsContextVc)>, + pub rules: Vec<(ContextCondition, Vc)>, #[serde(default)] /// A list of plugins which get applied before (in the future) and after /// resolving. - pub plugins: Vec, + pub plugins: Vec>>, #[serde(default)] pub placeholder_for_future_extensions: (), } #[turbo_tasks::value_impl] -impl ResolveOptionsContextVc { +impl ResolveOptionsContext { #[turbo_tasks::function] - pub fn default() -> Self { - Self::cell(Default::default()) - } - - #[turbo_tasks::function] - pub async fn with_types_enabled(self) -> Result { + pub async fn with_types_enabled(self: Vc) -> Result> { let mut clone = self.await?.clone_value(); clone.enable_types = true; clone.enable_typescript = true; Ok(Self::cell(clone)) } - /// Returns a new [ResolveOptionsContextVc] with its import map extended to - /// include the given import map. + /// Returns a new [Vc] with its import map extended + /// to include the given import map. #[turbo_tasks::function] - pub async fn with_extended_import_map(self, import_map: ImportMapVc) -> Result { + pub async fn with_extended_import_map( + self: Vc, + import_map: Vc, + ) -> Result> { let mut resolve_options_context = self.await?.clone_value(); resolve_options_context.import_map = Some( resolve_options_context @@ -97,13 +96,13 @@ impl ResolveOptionsContextVc { Ok(resolve_options_context.into()) } - /// Returns a new [ResolveOptionsContextVc] with its fallback import map + /// Returns a new [Vc] with its fallback import map /// extended to include the given import map. #[turbo_tasks::function] pub async fn with_extended_fallback_import_map( - self, - fallback_import_map: ImportMapVc, - ) -> Result { + self: Vc, + fallback_import_map: Vc, + ) -> Result> { let mut resolve_options_context = self.await?.clone_value(); resolve_options_context.fallback_import_map = Some( resolve_options_context @@ -117,8 +116,10 @@ impl ResolveOptionsContextVc { } } -impl Default for ResolveOptionsContextVc { - fn default() -> Self { - Self::default() +#[turbo_tasks::value_impl] +impl ValueDefault for ResolveOptionsContext { + #[turbo_tasks::function] + fn value_default() -> Vc { + Self::cell(Default::default()) } } diff --git a/crates/turbopack/src/transition/mod.rs b/crates/turbopack/src/transition/mod.rs index 2483cf556cef12..eb8ceed8ca94f4 100644 --- a/crates/turbopack/src/transition/mod.rs +++ b/crates/turbopack/src/transition/mod.rs @@ -1,14 +1,14 @@ use std::collections::HashMap; use anyhow::Result; -use turbo_tasks::Value; +use turbo_tasks::{Value, Vc}; use turbopack_core::{ - asset::AssetVc, compile_time_info::CompileTimeInfoVc, reference_type::ReferenceType, + asset::Asset, compile_time_info::CompileTimeInfo, reference_type::ReferenceType, }; use crate::{ - module_options::ModuleOptionsContextVc, resolve_options_context::ResolveOptionsContextVc, - ModuleAssetContextVc, + module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext, + ModuleAssetContext, }; /// Some kind of operation that is executed during reference processing. e. g. @@ -17,43 +17,50 @@ use crate::{ #[turbo_tasks::value_trait] pub trait Transition { /// Apply modifications/wrapping to the source asset - fn process_source(&self, asset: AssetVc) -> AssetVc { + fn process_source(self: Vc, asset: Vc>) -> Vc> { asset } /// Apply modifications to the compile-time information - fn process_compile_time_info(&self, compile_time_info: CompileTimeInfoVc) -> CompileTimeInfoVc { + fn process_compile_time_info( + self: Vc, + compile_time_info: Vc, + ) -> Vc { compile_time_info } /// Apply modifications/wrapping to the module options context fn process_module_options_context( - &self, - context: ModuleOptionsContextVc, - ) -> ModuleOptionsContextVc { + self: Vc, + context: Vc, + ) -> Vc { context } /// Apply modifications/wrapping to the resolve options context fn process_resolve_options_context( - &self, - context: ResolveOptionsContextVc, - ) -> ResolveOptionsContextVc { + self: Vc, + context: Vc, + ) -> Vc { context } /// Apply modifications/wrapping to the final asset - fn process_module(&self, asset: AssetVc, _context: ModuleAssetContextVc) -> AssetVc { + fn process_module( + self: Vc, + asset: Vc>, + _context: Vc, + ) -> Vc> { asset } /// Apply modifications to the context async fn process_context( - self_vc: TransitionVc, - context: ModuleAssetContextVc, - ) -> Result { + self: Vc, + context: Vc, + ) -> Result> { let context = context.await?; - let compile_time_info = self_vc.process_compile_time_info(context.compile_time_info); + let compile_time_info = self.process_compile_time_info(context.compile_time_info); let module_options_context = - self_vc.process_module_options_context(context.module_options_context); + self.process_module_options_context(context.module_options_context); let resolve_options_context = - self_vc.process_resolve_options_context(context.resolve_options_context); - let context = ModuleAssetContextVc::new( + self.process_resolve_options_context(context.resolve_options_context); + let context = ModuleAssetContext::new( context.transitions, compile_time_info, module_options_context, @@ -63,17 +70,17 @@ pub trait Transition { } /// Apply modification on the processing of the asset fn process( - self_vc: TransitionVc, - asset: AssetVc, - context: ModuleAssetContextVc, + self: Vc, + asset: Vc>, + context: Vc, reference_type: Value, - ) -> AssetVc { - let asset = self_vc.process_source(asset); - let context = self_vc.process_context(context); + ) -> Vc> { + let asset = self.process_source(asset); + let context = self.process_context(context); let m = context.process_default(asset, reference_type); - self_vc.process_module(m, context) + self.process_module(m, context) } } #[turbo_tasks::value(transparent)] -pub struct TransitionsByName(HashMap); +pub struct TransitionsByName(HashMap>>); diff --git a/crates/turbopack/src/unsupported_sass.rs b/crates/turbopack/src/unsupported_sass.rs index f3654e5f1ece86..e04e3837b1e9d5 100644 --- a/crates/turbopack/src/unsupported_sass.rs +++ b/crates/turbopack/src/unsupported_sass.rs @@ -1,27 +1,27 @@ //! TODO(WEB-741) Remove this file once Sass is supported. use anyhow::Result; -use turbo_tasks::primitives::StringVc; -use turbo_tasks_fs::{glob::GlobVc, FileSystemPathVc}; +use turbo_tasks::Vc; +use turbo_tasks_fs::{glob::Glob, FileSystemPath}; use turbopack_core::{ - issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, + issue::{Issue, IssueExt, IssueSeverity}, resolve::{ - parse::RequestVc, - plugin::{ResolvePlugin, ResolvePluginConditionVc, ResolvePluginVc}, - ResolveResultOptionVc, + parse::Request, + plugin::{ResolvePlugin, ResolvePluginCondition}, + ResolveResultOption, }, }; /// Resolve plugins that warns when importing a sass file. #[turbo_tasks::value] pub(crate) struct UnsupportedSassResolvePlugin { - root: FileSystemPathVc, + root: Vc, } #[turbo_tasks::value_impl] -impl UnsupportedSassResolvePluginVc { +impl UnsupportedSassResolvePlugin { #[turbo_tasks::function] - pub fn new(root: FileSystemPathVc) -> Self { + pub fn new(root: Vc) -> Vc { UnsupportedSassResolvePlugin { root }.cell() } } @@ -29,62 +29,61 @@ impl UnsupportedSassResolvePluginVc { #[turbo_tasks::value_impl] impl ResolvePlugin for UnsupportedSassResolvePlugin { #[turbo_tasks::function] - fn after_resolve_condition(&self) -> ResolvePluginConditionVc { - ResolvePluginConditionVc::new(self.root.root(), GlobVc::new("**/*.{sass,scss}")) + fn after_resolve_condition(&self) -> Vc { + ResolvePluginCondition::new(self.root.root(), Glob::new("**/*.{sass,scss}".to_string())) } #[turbo_tasks::function] async fn after_resolve( &self, - fs_path: FileSystemPathVc, - context: FileSystemPathVc, - request: RequestVc, - ) -> Result { + fs_path: Vc, + context: Vc, + request: Vc, + ) -> Result> { let extension = fs_path.extension().await?; if ["sass", "scss"].iter().any(|ext| ext == &*extension) { UnsupportedSassModuleIssue { context, request } .cell() - .as_issue() .emit(); } - Ok(ResolveResultOptionVc::none()) + Ok(ResolveResultOption::none()) } } #[turbo_tasks::value(shared)] struct UnsupportedSassModuleIssue { - context: FileSystemPathVc, - request: RequestVc, + context: Vc, + request: Vc, } #[turbo_tasks::value_impl] impl Issue for UnsupportedSassModuleIssue { #[turbo_tasks::function] - fn severity(&self) -> IssueSeverityVc { + fn severity(&self) -> Vc { IssueSeverity::Warning.into() } #[turbo_tasks::function] - fn category(&self) -> StringVc { - StringVc::cell("resolve".to_string()) + fn category(&self) -> Vc { + Vc::cell("resolve".to_string()) } #[turbo_tasks::function] - async fn title(&self) -> Result { - Ok(StringVc::cell(format!( + async fn title(&self) -> Result> { + Ok(Vc::cell(format!( "Unsupported Sass request: {}", self.request.await?.request().as_deref().unwrap_or("N/A") ))) } #[turbo_tasks::function] - fn context(&self) -> FileSystemPathVc { + fn context(&self) -> Vc { self.context } #[turbo_tasks::function] - fn description(&self) -> StringVc { - StringVc::cell("Turbopack does not yet support importing Sass modules.".to_string()) + fn description(&self) -> Vc { + Vc::cell("Turbopack does not yet support importing Sass modules.".to_string()) } } diff --git a/crates/turbopack/tests/node-file-trace.rs b/crates/turbopack/tests/node-file-trace.rs index 2f037cd21cf71a..a3dff09b4673b0 100644 --- a/crates/turbopack/tests/node-file-trace.rs +++ b/crates/turbopack/tests/node-file-trace.rs @@ -1,4 +1,5 @@ -#![feature(min_specialization)] +#![feature(arbitrary_self_types)] +#![feature(async_fn_in_trait)] mod helpers; #[cfg(feature = "bench_against_node_nft")] @@ -7,7 +8,9 @@ use std::{ collections::HashMap, env::temp_dir, fmt::Display, - fs::{self, remove_dir_all}, + fs::{ + remove_dir_all, {self}, + }, io::{ErrorKind, Write as _}, path::{Path, PathBuf}, sync::{Arc, Mutex}, @@ -20,25 +23,26 @@ use helpers::print_changeset; use lazy_static::lazy_static; use regex::Regex; use rstest::*; -use rstest_reuse::{self, *}; +use rstest_reuse::{ + *, {self}, +}; use serde::{Deserialize, Serialize}; use tokio::{process::Command, time::timeout}; -use turbo_tasks::{backend::Backend, TurboTasks, Value, ValueToString}; -use turbo_tasks_fs::{DiskFileSystemVc, FileSystem, FileSystemPathVc, FileSystemVc}; +use turbo_tasks::{backend::Backend, ReadRef, TurboTasks, Value, ValueToString, Vc}; +use turbo_tasks_fs::{DiskFileSystem, FileSystem, FileSystemPath}; use turbo_tasks_memory::MemoryBackend; use turbopack::{ - emit_with_completion, module_options::ModuleOptionsContext, rebase::RebasedAssetVc, register, - resolve_options_context::ResolveOptionsContext, transition::TransitionsByNameVc, - ModuleAssetContextVc, + emit_with_completion, module_options::ModuleOptionsContext, rebase::RebasedAsset, register, + resolve_options_context::ResolveOptionsContext, ModuleAssetContext, }; #[cfg(not(feature = "bench_against_node_nft"))] use turbopack_core::asset::Asset; use turbopack_core::{ - compile_time_info::CompileTimeInfoVc, + compile_time_info::CompileTimeInfo, context::AssetContext, - environment::{EnvironmentIntention, EnvironmentVc, ExecutionEnvironment, NodeJsEnvironment}, + environment::{Environment, EnvironmentIntention, ExecutionEnvironment, NodeJsEnvironment}, reference_type::ReferenceType, - source_asset::SourceAssetVc, + source_asset::SourceAsset, }; #[global_allocator] @@ -390,24 +394,26 @@ fn node_file_trace( let bench_suites = bench_suites.clone(); #[cfg(feature = "bench_against_node_nft")] let before_start = Instant::now(); - let workspace_fs: FileSystemVc = - DiskFileSystemVc::new("workspace".to_string(), package_root.clone()).into(); + let workspace_fs: Vc> = Vc::upcast(DiskFileSystem::new( + "workspace".to_string(), + package_root.clone(), + )); let input_dir = workspace_fs.root(); - let input = input_dir.join(&format!("tests/{input_string}")); + let input = input_dir.join(format!("tests/{input_string}")); #[cfg(not(feature = "bench_against_node_nft"))] let original_output = exec_node(package_root, input); - let output_fs = DiskFileSystemVc::new("output".to_string(), directory.clone()); + let output_fs = DiskFileSystem::new("output".to_string(), directory.clone()); let output_dir = output_fs.root(); - let source = SourceAssetVc::new(input); - let context = ModuleAssetContextVc::new( - TransitionsByNameVc::cell(HashMap::new()), + let source = SourceAsset::new(input); + let context = ModuleAssetContext::new( + Vc::cell(HashMap::new()), // TODO It's easy to make a mistake here as this should match the config in the // binary. TODO These test cases should move into the // `node-file-trace` crate and use the same config. - CompileTimeInfoVc::new(EnvironmentVc::new( + CompileTimeInfo::new(Environment::new( Value::new(ExecutionEnvironment::NodeJsLambda( NodeJsEnvironment::default().into(), )), @@ -426,12 +432,13 @@ fn node_file_trace( } .cell(), ); - let module = context.process(source.into(), Value::new(ReferenceType::Undefined)); - let rebased = RebasedAssetVc::new(module, input_dir, output_dir); + let module = + context.process(Vc::upcast(source), Value::new(ReferenceType::Undefined)); + let rebased = RebasedAsset::new(module, input_dir, output_dir); #[cfg(not(feature = "bench_against_node_nft"))] let output_path = rebased.ident().path(); - emit_with_completion(rebased.into(), output_dir).await?; + emit_with_completion(Vc::upcast(rebased), output_dir).await?; #[cfg(not(feature = "bench_against_node_nft"))] { @@ -474,14 +481,14 @@ fn node_file_trace( rust_speedup, }); } - CommandOutputVc::cell(CommandOutput { + CommandOutput::cell(CommandOutput { stdout: String::new(), stderr: String::new(), }) .await } }; - let handle_result = |result: Result| match result { + let handle_result = |result: Result>| match result { #[allow(unused)] Ok(output) => { #[cfg(not(feature = "bench_against_node_nft"))] @@ -554,7 +561,7 @@ impl Display for CommandOutput { } #[turbo_tasks::function] -async fn exec_node(directory: String, path: FileSystemPathVc) -> Result { +async fn exec_node(directory: String, path: Vc) -> Result> { let mut cmd = Command::new("node"); let p = path.await?; @@ -618,7 +625,7 @@ async fn exec_node(directory: String, path: FileSystemPathVc) -> Result String { @@ -651,13 +658,13 @@ fn diff(expected: &str, actual: &str) -> String { #[allow(unused)] #[turbo_tasks::function] async fn assert_output( - expected: CommandOutputVc, - actual: CommandOutputVc, + expected: Vc, + actual: Vc, expected_stderr: Option, -) -> Result { +) -> Result> { let expected = expected.await?; let actual = actual.await?; - Ok(CommandOutputVc::cell(CommandOutput { + Ok(CommandOutput::cell(CommandOutput { stdout: diff(&expected.stdout, &actual.stdout), stderr: if let Some(expected_stderr) = expected_stderr { if actual.stderr.contains(&expected_stderr) diff --git a/crates/turborepo-globwatch/src/lib.rs b/crates/turborepo-globwatch/src/lib.rs index d4565fca46f8b6..f5ff0f7f2ff737 100644 --- a/crates/turborepo-globwatch/src/lib.rs +++ b/crates/turborepo-globwatch/src/lib.rs @@ -18,7 +18,7 @@ unused_must_use, unsafe_code )] -#![feature(drain_filter)] +#![feature(extract_if)] use std::{ collections::HashMap, @@ -198,7 +198,7 @@ impl GlobWatcher { // requestor. flushes should not be considered as events. for flush_id in e .paths - .drain_filter(|p| p.starts_with(flush_dir.as_path())) + .extract_if(|p| p.starts_with(flush_dir.as_path())) .filter_map(|p| { get_flush_id( p.strip_prefix(flush_dir.as_path()) diff --git a/crates/turborepo-lockfiles/src/lib.rs b/crates/turborepo-lockfiles/src/lib.rs index 6ad08689bc4bd9..6731649ca83925 100644 --- a/crates/turborepo-lockfiles/src/lib.rs +++ b/crates/turborepo-lockfiles/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(once_cell)] - mod berry; mod error; mod npm; diff --git a/rust-toolchain b/rust-toolchain index e79845b64a5753..34b246f10e0e14 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2023-03-09 +nightly-2023-06-24 \ No newline at end of file