feat(turbopack): Introduce RcStr (#66262)

# Turbopack

* https://github.com/vercel/turbo/pull/8272 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.8` -->
* https://github.com/vercel/turbo/pull/8262 <!-- Alexander Lyon - add
crate to calculate prehashes -->
* https://github.com/vercel/turbo/pull/8174 <!-- Tobias Koppers - use
prehash to avoid rehashing the key in the task cache -->
* https://github.com/vercel/turbo/pull/7674 <!-- Alexander Lyon - [turbo
trace] add ability to filter by value and occurences -->
* https://github.com/vercel/turbo/pull/8287 <!-- Donny/강동윤 - feat:
Update `swc_core` to `v0.92.10` -->
* https://github.com/vercel/turbo/pull/8037 <!-- Alexander Lyon - create
turbo-static for compile time graph analysis -->
* https://github.com/vercel/turbo/pull/8293 <!-- Will Binns-Smith - Sync
Cargo.lock with Next.js -->
* https://github.com/vercel/turbo/pull/8239 <!-- Benjamin Woodruff -
Reduce amount of code generated by ValueDebugFormat -->
* https://github.com/vercel/turbo/pull/8304 <!-- Benjamin Woodruff -
Minor optimizations to the codegen of TaskFnInputFunction -->
* https://github.com/vercel/turbo/pull/8221 <!-- Donny/강동윤 - perf:
Introduce `RcStr` -->


### What?

I tried using `Arc<String>` in
https://github.com/vercel/turbo/pull/7772, but a team member suggested
creating a new type so we can replace underlying implementation easily
in the future.

### Why?

To reduce memory usage.

### How?

Closes PACK-2776
This commit is contained in:
Donny/강동윤 2024-06-05 15:09:28 +09:00 committed by GitHub
parent 750ae91e30
commit 3cf225c8ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
94 changed files with 1490 additions and 1483 deletions

78
Cargo.lock generated
View file

@ -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",
@ -6945,10 +6945,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",
@ -6980,7 +6985,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",
@ -6992,7 +6997,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",
@ -7006,7 +7011,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",
@ -7020,7 +7025,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",
@ -7036,7 +7041,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",
@ -7068,7 +7073,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",
@ -7078,7 +7083,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",
@ -7092,7 +7097,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",
@ -7102,7 +7107,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",
]
@ -7110,7 +7115,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",
@ -7127,6 +7132,7 @@ dependencies = [
"smallvec",
"tokio",
"tracing",
"turbo-prehash",
"turbo-tasks",
"turbo-tasks-build",
"turbo-tasks-hash",
@ -7136,7 +7142,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",
@ -7166,7 +7172,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",
@ -7207,7 +7213,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",
@ -7230,7 +7236,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",
@ -7247,7 +7253,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",
@ -7276,7 +7282,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",
@ -7303,7 +7309,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",
@ -7339,7 +7345,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",
@ -7374,7 +7380,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",
@ -7385,7 +7391,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",
@ -7409,7 +7415,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",
@ -7425,7 +7431,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",
@ -7441,7 +7447,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",
@ -7460,7 +7466,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",
@ -7475,7 +7481,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",
@ -7490,7 +7496,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",
@ -7524,7 +7530,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",
@ -7544,7 +7550,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",
@ -7562,7 +7568,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",
@ -7578,7 +7584,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",
@ -7589,7 +7595,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",
@ -7609,7 +7615,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",
@ -7625,7 +7631,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",

View file

@ -37,11 +37,11 @@ swc_core = { version = "0.92.10", 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

View file

@ -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<Vc<Box<dyn FileSystem>>> {
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<Vc<Box<dyn FileSystem>>> {
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<Vc<Box<dyn Fi
#[turbo_tasks::value]
#[serde(rename_all = "camelCase")]
struct LoaderTreeForJs {
segment: String,
parallel_routes: IndexMap<String, ReadRef<LoaderTreeForJs>>,
segment: RcStr,
parallel_routes: IndexMap<RcStr, ReadRef<LoaderTreeForJs>>,
#[turbo_tasks(trace_ignore)]
components: ComponentsForJs,
#[turbo_tasks(trace_ignore)]
@ -57,13 +53,13 @@ enum EntrypointForJs {
loader_tree: ReadRef<LoaderTreeForJs>,
},
AppRoute {
path: String,
path: RcStr,
},
}
#[turbo_tasks::value(transparent)]
#[serde(rename_all = "camelCase")]
struct EntrypointsForJs(HashMap<String, EntrypointForJs>);
struct EntrypointsForJs(HashMap<RcStr, EntrypointForJs>);
#[turbo_tasks::value(transparent)]
struct OptionEntrypointsForJs(Option<Vc<EntrypointsForJs>>);
@ -71,14 +67,14 @@ struct OptionEntrypointsForJs(Option<Vc<EntrypointsForJs>>);
async fn fs_path_to_path(
project_path: Vc<FileSystemPath>,
path: Vc<FileSystemPath>,
) -> Result<String> {
) -> Result<RcStr> {
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<String>,
page: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none")]
layout: Option<String>,
layout: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none")]
error: Option<String>,
error: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none")]
loading: Option<String>,
loading: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none")]
template: Option<String>,
template: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none", rename = "not-found")]
not_found: Option<String>,
not_found: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none")]
default: Option<String>,
default: Option<RcStr>,
#[serde(skip_serializing_if = "Option::is_none")]
route: Option<String>,
route: Option<RcStr>,
metadata: MetadataForJs,
}
@ -134,19 +130,19 @@ struct GlobalMetadataForJs {
#[serde(tag = "type", rename_all = "camelCase")]
enum MetadataWithAltItemForJs {
Static {
path: String,
alt_path: Option<String>,
path: RcStr,
alt_path: Option<RcStr>,
},
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<String>,
result: &mut Option<RcStr>,
project_path: Vc<FileSystemPath>,
value: &Option<Vc<FileSystemPath>>,
) -> 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<String>,
root_dir: RcStr,
project_dir: RcStr,
page_extensions: Vec<RcStr>,
watching: bool,
) -> Result<Vc<OptionEntrypointsForJs>> {
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<Option<ReadRef<EntrypointsForJs>>> = func.clone();
@ -383,9 +379,9 @@ pub fn stream_entrypoints(
let page_extensions: Arc<Vec<String>> = 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?

View file

@ -57,7 +57,7 @@ impl From<WrittenEndpoint> 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<WrittenEndpoint> 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()
},

View file

@ -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<NapiDraftModeOptions> 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<NapiProjectOptions> 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<NapiProjectOptions> for ProjectOptions {
impl From<NapiPartialProjectOptions> 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<NapiDefineEnv> 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<FileSystemPath>) -> Result<Vc<Completion>> {
let temp_path = directory.join(format!(
"tmp_file_io_benchmark_{:x}",
rand::random::<u128>()
));
let temp_path =
directory.join(format!("tmp_file_io_benchmark_{:x}", rand::random::<u128>()).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::<DiskFileSystem>(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::<Vec<_>>(),
middleware: entrypoints
@ -670,7 +674,7 @@ struct HmrUpdateWithIssues {
#[turbo_tasks::function]
async fn hmr_update(
project: Vc<Project>,
identifier: String,
identifier: RcStr,
state: Vc<VersionState>,
) -> Result<Vc<HmrUpdateWithIssues>> {
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<Vec<String>>,
identifiers: ReadRef<Vec<RcStr>>,
issues: Arc<Vec<ReadRef<PlainIssue>>>,
diagnostics: Arc<Vec<ReadRef<PlainDiagnostic>>>,
}
@ -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?;

View file

@ -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(),
}
}
}

View file

@ -190,10 +190,21 @@ impl FromNapiValue for NapiRouteHas {
impl From<NapiRouteHas> 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(),
},
}
}
}

View file

@ -40,5 +40,5 @@ pub async fn run_turbo_tracing(
}),
)
.await?;
Ok(files)
Ok(files.into_iter().map(|f| f.to_string()).collect())
}

View file

@ -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<Self>) -> Vc<String> {
Vc::cell(ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string())
fn client_transition_name(self: Vc<Self>) -> Vc<RcStr> {
Vc::cell(ECMASCRIPT_CLIENT_TRANSITION_NAME.into())
}
#[turbo_tasks::function]
@ -275,23 +275,20 @@ impl AppProject {
fn rsc_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
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<Self>) -> Vc<ModuleAssetContext> {
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<Self>) -> Vc<ModuleAssetContext> {
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<Self>) -> Vc<ModuleAssetContext> {
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::<anyhow::Result<Vec<_>>>()?;
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<FileSystemPath>,
original_name: &str,
filename: String,
filename: RcStr,
) -> Result<Vc<Box<dyn OutputAsset>>> {
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());

View file

@ -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<Box<dyn ChunkableModule>>) -> Fu,
Fu: Future<Output = Result<Vc<OutputAssets>>> + Send,
{
let mut chunks_hash: HashMap<String, Vc<OutputAssets>> = HashMap::new();
let mut chunks_hash: HashMap<RcStr, Vc<OutputAssets>> = 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<Box<dyn Module>>, ReadRef<String>)> for NextDynamicVisit {
type Edge = (Vc<Box<dyn Module>>, ReadRef<String>);
impl turbo_tasks::graph::Visit<(Vc<Box<dyn Module>>, ReadRef<RcStr>)> for NextDynamicVisit {
type Edge = (Vc<Box<dyn Module>>, ReadRef<RcStr>);
type EdgesIntoIter = Vec<Self::Edge>;
type EdgesFuture = impl Future<Output = Result<Self::EdgesIntoIter>>;
fn visit(
&mut self,
edge: Self::Edge,
) -> VisitControlFlow<(Vc<Box<dyn Module>>, ReadRef<String>)> {
) -> VisitControlFlow<(Vc<Box<dyn Module>>, ReadRef<RcStr>)> {
VisitControlFlow::Continue(edge)
}
fn edges(
&mut self,
&(parent, _): &(Vc<Box<dyn Module>>, ReadRef<String>),
) -> Self::EdgesFuture {
fn edges(&mut self, &(parent, _): &(Vc<Box<dyn Module>>, ReadRef<RcStr>)) -> Self::EdgesFuture {
async move {
primary_referenced_modules(parent)
.await?
@ -204,7 +201,7 @@ impl turbo_tasks::graph::Visit<(Vc<Box<dyn Module>>, ReadRef<String>)> for NextD
}
}
fn span(&mut self, (_, name): &(Vc<Box<dyn Module>>, ReadRef<String>)) -> tracing::Span {
fn span(&mut self, (_, name): &(Vc<Box<dyn Module>>, ReadRef<RcStr>)) -> 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<Ident>,
pub import_sources: Vec<String>,
pub import_sources: Vec<RcStr>,
}
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<String>,
import_source: Option<RcStr>,
}
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<Box<dyn Module>>)>;
pub type DynamicImportedOutputAssets = Vec<(String, Vc<OutputAssets>)>;
pub type DynamicImportedModules = Vec<(RcStr, Vc<Box<dyn Module>>)>;
pub type DynamicImportedOutputAssets = Vec<(RcStr, Vc<OutputAssets>)>;
/// A struct contains mapping for the dynamic imports to construct chunk per
/// each individual module (Origin Module, Vec<(ImportSourceString, Module)>)

View file

@ -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<String, Route>,
pub routes: IndexMap<RcStr, Route>,
pub middleware: Option<Middleware>,
pub instrumentation: Option<Instrumentation>,
pub pages_document_endpoint: Vc<Box<dyn Endpoint>>,

View file

@ -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::<Vec<_>>();
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()
}

View file

@ -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,

View file

@ -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<String, LoadableManifest> = Default::default();
let mut loadable_manifest: HashMap<RcStr, LoadableManifest> = 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()

View file

@ -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,

View file

@ -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<String, Route>,
routes: &mut IndexMap<RcStr, Route>,
page: Vc<PagesStructureItem>,
make_route: impl Fn(Vc<String>, Vc<String>, Vc<FileSystemPath>) -> Route,
make_route: impl Fn(Vc<RcStr>, Vc<RcStr>, Vc<FileSystemPath>) -> 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<String, Route>,
routes: &mut IndexMap<RcStr, Route>,
dir: Vc<PagesDirectoryStructure>,
make_route: impl Fn(Vc<String>, Vc<String>, Vc<FileSystemPath>) -> Route,
make_route: impl Fn(Vc<RcStr>, Vc<RcStr>, Vc<FileSystemPath>) -> 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<Self>) -> Vc<TransitionsByName> {
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<PagesProject>,
pathname: Vc<String>,
original_name: Vc<String>,
pathname: Vc<RcStr>,
original_name: Vc<RcStr>,
path: Vc<FileSystemPath>,
pages_structure: Vc<PagesStructure>,
}
@ -597,8 +597,8 @@ impl PageEndpoint {
fn new(
ty: PageEndpointType,
pages_project: Vc<PagesProject>,
pathname: Vc<String>,
original_name: Vc<String>,
pathname: Vc<RcStr>,
original_name: Vc<RcStr>,
path: Vc<FileSystemPath>,
pages_structure: Vc<PagesStructure>,
) -> Vc<Self> {
@ -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())
}
}
};

View file

@ -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<OutputAssets>,
root: Vc<FileSystemPath>,
) -> Result<Vc<Vec<String>>> {
) -> Result<Vc<Vec<RcStr>>> {
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<Box<dyn OutputAsset>>],
filter: impl FnOnce(&str) -> bool + Copy,
) -> Result<Vec<String>> {
) -> Result<Vec<RcStr>> {
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<Box<dyn OutputAsset>>],
) -> Result<Vec<String>> {
) -> Result<Vec<RcStr>> {
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<Box<dyn OutputAsset>>],
) -> Result<Vec<String>> {
) -> Result<Vec<RcStr>> {
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<Box<dyn OutputAsset>>],
) -> Result<Vec<String>> {
) -> Result<Vec<RcStr>> {
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<String>) -> Vec<AssetBinding> {
pub(crate) fn wasm_paths_to_bindings(paths: Vec<RcStr>) -> Vec<AssetBinding> {
paths
.into_iter()
.map(|path| {
@ -155,7 +155,7 @@ pub(crate) fn wasm_paths_to_bindings(paths: Vec<String>) -> Vec<AssetBinding> {
);
AssetBinding {
name: format!("wasm_{}", escaped),
name: format!("wasm_{}", escaped).into(),
file_path: path,
}
})

View file

@ -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<String>,
pub root_path: Option<RcStr>,
/// A path inside the root_path which contains the app/pages directories.
pub project_path: Option<String>,
pub project_path: Option<RcStr>,
/// The contents of next.config.js, serialized to JSON.
pub next_config: Option<String>,
pub next_config: Option<RcStr>,
/// The contents of ts/config read by load-jsconfig, serialized to JSON.
pub js_config: Option<String>,
pub js_config: Option<RcStr>,
/// A map of environment variables to use when compiling code.
pub env: Option<Vec<(String, String)>>,
pub env: Option<Vec<(RcStr, RcStr)>>,
/// A map of environment variables which should get injected at compile
/// time.
@ -145,10 +145,10 @@ pub struct PartialProjectOptions {
pub dev: Option<bool>,
/// The server actions encryption key.
pub encryption_key: Option<String>,
pub encryption_key: Option<RcStr>,
/// The build id.
pub build_id: Option<String>,
pub build_id: Option<RcStr>,
/// Options for draft mode.
pub preview_props: Option<DraftModeOptions>,
@ -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<Self>) -> Vc<Vec<String>> {
pub fn hmr_identifiers(self: Vc<Self>) -> Vc<Vec<RcStr>> {
self.project().hmr_identifiers()
}
@ -340,7 +340,7 @@ impl ProjectContainer {
pub async fn get_source_map(
self: Vc<Self>,
file_path: Vc<FileSystemPath>,
section: Option<String>,
section: Option<RcStr>,
) -> Result<Vc<OptionSourceMap>> {
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<ProjectDefineEnv>,
browserslist_query: String,
browserslist_query: RcStr,
mode: Vc<NextMode>,
versioned_content_map: Vc<VersionedContentMap>,
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<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
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<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
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<Self>) -> Result<Vc<String>> {
Ok(Vc::cell(self.await?.dist_dir.to_string()))
pub async fn dist_dir(self: Vc<Self>) -> Result<Vc<RcStr>> {
Ok(Vc::cell(self.await?.dist_dir.clone()))
}
#[turbo_tasks::function]
pub async fn node_root(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
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<Self>) -> Result<Vc<FileSystemPath>> {
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<Self>) -> Result<Vc<FileSystemPath>> {
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<EnvMap> {
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<Self>) -> Result<Vc<()>> {
let emit_event = |feature_name: &str, enabled: bool| {
NextFeatureTelemetry::new(feature_name.to_string(), enabled)
NextFeatureTelemetry::new(feature_name.into(), enabled)
.cell()
.emit();
};
@ -786,14 +786,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(),
@ -895,7 +895,7 @@ impl Project {
self.next_config(),
self.execution_context(),
),
Vc::cell("middleware".to_string()),
Vc::cell("middleware".into()),
))
}
@ -929,7 +929,7 @@ impl Project {
self.next_config(),
self.execution_context(),
),
Vc::cell("instrumentation".to_string()),
Vc::cell("instrumentation".into()),
))
}
@ -979,7 +979,7 @@ impl Project {
#[turbo_tasks::function]
async fn hmr_content(
self: Vc<Self>,
identifier: String,
identifier: RcStr,
) -> Result<Vc<Box<dyn VersionedContent>>> {
Ok(self
.await?
@ -988,7 +988,7 @@ impl Project {
}
#[turbo_tasks::function]
async fn hmr_version(self: Vc<Self>, identifier: String) -> Result<Vc<Box<dyn Version>>> {
async fn hmr_version(self: Vc<Self>, identifier: RcStr) -> Result<Vc<Box<dyn Version>>> {
let content = self.hmr_content(identifier);
Ok(content.version())
@ -999,7 +999,7 @@ impl Project {
#[turbo_tasks::function]
pub async fn hmr_version_state(
self: Vc<Self>,
identifier: String,
identifier: RcStr,
session: TransientInstance<()>,
) -> Result<Vc<VersionState>> {
let version = self.hmr_version(identifier);
@ -1019,7 +1019,7 @@ impl Project {
#[turbo_tasks::function]
pub async fn hmr_update(
self: Vc<Self>,
identifier: String,
identifier: RcStr,
from: Vc<VersionState>,
) -> Result<Vc<Update>> {
let from = from.get();
@ -1029,7 +1029,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<Self>) -> Result<Vc<Vec<String>>> {
pub async fn hmr_identifiers(self: Vc<Self>) -> Result<Vc<Vec<RcStr>>> {
Ok(self
.await?
.versioned_content_map

View file

@ -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<ServerPath>,
client_paths: Vec<String>,
client_paths: Vec<RcStr>,
},
Edge {
server_paths: Vec<ServerPath>,
client_paths: Vec<String>,
client_paths: Vec<RcStr>,
},
}
/// The routes as map from pathname to route. (pathname includes the leading
/// slash)
#[turbo_tasks::value(transparent)]
pub struct Routes(IndexMap<String, Route>);
pub struct Routes(IndexMap<RcStr, Route>);

View file

@ -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<Box<dyn EvaluatableAsset>>, Vc<Box<dyn OutputAsset>>)> {
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::<Box<dyn EvaluatableAsset>>(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<FileSystemPath>,
page_name: String,
page_name: RcStr,
actions: Vc<AllActions>,
asset_context: Vc<Box<dyn AssetContext>>,
) -> Result<Vc<Box<dyn EcmascriptChunkPlaceable>>> {
@ -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<AllActions>,
loader_id: Vc<String>,
loader_id: Vc<RcStr>,
) -> Result<Vc<Box<dyn OutputAsset>>> {
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<String> {
Vc::cell("action".to_string())
fn action_modifier() -> Vc<RcStr> {
Vc::cell("action".into())
}
/// Traverses the entire module graph starting from [Module], looking for magic

View file

@ -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<Self>,
path: Vc<FileSystemPath>,
section: Option<String>,
section: Option<RcStr>,
) -> Result<Vc<OptionSourceMap>> {
if let Some(generate_source_map) =
Vc::try_resolve_sidecast::<Box<dyn GenerateSourceMap>>(self.get_asset(path)).await?
@ -169,7 +169,7 @@ impl VersionedContentMap {
}
#[turbo_tasks::function]
pub async fn keys_in_path(&self, root: Vc<FileSystemPath>) -> Result<Vc<Vec<String>>> {
pub async fn keys_in_path(&self, root: Vc<FileSystemPath>) -> Result<Vc<Vec<RcStr>>> {
let keys = {
let map = self.map_path_to_op.get();
map.keys().copied().collect::<Vec<_>>()
@ -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))

View file

@ -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,7 @@ pub struct NextSegmentConfig {
pub revalidate: Option<NextRevalidate>,
pub fetch_cache: Option<NextSegmentFetchCache>,
pub runtime: Option<NextRuntime>,
pub preferred_region: Option<Vec<String>>,
pub preferred_region: Option<Vec<RcStr>>,
pub experimental_ppr: Option<bool>,
}
@ -178,7 +178,7 @@ impl Issue for NextSegmentConfigParsingIssue {
#[turbo_tasks::function]
fn title(&self) -> Vc<StyledString> {
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]
@ -197,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(),
))
@ -209,10 +209,10 @@ impl Issue for NextSegmentConfigParsingIssue {
}
#[turbo_tasks::function]
fn documentation_link(&self) -> Vc<String> {
fn documentation_link(&self) -> Vc<RcStr> {
Vc::cell(
"https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config"
.to_string(),
.into(),
)
}
@ -312,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()
@ -402,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",

View file

@ -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<Vc<String>> {
pub async fn get_metadata_route_name(meta: MetadataItem) -> Result<Vc<RcStr>> {
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<Vc<String>> {
};
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<String, Vc<DirectoryTree>>,
pub subdirectories: BTreeMap<RcStr, Vc<DirectoryTree>>,
pub components: Vc<Components>,
}
@ -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<FileSystemPath>) -> Result<Vc<OptionAppDir>> {
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<FileSystemPath>) -> Result
#[turbo_tasks::function]
async fn get_directory_tree(
dir: Vc<FileSystemPath>,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<DirectoryTree>> {
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<FileSystemPath>,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<DirectoryTree>> {
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<String, Vc<LoaderTree>>,
pub segment: RcStr,
pub parallel_routes: IndexMap<RcStr, Vc<LoaderTree>>,
pub components: Vc<Components>,
pub global_metadata: Vc<GlobalMetadata>,
}
@ -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<Vc<bool>> {
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<Vc<bool>> {
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<FileSystemPath>,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Vc<Entrypoints> {
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<Self>) -> Result<Vc<FileSystemPath>> {
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<Self>) -> Vc<StyledString> {
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<FileSystemPath>,
global_metadata: Vc<GlobalMetadata>,
directory_name: String,
directory_name: RcStr,
directory_tree: Vc<DirectoryTree>,
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<FileSystemPath>,
global_metadata: Vc<GlobalMetadata>,
directory_name: String,
directory_name: RcStr,
directory_tree: Vc<DirectoryTree>,
app_page: AppPage,
root_layouts: Vc<Vec<Vc<FileSystemPath>>>,
@ -1054,7 +1056,7 @@ async fn directory_tree_to_entrypoints_internal(
async fn directory_tree_to_entrypoints_internal_untraced(
app_dir: Vc<FileSystemPath>,
global_metadata: Vc<GlobalMetadata>,
directory_name: String,
directory_name: RcStr,
directory_tree: Vc<DirectoryTree>,
app_page: AppPage,
root_layouts: Vc<Vec<Vc<FileSystemPath>>>,
@ -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<FileSystemPath>,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<GlobalMetadata>> {
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<Vc<StyledString>> {
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]

View file

@ -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(

View file

@ -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<Box<dyn FileSystem>> {
}
#[turbo_tasks::function]
pub(crate) fn next_js_file(path: String) -> Vc<FileContent> {
pub(crate) fn next_js_file(path: RcStr) -> Vc<FileContent> {
next_js_fs().root().join(path).read()
}
#[turbo_tasks::function]
pub(crate) fn next_js_file_path(path: String) -> Vc<FileSystemPath> {
pub(crate) fn next_js_file_path(path: RcStr) -> Vc<FileSystemPath> {
next_js_fs().root().join(path)
}
#[turbo_tasks::function]
pub(crate) fn next_asset(path: String) -> Vc<Box<dyn Source>> {
pub(crate) fn next_asset(path: RcStr) -> Vc<Box<dyn Source>> {
Vc::upcast(FileSource::new(next_js_file_path(path)))
}

View file

@ -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<Vec<String>>) -> Result<Vc<Vec<String>>> {
pub async fn instrumentation_files(page_extensions: Vc<Vec<RcStr>>) -> Result<Vc<Vec<RcStr>>> {
let extensions = page_extensions.await?;
let files = ["instrumentation.", "src/instrumentation."]
.into_iter()
@ -10,6 +10,7 @@ pub async fn instrumentation_files(page_extensions: Vc<Vec<String>>) -> Result<V
extensions
.iter()
.map(move |ext| String::from(f) + ext.as_str())
.map(RcStr::from)
})
.collect();
Ok(Vc::cell(files))

View file

@ -7,7 +7,7 @@ use anyhow::Result;
use async_recursion::async_recursion;
use indexmap::IndexMap;
use indoc::formatdoc;
use turbo_tasks::{Value, ValueToString, Vc};
use turbo_tasks::{RcStr, Value, ValueToString, Vc};
use turbo_tasks_fs::FileSystemPath;
use turbopack_binding::turbopack::{
core::{
@ -33,15 +33,15 @@ use crate::{
};
pub struct LoaderTreeBuilder {
inner_assets: IndexMap<String, Vc<Box<dyn Module>>>,
inner_assets: IndexMap<RcStr, Vc<Box<dyn Module>>>,
counter: usize,
imports: Vec<String>,
imports: Vec<RcStr>,
loader_tree_code: String,
context: Vc<ModuleAssetContext>,
server_component_transition: Vc<Box<dyn Transition>>,
pages: Vec<Vc<FileSystemPath>>,
/// next.config.js' basePath option to construct og metadata.
base_path: Option<String>,
base_path: Option<RcStr>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -73,7 +73,7 @@ impl LoaderTreeBuilder {
fn new(
context: Vc<ModuleAssetContext>,
server_component_transition: Vc<Box<dyn Transition>>,
base_path: Option<String>,
base_path: Option<RcStr>,
) -> 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<String>,
pub loader_tree_code: String,
pub inner_assets: IndexMap<String, Vc<Box<dyn Module>>>,
pub imports: Vec<RcStr>,
pub loader_tree_code: RcStr,
pub inner_assets: IndexMap<RcStr, Vc<Box<dyn Module>>>,
pub pages: Vec<Vc<FileSystemPath>>,
}
@ -444,7 +448,7 @@ impl LoaderTreeModule {
loader_tree: Vc<LoaderTree>,
context: Vc<ModuleAssetContext>,
server_component_transition: Vc<Box<dyn Transition>>,
base_path: Option<String>,
base_path: Option<RcStr>,
) -> Result<Self> {
LoaderTreeBuilder::new(context, server_component_transition, base_path)
.build(loader_tree)

View file

@ -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<Vec<String>>) -> Result<Vc<Vec<String>>> {
pub async fn middleware_files(page_extensions: Vc<Vec<RcStr>>) -> Result<Vc<Vec<RcStr>>> {
let extensions = page_extensions.await?;
let files = ["middleware.", "src/middleware."]
.into_iter()
@ -17,6 +17,7 @@ pub async fn middleware_files(page_extensions: Vc<Vec<String>>) -> Result<Vc<Vec
extensions
.iter()
.map(move |ext| String::from(f) + ext.as_str())
.map(RcStr::from)
})
.collect();
Ok(Vc::cell(files))
@ -35,8 +36,8 @@ pub async fn get_middleware_module(
"middleware.js",
project_root,
indexmap! {
"VAR_USERLAND" => 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

View file

@ -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<String> {
Vc::cell("client modules".to_string())
fn client_modules_modifier() -> Vc<RcStr> {
Vc::cell("client modules".into())
}
#[turbo_tasks::function]
fn client_modules_ssr_modifier() -> Vc<String> {
Vc::cell("client modules ssr".to_string())
fn client_modules_ssr_modifier() -> Vc<RcStr> {
Vc::cell("client modules ssr".into())
}
#[turbo_tasks::value]

View file

@ -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<Box<dyn EcmascriptChunkPlaceable>>,
/// The source code config for this entry.

View file

@ -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(),
))
}

View file

@ -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<Box<dyn AssetContext>>,
project_root: Vc<FileSystemPath>,
entry: Vc<Box<dyn Module>>,
pathname: String,
pathname: RcStr,
) -> Result<Vc<Box<dyn Module>>> {
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

View file

@ -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<String> {
Vc::cell("module".to_string())
fn to_string(&self) -> Vc<RcStr> {
Vc::cell("module".into())
}
}

View file

@ -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<FileSystemPath>) -> Result<u64> {
pub async fn dynamic_image_metadata_source(
asset_context: Vc<Box<dyn AssetContext>>,
path: Vc<FileSystemPath>,
ty: String,
ty: RcStr,
page: AppPage,
) -> Result<Vc<Box<dyn Source>>> {
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<Box<dyn Module>>) -> Result<Vc<Vec<String>>> {
async fn collect_direct_exports(module: Vc<Box<dyn Module>>) -> Result<Vc<Vec<RcStr>>> {
let Some(ecmascript_asset) =
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(module).await?
else {

View file

@ -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<MetadataFileMatch<'a>> {
let (stem, ext) = filename.split_once('.')?;
@ -115,7 +115,7 @@ pub(crate) async fn get_content_type(path: Vc<FileSystemPath>) -> Result<String>
pub fn match_local_metadata_file<'a>(
basename: &'a str,
page_extensions: &[String],
page_extensions: &[RcStr],
) -> Option<MetadataFileMatch<'a>> {
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<GlobalMetadataFileMatch<'a>> {
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<AppPage> {
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))?;

View file

@ -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<FileSystemPath>) -> Result<Vc<Box<dy
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()),
);
@ -218,8 +218,7 @@ async fn dynamic_site_map_route_source(
let mut static_generation_code = "";
if mode.is_production() && page.contains(&PageSegment::Dynamic("[__metadata_id__]".to_string()))
{
if mode.is_production() && page.contains(&PageSegment::Dynamic("[__metadata_id__]".into())) {
static_generation_code = indoc! {
r#"
export async function generateStaticParams() {
@ -297,7 +296,7 @@ async fn dynamic_site_map_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()),
);
@ -355,7 +354,7 @@ async fn dynamic_image_route_source(path: Vc<FileSystemPath>) -> Result<Vc<Box<d
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()),
);

View file

@ -14,7 +14,7 @@ use std::{
use anyhow::{bail, Result};
use serde::{Deserialize, Serialize};
use turbo_tasks::{trace::TraceRawVcs, TaskInput};
use turbo_tasks::{trace::TraceRawVcs, RcStr, TaskInput};
pub use crate::next_app::{
app_client_references_chunks::{get_app_client_references_chunks, ClientReferencesChunks},
@ -40,17 +40,17 @@ pub use crate::next_app::{
)]
pub enum PageSegment {
/// e.g. `/dashboard`
Static(String),
Static(RcStr),
/// e.g. `/[id]`
Dynamic(String),
Dynamic(RcStr),
/// e.g. `/[...slug]`
CatchAll(String),
CatchAll(RcStr),
/// e.g. `/[[...slug]]`
OptionalCatchAll(String),
OptionalCatchAll(RcStr),
/// e.g. `/(shop)`
Group(String),
Group(RcStr),
/// e.g. `/@auth`
Parallel(String),
Parallel(RcStr),
/// The final page type appended. (e.g. `/dashboard/page`,
/// `/api/hello/route`)
PageType(PageType),
@ -67,32 +67,32 @@ impl PageSegment {
}
if let Some(s) = segment.strip_prefix('(').and_then(|s| s.strip_suffix(')')) {
return Ok(PageSegment::Group(s.to_string()));
return Ok(PageSegment::Group(s.into()));
}
if let Some(s) = segment.strip_prefix('@') {
return Ok(PageSegment::Parallel(s.to_string()));
return Ok(PageSegment::Parallel(s.into()));
}
if let Some(s) = segment
.strip_prefix("[[...")
.and_then(|s| s.strip_suffix("]]"))
{
return Ok(PageSegment::OptionalCatchAll(s.to_string()));
return Ok(PageSegment::OptionalCatchAll(s.into()));
}
if let Some(s) = segment
.strip_prefix("[...")
.and_then(|s| s.strip_suffix(']'))
{
return Ok(PageSegment::CatchAll(s.to_string()));
return Ok(PageSegment::CatchAll(s.into()));
}
if let Some(s) = segment.strip_prefix('[').and_then(|s| s.strip_suffix(']')) {
return Ok(PageSegment::Dynamic(s.to_string()));
return Ok(PageSegment::Dynamic(s.into()));
}
Ok(PageSegment::Static(segment.to_string()))
Ok(PageSegment::Static(segment.into()))
}
}
@ -308,13 +308,13 @@ impl PartialOrd for AppPage {
)]
pub enum PathSegment {
/// e.g. `/dashboard`
Static(String),
Static(RcStr),
/// e.g. `/[id]`
Dynamic(String),
Dynamic(RcStr),
/// e.g. `/[...slug]`
CatchAll(String),
CatchAll(RcStr),
/// e.g. `/[[...slug]]`
OptionalCatchAll(String),
OptionalCatchAll(RcStr),
}
impl Display for PathSegment {

View file

@ -1,5 +1,5 @@
use anyhow::Result;
use turbo_tasks::Vc;
use turbo_tasks::{RcStr, Vc};
use turbopack_binding::{
turbo::tasks_fs::FileSystemPath,
turbopack::core::resolve::{options::ImportMapping, ExternalType},
@ -13,22 +13,19 @@ pub async fn get_postcss_package_mapping(
) -> Result<Vc<ImportMapping>> {
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<String>,
package_name: Vc<RcStr>,
) -> Result<Vc<ImportMapping>> {
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()])

View file

@ -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<String, String>) -> CompileTimeDefines {
fn defines(define_env: &IndexMap<RcStr, RcStr>) -> CompileTimeDefines {
let mut defines = IndexMap::new();
for (k, v) in define_env {
defines
.entry(k.split('.').map(|s| s.to_string()).collect::<Vec<String>>())
.entry(k.split('.').map(|s| s.into()).collect::<Vec<RcStr>>())
.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<EnvMap>) -> Result<Vc<FreeVarRefer
Ok(free_var_references!(
..defines(&*define_env.await?).into_iter(),
Buffer = FreeVarReference::EcmaScriptModule {
request: "node:buffer".to_string(),
request: "node:buffer".into(),
lookup_path: None,
export: Some("Buffer".to_string()),
export: Some("Buffer".into()),
},
process = FreeVarReference::EcmaScriptModule {
request: "node:process".to_string(),
request: "node:process".into(),
lookup_path: None,
export: Some("default".to_string()),
export: Some("default".into()),
}
)
.cell())
@ -110,7 +110,7 @@ async fn next_client_free_vars(define_env: Vc<EnvMap>) -> Result<Vc<FreeVarRefer
#[turbo_tasks::function]
pub fn get_client_compile_time_info(
browserslist_query: String,
browserslist_query: RcStr,
define_env: Vc<EnvMap>,
) -> Vc<CompileTimeInfo> {
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<FileSystemPath>,
client_root: Vc<FileSystemPath>,
asset_prefix: Vc<Option<String>>,
asset_prefix: Vc<Option<RcStr>>,
environment: Vc<Environment>,
mode: Vc<NextMode>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
@ -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<FileSystemPath>) -> Vc<FileSystemPath> {
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(),
);

View file

@ -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<String> {
Vc::cell("css client reference".to_string())
fn css_client_reference_modifier() -> Vc<RcStr> {
Vc::cell("css client reference".into())
}
#[turbo_tasks::value_impl]

View file

@ -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<String> {
Vc::cell("ecmascript client reference".to_string())
fn ecmascript_client_reference_modifier() -> Vc<RcStr> {
Vc::cell("ecmascript client reference".into())
}
#[turbo_tasks::value_impl]

View file

@ -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<String> {
Vc::cell("client proxy".to_string())
fn client_proxy_modifier() -> Vc<RcStr> {
Vc::cell("client proxy".into())
}
#[turbo_tasks::function]
fn client_reference_description() -> Vc<String> {
Vc::cell("client references".to_string())
fn client_reference_description() -> Vc<RcStr> {
Vc::cell("client references".into())
}
#[turbo_tasks::value_impl]

View file

@ -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<Self>, layer: Vc<String>) -> Vc<String> {
fn process_layer(self: Vc<Self>, layer: Vc<RcStr>) -> Vc<RcStr> {
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

View file

@ -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<String>),
ServerComponentEntry(Vc<NextServerComponentModule>, ReadRef<String>),
Internal(Vc<Box<dyn Module>>, ReadRef<String>),
ClientReference(ClientReference, ReadRef<RcStr>),
ServerComponentEntry(Vc<NextServerComponentModule>, ReadRef<RcStr>),
Internal(Vc<Box<dyn Module>>, ReadRef<RcStr>),
}
impl Visit<VisitClientReferenceNode> for VisitClientReference {
@ -269,13 +269,13 @@ impl Visit<VisitClientReferenceNode> 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())
}
}
}

View file

@ -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,28 +59,28 @@ struct CustomRoutes {
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NextConfig {
pub config_file: Option<String>,
pub config_file_name: String,
pub config_file: Option<RcStr>,
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<f64>,
/// custom path to a cache handler to use
pub cache_handler: Option<String>,
pub cache_handler: Option<RcStr>,
pub env: IndexMap<String, JsonValue>,
pub experimental: ExperimentalConfig,
pub images: ImageConfig,
pub page_extensions: Vec<String>,
pub page_extensions: Vec<RcStr>,
pub react_strict_mode: Option<bool>,
pub transpile_packages: Option<Vec<String>>,
pub transpile_packages: Option<Vec<RcStr>>,
pub modularize_imports: Option<IndexMap<String, ModularizeImportPackageConfig>>,
pub dist_dir: Option<String>,
pub dist_dir: Option<RcStr>,
sass_options: Option<serde_json::Value>,
pub trailing_slash: Option<bool>,
pub asset_prefix: Option<String>,
pub base_path: Option<String>,
pub asset_prefix: Option<RcStr>,
pub base_path: Option<RcStr>,
pub skip_middleware_url_normalize: Option<bool>,
pub skip_trailing_slash_redirect: Option<bool>,
pub i18n: Option<I18NConfig>,
@ -98,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<Vec<String>>,
pub server_external_packages: Option<Vec<RcStr>>,
#[serde(rename = "_originalRedirects")]
pub original_redirects: Option<Vec<Redirect>>,
@ -223,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<String>,
value: Option<RcStr>,
},
Cookie {
key: String,
key: RcStr,
#[serde(skip_serializing_if = "Option::is_none")]
value: Option<String>,
value: Option<RcStr>,
},
Query {
key: String,
key: RcStr,
#[serde(skip_serializing_if = "Option::is_none")]
value: Option<String>,
value: Option<RcStr>,
},
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)]
@ -413,9 +413,9 @@ pub enum RemotePatternProtocal {
pub struct ExperimentalTurboConfig {
/// This option has been replaced by `rules`.
pub loaders: Option<JsonValue>,
pub rules: Option<IndexMap<String, RuleConfigItemOrShortcut>>,
pub resolve_alias: Option<IndexMap<String, JsonValue>>,
pub resolve_extensions: Option<Vec<String>>,
pub rules: Option<IndexMap<RcStr, RuleConfigItemOrShortcut>>,
pub resolve_alias: Option<IndexMap<RcStr, JsonValue>>,
pub resolve_extensions: Option<Vec<RcStr>>,
pub use_swc_css: Option<bool>,
}
@ -424,7 +424,7 @@ pub struct ExperimentalTurboConfig {
pub struct RuleConfigItemOptions {
pub loaders: Vec<LoaderItem>,
#[serde(default, alias = "as")]
pub rename_as: Option<String>,
pub rename_as: Option<RcStr>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)]
@ -438,14 +438,14 @@ pub enum RuleConfigItemOrShortcut {
#[serde(rename_all = "camelCase", untagged)]
pub enum RuleConfigItem {
Options(RuleConfigItemOptions),
Conditional(IndexMap<String, RuleConfigItem>),
Conditional(IndexMap<RcStr, RuleConfigItem>),
Boolean(bool),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)]
#[serde(untagged)]
pub enum LoaderItem {
LoaderName(String),
LoaderName(RcStr),
LoaderOptions(WebpackLoaderItem),
}
@ -473,7 +473,7 @@ pub struct ReactCompilerOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub compilation_mode: Option<ReactCompilerMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub panic_threshold: Option<String>,
pub panic_threshold: Option<RcStr>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
@ -489,26 +489,26 @@ pub struct OptionalReactCompilerOptions(Option<Vc<ReactCompilerOptions>>);
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "camelCase")]
pub struct ExperimentalConfig {
pub allowed_revalidate_header_keys: Option<Vec<String>>,
pub allowed_revalidate_header_keys: Option<Vec<RcStr>>,
pub client_router_filter: Option<bool>,
/// 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<f64>,
pub client_router_filter_redirects: Option<bool>,
pub fetch_cache_key_prefix: Option<String>,
pub fetch_cache_key_prefix: Option<RcStr>,
pub isr_flush_to_disk: Option<bool>,
/// 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<MdxRsOptions>,
pub strict_next_head: Option<bool>,
pub swc_plugins: Option<Vec<(String, serde_json::Value)>>,
pub swc_plugins: Option<Vec<(RcStr, serde_json::Value)>>,
pub turbo: Option<ExperimentalTurboConfig>,
pub turbotrace: Option<serde_json::Value>,
pub external_middleware_rewrites_resolve: Option<bool>,
pub scroll_restoration: Option<bool>,
pub use_deployment_id: Option<bool>,
pub use_deployment_id_server_actions: Option<bool>,
pub deployment_id: Option<String>,
pub deployment_id: Option<RcStr>,
pub manual_client_base_path: Option<bool>,
pub optimistic_client_cache: Option<bool>,
pub middleware_prefetch: Option<MiddlewarePrefetchType>,
@ -516,7 +516,7 @@ pub struct ExperimentalConfig {
/// Use Record<string, unknown> 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<serde_json::Value>,
pub next_script_workers: Option<bool>,
pub web_vitals_attribution: Option<Vec<String>>,
pub web_vitals_attribution: Option<Vec<RcStr>>,
pub server_actions: Option<ServerActionsOrLegacyBool>,
pub sri: Option<SubResourceIntegrity>,
react_compiler: Option<ReactCompilerOptionsOrBoolean>,
@ -554,10 +554,10 @@ pub struct ExperimentalConfig {
optimize_server_react: Option<bool>,
/// Automatically apply the "modularize_imports" optimization to imports of
/// the specified packages.
optimize_package_imports: Option<Vec<String>>,
output_file_tracing_ignores: Option<Vec<String>>,
optimize_package_imports: Option<Vec<RcStr>>,
output_file_tracing_ignores: Option<Vec<RcStr>>,
output_file_tracing_includes: Option<serde_json::Value>,
output_file_tracing_root: Option<String>,
output_file_tracing_root: Option<RcStr>,
/// Using this feature will enable the `react@experimental` for the `app`
/// directory.
ppr: Option<ExperimentalPartialPrerendering>,
@ -760,7 +760,7 @@ impl RemoveConsoleConfig {
}
#[turbo_tasks::value(transparent)]
pub struct ResolveExtensions(Option<Vec<String>>);
pub struct ResolveExtensions(Option<Vec<RcStr>>);
#[turbo_tasks::value(transparent)]
pub struct OptionalMdxTransformOptions(Option<Vc<MdxTransformOptions>>);
@ -768,7 +768,7 @@ pub struct OptionalMdxTransformOptions(Option<Vc<MdxTransformOptions>>);
#[turbo_tasks::value_impl]
impl NextConfig {
#[turbo_tasks::function]
pub async fn from_string(string: Vc<String>) -> Result<Vc<Self>> {
pub async fn from_string(string: Vc<RcStr>) -> Result<Vc<Self>> {
let string = string.await?;
let config: NextConfig = serde_json::from_str(&string)
.with_context(|| format!("failed to parse next.config.js: {}", string))?;
@ -781,7 +781,7 @@ impl NextConfig {
}
#[turbo_tasks::function]
pub async fn server_external_packages(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
pub async fn server_external_packages(self: Vc<Self>) -> Result<Vc<Vec<RcStr>>> {
Ok(Vc::cell(
self.await?
.server_external_packages
@ -802,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()
},
)
})
@ -822,12 +822,12 @@ impl NextConfig {
}
#[turbo_tasks::function]
pub async fn page_extensions(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
pub async fn page_extensions(self: Vc<Self>) -> Result<Vc<Vec<RcStr>>> {
Ok(Vc::cell(self.await?.page_extensions.clone()))
}
#[turbo_tasks::function]
pub async fn transpile_packages(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
pub async fn transpile_packages(self: Vc<Self>) -> Result<Vc<Vec<RcStr>>> {
Ok(Vc::cell(
self.await?.transpile_packages.clone().unwrap_or_default(),
))
@ -836,7 +836,7 @@ impl NextConfig {
#[turbo_tasks::function]
pub async fn webpack_rules(
self: Vc<Self>,
active_conditions: Vec<String>,
active_conditions: Vec<RcStr>,
) -> Result<Vc<OptionWebpackRules>> {
let this = self.await?;
let Some(turbo_rules) = this
@ -874,7 +874,7 @@ impl NextConfig {
}
fn find_rule<'a>(
rule: &'a RuleConfigItem,
active_conditions: &HashSet<String>,
active_conditions: &HashSet<RcStr>,
) -> FindRuleResult<'a> {
match rule {
RuleConfigItem::Options(rule) => FindRuleResult::Found(rule),
@ -900,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,
@ -912,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(),
@ -980,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()
@ -1041,18 +1040,21 @@ 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<Self>) -> Result<Vc<Option<String>>> {
pub async fn computed_asset_prefix(self: Vc<Self>) -> Result<Vc<Option<RcStr>>> {
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]
@ -1090,7 +1092,7 @@ impl NextConfig {
}
#[turbo_tasks::function]
pub async fn optimize_package_imports(self: Vc<Self>) -> Result<Vc<Vec<String>>> {
pub async fn optimize_package_imports(self: Vc<Self>) -> Result<Vc<Vec<RcStr>>> {
Ok(Vc::cell(
self.await?
.experimental
@ -1113,7 +1115,7 @@ pub struct JsConfig {
#[turbo_tasks::value_impl]
impl JsConfig {
#[turbo_tasks::function]
pub async fn from_string(string: Vc<String>) -> Result<Vc<Self>> {
pub async fn from_string(string: Vc<RcStr>) -> Result<Vc<Self>> {
let string = string.await?;
let config: JsConfig = serde_json::from_str(&string)
.with_context(|| format!("failed to parse next.config.js: {}", string))?;
@ -1132,9 +1134,9 @@ impl JsConfig {
#[turbo_tasks::value]
struct OutdatedConfigIssue {
path: Vc<FileSystemPath>,
old_name: String,
new_name: String,
description: String,
old_name: RcStr,
new_name: RcStr,
description: RcStr,
}
#[turbo_tasks::value_impl]
@ -1158,7 +1160,7 @@ impl Issue for OutdatedConfigIssue {
fn title(&self) -> Vc<StyledString> {
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()
@ -1166,8 +1168,6 @@ impl Issue for OutdatedConfigIssue {
#[turbo_tasks::function]
fn description(&self) -> Vc<OptionStyledString> {
Vc::cell(Some(
StyledString::Text(self.description.to_string()).cell(),
))
Vc::cell(Some(StyledString::Text(self.description.clone()).cell()))
}
}

View file

@ -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<String> {
Vc::cell("dynamic".to_string())
fn dynamic_modifier() -> Vc<RcStr> {
Vc::cell("dynamic".into())
}
#[turbo_tasks::value_impl]

View file

@ -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<Self>, layer: Vc<String>) -> Vc<String> {
fn process_layer(self: Vc<Self>, layer: Vc<RcStr>) -> Vc<RcStr> {
layer
}

View file

@ -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<NextDynamicEntryModule>, ReadRef<String>),
Internal(Vc<Box<dyn Module>>, ReadRef<String>),
Dynamic(Vc<NextDynamicEntryModule>, ReadRef<RcStr>),
Internal(Vc<Box<dyn Module>>, ReadRef<RcStr>),
}
impl Visit<VisitDynamicNode> for VisitDynamic {
@ -117,10 +117,10 @@ impl Visit<VisitDynamicNode> 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())
}
}
}

View file

@ -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<String, String>) -> CompileTimeDefines {
fn defines(define_env: &IndexMap<RcStr, RcStr>) -> CompileTimeDefines {
let mut defines = IndexMap::new();
for (k, v) in define_env {
defines
.entry(k.split('.').map(|s| s.to_string()).collect::<Vec<String>>())
.entry(k.split('.').map(|s| s.into()).collect::<Vec<RcStr>>())
.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<FileSystemPath>,
node_root: Vc<FileSystemPath>,
client_root: Vc<FileSystemPath>,
asset_prefix: Vc<Option<String>>,
asset_prefix: Vc<Option<RcStr>>,
environment: Vc<Environment>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
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<FileSystemPath>,
environment: Vc<Environment>,
) -> Result<Vc<Box<dyn ChunkingContext>>> {
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(),
))

View file

@ -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<Box<dyn AssetContext>>,
project_root: Vc<FileSystemPath>,
entry: Vc<Box<dyn Module>>,
pathname: String,
pathname: RcStr,
) -> Result<Vc<Box<dyn Module>>> {
// 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

View file

@ -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<ImportMapping> {
fn replace(&self, _capture: RcStr) -> Vc<ImportMapping> {
ImportMapping::Ignore.into()
}

View file

@ -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<DefaultFallbackFont> =
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<DefaultFallbackFont> =
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<DefaultFallbackFont> =
#[turbo_tasks::value(shared)]
pub(crate) struct AutomaticFontFallback {
/// e.g. `__Roboto_Fallback_c123b8`
pub scoped_font_family: Vc<String>,
pub scoped_font_family: Vc<RcStr>,
/// The name of font locally, used in `src: local("{}")`
pub local_font_family: Vc<String>,
pub local_font_family: Vc<RcStr>,
pub adjustment: Option<FontAdjustment>,
}
@ -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<String>),
Manual(Vec<RcStr>),
}
#[turbo_tasks::value_impl]

View file

@ -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<String, FontMetricsMapEntry>);
pub(super) struct FontMetricsMap(pub HashMap<RcStr, FontMetricsMapEntry>);
#[derive(Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
struct Fallback {
pub font_family: String,
pub font_family: RcStr,
pub adjustment: Option<FontAdjustment>,
}
@ -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<Regex> = 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: &regex::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,

View file

@ -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<String, FontDataEntry>);
struct FontData(IndexMap<RcStr, FontDataEntry>);
#[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<Vc<ImportMapResult>> {
async fn import_map_result(&self, query: RcStr) -> Result<Vc<ImportMapResult>> {
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<ImportMapping> {
fn replace(&self, _capture: RcStr) -> Vc<ImportMapping> {
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<Vc<ImportMapResult>> {
async fn import_map_result(&self, query: RcStr) -> Result<Vc<ImportMapResult>> {
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::<Box<dyn ProcessEnv>>(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<ImportMapping> {
fn replace(&self, _capture: RcStr) -> Vc<ImportMapping> {
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<ImportMapping> {
fn replace(&self, _capture: RcStr) -> Vc<ImportMapping> {
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<FileSystemPath>) -> Result<Vc<FontData>> {
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<FileSystemPath>) -> Result<Vc<FontData>
/// font family names.
#[turbo_tasks::function]
async fn update_google_stylesheet(
stylesheet: Vc<String>,
stylesheet: Vc<RcStr>,
options: Vc<NextFontGoogleOptions>,
scoped_font_family: Vc<String>,
scoped_font_family: Vc<RcStr>,
has_size_adjust: Vc<bool>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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<FontFile> {
fn find_font_files_in_css(css: &str, subsets_to_preload: &[RcStr]) -> Vec<FontFile> {
let mut font_files: Vec<FontFile> = Vec::new();
let mut current_subset = "";
@ -482,7 +484,7 @@ fn find_font_files_in_css(css: &str, subsets_to_preload: &[String]) -> Vec<FontF
async fn get_stylesheet_url_from_options(
options: Vc<NextFontGoogleOptions>,
font_data: Vc<FontData>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
#[allow(unused_mut, unused_assignments)] // This is used in test environments
let mut css_url: Option<String> = 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<String>,
query: Vc<RcStr>,
font_data: Vc<FontData>,
) -> Result<Vc<NextFontGoogleOptions>> {
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<String>,
query: Vc<RcStr>,
) -> Result<NextFontGoogleFontFileOptions> {
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<String>,
stylesheet_url: Vc<RcStr>,
css_virtual_path: Vc<FileSystemPath>,
) -> Result<Option<Vc<String>>> {
) -> Result<Option<Vc<RcStr>>> {
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<String>,
url: Vc<RcStr>,
virtual_path: Vc<FileSystemPath>,
) -> Result<Option<Vc<HttpResponseBody>>> {
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<String>,
stylesheet_url: Vc<RcStr>,
mocked_responses_path: &str,
execution_context: Vc<ExecutionContext>,
) -> Result<Option<Vc<String>>> {
) -> Result<Option<Vc<RcStr>>> {
let response_path = Path::new(&mocked_responses_path);
let mock_fs = Vc::upcast::<Box<dyn FileSystem>>(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<String, Option<String>> =
parse_json_with_source_context(val.to_str()?)?;
let val: HashMap<RcStr, Option<RcStr>> = parse_json_with_source_context(val.to_str()?)?;
Ok(val
.get(&*stylesheet_url.await?)
.context("url not found")?

View file

@ -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<String, FontDataEntry>;
pub(super) type FontData = IndexMap<RcStr, FontDataEntry>;
#[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<String>,
pub display: String,
pub styles: Vec<RcStr>,
pub display: RcStr,
pub preload: bool,
pub selected_variable_axes: Option<Vec<String>>,
pub fallback: Option<Vec<String>>,
pub selected_variable_axes: Option<Vec<RcStr>>,
pub fallback: Option<Vec<RcStr>>,
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<String>,
pub subsets: Option<Vec<String>>,
pub variable: Option<RcStr>,
pub subsets: Option<Vec<RcStr>>,
}
#[turbo_tasks::value_impl]
@ -36,8 +36,8 @@ impl NextFontGoogleOptions {
}
#[turbo_tasks::function]
pub async fn font_family(self: Vc<Self>) -> Result<Vc<String>> {
Ok(Vc::cell((*self.await?.font_family).to_owned()))
pub async fn font_family(self: Vc<Self>) -> Result<Vc<RcStr>> {
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<String>,
pub styles: Vec<String>,
pub weights: Vec<RcStr>,
pub styles: Vec<RcStr>,
pub axes: Option<Vec<Axis>>,
}
#[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<String, FontDataEntry>,
data: &IndexMap<RcStr, FontDataEntry>,
) -> Result<NextFontGoogleOptions> {
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<String> = argument
let requested_weights: IndexSet<RcStr> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = parse_json_with_source_context(
r#"
{
"ABeeZee": {
@ -314,7 +315,7 @@ mod tests {
#[test]
fn test_errors_on_unnecessary_weights() -> Result<()> {
let data: IndexMap<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = parse_json_with_source_context(
r#"
{
"ABeeZee": {
@ -353,7 +354,7 @@ mod tests {
#[test]
fn test_errors_on_unvavailable_weights() -> Result<()> {
let data: IndexMap<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = parse_json_with_source_context(
r#"
{
"ABeeZee": {
@ -495,7 +496,7 @@ mod tests {
#[test]
fn test_errors_on_unknown_display() -> Result<()> {
let data: IndexMap<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = 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<String, FontDataEntry> = parse_json_with_source_context(
let data: IndexMap<RcStr, FontDataEntry> = parse_json_with_source_context(
r#"
{
"ABeeZee": {

View file

@ -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<NextFontRequestArguments>,
}
#[derive(Clone, Debug, Default, Deserialize)]
pub(super) struct NextFontRequestArguments {
pub weight: Option<OneOrManyStrings>,
pub subsets: Option<Vec<String>>,
pub subsets: Option<Vec<RcStr>>,
pub style: Option<OneOrManyStrings>,
pub display: Option<String>,
pub display: Option<RcStr>,
pub preload: Option<bool>,
pub axes: Option<Vec<String>>,
pub fallback: Option<Vec<String>>,
pub axes: Option<Vec<RcStr>>,
pub fallback: Option<Vec<RcStr>>,
pub adjust_font_fallback: Option<bool>,
pub variable: Option<String>,
pub variable: Option<RcStr>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub(super) enum OneOrManyStrings {
One(String),
Many(Vec<String>),
One(RcStr),
Many(Vec<RcStr>),
}

View file

@ -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<Option<String>>,
base_stylesheet: Vc<Option<RcStr>>,
font_css_properties: Vc<FontCssProperties>,
font_fallback: Vc<FontFallback>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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()))
}

View file

@ -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<String>,
pub(super) wght: IndexSet<RcStr>,
pub(super) ital: IndexSet<FontStyle>,
pub(super) variable_axes: Option<Vec<(String, String)>>,
pub(super) variable_axes: Option<Vec<(RcStr, RcStr)>>,
}
#[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<Vec<String>>,
styles: &[RcStr],
selected_variable_axes: &Option<Vec<RcStr>>,
) -> Result<FontAxes> {
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::<Vec<String>>();
.collect::<Vec<RcStr>>();
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
},

View file

@ -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),
}

View file

@ -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<f64> {
#[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<String>) -> 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) => {

View file

@ -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> {
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<String>) -> Result<Vc<NextFontLocalOptions>> {
async fn font_options_from_query_map(query: Vc<RcStr>) -> Result<Vc<NextFontLocalOptions>> {
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<String>) -> Result<Vc<NextFontLoc
}
async fn font_file_options_from_query_map(
query: Vc<String>,
query: Vc<RcStr>,
) -> Result<NextFontLocalFontFileOptions> {
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<String>,
font_path: Vc<RcStr>,
origin_path: Vc<FileSystemPath>,
}
@ -335,9 +344,9 @@ impl Issue for FontResolvingIssue {
async fn title(self: Vc<Self>) -> Result<Vc<StyledString>> {
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())
}

View file

@ -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<FontWeight>,
pub default_style: Option<String>,
pub default_style: Option<RcStr>,
/// 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<Vec<String>>,
pub fallback: Option<Vec<RcStr>>,
/// 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<String>,
pub variable: Option<RcStr>,
/// 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<Self>) -> Result<Vc<String>> {
Ok(Vc::cell((*self.await?.variable_name).to_owned()))
pub async fn font_family(self: Vc<Self>) -> Result<Vc<RcStr>> {
Ok(Vc::cell(self.await?.variable_name.clone()))
}
}
@ -54,9 +54,9 @@ impl NextFontLocalOptions {
)]
pub(super) struct FontDescriptor {
pub weight: Option<FontWeight>,
pub style: Option<String>,
pub path: String,
pub ext: String,
pub style: Option<RcStr>,
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<Self, Self::Err> {
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<Nex
),
SrcRequest::One(path) => {
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()
},
);

View file

@ -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<String>,
pub style: Option<String>,
pub weight: Option<RcStr>,
pub style: Option<RcStr>,
#[serde(default = "default_display")]
pub display: String,
pub display: RcStr,
#[serde(default = "default_preload")]
pub preload: bool,
pub fallback: Option<Vec<String>>,
pub fallback: Option<Vec<RcStr>>,
#[serde(
default = "default_adjust_font_fallback",
deserialize_with = "deserialize_adjust_font_fallback"
)]
pub adjust_font_fallback: AdjustFontFallback,
pub variable: Option<String>,
pub variable: Option<RcStr>,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub(super) enum SrcRequest {
One(String),
One(RcStr),
Many(Vec<SrcDescriptor>),
}
#[derive(Clone, Debug, Deserialize)]
pub(super) struct SrcDescriptor {
pub path: String,
pub weight: Option<String>,
pub style: Option<String>,
pub path: RcStr,
pub weight: Option<RcStr>,
pub style: Option<RcStr>,
}
/// 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)]

View file

@ -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<NextFontLocalOptions>,
fallbacks: Vc<FontFallbacks>,
css_properties: Vc<FontCssProperties>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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<String>,
scoped_font_family: Vc<RcStr>,
options: Vc<NextFontLocalOptions>,
has_size_adjust: Vc<bool>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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`

View file

@ -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<NextFontLocalOptions>,
font_fallbacks: Vc<FontFallbacks>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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()))
}

View file

@ -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<FontFallbacks>) -> Result<Vc<String>> {
pub(crate) async fn build_fallback_definition(fallbacks: Vc<FontFallbacks>) -> Result<Vc<RcStr>> {
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<FontFallbacks>) -> R
}
}
Ok(Vc::cell(res))
Ok(Vc::cell(res.into()))
}
#[turbo_tasks::function]
pub(super) async fn build_font_class_rules(
css_properties: Vc<FontCssProperties>,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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 {

View file

@ -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<String>,
pub weight: Vc<Option<String>>,
pub style: Vc<Option<String>>,
pub variable: Vc<Option<String>>,
pub font_family: Vc<RcStr>,
pub weight: Vc<Option<RcStr>>,
pub style: Vc<Option<RcStr>>,
pub variable: Vc<Option<RcStr>>,
}
/// 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<FontFamilyType>,
font_family_name: Vc<String>,
) -> Result<Vc<String>> {
font_family_name: Vc<RcStr>,
) -> Result<Vc<RcStr>> {
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<String>, request_hash: u32) -> Result<Vc<String>> {
Ok(Vc::cell(format!(
"{}_{:x?}",
font_family.await?.to_lowercase().replace(' ', "_"),
request_hash
)))
pub async fn get_request_id(font_family: Vc<RcStr>, request_hash: u32) -> Result<Vc<RcStr>> {
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<FileSystemPath>,
query: Vc<String>,
query: Vc<RcStr>,
) -> Result<bool> {
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(),

View file

@ -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();

View file

@ -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<String> {
Vc::cell("structured image object".to_string())
fn modifier() -> Vc<RcStr> {
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())
}
}

View file

@ -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<ImportMap> {
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<FileSystemPath>) -> Result<V
let result = resolve(
context_directory,
Value::new(ReferenceType::CommonJs(CommonJsReferenceSubType::Undefined)),
Request::parse(Value::new(Pattern::Constant(
"next/package.json".to_string(),
))),
Request::parse(Value::new(Pattern::Constant("next/package.json".into()))),
node_cjs_resolve_options(context_directory.root()),
);
let source = result
@ -923,7 +914,7 @@ pub async fn insert_alias_option<const N: usize>(
alias_options: Vc<ResolveAliasMap>,
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<const N: usize>(
fn export_value_to_import_mapping(
value: &SubpathValue,
conditions: &BTreeMap<String, ConditionValue>,
conditions: &BTreeMap<RcStr, ConditionValue>,
project_path: Vc<FileSystemPath>,
) -> Option<Vc<ImportMapping>> {
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<String> + 'a,
alternatives: Vec<Vc<ImportMapping>>,
) {
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<FileSystemPath>, request: &str) -> Vc<ImportMapping> {
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> {
ImportMapping::External(Some(request.to_string()), ExternalType::CommonJs).into()
ImportMapping::External(Some(request.into()), ExternalType::CommonJs).into()
}

View file

@ -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<FileSystemPath>,
client_relative_path: Vc<FileSystemPath>,
entry_name: String,
entry_name: RcStr,
client_references: Vc<ClientReferenceGraphResult>,
client_references_chunks: Vc<ClientReferencesChunks>,
client_chunking_context: Vc<Box<dyn ChunkingContext>>,
@ -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::<Vec<_>>()
} 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::<Vec<_>>()
} 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()
}
}

View file

@ -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<String, String>,
pub pages: HashMap<RcStr, RcStr>,
}
#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BuildManifest {
pub dev_files: Vec<String>,
pub amp_dev_files: Vec<String>,
pub polyfill_files: Vec<String>,
pub low_priority_files: Vec<String>,
pub root_main_files: Vec<String>,
pub pages: HashMap<String, Vec<String>>,
pub amp_first_pages: Vec<String>,
pub dev_files: Vec<RcStr>,
pub amp_dev_files: Vec<RcStr>,
pub polyfill_files: Vec<RcStr>,
pub low_priority_files: Vec<RcStr>,
pub root_main_files: Vec<RcStr>,
pub pages: HashMap<RcStr, Vec<RcStr>>,
pub amp_first_pages: Vec<RcStr>,
}
#[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<String>,
pub regexp: Option<RcStr>,
#[serde(skip_serializing_if = "bool_is_true")]
pub locale: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub has: Option<Vec<RouteHas>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub missing: Option<Vec<RouteHas>>,
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<String>,
pub name: String,
pub page: String,
pub files: Vec<RcStr>,
pub name: RcStr,
pub page: RcStr,
pub matchers: Vec<MiddlewareMatcher>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub wasm: Vec<AssetBinding>,
@ -88,13 +88,13 @@ pub struct EdgeFunctionDefinition {
pub assets: Vec<AssetBinding>,
#[serde(skip_serializing_if = "Option::is_none")]
pub regions: Option<Regions>,
pub env: IndexMap<String, String>,
pub env: IndexMap<RcStr, RcStr>,
}
#[derive(Serialize, Default, Debug)]
pub struct InstrumentationDefinition {
pub files: Vec<String>,
pub name: String,
pub files: Vec<RcStr>,
pub name: RcStr,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub wasm: Vec<AssetBinding>,
#[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<String>),
Single(String),
Multiple(Vec<RcStr>),
Single(RcStr),
}
#[derive(Serialize, Default, Debug)]
pub struct MiddlewaresManifestV2 {
pub sorted_middleware: Vec<String>,
pub middleware: HashMap<String, EdgeFunctionDefinition>,
pub sorted_middleware: Vec<RcStr>,
pub middleware: HashMap<RcStr, EdgeFunctionDefinition>,
pub instrumentation: Option<InstrumentationDefinition>,
pub functions: HashMap<String, EdgeFunctionDefinition>,
pub functions: HashMap<RcStr, EdgeFunctionDefinition>,
}
#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ReactLoadableManifest {
#[serde(flatten)]
pub manifest: HashMap<String, ReactLoadableManifestEntry>,
pub manifest: HashMap<RcStr, ReactLoadableManifestEntry>,
}
#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ReactLoadableManifestEntry {
pub id: u32,
pub files: Vec<String>,
pub files: Vec<RcStr>,
}
#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct NextFontManifest {
pub pages: HashMap<String, Vec<String>>,
pub app: HashMap<String, Vec<String>>,
pub pages: HashMap<RcStr, Vec<RcStr>>,
pub app: HashMap<RcStr, Vec<RcStr>>,
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<String>,
pub id: RcStr,
pub files: Vec<RcStr>,
}
#[derive(Serialize, Default, Debug)]
@ -228,16 +228,16 @@ pub struct ClientReferenceManifest {
pub edge_ssr_module_mapping: HashMap<ModuleId, ManifestNode>,
/// Mapping of server component path to required CSS client chunks.
#[serde(rename = "entryCSSFiles")]
pub entry_css_files: HashMap<String, IndexSet<String>>,
pub entry_css_files: HashMap<RcStr, IndexSet<RcStr>>,
/// Mapping of server component path to required JS client chunks.
#[serde(rename = "entryJSFiles")]
pub entry_js_files: HashMap<String, IndexSet<String>>,
pub entry_js_files: HashMap<RcStr, IndexSet<RcStr>>,
}
#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ModuleLoading {
pub prefix: String,
pub prefix: RcStr,
pub cross_origin: Option<CrossOriginConfig>,
}
@ -246,7 +246,7 @@ pub struct ModuleLoading {
pub struct ManifestNode {
/// Mapping of export name to manifest node entry.
#[serde(flatten)]
pub module_exports: HashMap<String, ManifestNodeEntry>,
pub module_exports: HashMap<RcStr, ManifestNodeEntry>,
}
#[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<String>,
pub chunks: Vec<RcStr>,
// 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<FontManifestEntry>);
#[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<String, Vec<String>>,
pub pages: HashMap<RcStr, Vec<RcStr>>,
}
// 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<String, Vec<&'a str>>,
pub pages: HashMap<RcStr, Vec<&'a str>>,
}

View file

@ -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<String>,
pathname: Vc<RcStr>,
reference_type: Value<ReferenceType>,
project_root: Vc<FileSystemPath>,
ssr_module_context: Vc<Box<dyn AssetContext>>,
source: Vc<Box<dyn Source>>,
next_original_name: Vc<String>,
next_original_name: Vc<RcStr>,
pages_structure: Vc<PagesStructure>,
runtime: NextRuntime,
next_config: Vc<NextConfig>,
@ -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<Box<dyn AssetContext>>,
project_root: Vc<FileSystemPath>,
entry: Vc<Box<dyn Module>>,
page: String,
pathname: String,
page: RcStr,
pathname: RcStr,
reference_type: Value<ReferenceType>,
pages_structure: Vc<PagesStructure>,
next_config: Vc<NextConfig>,
@ -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(),
},
}
}

View file

@ -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<String>,
path: Vc<RcStr>,
}
#[turbo_tasks::value_impl]
impl NextExactMatcher {
#[turbo_tasks::function]
pub async fn new(path: Vc<String>) -> Result<Vc<Self>> {
pub async fn new(path: Vc<RcStr>) -> Result<Vc<Self>> {
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<Vc<bool>> {
async fn matches(&self, path: RcStr) -> Result<Vc<bool>> {
Ok(Vc::cell(path == *self.path.await?))
}
#[turbo_tasks::function]
async fn params(&self, path: String) -> Result<Vc<Params>> {
async fn params(&self, path: RcStr) -> Result<Vc<Params>> {
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<String>) -> Result<Vc<Self>> {
pub async fn new(path: Vc<RcStr>) -> Result<Vc<Self>> {
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<bool> {
fn matches(&self, path: RcStr) -> Vc<bool> {
Vc::cell(self.matcher.matches(&path))
}
#[turbo_tasks::function]
fn params(&self, path: String) -> Vc<Params> {
fn params(&self, path: RcStr) -> Vc<Params> {
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<String>, prefix: String, suffix: String) -> Result<Vc<Self>> {
pub async fn new(path: Vc<RcStr>, prefix: RcStr, suffix: RcStr) -> Result<Vc<Self>> {
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<bool> {
fn matches(&self, path: RcStr) -> Vc<bool> {
Vc::cell(self.matcher.matches(&path))
}
#[turbo_tasks::function]
fn params(&self, path: String) -> Vc<Params> {
fn params(&self, path: RcStr) -> Vc<Params> {
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<bool> {
fn matches(&self, path: RcStr) -> Vc<bool> {
Vc::cell(self.matcher.matches(&path))
}
#[turbo_tasks::function]
fn params(&self, path: String) -> Vc<Params> {
fn params(&self, path: RcStr) -> Vc<Params> {
Params::cell(self.matcher.params(&path))
}
}

View file

@ -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(),
),
},

View file

@ -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<FileSystemPath>,
ecmascript_client_reference_transition_name: Option<Vc<String>>,
ecmascript_client_reference_transition_name: Option<Vc<RcStr>>,
client_transition: Option<Vc<Box<dyn Transition>>>,
},
AppRoute {
app_dir: Vc<FileSystemPath>,
ecmascript_client_reference_transition_name: Option<Vc<String>>,
ecmascript_client_reference_transition_name: Option<Vc<RcStr>>,
},
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<String> = load_next_js_templateon(
let mut external_packages: Vec<RcStr> = 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<String, String>) -> CompileTimeDefines {
fn defines(define_env: &IndexMap<RcStr, RcStr>) -> CompileTimeDefines {
let mut defines = IndexMap::new();
for (k, v) in define_env {
defines
.entry(k.split('.').map(|s| s.to_string()).collect::<Vec<String>>())
.entry(k.split('.').map(|s| s.into()).collect::<Vec<RcStr>>())
.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<FileSystemPath>,
node_root: Vc<FileSystemPath>,
client_root: Vc<FileSystemPath>,
asset_prefix: Vc<Option<String>>,
asset_prefix: Vc<Option<RcStr>>,
environment: Vc<Environment>,
) -> Result<Vc<NodeJsChunkingContext>> {
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(),
)

View file

@ -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<Vec<String>>),
AllExcept(Vc<Vec<RcStr>>),
/// Only mark modules listed as external.
Only(Vc<Vec<String>>),
Only(Vc<Vec<RcStr>>),
}
/// 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<FileSystemPath>) -> Vc<AfterResolvePluginCondition> {
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<PackagesGlobs>);
#[turbo_tasks::function]
async fn packages_glob(packages: Vc<Vec<String>>) -> Result<Vc<OptionPackagesGlobs>> {
async fn packages_glob(packages: Vc<Vec<RcStr>>) -> Result<Vc<OptionPackagesGlobs>> {
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<Vec<String>>) -> Result<Vc<OptionPackagesGlo
#[turbo_tasks::value]
struct UnableToExternalize {
file_path: Vc<FileSystemPath>,
request: String,
reason: String,
request: RcStr,
reason: RcStr,
}
#[turbo_tasks::value_impl]
@ -476,17 +476,18 @@ impl Issue for UnableToExternalize {
.take(2)
.intersperse("/")
.collect::<String>()
.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(),
))

View file

@ -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<String> {
Vc::cell("Next.js server component".to_string())
fn modifier() -> Vc<RcStr> {
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<EcmascriptExports> {
let exports = BTreeMap::from([(
"default".to_string(),
"default".into(),
EsmExport::ImportedNamespace(Vc::upcast(NextServerComponentModuleReference::new(
Vc::upcast(self.module),
))),

View file

@ -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<Vc<String>> {
Ok(Vc::cell(format!(
"Next.js server component {}",
self.asset.ident().to_string().await?
)))
async fn to_string(&self) -> Result<Vc<RcStr>> {
Ok(Vc::cell(
format!(
"Next.js server component {}",
self.asset.ident().to_string().await?
)
.into(),
))
}
}

View file

@ -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<Self>, layer: Vc<String>) -> Vc<String> {
fn process_layer(self: Vc<Self>, layer: Vc<RcStr>) -> Vc<RcStr> {
layer
}

View file

@ -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> {
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<FileSystemPath>,
pub messages: Vec<String>,
pub messages: Vec<RcStr>,
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::<Vec<StyledString>>(),
)
.cell(),
@ -171,14 +169,14 @@ impl Issue for InvalidImportModuleIssue {
#[turbo_tasks::value]
pub(crate) struct InvalidImportResolvePlugin {
root: Vc<FileSystemPath>,
invalid_import: String,
message: Vec<String>,
invalid_import: RcStr,
message: Vec<RcStr>,
}
#[turbo_tasks::value_impl]
impl InvalidImportResolvePlugin {
#[turbo_tasks::function]
pub fn new(root: Vc<FileSystemPath>, invalid_import: String, message: Vec<String>) -> Vc<Self> {
pub fn new(root: Vc<FileSystemPath>, invalid_import: RcStr, message: Vec<RcStr>) -> Vc<Self> {
InvalidImportResolvePlugin {
root,
invalid_import,
@ -192,7 +190,7 @@ impl InvalidImportResolvePlugin {
impl AfterResolvePlugin for InvalidImportResolvePlugin {
#[turbo_tasks::function]
fn after_resolve_condition(&self) -> Vc<AfterResolvePluginCondition> {
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> {
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> {
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> {
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> {
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> {
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> {
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> {
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<Vc<ResolveResultOption>> {
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(),
)))

View file

@ -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::<Vec<StyledString>>(),
)
.cell(),

View file

@ -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?,
),
])),
]),

View file

@ -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<FileSystemPath>,
plugin_configs: &[(String, serde_json::Value)],
plugin_configs: &[(RcStr, serde_json::Value)],
enable_mdx_rs: bool,
) -> Result<Option<ModuleRule>> {
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 {

View file

@ -35,8 +35,8 @@ pub async fn maybe_add_babel_loader(
) -> Result<Vc<OptionWebpackRules>> {
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<FileSystemPath>) -> 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),
);

View file

@ -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<FileSystemPath>,
next_config: Vc<NextConfig>,
foreign: bool,
conditions: Vec<String>,
conditions: Vec<RcStr>,
) -> Result<Option<Vc<WebpackLoadersOptions>>> {
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<ImportMapping> {
get_external_next_compiled_package_mapping(Vc::cell("loader-runner".to_owned()))
get_external_next_compiled_package_mapping(Vc::cell("loader-runner".into()))
}

View file

@ -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()),
},
);
}

View file

@ -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<String> {
Vc::cell("NextFeatureTelemetry_category_tbd".to_string())
fn category(&self) -> Vc<RcStr> {
Vc::cell("NextFeatureTelemetry_category_tbd".into())
}
#[turbo_tasks::function]
fn name(&self) -> Vc<String> {
fn name(&self) -> Vc<RcStr> {
Vc::cell(self.event_name.clone())
}
@ -40,7 +41,7 @@ impl Diagnostic for NextFeatureTelemetry {
fn payload(&self) -> Vc<DiagnosticPayload> {
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<String> {
Vc::cell("ModuleFeatureTelemetry_category_tbd".to_string())
fn category(&self) -> Vc<RcStr> {
Vc::cell("ModuleFeatureTelemetry_category_tbd".into())
}
#[turbo_tasks::function]
fn name(&self) -> Vc<String> {
fn name(&self) -> Vc<RcStr> {
Vc::cell(self.event_name.clone())
}
@ -80,7 +81,7 @@ impl Diagnostic for ModuleFeatureTelemetry {
fn payload(&self) -> Vc<DiagnosticPayload> {
Vc::cell(HashMap::from([(
self.feature_name.clone(),
self.invocation_count.to_string(),
self.invocation_count.to_string().into(),
)]))
}
}

View file

@ -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<Box<dyn AssetContext>>,
entry_asset: Vc<Box<dyn Source>>,
pathname: Vc<String>,
pathname: Vc<RcStr>,
) -> Result<Vc<Box<dyn Module>>> {
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<FileSystemPath>,
pub pathname: Vc<String>,
pub pathname: Vc<RcStr>,
pub rebase_prefix_path: Vc<FileSystemPathOption>,
pub page_chunks: Vc<OutputAssets>,
}
@ -84,7 +84,7 @@ impl PageLoaderAsset {
#[turbo_tasks::function]
pub fn new(
server_root: Vc<FileSystemPath>,
pathname: Vc<String>,
pathname: Vc<RcStr>,
rebase_prefix_path: Vc<FileSystemPathOption>,
page_chunks: Vc<OutputAssets>,
) -> Vc<Self> {
@ -127,8 +127,8 @@ impl PageLoaderAsset {
}
#[turbo_tasks::function]
fn page_loader_chunk_reference_description() -> Vc<String> {
Vc::cell("page loader chunk".to_string())
fn page_loader_chunk_reference_description() -> Vc<RcStr> {
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<Vc<AssetIdent>> {
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]

View file

@ -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<FileSystemPath>,
next_router_root: Vc<FileSystemPath>,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<PagesStructure>> {
let pages_root = project_root.join("pages".to_string());
let pages_root = project_root.join("pages".into());
let pages_root = Vc::<FileSystemPathOption>::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<FileSystemPath>,
project_path: Vc<FileSystemPathOption>,
next_router_path: Vc<FileSystemPath>,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<PagesStructure>> {
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<FileSystemPath>,
next_router_path: Vc<FileSystemPath>,
position: u32,
page_extensions: Vc<Vec<String>>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<PagesDirectoryStructure>> {
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())
}
}

View file

@ -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() {

View file

@ -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<FileSystemPath>,
server_path: Vc<FileSystemPath>,
path_ty: PathType,
) -> Result<Vc<String>> {
) -> Result<Vc<RcStr>> {
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> {
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<AssetIdent>, 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<Box<dyn Module>>) -> Result<Vc<
detail: StyledString::Text(
"The exported config object must contain an variable \
initializer."
.to_string(),
.into(),
)
.cell(),
}
@ -415,7 +415,7 @@ pub async fn parse_config_from_source(module: Vc<Box<dyn Module>>) -> Result<Vc<
ident: module.ident(),
detail: StyledString::Text(
"The runtime property must be either \"nodejs\" or \"edge\"."
.to_string(),
.into(),
)
.cell(),
}
@ -449,7 +449,7 @@ pub async fn parse_config_from_source(module: Vc<Box<dyn Module>>) -> Result<Vc<
detail: StyledString::Text(
"The exported segment runtime option must contain an \
variable initializer."
.to_string(),
.into(),
)
.cell(),
}
@ -536,9 +536,9 @@ fn parse_config_from_js_value(module: Vc<Box<dyn Module>>, value: &JsValue) -> N
pub async fn load_next_js_template(
path: &str,
project_path: Vc<FileSystemPath>,
replacements: IndexMap<&'static str, String>,
injections: IndexMap<&'static str, String>,
imports: IndexMap<&'static str, Option<String>>,
replacements: IndexMap<&'static str, RcStr>,
injections: IndexMap<&'static str, RcStr>,
imports: IndexMap<&'static str, Option<RcStr>>,
) -> Result<Vc<Box<dyn Source>>> {
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<FileSystemPath> {
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<T: DeserializeOwned>(
project_path: Vc<FileSystemPath>,
path: String,
path: RcStr,
) -> Result<T> {
let file_path = get_next_package(project_path).join(path.clone());

View file

@ -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",

View file

@ -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
@ -25838,8 +25838,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: