diff --git a/Cargo.lock b/Cargo.lock index 72dc48380e3ea..ef958542275e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "auto-hash-map" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "serde", "smallvec", @@ -3092,7 +3092,7 @@ dependencies = [ [[package]] name = "node-file-trace" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "serde", @@ -6965,10 +6965,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "turbo-prehash" +version = "0.1.0" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" + [[package]] name = "turbo-tasks" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-trait", @@ -7000,7 +7005,7 @@ dependencies = [ [[package]] name = "turbo-tasks-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "cargo-lock", @@ -7012,7 +7017,7 @@ dependencies = [ [[package]] name = "turbo-tasks-bytes" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "bytes", @@ -7026,7 +7031,7 @@ dependencies = [ [[package]] name = "turbo-tasks-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "dotenvs", @@ -7040,7 +7045,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fetch" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "lazy_static", @@ -7056,7 +7061,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "auto-hash-map", @@ -7088,7 +7093,7 @@ dependencies = [ [[package]] name = "turbo-tasks-hash" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "md4", "turbo-tasks-macros", @@ -7098,7 +7103,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "proc-macro-error", @@ -7112,7 +7117,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros-shared" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "proc-macro2", "quote", @@ -7122,7 +7127,7 @@ dependencies = [ [[package]] name = "turbo-tasks-malloc" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "mimalloc", ] @@ -7130,7 +7135,7 @@ dependencies = [ [[package]] name = "turbo-tasks-memory" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "auto-hash-map", @@ -7147,6 +7152,7 @@ dependencies = [ "smallvec", "tokio", "tracing", + "turbo-prehash", "turbo-tasks", "turbo-tasks-build", "turbo-tasks-hash", @@ -7156,7 +7162,7 @@ dependencies = [ [[package]] name = "turbopack" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-recursion", @@ -7186,7 +7192,7 @@ dependencies = [ [[package]] name = "turbopack-binding" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "auto-hash-map", "mdxjs", @@ -7227,7 +7233,7 @@ dependencies = [ [[package]] name = "turbopack-browser" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7250,7 +7256,7 @@ dependencies = [ [[package]] name = "turbopack-cli-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "clap", @@ -7267,7 +7273,7 @@ dependencies = [ [[package]] name = "turbopack-core" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-recursion", @@ -7296,7 +7302,7 @@ dependencies = [ [[package]] name = "turbopack-css" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7323,7 +7329,7 @@ dependencies = [ [[package]] name = "turbopack-dev-server" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-compression", @@ -7359,7 +7365,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-trait", @@ -7394,7 +7400,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-hmr-protocol" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "serde", "serde_json", @@ -7405,7 +7411,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-plugins" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-trait", @@ -7429,7 +7435,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-runtime" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indoc", @@ -7445,7 +7451,7 @@ dependencies = [ [[package]] name = "turbopack-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7461,7 +7467,7 @@ dependencies = [ [[package]] name = "turbopack-image" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "base64 0.21.4", @@ -7480,7 +7486,7 @@ dependencies = [ [[package]] name = "turbopack-json" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "serde", @@ -7495,7 +7501,7 @@ dependencies = [ [[package]] name = "turbopack-mdx" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "mdxjs", @@ -7510,7 +7516,7 @@ dependencies = [ [[package]] name = "turbopack-node" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "async-stream", @@ -7544,7 +7550,7 @@ dependencies = [ [[package]] name = "turbopack-nodejs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7564,7 +7570,7 @@ dependencies = [ [[package]] name = "turbopack-resolve" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7582,7 +7588,7 @@ dependencies = [ [[package]] name = "turbopack-static" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "serde", @@ -7598,7 +7604,7 @@ dependencies = [ [[package]] name = "turbopack-swc-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "swc_core", "turbo-tasks", @@ -7609,7 +7615,7 @@ dependencies = [ [[package]] name = "turbopack-trace-server" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "either", @@ -7629,7 +7635,7 @@ dependencies = [ [[package]] name = "turbopack-trace-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "crossbeam-channel", @@ -7645,7 +7651,7 @@ dependencies = [ [[package]] name = "turbopack-wasm" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240531.2#d4fd4fbbffc829fb78b8cc57f2bbd036b869a5a4" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240605.1#6c244029821ba4b5ffe9c8d407830ec0c91d519d" dependencies = [ "anyhow", "indexmap 1.9.3", diff --git a/Cargo.toml b/Cargo.toml index 30564a30837aa..4c3d2769d8fa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,11 +37,11 @@ swc_core = { version = "0.92.5", features = [ testing = { version = "0.35.25" } # Turbo crates -turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240531.2" } +turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240605.1" } # [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros.. -turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240531.2" } +turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240605.1" } # [TODO]: need to refactor embed_directory! macro usage in next-core -turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240531.2" } +turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240605.1" } # General Deps diff --git a/packages/next-swc/crates/napi/src/app_structure.rs b/packages/next-swc/crates/napi/src/app_structure.rs index 9e8327d7637ba..d3548a589518b 100644 --- a/packages/next-swc/crates/napi/src/app_structure.rs +++ b/packages/next-swc/crates/napi/src/app_structure.rs @@ -12,7 +12,7 @@ use next_core::app_structure::{ LoaderTree, MetadataItem, MetadataWithAltItem, }; use serde::{Deserialize, Serialize}; -use turbo_tasks::{ReadRef, Vc}; +use turbo_tasks::{RcStr, ReadRef, Vc}; use turbopack_binding::{ turbo::{ tasks::{ @@ -27,12 +27,8 @@ use turbopack_binding::{ use crate::register; #[turbo_tasks::function] -async fn project_fs(project_dir: String, watching: bool) -> Result>> { - let disk_fs = DiskFileSystem::new( - PROJECT_FILESYSTEM_NAME.to_string(), - project_dir.to_string(), - vec![], - ); +async fn project_fs(project_dir: RcStr, watching: bool) -> Result>> { + let disk_fs = DiskFileSystem::new(PROJECT_FILESYSTEM_NAME.into(), project_dir, vec![]); if watching { disk_fs.await?.start_watching_with_invalidation_reason()?; } @@ -42,8 +38,8 @@ async fn project_fs(project_dir: String, watching: bool) -> Result>, + segment: RcStr, + parallel_routes: IndexMap>, #[turbo_tasks(trace_ignore)] components: ComponentsForJs, #[turbo_tasks(trace_ignore)] @@ -57,13 +53,13 @@ enum EntrypointForJs { loader_tree: ReadRef, }, AppRoute { - path: String, + path: RcStr, }, } #[turbo_tasks::value(transparent)] #[serde(rename_all = "camelCase")] -struct EntrypointsForJs(HashMap); +struct EntrypointsForJs(HashMap); #[turbo_tasks::value(transparent)] struct OptionEntrypointsForJs(Option>); @@ -71,14 +67,14 @@ struct OptionEntrypointsForJs(Option>); async fn fs_path_to_path( project_path: Vc, path: Vc, -) -> Result { +) -> Result { match project_path.await?.get_path_to(&*path.await?) { None => Err(anyhow!( "Path {} is not inside of the project path {}", path.to_string().await?, project_path.to_string().await? )), - Some(p) => Ok(p.to_string()), + Some(p) => Ok(p.into()), } } @@ -86,21 +82,21 @@ async fn fs_path_to_path( #[serde(rename_all = "camelCase")] struct ComponentsForJs { #[serde(skip_serializing_if = "Option::is_none")] - page: Option, + page: Option, #[serde(skip_serializing_if = "Option::is_none")] - layout: Option, + layout: Option, #[serde(skip_serializing_if = "Option::is_none")] - error: Option, + error: Option, #[serde(skip_serializing_if = "Option::is_none")] - loading: Option, + loading: Option, #[serde(skip_serializing_if = "Option::is_none")] - template: Option, + template: Option, #[serde(skip_serializing_if = "Option::is_none", rename = "not-found")] - not_found: Option, + not_found: Option, #[serde(skip_serializing_if = "Option::is_none")] - default: Option, + default: Option, #[serde(skip_serializing_if = "Option::is_none")] - route: Option, + route: Option, metadata: MetadataForJs, } @@ -134,19 +130,19 @@ struct GlobalMetadataForJs { #[serde(tag = "type", rename_all = "camelCase")] enum MetadataWithAltItemForJs { Static { - path: String, - alt_path: Option, + path: RcStr, + alt_path: Option, }, Dynamic { - path: String, + path: RcStr, }, } #[derive(Deserialize, Serialize, PartialEq, Eq, ValueDebugFormat)] #[serde(tag = "type", rename_all = "camelCase")] enum MetadataItemForJs { - Static { path: String }, - Dynamic { path: String }, + Static { path: RcStr }, + Dynamic { path: RcStr }, } async fn prepare_components_for_js( @@ -166,7 +162,7 @@ async fn prepare_components_for_js( } = &*components.await?; let mut result = ComponentsForJs::default(); async fn add( - result: &mut Option, + result: &mut Option, project_path: Vc, value: &Option>, ) -> Result<()> { @@ -305,7 +301,7 @@ async fn prepare_entrypoints_for_js( .await? .iter() .map(|(key, value)| { - let key = key.to_string(); + let key = key.to_string().into(); async move { let value = match *value { Entrypoint::AppPage { loader_tree, .. } => EntrypointForJs::AppPage { @@ -330,19 +326,19 @@ async fn prepare_entrypoints_for_js( #[turbo_tasks::function] async fn get_value( - root_dir: String, - project_dir: String, - page_extensions: Vec, + root_dir: RcStr, + project_dir: RcStr, + page_extensions: Vec, watching: bool, ) -> Result> { let page_extensions = Vc::cell(page_extensions); let fs = project_fs(root_dir.clone(), watching); - let project_relative = project_dir.strip_prefix(&root_dir).unwrap(); + 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 project_path = fs.root().join(project_relative.into()); let app_dir = find_app_dir(project_path); @@ -373,8 +369,8 @@ pub fn stream_entrypoints( let value = serde_json::to_value(value)?; Ok(vec![value]) })?; - let root_dir = Arc::new(root_dir); - let project_dir = Arc::new(project_dir); + let root_dir = RcStr::from(root_dir); + let project_dir = RcStr::from(project_dir); let page_extensions = Arc::new(page_extensions); turbo_tasks.spawn_root_task(move || { let func: ThreadsafeFunction>> = func.clone(); @@ -383,9 +379,9 @@ pub fn stream_entrypoints( let page_extensions: Arc> = page_extensions.clone(); Box::pin(async move { if let Some(entrypoints) = &*get_value( - (*root_dir).clone(), - (*project_dir).clone(), - page_extensions.iter().map(|s| s.to_string()).collect(), + root_dir.clone(), + project_dir.clone(), + page_extensions.iter().map(|s| s.as_str().into()).collect(), true, ) .await? @@ -415,9 +411,9 @@ pub async fn get_entrypoints( let result = turbo_tasks .run_once(async move { let value = if let Some(entrypoints) = &*get_value( - root_dir, - project_dir, - page_extensions.iter().map(|s| s.to_string()).collect(), + root_dir.into(), + project_dir.into(), + page_extensions.iter().map(|s| s.as_str().into()).collect(), false, ) .await? diff --git a/packages/next-swc/crates/napi/src/next_api/endpoint.rs b/packages/next-swc/crates/napi/src/next_api/endpoint.rs index 17b8ca5e05a02..04b4a17c5337c 100644 --- a/packages/next-swc/crates/napi/src/next_api/endpoint.rs +++ b/packages/next-swc/crates/napi/src/next_api/endpoint.rs @@ -57,7 +57,7 @@ impl From for NapiWrittenEndpoint { } => Self { r#type: "nodejs".to_string(), entry_path: Some(server_entry_path), - client_paths, + client_paths: client_paths.into_iter().map(From::from).collect(), server_paths: server_paths.into_iter().map(From::from).collect(), ..Default::default() }, @@ -66,7 +66,7 @@ impl From for NapiWrittenEndpoint { client_paths, } => Self { r#type: "edge".to_string(), - client_paths, + client_paths: client_paths.into_iter().map(From::from).collect(), server_paths: server_paths.into_iter().map(From::from).collect(), ..Default::default() }, diff --git a/packages/next-swc/crates/napi/src/next_api/project.rs b/packages/next-swc/crates/napi/src/next_api/project.rs index 49996a5124c1f..65a4d59d9602b 100644 --- a/packages/next-swc/crates/napi/src/next_api/project.rs +++ b/packages/next-swc/crates/napi/src/next_api/project.rs @@ -22,7 +22,7 @@ use rand::Rng; use tokio::{io::AsyncWriteExt, time::Instant}; use tracing::Instrument; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry}; -use turbo_tasks::{Completion, ReadRef, TransientInstance, TurboTasks, UpdateInfo, Vc}; +use turbo_tasks::{Completion, RcStr, ReadRef, TransientInstance, TurboTasks, UpdateInfo, Vc}; use turbopack_binding::{ turbo::{ tasks_fs::{DiskFileSystem, FileContent, FileSystem, FileSystemPath}, @@ -77,9 +77,9 @@ pub struct NapiDraftModeOptions { impl From for DraftModeOptions { fn from(val: NapiDraftModeOptions) -> Self { DraftModeOptions { - preview_mode_id: val.preview_mode_id, - preview_mode_encryption_key: val.preview_mode_encryption_key, - preview_mode_signing_key: val.preview_mode_signing_key, + preview_mode_id: val.preview_mode_id.into(), + preview_mode_encryption_key: val.preview_mode_encryption_key.into(), + preview_mode_signing_key: val.preview_mode_signing_key.into(), } } } @@ -186,20 +186,20 @@ pub struct NapiTurboEngineOptions { impl From for ProjectOptions { fn from(val: NapiProjectOptions) -> Self { ProjectOptions { - root_path: val.root_path, - project_path: val.project_path, + root_path: val.root_path.into(), + project_path: val.project_path.into(), watch: val.watch, - next_config: val.next_config, - js_config: val.js_config, + next_config: val.next_config.into(), + js_config: val.js_config.into(), env: val .env .into_iter() - .map(|var| (var.name, var.value)) + .map(|var| (var.name.into(), var.value.into())) .collect(), define_env: val.define_env.into(), dev: val.dev, - encryption_key: val.encryption_key, - build_id: val.build_id, + encryption_key: val.encryption_key.into(), + build_id: val.build_id.into(), preview_props: val.preview_props.into(), } } @@ -208,18 +208,20 @@ impl From for ProjectOptions { impl From for PartialProjectOptions { fn from(val: NapiPartialProjectOptions) -> Self { PartialProjectOptions { - root_path: val.root_path, - project_path: val.project_path, + root_path: val.root_path.map(From::from), + project_path: val.project_path.map(From::from), watch: val.watch, - next_config: val.next_config, - js_config: val.js_config, - env: val - .env - .map(|env| env.into_iter().map(|var| (var.name, var.value)).collect()), + next_config: val.next_config.map(From::from), + js_config: val.js_config.map(From::from), + env: val.env.map(|env| { + env.into_iter() + .map(|var| (var.name.into(), var.value.into())) + .collect() + }), define_env: val.define_env.map(|env| env.into()), dev: val.dev, - encryption_key: val.encryption_key, - build_id: val.build_id, + encryption_key: val.encryption_key.map(From::from), + build_id: val.build_id.map(From::from), preview_props: val.preview_props.map(|props| props.into()), } } @@ -231,17 +233,17 @@ impl From for DefineEnv { client: val .client .into_iter() - .map(|var| (var.name, var.value)) + .map(|var| (var.name.into(), var.value.into())) .collect(), edge: val .edge .into_iter() - .map(|var| (var.name, var.value)) + .map(|var| (var.name.into(), var.value.into())) .collect(), nodejs: val .nodejs .into_iter() - .map(|var| (var.name, var.value)) + .map(|var| (var.name.into(), var.value.into())) .collect(), } } @@ -357,10 +359,8 @@ pub async fn project_new( /// - https://github.com/oven-sh/bun/blob/06a9aa80c38b08b3148bfeabe560/src/install/install.zig#L3038 #[tracing::instrument] async fn benchmark_file_io(directory: Vc) -> Result> { - let temp_path = directory.join(format!( - "tmp_file_io_benchmark_{:x}", - rand::random::() - )); + let temp_path = + directory.join(format!("tmp_file_io_benchmark_{:x}", rand::random::()).into()); // try to get the real file path on disk so that we can use it with tokio let fs = Vc::try_resolve_downcast_type::(directory.fs()) @@ -624,7 +624,11 @@ pub fn project_entrypoints_subscribe( .routes .iter() .map(|(pathname, route)| { - NapiRoute::from_route(pathname.clone(), route.clone(), &turbo_tasks) + NapiRoute::from_route( + pathname.clone().into(), + route.clone(), + &turbo_tasks, + ) }) .collect::>(), middleware: entrypoints @@ -670,7 +674,7 @@ struct HmrUpdateWithIssues { #[turbo_tasks::function] async fn hmr_update( project: Vc, - identifier: String, + identifier: RcStr, state: Vc, ) -> Result> { let update_operation = project.hmr_update(identifier, state); @@ -701,7 +705,7 @@ pub fn project_hmr_events( let outer_identifier = identifier.clone(); let session = session.clone(); move || { - let identifier = outer_identifier.clone(); + let identifier: RcStr = outer_identifier.clone().into(); let session = session.clone(); async move { let project = project.project().resolve().await?; @@ -773,7 +777,7 @@ struct HmrIdentifiers { #[turbo_tasks::value(serialization = "none")] struct HmrIdentifiersWithIssues { - identifiers: ReadRef>, + identifiers: ReadRef>, issues: Arc>>, diagnostics: Arc>>, } @@ -967,7 +971,9 @@ pub async fn project_trace_source( ( path, match module { - Some(module) => Some(urlencoding::decode(&module.1)?.into_owned()), + Some(module) => { + Some(urlencoding::decode(&module.1)?.into_owned().into()) + } None => None, }, ) @@ -992,13 +998,13 @@ pub async fn project_trace_source( .container .project() .node_root() - .join(chunk_base.to_owned()); + .join(chunk_base.into()); let client_path = project .container .project() .client_relative_path() - .join(chunk_base.to_owned()); + .join(chunk_base.into()); let mut map_result = project .container @@ -1053,7 +1059,7 @@ pub async fn project_trace_source( Ok(Some(StackFrame { file: source_file.to_string(), - method_name: name, + method_name: name.as_ref().map(ToString::to_string), line, column, is_server: frame.is_server, @@ -1079,7 +1085,7 @@ pub async fn project_get_source_for_asset( .project_path() .fs() .root() - .join(file_path.to_string()) + .join(file_path.clone().into()) .read() .await?; diff --git a/packages/next-swc/crates/napi/src/next_api/utils.rs b/packages/next-swc/crates/napi/src/next_api/utils.rs index f46530ea9d450..c778cf4e4402d 100644 --- a/packages/next-swc/crates/napi/src/next_api/utils.rs +++ b/packages/next-swc/crates/napi/src/next_api/utils.rs @@ -120,12 +120,12 @@ impl From<&PlainIssue> for NapiIssue { .as_ref() .map(|styled| serde_json::to_value(StyledStringSerialize::from(styled)).unwrap()), stage: issue.stage.to_string(), - file_path: issue.file_path.clone(), + file_path: issue.file_path.to_string(), detail: issue .detail .as_ref() .map(|styled| serde_json::to_value(StyledStringSerialize::from(styled)).unwrap()), - documentation_link: issue.documentation_link.clone(), + documentation_link: issue.documentation_link.to_string(), severity: issue.severity.as_str().to_string(), source: issue.source.as_deref().map(|source| source.into()), title: serde_json::to_value(StyledStringSerialize::from(&issue.title)).unwrap(), @@ -255,9 +255,13 @@ pub struct NapiDiagnostic { impl NapiDiagnostic { pub fn from(diagnostic: &PlainDiagnostic) -> Self { Self { - category: diagnostic.category.clone(), - name: diagnostic.name.clone(), - payload: diagnostic.payload.clone(), + category: diagnostic.category.to_string(), + name: diagnostic.name.to_string(), + payload: diagnostic + .payload + .iter() + .map(|(k, v)| (k.to_string(), v.to_string())) + .collect(), } } } diff --git a/packages/next-swc/crates/napi/src/turbopack.rs b/packages/next-swc/crates/napi/src/turbopack.rs index 025026e5dfcfb..565ec53a29a6b 100644 --- a/packages/next-swc/crates/napi/src/turbopack.rs +++ b/packages/next-swc/crates/napi/src/turbopack.rs @@ -190,10 +190,21 @@ impl FromNapiValue for NapiRouteHas { impl From for RouteHas { fn from(val: NapiRouteHas) -> Self { match val { - NapiRouteHas::Header { key, value } => RouteHas::Header { key, value }, - NapiRouteHas::Query { key, value } => RouteHas::Query { key, value }, - NapiRouteHas::Cookie { key, value } => RouteHas::Cookie { key, value }, - NapiRouteHas::Host { value } => RouteHas::Host { value }, + NapiRouteHas::Header { key, value } => RouteHas::Header { + key: key.into(), + value: value.map(From::from), + }, + NapiRouteHas::Query { key, value } => RouteHas::Query { + key: key.into(), + value: value.map(From::from), + }, + NapiRouteHas::Cookie { key, value } => RouteHas::Cookie { + key: key.into(), + value: value.map(From::from), + }, + NapiRouteHas::Host { value } => RouteHas::Host { + value: value.into(), + }, } } } diff --git a/packages/next-swc/crates/napi/src/turbotrace.rs b/packages/next-swc/crates/napi/src/turbotrace.rs index 8afe5f6ee056c..6b50163ebb0ad 100644 --- a/packages/next-swc/crates/napi/src/turbotrace.rs +++ b/packages/next-swc/crates/napi/src/turbotrace.rs @@ -40,5 +40,5 @@ pub async fn run_turbo_tracing( }), ) .await?; - Ok(files) + Ok(files.into_iter().map(|f| f.to_string()).collect()) } diff --git a/packages/next-swc/crates/next-api/src/app.rs b/packages/next-swc/crates/next-api/src/app.rs index 44f72bdb99581..0e24456eb943c 100644 --- a/packages/next-swc/crates/next-api/src/app.rs +++ b/packages/next-swc/crates/next-api/src/app.rs @@ -36,7 +36,7 @@ use next_core::{ }; use serde::{Deserialize, Serialize}; use tracing::Instrument; -use turbo_tasks::{trace::TraceRawVcs, Completion, TryJoinIterExt, Value, Vc}; +use turbo_tasks::{trace::TraceRawVcs, Completion, RcStr, TryJoinIterExt, Value, Vc}; use turbopack_binding::{ turbo::{ tasks_env::{CustomProcessEnv, ProcessEnv}, @@ -167,8 +167,8 @@ impl AppProject { } #[turbo_tasks::function] - fn client_transition_name(self: Vc) -> Vc { - Vc::cell(ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string()) + fn client_transition_name(self: Vc) -> Vc { + Vc::cell(ECMASCRIPT_CLIENT_TRANSITION_NAME.into()) } #[turbo_tasks::function] @@ -275,23 +275,20 @@ impl AppProject { fn rsc_module_context(self: Vc) -> Vc { let transitions = [ ( - ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(), + ECMASCRIPT_CLIENT_TRANSITION_NAME.into(), Vc::upcast(NextEcmascriptClientReferenceTransition::new( Vc::upcast(self.client_transition()), self.ssr_transition(), )), ), ( - "next-dynamic".to_string(), + "next-dynamic".into(), Vc::upcast(NextDynamicTransition::new(Vc::upcast( self.client_transition(), ))), ), - ("next-ssr".to_string(), Vc::upcast(self.ssr_transition())), - ( - "next-shared".to_string(), - Vc::upcast(self.shared_transition()), - ), + ("next-ssr".into(), Vc::upcast(self.ssr_transition())), + ("next-shared".into(), Vc::upcast(self.shared_transition())), ] .into_iter() .collect(); @@ -300,7 +297,7 @@ impl AppProject { self.project().server_compile_time_info(), self.rsc_module_options_context(), self.rsc_resolve_options_context(), - Vc::cell("app-rsc".to_string()), + Vc::cell("app-rsc".into()), ) } @@ -308,24 +305,21 @@ impl AppProject { fn edge_rsc_module_context(self: Vc) -> Vc { let transitions = [ ( - ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(), + ECMASCRIPT_CLIENT_TRANSITION_NAME.into(), Vc::upcast(NextEcmascriptClientReferenceTransition::new( Vc::upcast(self.client_transition()), self.edge_ssr_transition(), )), ), ( - "next-dynamic".to_string(), + "next-dynamic".into(), Vc::upcast(NextDynamicTransition::new(Vc::upcast( self.client_transition(), ))), ), + ("next-ssr".into(), Vc::upcast(self.edge_ssr_transition())), ( - "next-ssr".to_string(), - Vc::upcast(self.edge_ssr_transition()), - ), - ( - "next-shared".to_string(), + "next-shared".into(), Vc::upcast(self.edge_shared_transition()), ), ] @@ -336,7 +330,7 @@ impl AppProject { self.project().edge_compile_time_info(), self.edge_rsc_module_options_context(), self.edge_rsc_resolve_options_context(), - Vc::cell("app-edge-rsc".to_string()), + Vc::cell("app-edge-rsc".into()), ) } @@ -344,23 +338,20 @@ impl AppProject { fn route_module_context(self: Vc) -> Vc { let transitions = [ ( - ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(), + ECMASCRIPT_CLIENT_TRANSITION_NAME.into(), Vc::upcast(NextEcmascriptClientReferenceTransition::new( Vc::upcast(self.client_transition()), self.ssr_transition(), )), ), ( - "next-dynamic".to_string(), + "next-dynamic".into(), Vc::upcast(NextDynamicTransition::new(Vc::upcast( self.client_transition(), ))), ), - ("next-ssr".to_string(), Vc::upcast(self.ssr_transition())), - ( - "next-shared".to_string(), - Vc::upcast(self.shared_transition()), - ), + ("next-ssr".into(), Vc::upcast(self.ssr_transition())), + ("next-shared".into(), Vc::upcast(self.shared_transition())), ] .into_iter() .collect(); @@ -370,7 +361,7 @@ impl AppProject { self.project().server_compile_time_info(), self.route_module_options_context(), self.route_resolve_options_context(), - Vc::cell("app-route".to_string()), + Vc::cell("app-route".into()), ) } @@ -378,21 +369,21 @@ impl AppProject { fn edge_route_module_context(self: Vc) -> Vc { let transitions = [ ( - ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(), + ECMASCRIPT_CLIENT_TRANSITION_NAME.into(), Vc::upcast(NextEcmascriptClientReferenceTransition::new( Vc::upcast(self.client_transition()), self.edge_ssr_transition(), )), ), ( - "next-dynamic".to_string(), + "next-dynamic".into(), Vc::upcast(NextDynamicTransition::new(Vc::upcast( self.client_transition(), ))), ), - ("next-ssr".to_string(), Vc::upcast(self.ssr_transition())), + ("next-ssr".into(), Vc::upcast(self.ssr_transition())), ( - "next-shared".to_string(), + "next-shared".into(), Vc::upcast(self.edge_shared_transition()), ), ] @@ -403,7 +394,7 @@ impl AppProject { self.project().edge_compile_time_info(), self.edge_route_module_options_context(), self.edge_route_resolve_options_context(), - Vc::cell("app-edge-route".to_string()), + Vc::cell("app-edge-route".into()), ) } @@ -414,7 +405,7 @@ impl AppProject { self.project().client_compile_time_info(), self.client_module_options_context(), self.client_resolve_options_context(), - Vc::cell("app-client".to_string()), + Vc::cell("app-client".into()), ) } @@ -470,7 +461,7 @@ impl AppProject { self.project().server_compile_time_info(), self.ssr_module_options_context(), self.ssr_resolve_options_context(), - Vc::cell("app-ssr".to_string()), + Vc::cell("app-ssr".into()), ) } @@ -480,7 +471,7 @@ impl AppProject { self.project().server_compile_time_info(), self.ssr_module_options_context(), self.ssr_resolve_options_context(), - Vc::cell("app-shared".to_string()), + Vc::cell("app-shared".into()), ) } @@ -490,7 +481,7 @@ impl AppProject { self.project().edge_compile_time_info(), self.edge_ssr_module_options_context(), self.edge_ssr_resolve_options_context(), - Vc::cell("app-edge-ssr".to_string()), + Vc::cell("app-edge-ssr".into()), ) } @@ -500,7 +491,7 @@ impl AppProject { self.project().edge_compile_time_info(), self.edge_ssr_module_options_context(), self.edge_ssr_resolve_options_context(), - Vc::cell("app-edge-shared".to_string()), + Vc::cell("app-edge-shared".into()), ) } @@ -553,7 +544,7 @@ impl AppProject { .iter() .map(|(pathname, app_entrypoint)| async { Ok(( - pathname.to_string(), + pathname.to_string().into(), app_entry_point_to_route(self, app_entrypoint.clone()) .await? .clone_value(), @@ -759,7 +750,7 @@ impl AppEndpoint { let client_relative_path = this.app_project.project().client_relative_path(); let client_relative_path_ref = client_relative_path.await?; - let server_path = node_root.join("server".to_string()); + let server_path = node_root.join("server".into()); let mut server_assets = vec![]; let mut client_assets = vec![]; @@ -781,7 +772,7 @@ impl AppEndpoint { app_entry .rsc_entry .ident() - .with_modifier(Vc::cell("client_shared_chunks".to_string())), + .with_modifier(Vc::cell("client_shared_chunks".into())), this.app_project.client_runtime_entries(), client_chunking_context, ) @@ -794,7 +785,7 @@ impl AppEndpoint { let chunk_path = chunk.ident().path().await?; if chunk_path.extension_ref() == Some("js") { if let Some(chunk_path) = client_relative_path_ref.get_path_to(&chunk_path) { - client_shared_chunks_paths.push(chunk_path.to_string()); + client_shared_chunks_paths.push(chunk_path.into()); } } } @@ -878,7 +869,7 @@ impl AppEndpoint { Ok(client_relative_path_ref .get_path_to(path) .context("asset path should be inside client root")? - .to_string()) + .into()) }) .collect::>>()?; entry_client_chunks_paths.extend(client_shared_chunks_paths.iter().cloned()); @@ -890,9 +881,9 @@ impl AppEndpoint { }; let manifest_path_prefix = &app_entry.original_name; let app_build_manifest_output = Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/app{manifest_path_prefix}/app-build-manifest.json", - )), + node_root.join( + format!("server/app{manifest_path_prefix}/app-build-manifest.json",).into(), + ), AssetContent::file( File::from(serde_json::to_string_pretty(&app_build_manifest)?).into(), ), @@ -903,16 +894,16 @@ impl AppEndpoint { // load it as a RawModule. let next_package = get_next_package(this.app_project.project().project_path()); let polyfill_source = FileSource::new( - next_package.join("dist/build/polyfills/polyfill-nomodule.js".to_string()), + next_package.join("dist/build/polyfills/polyfill-nomodule.js".into()), ); let polyfill_output_path = - client_chunking_context.chunk_path(polyfill_source.ident(), ".js".to_string()); + client_chunking_context.chunk_path(polyfill_source.ident(), ".js".into()); let polyfill_output_asset = RawOutput::new(polyfill_output_path, Vc::upcast(polyfill_source)); let polyfill_client_path = client_relative_path_ref .get_path_to(&*polyfill_output_path.await?) .context("failed to resolve client-relative path to polyfill")? - .to_string(); + .into(); let polyfill_client_paths = vec![polyfill_client_path]; client_assets.push(Vc::upcast(polyfill_output_asset)); @@ -922,9 +913,8 @@ impl AppEndpoint { ..Default::default() }; let build_manifest_output = Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/app{manifest_path_prefix}/build-manifest.json", - )), + node_root + .join(format!("server/app{manifest_path_prefix}/build-manifest.json",).into()), AssetContent::file( File::from(serde_json::to_string_pretty(&build_manifest)?).into(), ), @@ -973,17 +963,14 @@ impl AppEndpoint { fn create_app_paths_manifest( node_root: Vc, original_name: &str, - filename: String, + filename: RcStr, ) -> Result>> { let manifest_path_prefix = original_name; - let path = node_root.join(format!( - "server/app{manifest_path_prefix}/app-paths-manifest.json", - )); + let path = node_root + .join(format!("server/app{manifest_path_prefix}/app-paths-manifest.json",).into()); let app_paths_manifest = AppPathsManifest { node_server_app_paths: PagesManifest { - pages: [(original_name.to_string(), filename)] - .into_iter() - .collect(), + pages: [(original_name.into(), filename)].into_iter().collect(), }, ..Default::default() }; @@ -1057,11 +1044,11 @@ impl AppEndpoint { // // they are created in `setup-dev-bundler.ts` let mut file_paths_from_root = vec![ - "server/server-reference-manifest.js".to_string(), - "server/middleware-build-manifest.js".to_string(), - "server/middleware-react-loadable-manifest.js".to_string(), - "server/next-font-manifest.js".to_string(), - "server/interception-route-rewrite-manifest.js".to_string(), + "server/server-reference-manifest.js".into(), + "server/middleware-build-manifest.js".into(), + "server/middleware-react-loadable-manifest.js".into(), + "server/next-font-manifest.js".into(), + "server/interception-route-rewrite-manifest.js".into(), ]; let mut wasm_paths_from_root = vec![]; @@ -1079,20 +1066,20 @@ impl AppEndpoint { wasm_paths_from_root .extend(get_wasm_paths_from_root(&node_root_value, &all_output_assets).await?); - let entry_file = "app-edge-has-no-entrypoint".to_string(); + let entry_file = "app-edge-has-no-entrypoint".into(); // create middleware manifest // TODO(alexkirsz) This should be shared with next build. let named_regex = get_named_middleware_regex(&app_entry.pathname); let matchers = MiddlewareMatcher { - regexp: Some(named_regex), + regexp: Some(named_regex.into()), original_source: app_entry.pathname.clone(), ..Default::default() }; let edge_function_definition = EdgeFunctionDefinition { files: file_paths_from_root, wasm: wasm_paths_to_bindings(wasm_paths_from_root), - name: app_entry.pathname.to_string(), + name: app_entry.pathname.clone(), page: app_entry.original_name.clone(), regions: app_entry .config @@ -1113,9 +1100,10 @@ impl AppEndpoint { }; let manifest_path_prefix = &app_entry.original_name; let middleware_manifest_v2 = Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/app{manifest_path_prefix}/middleware-manifest.json", - )), + node_root.join( + format!("server/app{manifest_path_prefix}/middleware-manifest.json",) + .into(), + ), AssetContent::file( FileContent::Content(File::from(serde_json::to_string_pretty( &middleware_manifest_v2, @@ -1145,10 +1133,13 @@ impl AppEndpoint { let loadable_manifest_output = create_react_loadable_manifest( dynamic_import_entries, client_relative_path, - node_root.join(format!( - "server/app{}/react-loadable-manifest.json", - &app_entry.original_name - )), + node_root.join( + format!( + "server/app{}/react-loadable-manifest.json", + &app_entry.original_name + ) + .into(), + ), ); server_assets.extend(loadable_manifest_output.await?.iter().copied()); @@ -1188,10 +1179,13 @@ impl AppEndpoint { } = *{ let _span = tracing::trace_span!("server node entrypoint").entered(); chunking_context.entry_chunk_group( - server_path.join(format!( - "app{original_name}.js", - original_name = app_entry.original_name - )), + server_path.join( + format!( + "app{original_name}.js", + original_name = app_entry.original_name + ) + .into(), + ), app_entry.rsc_entry, Vc::cell(evaluatable_assets), Value::new(AvailabilityInfo::Root), @@ -1207,7 +1201,7 @@ impl AppEndpoint { .await? .get_path_to(&*rsc_chunk.ident().path().await?) .context("RSC chunk path should be within app paths manifest directory")? - .to_string(), + .into(), )?; server_assets.push(app_paths_manifest_output); @@ -1228,10 +1222,13 @@ impl AppEndpoint { let loadable_manifest_output = create_react_loadable_manifest( dynamic_import_entries, client_relative_path, - node_root.join(format!( - "server/app{}/react-loadable-manifest.json", - &app_entry.original_name - )), + node_root.join( + format!( + "server/app{}/react-loadable-manifest.json", + &app_entry.original_name + ) + .into(), + ), ); server_assets.extend(loadable_manifest_output.await?.iter().copied()); diff --git a/packages/next-swc/crates/next-api/src/dynamic_imports.rs b/packages/next-swc/crates/next-api/src/dynamic_imports.rs index 7f53b28ddcffd..92b945a5a0f76 100644 --- a/packages/next-swc/crates/next-api/src/dynamic_imports.rs +++ b/packages/next-swc/crates/next-api/src/dynamic_imports.rs @@ -6,7 +6,7 @@ use indexmap::IndexMap; use tracing::Level; use turbo_tasks::{ graph::{GraphTraversal, NonDeterministic, VisitControlFlow}, - ReadRef, TryJoinIterExt, Value, ValueToString, Vc, + RcStr, ReadRef, TryJoinIterExt, Value, ValueToString, Vc, }; use turbopack_binding::{ swc::core::ecma::{ @@ -39,7 +39,7 @@ where F: FnMut(Vc>) -> Fu, Fu: Future>> + Send, { - let mut chunks_hash: HashMap> = HashMap::new(); + let mut chunks_hash: HashMap> = HashMap::new(); let mut dynamic_import_chunks = IndexMap::new(); // Iterate over the collected import mappings, and create a chunk for each @@ -62,7 +62,7 @@ where // chunks in case if there are same modules being imported in differnt // origins. let chunk_group = build_chunk(module).await?; - chunks_hash.insert(imported_raw_str.to_string(), chunk_group); + chunks_hash.insert(imported_raw_str.clone(), chunk_group); chunk_group }; @@ -178,22 +178,19 @@ pub(crate) async fn collect_next_dynamic_imports( struct NextDynamicVisit; -impl turbo_tasks::graph::Visit<(Vc>, ReadRef)> for NextDynamicVisit { - type Edge = (Vc>, ReadRef); +impl turbo_tasks::graph::Visit<(Vc>, ReadRef)> for NextDynamicVisit { + type Edge = (Vc>, ReadRef); type EdgesIntoIter = Vec; type EdgesFuture = impl Future>; fn visit( &mut self, edge: Self::Edge, - ) -> VisitControlFlow<(Vc>, ReadRef)> { + ) -> VisitControlFlow<(Vc>, ReadRef)> { VisitControlFlow::Continue(edge) } - fn edges( - &mut self, - &(parent, _): &(Vc>, ReadRef), - ) -> Self::EdgesFuture { + fn edges(&mut self, &(parent, _): &(Vc>, ReadRef)) -> Self::EdgesFuture { async move { primary_referenced_modules(parent) .await? @@ -204,7 +201,7 @@ impl turbo_tasks::graph::Visit<(Vc>, ReadRef)> for NextD } } - fn span(&mut self, (_, name): &(Vc>, ReadRef)) -> tracing::Span { + fn span(&mut self, (_, name): &(Vc>, ReadRef)) -> tracing::Span { tracing::span!(Level::INFO, "next/dynamic visit", name = display(name)) } } @@ -244,7 +241,7 @@ async fn build_dynamic_imports_map_for_module( client_asset_context, server_module.ident().path(), )), - Request::parse(Value::new(Pattern::Constant(import.to_string()))), + Request::parse(Value::new(Pattern::Constant(import.clone()))), Value::new(EcmaScriptModulesReferenceSubType::DynamicImport), IssueSeverity::Error.cell(), None, @@ -264,7 +261,7 @@ async fn build_dynamic_imports_map_for_module( /// import wrapped with dynamic() via CollectImportSourceVisitor. struct DynamicImportVisitor { dynamic_ident: Option, - pub import_sources: Vec, + pub import_sources: Vec, } impl DynamicImportVisitor { @@ -309,7 +306,7 @@ impl Visit for DynamicImportVisitor { /// A visitor to collect import source string from import('path/to/module') struct CollectImportSourceVisitor { - import_source: Option, + import_source: Option, } impl CollectImportSourceVisitor { @@ -329,7 +326,7 @@ impl Visit for CollectImportSourceVisitor { if let Callee::Import(_import) = call_expr.callee { if let Some(arg) = call_expr.args.first() { if let Expr::Lit(Lit::Str(str_)) = &*arg.expr { - self.import_source = Some(str_.value.to_string()); + self.import_source = Some(str_.value.as_str().into()); } } } @@ -339,8 +336,8 @@ impl Visit for CollectImportSourceVisitor { } } -pub type DynamicImportedModules = Vec<(String, Vc>)>; -pub type DynamicImportedOutputAssets = Vec<(String, Vc)>; +pub type DynamicImportedModules = Vec<(RcStr, Vc>)>; +pub type DynamicImportedOutputAssets = Vec<(RcStr, Vc)>; /// A struct contains mapping for the dynamic imports to construct chunk per /// each individual module (Origin Module, Vec<(ImportSourceString, Module)>) diff --git a/packages/next-swc/crates/next-api/src/entrypoints.rs b/packages/next-swc/crates/next-api/src/entrypoints.rs index 578a3aba34695..21d69fa692d88 100644 --- a/packages/next-swc/crates/next-api/src/entrypoints.rs +++ b/packages/next-swc/crates/next-api/src/entrypoints.rs @@ -1,5 +1,5 @@ use indexmap::IndexMap; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use crate::{ project::{Instrumentation, Middleware}, @@ -8,7 +8,7 @@ use crate::{ #[turbo_tasks::value(shared)] pub struct Entrypoints { - pub routes: IndexMap, + pub routes: IndexMap, pub middleware: Option, pub instrumentation: Option, pub pages_document_endpoint: Vc>, diff --git a/packages/next-swc/crates/next-api/src/font.rs b/packages/next-swc/crates/next-api/src/font.rs index d5fc52f994a6d..d29c9a840cbac 100644 --- a/packages/next-swc/crates/next-api/src/font.rs +++ b/packages/next-swc/crates/next-api/src/font.rs @@ -1,6 +1,6 @@ use anyhow::Result; use next_core::{all_assets_from_entries, next_manifests::NextFontManifest}; -use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks::{RcStr, ValueToString, Vc}; use turbopack_binding::{ turbo::tasks_fs::{File, FileSystemPath}, turbopack::core::{ @@ -34,13 +34,9 @@ pub(crate) async fn create_font_manifest( .collect(); let path = if app_dir { - node_root.join(format!( - "server/app{manifest_path_prefix}/next-font-manifest.json", - )) + node_root.join(format!("server/app{manifest_path_prefix}/next-font-manifest.json",).into()) } else { - node_root.join(format!( - "server/pages{manifest_path_prefix}/next-font-manifest.json" - )) + node_root.join(format!("server/pages{manifest_path_prefix}/next-font-manifest.json").into()) }; let has_fonts = !font_paths.is_empty(); @@ -49,13 +45,14 @@ pub(crate) async fn create_font_manifest( let font_paths = font_paths .into_iter() .filter(|path| path.contains(".p.")) + .map(RcStr::from) .collect::>(); let next_font_manifest = if !has_fonts { Default::default() } else if app_dir { let dir_str = dir.to_string().await?; - let page_path = format!("{}{}", dir_str, original_name); + let page_path = format!("{}{}", dir_str, original_name).into(); NextFontManifest { app: [(page_path, font_paths)].into_iter().collect(), @@ -64,7 +61,7 @@ pub(crate) async fn create_font_manifest( } } else { NextFontManifest { - pages: [(pathname.to_string(), font_paths)].into_iter().collect(), + pages: [(pathname.into(), font_paths)].into_iter().collect(), pages_using_size_adjust: using_size_adjust, ..Default::default() } diff --git a/packages/next-swc/crates/next-api/src/instrumentation.rs b/packages/next-swc/crates/next-api/src/instrumentation.rs index ce37fa9be9541..03ce17691e66c 100644 --- a/packages/next-swc/crates/next-api/src/instrumentation.rs +++ b/packages/next-swc/crates/next-api/src/instrumentation.rs @@ -73,7 +73,7 @@ impl InstrumentationEndpoint { self.context, self.project.project_path(), userland_module, - "instrumentation".to_string(), + "instrumentation".into(), ); let mut evaluatable_assets = get_server_runtime_entries( @@ -126,7 +126,7 @@ impl InstrumentationEndpoint { .entry_chunk_group( self.project .node_root() - .join("server/instrumentation.js".to_string()), + .join("server/instrumentation.js".into()), module, get_server_runtime_entries( Value::new(ServerContextType::Instrumentation), @@ -161,7 +161,7 @@ impl InstrumentationEndpoint { let instrumentation_definition = InstrumentationDefinition { files: file_paths_from_root, wasm: wasm_paths_to_bindings(wasm_paths_from_root), - name: "instrumentation".to_string(), + name: "instrumentation".into(), ..Default::default() }; let middleware_manifest_v2 = MiddlewaresManifestV2 { @@ -169,7 +169,7 @@ impl InstrumentationEndpoint { ..Default::default() }; let middleware_manifest_v2 = Vc::upcast(VirtualOutputAsset::new( - node_root.join("server/instrumentation/middleware-manifest.json".to_string()), + node_root.join("server/instrumentation/middleware-manifest.json".into()), AssetContent::file( FileContent::Content(File::from(serde_json::to_string_pretty( &middleware_manifest_v2, diff --git a/packages/next-swc/crates/next-api/src/loadable_manifest.rs b/packages/next-swc/crates/next-api/src/loadable_manifest.rs index b79a1ecaa0315..0c7705a7205dd 100644 --- a/packages/next-swc/crates/next-api/src/loadable_manifest.rs +++ b/packages/next-swc/crates/next-api/src/loadable_manifest.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use next_core::next_manifests::LoadableManifest; -use turbo_tasks::{TryFlatJoinIterExt, Vc}; +use turbo_tasks::{RcStr, TryFlatJoinIterExt, Vc}; use turbopack_binding::{ turbo::tasks_fs::{File, FileContent, FileSystemPath}, turbopack::core::{ @@ -24,7 +24,7 @@ pub async fn create_react_loadable_manifest( let dynamic_import_entries = &*dynamic_import_entries.await?; let mut output = vec![]; - let mut loadable_manifest: HashMap = Default::default(); + let mut loadable_manifest: HashMap = Default::default(); for (origin, dynamic_imports) in dynamic_import_entries.into_iter() { let origin_path = &*origin.ident().path().await?; @@ -33,7 +33,7 @@ pub async fn create_react_loadable_manifest( let chunk_output = chunk_output.await?; output.extend(chunk_output.iter().copied()); - let id = format!("{} -> {}", origin_path, import); + let id: RcStr = format!("{} -> {}", origin_path, import).into(); let client_relative_path_value = client_relative_path.await?; let files = chunk_output @@ -43,7 +43,7 @@ pub async fn create_react_loadable_manifest( async move { Ok(client_relative_path_value .get_path_to(&*file.ident().path().await?) - .map(|path| path.to_string())) + .map(|path| path.into())) } }) .try_flat_join() diff --git a/packages/next-swc/crates/next-api/src/middleware.rs b/packages/next-swc/crates/next-api/src/middleware.rs index f4f2f63c8ce21..d2df5a768cff3 100644 --- a/packages/next-swc/crates/next-api/src/middleware.rs +++ b/packages/next-swc/crates/next-api/src/middleware.rs @@ -75,7 +75,7 @@ impl MiddlewareEndpoint { self.context, self.project.project_path(), module, - "middleware".to_string(), + "middleware".into(), ); let mut evaluatable_assets = get_server_runtime_entries( @@ -140,7 +140,7 @@ impl MiddlewareEndpoint { .iter() .map(|matcher| match matcher { MiddlewareMatcherKind::Str(matchers) => MiddlewareMatcher { - original_source: matchers.to_string(), + original_source: matchers.as_str().into(), ..Default::default() }, MiddlewareMatcherKind::Matcher(matcher) => matcher.clone(), @@ -148,8 +148,8 @@ impl MiddlewareEndpoint { .collect() } else { vec![MiddlewareMatcher { - regexp: Some("^/.*$".to_string()), - original_source: "/:path*".to_string(), + regexp: Some("^/.*$".into()), + original_source: "/:path*".into(), ..Default::default() }] }; @@ -157,21 +157,21 @@ impl MiddlewareEndpoint { let edge_function_definition = EdgeFunctionDefinition { files: file_paths_from_root, wasm: wasm_paths_to_bindings(wasm_paths_from_root), - name: "middleware".to_string(), - page: "/".to_string(), + name: "middleware".into(), + page: "/".into(), regions: None, matchers, env: this.project.edge_env().await?.clone_value(), ..Default::default() }; let middleware_manifest_v2 = MiddlewaresManifestV2 { - middleware: [("/".to_string(), edge_function_definition)] + middleware: [("/".into(), edge_function_definition)] .into_iter() .collect(), ..Default::default() }; let middleware_manifest_v2 = Vc::upcast(VirtualOutputAsset::new( - node_root.join("server/middleware/middleware-manifest.json".to_string()), + node_root.join("server/middleware/middleware-manifest.json".into()), AssetContent::file( FileContent::Content(File::from(serde_json::to_string_pretty( &middleware_manifest_v2, diff --git a/packages/next-swc/crates/next-api/src/pages.rs b/packages/next-swc/crates/next-api/src/pages.rs index fc59ee4a3d158..d6b0c398732a2 100644 --- a/packages/next-swc/crates/next-api/src/pages.rs +++ b/packages/next-swc/crates/next-api/src/pages.rs @@ -27,7 +27,7 @@ use next_core::{ }; use serde::{Deserialize, Serialize}; use tracing::Instrument; -use turbo_tasks::{trace::TraceRawVcs, Completion, TaskInput, TryJoinIterExt, Value, Vc}; +use turbo_tasks::{trace::TraceRawVcs, Completion, RcStr, TaskInput, TryJoinIterExt, Value, Vc}; use turbopack_binding::{ turbo::tasks_fs::{ File, FileContent, FileSystem, FileSystemPath, FileSystemPathOption, VirtualFileSystem, @@ -104,27 +104,27 @@ impl PagesProject { let mut routes = IndexMap::new(); async fn add_page_to_routes( - routes: &mut IndexMap, + routes: &mut IndexMap, page: Vc, - make_route: impl Fn(Vc, Vc, Vc) -> Route, + make_route: impl Fn(Vc, Vc, Vc) -> Route, ) -> Result<()> { let PagesStructureItem { next_router_path, project_path, original_path, } = *page.await?; - let pathname = format!("/{}", next_router_path.await?.path); + let pathname: RcStr = format!("/{}", next_router_path.await?.path).into(); let pathname_vc = Vc::cell(pathname.clone()); - let original_name = Vc::cell(format!("/{}", original_path.await?.path)); + let original_name = Vc::cell(format!("/{}", original_path.await?.path).into()); let route = make_route(pathname_vc, original_name, project_path); routes.insert(pathname, route); Ok(()) } async fn add_dir_to_routes( - routes: &mut IndexMap, + routes: &mut IndexMap, dir: Vc, - make_route: impl Fn(Vc, Vc, Vc) -> Route, + make_route: impl Fn(Vc, Vc, Vc) -> Route, ) -> Result<()> { let mut queue = vec![dir]; while let Some(dir) = queue.pop() { @@ -201,9 +201,9 @@ impl PagesProject { project_path, original_path, } = *item.await?; - let pathname = format!("/{}", next_router_path.await?.path); + let pathname: RcStr = format!("/{}", next_router_path.await?.path).into(); let pathname_vc = Vc::cell(pathname.clone()); - let original_name = Vc::cell(format!("/{}", original_path.await?.path)); + let original_name = Vc::cell(format!("/{}", original_path.await?.path).into()); let path = project_path; let endpoint = Vc::upcast(PageEndpoint::new( ty, @@ -255,7 +255,7 @@ impl PagesProject { Ok(if let Some(pages) = self.pages_structure().await?.pages { pages.project_path() } else { - self.project().project_path().join("pages".to_string()) + self.project().project_path().join("pages".into()) }) } @@ -263,7 +263,7 @@ impl PagesProject { fn transitions(self: Vc) -> Vc { Vc::cell( [( - "next-dynamic".to_string(), + "next-dynamic".into(), Vc::upcast(NextDynamicTransition::new(Vc::upcast( self.client_transition(), ))), @@ -279,7 +279,7 @@ impl PagesProject { self.project().client_compile_time_info(), self.client_module_options_context(), self.client_resolve_options_context(), - Vc::cell("client".to_string()), + Vc::cell("client".into()), ) } @@ -317,7 +317,7 @@ impl PagesProject { self.project().client_compile_time_info(), self.client_module_options_context(), self.client_resolve_options_context(), - Vc::cell("client".to_string()), + Vc::cell("client".into()), )) } @@ -328,7 +328,7 @@ impl PagesProject { self.project().server_compile_time_info(), self.ssr_module_options_context(), self.ssr_resolve_options_context(), - Vc::cell("ssr".to_string()), + Vc::cell("ssr".into()), ) } @@ -341,7 +341,7 @@ impl PagesProject { self.project().server_compile_time_info(), self.api_module_options_context(), self.ssr_resolve_options_context(), - Vc::cell("api".to_string()), + Vc::cell("api".into()), ) } @@ -352,7 +352,7 @@ impl PagesProject { self.project().server_compile_time_info(), self.ssr_data_module_options_context(), self.ssr_resolve_options_context(), - Vc::cell("ssr-data".to_string()), + Vc::cell("ssr-data".into()), ) } @@ -363,7 +363,7 @@ impl PagesProject { self.project().edge_compile_time_info(), self.edge_ssr_module_options_context(), self.edge_ssr_resolve_options_context(), - Vc::cell("edge-ssr".to_string()), + Vc::cell("edge-ssr".into()), ) } @@ -374,7 +374,7 @@ impl PagesProject { self.project().edge_compile_time_info(), self.edge_api_module_options_context(), self.edge_ssr_resolve_options_context(), - Vc::cell("edge-api".to_string()), + Vc::cell("edge-api".into()), ) } @@ -385,7 +385,7 @@ impl PagesProject { self.project().edge_compile_time_info(), self.edge_ssr_data_module_options_context(), self.edge_ssr_resolve_options_context(), - Vc::cell("edge-ssr-data".to_string()), + Vc::cell("edge-ssr-data".into()), ) } @@ -570,8 +570,8 @@ impl PagesProject { struct PageEndpoint { ty: PageEndpointType, pages_project: Vc, - pathname: Vc, - original_name: Vc, + pathname: Vc, + original_name: Vc, path: Vc, pages_structure: Vc, } @@ -597,8 +597,8 @@ impl PageEndpoint { fn new( ty: PageEndpointType, pages_project: Vc, - pathname: Vc, - original_name: Vc, + pathname: Vc, + original_name: Vc, path: Vc, pages_structure: Vc, ) -> Vc { @@ -640,17 +640,14 @@ impl PageEndpoint { let client_main_module = esm_resolve( Vc::upcast(PlainResolveOrigin::new( client_module_context, - this.pages_project - .project() - .project_path() - .join("_".to_string()), + this.pages_project.project().project_path().join("_".into()), )), Request::parse(Value::new(Pattern::Constant( match *this.pages_project.project().next_mode().await? { NextMode::Development => "next/dist/client/next-dev-turbopack.js", NextMode::Build => "next/dist/client/next-turbopack.js", } - .to_string(), + .into(), ))), Value::new(EcmaScriptModulesReferenceSubType::Undefined), IssueSeverity::Error.cell(), @@ -798,7 +795,7 @@ impl PageEndpoint { let asset_path = get_asset_path_from_pathname(pathname, ".js"); - let ssr_entry_chunk_path_string = format!("pages{asset_path}"); + let ssr_entry_chunk_path_string: RcStr = format!("pages{asset_path}").into(); let ssr_entry_chunk_path = node_path.join(ssr_entry_chunk_path_string); let EntryChunkGroupResult { asset: ssr_entry_chunk, @@ -851,7 +848,7 @@ impl PageEndpoint { this.pages_project .project() .node_root() - .join("server".to_string()), + .join("server".into()), this.pages_project.project().project_path(), this.pages_project.ssr_module_context(), this.pages_project.edge_ssr_module_context(), @@ -871,7 +868,7 @@ impl PageEndpoint { this.pages_project .project() .node_root() - .join("server/data".to_string()), + .join("server/data".into()), this.pages_project.project().project_path(), this.pages_project.ssr_data_module_context(), this.pages_project.edge_ssr_data_module_context(), @@ -891,7 +888,7 @@ impl PageEndpoint { this.pages_project .project() .node_root() - .join("server".to_string()), + .join("server".into()), this.pages_project.project().project_path(), this.pages_project.api_module_context(), this.pages_project.edge_api_module_context(), @@ -912,21 +909,20 @@ impl PageEndpoint { let chunk_path = entry_chunk.ident().path().await?; let asset_path = node_root - .join("server".to_string()) + .join("server".into()) .await? .get_path_to(&chunk_path) .context("ssr chunk entry path must be inside the node root")?; let pages_manifest = PagesManifest { - pages: [(this.pathname.await?.clone_value(), asset_path.to_string())] + pages: [(this.pathname.await?.clone_value(), asset_path.into())] .into_iter() .collect(), }; let manifest_path_prefix = get_asset_prefix_from_pathname(&this.pathname.await?); Ok(Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/pages{manifest_path_prefix}/pages-manifest.json", - )), + node_root + .join(format!("server/pages{manifest_path_prefix}/pages-manifest.json",).into()), AssetContent::file(File::from(serde_json::to_string_pretty(&pages_manifest)?).into()), ))) } @@ -942,9 +938,9 @@ impl PageEndpoint { Ok(create_react_loadable_manifest( dynamic_import_entries, client_relative_path, - node_root.join(format!( - "server/pages{loadable_path_prefix}/react-loadable-manifest.json" - )), + node_root.join( + format!("server/pages{loadable_path_prefix}/react-loadable-manifest.json").into(), + ), )) } @@ -971,7 +967,7 @@ impl PageEndpoint { Ok(client_relative_path_ref .get_path_to(&chunk_path) .context("client chunk entry path must be inside the client root")? - .to_string()) + .into()) } }) .try_join() @@ -983,9 +979,8 @@ impl PageEndpoint { }; let manifest_path_prefix = get_asset_prefix_from_pathname(&this.pathname.await?); Ok(Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/pages{manifest_path_prefix}/build-manifest.json", - )), + node_root + .join(format!("server/pages{manifest_path_prefix}/build-manifest.json",).into()), AssetContent::file(File::from(serde_json::to_string_pretty(&build_manifest)?).into()), ))) } @@ -1070,10 +1065,10 @@ impl PageEndpoint { // // they are created in `setup-dev-bundler.ts` let mut file_paths_from_root = vec![ - "server/server-reference-manifest.js".to_string(), - "server/middleware-build-manifest.js".to_string(), - "server/middleware-react-loadable-manifest.js".to_string(), - "server/next-font-manifest.js".to_string(), + "server/server-reference-manifest.js".into(), + "server/middleware-build-manifest.js".into(), + "server/middleware-react-loadable-manifest.js".into(), + "server/next-font-manifest.js".into(), ]; let mut wasm_paths_from_root = vec![]; @@ -1087,35 +1082,36 @@ impl PageEndpoint { wasm_paths_from_root .extend(get_wasm_paths_from_root(&node_root_value, &all_output_assets).await?); - let named_regex = get_named_middleware_regex(&pathname); + let named_regex = get_named_middleware_regex(&pathname).into(); let matchers = MiddlewareMatcher { regexp: Some(named_regex), - original_source: pathname.to_string(), + original_source: pathname.clone_value(), ..Default::default() }; let original_name = this.original_name.await?; let edge_function_definition = EdgeFunctionDefinition { files: file_paths_from_root, wasm: wasm_paths_to_bindings(wasm_paths_from_root), - name: pathname.to_string(), - page: original_name.to_string(), + name: pathname.clone_value(), + page: original_name.clone_value(), regions: None, matchers: vec![matchers], env: this.pages_project.project().edge_env().await?.clone_value(), ..Default::default() }; let middleware_manifest_v2 = MiddlewaresManifestV2 { - sorted_middleware: vec![pathname.to_string()], - functions: [(pathname.to_string(), edge_function_definition)] + sorted_middleware: vec![pathname.clone_value()], + functions: [(pathname.clone_value(), edge_function_definition)] .into_iter() .collect(), ..Default::default() }; let manifest_path_prefix = get_asset_prefix_from_pathname(&this.pathname.await?); let middleware_manifest_v2 = Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/pages{manifest_path_prefix}/middleware-manifest.json" - )), + node_root.join( + format!("server/pages{manifest_path_prefix}/middleware-manifest.json") + .into(), + ), AssetContent::file( FileContent::Content(File::from(serde_json::to_string_pretty( &middleware_manifest_v2, @@ -1154,16 +1150,16 @@ impl Endpoint for PageEndpoint { let span = { match this.ty { PageEndpointType::Html => { - tracing::info_span!("page endpoint HTML", name = *original_name) + tracing::info_span!("page endpoint HTML", name = original_name.to_string()) } PageEndpointType::Data => { - tracing::info_span!("page endpoint data", name = *original_name) + tracing::info_span!("page endpoint data", name = original_name.to_string()) } PageEndpointType::Api => { - tracing::info_span!("page endpoint API", name = *original_name) + tracing::info_span!("page endpoint API", name = original_name.to_string()) } PageEndpointType::SsrOnly => { - tracing::info_span!("page endpoint SSR", name = *original_name) + tracing::info_span!("page endpoint SSR", name = original_name.to_string()) } } }; diff --git a/packages/next-swc/crates/next-api/src/paths.rs b/packages/next-swc/crates/next-api/src/paths.rs index 0426f269db78a..4ffd865333438 100644 --- a/packages/next-swc/crates/next-api/src/paths.rs +++ b/packages/next-swc/crates/next-api/src/paths.rs @@ -1,7 +1,7 @@ use anyhow::Result; use next_core::{all_assets_from_entries, next_manifests::AssetBinding}; use serde::{Deserialize, Serialize}; -use turbo_tasks::{trace::TraceRawVcs, TryFlatJoinIterExt, Vc}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, TryFlatJoinIterExt, Vc}; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, turbopack::core::{ @@ -62,7 +62,7 @@ pub async fn all_server_paths( pub async fn all_paths_in_root( assets: Vc, root: Vc, -) -> Result>> { +) -> Result>> { let all_assets = &*all_assets_from_entries(assets).await?; let root = &*root.await?; @@ -75,7 +75,7 @@ pub(crate) async fn get_paths_from_root( root: &FileSystemPath, output_assets: &[Vc>], filter: impl FnOnce(&str) -> bool + Copy, -) -> Result> { +) -> Result> { output_assets .iter() .map({ @@ -86,7 +86,7 @@ pub(crate) async fn get_paths_from_root( }; Ok(if filter(relative) { - Some(relative.to_string()) + Some(relative.into()) } else { None }) @@ -99,21 +99,21 @@ pub(crate) async fn get_paths_from_root( pub(crate) async fn get_js_paths_from_root( root: &FileSystemPath, output_assets: &[Vc>], -) -> Result> { +) -> Result> { get_paths_from_root(root, output_assets, |path| path.ends_with(".js")).await } pub(crate) async fn get_wasm_paths_from_root( root: &FileSystemPath, output_assets: &[Vc>], -) -> Result> { +) -> Result> { get_paths_from_root(root, output_assets, |path| path.ends_with(".wasm")).await } pub(crate) async fn get_font_paths_from_root( root: &FileSystemPath, output_assets: &[Vc>], -) -> Result> { +) -> Result> { get_paths_from_root(root, output_assets, |path| { path.ends_with(".woff") || path.ends_with(".woff2") @@ -142,7 +142,7 @@ fn get_file_stem(path: &str) -> &str { } } -pub(crate) fn wasm_paths_to_bindings(paths: Vec) -> Vec { +pub(crate) fn wasm_paths_to_bindings(paths: Vec) -> Vec { paths .into_iter() .map(|path| { @@ -155,7 +155,7 @@ pub(crate) fn wasm_paths_to_bindings(paths: Vec) -> Vec { ); AssetBinding { - name: format!("wasm_{}", escaped), + name: format!("wasm_{}", escaped).into(), file_path: path, } }) diff --git a/packages/next-swc/crates/next-api/src/project.rs b/packages/next-swc/crates/next-api/src/project.rs index d165331e5f1be..fa04c10562373 100644 --- a/packages/next-swc/crates/next-api/src/project.rs +++ b/packages/next-swc/crates/next-api/src/project.rs @@ -26,7 +26,7 @@ use turbo_tasks::{ debug::ValueDebugFormat, graph::{AdjacencyMap, GraphTraversal}, trace::TraceRawVcs, - Completion, Completions, IntoTraitRef, State, TaskInput, TraitRef, TransientInstance, + Completion, Completions, IntoTraitRef, RcStr, State, TaskInput, TraitRef, TransientInstance, TryFlatJoinIterExt, Value, Vc, }; use turbopack_binding::{ @@ -71,9 +71,9 @@ use crate::{ #[derive(Debug, Serialize, Deserialize, Clone, TaskInput, PartialEq, Eq, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct DraftModeOptions { - pub preview_mode_id: String, - pub preview_mode_encryption_key: String, - pub preview_mode_signing_key: String, + pub preview_mode_id: RcStr, + pub preview_mode_encryption_key: RcStr, + pub preview_mode_signing_key: RcStr, } #[derive(Debug, Serialize, Deserialize, Clone, TaskInput, PartialEq, Eq, TraceRawVcs)] @@ -81,19 +81,19 @@ pub struct DraftModeOptions { pub struct ProjectOptions { /// A root path from which all files must be nested under. Trying to access /// a file outside this root will fail. Think of this as a chroot. - pub root_path: String, + pub root_path: RcStr, /// A path inside the root_path which contains the app/pages directories. - pub project_path: String, + pub project_path: RcStr, /// The contents of next.config.js, serialized to JSON. - pub next_config: String, + pub next_config: RcStr, /// The contents of ts/config read by load-jsconfig, serialized to JSON. - pub js_config: String, + pub js_config: RcStr, /// A map of environment variables to use when compiling code. - pub env: Vec<(String, String)>, + pub env: Vec<(RcStr, RcStr)>, /// A map of environment variables which should get injected at compile /// time. @@ -106,10 +106,10 @@ pub struct ProjectOptions { pub dev: bool, /// The server actions encryption key. - pub encryption_key: String, + pub encryption_key: RcStr, /// The build id. - pub build_id: String, + pub build_id: RcStr, /// Options for draft mode. pub preview_props: DraftModeOptions, @@ -120,19 +120,19 @@ pub struct ProjectOptions { pub struct PartialProjectOptions { /// A root path from which all files must be nested under. Trying to access /// a file outside this root will fail. Think of this as a chroot. - pub root_path: Option, + pub root_path: Option, /// A path inside the root_path which contains the app/pages directories. - pub project_path: Option, + pub project_path: Option, /// The contents of next.config.js, serialized to JSON. - pub next_config: Option, + pub next_config: Option, /// The contents of ts/config read by load-jsconfig, serialized to JSON. - pub js_config: Option, + pub js_config: Option, /// A map of environment variables to use when compiling code. - pub env: Option>, + pub env: Option>, /// A map of environment variables which should get injected at compile /// time. @@ -145,10 +145,10 @@ pub struct PartialProjectOptions { pub dev: Option, /// The server actions encryption key. - pub encryption_key: Option, + pub encryption_key: Option, /// The build id. - pub build_id: Option, + pub build_id: Option, /// Options for draft mode. pub preview_props: Option, @@ -157,9 +157,9 @@ pub struct PartialProjectOptions { #[derive(Debug, Serialize, Deserialize, Clone, TaskInput, PartialEq, Eq, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct DefineEnv { - pub client: Vec<(String, String)>, - pub edge: Vec<(String, String)>, - pub nodejs: Vec<(String, String)>, + pub client: Vec<(RcStr, RcStr)>, + pub edge: Vec<(RcStr, RcStr)>, + pub nodejs: Vec<(RcStr, RcStr)>, } #[derive(Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, ValueDebugFormat)] @@ -288,7 +288,7 @@ impl ProjectContainer { .await? .dist_dir .as_ref() - .map_or_else(|| ".next".to_string(), |d| d.to_string()); + .map_or_else(|| ".next".into(), |d| d.clone()); Ok(Project { root_path, @@ -301,7 +301,7 @@ impl ProjectContainer { define_env, browserslist_query: "last 1 Chrome versions, last 1 Firefox versions, last 1 Safari \ versions, last 1 Edge versions" - .to_string(), + .into(), mode: if dev { NextMode::Development.cell() } else { @@ -323,7 +323,7 @@ impl ProjectContainer { /// See [Project::hmr_identifiers]. #[turbo_tasks::function] - pub fn hmr_identifiers(self: Vc) -> Vc> { + pub fn hmr_identifiers(self: Vc) -> Vc> { self.project().hmr_identifiers() } @@ -340,7 +340,7 @@ impl ProjectContainer { pub async fn get_source_map( self: Vc, file_path: Vc, - section: Option, + section: Option, ) -> Result> { let this = self.await?; Ok(this @@ -353,13 +353,13 @@ impl ProjectContainer { pub struct Project { /// A root path from which all files must be nested under. Trying to access /// a file outside this root will fail. Think of this as a chroot. - root_path: String, + root_path: RcStr, /// A path where to emit the build outputs. next.config.js's distDir. - dist_dir: String, + dist_dir: RcStr, /// A path inside the root_path which contains the app/pages directories. - pub project_path: String, + pub project_path: RcStr, /// Whether to watch the filesystem for file changes. watch: bool, @@ -377,15 +377,15 @@ pub struct Project { /// time. define_env: Vc, - browserslist_query: String, + browserslist_query: RcStr, mode: Vc, versioned_content_map: Vc, - build_id: String, + build_id: RcStr, - encryption_key: String, + encryption_key: RcStr, preview_props: DraftModeOptions, } @@ -471,8 +471,8 @@ impl Project { async fn project_fs(self: Vc) -> Result>> { let this = self.await?; let disk_fs = DiskFileSystem::new( - PROJECT_FILESYSTEM_NAME.to_string(), - this.root_path.to_string(), + PROJECT_FILESYSTEM_NAME.into(), + this.root_path.clone(), vec![], ); if this.watch { @@ -490,19 +490,19 @@ impl Project { #[turbo_tasks::function] pub async fn output_fs(self: Vc) -> Result>> { let this = self.await?; - let disk_fs = DiskFileSystem::new("output".to_string(), this.project_path.clone(), vec![]); + let disk_fs = DiskFileSystem::new("output".into(), this.project_path.clone(), vec![]); Ok(Vc::upcast(disk_fs)) } #[turbo_tasks::function] - pub async fn dist_dir(self: Vc) -> Result> { - Ok(Vc::cell(self.await?.dist_dir.to_string())) + pub async fn dist_dir(self: Vc) -> Result> { + Ok(Vc::cell(self.await?.dist_dir.clone())) } #[turbo_tasks::function] pub async fn node_root(self: Vc) -> Result> { let this = self.await?; - Ok(self.output_fs().root().join(this.dist_dir.to_string())) + Ok(self.output_fs().root().join(this.dist_dir.clone())) } #[turbo_tasks::function] @@ -518,25 +518,25 @@ impl Project { #[turbo_tasks::function] pub async fn client_relative_path(self: Vc) -> Result> { let next_config = self.next_config().await?; - Ok(self.client_root().join(format!( - "{}/_next", - next_config - .base_path - .clone() - .unwrap_or_else(|| "".to_string()), - ))) + Ok(self.client_root().join( + format!( + "{}/_next", + next_config.base_path.clone().unwrap_or_else(|| "".into()), + ) + .into(), + )) } #[turbo_tasks::function] pub async fn project_path(self: Vc) -> Result> { let this = self.await?; let root = self.project_root_path(); - let project_relative = this.project_path.strip_prefix(&this.root_path).unwrap(); + let project_relative = this.project_path.strip_prefix(&*this.root_path).unwrap(); let project_relative = project_relative .strip_prefix(MAIN_SEPARATOR) .unwrap_or(project_relative) .replace(MAIN_SEPARATOR, "/"); - Ok(root.join(project_relative)) + Ok(root.join(project_relative.into())) } #[turbo_tasks::function] @@ -569,8 +569,8 @@ impl Project { self.project_path(), node_root, node_root, - node_root.join("chunks".to_string()), - node_root.join("assets".to_string()), + node_root.join("chunks".into()), + node_root.join("assets".into()), node_build_environment(), next_mode.runtime_type(), ) @@ -613,11 +613,11 @@ impl Project { #[turbo_tasks::function] pub(super) fn edge_env(&self) -> Vc { let edge_env = indexmap! { - "__NEXT_BUILD_ID".to_string() => self.build_id.clone(), - "NEXT_SERVER_ACTIONS_ENCRYPTION_KEY".to_string() => self.encryption_key.clone(), - "__NEXT_PREVIEW_MODE_ID".to_string() => self.preview_props.preview_mode_id.clone(), - "__NEXT_PREVIEW_MODE_ENCRYPTION_KEY".to_string() => self.preview_props.preview_mode_encryption_key.clone(), - "__NEXT_PREVIEW_MODE_SIGNING_KEY".to_string() => self.preview_props.preview_mode_signing_key.clone(), + "__NEXT_BUILD_ID".into() => self.build_id.clone(), + "NEXT_SERVER_ACTIONS_ENCRYPTION_KEY".into() => self.encryption_key.clone(), + "__NEXT_PREVIEW_MODE_ID".into() => self.preview_props.preview_mode_id.clone(), + "__NEXT_PREVIEW_MODE_ENCRYPTION_KEY".into() => self.preview_props.preview_mode_encryption_key.clone(), + "__NEXT_PREVIEW_MODE_SIGNING_KEY".into() => self.preview_props.preview_mode_signing_key.clone(), }; Vc::cell(edge_env) } @@ -688,7 +688,7 @@ impl Project { #[turbo_tasks::function] async fn collect_project_feature_telemetry(self: Vc) -> Result> { let emit_event = |feature_name: &str, enabled: bool| { - NextFeatureTelemetry::new(feature_name.to_string(), enabled) + NextFeatureTelemetry::new(feature_name.into(), enabled) .cell() .emit(); }; @@ -787,14 +787,14 @@ impl Project { path: self.project_path(), title: StyledString::Text( format!("App Router and Pages Router both match path: {}", pathname) - .to_string(), + .into(), ) .cell(), description: StyledString::Text( "Next.js does not support having both App Router and Pages Router \ routes matching the same path. Please remove one of the conflicting \ routes." - .to_string(), + .into(), ) .cell(), severity: IssueSeverity::Error.cell(), @@ -896,7 +896,7 @@ impl Project { self.next_config(), self.execution_context(), ), - Vc::cell("middleware".to_string()), + Vc::cell("middleware".into()), )) } @@ -930,7 +930,7 @@ impl Project { self.next_config(), self.execution_context(), ), - Vc::cell("instrumentation".to_string()), + Vc::cell("instrumentation".into()), )) } @@ -980,7 +980,7 @@ impl Project { #[turbo_tasks::function] async fn hmr_content( self: Vc, - identifier: String, + identifier: RcStr, ) -> Result>> { Ok(self .await? @@ -989,7 +989,7 @@ impl Project { } #[turbo_tasks::function] - async fn hmr_version(self: Vc, identifier: String) -> Result>> { + async fn hmr_version(self: Vc, identifier: RcStr) -> Result>> { let content = self.hmr_content(identifier); Ok(content.version()) @@ -1000,7 +1000,7 @@ impl Project { #[turbo_tasks::function] pub async fn hmr_version_state( self: Vc, - identifier: String, + identifier: RcStr, session: TransientInstance<()>, ) -> Result> { let version = self.hmr_version(identifier); @@ -1020,7 +1020,7 @@ impl Project { #[turbo_tasks::function] pub async fn hmr_update( self: Vc, - identifier: String, + identifier: RcStr, from: Vc, ) -> Result> { let from = from.get(); @@ -1030,7 +1030,7 @@ impl Project { /// Gets a list of all HMR identifiers that can be subscribed to. This is /// only needed for testing purposes and isn't used in real apps. #[turbo_tasks::function] - pub async fn hmr_identifiers(self: Vc) -> Result>> { + pub async fn hmr_identifiers(self: Vc) -> Result>> { Ok(self .await? .versioned_content_map diff --git a/packages/next-swc/crates/next-api/src/route.rs b/packages/next-swc/crates/next-api/src/route.rs index 9d7547a785c69..9736f507adc92 100644 --- a/packages/next-swc/crates/next-api/src/route.rs +++ b/packages/next-swc/crates/next-api/src/route.rs @@ -1,7 +1,7 @@ use anyhow::Result; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; -use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Vc}; +use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, Completion, RcStr, Vc}; use crate::paths::ServerPath; @@ -84,15 +84,15 @@ pub enum WrittenEndpoint { /// Relative to the root_path server_entry_path: String, server_paths: Vec, - client_paths: Vec, + client_paths: Vec, }, Edge { server_paths: Vec, - client_paths: Vec, + client_paths: Vec, }, } /// The routes as map from pathname to route. (pathname includes the leading /// slash) #[turbo_tasks::value(transparent)] -pub struct Routes(IndexMap); +pub struct Routes(IndexMap); diff --git a/packages/next-swc/crates/next-api/src/server_actions.rs b/packages/next-swc/crates/next-api/src/server_actions.rs index 63770bfc178f5..172c62fc7e71c 100644 --- a/packages/next-swc/crates/next-api/src/server_actions.rs +++ b/packages/next-swc/crates/next-api/src/server_actions.rs @@ -9,7 +9,7 @@ use next_core::{ use tracing::Instrument; use turbo_tasks::{ graph::{GraphTraversal, NonDeterministic}, - TryFlatJoinIterExt, Value, ValueToString, Vc, + RcStr, TryFlatJoinIterExt, Value, ValueToString, Vc, }; use turbopack_binding::{ swc::core::{common::comments::Comments, ecma::ast::Program}, @@ -54,7 +54,7 @@ pub(crate) async fn create_server_actions_manifest( ) -> Result<(Vc>, Vc>)> { let actions = get_actions(rsc_entry, server_reference_modules, asset_context); let loader = - build_server_actions_loader(project_path, page_name.to_string(), actions, asset_context); + build_server_actions_loader(project_path, page_name.into(), actions, asset_context); let evaluable = Vc::try_resolve_sidecast::>(loader) .await? .context("loader module must be evaluatable")?; @@ -76,7 +76,7 @@ pub(crate) async fn create_server_actions_manifest( #[turbo_tasks::function] async fn build_server_actions_loader( project_path: Vc, - page_name: String, + page_name: RcStr, actions: Vc, asset_context: Vc>, ) -> Result>> { @@ -92,7 +92,7 @@ async fn build_server_actions_loader( let index = import_map.len(); let module_name = import_map .entry(*module) - .or_insert_with(|| format!("ACTIONS_MODULE{index}")); + .or_insert_with(|| format!("ACTIONS_MODULE{index}").into()); writeln!( contents, " '{hash_id}': (...args) => Promise.resolve(require('{module_name}')).then(mod => \ @@ -101,7 +101,8 @@ async fn build_server_actions_loader( } write!(contents, "}});")?; - let output_path = project_path.join(format!(".next-internal/server/app{page_name}/actions.js")); + let output_path = + project_path.join(format!(".next-internal/server/app{page_name}/actions.js").into()); let file = File::from(contents.build()); let source = VirtualSource::new(output_path, AssetContent::file(file.into())); let import_map = import_map.into_iter().map(|(k, v)| (v, k)).collect(); @@ -128,12 +129,11 @@ async fn build_manifest( page_name: &str, runtime: NextRuntime, actions: Vc, - loader_id: Vc, + loader_id: Vc, ) -> Result>> { let manifest_path_prefix = page_name; - let manifest_path = node_root.join(format!( - "server/app{manifest_path_prefix}/server-reference-manifest.json", - )); + let manifest_path = node_root + .join(format!("server/app{manifest_path_prefix}/server-reference-manifest.json",).into()); let mut manifest = ServerReferenceManifest { ..Default::default() }; @@ -163,8 +163,8 @@ async fn build_manifest( } #[turbo_tasks::function] -fn action_modifier() -> Vc { - Vc::cell("action".to_string()) +fn action_modifier() -> Vc { + Vc::cell("action".into()) } /// Traverses the entire module graph starting from [Module], looking for magic diff --git a/packages/next-swc/crates/next-api/src/versioned_content_map.rs b/packages/next-swc/crates/next-api/src/versioned_content_map.rs index 357f2969fa1fc..50217681120bf 100644 --- a/packages/next-swc/crates/next-api/src/versioned_content_map.rs +++ b/packages/next-swc/crates/next-api/src/versioned_content_map.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Result}; use next_core::emit_client_assets; use serde::{Deserialize, Serialize}; use turbo_tasks::{ - debug::ValueDebugFormat, trace::TraceRawVcs, Completion, State, TryFlatJoinIterExt, + debug::ValueDebugFormat, trace::TraceRawVcs, Completion, RcStr, State, TryFlatJoinIterExt, TryJoinIterExt, ValueDefault, ValueToString, Vc, }; use turbopack_binding::{ @@ -124,7 +124,7 @@ impl VersionedContentMap { pub async fn get_source_map( self: Vc, path: Vc, - section: Option, + section: Option, ) -> Result> { if let Some(generate_source_map) = Vc::try_resolve_sidecast::>(self.get_asset(path)).await? @@ -169,7 +169,7 @@ impl VersionedContentMap { } #[turbo_tasks::function] - pub async fn keys_in_path(&self, root: Vc) -> Result>> { + pub async fn keys_in_path(&self, root: Vc) -> Result>> { let keys = { let map = self.map_path_to_op.get(); map.keys().copied().collect::>() @@ -177,7 +177,7 @@ impl VersionedContentMap { let root = &root.await?; let keys = keys .into_iter() - .map(|path| async move { Ok(root.get_path_to(&*path.await?).map(|p| p.to_string())) }) + .map(|path| async move { Ok(root.get_path_to(&*path.await?).map(RcStr::from)) }) .try_flat_join() .await?; Ok(Vc::cell(keys)) diff --git a/packages/next-swc/crates/next-core/src/app_segment_config.rs b/packages/next-swc/crates/next-core/src/app_segment_config.rs index cbed6876317f1..a4a76ede1533b 100644 --- a/packages/next-swc/crates/next-core/src/app_segment_config.rs +++ b/packages/next-swc/crates/next-core/src/app_segment_config.rs @@ -3,7 +3,7 @@ use std::ops::Deref; use anyhow::{bail, Result}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use turbo_tasks::{trace::TraceRawVcs, TryJoinIterExt, ValueDefault, Vc}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, TryJoinIterExt, ValueDefault, Vc}; use turbo_tasks_fs::FileSystemPath; use turbopack_binding::{ swc::core::{ @@ -71,7 +71,8 @@ pub struct NextSegmentConfig { pub revalidate: Option, pub fetch_cache: Option, pub runtime: Option, - pub preferred_region: Option>, + pub preferred_region: Option>, + pub experimental_ppr: Option, } #[turbo_tasks::value_impl] @@ -93,6 +94,7 @@ impl NextSegmentConfig { fetch_cache, runtime, preferred_region, + experimental_ppr, } = self; *dynamic = dynamic.or(parent.dynamic); *dynamic_params = dynamic_params.or(parent.dynamic_params); @@ -100,6 +102,7 @@ impl NextSegmentConfig { *fetch_cache = fetch_cache.or(parent.fetch_cache); *runtime = runtime.or(parent.runtime); *preferred_region = preferred_region.take().or(parent.preferred_region.clone()); + *experimental_ppr = experimental_ppr.or(parent.experimental_ppr); } /// Applies a config from a paralllel route to this config, returning an @@ -133,6 +136,7 @@ impl NextSegmentConfig { fetch_cache, runtime, preferred_region, + experimental_ppr, } = self; merge_parallel(dynamic, ¶llel_config.dynamic, "dynamic")?; merge_parallel( @@ -148,6 +152,11 @@ impl NextSegmentConfig { ¶llel_config.preferred_region, "referredRegion", )?; + merge_parallel( + experimental_ppr, + ¶llel_config.experimental_ppr, + "experimental_ppr", + )?; Ok(()) } } @@ -169,7 +178,7 @@ impl Issue for NextSegmentConfigParsingIssue { #[turbo_tasks::function] fn title(&self) -> Vc { - StyledString::Text("Unable to parse config export in source file".to_string()).cell() + StyledString::Text("Unable to parse config export in source file".into()).cell() } #[turbo_tasks::function] @@ -188,7 +197,7 @@ impl Issue for NextSegmentConfigParsingIssue { StyledString::Text( "The exported configuration object in a source file need to have a very specific \ format from which some properties can be statically parsed at compiled-time." - .to_string(), + .into(), ) .cell(), )) @@ -200,10 +209,10 @@ impl Issue for NextSegmentConfigParsingIssue { } #[turbo_tasks::function] - fn documentation_link(&self) -> Vc { + fn documentation_link(&self) -> Vc { Vc::cell( "https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config" - .to_string(), + .into(), ) } @@ -303,7 +312,7 @@ fn parse_config_value( let (explainer, hints) = value.explain(2, 0); NextSegmentConfigParsingIssue { ident: source.ident(), - detail: StyledString::Text(format!("{detail} Got {explainer}.{hints}")).cell(), + detail: StyledString::Text(format!("{detail} Got {explainer}.{hints}").into()).cell(), source: issue_source(source, span), } .cell() @@ -393,14 +402,14 @@ fn parse_config_value( let preferred_region = match value { // Single value is turned into a single-element Vec. - JsValue::Constant(ConstantValue::Str(str)) => vec![str.to_string()], + JsValue::Constant(ConstantValue::Str(str)) => vec![str.to_string().into()], // Array of strings is turned into a Vec. If one of the values in not a String it // will error. JsValue::Array { items, .. } => { let mut regions = Vec::new(); for item in items { if let JsValue::Constant(ConstantValue::Str(str)) = item { - regions.push(str.to_string()); + regions.push(str.to_string().into()); } else { invalid_config( "Values of the `preferredRegion` array need to static strings", @@ -422,6 +431,15 @@ fn parse_config_value( config.preferred_region = Some(preferred_region); } + "experimental_ppr" => { + let value = eval_context.eval(init); + let Some(val) = value.as_bool() else { + invalid_config("`experimental_ppr` needs to be a static boolean", &value); + return; + }; + + config.experimental_ppr = Some(val); + } _ => {} } } diff --git a/packages/next-swc/crates/next-core/src/app_structure.rs b/packages/next-swc/crates/next-core/src/app_structure.rs index 05c03994451c3..59836f3d79cae 100644 --- a/packages/next-swc/crates/next-core/src/app_structure.rs +++ b/packages/next-swc/crates/next-core/src/app_structure.rs @@ -11,7 +11,7 @@ use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use tracing::Instrument; use turbo_tasks::{ - debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Completions, TaskInput, + debug::ValueDebugFormat, trace::TraceRawVcs, Completion, Completions, RcStr, TaskInput, TryJoinIterExt, ValueToString, Vc, }; use turbopack_binding::{ @@ -104,11 +104,11 @@ pub enum MetadataItem { } #[turbo_tasks::function] -pub async fn get_metadata_route_name(meta: MetadataItem) -> Result> { +pub async fn get_metadata_route_name(meta: MetadataItem) -> Result> { Ok(match meta { MetadataItem::Static { path } => { let path_value = path.await?; - Vc::cell(path_value.file_name().to_string()) + Vc::cell(path_value.file_name().into()) } MetadataItem::Dynamic { path } => { let Some(stem) = &*path.file_stem().await? else { @@ -119,7 +119,7 @@ pub async fn get_metadata_route_name(meta: MetadataItem) -> Result> { }; match stem.as_str() { - "manifest" => Vc::cell("manifest.webmanifest".to_string()), + "manifest" => Vc::cell("manifest.webmanifest".into()), _ => Vc::cell(stem.clone()), } } @@ -213,7 +213,7 @@ impl GlobalMetadata { #[derive(Debug)] pub struct DirectoryTree { /// key is e.g. "dashboard", "(dashboard)", "@slot" - pub subdirectories: BTreeMap>, + pub subdirectories: BTreeMap>, pub components: Vc, } @@ -259,8 +259,8 @@ impl OptionAppDir { /// Finds and returns the [DirectoryTree] of the app directory if existing. #[turbo_tasks::function] pub async fn find_app_dir(project_path: Vc) -> Result> { - let app = project_path.join("app".to_string()); - let src_app = project_path.join("src/app".to_string()); + let app = project_path.join("app".into()); + let src_app = project_path.join("src/app".into()); let app_dir = if *app.get_type().await? == FileSystemEntryType::Directory { app } else if *src_app.get_type().await? == FileSystemEntryType::Directory { @@ -284,11 +284,11 @@ pub async fn find_app_dir_if_enabled(project_path: Vc) -> Result #[turbo_tasks::function] async fn get_directory_tree( dir: Vc, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Result> { let span = { - let dir = dir.to_string().await?; - tracing::info_span!("read app directory tree", name = *dir) + let dir = dir.to_string().await?.to_string(); + tracing::info_span!("read app directory tree", name = dir) }; get_directory_tree_internal(dir, page_extensions) .instrument(span) @@ -297,7 +297,7 @@ async fn get_directory_tree( async fn get_directory_tree_internal( dir: Vc, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Result> { let DirectoryContent::Entries(entries) = &*dir.read_dir().await? else { // the file watcher might invalidate things in the wrong order, @@ -375,7 +375,7 @@ async fn get_directory_tree_internal( let basename = file_name .rsplit_once('.') .map_or(file_name, |(basename, _)| basename); - let alt_path = file.parent().join(format!("{}.alt.txt", basename)); + let alt_path = file.parent().join(format!("{}.alt.txt", basename).into()); let alt_path = matches!(&*alt_path.get_type().await?, FileSystemEntryType::File) .then_some(alt_path); @@ -392,7 +392,7 @@ async fn get_directory_tree_internal( // appDir ignores paths starting with an underscore if !basename.starts_with('_') { let result = get_directory_tree(dir, page_extensions); - subdirectories.insert(basename.to_string(), result); + subdirectories.insert(basename.clone(), result); } } // TODO(WEB-952) handle symlinks in app dir @@ -421,8 +421,8 @@ async fn get_directory_tree_internal( #[derive(Debug, Clone)] pub struct LoaderTree { pub page: AppPage, - pub segment: String, - pub parallel_routes: IndexMap>, + pub segment: RcStr, + pub parallel_routes: IndexMap>, pub components: Vc, pub global_metadata: Vc, } @@ -432,7 +432,7 @@ impl LoaderTree { /// Returns true if there's a page match in this loader tree. #[turbo_tasks::function] pub async fn has_page(&self) -> Result> { - if self.segment == "__PAGE__" { + if &*self.segment == "__PAGE__" { return Ok(Vc::cell(true)); } @@ -449,7 +449,7 @@ impl LoaderTree { /// route. #[turbo_tasks::function] pub async fn has_only_catchall(&self) -> Result> { - if self.segment == "__PAGE__" && !self.page.is_catchall() { + if &*self.segment == "__PAGE__" && !self.page.is_catchall() { return Ok(Vc::cell(false)); } @@ -527,11 +527,14 @@ fn conflict_issue( DirectoryTreeIssue { app_dir, - message: StyledString::Text(format!( - "Conflicting {} at {}: {a} at {value_a} and {b} at {value_b}", - item_names, - e.key(), - )) + message: StyledString::Text( + format!( + "Conflicting {} at {}: {a} at {value_a} and {b} at {value_b}", + item_names, + e.key(), + ) + .into(), + ) .cell(), severity: IssueSeverity::Error.cell(), } @@ -684,7 +687,7 @@ fn add_app_metadata_route( #[turbo_tasks::function] pub fn get_entrypoints( app_dir: Vc, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Vc { directory_tree_to_entrypoints( app_dir, @@ -704,7 +707,7 @@ fn directory_tree_to_entrypoints( directory_tree_to_entrypoints_internal( app_dir, global_metadata, - "".to_string(), + "".into(), directory_tree, AppPage::new(), root_layouts, @@ -722,7 +725,7 @@ impl Issue for DuplicateParallelRouteIssue { #[turbo_tasks::function] async fn file_path(self: Vc) -> Result> { let this = self.await?; - Ok(this.app_dir.join(this.page.to_string())) + Ok(this.app_dir.join(this.page.to_string().into())) } #[turbo_tasks::function] @@ -733,7 +736,7 @@ impl Issue for DuplicateParallelRouteIssue { #[turbo_tasks::function] fn title(self: Vc) -> Vc { StyledString::Text( - "You cannot have two parallel pages that resolve to the same path.".to_string(), + "You cannot have two parallel pages that resolve to the same path.".into(), ) .cell() } @@ -795,7 +798,7 @@ async fn check_duplicate( async fn directory_tree_to_loader_tree( app_dir: Vc, global_metadata: Vc, - directory_name: String, + directory_name: RcStr, directory_tree: Vc, app_page: AppPage, // the page this loader tree is constructed for @@ -828,7 +831,7 @@ async fn directory_tree_to_loader_tree( if (is_root_directory || is_root_layout) && components.not_found.is_none() { components.not_found = Some( - get_next_package(app_dir).join("dist/client/components/not-found-error.js".to_string()), + get_next_package(app_dir).join("dist/client/components/not-found-error.js".into()), ); } @@ -843,7 +846,7 @@ async fn directory_tree_to_loader_tree( let current_level_is_parallel_route = is_parallel_route(&directory_name); if current_level_is_parallel_route { - tree.segment = "children".to_string(); + tree.segment = "children".into(); } if let Some(page) = (app_path == for_app_path || app_path.is_catchall()) @@ -862,10 +865,10 @@ async fn directory_tree_to_loader_tree( }; tree.parallel_routes.insert( - "children".to_string(), + "children".into(), LoaderTree { page: app_page.clone(), - segment: "__PAGE__".to_string(), + segment: "__PAGE__".into(), parallel_routes: IndexMap::new(), components: Components { page: Some(page), @@ -879,7 +882,7 @@ async fn directory_tree_to_loader_tree( ); if current_level_is_parallel_route { - tree.segment = "page$".to_string(); + tree.segment = "page$".into(); } } @@ -915,7 +918,7 @@ async fn directory_tree_to_loader_tree( if let Some(subtree) = subtree { if let Some(key) = parallel_route_key { - tree.parallel_routes.insert(key.to_string(), subtree); + tree.parallel_routes.insert(key.into(), subtree); continue; } @@ -933,7 +936,7 @@ async fn directory_tree_to_loader_tree( // there's probably already a more specific page in the // slot. } else if *current_tree.has_only_catchall().await? { - tree.parallel_routes.insert("children".to_string(), subtree); + tree.parallel_routes.insert("children".into(), subtree); } else { // TODO: Investigate if this is still needed. Emitting the // error causes the test "should @@ -955,7 +958,7 @@ async fn directory_tree_to_loader_tree( // .emit(); } } else { - tree.parallel_routes.insert("children".to_string(), subtree); + tree.parallel_routes.insert("children".into(), subtree); } } else if let Some(key) = parallel_route_key { bail!( @@ -967,7 +970,7 @@ async fn directory_tree_to_loader_tree( } if tree.parallel_routes.is_empty() { - tree.segment = "__DEFAULT__".to_string(); + tree.segment = "__DEFAULT__".into(); if let Some(default) = components.default { tree.components = Components { default: Some(default), @@ -979,7 +982,7 @@ async fn directory_tree_to_loader_tree( tree.components = Components { default: Some( get_next_package(app_dir) - .join("dist/client/components/parallel-route-default.js".to_string()), + .join("dist/client/components/parallel-route-default.js".into()), ), ..Default::default() } @@ -989,10 +992,10 @@ async fn directory_tree_to_loader_tree( } } else if tree.parallel_routes.get("children").is_none() { tree.parallel_routes.insert( - "children".to_string(), + "children".into(), LoaderTree { page: app_page.clone(), - segment: "__DEFAULT__".to_string(), + segment: "__DEFAULT__".into(), parallel_routes: IndexMap::new(), components: if let Some(default) = components.default { Components { @@ -1004,9 +1007,8 @@ async fn directory_tree_to_loader_tree( // default fallback component Components { default: Some( - get_next_package(app_dir).join( - "dist/client/components/parallel-route-default.js".to_string(), - ), + get_next_package(app_dir) + .join("dist/client/components/parallel-route-default.js".into()), ), ..Default::default() } @@ -1033,7 +1035,7 @@ async fn directory_tree_to_loader_tree( async fn directory_tree_to_entrypoints_internal( app_dir: Vc, global_metadata: Vc, - directory_name: String, + directory_name: RcStr, directory_tree: Vc, app_page: AppPage, root_layouts: Vc>>, @@ -1054,7 +1056,7 @@ async fn directory_tree_to_entrypoints_internal( async fn directory_tree_to_entrypoints_internal_untraced( app_dir: Vc, global_metadata: Vc, - directory_name: String, + directory_name: RcStr, directory_tree: Vc, app_page: AppPage, root_layouts: Vc>>, @@ -1161,16 +1163,16 @@ async fn directory_tree_to_entrypoints_internal_untraced( page: app_page.clone(), segment: directory_name.clone(), parallel_routes: indexmap! { - "children".to_string() => LoaderTree { + "children".into() => LoaderTree { page: app_page.clone(), - segment: "/_not-found".to_string(), + segment: "/_not-found".into(), parallel_routes: indexmap! { - "children".to_string() => LoaderTree { + "children".into() => LoaderTree { page: app_page.clone(), - segment: "__PAGE__".to_string(), + segment: "__PAGE__".into(), parallel_routes: IndexMap::new(), components: Components { - page: components.not_found.or_else(|| Some(get_next_package(app_dir).join("dist/client/components/not-found-error.js".to_string()))), + page: components.not_found.or_else(|| Some(get_next_package(app_dir).join("dist/client/components/not-found-error.js".into()))), ..Default::default() }.cell(), global_metadata @@ -1211,7 +1213,7 @@ async fn directory_tree_to_entrypoints_internal_untraced( let map = directory_tree_to_entrypoints_internal( app_dir, global_metadata, - subdir_name.to_string(), + subdir_name.clone(), subdirectory, child_app_page.clone(), root_layouts, @@ -1294,7 +1296,7 @@ async fn directory_tree_to_entrypoints_internal_untraced( #[turbo_tasks::function] pub async fn get_global_metadata( app_dir: Vc, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Result> { let DirectoryContent::Entries(entries) = &*app_dir.read_dir().await? else { bail!("app_dir must be a directory") @@ -1348,10 +1350,7 @@ impl Issue for DirectoryTreeIssue { #[turbo_tasks::function] async fn title(&self) -> Result> { - Ok( - StyledString::Text("An issue occurred while preparing your Next.js app".to_string()) - .cell(), - ) + Ok(StyledString::Text("An issue occurred while preparing your Next.js app".into()).cell()) } #[turbo_tasks::function] diff --git a/packages/next-swc/crates/next-core/src/bootstrap.rs b/packages/next-swc/crates/next-core/src/bootstrap.rs index d5645e2829699..b833dad6f1b48 100644 --- a/packages/next-swc/crates/next-core/src/bootstrap.rs +++ b/packages/next-swc/crates/next-core/src/bootstrap.rs @@ -80,7 +80,7 @@ pub async fn bootstrap( let config_asset = context .process( Vc::upcast(VirtualSource::new( - asset.ident().path().join("bootstrap-config.ts".to_string()), + asset.ident().path().join("bootstrap-config.ts".into()), AssetContent::file( File::from( config @@ -97,8 +97,8 @@ pub async fn bootstrap( .module(); let mut inner_assets = inner_assets.await?.clone_value(); - inner_assets.insert("ENTRY".to_string(), asset); - inner_assets.insert("BOOTSTRAP_CONFIG".to_string(), config_asset); + inner_assets.insert("ENTRY".into(), asset); + inner_assets.insert("BOOTSTRAP_CONFIG".into(), config_asset); let asset = context .process( diff --git a/packages/next-swc/crates/next-core/src/embed_js.rs b/packages/next-swc/crates/next-core/src/embed_js.rs index 11ecee4fd9702..5dcebdb90bfb3 100644 --- a/packages/next-swc/crates/next-core/src/embed_js.rs +++ b/packages/next-swc/crates/next-core/src/embed_js.rs @@ -1,4 +1,4 @@ -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::{ turbo::tasks_fs::{FileContent, FileSystem, FileSystemPath}, turbopack::core::{file_source::FileSource, source::Source}, @@ -13,16 +13,16 @@ pub(crate) fn next_js_fs() -> Vc> { } #[turbo_tasks::function] -pub(crate) fn next_js_file(path: String) -> Vc { +pub(crate) fn next_js_file(path: RcStr) -> Vc { next_js_fs().root().join(path).read() } #[turbo_tasks::function] -pub(crate) fn next_js_file_path(path: String) -> Vc { +pub(crate) fn next_js_file_path(path: RcStr) -> Vc { next_js_fs().root().join(path) } #[turbo_tasks::function] -pub(crate) fn next_asset(path: String) -> Vc> { +pub(crate) fn next_asset(path: RcStr) -> Vc> { Vc::upcast(FileSource::new(next_js_file_path(path))) } diff --git a/packages/next-swc/crates/next-core/src/instrumentation.rs b/packages/next-swc/crates/next-core/src/instrumentation.rs index 21df0efcec2e3..be5d31570745c 100644 --- a/packages/next-swc/crates/next-core/src/instrumentation.rs +++ b/packages/next-swc/crates/next-core/src/instrumentation.rs @@ -1,8 +1,8 @@ use anyhow::Result; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; #[turbo_tasks::function] -pub async fn instrumentation_files(page_extensions: Vc>) -> Result>> { +pub async fn instrumentation_files(page_extensions: Vc>) -> Result>> { let extensions = page_extensions.await?; let files = ["instrumentation.", "src/instrumentation."] .into_iter() @@ -10,6 +10,7 @@ pub async fn instrumentation_files(page_extensions: Vc>) -> Result>>, + inner_assets: IndexMap>>, counter: usize, - imports: Vec, + imports: Vec, loader_tree_code: String, context: Vc, server_component_transition: Vc>, pages: Vec>, /// next.config.js' basePath option to construct og metadata. - base_path: Option, + base_path: Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -73,7 +73,7 @@ impl LoaderTreeBuilder { fn new( context: Vc, server_component_transition: Vc>, - base_path: Option, + base_path: Option, ) -> Self { LoaderTreeBuilder { inner_assets: IndexMap::new(), @@ -123,15 +123,19 @@ impl LoaderTreeBuilder { path = StringifyJs(&module.ident().path().to_string().await?) )?; - self.imports.push(formatdoc!( - r#" + self.imports.push( + formatdoc!( + r#" import {} from "COMPONENT_{}"; "#, - identifier, - i - )); + identifier, + i + ) + .into(), + ); - self.inner_assets.insert(format!("COMPONENT_{i}"), module); + self.inner_assets + .insert(format!("COMPONENT_{i}").into(), module); } Ok(()) } @@ -240,12 +244,12 @@ impl LoaderTreeBuilder { let inner_module_id = format!("METADATA_{i}"); self.imports - .push(format!("import {identifier} from \"{inner_module_id}\";")); + .push(format!("import {identifier} from \"{inner_module_id}\";").into()); let source = dynamic_image_metadata_source( Vc::upcast(self.context), *path, - name.to_string(), + name.into(), app_page.clone(), ); @@ -258,7 +262,7 @@ impl LoaderTreeBuilder { )), ) .module(); - self.inner_assets.insert(inner_module_id, module); + self.inner_assets.insert(inner_module_id.into(), module); let s = " "; writeln!(self.loader_tree_code, "{s}{identifier},")?; @@ -279,18 +283,18 @@ impl LoaderTreeBuilder { let identifier = magic_identifier::mangle(&format!("{name} #{i}")); let inner_module_id = format!("METADATA_{i}"); - let helper_import = "import { fillMetadataSegment } from \ - \"next/dist/lib/metadata/get-metadata-route\"" - .to_string(); + let helper_import: RcStr = "import { fillMetadataSegment } from \ + \"next/dist/lib/metadata/get-metadata-route\"" + .into(); if !self.imports.contains(&helper_import) { self.imports.push(helper_import); } self.imports - .push(format!("import {identifier} from \"{inner_module_id}\";")); + .push(format!("import {identifier} from \"{inner_module_id}\";").into()); self.inner_assets.insert( - inner_module_id, + inner_module_id.into(), Vc::upcast(StructuredImageModuleType::create_module( Vc::upcast(FileSource::new(path)), BlurPlaceholderMode::None, @@ -332,7 +336,7 @@ impl LoaderTreeBuilder { let identifier = magic_identifier::mangle(&format!("{name} alt text #{i}")); let inner_module_id = format!("METADATA_ALT_{i}"); self.imports - .push(format!("import {identifier} from \"{inner_module_id}\";")); + .push(format!("import {identifier} from \"{inner_module_id}\";").into()); let module = self .context .process( @@ -342,7 +346,7 @@ impl LoaderTreeBuilder { Value::new(ReferenceType::Internal(InnerAssets::empty())), ) .module(); - self.inner_assets.insert(inner_module_id, module); + self.inner_assets.insert(inner_module_id.into(), module); writeln!(self.loader_tree_code, "{s} alt: {identifier},")?; } @@ -425,7 +429,7 @@ impl LoaderTreeBuilder { self.walk_tree(loader_tree, true).await?; Ok(LoaderTreeModule { imports: self.imports, - loader_tree_code: self.loader_tree_code, + loader_tree_code: self.loader_tree_code.into(), inner_assets: self.inner_assets, pages: self.pages, }) @@ -433,9 +437,9 @@ impl LoaderTreeBuilder { } pub struct LoaderTreeModule { - pub imports: Vec, - pub loader_tree_code: String, - pub inner_assets: IndexMap>>, + pub imports: Vec, + pub loader_tree_code: RcStr, + pub inner_assets: IndexMap>>, pub pages: Vec>, } @@ -444,7 +448,7 @@ impl LoaderTreeModule { loader_tree: Vc, context: Vc, server_component_transition: Vc>, - base_path: Option, + base_path: Option, ) -> Result { LoaderTreeBuilder::new(context, server_component_transition, base_path) .build(loader_tree) diff --git a/packages/next-swc/crates/next-core/src/middleware.rs b/packages/next-swc/crates/next-core/src/middleware.rs index 92ff48c07dfb8..ccdcb87f69383 100644 --- a/packages/next-swc/crates/next-core/src/middleware.rs +++ b/packages/next-swc/crates/next-core/src/middleware.rs @@ -1,6 +1,6 @@ use anyhow::Result; use indexmap::indexmap; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbo_tasks_fs::FileSystemPath; use turbopack_binding::turbopack::core::{ context::AssetContext, module::Module, reference_type::ReferenceType, @@ -9,7 +9,7 @@ use turbopack_binding::turbopack::core::{ use crate::util::load_next_js_template; #[turbo_tasks::function] -pub async fn middleware_files(page_extensions: Vc>) -> Result>> { +pub async fn middleware_files(page_extensions: Vc>) -> Result>> { let extensions = page_extensions.await?; let files = ["middleware.", "src/middleware."] .into_iter() @@ -17,6 +17,7 @@ pub async fn middleware_files(page_extensions: Vc>) -> Result INNER.to_string(), - "VAR_DEFINITION_PAGE" => "/middleware".to_string(), + "VAR_USERLAND" => INNER.into(), + "VAR_DEFINITION_PAGE" => "/middleware".into(), }, indexmap! {}, indexmap! {}, @@ -44,7 +45,7 @@ pub async fn get_middleware_module( .await?; let inner_assets = indexmap! { - INNER.to_string() => userland_module + INNER.into() => userland_module }; let module = context diff --git a/packages/next-swc/crates/next-core/src/next_app/app_client_references_chunks.rs b/packages/next-swc/crates/next-core/src/next_app/app_client_references_chunks.rs index 19f9f9762fa4b..abf1ee0235757 100644 --- a/packages/next-swc/crates/next-core/src/next_app/app_client_references_chunks.rs +++ b/packages/next-swc/crates/next-core/src/next_app/app_client_references_chunks.rs @@ -1,7 +1,7 @@ use anyhow::Result; use indexmap::IndexMap; use tracing::Instrument; -use turbo_tasks::{TryFlatJoinIterExt, TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks::{RcStr, TryFlatJoinIterExt, TryJoinIterExt, Value, ValueToString, Vc}; use turbopack_binding::turbopack::core::{ chunk::{availability_info::AvailabilityInfo, ChunkingContext, ChunkingContextExt}, module::Module, @@ -18,13 +18,13 @@ use crate::{ }; #[turbo_tasks::function] -fn client_modules_modifier() -> Vc { - Vc::cell("client modules".to_string()) +fn client_modules_modifier() -> Vc { + Vc::cell("client modules".into()) } #[turbo_tasks::function] -fn client_modules_ssr_modifier() -> Vc { - Vc::cell("client modules ssr".to_string()) +fn client_modules_ssr_modifier() -> Vc { + Vc::cell("client modules ssr".into()) } #[turbo_tasks::value] diff --git a/packages/next-swc/crates/next-core/src/next_app/app_entry.rs b/packages/next-swc/crates/next-core/src/next_app/app_entry.rs index 3f00106a12224..444717924fb4d 100644 --- a/packages/next-swc/crates/next-core/src/next_app/app_entry.rs +++ b/packages/next-swc/crates/next-core/src/next_app/app_entry.rs @@ -1,4 +1,4 @@ -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbopack::ecmascript::chunk::EcmascriptChunkPlaceable; use crate::app_segment_config::NextSegmentConfig; @@ -7,10 +7,10 @@ use crate::app_segment_config::NextSegmentConfig; #[turbo_tasks::value(shared)] pub struct AppEntry { /// The pathname of the route or page. - pub pathname: String, + pub pathname: RcStr, /// The original Next.js name of the route or page. This is used instead of /// the pathname to refer to this entry. - pub original_name: String, + pub original_name: RcStr, /// The RSC module asset for the route or page. pub rsc_entry: Vc>, /// The source code config for this entry. diff --git a/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs b/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs index 77f4a1b14857c..1305d4346ca58 100644 --- a/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs +++ b/packages/next-swc/crates/next-core/src/next_app/app_page_entry.rs @@ -2,7 +2,7 @@ use std::io::Write; use anyhow::{bail, Result}; use indexmap::indexmap; -use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc}; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, ValueToString, Vc}; use turbopack_binding::{ turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath}, turbopack::{ @@ -71,25 +71,25 @@ pub async fn get_app_page_entry( let pages = pages.iter().map(|page| page.to_string()).try_join().await?; - let original_name = page.to_string(); - let pathname = AppPath::from(page.clone()).to_string(); + let original_name: RcStr = page.to_string().into(); + let pathname: RcStr = AppPath::from(page.clone()).to_string().into(); // Load the file from the next.js codebase. let source = load_next_js_template( "app-page.js", project_root, indexmap! { - "VAR_DEFINITION_PAGE" => page.to_string(), + "VAR_DEFINITION_PAGE" => page.to_string().into(), "VAR_DEFINITION_PATHNAME" => pathname.clone(), "VAR_ORIGINAL_PATHNAME" => original_name.clone(), // TODO(alexkirsz) Support custom global error. - "VAR_MODULE_GLOBAL_ERROR" => "next/dist/client/components/error-boundary".to_string(), + "VAR_MODULE_GLOBAL_ERROR" => "next/dist/client/components/error-boundary".into(), }, indexmap! { "tree" => loader_tree_code, - "pages" => StringifyJs(&pages).to_string(), - "__next_app_require__" => "__turbopack_require__".to_string(), - "__next_app_load_chunk__" => " __turbopack_load__".to_string(), + "pages" => StringifyJs(&pages).to_string().into(), + "__next_app_require__" => "__turbopack_require__".into(), + "__next_app_load_chunk__" => " __turbopack_load__".into(), }, indexmap! {}, ) @@ -103,7 +103,9 @@ pub async fn get_app_page_entry( let file = File::from(result.build()); let source = VirtualSource::new_with_ident( - source.ident().with_query(Vc::cell(query.to_string())), + source + .ident() + .with_query(Vc::cell(query.to_string().into())), AssetContent::file(file.into()), ); @@ -171,15 +173,15 @@ async fn wrap_edge_page( "edge-ssr-app.js", project_root, indexmap! { - "VAR_USERLAND" => INNER.to_string(), - "VAR_PAGE" => page.to_string(), + "VAR_USERLAND" => INNER.into(), + "VAR_PAGE" => page.to_string().into(), }, indexmap! { - "sriEnabled" => serde_json::Value::Bool(sri_enabled).to_string(), - "nextConfig" => serde_json::to_string(next_config)?, - "isServerComponent" => serde_json::Value::Bool(is_server_component).to_string(), - "dev" => serde_json::Value::Bool(dev).to_string(), - "serverActions" => serde_json::to_string(&server_actions)? + "sriEnabled" => serde_json::Value::Bool(sri_enabled).to_string().into(), + "nextConfig" => serde_json::to_string(next_config)?.into(), + "isServerComponent" => serde_json::Value::Bool(is_server_component).to_string().into(), + "dev" => serde_json::Value::Bool(dev).to_string().into(), + "serverActions" => serde_json::to_string(&server_actions)?.into(), }, indexmap! { "incrementalCacheHandler" => None, @@ -188,7 +190,7 @@ async fn wrap_edge_page( .await?; let inner_assets = indexmap! { - INNER.to_string() => entry + INNER.into() => entry }; let wrapped = context @@ -202,6 +204,6 @@ async fn wrap_edge_page( context, project_root, wrapped, - AppPath::from(page).to_string(), + AppPath::from(page).to_string().into(), )) } diff --git a/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs b/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs index 3031fbab4cafc..1114043a4bed1 100644 --- a/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs +++ b/packages/next-swc/crates/next-core/src/next_app/app_route_entry.rs @@ -1,6 +1,6 @@ use anyhow::{bail, Result}; use indexmap::indexmap; -use turbo_tasks::{Value, ValueToString, Vc}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, turbopack::{ @@ -57,14 +57,14 @@ pub async fn get_app_route_entry( nodejs_context }; - let original_name = page.to_string(); - let pathname = AppPath::from(page.clone()).to_string(); + let original_name: RcStr = page.to_string().into(); + let pathname: RcStr = AppPath::from(page.clone()).to_string().into(); let path = source.ident().path(); const INNER: &str = "INNER_APP_ROUTE"; - let output_type = next_config + let output_type: RcStr = next_config .await? .output .as_ref() @@ -72,21 +72,22 @@ pub async fn get_app_route_entry( OutputType::Standalone => "\"standalone\"".to_string(), OutputType::Export => "\"export\"".to_string(), }) - .unwrap_or_else(|| "\"\"".to_string()); + .map(RcStr::from) + .unwrap_or_else(|| "\"\"".into()); // Load the file from the next.js codebase. let virtual_source = load_next_js_template( "app-route.js", project_root, indexmap! { - "VAR_DEFINITION_PAGE" => page.to_string(), + "VAR_DEFINITION_PAGE" => page.to_string().into(), "VAR_DEFINITION_PATHNAME" => pathname.clone(), - "VAR_DEFINITION_FILENAME" => path.file_stem().await?.as_ref().unwrap().clone(), + "VAR_DEFINITION_FILENAME" => path.file_stem().await?.as_ref().unwrap().as_str().into(), // TODO(alexkirsz) Is this necessary? - "VAR_DEFINITION_BUNDLE_PATH" => "".to_string(), + "VAR_DEFINITION_BUNDLE_PATH" => "".into(), "VAR_ORIGINAL_PATHNAME" => original_name.clone(), "VAR_RESOLVED_PAGE_PATH" => path.to_string().await?.clone_value(), - "VAR_USERLAND" => INNER.to_string(), + "VAR_USERLAND" => INNER.into(), }, indexmap! { "nextConfigOutput" => output_type @@ -103,7 +104,7 @@ pub async fn get_app_route_entry( .module(); let inner_assets = indexmap! { - INNER.to_string() => userland_module + INNER.into() => userland_module }; let mut rsc_entry = context @@ -142,7 +143,7 @@ async fn wrap_edge_route( context: Vc>, project_root: Vc, entry: Vc>, - pathname: String, + pathname: RcStr, ) -> Result>> { const INNER: &str = "INNER_ROUTE_ENTRY"; @@ -150,7 +151,7 @@ async fn wrap_edge_route( "edge-app-route.js", project_root, indexmap! { - "VAR_USERLAND" => INNER.to_string(), + "VAR_USERLAND" => INNER.into(), }, indexmap! {}, indexmap! {}, @@ -158,7 +159,7 @@ async fn wrap_edge_route( .await?; let inner_assets = indexmap! { - INNER.to_string() => entry + INNER.into() => entry }; let wrapped = context diff --git a/packages/next-swc/crates/next-core/src/next_app/include_modules_module.rs b/packages/next-swc/crates/next-core/src/next_app/include_modules_module.rs index 9efd893388144..f1aeceb954672 100644 --- a/packages/next-swc/crates/next-core/src/next_app/include_modules_module.rs +++ b/packages/next-swc/crates/next-core/src/next_app/include_modules_module.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use turbo_tasks::{TryJoinIterExt, ValueToString, Vc}; +use turbo_tasks::{RcStr, TryJoinIterExt, ValueToString, Vc}; use turbo_tasks_fs::glob::Glob; use turbopack_binding::turbopack::{ core::{ @@ -159,8 +159,8 @@ impl IncludedModuleReference { #[turbo_tasks::value_impl] impl ValueToString for IncludedModuleReference { #[turbo_tasks::function] - fn to_string(&self) -> Vc { - Vc::cell("module".to_string()) + fn to_string(&self) -> Vc { + Vc::cell("module".into()) } } diff --git a/packages/next-swc/crates/next-core/src/next_app/metadata/image.rs b/packages/next-swc/crates/next-core/src/next_app/metadata/image.rs index 888252b8623ea..b0be2829a97ae 100644 --- a/packages/next-swc/crates/next-core/src/next_app/metadata/image.rs +++ b/packages/next-swc/crates/next-core/src/next_app/metadata/image.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Result}; use indoc::formatdoc; -use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks::{RcStr, ValueToString, Vc}; use turbo_tasks_fs::{File, FileContent, FileSystemPath}; use turbopack_binding::{ turbo::tasks_hash::hash_xxh3_hash64, @@ -46,7 +46,7 @@ async fn hash_file_content(path: Vc) -> Result { pub async fn dynamic_image_metadata_source( asset_context: Vc>, path: Vc, - ty: String, + ty: RcStr, page: AppPage, ) -> Result>> { let stem = path.file_stem().await?; @@ -126,7 +126,7 @@ pub async fn dynamic_image_metadata_source( let file = File::from(code); let source = VirtualSource::new( - path.parent().join(format!("{stem}--metadata.js")), + path.parent().join(format!("{stem}--metadata.js").into()), AssetContent::file(file.into()), ); @@ -134,7 +134,7 @@ pub async fn dynamic_image_metadata_source( } #[turbo_tasks::function] -async fn collect_direct_exports(module: Vc>) -> Result>> { +async fn collect_direct_exports(module: Vc>) -> Result>> { let Some(ecmascript_asset) = Vc::try_resolve_downcast_type::(module).await? else { diff --git a/packages/next-swc/crates/next-core/src/next_app/metadata/mod.rs b/packages/next-swc/crates/next-core/src/next_app/metadata/mod.rs index c8bce94a78834..ac35312e3a235 100644 --- a/packages/next-swc/crates/next-core/src/next_app/metadata/mod.rs +++ b/packages/next-swc/crates/next-core/src/next_app/metadata/mod.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, ops::Deref}; use anyhow::Result; use once_cell::sync::Lazy; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::FileSystemPath; use crate::next_app::{AppPage, PageSegment, PageType}; @@ -50,7 +50,7 @@ fn match_numbered_metadata(stem: &str) -> Option<(&str, &str)> { fn match_metadata_file<'a>( filename: &'a str, - page_extensions: &[String], + page_extensions: &[RcStr], metadata: &HashMap<&str, &[&str]>, ) -> Option> { let (stem, ext) = filename.split_once('.')?; @@ -115,7 +115,7 @@ pub(crate) async fn get_content_type(path: Vc) -> Result pub fn match_local_metadata_file<'a>( basename: &'a str, - page_extensions: &[String], + page_extensions: &[RcStr], ) -> Option> { match_metadata_file(basename, page_extensions, STATIC_LOCAL_METADATA.deref()) } @@ -127,7 +127,7 @@ pub struct GlobalMetadataFileMatch<'a> { pub fn match_global_metadata_file<'a>( basename: &'a str, - page_extensions: &[String], + page_extensions: &[RcStr], ) -> Option> { match_metadata_file(basename, page_extensions, STATIC_GLOBAL_METADATA.deref()).map(|m| { GlobalMetadataFileMatch { @@ -183,7 +183,7 @@ fn file_stem(path: &str) -> &str { /// /favicon, /manifest, use to match dynamic API routes like app/robots.ts. pub fn is_metadata_route_file( app_dir_relative_path: &str, - page_extensions: &[String], + page_extensions: &[RcStr], with_extension: bool, ) -> bool { let (dir, filename) = split_directory(app_dir_relative_path); @@ -326,17 +326,20 @@ pub fn normalize_metadata_route(mut page: AppPage) -> Result { page.0.pop(); - page.push(PageSegment::Static(format!( - "{}{}{}", - base_name, - suffix - .map(|suffix| format!("-{suffix}")) - .unwrap_or_default(), - ext.map(|ext| format!(".{ext}")).unwrap_or_default(), - )))?; + page.push(PageSegment::Static( + format!( + "{}{}{}", + base_name, + suffix + .map(|suffix| format!("-{suffix}")) + .unwrap_or_default(), + ext.map(|ext| format!(".{ext}")).unwrap_or_default(), + ) + .into(), + ))?; if !is_static_route { - page.push(PageSegment::OptionalCatchAll("__metadata_id__".to_string()))?; + page.push(PageSegment::OptionalCatchAll("__metadata_id__".into()))?; } page.push(PageSegment::PageType(PageType::Route))?; diff --git a/packages/next-swc/crates/next-core/src/next_app/metadata/route.rs b/packages/next-swc/crates/next-core/src/next_app/metadata/route.rs index 251ccf5e99bc5..7227f34bdce9d 100644 --- a/packages/next-swc/crates/next-core/src/next_app/metadata/route.rs +++ b/packages/next-swc/crates/next-core/src/next_app/metadata/route.rs @@ -145,7 +145,7 @@ async fn static_route_source( let file = File::from(code); let source = VirtualSource::new( - path.parent().join(format!("{stem}--route-entry.js")), + path.parent().join(format!("{stem}--route-entry.js").into()), AssetContent::file(file.into()), ); @@ -197,7 +197,7 @@ async fn dynamic_text_route_source(path: Vc) -> Result) -> Result Result> { Ok(ImportMapping::Alternatives(vec![ // Prefer the local installed version over the next.js version - ImportMapping::PrimaryAlternative("postcss".to_string(), Some(project_path)).cell(), - ImportMapping::PrimaryAlternative( - "postcss".to_string(), - Some(get_next_package(project_path)), - ) - .cell(), + ImportMapping::PrimaryAlternative("postcss".into(), Some(project_path)).cell(), + ImportMapping::PrimaryAlternative("postcss".into(), Some(get_next_package(project_path))) + .cell(), ]) .cell()) } #[turbo_tasks::function] pub async fn get_external_next_compiled_package_mapping( - package_name: Vc, + package_name: Vc, ) -> Result> { Ok(ImportMapping::Alternatives(vec![ImportMapping::External( - Some(format!("next/dist/compiled/{}", &*package_name.await?)), + Some(format!("next/dist/compiled/{}", &*package_name.await?).into()), ExternalType::CommonJs, ) .into()]) diff --git a/packages/next-swc/crates/next-core/src/next_client/context.rs b/packages/next-swc/crates/next-core/src/next_client/context.rs index 797e182a2de89..2df977caca867 100644 --- a/packages/next-swc/crates/next-core/src/next_client/context.rs +++ b/packages/next-swc/crates/next-core/src/next_client/context.rs @@ -2,7 +2,7 @@ use std::iter::once; use anyhow::Result; use indexmap::IndexMap; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbo_tasks_fs::FileSystem; use turbopack_binding::{ turbo::{tasks_env::EnvMap, tasks_fs::FileSystemPath}, @@ -66,17 +66,17 @@ use crate::{ util::foreign_code_context_condition, }; -fn defines(define_env: &IndexMap) -> CompileTimeDefines { +fn defines(define_env: &IndexMap) -> CompileTimeDefines { let mut defines = IndexMap::new(); for (k, v) in define_env { defines - .entry(k.split('.').map(|s| s.to_string()).collect::>()) + .entry(k.split('.').map(|s| s.into()).collect::>()) .or_insert_with(|| { let val = serde_json::from_str(v); match val { Ok(serde_json::Value::Bool(v)) => CompileTimeDefineValue::Bool(v), - Ok(serde_json::Value::String(v)) => CompileTimeDefineValue::String(v), + Ok(serde_json::Value::String(v)) => CompileTimeDefineValue::String(v.into()), _ => CompileTimeDefineValue::JSON(v.clone()), } }); @@ -95,14 +95,14 @@ async fn next_client_free_vars(define_env: Vc) -> Result) -> Result, ) -> Vc { CompileTimeInfo::builder(Environment::new(Value::new(ExecutionEnvironment::Browser( @@ -149,7 +149,7 @@ pub async fn get_client_resolve_options_context( let next_client_fallback_import_map = get_next_client_fallback_import_map(ty); let next_client_resolved_map = get_next_client_resolved_map(project_path, project_path, *mode.await?); - let custom_conditions = vec![mode.await?.condition().to_string()]; + let custom_conditions = vec![mode.await?.condition().into()]; let module_options_context = ResolveOptionsContext { enable_node_modules: Some(project_path.root().resolve().await?), custom_conditions, @@ -218,7 +218,7 @@ pub async fn get_client_module_options_context( // foreign_code_context_condition. This allows to import codes from // node_modules that requires webpack loaders, which next-dev implicitly // does by default. - let conditions = vec!["browser".to_string(), mode.await?.condition().to_string()]; + let conditions = vec!["browser".into(), mode.await?.condition().into()]; let foreign_enable_webpack_loaders = webpack_loader_options( project_path, next_config, @@ -226,7 +226,7 @@ pub async fn get_client_module_options_context( conditions .iter() .cloned() - .chain(once("foreign".to_string())) + .chain(once("foreign".into())) .collect(), ) .await?; @@ -326,7 +326,7 @@ pub async fn get_client_module_options_context( pub async fn get_client_chunking_context( project_path: Vc, client_root: Vc, - asset_prefix: Vc>, + asset_prefix: Vc>, environment: Vc, mode: Vc, ) -> Result>> { @@ -335,7 +335,7 @@ pub async fn get_client_chunking_context( project_path, client_root, client_root, - client_root.join("static/chunks".to_string()), + client_root.join("static/chunks".into()), get_client_assets_path(client_root), environment, next_mode.runtime_type(), @@ -353,7 +353,7 @@ pub async fn get_client_chunking_context( #[turbo_tasks::function] pub fn get_client_assets_path(client_root: Vc) -> Vc { - client_root.join("static/media".to_string()) + client_root.join("static/media".into()) } #[turbo_tasks::function] @@ -379,7 +379,7 @@ pub async fn get_client_runtime_entries( // functions to be available. if let Some(request) = enable_react_refresh { runtime_entries - .push(RuntimeEntry::Request(request, project_root.join("_".to_string())).cell()) + .push(RuntimeEntry::Request(request, project_root.join("_".into())).cell()) }; } @@ -387,9 +387,9 @@ pub async fn get_client_runtime_entries( runtime_entries.push( RuntimeEntry::Request( Request::parse(Value::new(Pattern::Constant( - "next/dist/client/app-next-turbopack.js".to_string(), + "next/dist/client/app-next-turbopack.js".into(), ))), - project_root.join("_".to_string()), + project_root.join("_".into()), ) .cell(), ); diff --git a/packages/next-swc/crates/next-core/src/next_client_reference/css_client_reference/css_client_reference_module.rs b/packages/next-swc/crates/next-core/src/next_client_reference/css_client_reference/css_client_reference_module.rs index af5fe7205b6f8..ad284d05912d6 100644 --- a/packages/next-swc/crates/next-core/src/next_client_reference/css_client_reference/css_client_reference_module.rs +++ b/packages/next-swc/crates/next-core/src/next_client_reference/css_client_reference/css_client_reference_module.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Context, Result}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbopack::{ core::{ asset::{Asset, AssetContent}, @@ -31,8 +31,8 @@ impl CssClientReferenceModule { } #[turbo_tasks::function] -fn css_client_reference_modifier() -> Vc { - Vc::cell("css client reference".to_string()) +fn css_client_reference_modifier() -> Vc { + Vc::cell("css client reference".into()) } #[turbo_tasks::value_impl] diff --git a/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs b/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs index b5441e9e5e5c6..be2743dac817d 100644 --- a/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs +++ b/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs @@ -1,6 +1,6 @@ #![allow(rustdoc::private_intra_doc_links)] use anyhow::{bail, Result}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbopack::{ core::{ asset::{Asset, AssetContent}, @@ -46,8 +46,8 @@ impl EcmascriptClientReferenceModule { } #[turbo_tasks::function] -fn ecmascript_client_reference_modifier() -> Vc { - Vc::cell("ecmascript client reference".to_string()) +fn ecmascript_client_reference_modifier() -> Vc { + Vc::cell("ecmascript client reference".into()) } #[turbo_tasks::value_impl] diff --git a/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_proxy_module.rs b/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_proxy_module.rs index 4a79236b1ed2b..8d32e1498691a 100644 --- a/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_proxy_module.rs +++ b/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_proxy_module.rs @@ -2,7 +2,7 @@ use std::{io::Write, iter::once}; use anyhow::{bail, Context, Result}; use indoc::writedoc; -use turbo_tasks::{Value, ValueToString, Vc}; +use turbo_tasks::{RcStr, Value, ValueToString, Vc}; use turbo_tasks_fs::File; use turbopack_binding::turbopack::{ core::{ @@ -143,7 +143,7 @@ impl EcmascriptClientReferenceProxyModule { AssetContent::file(File::from(code.source_code().clone()).into()); let proxy_source = VirtualSource::new( - self.server_module_ident.path().join("proxy.js".to_string()), + self.server_module_ident.path().join("proxy.js".into()), proxy_module_content, ); @@ -253,13 +253,13 @@ struct ProxyModuleChunkItem { } #[turbo_tasks::function] -fn client_proxy_modifier() -> Vc { - Vc::cell("client proxy".to_string()) +fn client_proxy_modifier() -> Vc { + Vc::cell("client proxy".into()) } #[turbo_tasks::function] -fn client_reference_description() -> Vc { - Vc::cell("client references".to_string()) +fn client_reference_description() -> Vc { + Vc::cell("client references".into()) } #[turbo_tasks::value_impl] diff --git a/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_transition.rs b/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_transition.rs index 50015aec39396..1ae768f97d552 100644 --- a/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_transition.rs +++ b/packages/next-swc/crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_transition.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbopack_binding::turbopack::{ core::{ context::ProcessResult, @@ -40,7 +40,7 @@ impl NextEcmascriptClientReferenceTransition { #[turbo_tasks::value_impl] impl Transition for NextEcmascriptClientReferenceTransition { #[turbo_tasks::function] - fn process_layer(self: Vc, layer: Vc) -> Vc { + fn process_layer(self: Vc, layer: Vc) -> Vc { layer } @@ -58,10 +58,12 @@ impl Transition for NextEcmascriptClientReferenceTransition { let ident = source.ident().await?; let ident_path = ident.path.await?; let client_source = if ident_path.path.contains("next/dist/esm/") { - let path = ident - .path - .root() - .join(ident_path.path.replace("next/dist/esm/", "next/dist/")); + let path = ident.path.root().join( + ident_path + .path + .replace("next/dist/esm/", "next/dist/") + .into(), + ); Vc::upcast(FileSource::new_with_query(path, ident.query)) } else { source diff --git a/packages/next-swc/crates/next-core/src/next_client_reference/visit_client_reference.rs b/packages/next-swc/crates/next-core/src/next_client_reference/visit_client_reference.rs index 3abb30ce55b65..330e912d0904c 100644 --- a/packages/next-swc/crates/next-core/src/next_client_reference/visit_client_reference.rs +++ b/packages/next-swc/crates/next-core/src/next_client_reference/visit_client_reference.rs @@ -8,7 +8,7 @@ use turbo_tasks::{ debug::ValueDebugFormat, graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow}, trace::TraceRawVcs, - ReadRef, TryJoinIterExt, ValueToString, Vc, + RcStr, ReadRef, TryJoinIterExt, ValueToString, Vc, }; use turbopack_binding::turbopack::core::{ module::{Module, Modules}, @@ -170,9 +170,9 @@ struct VisitClientReferenceNode { Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs, )] enum VisitClientReferenceNodeType { - ClientReference(ClientReference, ReadRef), - ServerComponentEntry(Vc, ReadRef), - Internal(Vc>, ReadRef), + ClientReference(ClientReference, ReadRef), + ServerComponentEntry(Vc, ReadRef), + Internal(Vc>, ReadRef), } impl Visit for VisitClientReference { @@ -269,13 +269,13 @@ impl Visit for VisitClientReference { fn span(&mut self, node: &VisitClientReferenceNode) -> tracing::Span { match &node.ty { VisitClientReferenceNodeType::ClientReference(_, name) => { - tracing::info_span!("client reference", name = **name) + tracing::info_span!("client reference", name = name.to_string()) } VisitClientReferenceNodeType::Internal(_, name) => { - tracing::info_span!("module", name = **name) + tracing::info_span!("module", name = name.to_string()) } VisitClientReferenceNodeType::ServerComponentEntry(_, name) => { - tracing::info_span!("layout segment", name = **name) + tracing::info_span!("layout segment", name = name.to_string()) } } } diff --git a/packages/next-swc/crates/next-core/src/next_config.rs b/packages/next-swc/crates/next-core/src/next_config.rs index 3d27d4a852427..f56eaf9cba204 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -4,7 +4,7 @@ use anyhow::{bail, Context, Result}; use indexmap::IndexMap; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value as JsonValue; -use turbo_tasks::{trace::TraceRawVcs, TaskInput, Vc}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, TaskInput, Vc}; use turbopack_binding::{ turbo::{tasks_env::EnvMap, tasks_fs::FileSystemPath}, turbopack::{ @@ -59,35 +59,34 @@ struct CustomRoutes { #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NextConfig { - pub config_file: Option, - pub config_file_name: String, + pub config_file: Option, + pub config_file_name: RcStr, /// In-memory cache size in bytes. /// /// If `cache_max_memory_size: 0` disables in-memory caching. pub cache_max_memory_size: Option, /// custom path to a cache handler to use - pub cache_handler: Option, + pub cache_handler: Option, pub env: IndexMap, pub experimental: ExperimentalConfig, pub images: ImageConfig, - pub page_extensions: Vec, + pub page_extensions: Vec, pub react_strict_mode: Option, - pub transpile_packages: Option>, + pub transpile_packages: Option>, pub modularize_imports: Option>, - pub dist_dir: Option, + pub dist_dir: Option, sass_options: Option, pub trailing_slash: Option, - pub asset_prefix: Option, - pub base_path: Option, + pub asset_prefix: Option, + pub base_path: Option, pub skip_middleware_url_normalize: Option, pub skip_trailing_slash_redirect: Option, pub i18n: Option, pub cross_origin: Option, pub dev_indicators: Option, pub output: Option, - pub analytics_id: Option, /// Enables the bundling of node_modules packages (externals) for pages /// server-side bundles. @@ -99,7 +98,7 @@ pub struct NextConfig { /// build. /// /// [API Reference](https://nextjs.org/docs/app/api-reference/next-config-js/serverExternalPackages) - pub server_external_packages: Option>, + pub server_external_packages: Option>, #[serde(rename = "_originalRedirects")] pub original_redirects: Option>, @@ -122,13 +121,11 @@ pub struct NextConfig { generate_etags: bool, http_agent_options: HttpAgentConfig, on_demand_entries: OnDemandEntriesConfig, - output_file_tracing: bool, powered_by_header: bool, production_browser_source_maps: bool, public_runtime_config: IndexMap, server_runtime_config: IndexMap, static_page_generation_timeout: f64, - swc_minify: Option, target: Option, typescript: TypeScriptConfig, use_file_system_public_routes: bool, @@ -226,30 +223,30 @@ pub enum OutputType { #[serde(tag = "type", rename_all = "kebab-case")] pub enum RouteHas { Header { - key: String, + key: RcStr, #[serde(skip_serializing_if = "Option::is_none")] - value: Option, + value: Option, }, Cookie { - key: String, + key: RcStr, #[serde(skip_serializing_if = "Option::is_none")] - value: Option, + value: Option, }, Query { - key: String, + key: RcStr, #[serde(skip_serializing_if = "Option::is_none")] - value: Option, + value: Option, }, Host { - value: String, + value: RcStr, }, } #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct HeaderValue { - pub key: String, - pub value: String, + pub key: RcStr, + pub value: RcStr, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] @@ -416,39 +413,39 @@ pub enum RemotePatternProtocal { pub struct ExperimentalTurboConfig { /// This option has been replaced by `rules`. pub loaders: Option, - pub rules: Option>, - pub resolve_alias: Option>, - pub resolve_extensions: Option>, + pub rules: Option>, + pub resolve_alias: Option>, + pub resolve_extensions: Option>, pub use_swc_css: Option, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct RuleConfigItemOptions { pub loaders: Vec, #[serde(default, alias = "as")] - pub rename_as: Option, + pub rename_as: Option, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase", untagged)] pub enum RuleConfigItemOrShortcut { Loaders(Vec), Advanced(RuleConfigItem), } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase", untagged)] pub enum RuleConfigItem { Options(RuleConfigItemOptions), - Conditional(IndexMap), + Conditional(IndexMap), Boolean(bool), } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] #[serde(untagged)] pub enum LoaderItem { - LoaderName(String), + LoaderName(RcStr), LoaderOptions(WebpackLoaderItem), } @@ -459,29 +456,59 @@ pub enum MdxRsOptions { Option(MdxTransformOptions), } +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub enum ReactCompilerMode { + Infer, + Annotation, + All, +} + +/// Subset of react compiler options +#[turbo_tasks::value(shared)] +#[derive(Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ReactCompilerOptions { + #[serde(skip_serializing_if = "Option::is_none")] + pub compilation_mode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub panic_threshold: Option, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(untagged)] +pub enum ReactCompilerOptionsOrBoolean { + Boolean(bool), + Option(ReactCompilerOptions), +} + +#[turbo_tasks::value(transparent)] +pub struct OptionalReactCompilerOptions(Option>); + #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct ExperimentalConfig { - pub allowed_revalidate_header_keys: Option>, + pub allowed_revalidate_header_keys: Option>, pub client_router_filter: Option, /// decimal for percent for possible false positives e.g. 0.01 for 10% /// potential false matches lower percent increases size of the filter pub client_router_filter_allowed_rate: Option, pub client_router_filter_redirects: Option, - pub fetch_cache_key_prefix: Option, + pub fetch_cache_key_prefix: Option, pub isr_flush_to_disk: Option, /// For use with `@next/mdx`. Compile MDX files using the new Rust compiler. /// @see [api reference](https://nextjs.org/docs/app/api-reference/next-config-js/mdxRs) mdx_rs: Option, pub strict_next_head: Option, - pub swc_plugins: Option>, + pub swc_plugins: Option>, pub turbo: Option, pub turbotrace: Option, pub external_middleware_rewrites_resolve: Option, pub scroll_restoration: Option, pub use_deployment_id: Option, pub use_deployment_id_server_actions: Option, - pub deployment_id: Option, + pub deployment_id: Option, pub manual_client_base_path: Option, pub optimistic_client_cache: Option, pub middleware_prefetch: Option, @@ -489,15 +516,17 @@ pub struct ExperimentalConfig { /// Use Record as critters doesn't export its Option type ([link](https://github.com/GoogleChromeLabs/critters/blob/a590c05f9197b656d2aeaae9369df2483c26b072/packages/critters/src/index.d.ts)) pub optimize_css: Option, pub next_script_workers: Option, - pub web_vitals_attribution: Option>, + pub web_vitals_attribution: Option>, pub server_actions: Option, pub sri: Option, + react_compiler: Option, // --- // UNSUPPORTED // --- adjust_font_fallbacks: Option, adjust_font_fallbacks_with_size_adjust: Option, + after: Option, amp: Option, app_document_preloading: Option, case_sensitive_routes: Option, @@ -525,20 +554,19 @@ pub struct ExperimentalConfig { optimize_server_react: Option, /// Automatically apply the "modularize_imports" optimization to imports of /// the specified packages. - optimize_package_imports: Option>, - output_file_tracing_ignores: Option>, + optimize_package_imports: Option>, + output_file_tracing_ignores: Option>, output_file_tracing_includes: Option, - output_file_tracing_root: Option, + output_file_tracing_root: Option, /// Using this feature will enable the `react@experimental` for the `app` /// directory. - ppr: Option, + ppr: Option, taint: Option, proxy_timeout: Option, /// enables the minification of server code. server_minification: Option, /// Enables source maps generation for the server production bundle. server_source_maps: Option, - swc_minify: Option, swc_trace_profiling: Option, /// @internal Used by the Next.js internals only. trust_host_header: Option, @@ -553,6 +581,49 @@ pub struct ExperimentalConfig { worker_threads: Option, } +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(rename_all = "lowercase")] +pub enum ExperimentalPartialPrerenderingIncrementalValue { + Incremental, +} + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TraceRawVcs)] +#[serde(untagged)] +pub enum ExperimentalPartialPrerendering { + Incremental(ExperimentalPartialPrerenderingIncrementalValue), + Boolean(bool), +} + +#[test] +fn test_parse_experimental_partial_prerendering() { + let json = serde_json::json!({ + "ppr": "incremental" + }); + let config: ExperimentalConfig = serde_json::from_value(json).unwrap(); + assert_eq!( + config.ppr, + Some(ExperimentalPartialPrerendering::Incremental( + ExperimentalPartialPrerenderingIncrementalValue::Incremental + )) + ); + + let json = serde_json::json!({ + "ppr": true + }); + let config: ExperimentalConfig = serde_json::from_value(json).unwrap(); + assert_eq!( + config.ppr, + Some(ExperimentalPartialPrerendering::Boolean(true)) + ); + + // Expect if we provide a random string, it will fail. + let json = serde_json::json!({ + "ppr": "random" + }); + let config = serde_json::from_value::(json); + assert!(config.is_err()); +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct SubResourceIntegrity { @@ -583,6 +654,25 @@ pub enum EsmExternals { Bool(bool), } +// Test for esm externals deserialization. +#[test] +fn test_esm_externals_deserialization() { + let json = serde_json::json!({ + "esmExternals": true + }); + let config: ExperimentalConfig = serde_json::from_value(json).unwrap(); + assert_eq!(config.esm_externals, Some(EsmExternals::Bool(true))); + + let json = serde_json::json!({ + "esmExternals": "loose" + }); + let config: ExperimentalConfig = serde_json::from_value(json).unwrap(); + assert_eq!( + config.esm_externals, + Some(EsmExternals::Loose(EsmExternalsValue::Loose)) + ); +} + #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct ServerActions { @@ -670,7 +760,7 @@ impl RemoveConsoleConfig { } #[turbo_tasks::value(transparent)] -pub struct ResolveExtensions(Option>); +pub struct ResolveExtensions(Option>); #[turbo_tasks::value(transparent)] pub struct OptionalMdxTransformOptions(Option>); @@ -678,7 +768,7 @@ pub struct OptionalMdxTransformOptions(Option>); #[turbo_tasks::value_impl] impl NextConfig { #[turbo_tasks::function] - pub async fn from_string(string: Vc) -> Result> { + pub async fn from_string(string: Vc) -> Result> { let string = string.await?; let config: NextConfig = serde_json::from_str(&string) .with_context(|| format!("failed to parse next.config.js: {}", string))?; @@ -691,7 +781,7 @@ impl NextConfig { } #[turbo_tasks::function] - pub async fn server_external_packages(self: Vc) -> Result>> { + pub async fn server_external_packages(self: Vc) -> Result>> { Ok(Vc::cell( self.await? .server_external_packages @@ -712,12 +802,12 @@ impl NextConfig { .iter() .map(|(k, v)| { ( - k.clone(), + k.as_str().into(), if let JsonValue::String(s) = v { // A string value is kept, calling `to_string` would wrap in to quotes. - s.clone() + s.as_str().into() } else { - v.to_string() + v.to_string().into() }, ) }) @@ -732,12 +822,12 @@ impl NextConfig { } #[turbo_tasks::function] - pub async fn page_extensions(self: Vc) -> Result>> { + pub async fn page_extensions(self: Vc) -> Result>> { Ok(Vc::cell(self.await?.page_extensions.clone())) } #[turbo_tasks::function] - pub async fn transpile_packages(self: Vc) -> Result>> { + pub async fn transpile_packages(self: Vc) -> Result>> { Ok(Vc::cell( self.await?.transpile_packages.clone().unwrap_or_default(), )) @@ -746,7 +836,7 @@ impl NextConfig { #[turbo_tasks::function] pub async fn webpack_rules( self: Vc, - active_conditions: Vec, + active_conditions: Vec, ) -> Result> { let this = self.await?; let Some(turbo_rules) = this @@ -784,7 +874,7 @@ impl NextConfig { } fn find_rule<'a>( rule: &'a RuleConfigItem, - active_conditions: &HashSet, + active_conditions: &HashSet, ) -> FindRuleResult<'a> { match rule { RuleConfigItem::Options(rule) => FindRuleResult::Found(rule), @@ -810,7 +900,7 @@ impl NextConfig { match rule { RuleConfigItemOrShortcut::Loaders(loaders) => { rules.insert( - ext.to_string(), + ext.clone(), LoaderRuleItem { loaders: transform_loaders(loaders), rename_as: None, @@ -822,7 +912,7 @@ impl NextConfig { find_rule(rule, &active_conditions) { rules.insert( - ext.to_string(), + ext.clone(), LoaderRuleItem { loaders: transform_loaders(loaders), rename_as: rename_as.clone(), @@ -890,8 +980,7 @@ impl NextConfig { provider_import_source: Some( options .provider_import_source - .as_ref() - .map(|s| s.to_string()) + .clone() .unwrap_or(mdx_import_source_file()), ), ..options.clone() @@ -904,6 +993,29 @@ impl NextConfig { Ok(options.cell()) } + #[turbo_tasks::function] + pub async fn react_compiler(self: Vc) -> Result> { + let options = &self.await?.experimental.react_compiler; + + let options = match options { + Some(ReactCompilerOptionsOrBoolean::Boolean(true)) => { + OptionalReactCompilerOptions(Some( + ReactCompilerOptions { + compilation_mode: None, + panic_threshold: None, + } + .cell(), + )) + } + Some(ReactCompilerOptionsOrBoolean::Option(options)) => OptionalReactCompilerOptions( + Some(ReactCompilerOptions { ..options.clone() }.cell()), + ), + _ => OptionalReactCompilerOptions(None), + }; + + Ok(options.cell()) + } + #[turbo_tasks::function] pub async fn sass_config(self: Vc) -> Result> { Ok(Vc::cell( @@ -911,11 +1023,6 @@ impl NextConfig { )) } - #[turbo_tasks::function] - pub async fn swc_minify(self: Vc) -> Result> { - Ok(Vc::cell(self.await?.swc_minify.unwrap_or(false))) - } - #[turbo_tasks::function] pub async fn skip_middleware_url_normalize(self: Vc) -> Result> { Ok(Vc::cell( @@ -933,23 +1040,38 @@ impl NextConfig { /// Returns the final asset prefix. If an assetPrefix is set, it's used. /// Otherwise, the basePath is used. #[turbo_tasks::function] - pub async fn computed_asset_prefix(self: Vc) -> Result>> { + pub async fn computed_asset_prefix(self: Vc) -> Result>> { let this = self.await?; - Ok(Vc::cell(Some(format!( - "{}/_next/", - if let Some(asset_prefix) = &this.asset_prefix { - asset_prefix - } else { - this.base_path.as_ref().map_or("", |b| b.as_str()) - } - .trim_end_matches('/') - )))) + Ok(Vc::cell(Some( + format!( + "{}/_next/", + if let Some(asset_prefix) = &this.asset_prefix { + asset_prefix + } else { + this.base_path.as_ref().map_or("", |b| b.as_str()) + } + .trim_end_matches('/') + ) + .into(), + ))) } #[turbo_tasks::function] pub async fn enable_ppr(self: Vc) -> Result> { - Ok(Vc::cell(self.await?.experimental.ppr.unwrap_or(false))) + Ok(Vc::cell( + self.await? + .experimental + .ppr + .as_ref() + .map(|ppr| match ppr { + ExperimentalPartialPrerendering::Incremental( + ExperimentalPartialPrerenderingIncrementalValue::Incremental, + ) => true, + ExperimentalPartialPrerendering::Boolean(b) => *b, + }) + .unwrap_or(false), + )) } #[turbo_tasks::function] @@ -970,7 +1092,7 @@ impl NextConfig { } #[turbo_tasks::function] - pub async fn optimize_package_imports(self: Vc) -> Result>> { + pub async fn optimize_package_imports(self: Vc) -> Result>> { Ok(Vc::cell( self.await? .experimental @@ -993,7 +1115,7 @@ pub struct JsConfig { #[turbo_tasks::value_impl] impl JsConfig { #[turbo_tasks::function] - pub async fn from_string(string: Vc) -> Result> { + pub async fn from_string(string: Vc) -> Result> { let string = string.await?; let config: JsConfig = serde_json::from_str(&string) .with_context(|| format!("failed to parse next.config.js: {}", string))?; @@ -1012,9 +1134,9 @@ impl JsConfig { #[turbo_tasks::value] struct OutdatedConfigIssue { path: Vc, - old_name: String, - new_name: String, - description: String, + old_name: RcStr, + new_name: RcStr, + description: RcStr, } #[turbo_tasks::value_impl] @@ -1038,7 +1160,7 @@ impl Issue for OutdatedConfigIssue { fn title(&self) -> Vc { StyledString::Line(vec![ StyledString::Code(self.old_name.clone()), - StyledString::Text(" has been replaced by ".to_string()), + StyledString::Text(" has been replaced by ".into()), StyledString::Code(self.new_name.clone()), ]) .cell() @@ -1046,8 +1168,6 @@ impl Issue for OutdatedConfigIssue { #[turbo_tasks::function] fn description(&self) -> Vc { - Vc::cell(Some( - StyledString::Text(self.description.to_string()).cell(), - )) + Vc::cell(Some(StyledString::Text(self.description.clone()).cell())) } } diff --git a/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_module.rs b/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_module.rs index 5b713b4247ff3..08e9c7d29f7eb 100644 --- a/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_module.rs +++ b/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_module.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbopack::core::{ asset::{Asset, AssetContent}, chunk::{ChunkableModule, ChunkingContext, ChunkingContextExt}, @@ -46,8 +46,8 @@ impl NextDynamicEntryModule { } #[turbo_tasks::function] -fn dynamic_modifier() -> Vc { - Vc::cell("dynamic".to_string()) +fn dynamic_modifier() -> Vc { + Vc::cell("dynamic".into()) } #[turbo_tasks::value_impl] diff --git a/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_transition.rs b/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_transition.rs index 53792575ca3b6..c139f404c762f 100644 --- a/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_transition.rs +++ b/packages/next-swc/crates/next-core/src/next_dynamic/dynamic_transition.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbopack_binding::turbopack::{ core::{context::ProcessResult, reference_type::ReferenceType, source::Source}, turbopack::{transition::Transition, ModuleAssetContext}, @@ -26,7 +26,7 @@ impl NextDynamicTransition { #[turbo_tasks::value_impl] impl Transition for NextDynamicTransition { #[turbo_tasks::function] - fn process_layer(self: Vc, layer: Vc) -> Vc { + fn process_layer(self: Vc, layer: Vc) -> Vc { layer } diff --git a/packages/next-swc/crates/next-core/src/next_dynamic/visit_dynamic.rs b/packages/next-swc/crates/next-core/src/next_dynamic/visit_dynamic.rs index 486dfb4dc5f82..1facdad6032b3 100644 --- a/packages/next-swc/crates/next-core/src/next_dynamic/visit_dynamic.rs +++ b/packages/next-swc/crates/next-core/src/next_dynamic/visit_dynamic.rs @@ -4,7 +4,7 @@ use anyhow::Result; use tracing::Instrument; use turbo_tasks::{ graph::{AdjacencyMap, GraphTraversal, Visit, VisitControlFlow}, - ReadRef, TryJoinIterExt, ValueToString, Vc, + RcStr, ReadRef, TryJoinIterExt, ValueToString, Vc, }; use turbopack_binding::turbopack::core::{ module::{Module, Modules}, @@ -66,8 +66,8 @@ struct VisitDynamic; #[derive(Clone, Eq, PartialEq, Hash)] enum VisitDynamicNode { - Dynamic(Vc, ReadRef), - Internal(Vc>, ReadRef), + Dynamic(Vc, ReadRef), + Internal(Vc>, ReadRef), } impl Visit for VisitDynamic { @@ -117,10 +117,10 @@ impl Visit for VisitDynamic { fn span(&mut self, node: &VisitDynamicNode) -> tracing::Span { match node { VisitDynamicNode::Dynamic(_, name) => { - tracing::info_span!("dynamic module", name = **name) + tracing::info_span!("dynamic module", name = name.to_string()) } VisitDynamicNode::Internal(_, name) => { - tracing::info_span!("module", name = **name) + tracing::info_span!("module", name = name.to_string()) } } } diff --git a/packages/next-swc/crates/next-core/src/next_edge/context.rs b/packages/next-swc/crates/next-core/src/next_edge/context.rs index 5408d89bf61e8..acee2dc2c511a 100644 --- a/packages/next-swc/crates/next-core/src/next_edge/context.rs +++ b/packages/next-swc/crates/next-core/src/next_edge/context.rs @@ -1,6 +1,6 @@ use anyhow::Result; use indexmap::IndexMap; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbopack_binding::{ turbo::{tasks_env::EnvMap, tasks_fs::FileSystemPath}, turbopack::{ @@ -33,17 +33,17 @@ use crate::{ util::{foreign_code_context_condition, NextRuntime}, }; -fn defines(define_env: &IndexMap) -> CompileTimeDefines { +fn defines(define_env: &IndexMap) -> CompileTimeDefines { let mut defines = IndexMap::new(); for (k, v) in define_env { defines - .entry(k.split('.').map(|s| s.to_string()).collect::>()) + .entry(k.split('.').map(|s| s.into()).collect::>()) .or_insert_with(|| { let val = serde_json::from_str(v); match val { Ok(serde_json::Value::Bool(v)) => CompileTimeDefineValue::Bool(v), - Ok(serde_json::Value::String(v)) => CompileTimeDefineValue::String(v), + Ok(serde_json::Value::String(v)) => CompileTimeDefineValue::String(v.into()), _ => CompileTimeDefineValue::JSON(v.clone()), } }); @@ -67,9 +67,9 @@ async fn next_edge_free_vars( Ok(free_var_references!( ..defines(&*define_env.await?).into_iter(), Buffer = FreeVarReference::EcmaScriptModule { - request: "buffer".to_string(), + request: "buffer".into(), lookup_path: Some(project_path), - export: Some("Buffer".to_string()), + export: Some("Buffer".into()), }, ) .cell()) @@ -141,16 +141,17 @@ pub async fn get_edge_resolve_options_context( after_resolve_plugins.extend_from_slice(&base_plugins); // https://github.com/vercel/next.js/blob/bf52c254973d99fed9d71507a2e818af80b8ade7/packages/next/src/build/webpack-config.ts#L96-L102 - let mut custom_conditions = vec![mode.await?.condition().to_string()]; + let mut custom_conditions = vec![mode.await?.condition().into()]; custom_conditions.extend( NextRuntime::Edge .conditions() .iter() - .map(ToString::to_string), + .map(ToString::to_string) + .map(RcStr::from), ); if ty.supports_react_server() { - custom_conditions.push("react-server".to_string()); + custom_conditions.push("react-server".into()); }; let resolve_options_context = ResolveOptionsContext { @@ -186,18 +187,18 @@ pub async fn get_edge_chunking_context_with_client_assets( project_path: Vc, node_root: Vc, client_root: Vc, - asset_prefix: Vc>, + asset_prefix: Vc>, environment: Vc, ) -> Result>> { - let output_root = node_root.join("server/edge".to_string()); + let output_root = node_root.join("server/edge".into()); let next_mode = mode.await?; Ok(Vc::upcast( BrowserChunkingContext::builder( project_path, output_root, client_root, - output_root.join("chunks/ssr".to_string()), - client_root.join("static/media".to_string()), + output_root.join("chunks/ssr".into()), + client_root.join("static/media".into()), environment, next_mode.runtime_type(), ) @@ -214,15 +215,15 @@ pub async fn get_edge_chunking_context( node_root: Vc, environment: Vc, ) -> Result>> { - let output_root = node_root.join("server/edge".to_string()); + let output_root = node_root.join("server/edge".into()); let next_mode = mode.await?; Ok(Vc::upcast( BrowserChunkingContext::builder( project_path, output_root, output_root, - output_root.join("chunks".to_string()), - output_root.join("assets".to_string()), + output_root.join("chunks".into()), + output_root.join("assets".into()), environment, next_mode.runtime_type(), ) @@ -230,7 +231,7 @@ pub async fn get_edge_chunking_context( // instead. This special blob url is handled by the custom fetch // implementation in the edge sandbox. It will respond with the // asset from the output directory. - .asset_base_path(Vc::cell(Some("blob:server/edge/".to_string()))) + .asset_base_path(Vc::cell(Some("blob:server/edge/".into()))) .minify_type(next_mode.minify_type()) .build(), )) diff --git a/packages/next-swc/crates/next-core/src/next_edge/entry.rs b/packages/next-swc/crates/next-core/src/next_edge/entry.rs index 6364f98bce38b..4e0cf2cf97432 100644 --- a/packages/next-swc/crates/next-core/src/next_edge/entry.rs +++ b/packages/next-swc/crates/next-core/src/next_edge/entry.rs @@ -1,7 +1,7 @@ use anyhow::Result; use indexmap::indexmap; use indoc::formatdoc; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbo_tasks_fs::{File, FileSystemPath}; use turbopack_binding::turbopack::{ core::{ @@ -16,7 +16,7 @@ pub async fn wrap_edge_entry( context: Vc>, project_root: Vc, entry: Vc>, - pathname: String, + pathname: RcStr, ) -> Result>> { // The wrapped module could be an async module, we handle that with the proxy // here. The comma expression makes sure we don't call the function with the @@ -32,12 +32,12 @@ pub async fn wrap_edge_entry( // TODO(alexkirsz) Figure out how to name this virtual asset. let virtual_source = VirtualSource::new( - project_root.join("edge-wrapper.js".to_string()), + project_root.join("edge-wrapper.js".into()), AssetContent::file(file.into()), ); let inner_assets = indexmap! { - "MODULE".to_string() => entry + "MODULE".into() => entry }; let module = context diff --git a/packages/next-swc/crates/next-core/src/next_edge/unsupported.rs b/packages/next-swc/crates/next-core/src/next_edge/unsupported.rs index 1318c95c8f9da..ce4fc948067f6 100644 --- a/packages/next-swc/crates/next-core/src/next_edge/unsupported.rs +++ b/packages/next-swc/crates/next-core/src/next_edge/unsupported.rs @@ -1,6 +1,6 @@ use anyhow::Result; use indoc::formatdoc; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::File; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, @@ -46,7 +46,7 @@ impl NextEdgeUnsupportedModuleReplacer { #[turbo_tasks::value_impl] impl ImportMappingReplacement for NextEdgeUnsupportedModuleReplacer { #[turbo_tasks::function] - fn replace(&self, _capture: String) -> Vc { + fn replace(&self, _capture: RcStr) -> Vc { ImportMapping::Ignore.into() } diff --git a/packages/next-swc/crates/next-core/src/next_font/font_fallback.rs b/packages/next-swc/crates/next-core/src/next_font/font_fallback.rs index a33d84357ca42..f4c0db91643b3 100644 --- a/packages/next-swc/crates/next-core/src/next_font/font_fallback.rs +++ b/packages/next-swc/crates/next-core/src/next_font/font_fallback.rs @@ -1,12 +1,12 @@ use anyhow::Result; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbo::tasks::trace::TraceRawVcs; pub(crate) struct DefaultFallbackFont { - pub name: String, - pub capsize_key: String, + pub name: RcStr, + pub capsize_key: RcStr, pub az_avg_width: f64, pub units_per_em: u32, } @@ -14,16 +14,16 @@ pub(crate) struct DefaultFallbackFont { // From https://github.com/vercel/next.js/blob/a3893bf69c83fb08e88c87bf8a21d987a0448c8e/packages/font/src/utils.ts#L4 pub(crate) static DEFAULT_SANS_SERIF_FONT: Lazy = Lazy::new(|| DefaultFallbackFont { - name: "Arial".to_owned(), - capsize_key: "arial".to_owned(), + name: "Arial".into(), + capsize_key: "arial".into(), az_avg_width: 934.5116279069767, units_per_em: 2048, }); pub(crate) static DEFAULT_SERIF_FONT: Lazy = Lazy::new(|| DefaultFallbackFont { - name: "Times New Roman".to_owned(), - capsize_key: "timesNewRoman".to_owned(), + name: "Times New Roman".into(), + capsize_key: "timesNewRoman".into(), az_avg_width: 854.3953488372093, units_per_em: 2048, }); @@ -32,9 +32,9 @@ pub(crate) static DEFAULT_SERIF_FONT: Lazy = #[turbo_tasks::value(shared)] pub(crate) struct AutomaticFontFallback { /// e.g. `__Roboto_Fallback_c123b8` - pub scoped_font_family: Vc, + pub scoped_font_family: Vc, /// The name of font locally, used in `src: local("{}")` - pub local_font_family: Vc, + pub local_font_family: Vc, pub adjustment: Option, } @@ -48,7 +48,7 @@ pub(crate) enum FontFallback { /// return this and omit fallback information instead. Error, /// A list of manually provided font names to use a fallback, as-is. - Manual(Vec), + Manual(Vec), } #[turbo_tasks::value_impl] diff --git a/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs b/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs index 7e703d578bd64..008140df0d7ae 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs @@ -4,7 +4,7 @@ use anyhow::{Context, Result}; use once_cell::sync::Lazy; use regex::Regex; use serde::{Deserialize, Serialize}; -use turbo_tasks::{trace::TraceRawVcs, Vc}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, Vc}; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, turbopack::core::issue::{IssueExt, IssueSeverity, StyledString}, @@ -27,7 +27,7 @@ use crate::{ #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub(super) struct FontMetricsMapEntry { - category: String, + category: RcStr, ascent: i32, descent: i32, line_gap: u32, @@ -36,11 +36,11 @@ pub(super) struct FontMetricsMapEntry { } #[derive(Deserialize, Debug)] -pub(super) struct FontMetricsMap(pub HashMap); +pub(super) struct FontMetricsMap(pub HashMap); #[derive(Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] struct Fallback { - pub font_family: String, + pub font_family: RcStr, pub adjustment: Option, } @@ -53,11 +53,9 @@ pub(super) async fn get_font_fallback( Ok(match &options.fallback { Some(fallback) => FontFallback::Manual(fallback.clone()).cell(), None => { - let metrics_json = load_next_js_templateon( - context, - "dist/server/capsize-font-metrics.json".to_string(), - ) - .await?; + let metrics_json = + load_next_js_templateon(context, "dist/server/capsize-font-metrics.json".into()) + .await?; let fallback = lookup_fallback( &options.font_family, metrics_json, @@ -77,13 +75,16 @@ pub(super) async fn get_font_fallback( Err(_) => { NextFontIssue { path: context, - title: StyledString::Text(format!( - "Failed to find font override values for font `{}`", - &options.font_family, - )) + title: StyledString::Text( + format!( + "Failed to find font override values for font `{}`", + &options.font_family, + ) + .into(), + ) .cell(), description: StyledString::Text( - "Skipping generating a fallback font.".to_owned(), + "Skipping generating a fallback font.".into(), ) .cell(), severity: IssueSeverity::Warning.cell(), @@ -100,7 +101,7 @@ pub(super) async fn get_font_fallback( static FALLBACK_FONT_NAME: Lazy = Lazy::new(|| Regex::new(r"(?:^\w|[A-Z]|\b\w)").unwrap()); // From https://github.com/vercel/next.js/blob/1628260b88ce3052ac307a1607b6e8470188ab83/packages/next/src/server/font-utils.ts#L101 -fn format_fallback_font_name(font_family: &str) -> String { +fn format_fallback_font_name(font_family: &str) -> RcStr { let mut fallback_name = FALLBACK_FONT_NAME .replace(font_family, |caps: ®ex::Captures| { caps.iter() @@ -118,7 +119,7 @@ fn format_fallback_font_name(font_family: &str) -> String { }) .to_string(); fallback_name.retain(|c| !c.is_whitespace()); - fallback_name + fallback_name.into() } fn lookup_fallback( @@ -208,7 +209,7 @@ mod tests { assert_eq!( lookup_fallback("Inter", font_metrics, true)?, Fallback { - font_family: "Arial".to_owned(), + font_family: "Arial".into(), adjustment: Some(FontAdjustment { ascent: 0.901_989_700_374_532, descent: -0.224_836_142_322_097_4, @@ -254,7 +255,7 @@ mod tests { assert_eq!( lookup_fallback("Roboto Slab", font_metrics, true)?, Fallback { - font_family: "Times New Roman".to_owned(), + font_family: "Times New Roman".into(), adjustment: Some(FontAdjustment { ascent: 0.885_645_438_273_993_8, descent: -0.229_046_234_036_377_7, diff --git a/packages/next-swc/crates/next-core/src/next_font/google/mod.rs b/packages/next-swc/crates/next-core/src/next_font/google/mod.rs index 5046f3faa9eed..b1b225697b033 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/mod.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/mod.rs @@ -5,7 +5,7 @@ use futures::FutureExt; use indexmap::IndexMap; use indoc::formatdoc; use serde::{Deserialize, Serialize}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::{ turbo::{ tasks::{Completion, Value}, @@ -68,7 +68,7 @@ pub const USER_AGENT_FOR_GOOGLE_FONTS: &str = "Mozilla/5.0 (Macintosh; Intel Mac Chrome/104.0.0.0 Safari/537.36"; #[turbo_tasks::value(transparent)] -struct FontData(IndexMap); +struct FontData(IndexMap); #[turbo_tasks::value(shared)] pub(crate) struct NextFontGoogleReplacer { @@ -83,7 +83,7 @@ impl NextFontGoogleReplacer { } #[turbo_tasks::function] - async fn import_map_result(&self, query: String) -> Result> { + async fn import_map_result(&self, query: RcStr) -> Result> { let request_hash = get_request_hash(&query).await?; let qstr = qstring::QString::from(query.as_str()); @@ -95,8 +95,8 @@ impl NextFontGoogleReplacer { let fallback = get_font_fallback(self.project_path, options); let properties = get_font_css_properties(options, fallback).await?; let js_asset = VirtualSource::new( - next_js_file_path("internal/font/google".to_string()) - .join(format!("{}.js", get_request_id(options.font_family(), request_hash).await?)), + next_js_file_path("internal/font/google".into()) + .join(format!("{}.js", get_request_id(options.font_family(), request_hash).await?).into()), AssetContent::file(FileContent::Content( formatdoc!( r#" @@ -142,7 +142,7 @@ impl NextFontGoogleReplacer { #[turbo_tasks::value_impl] impl ImportMappingReplacement for NextFontGoogleReplacer { #[turbo_tasks::function] - fn replace(&self, _capture: String) -> Vc { + fn replace(&self, _capture: RcStr) -> Vc { ImportMapping::Ignore.into() } @@ -168,7 +168,7 @@ impl ImportMappingReplacement for NextFontGoogleReplacer { let this = &*self.await?; if can_use_next_font(this.project_path, *query).await? { - Ok(self.import_map_result(query.await?.to_string())) + Ok(self.import_map_result(query.await?.as_str().into())) } else { Ok(ImportMapResult::NoEntry.into()) } @@ -195,7 +195,7 @@ impl NextFontGoogleCssModuleReplacer { } #[turbo_tasks::function] - async fn import_map_result(&self, query: String) -> Result> { + async fn import_map_result(&self, query: RcStr) -> Result> { let request_hash = get_request_hash(&query).await?; let query_vc = Vc::cell(query); let font_data = load_font_data(self.project_path); @@ -203,18 +203,19 @@ impl NextFontGoogleCssModuleReplacer { let stylesheet_url = get_stylesheet_url_from_options(options, font_data); let scoped_font_family = get_scoped_font_family(FontFamilyType::WebFont.cell(), options.font_family()); - let css_virtual_path = next_js_file_path("internal/font/google".to_string()).join(format!( - "/{}.module.css", - get_request_id(options.font_family(), request_hash).await? - )); + let css_virtual_path = next_js_file_path("internal/font/google".into()).join( + format!( + "/{}.module.css", + get_request_id(options.font_family(), request_hash).await? + ) + .into(), + ); // When running Next.js integration tests, use the mock data available in // process.env.NEXT_FONT_GOOGLE_MOCKED_RESPONSES instead of making real // requests to Google Fonts. let env = Vc::upcast::>(CommandLineProcessEnv::new()); - let mocked_responses_path = &*env - .read("NEXT_FONT_GOOGLE_MOCKED_RESPONSES".to_string()) - .await?; + let mocked_responses_path = &*env.read("NEXT_FONT_GOOGLE_MOCKED_RESPONSES".into()).await?; let stylesheet_str = mocked_responses_path .as_ref() .map_or_else( @@ -270,7 +271,7 @@ impl NextFontGoogleCssModuleReplacer { #[turbo_tasks::value_impl] impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer { #[turbo_tasks::function] - fn replace(&self, _capture: String) -> Vc { + fn replace(&self, _capture: RcStr) -> Vc { ImportMapping::Ignore.into() } @@ -295,7 +296,7 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer { return Ok(ImportMapResult::NoEntry.into()); }; - Ok(self.import_map_result(query_vc.await?.to_string())) + Ok(self.import_map_result(query_vc.await?.to_string().into())) } } @@ -322,7 +323,7 @@ impl NextFontGoogleFontFileReplacer { #[turbo_tasks::value_impl] impl ImportMappingReplacement for NextFontGoogleFontFileReplacer { #[turbo_tasks::function] - fn replace(&self, _capture: String) -> Vc { + fn replace(&self, _capture: RcStr) -> Vc { ImportMapping::Ignore.into() } @@ -364,12 +365,13 @@ impl ImportMappingReplacement for NextFontGoogleFontFileReplacer { name.push_str(".p") } - let font_virtual_path = next_js_file_path("internal/font/google".to_string()) - .join(format!("/{}.{}", name, ext)); + let font_virtual_path = next_js_file_path("internal/font/google".into()) + .join(format!("/{}.{}", name, ext).into()); // doesn't seem ideal to download the font into a string, but probably doesn't // really matter either. - let Some(font) = fetch_from_google_fonts(Vc::cell(url), font_virtual_path).await? else { + let Some(font) = fetch_from_google_fonts(Vc::cell(url.into()), font_virtual_path).await? + else { return Ok(ImportMapResult::Result(ResolveResult::unresolveable().into()).into()); }; @@ -386,7 +388,7 @@ impl ImportMappingReplacement for NextFontGoogleFontFileReplacer { async fn load_font_data(project_root: Vc) -> Result> { let data: FontData = load_next_js_templateon( project_root, - "dist/compiled/@next/font/dist/google/font-data.json".to_string(), + "dist/compiled/@next/font/dist/google/font-data.json".into(), ) .await?; @@ -397,11 +399,11 @@ async fn load_font_data(project_root: Vc) -> Result /// font family names. #[turbo_tasks::function] async fn update_google_stylesheet( - stylesheet: Vc, + stylesheet: Vc, options: Vc, - scoped_font_family: Vc, + scoped_font_family: Vc, has_size_adjust: Vc, -) -> Result> { +) -> Result> { let options = &*options.await?; // Update font-family definitions to the scoped name @@ -439,7 +441,7 @@ async fn update_google_stylesheet( ) } - Ok(Vc::cell(stylesheet.to_string())) + Ok(Vc::cell(stylesheet.into())) } #[derive(Debug)] @@ -449,7 +451,7 @@ struct FontFile { } // https://github.com/vercel/next.js/blob/b95e45a5112e9f65e939eac9445ef550db072ea7/packages/font/src/google/find-font-files-in-css.ts -fn find_font_files_in_css(css: &str, subsets_to_preload: &[String]) -> Vec { +fn find_font_files_in_css(css: &str, subsets_to_preload: &[RcStr]) -> Vec { let mut font_files: Vec = Vec::new(); let mut current_subset = ""; @@ -482,7 +484,7 @@ fn find_font_files_in_css(css: &str, subsets_to_preload: &[String]) -> Vec, font_data: Vc, -) -> Result> { +) -> Result> { #[allow(unused_mut, unused_assignments)] // This is used in test environments let mut css_url: Option = None; #[cfg(debug_assertions)] @@ -490,27 +492,27 @@ async fn get_stylesheet_url_from_options( use turbopack_binding::turbo::tasks_env::{CommandLineProcessEnv, ProcessEnv}; let env = CommandLineProcessEnv::new(); - if let Some(url) = &*env - .read("TURBOPACK_TEST_ONLY_MOCK_SERVER".to_string()) - .await? - { + if let Some(url) = &*env.read("TURBOPACK_TEST_ONLY_MOCK_SERVER".into()).await? { css_url = Some(format!("{}/css2", url)); } } let options = options.await?; - Ok(Vc::cell(get_stylesheet_url( - css_url.as_deref().unwrap_or(GOOGLE_FONTS_STYLESHEET_URL), - &options.font_family, - &get_font_axes( - &*font_data.await?, + Ok(Vc::cell( + get_stylesheet_url( + css_url.as_deref().unwrap_or(GOOGLE_FONTS_STYLESHEET_URL), &options.font_family, - &options.weights, - &options.styles, - &options.selected_variable_axes, - )?, - &options.display, - )?)) + &get_font_axes( + &*font_data.await?, + &options.font_family, + &options.weights, + &options.styles, + &options.selected_variable_axes, + )?, + &options.display, + )? + .into(), + )) } #[turbo_tasks::function] @@ -522,20 +524,20 @@ async fn get_font_css_properties( let scoped_font_family = &*get_scoped_font_family(FontFamilyType::WebFont.cell(), options_vc.font_family()).await?; - let mut font_families = vec![format!("'{}'", scoped_font_family.clone())]; + let mut font_families = vec![format!("'{}'", scoped_font_family.clone()).into()]; let font_fallback = &*font_fallback.await?; match font_fallback { FontFallback::Manual(fonts) => { font_families.extend_from_slice(fonts); } FontFallback::Automatic(fallback) => { - font_families.push(format!("'{}'", *fallback.scoped_font_family.await?)); + font_families.push(format!("'{}'", *fallback.scoped_font_family.await?).into()); } FontFallback::Error => {} } Ok(FontCssProperties::cell(FontCssProperties { - font_family: Vc::cell(font_families.join(", ")), + font_family: Vc::cell(font_families.join(", ").into()), weight: Vc::cell(match &options.weights { FontWeights::Variable => None, FontWeights::Fixed(weights) => { @@ -543,7 +545,7 @@ async fn get_font_css_properties( // Don't set a rule for weight if multiple are requested None } else { - weights.first().map(|w| w.to_string()) + weights.first().map(|w| w.to_string().into()) } } }), @@ -559,7 +561,7 @@ async fn get_font_css_properties( #[turbo_tasks::function] async fn font_options_from_query_map( - query: Vc, + query: Vc, font_data: Vc, ) -> Result> { let query_map = qstring::QString::from(&**query.await?); @@ -578,7 +580,7 @@ async fn font_options_from_query_map( } async fn font_file_options_from_query_map( - query: Vc, + query: Vc, ) -> Result { let query_map = qstring::QString::from(&**query.await?); @@ -594,21 +596,21 @@ async fn font_file_options_from_query_map( } async fn fetch_real_stylesheet( - stylesheet_url: Vc, + stylesheet_url: Vc, css_virtual_path: Vc, -) -> Result>> { +) -> Result>> { let body = fetch_from_google_fonts(stylesheet_url, css_virtual_path).await?; Ok(body.map(|body| body.to_string())) } async fn fetch_from_google_fonts( - url: Vc, + url: Vc, virtual_path: Vc, ) -> Result>> { let result = fetch( url, - Vc::cell(Some(USER_AGENT_FOR_GOOGLE_FONTS.to_owned())), + Vc::cell(Some(USER_AGENT_FOR_GOOGLE_FONTS.into())), Vc::cell(None), ) .await?; @@ -632,19 +634,19 @@ async fn fetch_from_google_fonts( } async fn get_mock_stylesheet( - stylesheet_url: Vc, + stylesheet_url: Vc, mocked_responses_path: &str, execution_context: Vc, -) -> Result>> { +) -> Result>> { let response_path = Path::new(&mocked_responses_path); let mock_fs = Vc::upcast::>(DiskFileSystem::new( - "mock".to_string(), + "mock".into(), response_path .parent() .context("Must be valid path")? .to_str() .context("Must exist")? - .to_string(), + .into(), vec![], )); @@ -653,9 +655,8 @@ async fn get_mock_stylesheet( project_path: _, chunking_context, } = *execution_context.await?; - let context = - node_evaluate_asset_context(execution_context, None, None, "next_font".to_string()); - let loader_path = mock_fs.root().join("loader.js".to_string()); + let context = node_evaluate_asset_context(execution_context, None, None, "next_font".into()); + let loader_path = mock_fs.root().join("loader.js".into()); let mocked_response_asset = context .process( Vc::upcast(VirtualSource::new( @@ -693,8 +694,7 @@ async fn get_mock_stylesheet( match &val.try_into_single().await? { SingleValue::Single(val) => { - let val: HashMap> = - parse_json_with_source_context(val.to_str()?)?; + let val: HashMap> = parse_json_with_source_context(val.to_str()?)?; Ok(val .get(&*stylesheet_url.await?) .context("url not found")? diff --git a/packages/next-swc/crates/next-core/src/next_font/google/options.rs b/packages/next-swc/crates/next-core/src/next_font/google/options.rs index f026c80cb47d0..674c2a2504b8b 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/options.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/options.rs @@ -1,31 +1,31 @@ use anyhow::{anyhow, Context, Result}; use indexmap::{indexset, IndexMap, IndexSet}; use serde::{Deserialize, Serialize}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbo::tasks::{trace::TraceRawVcs, Value}; use super::request::{NextFontRequest, OneOrManyStrings}; const ALLOWED_DISPLAY_VALUES: &[&str] = &["auto", "block", "swap", "fallback", "optional"]; -pub(super) type FontData = IndexMap; +pub(super) type FontData = IndexMap; #[turbo_tasks::value(serialization = "auto_for_input")] #[derive(Clone, Debug, PartialOrd, Ord, Hash)] pub(super) struct NextFontGoogleOptions { /// Name of the requested font from Google. Contains literal spaces. - pub font_family: String, + pub font_family: RcStr, pub weights: FontWeights, - pub styles: Vec, - pub display: String, + pub styles: Vec, + pub display: RcStr, pub preload: bool, - pub selected_variable_axes: Option>, - pub fallback: Option>, + pub selected_variable_axes: Option>, + pub fallback: Option>, pub adjust_font_fallback: bool, /// An optional name for a css custom property (css variable) that applies /// the font family when used. - pub variable: Option, - pub subsets: Option>, + pub variable: Option, + pub subsets: Option>, } #[turbo_tasks::value_impl] @@ -36,8 +36,8 @@ impl NextFontGoogleOptions { } #[turbo_tasks::function] - pub async fn font_family(self: Vc) -> Result> { - Ok(Vc::cell((*self.await?.font_family).to_owned())) + pub async fn font_family(self: Vc) -> Result> { + Ok(Vc::cell((*self.await?.font_family).into())) } } @@ -51,15 +51,15 @@ pub(super) enum FontWeights { #[derive(Debug, PartialEq, Eq, Deserialize, Serialize, TraceRawVcs)] pub(super) struct FontDataEntry { - pub weights: Vec, - pub styles: Vec, + pub weights: Vec, + pub styles: Vec, pub axes: Option>, } #[derive(Debug, PartialEq, Deserialize, Serialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub(super) struct Axis { - pub tag: String, + pub tag: RcStr, pub min: f64, pub max: f64, } @@ -71,7 +71,7 @@ impl Eq for Axis {} // https://github.com/vercel/next.js/blob/28454c6ddbc310419467e5415aee26e48d079b46/packages/font/src/google/utils.ts#L22 pub(super) fn options_from_request( request: &NextFontRequest, - data: &IndexMap, + data: &IndexMap, ) -> Result { if request.arguments.len() > 1 { return Err(anyhow!( @@ -82,10 +82,10 @@ pub(super) fn options_from_request( let argument = request.arguments.last().cloned().unwrap_or_default(); // `import` comes from the imported symbol in JS, which separates with _ - let font_family = request.import.replace('_', " "); + let font_family: RcStr = request.import.replace('_', " ").into(); let font_data = data.get(&font_family).context("Unknown font")?; - let requested_weights: IndexSet = argument + let requested_weights: IndexSet = argument .weight .map(|w| match w { OneOrManyStrings::One(one) => indexset! {one}, @@ -102,7 +102,7 @@ pub(super) fn options_from_request( .unwrap_or_default(); let weights = if requested_weights.is_empty() { - if !font_data.weights.contains(&"variable".to_owned()) { + if !font_data.weights.contains(&"variable".into()) { return Err(anyhow!( "Missing weight for {}. Available weights: {}", font_family, @@ -145,7 +145,7 @@ pub(super) fn options_from_request( if font_data.styles.len() == 1 { styles.push(font_data.styles[0].clone()); } else { - styles.push("normal".to_owned()); + styles.push("normal".into()); } } @@ -160,9 +160,9 @@ pub(super) fn options_from_request( } } - let display = argument.display.unwrap_or_else(|| "swap".to_owned()); + let display = argument.display.unwrap_or_else(|| "swap".into()); - if !ALLOWED_DISPLAY_VALUES.contains(&display.as_ref()) { + if !ALLOWED_DISPLAY_VALUES.contains(&display.as_str()) { return Err(anyhow!( "Invalid display value {} for font {}.\nAvailable display values: {}", display, @@ -195,6 +195,7 @@ pub(super) fn options_from_request( mod tests { use anyhow::Result; use indexmap::IndexMap; + use turbo_tasks::RcStr; use turbopack_binding::turbo::tasks_fs::json::parse_json_with_source_context; use super::{options_from_request, FontDataEntry, NextFontGoogleOptions}; @@ -202,7 +203,7 @@ mod tests { #[test] fn test_errors_on_unknown_font() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -235,7 +236,7 @@ mod tests { #[test] fn test_default_values_when_no_arguments() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -260,10 +261,10 @@ mod tests { assert_eq!( options_from_request(&request, &data)?, NextFontGoogleOptions { - font_family: "ABeeZee".to_owned(), + font_family: "ABeeZee".into(), weights: FontWeights::Variable, - styles: vec!["normal".to_owned()], - display: "swap".to_owned(), + styles: vec!["normal".into()], + display: "swap".into(), preload: true, selected_variable_axes: None, fallback: None, @@ -278,7 +279,7 @@ mod tests { #[test] fn test_errors_when_no_weights_chosen_no_variable() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -314,7 +315,7 @@ mod tests { #[test] fn test_errors_on_unnecessary_weights() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -353,7 +354,7 @@ mod tests { #[test] fn test_errors_on_unvavailable_weights() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -391,7 +392,7 @@ mod tests { #[test] fn test_defaults_to_only_style_when_one_available() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -416,14 +417,14 @@ mod tests { )?; let options = options_from_request(&request, &data)?; - assert_eq!(options.styles, vec!["italic".to_owned()]); + assert_eq!(options.styles, vec![RcStr::from("italic")]); Ok(()) } #[test] fn test_defaults_to_normal_style_when_multiple() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -448,14 +449,14 @@ mod tests { )?; let options = options_from_request(&request, &data)?; - assert_eq!(options.styles, vec!["normal".to_owned()]); + assert_eq!(options.styles, vec![RcStr::from("normal")]); Ok(()) } #[test] fn test_errors_on_unknown_styles() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -495,7 +496,7 @@ mod tests { #[test] fn test_errors_on_unknown_display() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { @@ -536,7 +537,7 @@ mod tests { #[test] fn test_errors_on_axes_without_variable() -> Result<()> { - let data: IndexMap = parse_json_with_source_context( + let data: IndexMap = parse_json_with_source_context( r#" { "ABeeZee": { diff --git a/packages/next-swc/crates/next-core/src/next_font/google/request.rs b/packages/next-swc/crates/next-core/src/next_font/google/request.rs index 683982070cfa3..e312757b2f5e1 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/request.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/request.rs @@ -1,4 +1,5 @@ use serde::Deserialize; +use turbo_tasks::RcStr; /// The top-most structure encoded into the query param in requests to /// `next/font/google` generated by the next/font swc transform. e.g. @@ -6,26 +7,26 @@ use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(super) struct NextFontRequest { - pub import: String, + pub import: RcStr, pub arguments: Vec, } #[derive(Clone, Debug, Default, Deserialize)] pub(super) struct NextFontRequestArguments { pub weight: Option, - pub subsets: Option>, + pub subsets: Option>, pub style: Option, - pub display: Option, + pub display: Option, pub preload: Option, - pub axes: Option>, - pub fallback: Option>, + pub axes: Option>, + pub fallback: Option>, pub adjust_font_fallback: Option, - pub variable: Option, + pub variable: Option, } #[derive(Clone, Debug, Deserialize)] #[serde(untagged)] pub(super) enum OneOrManyStrings { - One(String), - Many(Vec), + One(RcStr), + Many(Vec), } diff --git a/packages/next-swc/crates/next-core/src/next_font/google/stylesheet.rs b/packages/next-swc/crates/next-core/src/next_font/google/stylesheet.rs index b63ca0f946a4e..7ea9badf8a1c0 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/stylesheet.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/stylesheet.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use super::FontCssProperties; use crate::next_font::{ @@ -9,16 +9,16 @@ use crate::next_font::{ #[turbo_tasks::function] pub(super) async fn build_stylesheet( - base_stylesheet: Vc>, + base_stylesheet: Vc>, font_css_properties: Vc, font_fallback: Vc, -) -> Result> { +) -> Result> { let base_stylesheet = &*base_stylesheet.await?; let mut stylesheet = base_stylesheet .as_ref() - .map_or_else(|| "".to_owned(), |s| s.to_owned()); + .map_or_else(|| "".to_owned(), |s| s.to_string()); stylesheet.push_str(&build_fallback_definition(Vc::cell(vec![font_fallback])).await?); stylesheet.push_str(&build_font_class_rules(font_css_properties).await?); - Ok(Vc::cell(stylesheet)) + Ok(Vc::cell(stylesheet.into())) } diff --git a/packages/next-swc/crates/next-core/src/next_font/google/util.rs b/packages/next-swc/crates/next-core/src/next_font/google/util.rs index 067f0bedd4b85..1717f5733c98a 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/util.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/util.rs @@ -2,14 +2,15 @@ use std::cmp::Ordering; use anyhow::{anyhow, bail, Context, Result}; use indexmap::{indexset, IndexSet}; +use turbo_tasks::RcStr; use super::options::{FontData, FontWeights}; #[derive(Debug, PartialEq)] pub(super) struct FontAxes { - pub(super) wght: IndexSet, + pub(super) wght: IndexSet, pub(super) ital: IndexSet, - pub(super) variable_axes: Option>, + pub(super) variable_axes: Option>, } #[derive(Debug, PartialEq, Eq, Hash)] @@ -23,8 +24,8 @@ pub(super) fn get_font_axes( font_data: &FontData, font_family: &str, weights: &FontWeights, - styles: &[String], - selected_variable_axes: &Option>, + styles: &[RcStr], + selected_variable_axes: &Option>, ) -> Result { let all_axes = &font_data .get(font_family) @@ -32,8 +33,8 @@ pub(super) fn get_font_axes( .axes; let ital = { - let has_italic = styles.contains(&"italic".to_owned()); - let has_normal = styles.contains(&"normal".to_owned()); + let has_italic = styles.contains(&"italic".into()); + let has_normal = styles.contains(&"normal".into()); let mut set = IndexSet::new(); if has_normal { set.insert(FontStyle::Normal); @@ -54,7 +55,7 @@ pub(super) fn get_font_axes( let definable_axes_tags = defineable_axes .iter() .map(|axis| axis.tag.to_owned()) - .collect::>(); + .collect::>(); for tag in selected_variable_axes { if !definable_axes_tags.contains(tag) { @@ -72,11 +73,13 @@ pub(super) fn get_font_axes( let mut variable_axes = vec![]; for axis in defineable_axes { if axis.tag == "wght" { - weight_axis = Some(format!("{}..{}", axis.min, axis.max)); + weight_axis = Some(format!("{}..{}", axis.min, axis.max).into()); } else if let Some(selected_variable_axes) = selected_variable_axes { if selected_variable_axes.contains(&axis.tag) { - variable_axes - .push((axis.tag.clone(), format!("{}..{}", axis.min, axis.max))); + variable_axes.push(( + axis.tag.clone(), + format!("{}..{}", axis.min, axis.max).into(), + )); } } } @@ -96,7 +99,7 @@ pub(super) fn get_font_axes( } FontWeights::Fixed(weights) => Ok(FontAxes { - wght: IndexSet::from_iter(weights.iter().map(|w| w.to_string())), + wght: IndexSet::from_iter(weights.iter().map(|w| w.to_string().into())), ital, variable_axes: None, }), @@ -320,12 +323,12 @@ mod tests { "Inter", &FontWeights::Variable, &[], - &Some(vec!["slnt".to_owned()]), + &Some(vec!["slnt".into()]), )?, FontAxes { - wght: indexset! {"100..900".to_owned()}, + wght: indexset! {"100..900".into()}, ital: indexset! {}, - variable_axes: Some(vec![("slnt".to_owned(), "-10..0".to_owned())]) + variable_axes: Some(vec![("slnt".into(), "-10..0".into())]) } ); Ok(()) @@ -361,12 +364,12 @@ mod tests { "Inter", &FontWeights::Variable, &[], - &Some(vec!["slnt".to_owned()]), + &Some(vec!["slnt".into()]), )?, FontAxes { wght: indexset! {}, ital: indexset! {}, - variable_axes: Some(vec![("slnt".to_owned(), "-10..0".to_owned())]) + variable_axes: Some(vec![("slnt".into(), "-10..0".into())]) } ); Ok(()) @@ -396,7 +399,7 @@ mod tests { assert_eq!( get_font_axes(&data, "Hind", &FontWeights::Fixed(vec![500]), &[], &None)?, FontAxes { - wght: indexset! {"500".to_owned()}, + wght: indexset! {"500".into()}, ital: indexset! {}, variable_axes: None } @@ -411,7 +414,7 @@ mod tests { GOOGLE_FONTS_STYLESHEET_URL, "Roboto Mono", &FontAxes { - wght: indexset! {"500".to_owned()}, + wght: indexset! {"500".into()}, ital: indexset! {FontStyle::Normal}, variable_axes: None }, @@ -430,12 +433,12 @@ mod tests { GOOGLE_FONTS_STYLESHEET_URL, "Roboto Serif", &FontAxes { - wght: indexset! {"500".to_owned()}, + wght: indexset! {"500".into()}, ital: indexset! {FontStyle::Normal}, variable_axes: Some(vec![ - ("GRAD".to_owned(), "-50..100".to_owned()), - ("opsz".to_owned(), "8..144".to_owned()), - ("wdth".to_owned(), "50..150".to_owned()), + ("GRAD".into(), "-50..100".into()), + ("opsz".into(), "8..144".into()), + ("wdth".into(), "50..150".into()), ]) }, "optional" @@ -453,12 +456,12 @@ mod tests { GOOGLE_FONTS_STYLESHEET_URL, "Roboto Serif", &FontAxes { - wght: indexset! {"500".to_owned(), "300".to_owned()}, + wght: indexset! {"500".into(), "300".into()}, ital: indexset! {FontStyle::Normal, FontStyle::Italic}, variable_axes: Some(vec![ - ("GRAD".to_owned(), "-50..100".to_owned()), - ("opsz".to_owned(), "8..144".to_owned()), - ("wdth".to_owned(), "50..150".to_owned()), + ("GRAD".into(), "-50..100".into()), + ("opsz".into(), "8..144".into()), + ("wdth".into(), "50..150".into()), ]) }, "optional" @@ -480,8 +483,8 @@ mod tests { wght: indexset! {}, ital: indexset! {}, variable_axes: Some(vec![ - ("EDPT".to_owned(), "0..200".to_owned()), - ("EHLT".to_owned(), "0..24".to_owned()), + ("EDPT".into(), "0..200".into()), + ("EHLT".into(), "0..24".into()), ]) }, "optional" @@ -537,7 +540,7 @@ mod tests { GOOGLE_FONTS_STYLESHEET_URL, "Hind", &FontAxes { - wght: indexset! {"500".to_owned()}, + wght: indexset! {"500".into()}, ital: indexset! {}, variable_axes: None }, diff --git a/packages/next-swc/crates/next-core/src/next_font/local/errors.rs b/packages/next-swc/crates/next-core/src/next_font/local/errors.rs index 9c3a3226f4b3b..99f1d46f86b8a 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/errors.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/errors.rs @@ -1,7 +1,8 @@ use thiserror::Error; +use turbo_tasks::RcStr; #[derive(Debug, Error)] pub enum FontError { #[error("could not find font file")] - FontFileNotFound(String), + FontFileNotFound(RcStr), } diff --git a/packages/next-swc/crates/next-core/src/next_font/local/font_fallback.rs b/packages/next-swc/crates/next-core/src/next_font/local/font_fallback.rs index 2aa3c618b84d9..cb272c388dd04 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/font_fallback.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/font_fallback.rs @@ -39,7 +39,7 @@ pub(super) async fn get_font_fallbacks( AdjustFontFallback::Arial => font_fallbacks.push( FontFallback::Automatic(AutomaticFontFallback { scoped_font_family, - local_font_family: Vc::cell("Arial".to_owned()), + local_font_family: Vc::cell("Arial".into()), adjustment: Some( get_font_adjustment(context, options_vc, &DEFAULT_SANS_SERIF_FONT).await?, ), @@ -49,7 +49,7 @@ pub(super) async fn get_font_fallbacks( AdjustFontFallback::TimesNewRoman => font_fallbacks.push( FontFallback::Automatic(AutomaticFontFallback { scoped_font_family, - local_font_family: Vc::cell("Times New Roman".to_owned()), + local_font_family: Vc::cell("Times New Roman".into()), adjustment: Some( get_font_adjustment(context, options_vc, &DEFAULT_SERIF_FONT).await?, ), @@ -164,7 +164,7 @@ fn pick_font_for_fallback_generation( // Prefer normal style if they have the same weight if used_font_distance == current_font_distance - && current_descriptor.style != Some("italic".to_owned()) + && current_descriptor.style != Some("italic".into()) { used_descriptor = current_descriptor; continue; @@ -251,6 +251,7 @@ fn parse_weight_string(weight_str: &str) -> Result { #[cfg(test)] mod tests { use anyhow::Result; + use turbo_tasks::RcStr; use crate::next_font::local::{ font_fallback::pick_font_for_fallback_generation, @@ -259,9 +260,9 @@ mod tests { fn generate_font_descriptor(weight: &FontWeight, style: &Option) -> FontDescriptor { FontDescriptor { - ext: "ttf".to_owned(), - path: "foo.ttf".to_owned(), - style: style.clone(), + ext: "ttf".into(), + path: "foo.ttf".into(), + style: style.clone().map(RcStr::from), weight: Some(weight.clone()), } } @@ -270,34 +271,34 @@ mod tests { fn test_picks_weight_closest_to_400() -> Result<()> { assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor(&FontWeight::Fixed("300".to_owned()), &None), - generate_font_descriptor(&FontWeight::Fixed("600".to_owned()), &None) + generate_font_descriptor(&FontWeight::Fixed("300".into()), &None), + generate_font_descriptor(&FontWeight::Fixed("600".into()), &None) ]))?, - &generate_font_descriptor(&FontWeight::Fixed("300".to_owned()), &None) + &generate_font_descriptor(&FontWeight::Fixed("300".into()), &None) ); assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor(&FontWeight::Fixed("200".to_owned()), &None), - generate_font_descriptor(&FontWeight::Fixed("500".to_owned()), &None) + generate_font_descriptor(&FontWeight::Fixed("200".into()), &None), + generate_font_descriptor(&FontWeight::Fixed("500".into()), &None) ]))?, - &generate_font_descriptor(&FontWeight::Fixed("500".to_owned()), &None) + &generate_font_descriptor(&FontWeight::Fixed("500".into()), &None) ); assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor(&FontWeight::Fixed("normal".to_owned()), &None), - generate_font_descriptor(&FontWeight::Fixed("700".to_owned()), &None) + generate_font_descriptor(&FontWeight::Fixed("normal".into()), &None), + generate_font_descriptor(&FontWeight::Fixed("700".into()), &None) ]))?, - &generate_font_descriptor(&FontWeight::Fixed("normal".to_owned()), &None) + &generate_font_descriptor(&FontWeight::Fixed("normal".into()), &None) ); assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor(&FontWeight::Fixed("bold".to_owned()), &None), - generate_font_descriptor(&FontWeight::Fixed("900".to_owned()), &None) + generate_font_descriptor(&FontWeight::Fixed("bold".into()), &None), + generate_font_descriptor(&FontWeight::Fixed("900".into()), &None) ]))?, - &generate_font_descriptor(&FontWeight::Fixed("bold".to_owned()), &None) + &generate_font_descriptor(&FontWeight::Fixed("bold".into()), &None) ); Ok(()) @@ -307,10 +308,10 @@ mod tests { fn test_picks_thinner_weight_if_same_distance_to_400() -> Result<()> { assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor(&FontWeight::Fixed("300".to_owned()), &None), - generate_font_descriptor(&FontWeight::Fixed("500".to_owned()), &None) + generate_font_descriptor(&FontWeight::Fixed("300".into()), &None), + generate_font_descriptor(&FontWeight::Fixed("500".into()), &None) ]))?, - &generate_font_descriptor(&FontWeight::Fixed("300".to_owned()), &None) + &generate_font_descriptor(&FontWeight::Fixed("300".into()), &None) ); Ok(()) @@ -320,53 +321,26 @@ mod tests { fn test_picks_variable_closest_to_400() -> Result<()> { assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor( - &FontWeight::Variable("100".to_owned(), "300".to_owned()), - &None - ), - generate_font_descriptor( - &FontWeight::Variable("600".to_owned(), "900".to_owned()), - &None - ) + generate_font_descriptor(&FontWeight::Variable("100".into(), "300".into()), &None), + generate_font_descriptor(&FontWeight::Variable("600".into(), "900".into()), &None) ]))?, - &generate_font_descriptor( - &FontWeight::Variable("100".to_owned(), "300".to_owned()), - &None - ) + &generate_font_descriptor(&FontWeight::Variable("100".into(), "300".into()), &None) ); assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor( - &FontWeight::Variable("100".to_owned(), "200".to_owned()), - &None - ), - generate_font_descriptor( - &FontWeight::Variable("500".to_owned(), "800".to_owned()), - &None - ) + generate_font_descriptor(&FontWeight::Variable("100".into(), "200".into()), &None), + generate_font_descriptor(&FontWeight::Variable("500".into(), "800".into()), &None) ]))?, - &generate_font_descriptor( - &FontWeight::Variable("500".to_owned(), "800".to_owned()), - &None - ) + &generate_font_descriptor(&FontWeight::Variable("500".into(), "800".into()), &None) ); assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor( - &FontWeight::Variable("100".to_owned(), "900".to_owned()), - &None - ), - generate_font_descriptor( - &FontWeight::Variable("300".to_owned(), "399".to_owned()), - &None - ) + generate_font_descriptor(&FontWeight::Variable("100".into(), "900".into()), &None), + generate_font_descriptor(&FontWeight::Variable("300".into(), "399".into()), &None) ]))?, - &generate_font_descriptor( - &FontWeight::Variable("100".to_owned(), "900".to_owned()), - &None - ) + &generate_font_descriptor(&FontWeight::Variable("100".into(), "900".into()), &None) ); Ok(()) @@ -376,19 +350,10 @@ mod tests { fn test_prefer_normal_over_italic() -> Result<()> { assert_eq!( pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor( - &FontWeight::Fixed("400".to_owned()), - &Some("normal".to_owned()) - ), - generate_font_descriptor( - &FontWeight::Fixed("400".to_owned()), - &Some("italic".to_owned()) - ) + generate_font_descriptor(&FontWeight::Fixed("400".into()), &Some("normal".into())), + generate_font_descriptor(&FontWeight::Fixed("400".into()), &Some("italic".into())) ]))?, - &generate_font_descriptor( - &FontWeight::Fixed("400".to_owned()), - &Some("normal".to_owned()) - ) + &generate_font_descriptor(&FontWeight::Fixed("400".into()), &Some("normal".into())) ); Ok(()) @@ -397,22 +362,10 @@ mod tests { #[test] fn test_errors_on_invalid_weight() -> Result<()> { match pick_font_for_fallback_generation(&FontDescriptors::Many(vec![ - generate_font_descriptor( - &FontWeight::Variable("normal".to_owned(), "bold".to_owned()), - &None, - ), - generate_font_descriptor( - &FontWeight::Variable("400".to_owned(), "bold".to_owned()), - &None, - ), - generate_font_descriptor( - &FontWeight::Variable("normal".to_owned(), "700".to_owned()), - &None, - ), - generate_font_descriptor( - &FontWeight::Variable("100".to_owned(), "abc".to_owned()), - &None, - ), + generate_font_descriptor(&FontWeight::Variable("normal".into(), "bold".into()), &None), + generate_font_descriptor(&FontWeight::Variable("400".into(), "bold".into()), &None), + generate_font_descriptor(&FontWeight::Variable("normal".into(), "700".into()), &None), + generate_font_descriptor(&FontWeight::Variable("100".into(), "abc".into()), &None), ])) { Ok(_) => panic!(), Err(err) => { diff --git a/packages/next-swc/crates/next-core/src/next_font/local/mod.rs b/packages/next-swc/crates/next-core/src/next_font/local/mod.rs index fa68b5309254e..78740b883106b 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/mod.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/mod.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Context, Result}; use indoc::formatdoc; use serde::{Deserialize, Serialize}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::glob::Glob; use turbopack_binding::{ turbo::{ @@ -48,7 +48,7 @@ pub mod util; #[derive(Clone, Debug, Serialize, Deserialize)] struct NextFontLocalFontFileOptions { - pub path: String, + pub path: RcStr, pub preload: bool, pub has_size_adjust: bool, } @@ -71,7 +71,7 @@ impl BeforeResolvePlugin for NextFontLocalResolvePlugin { #[turbo_tasks::function] async fn before_resolve_condition(&self) -> Vc { BeforeResolvePluginCondition::new(Glob::new( - "{next,@vercel/turbopack-next/internal}/font/local/*".to_string(), + "{next,@vercel/turbopack-next/internal}/font/local/*".into(), )) } @@ -119,18 +119,21 @@ impl BeforeResolvePlugin for NextFontLocalResolvePlugin { { FontResolvingIssue { origin_path: lookup_path, - font_path: Vc::cell(font_path.to_string()), + font_path: Vc::cell(font_path.clone()), } .cell() .emit(); return Ok(ResolveResultOption::some( ResolveResult::primary_with_key( - RequestKey::new(font_path.to_string()), - ResolveResultItem::Error(Vc::cell(format!( - "Font file not found: Can't resolve {}'", - font_path - ))), + RequestKey::new(font_path.clone()), + ResolveResultItem::Error(Vc::cell( + format!( + "Font file not found: Can't resolve {}'", + font_path + ) + .into(), + )), ) .into(), )); @@ -173,10 +176,13 @@ impl BeforeResolvePlugin for NextFontLocalResolvePlugin { .unwrap_or_else(|| "".to_owned()), ); let js_asset = VirtualSource::new( - lookup_path.join(format!( - "{}.js", - get_request_id(options_vc.font_family(), request_hash).await? - )), + lookup_path.join( + format!( + "{}.js", + get_request_id(options_vc.font_family(), request_hash).await? + ) + .into(), + ), AssetContent::file(FileContent::Content(file_content.into()).into()), ); @@ -188,10 +194,13 @@ impl BeforeResolvePlugin for NextFontLocalResolvePlugin { let query = query_vc.await?.to_string(); let request_hash = get_request_hash(&query).await?; let options = font_options_from_query_map(*query_vc); - let css_virtual_path = lookup_path.join(format!( - "/{}.module.css", - get_request_id(options.font_family(), request_hash).await? - )); + let css_virtual_path = lookup_path.join( + format!( + "/{}.module.css", + get_request_id(options.font_family(), request_hash).await? + ) + .into(), + ); let fallback = get_font_fallbacks(lookup_path, options); let stylesheet = build_stylesheet( @@ -229,7 +238,7 @@ impl BeforeResolvePlugin for NextFontLocalResolvePlugin { name.push_str(".p") } - let font_virtual_path = lookup_path.join(format!("/{}.{}", name, ext)); + let font_virtual_path = lookup_path.join(format!("/{}.{}", name, ext).into()); let font_file = lookup_path.join(path.clone()).read(); @@ -264,7 +273,7 @@ async fn get_font_css_properties( // Don't include values for variable fonts. These are included in font-face // definitions only. .filter(|w| !matches!(w, FontWeight::Variable(_, _))) - .map(|w| w.to_string()), + .map(|w| w.to_string().into()), }), style: Vc::cell(match &options.fonts { FontDescriptors::Many(_) => None, @@ -277,7 +286,7 @@ async fn get_font_css_properties( } #[turbo_tasks::function] -async fn font_options_from_query_map(query: Vc) -> Result> { +async fn font_options_from_query_map(query: Vc) -> Result> { let query_map = qstring::QString::from(&**query.await?); if query_map.len() != 1 { @@ -293,7 +302,7 @@ async fn font_options_from_query_map(query: Vc) -> Result, + query: Vc, ) -> Result { let query_map = qstring::QString::from(&**query.await?); @@ -310,7 +319,7 @@ async fn font_file_options_from_query_map( #[turbo_tasks::value(shared)] struct FontResolvingIssue { - font_path: Vc, + font_path: Vc, origin_path: Vc, } @@ -335,9 +344,9 @@ impl Issue for FontResolvingIssue { async fn title(self: Vc) -> Result> { let this = self.await?; Ok(StyledString::Line(vec![ - StyledString::Text("Font file not found: Can't resolve '".to_string()), - StyledString::Code(this.font_path.await?.to_string()), - StyledString::Text("'".to_string()), + StyledString::Text("Font file not found: Can't resolve '".into()), + StyledString::Code(this.font_path.await?.clone_value()), + StyledString::Text("'".into()), ]) .cell()) } diff --git a/packages/next-swc/crates/next-core/src/next_font/local/options.rs b/packages/next-swc/crates/next-core/src/next_font/local/options.rs index 74e153e6ef556..44fcddb0fcb89 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/options.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/options.rs @@ -2,7 +2,7 @@ use std::{fmt::Display, str::FromStr}; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbo::tasks::{trace::TraceRawVcs, Value}; use super::request::{ @@ -17,21 +17,21 @@ use super::request::{ pub(super) struct NextFontLocalOptions { pub fonts: FontDescriptors, pub default_weight: Option, - pub default_style: Option, + pub default_style: Option, /// The desired css `font-display` property - pub display: String, + pub display: RcStr, pub preload: bool, /// A list of manually-provided fallback fonts to be included in the /// font-family string as-is. - pub fallback: Option>, + pub fallback: Option>, /// The user's desired fallback font pub adjust_font_fallback: AdjustFontFallback, /// An optional name for a css custom property (css variable) that applies /// the font family when used. - pub variable: Option, + pub variable: Option, /// The name of the variable assigned to the results of calling the /// `localFont` function. This is used as the font family's base name. - pub variable_name: String, + pub variable_name: RcStr, } #[turbo_tasks::value_impl] @@ -42,8 +42,8 @@ impl NextFontLocalOptions { } #[turbo_tasks::function] - pub async fn font_family(self: Vc) -> Result> { - Ok(Vc::cell((*self.await?.variable_name).to_owned())) + pub async fn font_family(self: Vc) -> Result> { + Ok(Vc::cell(self.await?.variable_name.clone())) } } @@ -54,9 +54,9 @@ impl NextFontLocalOptions { )] pub(super) struct FontDescriptor { pub weight: Option, - pub style: Option, - pub path: String, - pub ext: String, + pub style: Option, + pub path: RcStr, + pub ext: RcStr, } impl FontDescriptor { @@ -66,10 +66,10 @@ impl FontDescriptor { .rsplit('.') .next() .context("Extension required")? - .to_owned(); + .into(); Ok(Self { - path: src_descriptor.path.to_owned(), + path: src_descriptor.path.clone(), weight: src_descriptor .weight .as_ref() @@ -96,8 +96,8 @@ pub(super) enum FontDescriptors { Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Hash, TraceRawVcs, )] pub(super) enum FontWeight { - Variable(String, String), - Fixed(String), + Variable(RcStr, RcStr), + Fixed(RcStr), } pub struct ParseFontWeightErr; @@ -106,9 +106,9 @@ impl FromStr for FontWeight { fn from_str(weight_str: &str) -> std::result::Result { if let Some((start, end)) = weight_str.split_once(' ') { - Ok(FontWeight::Variable(start.to_owned(), end.to_owned())) + Ok(FontWeight::Variable(start.into(), end.into())) } else { - Ok(FontWeight::Fixed(weight_str.to_owned())) + Ok(FontWeight::Fixed(weight_str.into())) } } } @@ -120,7 +120,7 @@ impl Display for FontWeight { "{}", match self { Self::Variable(start, end) => format!("{} {}", start, end), - Self::Fixed(val) => val.to_owned(), + Self::Fixed(val) => val.to_string(), } ) } @@ -151,16 +151,16 @@ pub(super) fn options_from_request(request: &NextFontLocalRequest) -> Result { FontDescriptors::One(FontDescriptor::from_src_request(&SrcDescriptor { - path: path.to_owned(), - weight: weight.to_owned(), - style: style.to_owned(), + path: path.as_str().into(), + weight: weight.as_deref().map(RcStr::from), + style: style.as_deref().map(RcStr::from), })?) } }; Ok(NextFontLocalOptions { fonts, - display: display.to_owned(), + display: display.as_str().into(), preload: preload.to_owned(), fallback: fallback.to_owned(), adjust_font_fallback: adjust_font_fallback.to_owned(), @@ -201,19 +201,19 @@ mod tests { options_from_request(&request)?, NextFontLocalOptions { fonts: FontDescriptors::One(FontDescriptor { - path: "./Roboto-Regular.ttf".to_owned(), + path: "./Roboto-Regular.ttf".into(), weight: None, style: None, - ext: "ttf".to_owned(), + ext: "ttf".into(), }), default_style: None, default_weight: None, - display: "swap".to_owned(), + display: "swap".into(), preload: true, fallback: None, adjust_font_fallback: AdjustFontFallback::Arial, variable: None, - variable_name: "myFont".to_owned() + variable_name: "myFont".into() }, ); @@ -249,26 +249,26 @@ mod tests { NextFontLocalOptions { fonts: FontDescriptors::Many(vec![ FontDescriptor { - path: "./Roboto-Regular.ttf".to_owned(), - weight: Some(FontWeight::Fixed("400".to_owned())), - style: Some("normal".to_owned()), - ext: "ttf".to_owned(), + path: "./Roboto-Regular.ttf".into(), + weight: Some(FontWeight::Fixed("400".into())), + style: Some("normal".into()), + ext: "ttf".into(), }, FontDescriptor { - path: "./Roboto-Italic.ttf".to_owned(), - weight: Some(FontWeight::Fixed("400".to_owned())), + path: "./Roboto-Italic.ttf".into(), + weight: Some(FontWeight::Fixed("400".into())), style: None, - ext: "ttf".to_owned(), + ext: "ttf".into(), } ]), - default_weight: Some(FontWeight::Fixed("300".to_owned())), - default_style: Some("italic".to_owned()), - display: "swap".to_owned(), + default_weight: Some(FontWeight::Fixed("300".into())), + default_style: Some("italic".into()), + display: "swap".into(), preload: true, fallback: None, adjust_font_fallback: AdjustFontFallback::Arial, variable: None, - variable_name: "myFont".to_owned() + variable_name: "myFont".into() }, ); @@ -329,19 +329,19 @@ mod tests { options_from_request(&request)?, NextFontLocalOptions { fonts: FontDescriptors::One(FontDescriptor { - path: "./Roboto-Regular.woff".to_owned(), - weight: Some(FontWeight::Fixed("500".to_owned())), - style: Some("italic".to_owned()), - ext: "woff".to_owned(), + path: "./Roboto-Regular.woff".into(), + weight: Some(FontWeight::Fixed("500".into())), + style: Some("italic".into()), + ext: "woff".into(), }), - default_style: Some("italic".to_owned()), - default_weight: Some(FontWeight::Fixed("500".to_owned())), - display: "optional".to_owned(), + default_style: Some("italic".into()), + default_weight: Some(FontWeight::Fixed("500".into())), + display: "optional".into(), preload: false, - fallback: Some(vec!["Fallback".to_owned()]), + fallback: Some(vec!["Fallback".into()]), adjust_font_fallback: AdjustFontFallback::TimesNewRoman, - variable: Some("myvar".to_owned()), - variable_name: "myFont".to_owned() + variable: Some("myvar".into()), + variable_name: "myFont".into() }, ); diff --git a/packages/next-swc/crates/next-core/src/next_font/local/request.rs b/packages/next-swc/crates/next-core/src/next_font/local/request.rs index aa6710c108f69..b04bde2deb416 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/request.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/request.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use turbo_tasks::RcStr; use turbopack_binding::turbo::tasks::trace::TraceRawVcs; /// The top-most structure encoded into the query param in requests to @@ -8,40 +9,40 @@ use turbopack_binding::turbo::tasks::trace::TraceRawVcs; #[serde(rename_all = "camelCase")] pub(super) struct NextFontLocalRequest { pub arguments: (NextFontLocalRequestArguments,), - pub variable_name: String, + pub variable_name: RcStr, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(super) struct NextFontLocalRequestArguments { pub src: SrcRequest, - pub weight: Option, - pub style: Option, + pub weight: Option, + pub style: Option, #[serde(default = "default_display")] - pub display: String, + pub display: RcStr, #[serde(default = "default_preload")] pub preload: bool, - pub fallback: Option>, + pub fallback: Option>, #[serde( default = "default_adjust_font_fallback", deserialize_with = "deserialize_adjust_font_fallback" )] pub adjust_font_fallback: AdjustFontFallback, - pub variable: Option, + pub variable: Option, } #[derive(Debug, Deserialize)] #[serde(untagged)] pub(super) enum SrcRequest { - One(String), + One(RcStr), Many(Vec), } #[derive(Clone, Debug, Deserialize)] pub(super) struct SrcDescriptor { - pub path: String, - pub weight: Option, - pub style: Option, + pub path: RcStr, + pub weight: Option, + pub style: Option, } /// The user's desired fallback font @@ -99,8 +100,8 @@ fn default_preload() -> bool { true } -fn default_display() -> String { - "swap".to_owned() +fn default_display() -> RcStr { + "swap".into() } #[cfg(test)] diff --git a/packages/next-swc/crates/next-core/src/next_font/local/stylesheet.rs b/packages/next-swc/crates/next-core/src/next_font/local/stylesheet.rs index 1067c4029aa5c..c0167abe39dca 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/stylesheet.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/stylesheet.rs @@ -1,6 +1,6 @@ use anyhow::{bail, Result}; use indoc::formatdoc; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use super::options::{FontDescriptors, NextFontLocalOptions}; use crate::next_font::{ @@ -15,30 +15,33 @@ pub(super) async fn build_stylesheet( options: Vc, fallbacks: Vc, css_properties: Vc, -) -> Result> { +) -> Result> { let scoped_font_family = get_scoped_font_family(FontFamilyType::WebFont.cell(), options.font_family()); - Ok(Vc::cell(formatdoc!( - r#" + Ok(Vc::cell( + formatdoc!( + r#" {} {} {} "#, - *build_font_face_definitions(scoped_font_family, options, fallbacks.has_size_adjust()) - .await?, - (*build_fallback_definition(fallbacks).await?), - *build_font_class_rules(css_properties).await? - ))) + *build_font_face_definitions(scoped_font_family, options, fallbacks.has_size_adjust()) + .await?, + (*build_fallback_definition(fallbacks).await?), + *build_font_class_rules(css_properties).await? + ) + .into(), + )) } /// Builds a string of `@font-face` definitions for each local font file #[turbo_tasks::function] pub(super) async fn build_font_face_definitions( - scoped_font_family: Vc, + scoped_font_family: Vc, options: Vc, has_size_adjust: Vc, -) -> Result> { +) -> Result> { let options = &*options.await?; let mut definitions = String::new(); @@ -83,7 +86,7 @@ pub(super) async fn build_font_face_definitions( )); } - Ok(Vc::cell(definitions)) + Ok(Vc::cell(definitions.into())) } /// Used as e.g. `format('woff')` in `src` properties in `@font-face` diff --git a/packages/next-swc/crates/next-core/src/next_font/local/util.rs b/packages/next-swc/crates/next-core/src/next_font/local/util.rs index ff3b7c295237a..63d3c89ff39f2 100644 --- a/packages/next-swc/crates/next-core/src/next_font/local/util.rs +++ b/packages/next-swc/crates/next-core/src/next_font/local/util.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use super::options::NextFontLocalOptions; use crate::next_font::{ @@ -12,16 +12,17 @@ use crate::next_font::{ pub(super) async fn build_font_family_string( options: Vc, font_fallbacks: Vc, -) -> Result> { +) -> Result> { let mut font_families = vec![format!( "'{}'", *get_scoped_font_family(FontFamilyType::WebFont.cell(), options.font_family(),).await? - )]; + ) + .into()]; for font_fallback in &*font_fallbacks.await? { match &*font_fallback.await? { FontFallback::Automatic(fallback) => { - font_families.push(format!("'{}'", *fallback.scoped_font_family.await?)); + font_families.push(format!("'{}'", *fallback.scoped_font_family.await?).into()); } FontFallback::Manual(fallbacks) => { font_families.extend_from_slice(fallbacks); @@ -30,5 +31,5 @@ pub(super) async fn build_font_family_string( } } - Ok(Vc::cell(font_families.join(", "))) + Ok(Vc::cell(font_families.join(", ").into())) } diff --git a/packages/next-swc/crates/next-core/src/next_font/stylesheet.rs b/packages/next-swc/crates/next-core/src/next_font/stylesheet.rs index 64d02a44b1b31..307a53d5e1a31 100644 --- a/packages/next-swc/crates/next-core/src/next_font/stylesheet.rs +++ b/packages/next-swc/crates/next-core/src/next_font/stylesheet.rs @@ -1,6 +1,6 @@ use anyhow::Result; use indoc::formatdoc; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use super::{ font_fallback::{FontFallback, FontFallbacks}, @@ -9,7 +9,7 @@ use super::{ /// Builds `@font-face` stylesheet definition for a given FontFallback #[turbo_tasks::function] -pub(crate) async fn build_fallback_definition(fallbacks: Vc) -> Result> { +pub(crate) async fn build_fallback_definition(fallbacks: Vc) -> Result> { let mut res = "".to_owned(); for fallback_vc in &*fallbacks.await? { if let FontFallback::Automatic(fallback) = &*fallback_vc.await? { @@ -44,13 +44,13 @@ pub(crate) async fn build_fallback_definition(fallbacks: Vc) -> R } } - Ok(Vc::cell(res)) + Ok(Vc::cell(res.into())) } #[turbo_tasks::function] pub(super) async fn build_font_class_rules( css_properties: Vc, -) -> Result> { +) -> Result> { let css_properties = &*css_properties.await?; let font_family_string = &*css_properties.font_family.await?; @@ -88,7 +88,7 @@ pub(super) async fn build_font_class_rules( )) } - Ok(Vc::cell(rules)) + Ok(Vc::cell(rules.into())) } fn format_fixed_percentage(value: f64) -> String { diff --git a/packages/next-swc/crates/next-core/src/next_font/util.rs b/packages/next-swc/crates/next-core/src/next_font/util.rs index 2c0186707cd9f..58ec8e45ccab8 100644 --- a/packages/next-swc/crates/next-core/src/next_font/util.rs +++ b/packages/next-swc/crates/next-core/src/next_font/util.rs @@ -1,6 +1,6 @@ use anyhow::{Context, Result}; use serde::Deserialize; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::{json::parse_json_with_source_context, FileSystemPath}; use turbopack_binding::{ turbo::tasks_hash::hash_xxh3_hash64, @@ -14,10 +14,10 @@ use super::issue::NextFontIssue; /// module. #[turbo_tasks::value(shared)] pub(crate) struct FontCssProperties { - pub font_family: Vc, - pub weight: Vc>, - pub style: Vc>, - pub variable: Vc>, + pub font_family: Vc, + pub weight: Vc>, + pub style: Vc>, + pub variable: Vc>, } /// A hash of the requested querymap derived from how the user invoked @@ -52,35 +52,38 @@ pub(crate) enum FontFamilyType { #[turbo_tasks::function] pub(crate) async fn get_scoped_font_family( ty: Vc, - font_family_name: Vc, -) -> Result> { + font_family_name: Vc, +) -> Result> { let font_family_base = font_family_name.await?.to_string(); let font_family_name = match &*ty.await? { FontFamilyType::WebFont => font_family_base, FontFamilyType::Fallback => format!("{} Fallback", font_family_base), }; - Ok(Vc::cell(font_family_name)) + Ok(Vc::cell(font_family_name.into())) } /// Returns a [Vc] for [String] uniquely identifying the request for the font. #[turbo_tasks::function] -pub async fn get_request_id(font_family: Vc, request_hash: u32) -> Result> { - Ok(Vc::cell(format!( - "{}_{:x?}", - font_family.await?.to_lowercase().replace(' ', "_"), - request_hash - ))) +pub async fn get_request_id(font_family: Vc, request_hash: u32) -> Result> { + Ok(Vc::cell( + format!( + "{}_{:x?}", + font_family.await?.to_lowercase().replace(' ', "_"), + request_hash + ) + .into(), + )) } #[derive(Debug, Deserialize)] struct HasPath { - path: String, + path: RcStr, } pub(crate) async fn can_use_next_font( project_path: Vc, - query: Vc, + query: Vc, ) -> Result { let query_map = qstring::QString::from(&**query.await?); let request: HasPath = parse_json_with_source_context( @@ -98,12 +101,12 @@ pub(crate) async fn can_use_next_font( NextFontIssue { path, title: StyledString::Line(vec![ - StyledString::Code("next/font:".to_string()), - StyledString::Text(" error:".to_string()), + StyledString::Code("next/font:".into()), + StyledString::Text(" error:".into()), ]) .cell(), description: StyledString::Line(vec![ - StyledString::Text("Cannot be used within ".to_string()), + StyledString::Text("Cannot be used within ".into()), StyledString::Code(request.path), ]) .cell(), diff --git a/packages/next-swc/crates/next-core/src/next_image/module.rs b/packages/next-swc/crates/next-core/src/next_image/module.rs index 459c6517cc6aa..f0c2ee7e60168 100644 --- a/packages/next-swc/crates/next-core/src/next_image/module.rs +++ b/packages/next-swc/crates/next-core/src/next_image/module.rs @@ -57,7 +57,7 @@ impl StructuredImageModuleType { .cell(), ), Value::new(ReferenceType::Internal(Vc::cell(indexmap!( - "IMAGE".to_string() => Vc::upcast(static_asset) + "IMAGE".into() => Vc::upcast(static_asset) )))), ) .module(); diff --git a/packages/next-swc/crates/next-core/src/next_image/source_asset.rs b/packages/next-swc/crates/next-core/src/next_image/source_asset.rs index 7148b0fbc029d..b046670133a44 100644 --- a/packages/next-swc/crates/next-core/src/next_image/source_asset.rs +++ b/packages/next-swc/crates/next-core/src/next_image/source_asset.rs @@ -1,7 +1,7 @@ use std::io::Write; use anyhow::{bail, Result}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::{ turbo::tasks_fs::{rope::RopeBuilder, FileContent}, turbopack::{ @@ -17,8 +17,8 @@ use turbopack_binding::{ use super::module::BlurPlaceholderMode; -fn modifier() -> Vc { - Vc::cell("structured image object".to_string()) +fn modifier() -> Vc { + Vc::cell("structured image object".into()) } #[turbo_tasks::function] @@ -45,7 +45,7 @@ impl Source for StructuredImageFileSource { self.image .ident() .with_modifier(modifier()) - .rename_as("*.mjs".to_string()) + .rename_as("*.mjs".into()) } } diff --git a/packages/next-swc/crates/next-core/src/next_import_map.rs b/packages/next-swc/crates/next-core/src/next_import_map.rs index 61199c2af4c88..27cc8b0216a84 100644 --- a/packages/next-swc/crates/next-core/src/next_import_map.rs +++ b/packages/next-swc/crates/next-core/src/next_import_map.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashMap}; use anyhow::{Context, Result}; use indexmap::{indexmap, IndexMap}; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbopack_binding::{ turbo::tasks_fs::{FileSystem, FileSystemPath}, turbopack::{ @@ -249,11 +249,7 @@ pub fn get_next_build_import_map() -> Vc { import_map.insert_exact_alias("styled-jsx", external); import_map.insert_exact_alias( "styled-jsx/style", - ImportMapping::External( - Some("styled-jsx/style.js".to_string()), - ExternalType::CommonJs, - ) - .cell(), + ImportMapping::External(Some("styled-jsx/style.js".into()), ExternalType::CommonJs).cell(), ); import_map.insert_wildcard_alias("styled-jsx/", external); @@ -330,11 +326,8 @@ pub async fn get_next_server_import_map( import_map.insert_exact_alias("styled-jsx", external); import_map.insert_exact_alias( "styled-jsx/style", - ImportMapping::External( - Some("styled-jsx/style.js".to_string()), - ExternalType::CommonJs, - ) - .cell(), + ImportMapping::External(Some("styled-jsx/style.js".into()), ExternalType::CommonJs) + .cell(), ); import_map.insert_wildcard_alias("styled-jsx/", external); // TODO: we should not bundle next/dist/build/utils in the pages renderer at all @@ -739,8 +732,8 @@ async fn rsc_aliases( Ok(()) } -pub fn mdx_import_source_file() -> String { - format!("{VIRTUAL_PACKAGE_NAME}/mdx-import-source") +pub fn mdx_import_source_file() -> RcStr { + format!("{VIRTUAL_PACKAGE_NAME}/mdx-import-source").into() } // Insert aliases for Next.js stubs of fetch, object-assign, and url @@ -905,9 +898,7 @@ pub async fn get_next_package(context_directory: Vc) -> Result( alias_options: Vc, conditions: [&'static str; N], ) -> Result<()> { - let conditions = BTreeMap::from(conditions.map(|c| (c.to_string(), ConditionValue::Set))); + let conditions = BTreeMap::from(conditions.map(|c| (c.into(), ConditionValue::Set))); for (alias, value) in &alias_options.await? { if let Some(mapping) = export_value_to_import_mapping(value, &conditions, project_path) { import_map.insert_alias(alias, mapping); @@ -934,7 +925,7 @@ pub async fn insert_alias_option( fn export_value_to_import_mapping( value: &SubpathValue, - conditions: &BTreeMap, + conditions: &BTreeMap, project_path: Vc, ) -> Option> { let mut result = Vec::new(); @@ -948,13 +939,13 @@ fn export_value_to_import_mapping( None } else { Some(if result.len() == 1 { - ImportMapping::PrimaryAlternative(result[0].0.to_string(), Some(project_path)).cell() + ImportMapping::PrimaryAlternative(result[0].0.into(), Some(project_path)).cell() } else { ImportMapping::Alternatives( result .iter() .map(|(m, _)| { - ImportMapping::PrimaryAlternative(m.to_string(), Some(project_path)).cell() + ImportMapping::PrimaryAlternative((*m).into(), Some(project_path)).cell() }) .collect(), ) @@ -990,7 +981,10 @@ fn insert_alias_to_alternatives<'a>( alias: impl Into + 'a, alternatives: Vec>, ) { - import_map.insert_exact_alias(alias, ImportMapping::Alternatives(alternatives).into()); + import_map.insert_exact_alias( + alias.into(), + ImportMapping::Alternatives(alternatives).into(), + ); } /// Inserts an alias to an import mapping into an import map. @@ -1001,7 +995,7 @@ fn insert_package_alias( ) { import_map.insert_wildcard_alias( prefix, - ImportMapping::PrimaryAlternative("./*".to_string(), Some(package_root)).cell(), + ImportMapping::PrimaryAlternative("./*".into(), Some(package_root)).cell(), ); } @@ -1017,11 +1011,11 @@ fn insert_turbopack_dev_alias(import_map: &mut ImportMap) { /// Creates a direct import mapping to the result of resolving a request /// in a context. fn request_to_import_mapping(context_path: Vc, request: &str) -> Vc { - ImportMapping::PrimaryAlternative(request.to_string(), Some(context_path)).cell() + ImportMapping::PrimaryAlternative(request.into(), Some(context_path)).cell() } /// Creates a direct import mapping to the result of resolving an external /// request. fn external_request_to_import_mapping(request: &str) -> Vc { - ImportMapping::External(Some(request.to_string()), ExternalType::CommonJs).into() + ImportMapping::External(Some(request.into()), ExternalType::CommonJs).into() } diff --git a/packages/next-swc/crates/next-core/src/next_manifests/client_reference_manifest.rs b/packages/next-swc/crates/next-core/src/next_manifests/client_reference_manifest.rs index 2d9e831b41c5a..082f35cba9808 100644 --- a/packages/next-swc/crates/next-core/src/next_manifests/client_reference_manifest.rs +++ b/packages/next-swc/crates/next-core/src/next_manifests/client_reference_manifest.rs @@ -1,6 +1,6 @@ use anyhow::Result; use indoc::formatdoc; -use turbo_tasks::{TryJoinIterExt, ValueToString, Vc}; +use turbo_tasks::{RcStr, TryJoinIterExt, ValueToString, Vc}; use turbo_tasks_fs::{File, FileSystemPath}; use turbopack_binding::turbopack::{ core::{ @@ -26,7 +26,7 @@ impl ClientReferenceManifest { pub async fn build_output( node_root: Vc, client_relative_path: Vc, - entry_name: String, + entry_name: RcStr, client_references: Vc, client_references_chunks: Vc, client_chunking_context: Vc>, @@ -39,7 +39,7 @@ impl ClientReferenceManifest { .computed_asset_prefix() .await? .as_ref() - .map(|p| p.to_owned()) + .map(|p| p.clone()) .unwrap_or_default(); entry_manifest.module_loading.cross_origin = next_config @@ -90,6 +90,7 @@ impl ClientReferenceManifest { // It's possible that a chunk also emits CSS files, that will // be handled separatedly. .filter(|path| path.ends_with(".js")) + .map(RcStr::from) .collect::>() } else { Vec::new() @@ -97,7 +98,7 @@ impl ClientReferenceManifest { entry_manifest.client_modules.module_exports.insert( get_client_reference_module_key(&server_path, "*"), ManifestNodeEntry { - name: "*".to_string(), + name: "*".into(), id: (&*client_module_id).into(), chunks: client_chunks_paths, // TODO(WEB-434) @@ -134,15 +135,16 @@ impl ClientReferenceManifest { .iter() .filter_map(|chunk_path| node_root_ref.get_path_to(chunk_path)) .map(ToString::to_string) + .map(RcStr::from) .collect::>() } else { Vec::new() }; let mut ssr_manifest_node = ManifestNode::default(); ssr_manifest_node.module_exports.insert( - "*".to_string(), + "*".into(), ManifestNodeEntry { - name: "*".to_string(), + name: "*".into(), id: (&*ssr_module_id).into(), chunks: ssr_chunks_paths, // TODO(WEB-434) @@ -180,7 +182,7 @@ impl ClientReferenceManifest { let server_component_name = server_component .server_path() - .with_extension("".to_string()) + .with_extension("".into()) .to_string() .await?; @@ -196,7 +198,7 @@ impl ClientReferenceManifest { for chunk_path in client_chunks_paths { if let Some(path) = client_relative_path.get_path_to(&chunk_path) { - let path = path.to_string(); + let path = path.into(); if chunk_path.extension_ref() == Some("css") { entry_css_files.insert(path); } else { @@ -215,9 +217,10 @@ impl ClientReferenceManifest { // path still (same as webpack does) let normalized_manifest_entry = entry_name.replace("%5F", "_"); Ok(Vc::upcast(VirtualOutputAsset::new( - node_root.join(format!( - "server/app{normalized_manifest_entry}_client-reference-manifest.js", - )), + node_root.join( + format!("server/app{normalized_manifest_entry}_client-reference-manifest.js",) + .into(), + ), AssetContent::file( File::from(formatdoc! { r#" @@ -243,10 +246,10 @@ impl From<&TurbopackModuleId> for ModuleId { } /// See next.js/packages/next/src/lib/client-reference.ts -pub fn get_client_reference_module_key(server_path: &str, export_name: &str) -> String { +pub fn get_client_reference_module_key(server_path: &str, export_name: &str) -> RcStr { if export_name == "*" { - server_path.to_string() + server_path.into() } else { - format!("{}#{}", server_path, export_name) + format!("{}#{}", server_path, export_name).into() } } diff --git a/packages/next-swc/crates/next-core/src/next_manifests/mod.rs b/packages/next-swc/crates/next-core/src/next_manifests/mod.rs index 409078f8e0a00..b77e4d350972f 100644 --- a/packages/next-swc/crates/next-core/src/next_manifests/mod.rs +++ b/packages/next-swc/crates/next-core/src/next_manifests/mod.rs @@ -6,26 +6,26 @@ use std::collections::HashMap; use indexmap::{IndexMap, IndexSet}; use serde::{Deserialize, Serialize}; -use turbo_tasks::{trace::TraceRawVcs, TaskInput}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, TaskInput}; use crate::next_config::{CrossOriginConfig, Rewrites, RouteHas}; #[derive(Serialize, Default, Debug)] pub struct PagesManifest { #[serde(flatten)] - pub pages: HashMap, + pub pages: HashMap, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct BuildManifest { - pub dev_files: Vec, - pub amp_dev_files: Vec, - pub polyfill_files: Vec, - pub low_priority_files: Vec, - pub root_main_files: Vec, - pub pages: HashMap>, - pub amp_first_pages: Vec, + pub dev_files: Vec, + pub amp_dev_files: Vec, + pub polyfill_files: Vec, + pub low_priority_files: Vec, + pub root_main_files: Vec, + pub pages: HashMap>, + pub amp_first_pages: Vec, } #[derive(Serialize, Debug)] @@ -62,14 +62,14 @@ impl Default for MiddlewaresManifest { pub struct MiddlewareMatcher { // When skipped next.js with fill that during merging. #[serde(skip_serializing_if = "Option::is_none")] - pub regexp: Option, + pub regexp: Option, #[serde(skip_serializing_if = "bool_is_true")] pub locale: bool, #[serde(skip_serializing_if = "Option::is_none")] pub has: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub missing: Option>, - pub original_source: String, + pub original_source: RcStr, } fn bool_is_true(b: &bool) -> bool { @@ -78,9 +78,9 @@ fn bool_is_true(b: &bool) -> bool { #[derive(Serialize, Default, Debug)] pub struct EdgeFunctionDefinition { - pub files: Vec, - pub name: String, - pub page: String, + pub files: Vec, + pub name: RcStr, + pub page: RcStr, pub matchers: Vec, #[serde(skip_serializing_if = "Vec::is_empty")] pub wasm: Vec, @@ -88,13 +88,13 @@ pub struct EdgeFunctionDefinition { pub assets: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub regions: Option, - pub env: IndexMap, + pub env: IndexMap, } #[derive(Serialize, Default, Debug)] pub struct InstrumentationDefinition { - pub files: Vec, - pub name: String, + pub files: Vec, + pub name: RcStr, #[serde(skip_serializing_if = "Vec::is_empty")] pub wasm: Vec, #[serde(skip_serializing_if = "Vec::is_empty")] @@ -104,44 +104,44 @@ pub struct InstrumentationDefinition { #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct AssetBinding { - pub name: String, - pub file_path: String, + pub name: RcStr, + pub file_path: RcStr, } #[derive(Serialize, Debug)] #[serde(untagged)] pub enum Regions { - Multiple(Vec), - Single(String), + Multiple(Vec), + Single(RcStr), } #[derive(Serialize, Default, Debug)] pub struct MiddlewaresManifestV2 { - pub sorted_middleware: Vec, - pub middleware: HashMap, + pub sorted_middleware: Vec, + pub middleware: HashMap, pub instrumentation: Option, - pub functions: HashMap, + pub functions: HashMap, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct ReactLoadableManifest { #[serde(flatten)] - pub manifest: HashMap, + pub manifest: HashMap, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct ReactLoadableManifestEntry { pub id: u32, - pub files: Vec, + pub files: Vec, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct NextFontManifest { - pub pages: HashMap>, - pub app: HashMap>, + pub pages: HashMap>, + pub app: HashMap>, pub app_using_size_adjust: bool, pub pages_using_size_adjust: bool, } @@ -162,8 +162,8 @@ pub struct AppPathsManifest { #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct LoadableManifest { - pub id: String, - pub files: Vec, + pub id: RcStr, + pub files: Vec, } #[derive(Serialize, Default, Debug)] @@ -228,16 +228,16 @@ pub struct ClientReferenceManifest { pub edge_ssr_module_mapping: HashMap, /// Mapping of server component path to required CSS client chunks. #[serde(rename = "entryCSSFiles")] - pub entry_css_files: HashMap>, + pub entry_css_files: HashMap>, /// Mapping of server component path to required JS client chunks. #[serde(rename = "entryJSFiles")] - pub entry_js_files: HashMap>, + pub entry_js_files: HashMap>, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct ModuleLoading { - pub prefix: String, + pub prefix: RcStr, pub cross_origin: Option, } @@ -246,7 +246,7 @@ pub struct ModuleLoading { pub struct ManifestNode { /// Mapping of export name to manifest node entry. #[serde(flatten)] - pub module_exports: HashMap, + pub module_exports: HashMap, } #[derive(Serialize, Debug, Clone)] @@ -255,9 +255,9 @@ pub struct ManifestNodeEntry { /// Turbopack module ID. pub id: ModuleId, /// Export name. - pub name: String, + pub name: RcStr, /// Chunks for the module. JS and CSS. - pub chunks: Vec, + pub chunks: Vec, // TODO(WEB-434) pub r#async: bool, } @@ -266,7 +266,7 @@ pub struct ManifestNodeEntry { #[serde(rename_all = "camelCase")] #[serde(untagged)] pub enum ModuleId { - String(String), + String(RcStr), Number(u64), } @@ -277,14 +277,14 @@ pub struct FontManifest(pub Vec); #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct FontManifestEntry { - pub url: String, - pub content: String, + pub url: RcStr, + pub content: RcStr, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct AppBuildManifest { - pub pages: HashMap>, + pub pages: HashMap>, } // TODO(alexkirsz) Unify with the one for dev. @@ -294,8 +294,8 @@ pub struct ClientBuildManifest<'a> { #[serde(rename = "__rewrites")] pub rewrites: &'a Rewrites, - pub sorted_pages: &'a [String], + pub sorted_pages: &'a [RcStr], #[serde(flatten)] - pub pages: HashMap>, + pub pages: HashMap>, } diff --git a/packages/next-swc/crates/next-core/src/next_pages/page_entry.rs b/packages/next-swc/crates/next-core/src/next_pages/page_entry.rs index 4800d5b772d4d..00d12456212fd 100644 --- a/packages/next-swc/crates/next-core/src/next_pages/page_entry.rs +++ b/packages/next-swc/crates/next-core/src/next_pages/page_entry.rs @@ -3,7 +3,7 @@ use std::io::Write; use anyhow::{bail, Result}; use indexmap::indexmap; use serde::Serialize; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::FileSystemPath; use turbopack_binding::{ turbo::{ @@ -33,12 +33,12 @@ use crate::{ #[turbo_tasks::function] pub async fn create_page_ssr_entry_module( - pathname: Vc, + pathname: Vc, reference_type: Value, project_root: Vc, ssr_module_context: Vc>, source: Vc>, - next_original_name: Vc, + next_original_name: Vc, pages_structure: Vc, runtime: NextRuntime, next_config: Vc, @@ -76,12 +76,12 @@ pub async fn create_page_ssr_entry_module( let mut replacements = indexmap! { "VAR_DEFINITION_PAGE" => definition_page.clone(), "VAR_DEFINITION_PATHNAME" => definition_pathname.clone(), - "VAR_USERLAND" => INNER.to_string(), + "VAR_USERLAND" => INNER.into(), }; if reference_type == ReferenceType::Entry(EntryReferenceSubType::Page) { - replacements.insert("VAR_MODULE_DOCUMENT", INNER_DOCUMENT.to_string()); - replacements.insert("VAR_MODULE_APP", INNER_APP.to_string()); + replacements.insert("VAR_MODULE_DOCUMENT", INNER_DOCUMENT.into()); + replacements.insert("VAR_MODULE_APP", INNER_APP.into()); } // Load the file from the next.js codebase. @@ -119,12 +119,12 @@ pub async fn create_page_ssr_entry_module( } let mut inner_assets = indexmap! { - INNER.to_string() => ssr_module, + INNER.into() => ssr_module, }; if reference_type == ReferenceType::Entry(EntryReferenceSubType::Page) { inner_assets.insert( - INNER_DOCUMENT.to_string(), + INNER_DOCUMENT.into(), process_global_item( pages_structure.document(), Value::new(reference_type.clone()), @@ -132,7 +132,7 @@ pub async fn create_page_ssr_entry_module( ), ); inner_assets.insert( - INNER_APP.to_string(), + INNER_APP.into(), process_global_item( pages_structure.app(), Value::new(reference_type.clone()), @@ -165,7 +165,7 @@ pub async fn create_page_ssr_entry_module( ssr_module_context, project_root, ssr_module, - definition_pathname.to_string(), + definition_pathname.clone(), ); } } @@ -197,8 +197,8 @@ async fn wrap_edge_page( context: Vc>, project_root: Vc, entry: Vc>, - page: String, - pathname: String, + page: RcStr, + pathname: RcStr, reference_type: Value, pages_structure: Vc, next_config: Vc, @@ -226,20 +226,20 @@ async fn wrap_edge_page( "edge-ssr.js", project_root, indexmap! { - "VAR_USERLAND" => INNER.to_string(), + "VAR_USERLAND" => INNER.into(), "VAR_PAGE" => pathname.clone(), - "VAR_MODULE_DOCUMENT" => INNER_DOCUMENT.to_string(), - "VAR_MODULE_APP" => INNER_APP.to_string(), - "VAR_MODULE_GLOBAL_ERROR" => INNER_ERROR.to_string(), + "VAR_MODULE_DOCUMENT" => INNER_DOCUMENT.into(), + "VAR_MODULE_APP" => INNER_APP.into(), + "VAR_MODULE_GLOBAL_ERROR" => INNER_ERROR.into(), }, indexmap! { - "pagesType" => StringifyJs("pages").to_string(), - "sriEnabled" => serde_json::Value::Bool(sri_enabled).to_string(), - "nextConfig" => serde_json::to_string(next_config)?, - "dev" => serde_json::Value::Bool(dev).to_string(), - "pageRouteModuleOptions" => serde_json::to_string(&get_route_module_options(page.clone(), pathname.clone()))?, - "errorRouteModuleOptions" => serde_json::to_string(&get_route_module_options("/_error".to_string(), "/_error".to_string()))?, - "user500RouteModuleOptions" => serde_json::to_string(&get_route_module_options("/500".to_string(), "/500".to_string()))?, + "pagesType" => StringifyJs("pages").to_string().into(), + "sriEnabled" => serde_json::Value::Bool(sri_enabled).to_string().into(), + "nextConfig" => serde_json::to_string(next_config)?.into(), + "dev" => serde_json::Value::Bool(dev).to_string().into(), + "pageRouteModuleOptions" => serde_json::to_string(&get_route_module_options(page.clone(), pathname.clone()))?.into(), + "errorRouteModuleOptions" => serde_json::to_string(&get_route_module_options("/_error".into(), "/_error".into()))?.into(), + "user500RouteModuleOptions" => serde_json::to_string(&get_route_module_options("/500".into(), "/500".into()))?.into(), }, indexmap! { // TODO @@ -250,10 +250,10 @@ async fn wrap_edge_page( .await?; let inner_assets = indexmap! { - INNER.to_string() => entry, - INNER_DOCUMENT.to_string() => process_global_item(pages_structure.document(), reference_type.clone(), context), - INNER_APP.to_string() => process_global_item(pages_structure.app(), reference_type.clone(), context), - INNER_ERROR.to_string() => process_global_item(pages_structure.error(), reference_type.clone(), context), + INNER.into() => entry, + INNER_DOCUMENT.into() => process_global_item(pages_structure.document(), reference_type.clone(), context), + INNER_APP.into() => process_global_item(pages_structure.app(), reference_type.clone(), context), + INNER_ERROR.into() => process_global_item(pages_structure.error(), reference_type.clone(), context), }; let wrapped = context @@ -278,27 +278,27 @@ struct PartialRouteModuleOptions { #[derive(Serialize)] struct RouteDefinition { - kind: String, - bundle_path: String, - filename: String, + kind: RcStr, + bundle_path: RcStr, + filename: RcStr, /// Describes the pathname including all internal modifiers such as /// intercepting routes, parallel routes and route/page suffixes that are /// not part of the pathname. - page: String, + page: RcStr, /// The pathname (including dynamic placeholders) for a route to resolve. - pathname: String, + pathname: RcStr, } -fn get_route_module_options(page: String, pathname: String) -> PartialRouteModuleOptions { +fn get_route_module_options(page: RcStr, pathname: RcStr) -> PartialRouteModuleOptions { PartialRouteModuleOptions { definition: RouteDefinition { - kind: "PAGES".to_string(), + kind: "PAGES".into(), page, pathname, // The following aren't used in production. - bundle_path: "".to_string(), - filename: "".to_string(), + bundle_path: "".into(), + filename: "".into(), }, } } diff --git a/packages/next-swc/crates/next-core/src/next_route_matcher/mod.rs b/packages/next-swc/crates/next-core/src/next_route_matcher/mod.rs index 2c1f32288d94d..d7e404088f319 100644 --- a/packages/next-swc/crates/next-core/src/next_route_matcher/mod.rs +++ b/packages/next-swc/crates/next-core/src/next_route_matcher/mod.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbopack::node::route_matcher::{Params, RouteMatcher, RouteMatcherRef}; use self::{ @@ -15,13 +15,13 @@ mod prefix_suffix; /// A route matcher that matches a path against an exact route. #[turbo_tasks::value] pub(crate) struct NextExactMatcher { - path: Vc, + path: Vc, } #[turbo_tasks::value_impl] impl NextExactMatcher { #[turbo_tasks::function] - pub async fn new(path: Vc) -> Result> { + pub async fn new(path: Vc) -> Result> { Ok(Self::cell(NextExactMatcher { path })) } } @@ -29,12 +29,12 @@ impl NextExactMatcher { #[turbo_tasks::value_impl] impl RouteMatcher for NextExactMatcher { #[turbo_tasks::function] - async fn matches(&self, path: String) -> Result> { + async fn matches(&self, path: RcStr) -> Result> { Ok(Vc::cell(path == *self.path.await?)) } #[turbo_tasks::function] - async fn params(&self, path: String) -> Result> { + async fn params(&self, path: RcStr) -> Result> { Ok(Vc::cell(if path == *self.path.await? { Some(Default::default()) } else { @@ -53,7 +53,7 @@ pub(crate) struct NextParamsMatcher { #[turbo_tasks::value_impl] impl NextParamsMatcher { #[turbo_tasks::function] - pub async fn new(path: Vc) -> Result> { + pub async fn new(path: Vc) -> Result> { Ok(Self::cell(NextParamsMatcher { matcher: build_path_regex(path.await?.as_str())?, })) @@ -63,12 +63,12 @@ impl NextParamsMatcher { #[turbo_tasks::value_impl] impl RouteMatcher for NextParamsMatcher { #[turbo_tasks::function] - fn matches(&self, path: String) -> Vc { + fn matches(&self, path: RcStr) -> Vc { Vc::cell(self.matcher.matches(&path)) } #[turbo_tasks::function] - fn params(&self, path: String) -> Vc { + fn params(&self, path: RcStr) -> Vc { Params::cell(self.matcher.params(&path)) } } @@ -86,7 +86,7 @@ impl NextPrefixSuffixParamsMatcher { /// Converts a filename within the server root into a regular expression /// with named capture groups for every dynamic segment. #[turbo_tasks::function] - pub async fn new(path: Vc, prefix: String, suffix: String) -> Result> { + pub async fn new(path: Vc, prefix: RcStr, suffix: RcStr) -> Result> { Ok(Self::cell(NextPrefixSuffixParamsMatcher { matcher: PrefixSuffixMatcher::new( prefix.to_string(), @@ -100,12 +100,12 @@ impl NextPrefixSuffixParamsMatcher { #[turbo_tasks::value_impl] impl RouteMatcher for NextPrefixSuffixParamsMatcher { #[turbo_tasks::function] - fn matches(&self, path: String) -> Vc { + fn matches(&self, path: RcStr) -> Vc { Vc::cell(self.matcher.matches(&path)) } #[turbo_tasks::function] - fn params(&self, path: String) -> Vc { + fn params(&self, path: RcStr) -> Vc { Params::cell(self.matcher.params(&path)) } } @@ -128,12 +128,12 @@ impl NextFallbackMatcher { #[turbo_tasks::value_impl] impl RouteMatcher for NextFallbackMatcher { #[turbo_tasks::function] - fn matches(&self, path: String) -> Vc { + fn matches(&self, path: RcStr) -> Vc { Vc::cell(self.matcher.matches(&path)) } #[turbo_tasks::function] - fn params(&self, path: String) -> Vc { + fn params(&self, path: RcStr) -> Vc { Params::cell(self.matcher.params(&path)) } } diff --git a/packages/next-swc/crates/next-core/src/next_route_matcher/path_regex.rs b/packages/next-swc/crates/next-core/src/next_route_matcher/path_regex.rs index 863944a592d61..64333ab40d708 100644 --- a/packages/next-swc/crates/next-core/src/next_route_matcher/path_regex.rs +++ b/packages/next-swc/crates/next-core/src/next_route_matcher/path_regex.rs @@ -47,14 +47,14 @@ impl RouteMatcherRef for PathRegex { } let value = capture.get(idx + 1)?; Some(( - param.name.to_string(), + param.name.as_str().into(), match param.kind { - NamedParamKind::Single => Param::Single(value.as_str().to_string()), + NamedParamKind::Single => Param::Single(value.as_str().into()), NamedParamKind::Multi => Param::Multi( value .as_str() .split('/') - .map(|segment| segment.to_string()) + .map(|segment| segment.into()) .collect(), ), }, diff --git a/packages/next-swc/crates/next-core/src/next_server/context.rs b/packages/next-swc/crates/next-core/src/next_server/context.rs index c934abde0daba..897d76ea868c1 100644 --- a/packages/next-swc/crates/next-core/src/next_server/context.rs +++ b/packages/next-swc/crates/next-core/src/next_server/context.rs @@ -2,7 +2,7 @@ use std::iter::once; use anyhow::{bail, Result}; use indexmap::IndexMap; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbo_tasks_fs::FileSystem; use turbopack_binding::{ turbo::{ @@ -89,12 +89,12 @@ pub enum ServerContextType { }, AppRSC { app_dir: Vc, - ecmascript_client_reference_transition_name: Option>, + ecmascript_client_reference_transition_name: Option>, client_transition: Option>>, }, AppRoute { app_dir: Vc, - ecmascript_client_reference_transition_name: Option>, + ecmascript_client_reference_transition_name: Option>, }, Middleware, Instrumentation, @@ -139,9 +139,9 @@ pub async fn get_server_resolve_options_context( ); // Always load these predefined packages as external. - let mut external_packages: Vec = load_next_js_templateon( + let mut external_packages: Vec = load_next_js_templateon( project_path, - "dist/lib/server-external-packages.json".to_string(), + "dist/lib/server-external-packages.json".into(), ) .await?; @@ -174,16 +174,17 @@ pub async fn get_server_resolve_options_context( ); let ty = ty.into_value(); - let mut custom_conditions = vec![mode.await?.condition().to_string()]; + let mut custom_conditions = vec![mode.await?.condition().to_string().into()]; custom_conditions.extend( NextRuntime::NodeJs .conditions() .iter() - .map(ToString::to_string), + .map(ToString::to_string) + .map(RcStr::from), ); if ty.supports_react_server() { - custom_conditions.push("react-server".to_string()); + custom_conditions.push("react-server".into()); }; let external_cjs_modules_plugin = if *next_config.bundle_pages_router_dependencies().await? { @@ -305,17 +306,17 @@ pub async fn get_server_resolve_options_context( .cell()) } -fn defines(define_env: &IndexMap) -> CompileTimeDefines { +fn defines(define_env: &IndexMap) -> CompileTimeDefines { let mut defines = IndexMap::new(); for (k, v) in define_env { defines - .entry(k.split('.').map(|s| s.to_string()).collect::>()) + .entry(k.split('.').map(|s| s.into()).collect::>()) .or_insert_with(|| { let val = serde_json::from_str(v); match val { Ok(serde_json::Value::Bool(v)) => CompileTimeDefineValue::Bool(v), - Ok(serde_json::Value::String(v)) => CompileTimeDefineValue::String(v), + Ok(serde_json::Value::String(v)) => CompileTimeDefineValue::String(v.into()), _ => CompileTimeDefineValue::JSON(v.clone()), } }); @@ -402,8 +403,14 @@ pub async fn get_server_module_options_context( let enable_postcss_transform = Some(postcss_transform_options.cell()); let enable_foreign_postcss_transform = Some(postcss_foreign_transform_options.cell()); - let mut conditions = vec![mode.await?.condition().to_string()]; - conditions.extend(next_runtime.conditions().iter().map(ToString::to_string)); + let mut conditions = vec![mode.await?.condition().into()]; + conditions.extend( + next_runtime + .conditions() + .iter() + .map(ToString::to_string) + .map(RcStr::from), + ); // A separate webpack rules will be applied to codes matching // foreign_code_context_condition. This allows to import codes from @@ -416,7 +423,7 @@ pub async fn get_server_module_options_context( conditions .iter() .cloned() - .chain(once("foreign".to_string())) + .chain(once("foreign".into())) .collect(), ) .await?; @@ -809,7 +816,7 @@ pub async fn get_server_chunking_context_with_client_assets( project_path: Vc, node_root: Vc, client_root: Vc, - asset_prefix: Vc>, + asset_prefix: Vc>, environment: Vc, ) -> Result> { let next_mode = mode.await?; @@ -820,8 +827,8 @@ pub async fn get_server_chunking_context_with_client_assets( project_path, node_root, client_root, - node_root.join("server/chunks/ssr".to_string()), - client_root.join("static/media".to_string()), + node_root.join("server/chunks/ssr".into()), + client_root.join("static/media".into()), environment, next_mode.runtime_type(), ) @@ -845,8 +852,8 @@ pub async fn get_server_chunking_context( project_path, node_root, node_root, - node_root.join("server/chunks".to_string()), - node_root.join("server/assets".to_string()), + node_root.join("server/chunks".into()), + node_root.join("server/assets".into()), environment, next_mode.runtime_type(), ) diff --git a/packages/next-swc/crates/next-core/src/next_server/resolve.rs b/packages/next-swc/crates/next-core/src/next_server/resolve.rs index 48e80a1fac8a5..f9a9e5eb6504c 100644 --- a/packages/next-swc/crates/next-core/src/next_server/resolve.rs +++ b/packages/next-swc/crates/next-core/src/next_server/resolve.rs @@ -1,6 +1,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; -use turbo_tasks::{trace::TraceRawVcs, Value, Vc}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, Value, Vc}; use turbopack_binding::{ turbo::tasks_fs::{glob::Glob, FileJsonContent, FileSystemPath}, turbopack::core::{ @@ -24,9 +24,9 @@ use turbopack_binding::{ #[turbo_tasks::value(into = "shared")] pub enum ExternalPredicate { /// Mark all modules as external if they're not listed in the list. - AllExcept(Vc>), + AllExcept(Vc>), /// Only mark modules listed as external. - Only(Vc>), + Only(Vc>), } /// Mark modules as external, so they're resolved at runtime instead of bundled. @@ -62,7 +62,7 @@ impl ExternalCjsModulesResolvePlugin { #[turbo_tasks::function] fn condition(root: Vc) -> Vc { - AfterResolvePluginCondition::new(root, Glob::new("**/node_modules/**".to_string())) + AfterResolvePluginCondition::new(root, Glob::new("**/node_modules/**".into())) } #[turbo_tasks::value_impl] @@ -91,7 +91,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { // from https://github.com/vercel/next.js/blob/8d1c619ad650f5d147207f267441caf12acd91d1/packages/next/src/build/handle-externals.ts#L188 let never_external_regex = lazy_regex::regex!("^(?:private-next-pages\\/|next\\/(?:dist\\/pages\\/|(?:app|document|link|image|legacy\\/image|constants|dynamic|script|navigation|headers|router)$)|string-hash|private-next-rsc-action-validate|private-next-rsc-action-client-wrapper|private-next-rsc-server-reference$)"); - let request_str = request_value.request(); + let request_str = request_value.request().map(|v| v.into_owned()); let Some(mut request_str) = request_str else { return Ok(ResolveResultOption::none()); }; @@ -189,12 +189,12 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { Ok(FileType::UnsupportedExtension) } - let unable_to_externalize = |request_str: String, reason: &str| { + let unable_to_externalize = |request_str: RcStr, reason: &str| { if must_be_external { UnableToExternalize { file_path: fs_path, request: request_str, - reason: reason.to_string(), + reason: reason.into(), } .cell() .emit(); @@ -224,12 +224,12 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { // have an extension in the request we try to append ".js" // automatically request_str.push_str(".js"); - request = request.append_path(".js".to_string()).resolve().await?; + request = request.append_path(".js".into()).resolve().await?; continue; } // this can't resolve with node.js from the original location, so bundle it return unable_to_externalize( - request_str, + request_str.into(), "The request could not be resolved by Node.js from the importing module. The \ way Node.js resolves modules is slightly different from the way Next.js \ resolves modules. Next.js was able to resolve it, while Node.js would not be \ @@ -249,7 +249,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { let Some(result) = *node_resolved.first_source().await? else { // this can't resolve with node.js from the project directory, so bundle it return unable_to_externalize( - request_str, + request_str.into(), "The request could not be resolved by Node.js from the project \ directory.\nPackages that should be external need to be installed in the project \ directory, so they can be resolved from the output files.\nTry to install the \ @@ -276,7 +276,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { let FindContextFileResult::Found(package_json_file, _) = *package_json_file.await? else { return unable_to_externalize( - request_str, + request_str.into(), "The package.json of the package resolved from the project directory can't be \ found.", ); @@ -285,7 +285,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { *package_json_from_original_location.await? else { return unable_to_externalize( - request_str, + request_str.into(), "The package.json of the package can't be found.", ); }; @@ -293,7 +293,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { &*package_json_file.read_json().await? else { return unable_to_externalize( - request_str, + request_str.into(), "The package.json of the package resolved from project directory can't be \ parsed.", ); @@ -302,7 +302,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { &*package_json_from_original_location.read_json().await? else { return unable_to_externalize( - request_str, + request_str.into(), "The package.json of the package can't be parsed.", ); }; @@ -311,7 +311,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { package_json_file.get("version"), ) else { return unable_to_externalize( - request_str, + request_str.into(), "The package.json of the package has not name or version.", ); }; @@ -320,7 +320,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { package_json_from_original_location.get("version"), ) else { return unable_to_externalize( - request_str, + request_str.into(), "The package.json of the package resolved from project directory has not name \ or version.", ); @@ -328,7 +328,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { if (name, version) != (name2, version2) { // this can't resolve with node.js from the original location, so bundle it return unable_to_externalize( - request_str, + request_str.into(), "The package resolves to a different version when requested from the project \ directory compared to the package requested from the importing module.\nMake \ sure to install the same version of the package in both locations.", @@ -342,19 +342,22 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { (FileType::UnsupportedExtension, _) => { // unsupported file type, bundle it unable_to_externalize( - request_str, + request_str.into(), "Only .mjs, .cjs, .js, .json, or .node can be handled by Node.js.", ) } (FileType::InvalidPackageJson, _) => { // invalid package.json, bundle it - unable_to_externalize(request_str, "The package.json can't be found or parsed.") + unable_to_externalize( + request_str.into(), + "The package.json can't be found or parsed.", + ) } (FileType::CommonJs, false) => { // mark as external Ok(ResolveResultOption::some( ResolveResult::primary(ResolveResultItem::External( - request_str, + request_str.into(), ExternalType::CommonJs, )) .cell(), @@ -391,7 +394,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { // mark as external Ok(ResolveResultOption::some( ResolveResult::primary(ResolveResultItem::External( - request_str, + request_str.into(), if resolves_equal { ExternalType::CommonJs } else { @@ -406,7 +409,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { // mark as external Ok(ResolveResultOption::some( ResolveResult::primary(ResolveResultItem::External( - request_str, + request_str.into(), ExternalType::EcmaScriptModule, )) .cell(), @@ -416,7 +419,7 @@ impl AfterResolvePlugin for ExternalCjsModulesResolvePlugin { // even with require() this resolves to a ESM, // which would break node.js, bundle it unable_to_externalize( - request_str, + request_str.into(), "The package seems invalid. require() resolves to a EcmaScript module, which \ would result in an error in Node.js.", ) @@ -436,17 +439,14 @@ pub struct PackagesGlobs { pub struct OptionPackagesGlobs(Option); #[turbo_tasks::function] -async fn packages_glob(packages: Vc>) -> Result> { +async fn packages_glob(packages: Vc>) -> Result> { let packages = packages.await?; if packages.is_empty() { return Ok(Vc::cell(None)); } - let path_glob = Glob::new(format!("**/node_modules/{{{}}}/**", packages.join(","))); - let request_glob = Glob::new(format!( - "{{{},{}/**}}", - packages.join(","), - packages.join("/**,") - )); + let path_glob = Glob::new(format!("**/node_modules/{{{}}}/**", packages.join(",")).into()); + let request_glob = + Glob::new(format!("{{{},{}/**}}", packages.join(","), packages.join("/**,")).into()); Ok(Vc::cell(Some(PackagesGlobs { path_glob: path_glob.resolve().await?, request_glob: request_glob.resolve().await?, @@ -456,8 +456,8 @@ async fn packages_glob(packages: Vc>) -> Result, - request: String, - reason: String, + request: RcStr, + reason: RcStr, } #[turbo_tasks::value_impl] @@ -476,17 +476,18 @@ impl Issue for UnableToExternalize { .take(2) .intersperse("/") .collect::() + .into() } else if let Some((package, _)) = request.split_once('/') { - package.to_string() + package.into() } else { - request.to_string() + request.clone() }; Ok(StyledString::Line(vec![ - StyledString::Text("Package ".to_string()), + StyledString::Text("Package ".into()), StyledString::Code(package), - StyledString::Text(" (".to_string()), - StyledString::Code("serverExternalPackages".to_string()), - StyledString::Text(" or default list) can't be external".to_string()), + StyledString::Text(" (".into()), + StyledString::Code("serverExternalPackages".into()), + StyledString::Text(" or default list) can't be external".into()), ]) .cell()) } @@ -506,15 +507,13 @@ impl Issue for UnableToExternalize { Vc::cell(Some( StyledString::Stack(vec![ StyledString::Line(vec![ - StyledString::Text("The request ".to_string()), - StyledString::Code(self.request.to_string()), - StyledString::Text(" matches ".to_string()), - StyledString::Code("serverExternalPackages".to_string()), - StyledString::Text( - " (or the default list), but it can't be external:".to_string(), - ), + StyledString::Text("The request ".into()), + StyledString::Code(self.request.clone()), + StyledString::Text(" matches ".into()), + StyledString::Code("serverExternalPackages".into()), + StyledString::Text(" (or the default list), but it can't be external:".into()), ]), - StyledString::Line(vec![StyledString::Text(self.reason.to_string())]), + StyledString::Line(vec![StyledString::Text(self.reason.clone())]), ]) .cell(), )) diff --git a/packages/next-swc/crates/next-core/src/next_server_component/server_component_module.rs b/packages/next-swc/crates/next-core/src/next_server_component/server_component_module.rs index 8aeb725046a91..c875fcf26c4d5 100644 --- a/packages/next-swc/crates/next-core/src/next_server_component/server_component_module.rs +++ b/packages/next-swc/crates/next-core/src/next_server_component/server_component_module.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use anyhow::{bail, Result}; use indoc::formatdoc; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::FileSystemPath; use turbopack_binding::turbopack::{ core::{ @@ -28,8 +28,8 @@ use turbopack_binding::turbopack::{ use super::server_component_reference::NextServerComponentModuleReference; #[turbo_tasks::function] -fn modifier() -> Vc { - Vc::cell("Next.js server component".to_string()) +fn modifier() -> Vc { + Vc::cell("Next.js server component".into()) } #[turbo_tasks::value(shared)] @@ -96,7 +96,7 @@ impl EcmascriptChunkPlaceable for NextServerComponentModule { #[turbo_tasks::function] fn get_exports(&self) -> Vc { let exports = BTreeMap::from([( - "default".to_string(), + "default".into(), EsmExport::ImportedNamespace(Vc::upcast(NextServerComponentModuleReference::new( Vc::upcast(self.module), ))), diff --git a/packages/next-swc/crates/next-core/src/next_server_component/server_component_reference.rs b/packages/next-swc/crates/next-core/src/next_server_component/server_component_reference.rs index b82d1055c9f3d..c5b005994fccf 100644 --- a/packages/next-swc/crates/next-core/src/next_server_component/server_component_reference.rs +++ b/packages/next-swc/crates/next-core/src/next_server_component/server_component_reference.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use turbo_tasks::{ValueToString, Vc}; +use turbo_tasks::{RcStr, ValueToString, Vc}; use turbopack_binding::turbopack::core::{ chunk::ChunkableModuleReference, module::Module, reference::ModuleReference, resolve::ModuleResolveResult, @@ -21,11 +21,14 @@ impl NextServerComponentModuleReference { #[turbo_tasks::value_impl] impl ValueToString for NextServerComponentModuleReference { #[turbo_tasks::function] - async fn to_string(&self) -> Result> { - Ok(Vc::cell(format!( - "Next.js server component {}", - self.asset.ident().to_string().await? - ))) + async fn to_string(&self) -> Result> { + Ok(Vc::cell( + format!( + "Next.js server component {}", + self.asset.ident().to_string().await? + ) + .into(), + )) } } diff --git a/packages/next-swc/crates/next-core/src/next_server_component/server_component_transition.rs b/packages/next-swc/crates/next-core/src/next_server_component/server_component_transition.rs index 18df3fb6d81d8..646c04ad4af71 100644 --- a/packages/next-swc/crates/next-core/src/next_server_component/server_component_transition.rs +++ b/packages/next-swc/crates/next-core/src/next_server_component/server_component_transition.rs @@ -1,5 +1,5 @@ use anyhow::{bail, Result}; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbopack_binding::turbopack::{ core::module::Module, ecmascript::chunk::EcmascriptChunkPlaceable, @@ -29,7 +29,7 @@ impl NextServerComponentTransition { #[turbo_tasks::value_impl] impl Transition for NextServerComponentTransition { #[turbo_tasks::function] - fn process_layer(self: Vc, layer: Vc) -> Vc { + fn process_layer(self: Vc, layer: Vc) -> Vc { layer } diff --git a/packages/next-swc/crates/next-core/src/next_shared/resolve.rs b/packages/next-swc/crates/next-core/src/next_shared/resolve.rs index f048e50ccf27b..e9792821859be 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/resolve.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/resolve.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use anyhow::Result; use lazy_static::lazy_static; -use turbo_tasks::{Value, Vc}; +use turbo_tasks::{RcStr, Value, Vc}; use turbo_tasks_fs::glob::Glob; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, @@ -63,7 +63,7 @@ impl UnsupportedModulesResolvePlugin { impl AfterResolvePlugin for UnsupportedModulesResolvePlugin { #[turbo_tasks::function] fn after_resolve_condition(&self) -> Vc { - AfterResolvePluginCondition::new(self.root.root(), Glob::new("**".to_string())) + AfterResolvePluginCondition::new(self.root.root(), Glob::new("**".into())) } #[turbo_tasks::function] @@ -85,7 +85,7 @@ impl AfterResolvePlugin for UnsupportedModulesResolvePlugin { if UNSUPPORTED_PACKAGES.contains(module.as_str()) { UnsupportedModuleIssue { file_path, - package: module.into(), + package: module.clone(), package_path: None, } .cell() @@ -96,7 +96,7 @@ impl AfterResolvePlugin for UnsupportedModulesResolvePlugin { if UNSUPPORTED_PACKAGE_PATHS.contains(&(module, path)) { UnsupportedModuleIssue { file_path, - package: module.into(), + package: module.clone(), package_path: Some(path.to_owned()), } .cell() @@ -112,7 +112,7 @@ impl AfterResolvePlugin for UnsupportedModulesResolvePlugin { #[turbo_tasks::value(shared)] pub struct InvalidImportModuleIssue { pub file_path: Vc, - pub messages: Vec, + pub messages: Vec, pub skip_context_message: bool, } @@ -146,17 +146,15 @@ impl Issue for InvalidImportModuleIssue { if !self.skip_context_message { //[TODO]: how do we get the import trace? - messages.push(format!( - "The error was caused by importing '{}'", - raw_context.path - )); + messages + .push(format!("The error was caused by importing '{}'", raw_context.path).into()); } Ok(Vc::cell(Some( StyledString::Line( messages .iter() - .map(|v| StyledString::Text(format!("{}\n", v))) + .map(|v| StyledString::Text(format!("{}\n", v).into())) .collect::>(), ) .cell(), @@ -171,14 +169,14 @@ impl Issue for InvalidImportModuleIssue { #[turbo_tasks::value] pub(crate) struct InvalidImportResolvePlugin { root: Vc, - invalid_import: String, - message: Vec, + invalid_import: RcStr, + message: Vec, } #[turbo_tasks::value_impl] impl InvalidImportResolvePlugin { #[turbo_tasks::function] - pub fn new(root: Vc, invalid_import: String, message: Vec) -> Vc { + pub fn new(root: Vc, invalid_import: RcStr, message: Vec) -> Vc { InvalidImportResolvePlugin { root, invalid_import, @@ -192,7 +190,7 @@ impl InvalidImportResolvePlugin { impl AfterResolvePlugin for InvalidImportResolvePlugin { #[turbo_tasks::function] fn after_resolve_condition(&self) -> Vc { - AfterResolvePluginCondition::new(self.root.root(), Glob::new("**".to_string())) + AfterResolvePluginCondition::new(self.root.root(), Glob::new("**".into())) } #[turbo_tasks::function] @@ -228,11 +226,11 @@ pub(crate) fn get_invalid_client_only_resolve_plugin( ) -> Vc { InvalidImportResolvePlugin::new( root, - "client-only".to_string(), + "client-only".into(), vec![ "'client-only' cannot be imported from a Server Component module. It should only be \ used from a Client Component." - .to_string(), + .into(), ], ) } @@ -245,11 +243,11 @@ pub(crate) fn get_invalid_server_only_resolve_plugin( ) -> Vc { InvalidImportResolvePlugin::new( root, - "server-only".to_string(), + "server-only".into(), vec![ "'server-only' cannot be imported from a Client Component module. It should only be \ used from a Server Component." - .to_string(), + .into(), ], ) } @@ -260,15 +258,15 @@ pub(crate) fn get_invalid_styled_jsx_resolve_plugin( ) -> Vc { InvalidImportResolvePlugin::new( root, - "styled-jsx".to_string(), + "styled-jsx".into(), vec![ "'client-only' cannot be imported from a Server Component module. It should only be \ used from a Client Component." - .to_string(), + .into(), "The error was caused by using 'styled-jsx'. It only works in a Client Component but \ none of its parents are marked with \"use client\", so they're Server Components by \ default." - .to_string(), + .into(), ], ) } @@ -292,7 +290,7 @@ impl AfterResolvePlugin for NextExternalResolvePlugin { fn after_resolve_condition(&self) -> Vc { AfterResolvePluginCondition::new( self.root.root(), - Glob::new("**/next/dist/**/*.{external,runtime.dev,runtime.prod}.js".to_string()), + Glob::new("**/next/dist/**/*.{external,runtime.dev,runtime.prod}.js".into()), ) } @@ -310,10 +308,10 @@ impl AfterResolvePlugin for NextExternalResolvePlugin { // always be found since the glob pattern above is specific enough. let starting_index = path.find("next/dist").unwrap(); // Replace '/esm/' with '/' to match the CJS version of the file. - let modified_path = &path[starting_index..].replace("/esm/", "/"); + let modified_path = path[starting_index..].replace("/esm/", "/"); Ok(Vc::cell(Some( ResolveResult::primary(ResolveResultItem::External( - modified_path.to_string(), + modified_path.into(), ExternalType::CommonJs, )) .into(), @@ -342,7 +340,7 @@ impl AfterResolvePlugin for NextNodeSharedRuntimeResolvePlugin { fn after_resolve_condition(&self) -> Vc { AfterResolvePluginCondition::new( self.root.root(), - Glob::new("**/next/dist/**/*.shared-runtime.js".to_string()), + Glob::new("**/next/dist/**/*.shared-runtime.js".into()), ) } @@ -378,7 +376,9 @@ impl AfterResolvePlugin for NextNodeSharedRuntimeResolvePlugin { let (base, _) = path.split_at(starting_index); - let new_path = fs_path.root().join(format!("{base}/{resource_request}")); + let new_path = fs_path + .root() + .join(format!("{base}/{resource_request}").into()); Ok(Vc::cell(Some( ResolveResult::source(Vc::upcast(FileSource::new(new_path))).into(), @@ -405,7 +405,7 @@ impl ModuleFeatureReportResolvePlugin { impl AfterResolvePlugin for ModuleFeatureReportResolvePlugin { #[turbo_tasks::function] fn after_resolve_condition(&self) -> Vc { - AfterResolvePluginCondition::new(self.root.root(), Glob::new("**".to_string())) + AfterResolvePluginCondition::new(self.root.root(), Glob::new("**".into())) } #[turbo_tasks::function] @@ -430,7 +430,7 @@ impl AfterResolvePlugin for ModuleFeatureReportResolvePlugin { .find(|sub_path| path.is_match(sub_path)); if let Some(sub_path) = sub_path { - ModuleFeatureTelemetry::new(format!("{}{}", module, sub_path), 1) + ModuleFeatureTelemetry::new(format!("{}{}", module, sub_path).into(), 1) .cell() .emit(); } @@ -460,7 +460,7 @@ impl AfterResolvePlugin for NextSharedRuntimeResolvePlugin { fn after_resolve_condition(&self) -> Vc { AfterResolvePluginCondition::new( self.root.root(), - Glob::new("**/next/dist/esm/**/*.shared-runtime.js".to_string()), + Glob::new("**/next/dist/esm/**/*.shared-runtime.js".into()), ) } @@ -474,7 +474,7 @@ impl AfterResolvePlugin for NextSharedRuntimeResolvePlugin { ) -> Result> { let raw_fs_path = &*fs_path.await?; let modified_path = raw_fs_path.path.replace("next/dist/esm/", "next/dist/"); - let new_path = fs_path.root().join(modified_path); + let new_path = fs_path.root().join(modified_path.into()); Ok(Vc::cell(Some( ResolveResult::source(Vc::upcast(FileSource::new(new_path))).into(), ))) diff --git a/packages/next-swc/crates/next-core/src/next_shared/transforms/next_page_static_info.rs b/packages/next-swc/crates/next-core/src/next_shared/transforms/next_page_static_info.rs index 2c31c4154f4fc..2ad25f3ba40fe 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/transforms/next_page_static_info.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/transforms/next_page_static_info.rs @@ -166,7 +166,7 @@ impl Issue for PageStaticInfoIssue { StyledString::Line( self.messages .iter() - .map(|v| StyledString::Text(format!("{}\n", v))) + .map(|v| StyledString::Text(format!("{}\n", v).into())) .collect::>(), ) .cell(), diff --git a/packages/next-swc/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs b/packages/next-swc/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs index 4104c6ba17a53..5d0e1fd96525f 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/transforms/next_strip_page_exports.rs @@ -36,21 +36,21 @@ pub async fn get_next_pages_transforms_rule( ModuleRuleCondition::all(vec![ ModuleRuleCondition::ResourcePathInExactDirectory(pages_dir.await?), ModuleRuleCondition::not(ModuleRuleCondition::ResourcePathInExactDirectory( - pages_dir.join("api".to_string()).await?, + pages_dir.join("api".into()).await?, )), ModuleRuleCondition::not(ModuleRuleCondition::any(vec![ // TODO(alexkirsz): Possibly ignore _app as well? ModuleRuleCondition::ResourcePathEquals( - pages_dir.join("_document.js".to_string()).await?, + pages_dir.join("_document.js".into()).await?, ), ModuleRuleCondition::ResourcePathEquals( - pages_dir.join("_document.jsx".to_string()).await?, + pages_dir.join("_document.jsx".into()).await?, ), ModuleRuleCondition::ResourcePathEquals( - pages_dir.join("_document.ts".to_string()).await?, + pages_dir.join("_document.ts".into()).await?, ), ModuleRuleCondition::ResourcePathEquals( - pages_dir.join("_document.tsx".to_string()).await?, + pages_dir.join("_document.tsx".into()).await?, ), ])), ]), diff --git a/packages/next-swc/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs b/packages/next-swc/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs index 63a8ca6ce5723..c0b3eb84519c6 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/transforms/swc_ecma_transform_plugins.rs @@ -1,4 +1,6 @@ use anyhow::Result; +#[allow(unused_imports)] +use turbo_tasks::RcStr; use turbo_tasks::Vc; use turbo_tasks_fs::FileSystemPath; use turbopack_binding::turbopack::turbopack::module_options::ModuleRule; @@ -30,7 +32,7 @@ pub async fn get_swc_ecma_transform_plugin_rule( #[cfg(feature = "plugin")] pub async fn get_swc_ecma_transform_rule_impl( project_path: Vc, - plugin_configs: &[(String, serde_json::Value)], + plugin_configs: &[(RcStr, serde_json::Value)], enable_mdx_rs: bool, ) -> Result> { use anyhow::{bail, Context}; @@ -58,7 +60,7 @@ pub async fn get_swc_ecma_transform_rule_impl( // one for implicit package name resolves to node_modules, // and one for explicit path to a .wasm binary. // Current resolve will fail with latter. - let request = Request::parse(Value::new(Pattern::Constant(name.to_string()))); + let request = Request::parse(Value::new(Pattern::Constant(name.as_str().into()))); let resolve_options = resolve_options( project_path, ResolveOptionsContext { diff --git a/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/babel.rs b/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/babel.rs index 22467d0a8131d..f283bf3501d8b 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/babel.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/babel.rs @@ -35,8 +35,8 @@ pub async fn maybe_add_babel_loader( ) -> Result> { let has_babel_config = { let mut has_babel_config = false; - for filename in BABEL_CONFIG_FILES { - let filetype = *project_root.join(filename.to_string()).get_type().await?; + for &filename in BABEL_CONFIG_FILES { + let filetype = *project_root.join(filename.into()).get_type().await?; if matches!(filetype, FileSystemEntryType::File) { has_babel_config = true; break; @@ -71,13 +71,11 @@ pub async fn maybe_add_babel_loader( BabelIssue { path: project_root, title: StyledString::Text( - "Unable to resolve babel-loader, but a babel config is present" - .to_owned(), + "Unable to resolve babel-loader, but a babel config is present".into(), ) .cell(), description: StyledString::Text( - "Make sure babel-loader is installed via your package manager." - .to_owned(), + "Make sure babel-loader is installed via your package manager.".into(), ) .cell(), severity: IssueSeverity::Fatal.cell(), @@ -89,7 +87,7 @@ pub async fn maybe_add_babel_loader( } let loader = WebpackLoaderItem { - loader: "babel-loader".to_string(), + loader: "babel-loader".into(), options: Default::default(), }; if let Some(rule) = rule { @@ -98,10 +96,10 @@ pub async fn maybe_add_babel_loader( rule.loaders = Vc::cell(loaders); } else { rules.insert( - pattern.to_string(), + pattern.into(), LoaderRuleItem { loaders: Vc::cell(vec![loader]), - rename_as: Some("*".to_string()), + rename_as: Some("*".into()), }, ); } @@ -122,7 +120,7 @@ pub async fn is_babel_loader_available(project_path: Vc) -> Resu project_path, Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)), Request::parse(Value::new(Pattern::Constant( - "babel-loader/package.json".to_string(), + "babel-loader/package.json".into(), ))), node_cjs_resolve_options(project_path), ); diff --git a/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/mod.rs b/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/mod.rs index 7dca8bf01595e..865672b560291 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/mod.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/mod.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use turbo_tasks::Vc; +use turbo_tasks::{RcStr, Vc}; use turbo_tasks_fs::FileSystemPath; use turbopack_binding::turbopack::{ core::resolve::options::ImportMapping, turbopack::module_options::WebpackLoadersOptions, @@ -15,7 +15,7 @@ pub async fn webpack_loader_options( project_path: Vc, next_config: Vc, foreign: bool, - conditions: Vec, + conditions: Vec, ) -> Result>> { let rules = *next_config.webpack_rules(conditions).await?; let rules = *maybe_add_sass_loader(next_config.sass_config(), rules).await?; @@ -35,5 +35,5 @@ pub async fn webpack_loader_options( #[turbo_tasks::function] fn loader_runner_package_mapping() -> Vc { - get_external_next_compiled_package_mapping(Vc::cell("loader-runner".to_owned())) + get_external_next_compiled_package_mapping(Vc::cell("loader-runner".into())) } diff --git a/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/sass.rs b/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/sass.rs index 38a3317bda4f5..2cb1b5dcb2511 100644 --- a/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/sass.rs +++ b/packages/next-swc/crates/next-core/src/next_shared/webpack_rules/sass.rs @@ -35,7 +35,7 @@ pub async fn maybe_add_sass_loader( .or(sass_options.get("additionalData")); let rule = rules.get_mut(pattern); let sass_loader = WebpackLoaderItem { - loader: "next/dist/compiled/sass-loader".to_string(), + loader: "next/dist/compiled/sass-loader".into(), options: take( serde_json::json!({ "sourceMap": true, @@ -47,7 +47,7 @@ pub async fn maybe_add_sass_loader( ), }; let resolve_url_loader = WebpackLoaderItem { - loader: "next/dist/build/webpack/loaders/resolve-url-loader/index".to_string(), + loader: "next/dist/build/webpack/loaders/resolve-url-loader/index".into(), options: take( serde_json::json!({ //https://github.com/vercel/turbo/blob/d527eb54be384a4658243304cecd547d09c05c6b/crates/turbopack-node/src/transforms/webpack.rs#L191 @@ -75,10 +75,10 @@ pub async fn maybe_add_sass_loader( rule.loaders = Vc::cell(loaders); } else { rules.insert( - pattern.to_string(), + pattern.into(), LoaderRuleItem { loaders: Vc::cell(vec![resolve_url_loader, sass_loader]), - rename_as: Some(format!("*{rename}")), + rename_as: Some(format!("*{rename}").into()), }, ); } diff --git a/packages/next-swc/crates/next-core/src/next_telemetry.rs b/packages/next-swc/crates/next-core/src/next_telemetry.rs index 6746814455af8..6ce9430aac136 100644 --- a/packages/next-swc/crates/next-core/src/next_telemetry.rs +++ b/packages/next-swc/crates/next-core/src/next_telemetry.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use turbo_tasks::RcStr; use turbopack_binding::{ turbo::tasks::Vc, turbopack::core::diagnostics::{Diagnostic, DiagnosticPayload}, @@ -9,15 +10,15 @@ use turbopack_binding::{ /// enabled for the telemetry. The original implementation code can be found at the following [link](https://github.com/vercel/next.js/blob/9da305fe320b89ee2f8c3cfb7ecbf48856368913/packages/next/src/build/webpack-config.ts#L2516). #[turbo_tasks::value(shared)] pub struct NextFeatureTelemetry { - pub event_name: String, - pub feature_name: String, + pub event_name: RcStr, + pub feature_name: RcStr, pub enabled: bool, } impl NextFeatureTelemetry { - pub fn new(feature_name: String, enabled: bool) -> Self { + pub fn new(feature_name: RcStr, enabled: bool) -> Self { NextFeatureTelemetry { - event_name: "EVENT_BUILD_FEATURE_USAGE".to_string(), + event_name: "EVENT_BUILD_FEATURE_USAGE".into(), feature_name, enabled, } @@ -27,12 +28,12 @@ impl NextFeatureTelemetry { #[turbo_tasks::value_impl] impl Diagnostic for NextFeatureTelemetry { #[turbo_tasks::function] - fn category(&self) -> Vc { - Vc::cell("NextFeatureTelemetry_category_tbd".to_string()) + fn category(&self) -> Vc { + Vc::cell("NextFeatureTelemetry_category_tbd".into()) } #[turbo_tasks::function] - fn name(&self) -> Vc { + fn name(&self) -> Vc { Vc::cell(self.event_name.clone()) } @@ -40,7 +41,7 @@ impl Diagnostic for NextFeatureTelemetry { fn payload(&self) -> Vc { Vc::cell(HashMap::from([( self.feature_name.clone(), - self.enabled.to_string(), + self.enabled.to_string().into(), )])) } } @@ -49,15 +50,15 @@ impl Diagnostic for NextFeatureTelemetry { /// referred as `importing` a certain module. (i.e importing @next/image) #[turbo_tasks::value(shared)] pub struct ModuleFeatureTelemetry { - pub event_name: String, - pub feature_name: String, + pub event_name: RcStr, + pub feature_name: RcStr, pub invocation_count: usize, } impl ModuleFeatureTelemetry { - pub fn new(feature_name: String, invocation_count: usize) -> Self { + pub fn new(feature_name: RcStr, invocation_count: usize) -> Self { ModuleFeatureTelemetry { - event_name: "EVENT_BUILD_FEATURE_USAGE".to_string(), + event_name: "EVENT_BUILD_FEATURE_USAGE".into(), feature_name, invocation_count, } @@ -67,12 +68,12 @@ impl ModuleFeatureTelemetry { #[turbo_tasks::value_impl] impl Diagnostic for ModuleFeatureTelemetry { #[turbo_tasks::function] - fn category(&self) -> Vc { - Vc::cell("ModuleFeatureTelemetry_category_tbd".to_string()) + fn category(&self) -> Vc { + Vc::cell("ModuleFeatureTelemetry_category_tbd".into()) } #[turbo_tasks::function] - fn name(&self) -> Vc { + fn name(&self) -> Vc { Vc::cell(self.event_name.clone()) } @@ -80,7 +81,7 @@ impl Diagnostic for ModuleFeatureTelemetry { fn payload(&self) -> Vc { Vc::cell(HashMap::from([( self.feature_name.clone(), - self.invocation_count.to_string(), + self.invocation_count.to_string().into(), )])) } } diff --git a/packages/next-swc/crates/next-core/src/page_loader.rs b/packages/next-swc/crates/next-core/src/page_loader.rs index aa6a6221246b4..28d39ea1d52da 100644 --- a/packages/next-swc/crates/next-core/src/page_loader.rs +++ b/packages/next-swc/crates/next-core/src/page_loader.rs @@ -2,7 +2,7 @@ use std::io::Write; use anyhow::{bail, Result}; use indexmap::indexmap; -use turbo_tasks::{TryJoinIterExt, Value, Vc}; +use turbo_tasks::{RcStr, TryJoinIterExt, Value, Vc}; use turbo_tasks_fs::FileSystemPathOption; use turbopack_binding::{ turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPath}, @@ -29,7 +29,7 @@ use crate::{embed_js::next_js_file_path, util::get_asset_path_from_pathname}; pub async fn create_page_loader_entry_module( client_context: Vc>, entry_asset: Vc>, - pathname: Vc, + pathname: Vc, ) -> Result>> { let mut result = RopeBuilder::default(); writeln!( @@ -38,7 +38,7 @@ pub async fn create_page_loader_entry_module( StringifyJs(&*pathname.await?) )?; - let page_loader_path = next_js_file_path("entry/page-loader.ts".to_string()); + let page_loader_path = next_js_file_path("entry/page-loader.ts".into()); let base_code = page_loader_path.read(); if let FileContent::Content(base_file) = &*base_code.await? { result += base_file.content() @@ -64,7 +64,7 @@ pub async fn create_page_loader_entry_module( .process( virtual_source, Value::new(ReferenceType::Internal(Vc::cell(indexmap! { - "PAGE".to_string() => module, + "PAGE".into() => module, }))), ) .module(); @@ -74,7 +74,7 @@ pub async fn create_page_loader_entry_module( #[turbo_tasks::value(shared)] pub struct PageLoaderAsset { pub server_root: Vc, - pub pathname: Vc, + pub pathname: Vc, pub rebase_prefix_path: Vc, pub page_chunks: Vc, } @@ -84,7 +84,7 @@ impl PageLoaderAsset { #[turbo_tasks::function] pub fn new( server_root: Vc, - pathname: Vc, + pathname: Vc, rebase_prefix_path: Vc, page_chunks: Vc, ) -> Vc { @@ -127,8 +127,8 @@ impl PageLoaderAsset { } #[turbo_tasks::function] -fn page_loader_chunk_reference_description() -> Vc { - Vc::cell("page loader chunk".to_string()) +fn page_loader_chunk_reference_description() -> Vc { + Vc::cell("page loader chunk".into()) } #[turbo_tasks::value_impl] @@ -136,10 +136,15 @@ impl OutputAsset for PageLoaderAsset { #[turbo_tasks::function] async fn ident(&self) -> Result> { let root = self.rebase_prefix_path.await?.unwrap_or(self.server_root); - Ok(AssetIdent::from_path(root.join(format!( - "static/chunks/pages{}", - get_asset_path_from_pathname(&self.pathname.await?, ".js") - )))) + Ok(AssetIdent::from_path( + root.join( + format!( + "static/chunks/pages{}", + get_asset_path_from_pathname(&self.pathname.await?, ".js") + ) + .into(), + ), + )) } #[turbo_tasks::function] diff --git a/packages/next-swc/crates/next-core/src/pages_structure.rs b/packages/next-swc/crates/next-core/src/pages_structure.rs index 11731148ec8f7..95769a0fae6f1 100644 --- a/packages/next-swc/crates/next-core/src/pages_structure.rs +++ b/packages/next-swc/crates/next-core/src/pages_structure.rs @@ -1,6 +1,6 @@ use anyhow::Result; use tracing::Instrument; -use turbo_tasks::{Completion, ValueToString, Vc}; +use turbo_tasks::{Completion, RcStr, ValueToString, Vc}; use turbo_tasks_fs::FileSystemPathOption; use turbopack_binding::turbo::tasks_fs::{ DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath, @@ -146,14 +146,14 @@ impl PagesDirectoryStructure { pub async fn find_pages_structure( project_root: Vc, next_router_root: Vc, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Result> { - let pages_root = project_root.join("pages".to_string()); + let pages_root = project_root.join("pages".into()); let pages_root = Vc::::cell( if *pages_root.get_type().await? == FileSystemEntryType::Directory { Some(pages_root) } else { - let src_pages_root = project_root.join("src/pages".to_string()); + let src_pages_root = project_root.join("src/pages".into()); if *src_pages_root.get_type().await? == FileSystemEntryType::Directory { Some(src_pages_root) } else { @@ -181,7 +181,7 @@ async fn get_pages_structure_for_root_directory( project_root: Vc, project_path: Vc, next_router_path: Vc, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Result> { let page_extensions_raw = &*page_extensions.await?; @@ -204,8 +204,7 @@ async fn get_pages_structure_for_root_directory( }; match basename { "_app" => { - let item_next_router_path = - next_router_path.join("_app".to_string()); + let item_next_router_path = next_router_path.join("_app".into()); app_item = Some(PagesStructureItem::new( *file_project_path, item_next_router_path, @@ -214,7 +213,7 @@ async fn get_pages_structure_for_root_directory( } "_document" => { let item_next_router_path = - next_router_path.join("_document".to_string()); + next_router_path.join("_document".into()); document_item = Some(PagesStructureItem::new( *file_project_path, item_next_router_path, @@ -222,8 +221,7 @@ async fn get_pages_structure_for_root_directory( )); } "_error" => { - let item_next_router_path = - next_router_path.join("_error".to_string()); + let item_next_router_path = next_router_path.join("_error".into()); error_item = Some(PagesStructureItem::new( *file_project_path, item_next_router_path, @@ -233,8 +231,7 @@ async fn get_pages_structure_for_root_directory( basename => { let item_next_router_path = next_router_path_for_basename(next_router_path, basename); - let item_original_path = - next_router_path.join(basename.to_string()); + let item_original_path = next_router_path.join(basename.into()); items.push(( basename, PagesStructureItem::new( @@ -246,7 +243,7 @@ async fn get_pages_structure_for_root_directory( } } } - DirectoryEntry::Directory(dir_project_path) => match name.as_ref() { + DirectoryEntry::Directory(dir_project_path) => match name.as_str() { "api" => { api_directory = Some(get_pages_structure_for_directory( *dir_project_path, @@ -292,9 +289,9 @@ async fn get_pages_structure_for_root_directory( let app_item = if let Some(app_item) = app_item { app_item } else { - let app_router_path = next_router_path.join("_app".to_string()); + let app_router_path = next_router_path.join("_app".into()); PagesStructureItem::new( - get_next_package(project_root).join("app.js".to_string()), + get_next_package(project_root).join("app.js".into()), app_router_path, app_router_path, ) @@ -303,9 +300,9 @@ async fn get_pages_structure_for_root_directory( let document_item = if let Some(document_item) = document_item { document_item } else { - let document_router_path = next_router_path.join("_document".to_string()); + let document_router_path = next_router_path.join("_document".into()); PagesStructureItem::new( - get_next_package(project_root).join("document.js".to_string()), + get_next_package(project_root).join("document.js".into()), document_router_path, document_router_path, ) @@ -314,9 +311,9 @@ async fn get_pages_structure_for_root_directory( let error_item = if let Some(error_item) = error_item { error_item } else { - let error_router_path = next_router_path.join("_error".to_string()); + let error_router_path = next_router_path.join("_error".into()); PagesStructureItem::new( - get_next_package(project_root).join("error.js".to_string()), + get_next_package(project_root).join("error.js".into()), error_router_path, error_router_path, ) @@ -339,11 +336,11 @@ async fn get_pages_structure_for_directory( project_path: Vc, next_router_path: Vc, position: u32, - page_extensions: Vc>, + page_extensions: Vc>, ) -> Result> { let span = { - let path = project_path.to_string().await?; - tracing::info_span!("analyse pages structure", name = *path) + let path = project_path.to_string().await?.to_string(); + tracing::info_span!("analyse pages structure", name = path) }; async move { let page_extensions_raw = &*page_extensions.await?; @@ -360,9 +357,9 @@ async fn get_pages_structure_for_directory( }; let item_next_router_path = match basename { "index" => next_router_path, - _ => next_router_path.join(basename.to_string()), + _ => next_router_path.join(basename.into()), }; - let item_original_name = next_router_path.join(basename.to_string()); + let item_original_name = next_router_path.join(basename.into()); items.push(( basename, PagesStructureItem::new( @@ -406,10 +403,10 @@ async fn get_pages_structure_for_directory( .await } -fn page_basename<'a>(name: &'a str, page_extensions: &'a [String]) -> Option<&'a str> { +fn page_basename<'a>(name: &'a str, page_extensions: &'a [RcStr]) -> Option<&'a str> { page_extensions .iter() - .find_map(|allowed| name.strip_suffix(allowed)?.strip_suffix('.')) + .find_map(|allowed| name.strip_suffix(&**allowed)?.strip_suffix('.')) } fn next_router_path_for_basename( @@ -419,6 +416,6 @@ fn next_router_path_for_basename( if basename == "index" { next_router_path } else { - next_router_path.join(basename.to_string()) + next_router_path.join(basename.into()) } } diff --git a/packages/next-swc/crates/next-core/src/transform_options.rs b/packages/next-swc/crates/next-core/src/transform_options.rs index 7b3c8d01fd166..cead6affe253a 100644 --- a/packages/next-swc/crates/next-core/src/transform_options.rs +++ b/packages/next-swc/crates/next-core/src/transform_options.rs @@ -156,11 +156,11 @@ pub async fn get_jsx_transform_options( // https://github.com/vercel/next.js/blob/3dc2c1c7f8441cdee31da9f7e0986d654c7fd2e7/packages/next/src/build/swc/options.ts#L112 // This'll be ignored if ts|jsconfig explicitly specifies importSource import_source: if is_emotion_enabled && !is_rsc_context { - Some("@emotion/react".to_string()) + Some("@emotion/react".into()) } else { None }, - runtime: Some("automatic".to_string()), + runtime: Some("automatic".into()), react_refresh: enable_react_refresh, }; @@ -168,7 +168,7 @@ pub async fn get_jsx_transform_options( read_from_tsconfigs(&tsconfig, |json, _| { let jsx_import_source = json["compilerOptions"]["jsxImportSource"] .as_str() - .map(|s| s.to_string()); + .map(|s| s.into()); Some(JsxTransformOptions { import_source: if jsx_import_source.is_some() { diff --git a/packages/next-swc/crates/next-core/src/util.rs b/packages/next-swc/crates/next-core/src/util.rs index cd6d2ab7db81d..40841e28cf8fa 100644 --- a/packages/next-swc/crates/next-core/src/util.rs +++ b/packages/next-swc/crates/next-core/src/util.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Context, Result}; use indexmap::{IndexMap, IndexSet}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use turbo_tasks::{trace::TraceRawVcs, TaskInput, ValueDefault, ValueToString, Vc}; +use turbo_tasks::{trace::TraceRawVcs, RcStr, TaskInput, ValueDefault, ValueToString, Vc}; use turbo_tasks_fs::{rope::Rope, util::join_path, File}; use turbopack_binding::{ swc::core::{ @@ -49,7 +49,7 @@ pub async fn pathname_for_path( server_root: Vc, server_path: Vc, path_ty: PathType, -) -> Result> { +) -> Result> { let server_path_value = &*server_path.await?; let path = if let Some(path) = server_root.await?.get_path_to(server_path_value) { path @@ -62,10 +62,10 @@ pub async fn pathname_for_path( }; let path = match (path_ty, path) { // "/" is special-cased to "/index" for data routes. - (PathType::Data, "") => "/index".to_string(), + (PathType::Data, "") => "/index".into(), // `get_path_to` always strips the leading `/` from the path, so we need to add // it back here. - (_, path) => format!("/{}", path), + (_, path) => format!("/{}", path).into(), }; Ok(Vc::cell(path)) @@ -100,7 +100,7 @@ pub async fn foreign_code_context_condition( // of the `node_modules` specific resolve options (the template files are // technically node module files). let not_next_template_dir = ContextCondition::not(ContextCondition::InPath( - get_next_package(project_path).join(NEXT_TEMPLATE_PATH.to_string()), + get_next_package(project_path).join(NEXT_TEMPLATE_PATH.into()), )); let result = if transpile_packages.is_empty() { @@ -195,7 +195,7 @@ impl Issue for NextSourceConfigParsingIssue { #[turbo_tasks::function] fn title(&self) -> Vc { - StyledString::Text("Unable to parse config export in source file".to_string()).cell() + StyledString::Text("Unable to parse config export in source file".into()).cell() } #[turbo_tasks::function] @@ -214,7 +214,7 @@ impl Issue for NextSourceConfigParsingIssue { StyledString::Text( "The exported configuration object in a source file need to have a very specific \ format from which some properties can be statically parsed at compiled-time." - .to_string(), + .into(), ) .cell(), )) @@ -230,7 +230,7 @@ fn emit_invalid_config_warning(ident: Vc, detail: &str, value: &JsVa let (explainer, hints) = value.explain(2, 0); NextSourceConfigParsingIssue { ident, - detail: StyledString::Text(format!("{detail} Got {explainer}.{hints}")).cell(), + detail: StyledString::Text(format!("{detail} Got {explainer}.{hints}").into()).cell(), } .cell() .emit() @@ -267,20 +267,20 @@ fn parse_route_matcher_from_js_value( } let r = match route_type.as_deref() { Some("header") => route_key.map(|route_key| RouteHas::Header { - key: route_key, - value: route_value, + key: route_key.into(), + value: route_value.map(From::from), }), Some("cookie") => route_key.map(|route_key| RouteHas::Cookie { - key: route_key, - value: route_value, + key: route_key.into(), + value: route_value.map(From::from), }), Some("query") => route_key.map(|route_key| RouteHas::Query { - key: route_key, - value: route_value, + key: route_key.into(), + value: route_value.map(From::from), + }), + Some("host") => route_value.map(|route_value| RouteHas::Host { + value: route_value.into(), }), - Some("host") => { - route_value.map(|route_value| RouteHas::Host { value: route_value }) - } _ => None, }; @@ -319,7 +319,7 @@ fn parse_route_matcher_from_js_value( match key.as_str() { Some("source") => { if let Some(value) = value.as_str() { - matcher.original_source = value.to_string(); + matcher.original_source = value.into(); } } Some("missing") => { @@ -397,7 +397,7 @@ pub async fn parse_config_from_source(module: Vc>) -> Result>) -> Result>) -> Result>, value: &JsValue) -> N pub async fn load_next_js_template( path: &str, project_path: Vc, - replacements: IndexMap<&'static str, String>, - injections: IndexMap<&'static str, String>, - imports: IndexMap<&'static str, Option>, + replacements: IndexMap<&'static str, RcStr>, + injections: IndexMap<&'static str, RcStr>, + imports: IndexMap<&'static str, Option>, ) -> Result>> { let path = virtual_next_js_template_path(project_path, path.to_string()); @@ -591,7 +591,8 @@ pub async fn load_next_js_template( import_request }, ) - .context("path should not leave the fs")?, + .context("path should not leave the fs")? + .into(), }; let relative = package_root_value @@ -803,12 +804,12 @@ pub fn virtual_next_js_template_path( file: String, ) -> Vc { debug_assert!(!file.contains('/')); - get_next_package(project_path).join(format!("{NEXT_TEMPLATE_PATH}/{file}")) + get_next_package(project_path).join(format!("{NEXT_TEMPLATE_PATH}/{file}").into()) } pub async fn load_next_js_templateon( project_path: Vc, - path: String, + path: RcStr, ) -> Result { let file_path = get_next_package(project_path).join(path.clone()); diff --git a/packages/next/package.json b/packages/next/package.json index 90f17e88f24f8..270af2f42a10a 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -206,7 +206,7 @@ "@types/ws": "8.2.0", "@vercel/ncc": "0.34.0", "@vercel/nft": "0.27.1", - "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240526.2", + "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240605.1", "acorn": "8.11.3", "amphtml-validator": "1.0.35", "anser": "1.4.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39728669d0b03..6a99387b71509 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1090,8 +1090,8 @@ importers: specifier: 0.27.1 version: 0.27.1 '@vercel/turbopack-ecmascript-runtime': - specifier: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240526.2 - version: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240526.2' + specifier: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240605.1 + version: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240605.1' acorn: specifier: 8.11.3 version: 8.11.3 @@ -25806,8 +25806,8 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240526.2': - resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240526.2} + '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240605.1': + resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240605.1} name: '@vercel/turbopack-ecmascript-runtime' version: 0.0.0 dependencies: